diff --git a/builder/virtualbox/common/vboxmanage_post_config.go b/builder/virtualbox/common/vboxmanage_post_config.go new file mode 100644 index 000000000..df683f100 --- /dev/null +++ b/builder/virtualbox/common/vboxmanage_post_config.go @@ -0,0 +1,28 @@ +package common + +import ( + "fmt" + "github.com/mitchellh/packer/packer" +) + +type VBoxManagePostConfig struct { + VBoxManagePost [][]string `mapstructure:"vboxmanage_post"` +} + +func (c *VBoxManagePostConfig) Prepare(t *packer.ConfigTemplate) []error { + if c.VBoxManagePost == nil { + c.VBoxManagePost = make([][]string, 0) + } + + errs := make([]error, 0) + for i, args := range c.VBoxManagePost { + for j, arg := range args { + if err := t.Validate(arg); err != nil { + errs = append(errs, + fmt.Errorf("Error processing vboxmanage_post[%d][%d]: %s", i, j, err)) + } + } + } + + return errs +} diff --git a/builder/virtualbox/common/vboxmanage_post_config_test.go b/builder/virtualbox/common/vboxmanage_post_config_test.go new file mode 100644 index 000000000..60a2c7abb --- /dev/null +++ b/builder/virtualbox/common/vboxmanage_post_config_test.go @@ -0,0 +1,37 @@ +package common + +import ( + "reflect" + "testing" +) + +func TestVBoxManagePostConfigPrepare_VBoxManage(t *testing.T) { + // Test with empty + c := new(VBoxManagePostConfig) + errs := c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if !reflect.DeepEqual(c.VBoxManagePost, [][]string{}) { + t.Fatalf("bad: %#v", c.VBoxManagePost) + } + + // Test with a good one + c = new(VBoxManagePostConfig) + c.VBoxManagePost = [][]string{ + {"foo", "bar", "baz"}, + } + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + expected := [][]string{ + []string{"foo", "bar", "baz"}, + } + + if !reflect.DeepEqual(c.VBoxManagePost, expected) { + t.Fatalf("bad: %#v", c.VBoxManagePost) + } +} diff --git a/builder/virtualbox/iso/builder.go b/builder/virtualbox/iso/builder.go index 31660a961..7861866b2 100644 --- a/builder/virtualbox/iso/builder.go +++ b/builder/virtualbox/iso/builder.go @@ -27,16 +27,17 @@ type Builder struct { } type config struct { - common.PackerConfig `mapstructure:",squash"` - vboxcommon.ExportConfig `mapstructure:",squash"` - vboxcommon.ExportOpts `mapstructure:",squash"` - vboxcommon.FloppyConfig `mapstructure:",squash"` - vboxcommon.OutputConfig `mapstructure:",squash"` - vboxcommon.RunConfig `mapstructure:",squash"` - vboxcommon.ShutdownConfig `mapstructure:",squash"` - vboxcommon.SSHConfig `mapstructure:",squash"` - vboxcommon.VBoxManageConfig `mapstructure:",squash"` - vboxcommon.VBoxVersionConfig `mapstructure:",squash"` + common.PackerConfig `mapstructure:",squash"` + vboxcommon.ExportConfig `mapstructure:",squash"` + vboxcommon.ExportOpts `mapstructure:",squash"` + vboxcommon.FloppyConfig `mapstructure:",squash"` + vboxcommon.OutputConfig `mapstructure:",squash"` + vboxcommon.RunConfig `mapstructure:",squash"` + vboxcommon.ShutdownConfig `mapstructure:",squash"` + vboxcommon.SSHConfig `mapstructure:",squash"` + vboxcommon.VBoxManageConfig `mapstructure:",squash"` + vboxcommon.VBoxManagePostConfig `mapstructure:",squash"` + vboxcommon.VBoxVersionConfig `mapstructure:",squash"` BootCommand []string `mapstructure:"boot_command"` DiskSize uint `mapstructure:"disk_size"` @@ -82,6 +83,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.VBoxManageConfig.Prepare(b.config.tpl)...) + errs = packer.MultiErrorAppend(errs, b.config.VBoxManagePostConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.VBoxVersionConfig.Prepare(b.config.tpl)...) warnings := make([]string, 0) @@ -318,6 +320,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Timeout: b.config.ShutdownTimeout, }, new(vboxcommon.StepRemoveDevices), + &vboxcommon.StepVBoxManage{ + Commands: b.config.VBoxManagePost, + Tpl: b.config.tpl, + }, &vboxcommon.StepExport{ Format: b.config.Format, OutputDir: b.config.OutputDir, diff --git a/builder/virtualbox/ovf/builder.go b/builder/virtualbox/ovf/builder.go index f2e6a92f5..ffc1a0d1b 100644 --- a/builder/virtualbox/ovf/builder.go +++ b/builder/virtualbox/ovf/builder.go @@ -94,6 +94,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Timeout: b.config.ShutdownTimeout, }, new(vboxcommon.StepRemoveDevices), + &vboxcommon.StepVBoxManage{ + Commands: b.config.VBoxManagePost, + Tpl: b.config.tpl, + }, &vboxcommon.StepExport{ Format: b.config.Format, OutputDir: b.config.OutputDir, diff --git a/builder/virtualbox/ovf/config.go b/builder/virtualbox/ovf/config.go index 054d09e3a..4b0c9111a 100644 --- a/builder/virtualbox/ovf/config.go +++ b/builder/virtualbox/ovf/config.go @@ -11,16 +11,17 @@ import ( // Config is the configuration structure for the builder. type Config struct { - common.PackerConfig `mapstructure:",squash"` - vboxcommon.ExportConfig `mapstructure:",squash"` - vboxcommon.ExportOpts `mapstructure:",squash"` - vboxcommon.FloppyConfig `mapstructure:",squash"` - vboxcommon.OutputConfig `mapstructure:",squash"` - vboxcommon.RunConfig `mapstructure:",squash"` - vboxcommon.SSHConfig `mapstructure:",squash"` - vboxcommon.ShutdownConfig `mapstructure:",squash"` - vboxcommon.VBoxManageConfig `mapstructure:",squash"` - vboxcommon.VBoxVersionConfig `mapstructure:",squash"` + common.PackerConfig `mapstructure:",squash"` + vboxcommon.ExportConfig `mapstructure:",squash"` + vboxcommon.ExportOpts `mapstructure:",squash"` + vboxcommon.FloppyConfig `mapstructure:",squash"` + vboxcommon.OutputConfig `mapstructure:",squash"` + vboxcommon.RunConfig `mapstructure:",squash"` + vboxcommon.SSHConfig `mapstructure:",squash"` + vboxcommon.ShutdownConfig `mapstructure:",squash"` + vboxcommon.VBoxManageConfig `mapstructure:",squash"` + vboxcommon.VBoxManagePostConfig `mapstructure:",squash"` + vboxcommon.VBoxVersionConfig `mapstructure:",squash"` SourcePath string `mapstructure:"source_path"` VMName string `mapstructure:"vm_name"` @@ -57,6 +58,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.VBoxManageConfig.Prepare(c.tpl)...) + errs = packer.MultiErrorAppend(errs, c.VBoxManagePostConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.VBoxVersionConfig.Prepare(c.tpl)...) templates := map[string]*string{ diff --git a/website/source/docs/builders/virtualbox-iso.html.markdown b/website/source/docs/builders/virtualbox-iso.html.markdown index e6e3b2454..c59b4ae5e 100644 --- a/website/source/docs/builders/virtualbox-iso.html.markdown +++ b/website/source/docs/builders/virtualbox-iso.html.markdown @@ -201,6 +201,10 @@ Optional: where the `Name` variable is replaced with the VM name. More details on how to use `VBoxManage` are below. +* `vboxmanage_post` (array of array of strings) - Identical to `vboxmanage`, + except that it is run after the virtual machine is shutdown, and before the + virtual machine is exported. + * `virtualbox_version_file` (string) - The path within the virtual machine to upload a file that contains the VirtualBox version that was used to create the machine. This information can be useful for provisioning. diff --git a/website/source/docs/builders/virtualbox-ovf.html.markdown b/website/source/docs/builders/virtualbox-ovf.html.markdown index 6bf6e49d9..602ced197 100644 --- a/website/source/docs/builders/virtualbox-ovf.html.markdown +++ b/website/source/docs/builders/virtualbox-ovf.html.markdown @@ -136,6 +136,10 @@ Optional: where the `Name` variable is replaced with the VM name. More details on how to use `VBoxManage` are below. +* `vboxmanage_post` (array of array of strings) - Identical to `vboxmanage`, + except that it is run after the virtual machine is shutdown, and before the + virtual machine is exported. + * `virtualbox_version_file` (string) - The path within the virtual machine to upload a file that contains the VirtualBox version that was used to create the machine. This information can be useful for provisioning.