From c43a52aafe53dcbbcc209d8bab62e795e3fc099f Mon Sep 17 00:00:00 2001 From: jhawk28 Date: Thu, 23 Apr 2020 08:07:07 -0400 Subject: [PATCH] fix issue where -force is not working with vsphere builders (#9039) * add better error support to check if vm exists use path.Join so that it looks up the VM correctly turn off VM if it is still running * fix the vsphere-clone also * add a common precleanvm to the driver to dedupe iso and clone logic, reduce the if nesting --- builder/vsphere/clone/step_clone.go | 18 ++++++---------- builder/vsphere/driver/vm.go | 32 ++++++++++++++++++++++++++--- builder/vsphere/iso/step_create.go | 18 ++++++---------- 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/builder/vsphere/clone/step_clone.go b/builder/vsphere/clone/step_clone.go index ff395738b..86f2ab7c9 100644 --- a/builder/vsphere/clone/step_clone.go +++ b/builder/vsphere/clone/step_clone.go @@ -6,6 +6,7 @@ package clone import ( "context" "fmt" + "path" "github.com/hashicorp/packer/builder/vsphere/common" "github.com/hashicorp/packer/builder/vsphere/driver" @@ -49,19 +50,12 @@ type StepCloneVM struct { func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) d := state.Get("driver").(*driver.Driver) - vmPath := fmt.Sprintf("%s/%s", s.Location.Folder, s.Location.VMName) + vmPath := path.Join(s.Location.Folder, s.Location.VMName) - vm, err := d.FindVM(vmPath) - - if s.Force == false && err == nil { - state.Put("error", fmt.Errorf("%s already exists, you can use -force flag to destroy it", vmPath)) + err := d.PreCleanVM(ui, vmPath, s.Force) + if err != nil { + state.Put("error", err) return multistep.ActionHalt - } else if s.Force == true && err == nil { - ui.Say(fmt.Sprintf("the vm/template %s already exists, but deleting it due to -force flag", vmPath)) - err := vm.Destroy() - if err != nil { - state.Put("error", fmt.Errorf("error destroying %s: %v", vmPath, err)) - } } ui.Say("Cloning VM...") @@ -71,7 +65,7 @@ func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multist return multistep.ActionHalt } - vm, err = template.Clone(ctx, &driver.CloneConfig{ + vm, err := template.Clone(ctx, &driver.CloneConfig{ Name: s.Location.VMName, Folder: s.Location.Folder, Cluster: s.Location.Cluster, diff --git a/builder/vsphere/driver/vm.go b/builder/vsphere/driver/vm.go index 1736bd892..6df99b987 100644 --- a/builder/vsphere/driver/vm.go +++ b/builder/vsphere/driver/vm.go @@ -8,12 +8,13 @@ import ( "strings" "time" - "github.com/vmware/govmomi/property" + "github.com/hashicorp/packer/packer" + "github.com/vmware/govmomi/find" "github.com/vmware/govmomi/nfc" - "github.com/vmware/govmomi/ovf" - "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/ovf" + "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" ) @@ -99,6 +100,31 @@ func (d *Driver) FindVM(name string) (*VirtualMachine, error) { }, nil } +func (d *Driver) PreCleanVM(ui packer.Ui, vmPath string, force bool) error { + vm, err := d.FindVM(vmPath) + if err != nil { + if _, ok := err.(*find.NotFoundError); !ok { + return fmt.Errorf("error looking up old vm: %v", err) + } + } + if force && vm != nil { + ui.Say(fmt.Sprintf("the vm/template %s already exists, but deleting it due to -force flag", vmPath)) + + // power off just in case it is still on + vm.PowerOff() + + err := vm.Destroy() + if err != nil { + return fmt.Errorf("error destroying %s: %v", vmPath, err) + } + } + if !force && vm != nil { + return fmt.Errorf("%s already exists, you can use -force flag to destroy it: %v", vmPath, err) + } + + return nil +} + func (d *Driver) CreateVM(config *CreateConfig) (*VirtualMachine, error) { createSpec := types.VirtualMachineConfigSpec{ Name: config.Name, diff --git a/builder/vsphere/iso/step_create.go b/builder/vsphere/iso/step_create.go index 701910fd7..6ebd9d7e8 100644 --- a/builder/vsphere/iso/step_create.go +++ b/builder/vsphere/iso/step_create.go @@ -6,6 +6,7 @@ package iso import ( "context" "fmt" + "path" "github.com/hashicorp/packer/builder/vsphere/common" "github.com/hashicorp/packer/builder/vsphere/driver" @@ -131,19 +132,12 @@ type StepCreateVM struct { func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) d := state.Get("driver").(*driver.Driver) - vmPath := fmt.Sprintf("%s/%s", s.Location.Folder, s.Location.VMName) + vmPath := path.Join(s.Location.Folder, s.Location.VMName) - vm, err := d.FindVM(vmPath) - - if s.Force == false && err == nil { - state.Put("error", fmt.Errorf("%s already exists, you can use -force flag to destroy it: %v", vmPath, err)) + err := d.PreCleanVM(ui, vmPath, s.Force) + if err != nil { + state.Put("error", err) return multistep.ActionHalt - } else if s.Force == true && err == nil { - ui.Say(fmt.Sprintf("the vm/template %s already exists, but deleting it due to -force flag", vmPath)) - err := vm.Destroy() - if err != nil { - state.Put("error", fmt.Errorf("error destroying %s: %v", vmPath, err)) - } } ui.Say("Creating VM...") @@ -181,7 +175,7 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste }) } - vm, err = d.CreateVM(&driver.CreateConfig{ + vm, err := d.CreateVM(&driver.CreateConfig{ DiskControllerType: s.Config.DiskControllerType, Storage: disks, Annotation: s.Config.Notes,