Separate config for shutdown step

This commit is contained in:
Michael Kuzmin 2017-07-02 03:06:02 +03:00
parent 310e10b19b
commit 228ac12366
4 changed files with 40 additions and 34 deletions

View File

@ -94,8 +94,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
},
&common.StepProvision{},
&StepShutdown{
Command: b.config.ShutdownCommand,
ShutdownTimeout: b.config.ShutdownTimeout,
config: &b.config.ShutdownConfig,
},
&StepCreateSnapshot{
createSnapshot: b.config.CreateSnapshot,

View File

@ -8,7 +8,6 @@ import (
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
"time"
)
type Config struct {
@ -37,11 +36,9 @@ type Config struct {
communicator.Config `mapstructure:",squash"`
// Post-processing
ShutdownCommand string `mapstructure:"shutdown_command"`
RawShutdownTimeout string `mapstructure:"shutdown_timeout"`
ShutdownTimeout time.Duration
CreateSnapshot bool `mapstructure:"create_snapshot"`
ConvertToTemplate bool `mapstructure:"convert_to_template"`
ShutdownConfig `mapstructure:",squash"`
CreateSnapshot bool `mapstructure:"create_snapshot"`
ConvertToTemplate bool `mapstructure:"convert_to_template"`
ctx interpolate.Context
}
@ -82,16 +79,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
}
errs = packer.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...)
if c.RawShutdownTimeout != "" {
timeout, err := time.ParseDuration(c.RawShutdownTimeout)
if err != nil {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err))
}
c.ShutdownTimeout = timeout
} else {
c.ShutdownTimeout = 5 * time.Minute
}
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare()...)
if len(errs.Errors) > 0 {
return nil, warnings, errs

View File

@ -16,8 +16,8 @@ func TestTimeout(t *testing.T) {
raw["shutdown_timeout"] = "3m"
conf, warns, err := NewConfig(raw)
testConfigOk(t, warns, err)
if conf.ShutdownTimeout != 3 * time.Minute {
t.Fatalf("shutdown_timeout sould be equal 3 minutes")
if conf.ShutdownConfig.Timeout != 3 * time.Minute {
t.Fatalf("shutdown_timeout sould be equal 3 minutes, got %v", conf.ShutdownConfig.Timeout)
}
}

View File

@ -12,9 +12,31 @@ import (
"errors"
)
type StepShutdown struct{
Command string
ShutdownTimeout time.Duration
type ShutdownConfig struct {
Command string `mapstructure:"shutdown_command"`
RawTimeout string `mapstructure:"shutdown_timeout"`
Timeout time.Duration
}
func (c *ShutdownConfig) Prepare() []error {
var errs []error
if c.RawTimeout != "" {
timeout, err := time.ParseDuration(c.RawTimeout)
if err != nil {
errs = append(errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err))
return errs
}
c.Timeout = timeout
} else {
c.Timeout = 5 * time.Minute
}
return nil
}
type StepShutdown struct {
config *ShutdownConfig
}
func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
@ -24,22 +46,20 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
vm := state.Get("vm").(*object.VirtualMachine)
ctx := state.Get("ctx").(context.Context)
ui.Say("VM shutdown...")
ui.Say("Shut down VM...")
if s.Command != "" {
if s.config.Command != "" {
ui.Say("Gracefully halting virtual machine...")
log.Printf("Executing shutdown command: %s", s.Command)
log.Printf("Executing shutdown command: %s", s.config.Command)
var stdout, stderr bytes.Buffer
cmd := &packer.RemoteCmd{
Command: s.Command,
Command: s.config.Command,
Stdout: &stdout,
Stderr: &stderr,
}
if err := comm.Start(cmd); err != nil {
err := fmt.Errorf("Failed to send shutdown command: %s", err)
state.Put("error", err)
ui.Error(err.Error())
state.Put("error", fmt.Errorf("Failed to send shutdown command: %s", err))
return multistep.ActionHalt
}
} else {
@ -47,14 +67,14 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
err := vm.ShutdownGuest(ctx)
if err != nil {
state.Put("error", fmt.Errorf("Could not shutdown guest: %v", err))
state.Put("error", fmt.Errorf("Cannot shut down VM: %v", err))
return multistep.ActionHalt
}
}
// Wait for the machine to actually shut down
log.Printf("Waiting max %s for shutdown to complete", s.ShutdownTimeout)
shutdownTimer := time.After(s.ShutdownTimeout)
log.Printf("Waiting max %s for shutdown to complete", s.config.Timeout)
shutdownTimer := time.After(s.config.Timeout)
for {
powerState, err := vm.PowerState(ctx)
if err != nil {
@ -81,4 +101,3 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
}
func (s *StepShutdown) Cleanup(state multistep.StateBag) {}