diff --git a/builder/hyperv/common/driver.go b/builder/hyperv/common/driver.go index ba9ab5c4c..3e44b0ece 100644 --- a/builder/hyperv/common/driver.go +++ b/builder/hyperv/common/driver.go @@ -66,6 +66,8 @@ type Driver interface { CreateVirtualMachine(string, string, string, string, int64, int64, string, uint) error + AddVirtualMachineHardDrive(string, string, string, int64, string) error + CloneVirtualMachine(string, string, string, bool, string, string, string, int64, string) error DeleteVirtualMachine(string) error diff --git a/builder/hyperv/common/driver_ps_4.go b/builder/hyperv/common/driver_ps_4.go index c836137d2..c06294d49 100644 --- a/builder/hyperv/common/driver_ps_4.go +++ b/builder/hyperv/common/driver_ps_4.go @@ -170,6 +170,10 @@ 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) CreateVirtualMachine(vmName string, path string, harddrivePath string, vhdPath string, ram int64, diskSize int64, switchName string, generation uint) error { return hyperv.CreateVirtualMachine(vmName, path, harddrivePath, vhdPath, ram, diskSize, switchName, generation) } diff --git a/builder/hyperv/common/step_create_vm.go b/builder/hyperv/common/step_create_vm.go index d88de5558..a244a9f5e 100644 --- a/builder/hyperv/common/step_create_vm.go +++ b/builder/hyperv/common/step_create_vm.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "path/filepath" + "strconv" "strings" "github.com/hashicorp/packer/packer" @@ -26,6 +27,7 @@ type StepCreateVM struct { EnableDynamicMemory bool EnableSecureBoot bool EnableVirtualizationExtensions bool + AdditionalDiskSize []uint } func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction { @@ -108,6 +110,19 @@ func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction { } } + if len(s.AdditionalDiskSize) > 0 { + for index, size := range s.AdditionalDiskSize { + var diskSize = size * 1024 * 1024 + err = driver.AddVirtualMachineHardDrive(s.VMName, vhdPath, s.VMName+"-"+strconv.Itoa(int(index))+".vhdx", int64(diskSize), "SCSI") + if err != nil { + err := fmt.Errorf("Error creating and attaching additional disk drive: %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 2cd786a42..b3c1e1f61 100644 --- a/builder/hyperv/iso/builder.go +++ b/builder/hyperv/iso/builder.go @@ -90,6 +90,8 @@ type Config struct { Communicator string `mapstructure:"communicator"` + AdditionalDiskSize []uint `mapstructure:"disk_additional_size"` + SkipCompaction bool `mapstructure:"skip_compaction"` ctx interpolate.Context @@ -163,6 +165,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } } + if len(b.config.AdditionalDiskSize) > 64 { + err = errors.New("VM's currently support a maximun of 64 additional SCSI attached disks.") + errs = packer.MultiErrorAppend(errs, err) + } + log.Println(fmt.Sprintf("Using switch %s", b.config.SwitchName)) log.Println(fmt.Sprintf("%s: %v", "SwitchName", b.config.SwitchName)) @@ -345,6 +352,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, + AdditionalDiskSize: b.config.AdditionalDiskSize, }, &hypervcommon.StepEnableIntegrationService{}, diff --git a/builder/hyperv/iso/builder_test.go b/builder/hyperv/iso/builder_test.go index 3fc17a8b7..73ae5591b 100644 --- a/builder/hyperv/iso/builder_test.go +++ b/builder/hyperv/iso/builder_test.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "reflect" + "strconv" "testing" "github.com/hashicorp/packer/packer" @@ -18,6 +19,7 @@ func testConfig() map[string]interface{} { "ram_size": 64, "disk_size": 256, "guest_additions_mode": "none", + "disk_additional_size": "50000,40000,30000", packer.BuildNameConfigKey: "foo", } } @@ -391,6 +393,27 @@ func TestBuilderPrepare_SizeIsRequiredWhenNotUsingExistingHarddrive(t *testing.T } } +func TestBuilderPrepare_MaximumOfSixtyFourAdditionalDisks(t *testing.T) { + var b Builder + config := testConfig() + + disks := make([]string, 65) + for i := range disks { + disks[i] = strconv.Itoa(i) + } + config["disk_additional_size"] = disks + + b = Builder{} + warns, err := b.Prepare(config) + if len(warns) > 0 { + t.Fatalf("bad: %#v", warns) + } + if err == nil { + t.Errorf("should have error") + } + +} + func TestBuilderPrepare_CommConfig(t *testing.T) { // Test Winrm { @@ -447,4 +470,5 @@ func TestBuilderPrepare_CommConfig(t *testing.T) { t.Errorf("bad host: %s", host) } } + } diff --git a/common/powershell/hyperv/hyperv.go b/common/powershell/hyperv/hyperv.go index 0c649c450..d15ee0748 100644 --- a/common/powershell/hyperv/hyperv.go +++ b/common/powershell/hyperv/hyperv.go @@ -855,6 +855,19 @@ Get-VMNetworkAdapter -VMName $vmName | Connect-VMNetworkAdapter -SwitchName $swi return err } +func AddVirtualMachineHardDiskDrive(vmName string, vhdRoot string, vhdName string, vhdSizeBytes int64, controllerType string) error { + + var script = ` +param([string]$vmName,[string]$vhdRoot, [string]$vhdName, [string]$vhdSizeInBytes, [string]$controllerType) +$vhdPath = Join-Path -Path $vhdRoot -ChildPath $vhdName +New-VHD $vhdPath -SizeBytes $vhdSizeInBytes +Add-VMHardDiskDrive -VMName $vmName -path $vhdPath -controllerType $controllerType +` + var ps powershell.PowerShellCmd + err := ps.Run(script, vmName, vhdRoot, vhdName, strconv.FormatInt(vhdSizeBytes, 10), controllerType) + return err +} + func UntagVirtualMachineNetworkAdapterVlan(vmName string, switchName string) error { var script = ` diff --git a/website/source/docs/builders/hyperv-iso.html.md b/website/source/docs/builders/hyperv-iso.html.md index be66cd0e2..b5b6a3826 100644 --- a/website/source/docs/builders/hyperv-iso.html.md +++ b/website/source/docs/builders/hyperv-iso.html.md @@ -88,6 +88,12 @@ can be configured for this builder. - `cpu` (number) - The number of cpus the virtual machine should use. If this isn't specified, the default is 1 cpu. +- `disk_additional_size` (array of integers) - The size(s) of any additional + hard disks for the VM in megabytes. If this is not specified then the VM + will only contain a primary hard disk. Additional drives will be attached to the SCSI + interface only. The builder uses expandable, not fixed-size virtual hard disks, + so the actual file representing the disk will not use the full size unless it is full. + - `disk_size` (number) - The size, in megabytes, of the hard disk to create for the VM. By default, this is 40 GB.