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