Merge pull request #331 from jasonberanek/vbox-vagrant-ova

post-processor/vagrant: support for Virtualbox OVA artifacts
This commit is contained in:
Mitchell Hashimoto 2013-08-23 15:06:44 -07:00
commit 1f82511768
2 changed files with 90 additions and 34 deletions

View File

@ -111,6 +111,48 @@ func DirToBox(dst, dir string, ui packer.Ui) error {
return filepath.Walk(dir, tarWalk)
}
func OvaToDir(dir, src string) error {
log.Printf("Turning ova to dir: %s => %s", src, dir)
srcF, err := os.Open(src)
if err != nil {
return err
}
defer srcF.Close()
tarReader := tar.NewReader(srcF)
for {
hdr, err := tarReader.Next()
if hdr == nil || err == io.EOF {
break
}
info := hdr.FileInfo()
// Shouldn't be any directories, skip them
if info.IsDir() {
continue
}
path := filepath.Join(dir, info.Name())
output, err := os.Create(path)
if err != nil {
return err
}
defer output.Close()
os.Chmod(path, info.Mode())
os.Chtimes(path, hdr.AccessTime, hdr.ModTime)
if _, err := io.Copy(output, tarReader); err != nil {
return err
}
}
return nil
}
// WriteMetadata writes the "metadata.json" file for a Vagrant box.
func WriteMetadata(dir string, contents interface{}) error {
f, err := os.Create(filepath.Join(dir, "metadata.json"))

View File

@ -10,7 +10,6 @@ import (
"os"
"path/filepath"
"regexp"
"strings"
)
type VBoxBoxConfig struct {
@ -66,11 +65,6 @@ func (p *VBoxBoxPostProcessor) Configure(raws ...interface{}) error {
func (p *VBoxBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
var err error
tplData := &VBoxVagrantfileTemplate{}
tplData.BaseMacAddress, err = p.findBaseMacAddress(artifact)
if err != nil {
return nil, false, err
}
// Compile the output path
outputPath, err := p.config.tpl.Process(p.config.OutputPath, &OutputPathTemplate{
@ -93,13 +87,27 @@ func (p *VBoxBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifac
for _, path := range artifact.Files() {
ui.Message(fmt.Sprintf("Copying: %s", path))
dstPath := filepath.Join(dir, filepath.Base(path))
if err := CopyContents(dstPath, path); err != nil {
return nil, false, err
if extension := filepath.Ext(path); extension == ".ova" {
log.Printf("File is an OVA: %s", path)
if err := OvaToDir(dir, filepath.Base(path)); err != nil {
return nil, false, err
}
} else {
dstPath := filepath.Join(dir, filepath.Base(path))
if err := CopyContents(dstPath, path); err != nil {
return nil, false, err
}
}
}
// Create the Vagrantfile from the template
tplData := &VBoxVagrantfileTemplate{}
tplData.BaseMacAddress, err = p.findBaseMacAddress(dir)
if err != nil {
return nil, false, err
}
vf, err := os.Create(filepath.Join(dir, "Vagrantfile"))
if err != nil {
return nil, false, err
@ -150,21 +158,42 @@ func (p *VBoxBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifac
return NewArtifact("virtualbox", outputPath), false, nil
}
func (p *VBoxBoxPostProcessor) findBaseMacAddress(a packer.Artifact) (string, error) {
log.Println("Looking for OVF for base mac address...")
var ovf string
for _, f := range a.Files() {
if strings.HasSuffix(f, ".ovf") {
log.Printf("OVF found: %s", f)
ovf = f
break
}
func (p *VBoxBoxPostProcessor) findOvf(dir string) (string, error) {
log.Println("Looking for OVF in artifact...")
file_matches, err := filepath.Glob(filepath.Join(dir, "*.ovf"))
if err != nil {
return "", err
}
if ovf == "" {
if len(file_matches) > 1 {
return "", errors.New("More than one OVF file in VirtualBox artifact.")
}
if len(file_matches) < 1 {
return "", errors.New("ovf file couldn't be found")
}
return file_matches[0], err
}
func (p *VBoxBoxPostProcessor) renameOVF(dir string) error {
log.Println("Looking for OVF to rename...")
ovf, err := p.findOvf(dir)
if err != nil {
return err
}
log.Printf("Renaming: '%s' => box.ovf", ovf)
return os.Rename(ovf, filepath.Join(dir, "box.ovf"))
}
func (p *VBoxBoxPostProcessor) findBaseMacAddress(dir string) (string, error) {
log.Println("Looking for OVF for base mac address...")
ovf, err := p.findOvf(dir)
if err != nil {
return "", err
}
f, err := os.Open(ovf)
if err != nil {
return "", err
@ -186,21 +215,6 @@ func (p *VBoxBoxPostProcessor) findBaseMacAddress(a packer.Artifact) (string, er
return string(matches[1]), nil
}
func (p *VBoxBoxPostProcessor) renameOVF(dir string) error {
log.Println("Looking for OVF to rename...")
matches, err := filepath.Glob(filepath.Join(dir, "*.ovf"))
if err != nil {
return err
}
if len(matches) > 1 {
return errors.New("More than one OVF file in VirtualBox artifact.")
}
log.Printf("Renaming: '%s' => box.ovf", matches[0])
return os.Rename(matches[0], filepath.Join(dir, "box.ovf"))
}
var defaultVBoxVagrantfile = `
Vagrant.configure("2") do |config|
config.vm.base_mac = "{{ .BaseMacAddress }}"