Add support for mac spoofing and dynamic memory.

To enable nested virtualization, mac spoofing, no dynamic memory and at least 4gb of ram should be set for the vm. Set warning if this has not been done.
Detected Virtualization Extensions are supported by the machine your are running on, as it only works for Windows 10 and Windows Server 2016 onwards.
pull/2576/head
Taliesin Sisson 10 years ago
parent 1277a25d0b
commit 9fbd1e472a

@ -72,9 +72,15 @@ type Driver interface {
DeleteVirtualMachine(string) error
SetVirtualMachineCpu(string, uint, bool) error
SetVirtualMachineCpuCount(string, uint) error
SetSecureBoot(string, bool) error
SetVirtualMachineMacSpoofing(string, bool) error
SetVirtualMachineDynamicMemory(string, bool) error
SetVirtualMachineSecureBoot(string, bool) error
SetVirtualMachineVirtualizationExtensions(string, bool) error
EnableVirtualMachineIntegrationService(string, string) error

@ -6,12 +6,13 @@ package common
import (
"fmt"
"github.com/mitchellh/packer/powershell"
"github.com/mitchellh/packer/powershell/hyperv"
"log"
"runtime"
"strconv"
"strings"
"github.com/mitchellh/packer/powershell"
"github.com/mitchellh/packer/powershell/hyperv"
)
type HypervPS4Driver struct {
@ -177,12 +178,24 @@ func (d *HypervPS4Driver) DeleteVirtualMachine(vmName string) error {
return hyperv.DeleteVirtualMachine(vmName)
}
func (d *HypervPS4Driver) SetVirtualMachineCpu(vmName string, cpu uint, exposeVirtualizationExtensions bool) error {
return hyperv.SetVirtualMachineCpu(vmName, cpu, exposeVirtualizationExtensions)
func (d *HypervPS4Driver) SetVirtualMachineCpuCount(vmName string, cpu uint) error {
return hyperv.SetVirtualMachineCpuCount(vmName, cpu)
}
func (d *HypervPS4Driver) SetVirtualMachineMacSpoofing(vmName string, enable bool) error {
return hyperv.SetVirtualMachineMacSpoofing(vmName, enable)
}
func (d *HypervPS4Driver) SetVirtualMachineDynamicMemory(vmName string, enable bool) error {
return hyperv.SetVirtualMachineDynamicMemory(vmName, enable)
}
func (d *HypervPS4Driver) SetVirtualMachineSecureBoot(vmName string, enable bool) error {
return hyperv.SetVirtualMachineSecureBoot(vmName, enable)
}
func (d *HypervPS4Driver) SetSecureBoot(vmName string, enable bool) error {
return hyperv.SetSecureBoot(vmName, enable)
func (d *HypervPS4Driver) SetVirtualMachineVirtualizationExtensions(vmName string, enable bool) error {
return hyperv.SetVirtualMachineVirtualizationExtensions(vmName, enable)
}
func (d *HypervPS4Driver) EnableVirtualMachineIntegrationService(vmName string, integrationServiceName string) error {

@ -6,6 +6,7 @@ package common
import (
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
@ -15,13 +16,15 @@ import (
// Produces:
// VMName string - The name of the VM
type StepCreateVM struct {
VMName string
SwitchName string
RamSizeMB uint
DiskSize uint
Generation uint
Cpu uint
EnableSecureBoot bool
VMName string
SwitchName string
RamSizeMB uint
DiskSize uint
Generation uint
Cpu uint
EnableMacSpoofing bool
EnableDynamicMemory bool
EnableSecureBoot bool
EnableVirtualizationExtensions bool
}
@ -36,10 +39,7 @@ func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction {
ram := int64(s.RamSizeMB * 1024 * 1024)
diskSize := int64(s.DiskSize * 1024 * 1024)
switchName := s.SwitchName
enableSecureBoot := s.EnableSecureBoot
err := driver.CreateVirtualMachine(s.VMName, path, ram, diskSize, switchName, s.Generation)
err := driver.CreateVirtualMachine(s.VMName, path, ram, diskSize, s.SwitchName, s.Generation)
if err != nil {
err := fmt.Errorf("Error creating virtual machine: %s", err)
state.Put("error", err)
@ -47,7 +47,7 @@ func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
err = driver.SetVirtualMachineCpu(s.VMName, s.Cpu, s.EnableVirtualizationExtensions)
err = driver.SetVirtualMachineCpuCount(s.VMName, s.Cpu)
if err != nil {
err := fmt.Errorf("Error creating setting virtual machine cpu: %s", err)
state.Put("error", err)
@ -55,8 +55,28 @@ func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
if s.EnableDynamicMemory {
err = driver.SetVirtualMachineDynamicMemory(s.VMName, s.EnableDynamicMemory)
if err != nil {
err := fmt.Errorf("Error creating setting virtual machine dynamic memory: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
}
if s.EnableMacSpoofing {
err = driver.SetVirtualMachineMacSpoofing(s.VMName, s.EnableMacSpoofing)
if err != nil {
err := fmt.Errorf("Error creating setting virtual machine mac spoofing: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
}
if s.Generation == 2 {
err = driver.SetSecureBoot(s.VMName, enableSecureBoot)
err = driver.SetVirtualMachineSecureBoot(s.VMName, s.EnableSecureBoot)
if err != nil {
err := fmt.Errorf("Error setting secure boot: %s", err)
state.Put("error", err)
@ -65,6 +85,17 @@ func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction {
}
}
if s.EnableVirtualizationExtensions {
//This is only supported on Windows 10 and Windows Server 2016 onwards
err = driver.SetVirtualMachineVirtualizationExtensions(s.VMName, s.EnableVirtualizationExtensions)
if err != nil {
err := fmt.Errorf("Error creating setting virtual machine virtualization extensions: %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)

@ -28,9 +28,10 @@ const (
MinDiskSize = 256 // 256MB
MaxDiskSize = 64 * 1024 * 1024 // 64TB
DefaultRamSize = 1 * 1024 // 1GB
MinRamSize = 32 // 32MB
MaxRamSize = 32 * 1024 // 32GB
DefaultRamSize = 1 * 1024 // 1GB
MinRamSize = 32 // 32MB
MaxRamSize = 32 * 1024 // 32GB
MinNestedVirtualizationRamSize = 4 * 1024 // 4GB
LowRam = 256 // 256MB
@ -84,12 +85,14 @@ type Config struct {
// By default this is "packer-BUILDNAME", where "BUILDNAME" is the name of the build.
VMName string `mapstructure:"vm_name"`
BootCommand []string `mapstructure:"boot_command"`
SwitchName string `mapstructure:"switch_name"`
Cpu uint `mapstructure:"cpu"`
Generation uint `mapstructure:"generation"`
EnableSecureBoot bool `mapstructure:"enable_secure_boot"`
EnableVirtualizationExtensions bool `mapstructure:"enable_virtualization_extensions"`
BootCommand []string `mapstructure:"boot_command"`
SwitchName string `mapstructure:"switch_name"`
Cpu uint `mapstructure:"cpu"`
Generation uint `mapstructure:"generation"`
EnableMacSpoofing bool `mapstructure:"enable_mac_spoofing"`
EnableDynamicMemory bool `mapstructure:"enable_dynamic_memory"`
EnableSecureBoot bool `mapstructure:"enable_secure_boot"`
EnableVirtualizationExtensions bool `mapstructure:"enable_virtualization_extensions"`
Communicator string `mapstructure:"communicator"`
@ -227,6 +230,17 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
}
if b.config.EnableVirtualizationExtensions {
hasVirtualMachineVirtualizationExtensions, err := powershell.HasVirtualMachineVirtualizationExtensions()
if err != nil {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("Failed detecting virtual machine virtualization extensions support: %s", err))
} else {
if !hasVirtualMachineVirtualizationExtensions {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("This version of Hyper-V does not support virtual machine virtualization extension. Please use Windows 10 or Windows Server 2016 or newer."))
}
}
}
// Warnings
if b.config.ShutdownCommand == "" {
@ -240,6 +254,23 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
warnings = appendWarnings(warnings, warning)
}
if b.config.EnableVirtualizationExtensions {
if b.config.EnableDynamicMemory {
warning = fmt.Sprintf("For nested virtualization, when virtualization extension is enabled, dynamic memory should not be allowed.")
warnings = appendWarnings(warnings, warning)
}
if !b.config.EnableMacSpoofing {
warning = fmt.Sprintf("For nested virtualization, when virtualization extension is enabled, mac spoofing should be allowed.")
warnings = appendWarnings(warnings, warning)
}
if b.config.RamSizeMB < MinNestedVirtualizationRamSize {
warning = fmt.Sprintf("For nested virtualization, when virtualization extension is enabled, there should be 4GB or more memory set for the vm, otherwise Hyper-V may fail to start any nested VMs.")
warnings = appendWarnings(warnings, warning)
}
}
if errs != nil && len(errs.Errors) > 0 {
return warnings, errs
}
@ -292,13 +323,15 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
SwitchName: b.config.SwitchName,
},
&hypervcommon.StepCreateVM{
VMName: b.config.VMName,
SwitchName: b.config.SwitchName,
RamSizeMB: b.config.RamSizeMB,
DiskSize: b.config.DiskSize,
Generation: b.config.Generation,
Cpu: b.config.Cpu,
EnableSecureBoot: b.config.EnableSecureBoot,
VMName: b.config.VMName,
SwitchName: b.config.SwitchName,
RamSizeMB: b.config.RamSizeMB,
DiskSize: b.config.DiskSize,
Generation: b.config.Generation,
Cpu: b.config.Cpu,
EnableMacSpoofing: b.config.EnableMacSpoofing,
EnableDynamicMemory: b.config.EnableDynamicMemory,
EnableSecureBoot: b.config.EnableSecureBoot,
EnableVirtualizationExtensions: b.config.EnableVirtualizationExtensions,
},
&hypervcommon.StepEnableIntegrationService{},

@ -217,23 +217,67 @@ New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHD
}
}
func SetVirtualMachineCpu(vmName string, cpu uint, enableVirtualizationExtensions bool) error {
func SetVirtualMachineCpuCount(vmName string, cpu uint) error {
var script = `
param([string]$vmName, [int]$cpu, [string]$exposeVirtualizationExtensions)
$nested = [System.Boolean]::Parse($exposeVirtualizationExtensions)
Set-VMProcessor -VMName $vmName -Count $cpu -exposeVirtualizationExtensions $nested
param([string]$vmName, [int]$cpu)
Set-VMProcessor -VMName $vmName -Count $cpu
`
var ps powershell.PowerShellCmd
err := ps.Run(script, vmName, strconv.FormatInt(int64(cpu), 10))
return err
}
func SetVirtualMachineVirtualizationExtensions(vmName string, enableVirtualizationExtensions bool) error {
var script = `
param([string]$vmName, [string]$exposeVirtualizationExtensionsString)
$exposeVirtualizationExtensions = [System.Boolean]::Parse($exposeVirtualizationExtensionsString)
Set-VMProcessor -VMName $vmName -ExposeVirtualizationExtensions $exposeVirtualizationExtensions
`
exposeVirtualizationExtensionsString := "False"
if enableVirtualizationExtensions {
exposeVirtualizationExtensionsString = "True"
}
}
var ps powershell.PowerShellCmd
err := ps.Run(script, vmName, exposeVirtualizationExtensionsString)
return err
}
func SetVirtualMachineDynamicMemory(vmName string, enableDynamicMemory bool) error {
var script = `
param([string]$vmName, [string]$enableDynamicMemoryString)
$enableDynamicMemory = [System.Boolean]::Parse($enableDynamicMemoryString)
Set-VMMemory -VMName $vmName -DynamicMemoryEnabled $enableDynamicMemory
`
enableDynamicMemoryString := "False"
if enableDynamicMemory {
enableDynamicMemoryString = "True"
}
var ps powershell.PowerShellCmd
err := ps.Run(script, vmName, strconv.FormatInt(int64(cpu), 10), exposeVirtualizationExtensionsString)
err := ps.Run(script, vmName, enableDynamicMemoryString)
return err
}
func SetVirtualMachineMacSpoofing(vmName string, enableMacSpoofing bool) error {
var script = `
param([string]$vmName, $enableMacSpoofing)
Set-VMNetworkAdapter -VMName $vmName -MacAddressSpoofing $enableMacSpoofing
`
var ps powershell.PowerShellCmd
enableMacSpoofingString := "Off"
if enableMacSpoofing {
enableMacSpoofingString = "On"
}
err := ps.Run(script, vmName, enableMacSpoofingString)
return err
}
func SetSecureBoot(vmName string, enable bool) error {
func SetVirtualMachineSecureBoot(vmName string, enableSecureBoot bool) error {
var script = `
param([string]$vmName, $enableSecureBoot)
Set-VMFirmware -VMName $vmName -EnableSecureBoot $enableSecureBoot
@ -241,12 +285,12 @@ Set-VMFirmware -VMName $vmName -EnableSecureBoot $enableSecureBoot
var ps powershell.PowerShellCmd
enableSecureBoot := "Off"
if enable {
enableSecureBoot = "On"
enableSecureBootString := "Off"
if enableSecureBoot {
enableSecureBootString = "On"
}
err := ps.Run(script, vmName, enableSecureBoot)
err := ps.Run(script, vmName, enableSecureBootString)
return err
}

@ -231,6 +231,23 @@ param([string]$moduleName)
return true, nil
}
func HasVirtualMachineVirtualizationExtensions() (bool, error) {
var script = `
(GET-Command Set-VMProcessor).parameters.keys -contains "ExposeVirtualizationExtensions"
`
var ps PowerShellCmd
cmdOut, err := ps.Output(script)
if err != nil {
return false, err
}
var hasVirtualMachineVirtualizationExtensions = strings.TrimSpace(cmdOut) == "True"
return hasVirtualMachineVirtualizationExtensions, err
}
func SetUnattendedProductKey(path string, productKey string) error {
var script = `

Loading…
Cancel
Save