github.phpd.cn/hashicorp/packer@v1.3.2/builder/hyperv/common/step_create_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 creates the actual virtual machine.
    15  //
    16  // Produces:
    17  //   VMName string - The name of the VM
    18  type StepCreateVM struct {
    19  	VMName                         string
    20  	SwitchName                     string
    21  	HarddrivePath                  string
    22  	RamSize                        uint
    23  	DiskSize                       uint
    24  	DiskBlockSize                  uint
    25  	Generation                     uint
    26  	Cpu                            uint
    27  	EnableMacSpoofing              bool
    28  	EnableDynamicMemory            bool
    29  	EnableSecureBoot               bool
    30  	SecureBootTemplate             string
    31  	EnableVirtualizationExtensions bool
    32  	AdditionalDiskSize             []uint
    33  	DifferencingDisk               bool
    34  	MacAddress                     string
    35  	FixedVHD                       bool
    36  }
    37  
    38  func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
    39  	driver := state.Get("driver").(Driver)
    40  	ui := state.Get("ui").(packer.Ui)
    41  	ui.Say("Creating virtual machine...")
    42  
    43  	var path string
    44  	if v, ok := state.GetOk("build_dir"); ok {
    45  		path = v.(string)
    46  	}
    47  
    48  	// Determine if we even have an existing virtual harddrive to attach
    49  	harddrivePath := ""
    50  	if harddrivePathRaw, ok := state.GetOk("iso_path"); ok {
    51  		extension := strings.ToLower(filepath.Ext(harddrivePathRaw.(string)))
    52  		if extension == ".vhd" || extension == ".vhdx" {
    53  			harddrivePath = harddrivePathRaw.(string)
    54  		} else {
    55  			log.Println("No existing virtual harddrive, not attaching.")
    56  		}
    57  	} else {
    58  		log.Println("No existing virtual harddrive, not attaching.")
    59  	}
    60  
    61  	// convert the MB to bytes
    62  	ramSize := int64(s.RamSize * 1024 * 1024)
    63  	diskSize := int64(s.DiskSize * 1024 * 1024)
    64  	diskBlockSize := int64(s.DiskBlockSize * 1024 * 1024)
    65  
    66  	err := driver.CreateVirtualMachine(s.VMName, path, harddrivePath, ramSize, diskSize, diskBlockSize,
    67  		s.SwitchName, s.Generation, s.DifferencingDisk, s.FixedVHD)
    68  	if err != nil {
    69  		err := fmt.Errorf("Error creating virtual machine: %s", err)
    70  		state.Put("error", err)
    71  		ui.Error(err.Error())
    72  		return multistep.ActionHalt
    73  	}
    74  
    75  	err = driver.SetVirtualMachineCpuCount(s.VMName, s.Cpu)
    76  	if err != nil {
    77  		err := fmt.Errorf("Error setting virtual machine cpu count: %s", err)
    78  		state.Put("error", err)
    79  		ui.Error(err.Error())
    80  		return multistep.ActionHalt
    81  	}
    82  
    83  	err = driver.SetVirtualMachineDynamicMemory(s.VMName, s.EnableDynamicMemory)
    84  	if err != nil {
    85  		err := fmt.Errorf("Error setting virtual machine dynamic memory: %s", err)
    86  		state.Put("error", err)
    87  		ui.Error(err.Error())
    88  		return multistep.ActionHalt
    89  	}
    90  
    91  	if s.EnableMacSpoofing {
    92  		err = driver.SetVirtualMachineMacSpoofing(s.VMName, s.EnableMacSpoofing)
    93  		if err != nil {
    94  			err := fmt.Errorf("Error setting virtual machine mac spoofing: %s", err)
    95  			state.Put("error", err)
    96  			ui.Error(err.Error())
    97  			return multistep.ActionHalt
    98  		}
    99  	}
   100  
   101  	if s.Generation == 2 {
   102  		err = driver.SetVirtualMachineSecureBoot(s.VMName, s.EnableSecureBoot, s.SecureBootTemplate)
   103  		if err != nil {
   104  			err := fmt.Errorf("Error setting secure boot: %s", err)
   105  			state.Put("error", err)
   106  			ui.Error(err.Error())
   107  			return multistep.ActionHalt
   108  		}
   109  	}
   110  
   111  	if s.EnableVirtualizationExtensions {
   112  		//This is only supported on Windows 10 and Windows Server 2016 onwards
   113  		err = driver.SetVirtualMachineVirtualizationExtensions(s.VMName, s.EnableVirtualizationExtensions)
   114  		if err != nil {
   115  			err := fmt.Errorf("Error setting virtual machine virtualization extensions: %s", err)
   116  			state.Put("error", err)
   117  			ui.Error(err.Error())
   118  			return multistep.ActionHalt
   119  		}
   120  	}
   121  
   122  	if len(s.AdditionalDiskSize) > 0 {
   123  		for index, size := range s.AdditionalDiskSize {
   124  			diskSize := int64(size * 1024 * 1024)
   125  			diskFile := fmt.Sprintf("%s-%d.vhdx", s.VMName, index)
   126  			err = driver.AddVirtualMachineHardDrive(s.VMName, path, diskFile, diskSize, diskBlockSize, "SCSI")
   127  			if err != nil {
   128  				err := fmt.Errorf("Error creating and attaching additional disk drive: %s", err)
   129  				state.Put("error", err)
   130  				ui.Error(err.Error())
   131  				return multistep.ActionHalt
   132  			}
   133  		}
   134  	}
   135  
   136  	if s.MacAddress != "" {
   137  		err = driver.SetVmNetworkAdapterMacAddress(s.VMName, s.MacAddress)
   138  		if err != nil {
   139  			err := fmt.Errorf("Error setting MAC address: %s", err)
   140  			state.Put("error", err)
   141  			ui.Error(err.Error())
   142  			return multistep.ActionHalt
   143  		}
   144  	}
   145  
   146  	// Set the final name in the state bag so others can use it
   147  	state.Put("vmName", s.VMName)
   148  
   149  	return multistep.ActionContinue
   150  }
   151  
   152  func (s *StepCreateVM) Cleanup(state multistep.StateBag) {
   153  	if s.VMName == "" {
   154  		return
   155  	}
   156  
   157  	driver := state.Get("driver").(Driver)
   158  	ui := state.Get("ui").(packer.Ui)
   159  	ui.Say("Unregistering and deleting virtual machine...")
   160  
   161  	err := driver.DeleteVirtualMachine(s.VMName)
   162  	if err != nil {
   163  		ui.Error(fmt.Sprintf("Error deleting virtual machine: %s", err))
   164  	}
   165  
   166  	// TODO: Clean up created VHDX
   167  }