From 1e747c8c9383d1d58964e579a56334eb2d8c14cd Mon Sep 17 00:00:00 2001 From: Michael Kuzmin Date: Sun, 2 Jul 2017 06:46:38 +0300 Subject: [PATCH] extract vSphere driver --- builder.go | 2 -- driver.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ step_clone.go | 27 ++++++++++++--------------- step_connect.go | 26 ++------------------------ step_hardware.go | 7 +++---- step_run.go | 17 ++++++++--------- step_shutdown.go | 7 +++---- step_snapshot.go | 5 ++--- step_template.go | 5 ++--- 9 files changed, 78 insertions(+), 64 deletions(-) create mode 100644 driver.go diff --git a/builder.go b/builder.go index 5487cd39b..360cb58f3 100644 --- a/builder.go +++ b/builder.go @@ -10,7 +10,6 @@ import ( "github.com/hashicorp/packer/helper/communicator" gossh "golang.org/x/crypto/ssh" "github.com/hashicorp/packer/communicator/ssh" - "context" "github.com/vmware/govmomi/object" ) @@ -33,7 +32,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe state := new(multistep.BasicStateBag) state.Put("hook", hook) state.Put("ui", ui) - state.Put("ctx", context.TODO()) steps := []multistep.Step{ &StepConnect{ diff --git a/driver.go b/driver.go new file mode 100644 index 000000000..65437722f --- /dev/null +++ b/driver.go @@ -0,0 +1,46 @@ +package main + +import ( + "github.com/vmware/govmomi" + "github.com/vmware/govmomi/find" + "context" + "net/url" + "fmt" + "github.com/vmware/govmomi/object" +) + +type Driver struct { + ctx context.Context + client *govmomi.Client + datacenter *object.Datacenter + finder *find.Finder +} + +func NewDriverVSphere(config *ConnectConfig) (Driver, error) { + ctx := context.TODO() + + vcenter_url, err := url.Parse(fmt.Sprintf("https://%v/sdk", config.VCenterServer)) + if err != nil { + return Driver{}, err + } + vcenter_url.User = url.UserPassword(config.Username, config.Password) + client, err := govmomi.NewClient(ctx, vcenter_url, config.InsecureConnection) + if err != nil { + return Driver{}, err + } + + finder := find.NewFinder(client.Client, false) + datacenter, err := finder.DatacenterOrDefault(ctx, config.Datacenter) + if err != nil { + return Driver{}, err + } + finder.SetDatacenter(datacenter) + + d := Driver{ + ctx: ctx, + client: client, + datacenter: datacenter, + finder: finder, + } + return d, nil +} diff --git a/step_clone.go b/step_clone.go index 519adb6b4..faf4041be 100644 --- a/step_clone.go +++ b/step_clone.go @@ -6,7 +6,6 @@ import ( "github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/object" "github.com/hashicorp/packer/packer" - "github.com/vmware/govmomi/find" "fmt" "github.com/vmware/govmomi/vim25/mo" "errors" @@ -49,39 +48,37 @@ type CloneParameters struct { } type StepCloneVM struct { - config *CloneConfig + config *CloneConfig } func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction { - ctx := state.Get("ctx").(context.Context) - finder := state.Get("finder").(*find.Finder) - datacenter := state.Get("datacenter").(*object.Datacenter) + d := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) - vmSrc, err := finder.VirtualMachine(ctx, s.config.Template) + vmSrc, err := d.finder.VirtualMachine(d.ctx, s.config.Template) if err != nil { state.Put("error", err) return multistep.ActionHalt } state.Put("vmSrc", vmSrc) - ui.Say("start cloning...") + ui.Say("Cloning VM...") - folder, err := finder.FolderOrDefault(ctx, fmt.Sprintf("/%v/vm/%v", datacenter.Name(), s.config.FolderName)) + folder, err := d.finder.FolderOrDefault(d.ctx, fmt.Sprintf("/%v/vm/%v", d.datacenter.Name(), s.config.FolderName)) if err != nil { state.Put("error", err) return multistep.ActionHalt } - pool, err := finder.ResourcePoolOrDefault(ctx, fmt.Sprintf("/%v/host/%v/Resources/%v", datacenter.Name(), s.config.Host, s.config.ResourcePool)) + pool, err := d.finder.ResourcePoolOrDefault(d.ctx, fmt.Sprintf("/%v/host/%v/Resources/%v", d.datacenter.Name(), s.config.Host, s.config.ResourcePool)) if err != nil { state.Put("error", err) return multistep.ActionHalt } - var datastore *object.Datastore = nil + var datastore *object.Datastore if s.config.Datastore != "" { - datastore, err = finder.Datastore(ctx, s.config.Datastore) + datastore, err = d.finder.Datastore(d.ctx, s.config.Datastore) if err != nil { state.Put("error", err) return multistep.ActionHalt @@ -89,7 +86,7 @@ func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction { } vm, err := cloneVM(&CloneParameters{ - ctx: ctx, + ctx: d.ctx, vmSrc: vmSrc, vmName: s.config.VMName, folder: folder, @@ -114,17 +111,17 @@ func (s *StepCloneVM) Cleanup(state multistep.StateBag) { } if vm, ok := state.GetOk("vm"); ok { - ctx := state.Get("ctx").(context.Context) + d := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) ui.Say("Destroying VM...") - task, err := vm.(*object.VirtualMachine).Destroy(ctx) + task, err := vm.(*object.VirtualMachine).Destroy(d.ctx) if err != nil { ui.Error(err.Error()) return } - _, err = task.WaitForResult(ctx, nil) + _, err = task.WaitForResult(d.ctx, nil) if err != nil { ui.Error(err.Error()) return diff --git a/step_connect.go b/step_connect.go index a42a5d166..1d3063f58 100644 --- a/step_connect.go +++ b/step_connect.go @@ -2,11 +2,7 @@ package main import ( "github.com/mitchellh/multistep" - "context" "fmt" - "net/url" - "github.com/vmware/govmomi" - "github.com/vmware/govmomi/find" ) type ConnectConfig struct { @@ -38,30 +34,12 @@ type StepConnect struct { } func (s *StepConnect) Run(state multistep.StateBag) multistep.StepAction { - ctx := state.Get("ctx").(context.Context) - - vcenter_url, err := url.Parse(fmt.Sprintf("https://%v/sdk", s.config.VCenterServer)) + driver, err := NewDriverVSphere(s.config) if err != nil { state.Put("error", err) return multistep.ActionHalt } - vcenter_url.User = url.UserPassword(s.config.Username, s.config.Password) - client, err := govmomi.NewClient(ctx, vcenter_url, s.config.InsecureConnection) - if err != nil { - state.Put("error", err) - return multistep.ActionHalt - } - state.Put("client", client) - - finder := find.NewFinder(client.Client, false) - datacenter, err := finder.DatacenterOrDefault(ctx, s.config.Datacenter) - if err != nil { - state.Put("error", err) - return multistep.ActionHalt - } - finder.SetDatacenter(datacenter) - state.Put("finder", finder) - state.Put("datacenter", datacenter) + state.Put("driver", driver) return multistep.ActionContinue } diff --git a/step_hardware.go b/step_hardware.go index 076fa1c73..9da092ef6 100644 --- a/step_hardware.go +++ b/step_hardware.go @@ -4,7 +4,6 @@ import ( "github.com/mitchellh/multistep" "github.com/hashicorp/packer/packer" "github.com/vmware/govmomi/vim25/types" - "context" "github.com/vmware/govmomi/object" "fmt" ) @@ -33,8 +32,8 @@ type StepConfigureHardware struct { } func (s *StepConfigureHardware) Run(state multistep.StateBag) multistep.StepAction { + d := state.Get("driver").(Driver) vm := state.Get("vm").(*object.VirtualMachine) - ctx := state.Get("ctx").(context.Context) ui := state.Get("ui").(packer.Ui) if *s.config != (HardwareConfig{}) { @@ -55,12 +54,12 @@ func (s *StepConfigureHardware) Run(state multistep.StateBag) multistep.StepActi confSpec.MemoryReservationLockedToMax = &s.config.RAMReserveAll - task, err := vm.Reconfigure(ctx, confSpec) + task, err := vm.Reconfigure(d.ctx, confSpec) if err != nil { state.Put("error", err) return multistep.ActionHalt } - _, err = task.WaitForResult(ctx, nil) + _, err = task.WaitForResult(d.ctx, nil) if err != nil { state.Put("error", err) return multistep.ActionHalt diff --git a/step_run.go b/step_run.go index b603cdd84..f0d20e23a 100644 --- a/step_run.go +++ b/step_run.go @@ -4,7 +4,6 @@ import ( "github.com/mitchellh/multistep" "github.com/hashicorp/packer/packer" "github.com/vmware/govmomi/object" - "context" "fmt" "github.com/vmware/govmomi/vim25/types" ) @@ -16,22 +15,22 @@ type StepRun struct{ func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) vm := state.Get("vm").(*object.VirtualMachine) - ctx := state.Get("ctx").(context.Context) + d := state.Get("driver").(Driver) ui.Say("VM power on...") - task, err := vm.PowerOn(ctx) + task, err := vm.PowerOn(d.ctx) if err != nil { state.Put("error", err) return multistep.ActionHalt } - _, err = task.WaitForResult(ctx, nil) + _, err = task.WaitForResult(d.ctx, nil) if err != nil { state.Put("error", err) return multistep.ActionHalt } ui.Say("VM waiting for IP...") - ip, err := vm.WaitForIP(ctx) + ip, err := vm.WaitForIP(d.ctx) if err != nil { state.Put("error", err) return multistep.ActionHalt @@ -48,18 +47,18 @@ func (s *StepRun) Cleanup(state multistep.StateBag) { if cancelled || halted { vm := state.Get("vm").(*object.VirtualMachine) - ctx := state.Get("ctx").(context.Context) + d := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) - if state, err := vm.PowerState(ctx); state != types.VirtualMachinePowerStatePoweredOff && err == nil { + if state, err := vm.PowerState(d.ctx); state != types.VirtualMachinePowerStatePoweredOff && err == nil { ui.Say("shutting down VM...") - task, err := vm.PowerOff(ctx) + task, err := vm.PowerOff(d.ctx) if err != nil { ui.Error(err.Error()) return } - _, err = task.WaitForResult(ctx, nil) + _, err = task.WaitForResult(d.ctx, nil) if err != nil { ui.Error(err.Error()) return diff --git a/step_shutdown.go b/step_shutdown.go index 47e23259a..82e10b415 100644 --- a/step_shutdown.go +++ b/step_shutdown.go @@ -4,7 +4,6 @@ import ( "github.com/mitchellh/multistep" "github.com/hashicorp/packer/packer" "github.com/vmware/govmomi/object" - "context" "fmt" "log" "time" @@ -44,7 +43,7 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction { comm := state.Get("communicator").(packer.Communicator) ui := state.Get("ui").(packer.Ui) vm := state.Get("vm").(*object.VirtualMachine) - ctx := state.Get("ctx").(context.Context) + d := state.Get("driver").(Driver) ui.Say("Shut down VM...") @@ -65,7 +64,7 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction { } else { ui.Say("Forcibly halting virtual machine...") - err := vm.ShutdownGuest(ctx) + err := vm.ShutdownGuest(d.ctx) if err != nil { state.Put("error", fmt.Errorf("Cannot shut down VM: %v", err)) return multistep.ActionHalt @@ -76,7 +75,7 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction { log.Printf("Waiting max %s for shutdown to complete", s.config.Timeout) shutdownTimer := time.After(s.config.Timeout) for { - powerState, err := vm.PowerState(ctx) + powerState, err := vm.PowerState(d.ctx) if err != nil { state.Put("error", err) return multistep.ActionHalt diff --git a/step_snapshot.go b/step_snapshot.go index 81a07acee..61ba9af03 100644 --- a/step_snapshot.go +++ b/step_snapshot.go @@ -3,7 +3,6 @@ package main import ( "github.com/mitchellh/multistep" "github.com/hashicorp/packer/packer" - "context" "github.com/vmware/govmomi/object" ) @@ -14,12 +13,12 @@ type StepCreateSnapshot struct{ func (s *StepCreateSnapshot) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) vm := state.Get("vm").(*object.VirtualMachine) - ctx := state.Get("ctx").(context.Context) + d := state.Get("driver").(Driver) if s.createSnapshot { ui.Say("creating snapshot...") - _, err := vm.CreateSnapshot(ctx, "packer_snapshot", "", true, true) + _, err := vm.CreateSnapshot(d.ctx, "packer_snapshot", "", true, true) if err != nil { state.Put("error", err) return multistep.ActionHalt diff --git a/step_template.go b/step_template.go index 3b64985bc..2a5519a41 100644 --- a/step_template.go +++ b/step_template.go @@ -4,7 +4,6 @@ import ( "github.com/mitchellh/multistep" "github.com/hashicorp/packer/packer" "github.com/vmware/govmomi/object" - "context" ) type StepConvertToTemplate struct{ @@ -14,12 +13,12 @@ type StepConvertToTemplate struct{ func (s *StepConvertToTemplate) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) vm := state.Get("vm").(*object.VirtualMachine) - ctx := state.Get("ctx").(context.Context) + d := state.Get("driver").(Driver) // Turning into template if needed if s.ConvertToTemplate { ui.Say("turning into template...") - err := vm.MarkAsTemplate(ctx) + err := vm.MarkAsTemplate(d.ctx) if err != nil { state.Put("error", err) return multistep.ActionHalt