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  }