Adds acpi_shutdown to virtualbox builder (#8587)

pull/8592/head
Sylvia Moss 6 years ago committed by GitHub
parent d9a128a375
commit baa203bb53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -40,6 +40,9 @@ type Driver interface {
// Stop stops a running machine, forcefully.
Stop(string) error
// ACPIStop stops a running machine via ACPI power button.
StopViaACPI(string) error
// SuppressMessages should do what needs to be done in order to
// suppress any annoying popups from VirtualBox.
SuppressMessages() error

@ -161,6 +161,14 @@ func (d *VBox42Driver) Stop(name string) error {
return nil
}
func (d *VBox42Driver) StopViaACPI(name string) error {
if err := d.VBoxManage("controlvm", name, "acpipowerbutton"); err != nil {
return err
}
return nil
}
func (d *VBox42Driver) SuppressMessages() error {
extraData := map[string]string{
"GUI/RegistrationData": "triesLeft=0",

@ -34,8 +34,9 @@ type DriverMock struct {
IsRunningReturn bool
IsRunningErr error
StopName string
StopErr error
StopViaACPIName string
StopName string
StopErr error
SuppressMessagesCalled bool
SuppressMessagesErr error
@ -112,6 +113,11 @@ func (d *DriverMock) Stop(name string) error {
return d.StopErr
}
func (d *DriverMock) StopViaACPI(name string) error {
d.StopViaACPIName = name
return d.StopErr
}
func (d *DriverMock) SuppressMessages() error {
d.SuppressMessagesCalled = true
return d.SuppressMessagesErr

@ -34,6 +34,9 @@ type ShutdownConfig struct {
// Packer will wait for a default of 5 minutes until the virtual machine is shutdown.
// The timeout can be changed using `shutdown_timeout` option.
DisableShutdown bool `mapstructure:"disable_shutdown" required:"false"`
// If it's set to true, it will shutdown the VM via power button. It could be a good option
// when keeping the machine state is necessary after shutting it down.
ACPIShutdown bool `mapstructure:"acpi_shutdown" required:"false"`
}
func (c *ShutdownConfig) Prepare(ctx *interpolate.Context) []error {

@ -27,6 +27,7 @@ type StepShutdown struct {
Timeout time.Duration
Delay time.Duration
DisableShutdown bool
ACPIShutdown bool
}
func (s *StepShutdown) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
@ -35,7 +36,15 @@ func (s *StepShutdown) Run(ctx context.Context, state multistep.StateBag) multis
ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string)
if !s.DisableShutdown {
if s.ACPIShutdown {
ui.Say("Shuting down the virtual machine via ACPI power button...")
if err := driver.StopViaACPI(vmName); err != nil {
err := fmt.Errorf("Error stopping VM: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
} else if !s.DisableShutdown {
if s.Command != "" {
ui.Say("Gracefully halting virtual machine...")
log.Printf("Executing shutdown command: %s", s.Command)

@ -17,6 +17,7 @@ func TestStepShutdown_noShutdownCommand(t *testing.T) {
state := testState(t)
step := new(StepShutdown)
step.DisableShutdown = false
step.ACPIShutdown = false
comm := new(packer.MockCommunicator)
state.Put("communicator", comm)
@ -47,6 +48,7 @@ func TestStepShutdown_shutdownCommand(t *testing.T) {
step.Command = "poweroff"
step.Timeout = 1 * time.Second
step.DisableShutdown = false
step.ACPIShutdown = false
comm := new(packer.MockCommunicator)
state.Put("communicator", comm)
@ -85,6 +87,7 @@ func TestStepShutdown_shutdownTimeout(t *testing.T) {
step.Command = "poweroff"
step.Timeout = 1 * time.Second
step.DisableShutdown = false
step.ACPIShutdown = false
comm := new(packer.MockCommunicator)
state.Put("communicator", comm)
@ -113,6 +116,7 @@ func TestStepShutdown_DisableShutdown(t *testing.T) {
state := testState(t)
step := new(StepShutdown)
step.DisableShutdown = true
step.ACPIShutdown = false
step.Timeout = 2 * time.Second
comm := new(packer.MockCommunicator)
@ -137,3 +141,32 @@ func TestStepShutdown_DisableShutdown(t *testing.T) {
t.Fatal("should NOT have error")
}
}
func TestStepShutdown_ACPIShutdown(t *testing.T) {
state := testState(t)
step := new(StepShutdown)
step.ACPIShutdown = true
step.Timeout = 2 * time.Second
comm := new(packer.MockCommunicator)
state.Put("communicator", comm)
state.Put("vmName", "foo")
driver := state.Get("driver").(*DriverMock)
// Test the run
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
t.Fatalf("bad action: %#v", action)
}
if _, ok := state.GetOk("error"); ok {
t.Fatal("should NOT have error")
}
// Test that Stop was just called
if driver.StopViaACPIName != "foo" {
t.Fatal("should call stop via ACPI")
}
if comm.StartCalled {
t.Fatal("comm start should not be called")
}
}

@ -377,6 +377,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Timeout: b.config.ShutdownTimeout,
Delay: b.config.PostShutdownDelay,
DisableShutdown: b.config.DisableShutdown,
ACPIShutdown: b.config.ACPIShutdown,
},
&vboxcommon.StepRemoveDevices{
Bundling: b.config.VBoxBundleConfig,

@ -43,6 +43,7 @@ type FlatConfig struct {
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
PostShutdownDelay *string `mapstructure:"post_shutdown_delay" required:"false" cty:"post_shutdown_delay"`
DisableShutdown *bool `mapstructure:"disable_shutdown" required:"false" cty:"disable_shutdown"`
ACPIShutdown *bool `mapstructure:"acpi_shutdown" required:"false" cty:"acpi_shutdown"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
@ -159,6 +160,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
"post_shutdown_delay": &hcldec.AttrSpec{Name: "post_shutdown_delay", Type: cty.String, Required: false},
"disable_shutdown": &hcldec.AttrSpec{Name: "disable_shutdown", Type: cty.Bool, Required: false},
"acpi_shutdown": &hcldec.AttrSpec{Name: "acpi_shutdown", Type: cty.Bool, Required: false},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},

@ -145,6 +145,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Timeout: b.config.ShutdownTimeout,
Delay: b.config.PostShutdownDelay,
DisableShutdown: b.config.DisableShutdown,
ACPIShutdown: b.config.ACPIShutdown,
},
&vboxcommon.StepRemoveDevices{
GuestAdditionsInterface: b.config.GuestAdditionsInterface,

@ -80,6 +80,7 @@ type FlatConfig struct {
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
PostShutdownDelay *string `mapstructure:"post_shutdown_delay" required:"false" cty:"post_shutdown_delay"`
DisableShutdown *bool `mapstructure:"disable_shutdown" required:"false" cty:"disable_shutdown"`
ACPIShutdown *bool `mapstructure:"acpi_shutdown" required:"false" cty:"acpi_shutdown"`
VBoxManage [][]string `mapstructure:"vboxmanage" required:"false" cty:"vboxmanage"`
VBoxManagePost [][]string `mapstructure:"vboxmanage_post" required:"false" cty:"vboxmanage_post"`
VBoxVersionFile *string `mapstructure:"virtualbox_version_file" required:"false" cty:"virtualbox_version_file"`
@ -182,6 +183,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
"post_shutdown_delay": &hcldec.AttrSpec{Name: "post_shutdown_delay", Type: cty.String, Required: false},
"disable_shutdown": &hcldec.AttrSpec{Name: "disable_shutdown", Type: cty.Bool, Required: false},
"acpi_shutdown": &hcldec.AttrSpec{Name: "acpi_shutdown", Type: cty.Bool, Required: false},
"vboxmanage": &hcldec.BlockListSpec{TypeName: "vboxmanage", Nested: &hcldec.AttrSpec{Name: "vboxmanage", Type: cty.List(cty.String), Required: false}},
"vboxmanage_post": &hcldec.BlockListSpec{TypeName: "vboxmanage_post", Nested: &hcldec.AttrSpec{Name: "vboxmanage_post", Type: cty.List(cty.String), Required: false}},
"virtualbox_version_file": &hcldec.AttrSpec{Name: "virtualbox_version_file", Type: cty.String, Required: false},

@ -127,6 +127,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Timeout: b.config.ShutdownTimeout,
Delay: b.config.PostShutdownDelay,
DisableShutdown: b.config.DisableShutdown,
ACPIShutdown: b.config.ACPIShutdown,
},
&vboxcommon.StepVBoxManage{
Commands: b.config.VBoxManagePost,

@ -80,6 +80,7 @@ type FlatConfig struct {
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
PostShutdownDelay *string `mapstructure:"post_shutdown_delay" required:"false" cty:"post_shutdown_delay"`
DisableShutdown *bool `mapstructure:"disable_shutdown" required:"false" cty:"disable_shutdown"`
ACPIShutdown *bool `mapstructure:"acpi_shutdown" required:"false" cty:"acpi_shutdown"`
VBoxManage [][]string `mapstructure:"vboxmanage" required:"false" cty:"vboxmanage"`
VBoxManagePost [][]string `mapstructure:"vboxmanage_post" required:"false" cty:"vboxmanage_post"`
VBoxVersionFile *string `mapstructure:"virtualbox_version_file" required:"false" cty:"virtualbox_version_file"`
@ -178,6 +179,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
"post_shutdown_delay": &hcldec.AttrSpec{Name: "post_shutdown_delay", Type: cty.String, Required: false},
"disable_shutdown": &hcldec.AttrSpec{Name: "disable_shutdown", Type: cty.Bool, Required: false},
"acpi_shutdown": &hcldec.AttrSpec{Name: "acpi_shutdown", Type: cty.Bool, Required: false},
"vboxmanage": &hcldec.BlockListSpec{TypeName: "vboxmanage", Nested: &hcldec.AttrSpec{Name: "vboxmanage", Type: cty.List(cty.String), Required: false}},
"vboxmanage_post": &hcldec.BlockListSpec{TypeName: "vboxmanage_post", Nested: &hcldec.AttrSpec{Name: "vboxmanage_post", Type: cty.List(cty.String), Required: false}},
"virtualbox_version_file": &hcldec.AttrSpec{Name: "virtualbox_version_file", Type: cty.String, Required: false},

@ -24,4 +24,7 @@
signal yourself through the preseed.cfg or your final provisioner.
Packer will wait for a default of 5 minutes until the virtual machine is shutdown.
The timeout can be changed using `shutdown_timeout` option.
- `acpi_shutdown` (bool) - If it's set to true, it will shutdown the VM via power button. It could be a good option
when keeping the machine state is necessary after shutting it down.
Loading…
Cancel
Save