diff --git a/builder/hyperv/common/driver.go b/builder/hyperv/common/driver.go index 571214acd..e7b58464e 100644 --- a/builder/hyperv/common/driver.go +++ b/builder/hyperv/common/driver.go @@ -66,9 +66,9 @@ type Driver interface { DeleteVirtualSwitch(string) error - CreateVirtualMachine(string, string, string, string, int64, int64, string, uint, bool) error + CreateVirtualMachine(string, string, string, string, int64, int64, int64, string, uint, bool) error - AddVirtualMachineHardDrive(string, string, string, int64, string) error + AddVirtualMachineHardDrive(string, string, string, int64, int64, string) error CloneVirtualMachine(string, string, string, bool, string, string, string, int64, string) error diff --git a/builder/hyperv/common/driver_mock.go b/builder/hyperv/common/driver_mock.go index 7d8e02c6a..8af637e66 100644 --- a/builder/hyperv/common/driver_mock.go +++ b/builder/hyperv/common/driver_mock.go @@ -112,6 +112,7 @@ type DriverMock struct { AddVirtualMachineHardDrive_VhdFile string AddVirtualMachineHardDrive_VhdName string AddVirtualMachineHardDrive_VhdSizeBytes int64 + AddVirtualMachineHardDrive_VhdBlockSize int64 AddVirtualMachineHardDrive_ControllerType string AddVirtualMachineHardDrive_Err error @@ -122,6 +123,7 @@ type DriverMock struct { CreateVirtualMachine_VhdPath string CreateVirtualMachine_Ram int64 CreateVirtualMachine_DiskSize int64 + CreateVirtualMachine_DiskBlockSize int64 CreateVirtualMachine_SwitchName string CreateVirtualMachine_Generation uint CreateVirtualMachine_DifferentialDisk bool @@ -377,17 +379,18 @@ func (d *DriverMock) CreateVirtualSwitch(switchName string, switchType string) ( return d.CreateVirtualSwitch_Return, d.CreateVirtualSwitch_Err } -func (d *DriverMock) AddVirtualMachineHardDrive(vmName string, vhdFile string, vhdName string, vhdSizeBytes int64, controllerType string) error { +func (d *DriverMock) AddVirtualMachineHardDrive(vmName string, vhdFile string, vhdName string, vhdSizeBytes int64, vhdDiskBlockSize int64, controllerType string) error { d.AddVirtualMachineHardDrive_Called = true d.AddVirtualMachineHardDrive_VmName = vmName d.AddVirtualMachineHardDrive_VhdFile = vhdFile d.AddVirtualMachineHardDrive_VhdName = vhdName d.AddVirtualMachineHardDrive_VhdSizeBytes = vhdSizeBytes + d.AddVirtualMachineHardDrive_VhdSizeBytes = vhdDiskBlockSize d.AddVirtualMachineHardDrive_ControllerType = controllerType 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, diskBlockSize int64, switchName string, generation uint, diffDisks bool) error { d.CreateVirtualMachine_Called = true d.CreateVirtualMachine_VmName = vmName d.CreateVirtualMachine_Path = path @@ -395,6 +398,7 @@ func (d *DriverMock) CreateVirtualMachine(vmName string, path string, harddriveP d.CreateVirtualMachine_VhdPath = vhdPath d.CreateVirtualMachine_Ram = ram d.CreateVirtualMachine_DiskSize = diskSize + d.CreateVirtualMachine_DiskBlockSize = diskBlockSize d.CreateVirtualMachine_SwitchName = switchName d.CreateVirtualMachine_Generation = generation d.CreateVirtualMachine_DifferentialDisk = diffDisks diff --git a/builder/hyperv/common/driver_ps_4.go b/builder/hyperv/common/driver_ps_4.go index a6c1b7352..34a9edbb5 100644 --- a/builder/hyperv/common/driver_ps_4.go +++ b/builder/hyperv/common/driver_ps_4.go @@ -174,12 +174,12 @@ func (d *HypervPS4Driver) CreateVirtualSwitch(switchName string, switchType stri return hyperv.CreateVirtualSwitch(switchName, switchType) } -func (d *HypervPS4Driver) AddVirtualMachineHardDrive(vmName string, vhdFile string, vhdName string, vhdSizeBytes int64, controllerType string) error { - return hyperv.AddVirtualMachineHardDiskDrive(vmName, vhdFile, vhdName, vhdSizeBytes, controllerType) +func (d *HypervPS4Driver) AddVirtualMachineHardDrive(vmName string, vhdFile string, vhdName string, vhdSizeBytes int64, diskBlockSize int64, controllerType string) error { + return hyperv.AddVirtualMachineHardDiskDrive(vmName, vhdFile, vhdName, vhdSizeBytes, diskBlockSize, 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, diskBlockSize int64, switchName string, generation uint, diffDisks bool) error { + return hyperv.CreateVirtualMachine(vmName, path, harddrivePath, vhdPath, ram, diskSize, diskBlockSize, switchName, generation, diffDisks) } func (d *HypervPS4Driver) CloneVirtualMachine(cloneFromVmxcPath string, cloneFromVmName string, cloneFromSnapshotName string, cloneAllSnapshots bool, vmName string, path string, harddrivePath string, ram int64, switchName string) error { diff --git a/builder/hyperv/common/step_create_vm.go b/builder/hyperv/common/step_create_vm.go index f046d1a48..f8125ed91 100644 --- a/builder/hyperv/common/step_create_vm.go +++ b/builder/hyperv/common/step_create_vm.go @@ -21,6 +21,7 @@ type StepCreateVM struct { HarddrivePath string RamSize uint DiskSize uint + DiskBlockSize uint Generation uint Cpu uint EnableMacSpoofing bool @@ -64,8 +65,9 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste // convert the MB to bytes ramSize := int64(s.RamSize * 1024 * 1024) diskSize := int64(s.DiskSize * 1024 * 1024) + diskBlockSize := int64(s.DiskBlockSize * 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, diskBlockSize, s.SwitchName, s.Generation, s.DifferencingDisk) if err != nil { err := fmt.Errorf("Error creating virtual machine: %s", err) state.Put("error", err) @@ -124,7 +126,7 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste for index, size := range s.AdditionalDiskSize { diskSize := int64(size * 1024 * 1024) diskFile := fmt.Sprintf("%s-%d.vhdx", s.VMName, index) - err = driver.AddVirtualMachineHardDrive(s.VMName, vhdPath, diskFile, diskSize, "SCSI") + err = driver.AddVirtualMachineHardDrive(s.VMName, vhdPath, diskFile, diskSize, diskBlockSize, "SCSI") if err != nil { err := fmt.Errorf("Error creating and attaching additional disk drive: %s", err) state.Put("error", err) @@ -163,4 +165,6 @@ func (s *StepCreateVM) Cleanup(state multistep.StateBag) { if err != nil { ui.Error(fmt.Sprintf("Error deleting virtual machine: %s", err)) } + + // TODO: Clean up created VHDX } diff --git a/builder/hyperv/iso/builder.go b/builder/hyperv/iso/builder.go index b92e779df..a95814630 100644 --- a/builder/hyperv/iso/builder.go +++ b/builder/hyperv/iso/builder.go @@ -24,6 +24,10 @@ const ( MinDiskSize = 256 // 256MB MaxDiskSize = 64 * 1024 * 1024 // 64TB + DefaultDiskBlockSize = 32 // 32MB + MinDiskBlockSize = 1 // 1MB + MaxDiskBlockSize = 256 // 256MB + DefaultRamSize = 1 * 1024 // 1GB MinRamSize = 32 // 32MB MaxRamSize = 32 * 1024 // 32GB @@ -55,9 +59,15 @@ type Config struct { // The size, in megabytes, of the hard disk to create for the VM. // By default, this is 130048 (about 127 GB). DiskSize uint `mapstructure:"disk_size"` + + // The size, in megabytes, of the block size used to create the hard disk. + // By default, this is 32768 (about 32 MB) + DiskBlockSize uint `mapstructure:"disk_block_size"` + // The size, in megabytes, of the computer memory in the VM. // By default, this is 1024 (about 1 GB). RamSize uint `mapstructure:"ram_size"` + // SecondaryDvdImages []string `mapstructure:"secondary_iso_images"` @@ -141,6 +151,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } } + err = b.checkDiskBlockSize() + if err != nil { + errs = packer.MultiErrorAppend(errs, err) + } + err = b.checkRamSize() if err != nil { errs = packer.MultiErrorAppend(errs, err) @@ -352,6 +367,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SwitchName: b.config.SwitchName, RamSize: b.config.RamSize, DiskSize: b.config.DiskSize, + DiskBlockSize: b.config.DiskBlockSize, Generation: b.config.Generation, Cpu: b.config.Cpu, EnableMacSpoofing: b.config.EnableMacSpoofing, @@ -492,6 +508,22 @@ func (b *Builder) checkDiskSize() error { return nil } +func (b *Builder) checkDiskBlockSize() error { + if b.config.DiskBlockSize == 0 { + b.config.DiskBlockSize = DefaultDiskBlockSize + } + + log.Println(fmt.Sprintf("%s: %v", "DiskBlockSize", b.config.DiskBlockSize)) + + if b.config.DiskBlockSize < MinDiskBlockSize { + return fmt.Errorf("disk_block_size: Virtual machine requires disk block size >= %v MB, but defined: %v", MinDiskBlockSize, b.config.DiskBlockSize) + } else if b.config.DiskBlockSize > MaxDiskBlockSize { + return fmt.Errorf("disk_block_size: Virtual machine requires disk block size <= %v MB, but defined: %v", MaxDiskBlockSize, b.config.DiskBlockSize) + } + + return nil +} + func (b *Builder) checkRamSize() error { if b.config.RamSize == 0 { b.config.RamSize = DefaultRamSize diff --git a/builder/hyperv/iso/builder_test.go b/builder/hyperv/iso/builder_test.go index b08a683f9..8523876ef 100644 --- a/builder/hyperv/iso/builder_test.go +++ b/builder/hyperv/iso/builder_test.go @@ -23,6 +23,7 @@ func testConfig() map[string]interface{} { "ssh_username": "foo", "ram_size": 64, "disk_size": 256, + "disk_block_size": 1, "guest_additions_mode": "none", "disk_additional_size": "50000,40000,30000", packer.BuildNameConfigKey: "foo", @@ -86,6 +87,58 @@ func TestBuilderPrepare_DiskSize(t *testing.T) { } } +func TestBuilderPrepare_DiskBlockSize(t *testing.T) { + var b Builder + config := testConfig() + expected_default_block_size := uint(32) + expected_min_block_size := uint(0) + expected_max_block_size := uint(256) + + // Test default with empty disk_block_size + delete(config, "disk_block_size") + warns, err := b.Prepare(config) + if len(warns) > 0 { + t.Fatalf("bad: %#v", warns) + } + if err != nil { + t.Fatalf("bad err: %s", err) + } + if b.config.DiskBlockSize != expected_default_block_size { + t.Fatalf("bad default block size with empty config: %d. Expected %d", b.config.DiskBlockSize, expected_default_block_size) + } + + test_sizes := []uint{0, 1, 32, 256, 512, 1 * 1024, 32 * 1024} + for _, test_size := range test_sizes { + config["disk_block_size"] = test_size + b = Builder{} + warns, err = b.Prepare(config) + if test_size > expected_max_block_size || test_size < expected_min_block_size { + if len(warns) > 0 { + t.Fatalf("bad, should have no warns: %#v", warns) + } + if err == nil { + t.Fatalf("bad, should have error but didn't. disk_block_size=%d outside expected valid range [%d,%d]", test_size, expected_min_block_size, expected_max_block_size) + } + } else { + if len(warns) > 0 { + t.Fatalf("bad: %#v", warns) + } + if err != nil { + t.Fatalf("bad, should not have error: %s", err) + } + if test_size == 0 { + if b.config.DiskBlockSize != expected_default_block_size { + t.Fatalf("bad default block size with 0 value config: %d. Expected: %d", b.config.DiskBlockSize, expected_default_block_size) + } + } else { + if b.config.DiskBlockSize != test_size { + t.Fatalf("bad block size with 0 value config: %d. Expected: %d", b.config.DiskBlockSize, expected_default_block_size) + } + } + } + } +} + func TestBuilderPrepare_FloppyFiles(t *testing.T) { var b Builder config := testConfig() diff --git a/common/powershell/hyperv/hyperv.go b/common/powershell/hyperv/hyperv.go index d26ec5eeb..0a296cce2 100644 --- a/common/powershell/hyperv/hyperv.go +++ b/common/powershell/hyperv/hyperv.go @@ -53,6 +53,22 @@ $ip return cmdOut, err } +//func CreateVirtualHardDiskDrive(vmName string, diskPath string, diskSize int64, diskBlockSize int64, generation uint) (uint, uint, error) { +// +// var script = ` +//param([string]$vmName, [string]$path, +// +// +//[long]$memoryStartupBytes, [long]$newVHDSizeBytes, [string]$switchName, [int]$generation) +//$vhdx = $vmName + '.vhdx' +//$vhdPath = Join-Path -Path $path -ChildPath $vhdx +//New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHDPath $vhdPath -NewVHDSizeBytes $newVHDSizeBytes -SwitchName $switchName -Generation $generation +//` +// var ps powershell.PowerShellCmd +// err := ps.Run(script, vmName, path, strconv.FormatInt(ram, 10), strconv.FormatInt(diskSize, 10), switchName, strconv.FormatInt(int64(generation), 10)) +// return err +//} + func CreateDvdDrive(vmName string, isoPath string, generation uint) (uint, uint, error) { var ps powershell.PowerShellCmd var script string @@ -187,45 +203,47 @@ 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, diskBlockSize int64, switchName string, generation uint, diffDisks bool) error { if generation == 2 { var script = ` -param([string]$vmName, [string]$path, [string]$harddrivePath, [string]$vhdRoot, [long]$memoryStartupBytes, [long]$newVHDSizeBytes, [string]$switchName, [int]$generation, [string]$diffDisks) +param([string]$vmName, [string]$path, [string]$harddrivePath, [string]$vhdRoot, [long]$memoryStartupBytes, [long]$newVHDSizeBytes, [long]$vhdBlockSizeBytes, [string]$switchName, [int]$generation, [string]$diffDisks) $vhdx = $vmName + '.vhdx' $vhdPath = Join-Path -Path $vhdRoot -ChildPath $vhdx if ($harddrivePath){ if($diffDisks -eq "true"){ - New-VHD -Path $vhdPath -ParentPath $harddrivePath -Differencing + New-VHD -Path $vhdPath -ParentPath $harddrivePath -Differencing -BlockSizeBytes $vhdBlockSizeBytes } else { Copy-Item -Path $harddrivePath -Destination $vhdPath } New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -VHDPath $vhdPath -SwitchName $switchName -Generation $generation } else { - New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHDPath $vhdPath -NewVHDSizeBytes $newVHDSizeBytes -SwitchName $switchName -Generation $generation + New-VHD -Path $vhdPath -SizeBytes $newVHDSizeBytes -BlockSizeBytes $vhdBlockSizeBytes + New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -VHDPath $vhdPath -SwitchName $switchName -Generation $generation } ` var ps powershell.PowerShellCmd - if err := ps.Run(script, vmName, path, harddrivePath, vhdRoot, strconv.FormatInt(ram, 10), strconv.FormatInt(diskSize, 10), switchName, strconv.FormatInt(int64(generation), 10), strconv.FormatBool(diffDisks)); err != nil { + if err := ps.Run(script, vmName, path, harddrivePath, vhdRoot, strconv.FormatInt(ram, 10), strconv.FormatInt(diskSize, 10), strconv.FormatInt(diskBlockSize, 10), switchName, strconv.FormatInt(int64(generation), 10), strconv.FormatBool(diffDisks)); err != nil { return err } return DisableAutomaticCheckpoints(vmName) } else { var script = ` -param([string]$vmName, [string]$path, [string]$harddrivePath, [string]$vhdRoot, [long]$memoryStartupBytes, [long]$newVHDSizeBytes, [string]$switchName, [string]$diffDisks) +param([string]$vmName, [string]$path, [string]$harddrivePath, [string]$vhdRoot, [long]$memoryStartupBytes, [long]$newVHDSizeBytes, [long]$vhdBlockSizeBytes, [string]$switchName, [string]$diffDisks) $vhdx = $vmName + '.vhdx' $vhdPath = Join-Path -Path $vhdRoot -ChildPath $vhdx if ($harddrivePath){ if($diffDisks -eq "true"){ - New-VHD -Path $vhdPath -ParentPath $harddrivePath -Differencing + New-VHD -Path $vhdPath -ParentPath $harddrivePath -Differencing -BlockSizeBytes $vhdBlockSizeBytes } else{ Copy-Item -Path $harddrivePath -Destination $vhdPath } New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -VHDPath $vhdPath -SwitchName $switchName } else { - New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHDPath $vhdPath -NewVHDSizeBytes $newVHDSizeBytes -SwitchName $switchName + New-VHD -Path $vhdPath -SizeBytes $newVHDSizeBytes -BlockSizeBytes $vhdBlockSizeBytes + New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -VHDPath $vhdPath -SwitchName $switchName } ` var ps powershell.PowerShellCmd @@ -872,16 +890,16 @@ Get-VMNetworkAdapter -VMName $vmName | Connect-VMNetworkAdapter -SwitchName $swi return err } -func AddVirtualMachineHardDiskDrive(vmName string, vhdRoot string, vhdName string, vhdSizeBytes int64, controllerType string) error { +func AddVirtualMachineHardDiskDrive(vmName string, vhdRoot string, vhdName string, vhdSizeBytes int64, vhdBlockSize int64, controllerType string) error { var script = ` -param([string]$vmName,[string]$vhdRoot, [string]$vhdName, [string]$vhdSizeInBytes, [string]$controllerType) +param([string]$vmName,[string]$vhdRoot, [string]$vhdName, [string]$vhdSizeInBytes,[string]$vhdBlockSizeInBize [string]$controllerType) $vhdPath = Join-Path -Path $vhdRoot -ChildPath $vhdName -New-VHD $vhdPath -SizeBytes $vhdSizeInBytes +New-VHD -path $vhdPath -SizeBytes $vhdSizeInBytes -BlockSizeBytes $vhdBlockSizeInBize Add-VMHardDiskDrive -VMName $vmName -path $vhdPath -controllerType $controllerType ` var ps powershell.PowerShellCmd - err := ps.Run(script, vmName, vhdRoot, vhdName, strconv.FormatInt(vhdSizeBytes, 10), controllerType) + err := ps.Run(script, vmName, vhdRoot, vhdName, strconv.FormatInt(vhdSizeBytes, 10), strconv.FormatInt(vhdBlockSize, 10), controllerType) return err }