github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/post-processor/vsphere-template/step_mark_as_template.go (about) 1 package vsphere_template 2 3 import ( 4 "context" 5 "fmt" 6 "path" 7 "strings" 8 9 "github.com/hashicorp/packer/packer" 10 "github.com/mitchellh/multistep" 11 "github.com/vmware/govmomi" 12 "github.com/vmware/govmomi/object" 13 ) 14 15 type stepMarkAsTemplate struct { 16 VMName string 17 Source string 18 } 19 20 func (s *stepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction { 21 ui := state.Get("ui").(packer.Ui) 22 cli := state.Get("client").(*govmomi.Client) 23 folder := state.Get("folder").(*object.Folder) 24 dcPath := state.Get("dcPath").(string) 25 26 ui.Message("Marking as a template...") 27 28 vm, err := findRuntimeVM(cli, dcPath, s.VMName) 29 if err != nil { 30 state.Put("error", err) 31 ui.Error(err.Error()) 32 return multistep.ActionHalt 33 } 34 35 host, err := vm.HostSystem(context.Background()) 36 if err != nil { 37 state.Put("error", err) 38 ui.Error(err.Error()) 39 return multistep.ActionHalt 40 } 41 42 if err := vm.Unregister(context.Background()); err != nil { 43 state.Put("error", err) 44 ui.Error(err.Error()) 45 return multistep.ActionHalt 46 } 47 48 source := strings.Split(s.Source, "/vmfs/volumes/")[1] 49 i := strings.Index(source, "/") 50 51 path := (&object.DatastorePath{ 52 Datastore: source[:i], 53 Path: source[i:], 54 }).String() 55 56 if err := unregisterPreviousVM(cli, folder, s.VMName); err != nil { 57 state.Put("error", err) 58 ui.Error(err.Error()) 59 return multistep.ActionHalt 60 } 61 62 task, err := folder.RegisterVM(context.Background(), path, s.VMName, true, nil, host) 63 if err != nil { 64 state.Put("error", err) 65 ui.Error(err.Error()) 66 return multistep.ActionHalt 67 } 68 69 if err = task.Wait(context.Background()); err != nil { 70 state.Put("error", err) 71 ui.Error(err.Error()) 72 return multistep.ActionHalt 73 } 74 75 return multistep.ActionContinue 76 } 77 78 // We will use the virtual machine created by vmware-iso builder 79 func findRuntimeVM(cli *govmomi.Client, dcPath, name string) (*object.VirtualMachine, error) { 80 si := object.NewSearchIndex(cli.Client) 81 fullPath := path.Join(dcPath, "vm", "Discovered virtual machine", name) 82 83 ref, err := si.FindByInventoryPath(context.Background(), fullPath) 84 if err != nil { 85 return nil, err 86 } 87 88 if ref == nil { 89 return nil, fmt.Errorf("VM at path %s not found", fullPath) 90 } 91 92 return ref.(*object.VirtualMachine), nil 93 } 94 95 // If in the target folder a virtual machine or template already exists 96 // it will be removed to maintain consistency 97 func unregisterPreviousVM(cli *govmomi.Client, folder *object.Folder, name string) error { 98 si := object.NewSearchIndex(cli.Client) 99 fullPath := path.Join(folder.InventoryPath, name) 100 101 ref, err := si.FindByInventoryPath(context.Background(), fullPath) 102 if err != nil { 103 return err 104 } 105 106 if ref != nil { 107 if vm, ok := ref.(*object.VirtualMachine); ok { 108 return vm.Unregister(context.Background()) 109 } else { 110 return fmt.Errorf("an object name '%v' already exists", name) 111 } 112 113 } 114 115 return nil 116 } 117 118 func (s *stepMarkAsTemplate) Cleanup(multistep.StateBag) {}