diff --git a/builder/virtualbox/common/run_config.go b/builder/virtualbox/common/run_config.go new file mode 100644 index 000000000..755d0f1c1 --- /dev/null +++ b/builder/virtualbox/common/run_config.go @@ -0,0 +1,41 @@ +package common + +import ( + "fmt" + "github.com/mitchellh/packer/packer" + "time" +) + +type RunConfig struct { + Headless bool `mapstructure:"headless"` + RawBootWait string `mapstructure:"boot_wait"` + + BootWait time.Duration `` +} + +func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error { + if c.RawBootWait == "" { + c.RawBootWait = "10s" + } + + templates := map[string]*string{ + "boot_wait": &c.RawBootWait, + } + + errs := make([]error, 0) + for n, ptr := range templates { + var err error + *ptr, err = t.Process(*ptr, nil) + if err != nil { + errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err)) + } + } + + var err error + c.BootWait, err = time.ParseDuration(c.RawBootWait) + if err != nil { + errs = append(errs, fmt.Errorf("Failed parsing boot_wait: %s", err)) + } + + return errs +} diff --git a/builder/virtualbox/common/run_config_test.go b/builder/virtualbox/common/run_config_test.go new file mode 100644 index 000000000..8068fe625 --- /dev/null +++ b/builder/virtualbox/common/run_config_test.go @@ -0,0 +1,37 @@ +package common + +import ( + "testing" +) + +func TestRunConfigPrepare_BootWait(t *testing.T) { + var c *RunConfig + var errs []error + + // Test a default boot_wait + c = new(RunConfig) + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("should not have error: %s", errs) + } + + if c.RawBootWait != "10s" { + t.Fatalf("bad value: %s", c.RawBootWait) + } + + // Test with a bad boot_wait + c = new(RunConfig) + c.RawBootWait = "this is not good" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) == 0 { + t.Fatalf("bad: %#v", errs) + } + + // Test with a good one + c = new(RunConfig) + c.RawBootWait = "5s" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("should not have error: %s", errs) + } +} diff --git a/builder/virtualbox/iso/step_run.go b/builder/virtualbox/common/step_run.go similarity index 72% rename from builder/virtualbox/iso/step_run.go rename to builder/virtualbox/common/step_run.go index 1d5cc63be..0718ad7f3 100644 --- a/builder/virtualbox/iso/step_run.go +++ b/builder/virtualbox/common/step_run.go @@ -1,9 +1,8 @@ -package iso +package common import ( "fmt" "github.com/mitchellh/multistep" - vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "time" ) @@ -11,21 +10,26 @@ import ( // This step starts the virtual machine. // // Uses: +// driver Driver +// ui packer.Ui +// vmName string // // Produces: -type stepRun struct { +type StepRun struct { + BootWait time.Duration + Headless bool + vmName string } -func (s *stepRun) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*config) - driver := state.Get("driver").(vboxcommon.Driver) +func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction { + driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) ui.Say("Starting the virtual machine...") guiArgument := "gui" - if config.Headless == true { + if s.Headless == true { ui.Message("WARNING: The VM will be started in headless mode, as configured.\n" + "In headless mode, errors during the boot sequence or OS setup\n" + "won't be easily visible. Use at your own discretion.") @@ -41,9 +45,9 @@ func (s *stepRun) Run(state multistep.StateBag) multistep.StepAction { s.vmName = vmName - if int64(config.bootWait) > 0 { - ui.Say(fmt.Sprintf("Waiting %s for boot...", config.bootWait)) - wait := time.After(config.bootWait) + if int64(s.BootWait) > 0 { + ui.Say(fmt.Sprintf("Waiting %s for boot...", s.BootWait)) + wait := time.After(s.BootWait) WAITLOOP: for { select { @@ -60,12 +64,12 @@ func (s *stepRun) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionContinue } -func (s *stepRun) Cleanup(state multistep.StateBag) { +func (s *StepRun) Cleanup(state multistep.StateBag) { if s.vmName == "" { return } - driver := state.Get("driver").(vboxcommon.Driver) + driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) if running, _ := driver.IsRunning(s.vmName); running { diff --git a/builder/virtualbox/iso/builder.go b/builder/virtualbox/iso/builder.go index ab5ae993d..86a351ae6 100644 --- a/builder/virtualbox/iso/builder.go +++ b/builder/virtualbox/iso/builder.go @@ -9,7 +9,6 @@ import ( "github.com/mitchellh/packer/packer" "log" "strings" - "time" ) const BuilderId = "mitchellh.virtualbox" @@ -31,6 +30,7 @@ type config struct { common.PackerConfig `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"` @@ -44,7 +44,6 @@ type config struct { GuestAdditionsSHA256 string `mapstructure:"guest_additions_sha256"` GuestOSType string `mapstructure:"guest_os_type"` HardDriveInterface string `mapstructure:"hard_drive_interface"` - Headless bool `mapstructure:"headless"` HTTPDir string `mapstructure:"http_directory"` HTTPPortMin uint `mapstructure:"http_port_min"` HTTPPortMax uint `mapstructure:"http_port_max"` @@ -54,11 +53,9 @@ type config struct { VBoxVersionFile string `mapstructure:"virtualbox_version_file"` VMName string `mapstructure:"vm_name"` - RawBootWait string `mapstructure:"boot_wait"` RawSingleISOUrl string `mapstructure:"iso_url"` - bootWait time.Duration `` - tpl *packer.ConfigTemplate + tpl *packer.ConfigTemplate } func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { @@ -78,6 +75,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend( errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...) + errs = packer.MultiErrorAppend(errs, b.config.RunConfig.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)...) warnings := make([]string, 0) @@ -110,10 +108,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { b.config.HTTPPortMax = 9000 } - if b.config.RawBootWait == "" { - b.config.RawBootWait = "10s" - } - if b.config.VBoxVersionFile == "" { b.config.VBoxVersionFile = ".vbox_version" } @@ -139,7 +133,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { "virtualbox_version_file": &b.config.VBoxVersionFile, "vm_name": &b.config.VMName, "format": &b.config.Format, - "boot_wait": &b.config.RawBootWait, } for n, ptr := range templates { @@ -254,12 +247,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { b.config.GuestAdditionsSHA256 = strings.ToLower(b.config.GuestAdditionsSHA256) } - b.config.bootWait, err = time.ParseDuration(b.config.RawBootWait) - if err != nil { - errs = packer.MultiErrorAppend( - errs, fmt.Errorf("Failed parsing boot_wait: %s", err)) - } - // Warnings if b.config.ShutdownCommand == "" { warnings = append(warnings, @@ -312,7 +299,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &vboxcommon.StepVBoxManage{ Commands: b.config.VBoxManage, }, - new(stepRun), + &vboxcommon.StepRun{ + BootWait: b.config.BootWait, + Headless: b.config.Headless, + }, new(stepTypeBootCommand), &common.StepConnectSSH{ SSHAddress: vboxcommon.SSHAddress, diff --git a/builder/virtualbox/iso/builder_test.go b/builder/virtualbox/iso/builder_test.go index 7e7bf4ead..fa60e482b 100644 --- a/builder/virtualbox/iso/builder_test.go +++ b/builder/virtualbox/iso/builder_test.go @@ -54,46 +54,6 @@ func TestBuilderPrepare_Defaults(t *testing.T) { } } -func TestBuilderPrepare_BootWait(t *testing.T) { - var b Builder - config := testConfig() - - // Test a default boot_wait - delete(config, "boot_wait") - warns, err := b.Prepare(config) - if len(warns) > 0 { - t.Fatalf("bad: %#v", warns) - } - if err != nil { - t.Fatalf("err: %s", err) - } - - if b.config.RawBootWait != "10s" { - t.Fatalf("bad value: %s", b.config.RawBootWait) - } - - // Test with a bad boot_wait - config["boot_wait"] = "this is not good" - warns, err = b.Prepare(config) - if len(warns) > 0 { - t.Fatalf("bad: %#v", warns) - } - if err == nil { - t.Fatal("should have error") - } - - // Test with a good one - config["boot_wait"] = "5s" - b = Builder{} - warns, err = b.Prepare(config) - if len(warns) > 0 { - t.Fatalf("bad: %#v", warns) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } -} - func TestBuilderPrepare_DiskSize(t *testing.T) { var b Builder config := testConfig() diff --git a/builder/virtualbox/ovf/builder.go b/builder/virtualbox/ovf/builder.go index 4cd7d2e52..2317a4601 100644 --- a/builder/virtualbox/ovf/builder.go +++ b/builder/virtualbox/ovf/builder.go @@ -62,9 +62,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &vboxcommon.StepVBoxManage{ Commands: b.config.VBoxManage, }, - /* - new(stepRun), - */ + &vboxcommon.StepRun{ + BootWait: b.config.BootWait, + Headless: b.config.Headless, + }, &common.StepConnectSSH{ SSHAddress: vboxcommon.SSHAddress, SSHConfig: vboxcommon.SSHConfigFunc(b.config.SSHConfig), diff --git a/builder/virtualbox/ovf/config.go b/builder/virtualbox/ovf/config.go index 999173ac0..929bb24a5 100644 --- a/builder/virtualbox/ovf/config.go +++ b/builder/virtualbox/ovf/config.go @@ -11,6 +11,7 @@ type Config struct { common.PackerConfig `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"` @@ -35,6 +36,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { errs := common.CheckUnusedConfig(md) errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.OutputConfig.Prepare(c.tpl, &c.PackerConfig)...) + errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.VBoxManageConfig.Prepare(c.tpl)...)