Add disable_shutdown option to VSphere builders
Also don't try to shut down VM if it's already off, otherwise VSphere would raise an error: "The attempted operation cannot be performed in the current state (Powered off)."
This commit is contained in:
parent
1155ab8e3c
commit
03c4bebf00
|
@ -92,6 +92,7 @@ type FlatConfig struct {
|
||||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
|
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
|
||||||
Command *string `mapstructure:"shutdown_command" cty:"shutdown_command"`
|
Command *string `mapstructure:"shutdown_command" cty:"shutdown_command"`
|
||||||
Timeout *string `mapstructure:"shutdown_timeout" cty:"shutdown_timeout"`
|
Timeout *string `mapstructure:"shutdown_timeout" cty:"shutdown_timeout"`
|
||||||
|
DisableShutdown *bool `mapstructure:"disable_shutdown" cty:"disable_shutdown"`
|
||||||
CreateSnapshot *bool `mapstructure:"create_snapshot" cty:"create_snapshot"`
|
CreateSnapshot *bool `mapstructure:"create_snapshot" cty:"create_snapshot"`
|
||||||
ConvertToTemplate *bool `mapstructure:"convert_to_template" cty:"convert_to_template"`
|
ConvertToTemplate *bool `mapstructure:"convert_to_template" cty:"convert_to_template"`
|
||||||
Export *common.FlatExportConfig `mapstructure:"export" cty:"export"`
|
Export *common.FlatExportConfig `mapstructure:"export" cty:"export"`
|
||||||
|
@ -191,6 +192,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
||||||
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
|
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
|
||||||
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
|
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
|
||||||
|
"disable_shutdown": &hcldec.AttrSpec{Name: "disable_shutdown", Type: cty.Bool, Required: false},
|
||||||
"create_snapshot": &hcldec.AttrSpec{Name: "create_snapshot", Type: cty.Bool, Required: false},
|
"create_snapshot": &hcldec.AttrSpec{Name: "create_snapshot", Type: cty.Bool, Required: false},
|
||||||
"convert_to_template": &hcldec.AttrSpec{Name: "convert_to_template", Type: cty.Bool, Required: false},
|
"convert_to_template": &hcldec.AttrSpec{Name: "convert_to_template", Type: cty.Bool, Required: false},
|
||||||
"export": &hcldec.BlockSpec{TypeName: "export", Nested: hcldec.ObjectSpec((*common.FlatExportConfig)(nil).HCL2Spec())},
|
"export": &hcldec.BlockSpec{TypeName: "export", Nested: hcldec.ObjectSpec((*common.FlatExportConfig)(nil).HCL2Spec())},
|
||||||
|
|
|
@ -19,9 +19,16 @@ type ShutdownConfig struct {
|
||||||
// Specify a VM guest shutdown command. VMware guest tools are used by
|
// Specify a VM guest shutdown command. VMware guest tools are used by
|
||||||
// default.
|
// default.
|
||||||
Command string `mapstructure:"shutdown_command"`
|
Command string `mapstructure:"shutdown_command"`
|
||||||
// Amount of time to wait for graceful VM shutdown. Examples 45s and 10m.
|
// Amount of time to wait for graceful VM shutdown.
|
||||||
// Defaults to 5m(5 minutes).
|
// Defaults to 5m or five minutes.
|
||||||
Timeout time.Duration `mapstructure:"shutdown_timeout"`
|
Timeout time.Duration `mapstructure:"shutdown_timeout"`
|
||||||
|
// Packer normally halts the virtual machine after all provisioners have
|
||||||
|
// run when no `shutdown_command` is defined. If this is set to `true`, Packer
|
||||||
|
// *will not* halt the virtual machine but will assume that you will send the stop
|
||||||
|
// signal yourself through the preseed.cfg or your final provisioner.
|
||||||
|
// Packer will wait for a default of five minutes until the virtual machine is shutdown.
|
||||||
|
// The timeout can be changed using `shutdown_timeout` option.
|
||||||
|
DisableShutdown bool `mapstructure:"disable_shutdown"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ShutdownConfig) Prepare() []error {
|
func (c *ShutdownConfig) Prepare() []error {
|
||||||
|
@ -43,7 +50,15 @@ func (s *StepShutdown) Run(ctx context.Context, state multistep.StateBag) multis
|
||||||
comm := state.Get("communicator").(packer.Communicator)
|
comm := state.Get("communicator").(packer.Communicator)
|
||||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||||
|
|
||||||
if s.Config.Command != "" {
|
if off, _ := vm.IsPoweredOff(); off {
|
||||||
|
// Probably power off initiated by last provisioner, though disable_shutdown is not set
|
||||||
|
ui.Say("VM is already powered off")
|
||||||
|
return multistep.ActionContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Config.DisableShutdown {
|
||||||
|
ui.Say("Automatic shutdown disabled. Please shutdown virtual machine.")
|
||||||
|
} else if s.Config.Command != "" {
|
||||||
ui.Say("Executing shutdown command...")
|
ui.Say("Executing shutdown command...")
|
||||||
log.Printf("Shutdown command: %s", s.Config.Command)
|
log.Printf("Shutdown command: %s", s.Config.Command)
|
||||||
|
|
||||||
|
@ -59,7 +74,7 @@ func (s *StepShutdown) Run(ctx context.Context, state multistep.StateBag) multis
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ui.Say("Shut down VM...")
|
ui.Say("Shutting down VM...")
|
||||||
|
|
||||||
err := vm.StartShutdown()
|
err := vm.StartShutdown()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
type FlatShutdownConfig struct {
|
type FlatShutdownConfig struct {
|
||||||
Command *string `mapstructure:"shutdown_command" cty:"shutdown_command"`
|
Command *string `mapstructure:"shutdown_command" cty:"shutdown_command"`
|
||||||
Timeout *string `mapstructure:"shutdown_timeout" cty:"shutdown_timeout"`
|
Timeout *string `mapstructure:"shutdown_timeout" cty:"shutdown_timeout"`
|
||||||
|
DisableShutdown *bool `mapstructure:"disable_shutdown" cty:"disable_shutdown"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlatMapstructure returns a new FlatShutdownConfig.
|
// FlatMapstructure returns a new FlatShutdownConfig.
|
||||||
|
@ -27,6 +28,7 @@ func (*FlatShutdownConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
s := map[string]hcldec.Spec{
|
s := map[string]hcldec.Spec{
|
||||||
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
|
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
|
||||||
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
|
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
|
||||||
|
"disable_shutdown": &hcldec.AttrSpec{Name: "disable_shutdown", Type: cty.Bool, Required: false},
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
|
@ -454,6 +454,15 @@ func (vm *VirtualMachine) PowerOff() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) IsPoweredOff() (bool, error) {
|
||||||
|
state, err := vm.vm.PowerState(vm.driver.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return state == types.VirtualMachinePowerStatePoweredOff, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (vm *VirtualMachine) StartShutdown() error {
|
func (vm *VirtualMachine) StartShutdown() error {
|
||||||
err := vm.vm.ShutdownGuest(vm.driver.ctx)
|
err := vm.vm.ShutdownGuest(vm.driver.ctx)
|
||||||
return err
|
return err
|
||||||
|
@ -462,11 +471,11 @@ func (vm *VirtualMachine) StartShutdown() error {
|
||||||
func (vm *VirtualMachine) WaitForShutdown(ctx context.Context, timeout time.Duration) error {
|
func (vm *VirtualMachine) WaitForShutdown(ctx context.Context, timeout time.Duration) error {
|
||||||
shutdownTimer := time.After(timeout)
|
shutdownTimer := time.After(timeout)
|
||||||
for {
|
for {
|
||||||
powerState, err := vm.vm.PowerState(vm.driver.ctx)
|
off, err := vm.IsPoweredOff()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if powerState == "poweredOff" {
|
if off {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,7 @@ type FlatConfig struct {
|
||||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
|
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
|
||||||
Command *string `mapstructure:"shutdown_command" cty:"shutdown_command"`
|
Command *string `mapstructure:"shutdown_command" cty:"shutdown_command"`
|
||||||
Timeout *string `mapstructure:"shutdown_timeout" cty:"shutdown_timeout"`
|
Timeout *string `mapstructure:"shutdown_timeout" cty:"shutdown_timeout"`
|
||||||
|
DisableShutdown *bool `mapstructure:"disable_shutdown" cty:"disable_shutdown"`
|
||||||
CreateSnapshot *bool `mapstructure:"create_snapshot" cty:"create_snapshot"`
|
CreateSnapshot *bool `mapstructure:"create_snapshot" cty:"create_snapshot"`
|
||||||
ConvertToTemplate *bool `mapstructure:"convert_to_template" cty:"convert_to_template"`
|
ConvertToTemplate *bool `mapstructure:"convert_to_template" cty:"convert_to_template"`
|
||||||
Export *common.FlatExportConfig `mapstructure:"export" cty:"export"`
|
Export *common.FlatExportConfig `mapstructure:"export" cty:"export"`
|
||||||
|
@ -243,6 +244,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
||||||
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
|
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
|
||||||
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
|
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
|
||||||
|
"disable_shutdown": &hcldec.AttrSpec{Name: "disable_shutdown", Type: cty.Bool, Required: false},
|
||||||
"create_snapshot": &hcldec.AttrSpec{Name: "create_snapshot", Type: cty.Bool, Required: false},
|
"create_snapshot": &hcldec.AttrSpec{Name: "create_snapshot", Type: cty.Bool, Required: false},
|
||||||
"convert_to_template": &hcldec.AttrSpec{Name: "convert_to_template", Type: cty.Bool, Required: false},
|
"convert_to_template": &hcldec.AttrSpec{Name: "convert_to_template", Type: cty.Bool, Required: false},
|
||||||
"export": &hcldec.BlockSpec{TypeName: "export", Nested: hcldec.ObjectSpec((*common.FlatExportConfig)(nil).HCL2Spec())},
|
"export": &hcldec.BlockSpec{TypeName: "export", Nested: hcldec.ObjectSpec((*common.FlatExportConfig)(nil).HCL2Spec())},
|
||||||
|
|
|
@ -3,6 +3,13 @@
|
||||||
- `shutdown_command` (string) - Specify a VM guest shutdown command. VMware guest tools are used by
|
- `shutdown_command` (string) - Specify a VM guest shutdown command. VMware guest tools are used by
|
||||||
default.
|
default.
|
||||||
|
|
||||||
- `shutdown_timeout` (duration string | ex: "1h5m2s") - Amount of time to wait for graceful VM shutdown. Examples 45s and 10m.
|
- `shutdown_timeout` (duration string | ex: "1h5m2s") - Amount of time to wait for graceful VM shutdown.
|
||||||
Defaults to 5m(5 minutes).
|
Defaults to 5m or five minutes.
|
||||||
|
|
||||||
|
- `disable_shutdown` (bool) - Packer normally halts the virtual machine after all provisioners have
|
||||||
|
run when no `shutdown_command` is defined. If this is set to `true`, Packer
|
||||||
|
*will not* halt the virtual machine but will assume that you will send the stop
|
||||||
|
signal yourself through the preseed.cfg or your final provisioner.
|
||||||
|
Packer will wait for a default of five minutes until the virtual machine is shutdown.
|
||||||
|
The timeout can be changed using `shutdown_timeout` option.
|
||||||
|
|
Loading…
Reference in New Issue