Added template conversion (#18)

* Added conversion to template without timeout
* Added timeout
* Extracted converting to template to a separate step
This commit is contained in:
Elizaveta Tretyakova 2017-06-13 14:11:41 +03:00 committed by GitHub
parent 66705e4a26
commit 39099ad3af
5 changed files with 77 additions and 24 deletions

View File

@ -62,7 +62,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
},
&common.StepProvision{},
&StepShutdown{
Command: b.config.ShutdownCommand,
Command: b.config.ShutdownCommand,
ShutdownTimeout: b.config.ShutdownTimeout,
},
&StepPostProcess{
ToTemplate: b.config.ToTemplate,
},
}

View File

@ -9,6 +9,7 @@ import (
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
"strconv"
"time"
)
type Config struct {
@ -27,7 +28,12 @@ type Config struct {
Host string `mapstructure:"host"`
ResourcePool string `mapstructure:"resource_pool"`
Datastore string `mapstructure:"datastore"`
// Settings
LinkedClone bool `mapstructure:"linked_clone"`
ToTemplate bool `mapstructure:"to_template"`
RawShutdownTimeout string `mapstructure:"shutdown_timeout"`
ShutdownTimeout time.Duration ``
// Hardware
Cpus string `mapstructure:"cpus"`
@ -84,11 +90,19 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("Invalid number for Ram"))
}
}
if c.RawShutdownTimeout == "" {
c.RawShutdownTimeout = "5m"
}
c.ShutdownTimeout, err = time.ParseDuration(c.RawShutdownTimeout)
if err != nil {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err))
}
// Warnings
var warnings []string
if c.Datastore == "" {
warnings = append(warnings, "Datastore is not specified, will try to find a default one")
warnings = append(warnings, "Datastore is not specified, will try to find the default one")
}
if len(errs.Errors) > 0 {

View File

@ -49,6 +49,7 @@ func (s *StepConfigureHW) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
if parametersFlag != (ConfigParametersFlag{}) {
ui.Say("configuring virtual hardware...")
// Reconfigure hardware
task, err := vm.Reconfigure(ctx, confSpec)
if err != nil {
state.Put("error", err)

33
step_post_process.go Normal file
View File

@ -0,0 +1,33 @@
package main
import (
"github.com/mitchellh/multistep"
"github.com/hashicorp/packer/packer"
"github.com/vmware/govmomi/object"
"context"
)
type StepPostProcess struct{
ToTemplate bool
}
func (s *StepPostProcess) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
vm := state.Get("vm").(*object.VirtualMachine)
ctx := state.Get("ctx").(context.Context)
// Turning into template if needed
if s.ToTemplate {
ui.Say("turning into template...")
err := vm.MarkAsTemplate(ctx)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
ui.Say("done")
}
return multistep.ActionContinue
}
func (s *StepPostProcess) Cleanup(state multistep.StateBag) {}

View File

@ -9,10 +9,12 @@ import (
"log"
"time"
"bytes"
"errors"
)
type StepShutdown struct{
Command string
Command string
ShutdownTimeout time.Duration
}
func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
@ -40,38 +42,37 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
ui.Error(err.Error())
return multistep.ActionHalt
}
// TODO: add timeout
for !cmd.Exited {
ui.Say("Waiting for remote cmd to finish...")
time.Sleep(150 * time.Millisecond)
}
if cmd.ExitStatus != 0 && cmd.ExitStatus != packer.CmdDisconnect {
err := fmt.Errorf("Cmd exit status %v, not 0", cmd.ExitStatus)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
} else if cmd.ExitStatus == packer.CmdDisconnect {
ui.Say("VM disconnected")
}
} else {
ui.Say("Forcibly halting virtual machine...")
err := vm.ShutdownGuest(ctx)
if err != nil {
state.Put("error", fmt.Errorf("Could not shutdown guest: %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)
for {
powerState, err := vm.PowerState(ctx)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
if powerState == "poweredOff" {
break
}
task, err := vm.PowerOff(ctx)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
_, err = task.WaitForResult(ctx, nil)
if err != nil {
select {
case <-shutdownTimer:
err := errors.New("Timeout while waiting for machine to shut down.")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
default:
time.Sleep(150 * time.Millisecond)
}
}