github.phpd.cn/hashicorp/packer@v1.3.2/builder/hyperv/common/step_clone_vm.go (about) 1 package common 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 "path/filepath" 8 "strings" 9 10 "github.com/hashicorp/packer/helper/multistep" 11 "github.com/hashicorp/packer/packer" 12 ) 13 14 // This step clones an existing virtual machine. 15 // 16 // Produces: 17 // VMName string - The name of the VM 18 type StepCloneVM struct { 19 CloneFromVMCXPath string 20 CloneFromVMName string 21 CloneFromSnapshotName string 22 CloneAllSnapshots bool 23 VMName string 24 SwitchName string 25 RamSize uint 26 Cpu uint 27 EnableMacSpoofing bool 28 EnableDynamicMemory bool 29 EnableSecureBoot bool 30 SecureBootTemplate string 31 EnableVirtualizationExtensions bool 32 MacAddress string 33 } 34 35 func (s *StepCloneVM) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { 36 driver := state.Get("driver").(Driver) 37 ui := state.Get("ui").(packer.Ui) 38 ui.Say("Cloning virtual machine...") 39 40 path := state.Get("build_dir").(string) 41 42 // Determine if we even have an existing virtual harddrive to attach 43 harddrivePath := "" 44 if harddrivePathRaw, ok := state.GetOk("iso_path"); ok { 45 extension := strings.ToLower(filepath.Ext(harddrivePathRaw.(string))) 46 if extension == ".vhd" || extension == ".vhdx" { 47 harddrivePath = harddrivePathRaw.(string) 48 } else { 49 log.Println("No existing virtual harddrive, not attaching.") 50 } 51 } else { 52 log.Println("No existing virtual harddrive, not attaching.") 53 } 54 55 // convert the MB to bytes 56 ramSize := int64(s.RamSize * 1024 * 1024) 57 58 err := driver.CloneVirtualMachine(s.CloneFromVMCXPath, s.CloneFromVMName, s.CloneFromSnapshotName, 59 s.CloneAllSnapshots, s.VMName, path, harddrivePath, ramSize, s.SwitchName) 60 if err != nil { 61 err := fmt.Errorf("Error cloning virtual machine: %s", err) 62 state.Put("error", err) 63 ui.Error(err.Error()) 64 return multistep.ActionHalt 65 } 66 67 err = driver.SetVirtualMachineCpuCount(s.VMName, s.Cpu) 68 if err != nil { 69 err := fmt.Errorf("Error creating setting virtual machine cpu: %s", err) 70 state.Put("error", err) 71 ui.Error(err.Error()) 72 return multistep.ActionHalt 73 } 74 75 if s.EnableDynamicMemory { 76 err = driver.SetVirtualMachineDynamicMemory(s.VMName, s.EnableDynamicMemory) 77 if err != nil { 78 err := fmt.Errorf("Error creating setting virtual machine dynamic memory: %s", err) 79 state.Put("error", err) 80 ui.Error(err.Error()) 81 return multistep.ActionHalt 82 } 83 } 84 85 if s.EnableMacSpoofing { 86 err = driver.SetVirtualMachineMacSpoofing(s.VMName, s.EnableMacSpoofing) 87 if err != nil { 88 err := fmt.Errorf("Error creating setting virtual machine mac spoofing: %s", err) 89 state.Put("error", err) 90 ui.Error(err.Error()) 91 return multistep.ActionHalt 92 } 93 } 94 95 generation, err := driver.GetVirtualMachineGeneration(s.VMName) 96 if err != nil { 97 err := fmt.Errorf("Error detecting vm generation: %s", err) 98 state.Put("error", err) 99 ui.Error(err.Error()) 100 return multistep.ActionHalt 101 } 102 103 if generation == 2 { 104 105 err = driver.SetVirtualMachineSecureBoot(s.VMName, s.EnableSecureBoot, s.SecureBootTemplate) 106 if err != nil { 107 err := fmt.Errorf("Error setting secure boot: %s", err) 108 state.Put("error", err) 109 ui.Error(err.Error()) 110 return multistep.ActionHalt 111 } 112 } 113 114 if s.EnableVirtualizationExtensions { 115 //This is only supported on Windows 10 and Windows Server 2016 onwards 116 err = driver.SetVirtualMachineVirtualizationExtensions(s.VMName, s.EnableVirtualizationExtensions) 117 if err != nil { 118 err := fmt.Errorf("Error creating setting virtual machine virtualization extensions: %s", err) 119 state.Put("error", err) 120 ui.Error(err.Error()) 121 return multistep.ActionHalt 122 } 123 } 124 125 if s.MacAddress != "" { 126 err = driver.SetVmNetworkAdapterMacAddress(s.VMName, s.MacAddress) 127 if err != nil { 128 err := fmt.Errorf("Error setting MAC address: %s", err) 129 state.Put("error", err) 130 ui.Error(err.Error()) 131 return multistep.ActionHalt 132 } 133 } 134 135 // Set the final name in the state bag so others can use it 136 state.Put("vmName", s.VMName) 137 138 return multistep.ActionContinue 139 } 140 141 func (s *StepCloneVM) Cleanup(state multistep.StateBag) { 142 if s.VMName == "" { 143 return 144 } 145 146 driver := state.Get("driver").(Driver) 147 ui := state.Get("ui").(packer.Ui) 148 ui.Say("Unregistering and deleting virtual machine...") 149 150 err := driver.DeleteVirtualMachine(s.VMName) 151 if err != nil { 152 ui.Error(fmt.Sprintf("Error deleting virtual machine: %s", err)) 153 } 154 }