Skip to content

Commit

Permalink
Add use_fixed_vhd_format Hyper-V ISO option
Browse files Browse the repository at this point in the history
  • Loading branch information
adarobin committed Apr 10, 2018
1 parent bc5cf25 commit b33d5f1
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 11 deletions.
2 changes: 1 addition & 1 deletion builder/hyperv/common/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ type Driver interface {

DeleteVirtualSwitch(string) error

CreateVirtualMachine(string, string, string, string, int64, int64, string, uint, bool) error
CreateVirtualMachine(string, string, string, string, int64, int64, string, uint, bool, bool) error

AddVirtualMachineHardDrive(string, string, string, int64, string) error

Expand Down
4 changes: 3 additions & 1 deletion builder/hyperv/common/driver_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ type DriverMock struct {
CreateVirtualMachine_SwitchName string
CreateVirtualMachine_Generation uint
CreateVirtualMachine_DifferentialDisk bool
CreateVirtualMachine_FixedVHD bool
CreateVirtualMachine_Err error

CloneVirtualMachine_Called bool
Expand Down Expand Up @@ -387,7 +388,7 @@ func (d *DriverMock) AddVirtualMachineHardDrive(vmName string, vhdFile string, v
return d.AddVirtualMachineHardDrive_Err
}

func (d *DriverMock) CreateVirtualMachine(vmName string, path string, harddrivePath string, vhdPath string, ram int64, diskSize int64, switchName string, generation uint, diffDisks bool) error {
func (d *DriverMock) CreateVirtualMachine(vmName string, path string, harddrivePath string, vhdPath string, ram int64, diskSize int64, switchName string, generation uint, diffDisks bool, fixedVHD bool) error {
d.CreateVirtualMachine_Called = true
d.CreateVirtualMachine_VmName = vmName
d.CreateVirtualMachine_Path = path
Expand All @@ -398,6 +399,7 @@ func (d *DriverMock) CreateVirtualMachine(vmName string, path string, harddriveP
d.CreateVirtualMachine_SwitchName = switchName
d.CreateVirtualMachine_Generation = generation
d.CreateVirtualMachine_DifferentialDisk = diffDisks
d.CreateVirtualMachine_FixedVHD = fixedVHD
return d.CreateVirtualMachine_Err
}

Expand Down
4 changes: 2 additions & 2 deletions builder/hyperv/common/driver_ps_4.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ func (d *HypervPS4Driver) AddVirtualMachineHardDrive(vmName string, vhdFile stri
return hyperv.AddVirtualMachineHardDiskDrive(vmName, vhdFile, vhdName, vhdSizeBytes, controllerType)
}

func (d *HypervPS4Driver) CreateVirtualMachine(vmName string, path string, harddrivePath string, vhdPath string, ram int64, diskSize int64, switchName string, generation uint, diffDisks bool) error {
return hyperv.CreateVirtualMachine(vmName, path, harddrivePath, vhdPath, ram, diskSize, switchName, generation, diffDisks)
func (d *HypervPS4Driver) CreateVirtualMachine(vmName string, path string, harddrivePath string, vhdPath string, ram int64, diskSize int64, switchName string, generation uint, diffDisks bool, fixedVHD bool) error {
return hyperv.CreateVirtualMachine(vmName, path, harddrivePath, vhdPath, ram, diskSize, switchName, generation, diffDisks, fixedVHD)
}

func (d *HypervPS4Driver) CloneVirtualMachine(cloneFromVmxcPath string, cloneFromVmName string, cloneFromSnapshotName string, cloneAllSnapshots bool, vmName string, path string, harddrivePath string, ram int64, switchName string) error {
Expand Down
3 changes: 2 additions & 1 deletion builder/hyperv/common/step_create_vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type StepCreateVM struct {
MacAddress string
SkipExport bool
OutputDir string
FixedVHD bool
}

func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
Expand Down Expand Up @@ -65,7 +66,7 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste
ramSize := int64(s.RamSize * 1024 * 1024)
diskSize := int64(s.DiskSize * 1024 * 1024)

err := driver.CreateVirtualMachine(s.VMName, path, harddrivePath, vhdPath, ramSize, diskSize, s.SwitchName, s.Generation, s.DifferencingDisk)
err := driver.CreateVirtualMachine(s.VMName, path, harddrivePath, vhdPath, ramSize, diskSize, s.SwitchName, s.Generation, s.DifferencingDisk, s.FixedVHD)
if err != nil {
err := fmt.Errorf("Error creating virtual machine: %s", err)
state.Put("error", err)
Expand Down
24 changes: 23 additions & 1 deletion builder/hyperv/iso/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
DefaultDiskSize = 40 * 1024 // ~40GB
MinDiskSize = 256 // 256MB
MaxDiskSize = 64 * 1024 * 1024 // 64TB
MaxVHDSize = 2040 * 1024 // 2040GB

DefaultRamSize = 1 * 1024 // 1GB
MinRamSize = 32 // 32MB
Expand Down Expand Up @@ -100,6 +101,9 @@ type Config struct {
// Use differencing disk
DifferencingDisk bool `mapstructure:"differencing_disk"`

// Create the VM with a Fixed VHD format disk instead of Dynamic VHDX
FixedVHD bool `mapstructure:"use_fixed_vhd_format"`

ctx interpolate.Context
}

Expand Down Expand Up @@ -255,6 +259,21 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
}

if b.config.Generation > 1 && b.config.FixedVHD {
err = errors.New("Fixed VHD disks are only supported on Generation 1 virtual machines.")
errs = packer.MultiErrorAppend(errs, err)
}

if !b.config.SkipCompaction && b.config.FixedVHD {
err = errors.New("Fixed VHD disks do not support compaction.")
errs = packer.MultiErrorAppend(errs, err)
}

if b.config.DifferencingDisk && b.config.FixedVHD {
err = errors.New("Fixed VHD disks are not supported with differencing disks.")
errs = packer.MultiErrorAppend(errs, err)
}

// Warnings

if b.config.ShutdownCommand == "" {
Expand Down Expand Up @@ -362,6 +381,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
DifferencingDisk: b.config.DifferencingDisk,
SkipExport: b.config.SkipExport,
OutputDir: b.config.OutputDir,
FixedVHD: b.config.FixedVHD,
},
&hypervcommon.StepEnableIntegrationService{},

Expand Down Expand Up @@ -485,8 +505,10 @@ func (b *Builder) checkDiskSize() error {

if b.config.DiskSize < MinDiskSize {
return fmt.Errorf("disk_size: Virtual machine requires disk space >= %v GB, but defined: %v", MinDiskSize, b.config.DiskSize/1024)
} else if b.config.DiskSize > MaxDiskSize {
} else if b.config.DiskSize > MaxDiskSize && !b.config.FixedVHD {
return fmt.Errorf("disk_size: Virtual machine requires disk space <= %v GB, but defined: %v", MaxDiskSize, b.config.DiskSize/1024)
} else if b.config.DiskSize > MaxVHDSize && b.config.FixedVHD {
return fmt.Errorf("disk_size: Virtual machine requires disk space <= %v GB, but defined: %v", MaxVHDSize/1024, b.config.DiskSize/1024)
}

return nil
Expand Down
53 changes: 53 additions & 0 deletions builder/hyperv/iso/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,59 @@ func TestBuilderPrepare_DiskSize(t *testing.T) {
}
}

func TestBuilderPrepare_FixedVHDFormat(t *testing.T) {
var b Builder
config := testConfig()
config["use_fixed_vhd_format"] = true
config["generation"] = 1
config["skip_compaction"] = true
config["differencing_disk"] = false

//use_fixed_vhd_format should work with generation = 1, skip_compaction = true, and differencing_disk = false
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad err: %s", err)
}

//use_fixed_vhd_format should not work with differencing_disk = true
config["differencing_disk"] = true
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
config["differencing_disk"] = false

//use_fixed_vhd_format should not work with skip_compaction = false
config["skip_compaction"] = false
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
config["skip_compaction"] = true

//use_fixed_vhd_format should not work with generation = 2
config["generation"] = 2
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
}

func TestBuilderPrepare_FloppyFiles(t *testing.T) {
var b Builder
config := testConfig()
Expand Down
21 changes: 16 additions & 5 deletions common/powershell/hyperv/hyperv.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Hyper-V\Set-VMFloppyDiskDrive -VMName $vmName -Path $null
return err
}

func CreateVirtualMachine(vmName string, path string, harddrivePath string, vhdRoot string, ram int64, diskSize int64, switchName string, generation uint, diffDisks bool) error {
func CreateVirtualMachine(vmName string, path string, harddrivePath string, vhdRoot string, ram int64, diskSize int64, switchName string, generation uint, diffDisks bool, fixedVHD bool) error {

if generation == 2 {
var script = `
Expand All @@ -213,8 +213,13 @@ if ($harddrivePath){
return DisableAutomaticCheckpoints(vmName)
} else {
var script = `
param([string]$vmName, [string]$path, [string]$harddrivePath, [string]$vhdRoot, [long]$memoryStartupBytes, [long]$newVHDSizeBytes, [string]$switchName, [string]$diffDisks)
$vhdx = $vmName + '.vhdx'
param([string]$vmName, [string]$path, [string]$harddrivePath, [string]$vhdRoot, [long]$memoryStartupBytes, [long]$newVHDSizeBytes, [string]$switchName, [string]$diffDisks, [string]$fixedVHD)
if($fixedVHD -eq "true"){
$vhdx = $vmName + '.vhd'
}
else{
$vhdx = $vmName + '.vhdx'
}
$vhdPath = Join-Path -Path $vhdRoot -ChildPath $vhdx
if ($harddrivePath){
if($diffDisks -eq "true"){
Expand All @@ -225,11 +230,17 @@ if ($harddrivePath){
}
Hyper-V\New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -VHDPath $vhdPath -SwitchName $switchName
} else {
Hyper-V\New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHDPath $vhdPath -NewVHDSizeBytes $newVHDSizeBytes -SwitchName $switchName
if($fixedVHD -eq "true"){
New-VHD -Path $vhdPath -Fixed -SizeBytes $newVHDSizeBytes
Hyper-V\New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -VHDPath $vhdPath -SwitchName $switchName
}
else{
Hyper-V\New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHDPath $vhdPath -NewVHDSizeBytes $newVHDSizeBytes -SwitchName $switchName
}
}
`
var ps powershell.PowerShellCmd
if err := ps.Run(script, vmName, path, harddrivePath, vhdRoot, strconv.FormatInt(ram, 10), strconv.FormatInt(diskSize, 10), switchName, strconv.FormatBool(diffDisks)); err != nil {
if err := ps.Run(script, vmName, path, harddrivePath, vhdRoot, strconv.FormatInt(ram, 10), strconv.FormatInt(diskSize, 10), switchName, strconv.FormatBool(diffDisks), strconv.FormatBool(fixedVHD)); err != nil {
return err
}

Expand Down
6 changes: 6 additions & 0 deletions website/source/docs/builders/hyperv-iso.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ 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`.

- `use_fixed_vhd_format` (boolean) - If true, creates the boot disk on the virtual machine as
a fixed VHD format disk. The default is false, which creates a dynamic VHDX format disk. This
option requires setting `generation` to 1, `skip_compaction` to true, and `differencing_disk` to false.
The most likely use case for this option is outputing a disk that is in the format required
for upload to Azure.

- `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
Expand Down

0 comments on commit b33d5f1

Please sign in to comment.