From c338cb79d05629a5b6462ebcd122003d90e95ea6 Mon Sep 17 00:00:00 2001 From: Ben Phegan Date: Fri, 15 Dec 2017 13:24:15 +1100 Subject: [PATCH] Initial commit of feature to allow MAC address specification for HyperV builders --- builder/hyperv/common/driver.go | 2 ++ builder/hyperv/common/driver_mock.go | 12 ++++++++++++ builder/hyperv/common/driver_ps_4.go | 4 ++++ builder/hyperv/common/step_clone_vm.go | 11 +++++++++++ builder/hyperv/common/step_create_vm.go | 11 +++++++++++ builder/hyperv/iso/builder.go | 1 + builder/hyperv/vmcx/builder.go | 2 ++ common/powershell/hyperv/hyperv.go | 12 ++++++++++++ website/source/docs/builders/hyperv-iso.html.md | 6 +++++- website/source/docs/builders/hyperv-vmcx.html.md | 4 ++++ 10 files changed, 64 insertions(+), 1 deletion(-) diff --git a/builder/hyperv/common/driver.go b/builder/hyperv/common/driver.go index 2a2f0b810..571214acd 100644 --- a/builder/hyperv/common/driver.go +++ b/builder/hyperv/common/driver.go @@ -52,6 +52,8 @@ type Driver interface { //Set the vlan to use for machine SetVirtualMachineVlanId(string, string) error + SetVmNetworkAdapterMacAddress(string, string) error + UntagVirtualMachineNetworkAdapterVlan(string, string) error CreateExternalVirtualSwitch(string, string) error diff --git a/builder/hyperv/common/driver_mock.go b/builder/hyperv/common/driver_mock.go index 3823cbd12..7d8e02c6a 100644 --- a/builder/hyperv/common/driver_mock.go +++ b/builder/hyperv/common/driver_mock.go @@ -67,6 +67,11 @@ type DriverMock struct { SetNetworkAdapterVlanId_VlanId string SetNetworkAdapterVlanId_Err error + SetVmNetworkAdapterMacAddress_Called bool + SetVmNetworkAdapterMacAddress_VmName string + SetVmNetworkAdapterMacAddress_Mac string + SetVmNetworkAdapterMacAddress_Err error + SetVirtualMachineVlanId_Called bool SetVirtualMachineVlanId_VmName string SetVirtualMachineVlanId_VlanId string @@ -318,6 +323,13 @@ func (d *DriverMock) SetNetworkAdapterVlanId(switchName string, vlanId string) e return d.SetNetworkAdapterVlanId_Err } +func (d *DriverMock) SetVmNetworkAdapterMacAddress(vmName string, mac string) error { + d.SetVmNetworkAdapterMacAddress_Called = true + d.SetVmNetworkAdapterMacAddress_VmName = vmName + d.SetVmNetworkAdapterMacAddress_Mac = mac + return d.SetVmNetworkAdapterMacAddress_Err +} + func (d *DriverMock) SetVirtualMachineVlanId(vmName string, vlanId string) error { d.SetVirtualMachineVlanId_Called = true d.SetVirtualMachineVlanId_VmName = vmName diff --git a/builder/hyperv/common/driver_ps_4.go b/builder/hyperv/common/driver_ps_4.go index 853aa7021..a6c1b7352 100644 --- a/builder/hyperv/common/driver_ps_4.go +++ b/builder/hyperv/common/driver_ps_4.go @@ -146,6 +146,10 @@ func (d *HypervPS4Driver) SetVirtualMachineVlanId(vmName string, vlanId string) return hyperv.SetVirtualMachineVlanId(vmName, vlanId) } +func (d *HypervPS4Driver) SetVmNetworkAdapterMacAddress(vmName string, mac string) error { + return hyperv.SetVmNetworkAdapterMacAddress(vmName, mac) +} + func (d *HypervPS4Driver) UntagVirtualMachineNetworkAdapterVlan(vmName string, switchName string) error { return hyperv.UntagVirtualMachineNetworkAdapterVlan(vmName, switchName) } diff --git a/builder/hyperv/common/step_clone_vm.go b/builder/hyperv/common/step_clone_vm.go index 4a5b55566..24d731b02 100644 --- a/builder/hyperv/common/step_clone_vm.go +++ b/builder/hyperv/common/step_clone_vm.go @@ -27,6 +27,7 @@ type StepCloneVM struct { EnableDynamicMemory bool EnableSecureBoot bool EnableVirtualizationExtensions bool + MacAddress string } func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction { @@ -117,6 +118,16 @@ func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction { } } + if s.MacAddress != "" { + err = driver.SetVmNetworkAdapterMacAddress(s.VMName, s.MacAddress) + if err != nil { + err := fmt.Errorf("Error setting MAC address: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + } + // Set the final name in the state bag so others can use it state.Put("vmName", s.VMName) diff --git a/builder/hyperv/common/step_create_vm.go b/builder/hyperv/common/step_create_vm.go index 02171d9c6..92fdbcb04 100644 --- a/builder/hyperv/common/step_create_vm.go +++ b/builder/hyperv/common/step_create_vm.go @@ -28,6 +28,7 @@ type StepCreateVM struct { EnableVirtualizationExtensions bool AdditionalDiskSize []uint DifferencingDisk bool + MacAddress string } func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction { @@ -124,6 +125,16 @@ func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction { } } + if s.MacAddress != "" { + err = driver.SetVmNetworkAdapterMacAddress(s.VMName, s.MacAddress) + if err != nil { + err := fmt.Errorf("Error setting MAC address: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + } + // Set the final name in the state bag so others can use it state.Put("vmName", s.VMName) diff --git a/builder/hyperv/iso/builder.go b/builder/hyperv/iso/builder.go index 849cbcacf..fd27cf94b 100644 --- a/builder/hyperv/iso/builder.go +++ b/builder/hyperv/iso/builder.go @@ -74,6 +74,7 @@ type Config struct { BootCommand []string `mapstructure:"boot_command"` SwitchName string `mapstructure:"switch_name"` SwitchVlanId string `mapstructure:"switch_vlan_id"` + MacAddress string `mapstructure:"mac_address"` VlanId string `mapstructure:"vlan_id"` Cpu uint `mapstructure:"cpu"` Generation uint `mapstructure:"generation"` diff --git a/builder/hyperv/vmcx/builder.go b/builder/hyperv/vmcx/builder.go index 6a976b3df..ae0e4c61e 100644 --- a/builder/hyperv/vmcx/builder.go +++ b/builder/hyperv/vmcx/builder.go @@ -82,6 +82,7 @@ type Config struct { BootCommand []string `mapstructure:"boot_command"` SwitchName string `mapstructure:"switch_name"` SwitchVlanId string `mapstructure:"switch_vlan_id"` + MacAddress string `mapstructure:"mac_address"` VlanId string `mapstructure:"vlan_id"` Cpu uint `mapstructure:"cpu"` Generation uint @@ -403,6 +404,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe EnableDynamicMemory: b.config.EnableDynamicMemory, EnableSecureBoot: b.config.EnableSecureBoot, EnableVirtualizationExtensions: b.config.EnableVirtualizationExtensions, + MacAddress: b.config.MacAddress, }, &hypervcommon.StepEnableIntegrationService{}, diff --git a/common/powershell/hyperv/hyperv.go b/common/powershell/hyperv/hyperv.go index 25073d238..d26ec5eeb 100644 --- a/common/powershell/hyperv/hyperv.go +++ b/common/powershell/hyperv/hyperv.go @@ -319,6 +319,18 @@ Copy-Item $cloneFromVmxcPath $exportPath -Recurse -Force return err } +func SetVmNetworkAdapterMacAddress(vmName string, mac string) error { + var script = ` +param([string]$vmName, [string]$mac) +Set-VMNetworkAdapter $vmName -staticmacaddress $mac + ` + + var ps powershell.PowerShellCmd + err := ps.Run(script, vmName, mac) + + return err +} + func ImportVmxcVirtualMachine(importPath string, vmName string, harddrivePath string, ram int64, switchName string) error { var script = ` param([string]$importPath, [string]$vmName, [string]$harddrivePath, [long]$memoryStartupBytes, [string]$switchName) diff --git a/website/source/docs/builders/hyperv-iso.html.md b/website/source/docs/builders/hyperv-iso.html.md index ff267392c..41e603129 100644 --- a/website/source/docs/builders/hyperv-iso.html.md +++ b/website/source/docs/builders/hyperv-iso.html.md @@ -204,7 +204,7 @@ can be configured for this builder. By default none is set. If none is set then a vlan is not set on the switch's network card. If this value is set it should match the vlan specified in by `vlan_id`. -* `vhd_temp_path` (string) - A separate path to be used for storing the VM's +- `vhd_temp_path` (string) - A separate path to be used for storing the VM's disk image. The purpose is to enable reading and writing to take place on different physical disks (read from VHD temp path, write to regular temp path while exporting the VM) to eliminate a single-disk bottleneck. @@ -213,6 +213,10 @@ can be configured for this builder. for the new virtual machine. By default none is set. If none is set then vlans are not set on the virtual machine's network card. +- `mac_address` (string) - This allows a specific MAC address to be used on the + default virtual network card. The MAC address must be a string with no + delimeters, for example "0000deadbeef". + - `vm_name` (string) - This is the name of the virtual machine for the new virtual machine, without the file extension. By default this is "packer-BUILDNAME", where "BUILDNAME" is the name of the build. diff --git a/website/source/docs/builders/hyperv-vmcx.html.md b/website/source/docs/builders/hyperv-vmcx.html.md index 1aac29fc1..a7afe93ce 100644 --- a/website/source/docs/builders/hyperv-vmcx.html.md +++ b/website/source/docs/builders/hyperv-vmcx.html.md @@ -225,6 +225,10 @@ can be configured for this builder. for the new virtual machine. By default none is set. If none is set then vlans are not set on the virtual machine's network card. +- `mac_address` (string) - This allows a specific MAC address to be used on the + default virtual network card. The MAC address must be a string with no + delimeters, for example "0000deadbeef". + - `vm_name` (string) - This is the name of the virtual machine for the new virtual machine, without the file extension. By default this is "packer-BUILDNAME", where "BUILDNAME" is the name of the build.