From d7230827cde056774bd089c5014cb772c42ffd0f Mon Sep 17 00:00:00 2001 From: Joshua Foster Date: Fri, 21 Feb 2020 10:47:46 -0500 Subject: [PATCH 1/2] (vsphere-iso) add ability to define multiple disks Closes #8749 --- builder/vsphere/driver/vm.go | 42 ++++++++----- builder/vsphere/iso/config.hcl2spec.go | 2 + builder/vsphere/iso/step_create.go | 60 +++++++++++++------ builder/vsphere/iso/step_create.hcl2spec.go | 55 +++++++++++++---- .../docs/builders/vsphere-iso.html.md.erb | 6 ++ .../iso/_CreateConfig-not-required.html.md | 2 + .../iso/_DiskConfig-not-required.html.md | 6 ++ .../vsphere/iso/_DiskConfig-required.html.md | 4 ++ 8 files changed, 131 insertions(+), 46 deletions(-) create mode 100644 website/source/partials/builder/vsphere/iso/_DiskConfig-not-required.html.md create mode 100644 website/source/partials/builder/vsphere/iso/_DiskConfig-required.html.md diff --git a/builder/vsphere/driver/vm.go b/builder/vsphere/driver/vm.go index fa6a5e987..e0bafd6ed 100644 --- a/builder/vsphere/driver/vm.go +++ b/builder/vsphere/driver/vm.go @@ -52,10 +52,7 @@ type NIC struct { } type CreateConfig struct { - DiskThinProvisioned bool - DiskEagerlyScrub bool - DiskControllerType string // example: "scsi", "pvscsi" - DiskSize int64 + DiskControllerType string // example: "scsi", "pvscsi" Annotation string Name string @@ -69,6 +66,13 @@ type CreateConfig struct { USBController bool Version uint // example: 10 Firmware string // efi or bios + Storage []Disk +} + +type Disk struct { + DiskSize int64 + DiskEagerlyScrub bool + DiskThinProvisioned bool } func (d *Driver) NewVM(ref *types.ManagedObjectReference) *VirtualMachine { @@ -488,6 +492,10 @@ func (vm *VirtualMachine) GetDir() (string, error) { } func addDisk(_ *Driver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) { + if len(config.Storage) == 0 { + return nil, errors.New("no storage devices have been defined") + } + device, err := devices.CreateSCSIController(config.DiskControllerType) if err != nil { return nil, err @@ -498,20 +506,22 @@ func addDisk(_ *Driver, devices object.VirtualDeviceList, config *CreateConfig) return nil, err } - disk := &types.VirtualDisk{ - VirtualDevice: types.VirtualDevice{ - Key: devices.NewKey(), - Backing: &types.VirtualDiskFlatVer2BackingInfo{ - DiskMode: string(types.VirtualDiskModePersistent), - ThinProvisioned: types.NewBool(config.DiskThinProvisioned), - EagerlyScrub: types.NewBool(config.DiskEagerlyScrub), + for _, dc := range config.Storage { + disk := &types.VirtualDisk{ + VirtualDevice: types.VirtualDevice{ + Key: devices.NewKey(), + Backing: &types.VirtualDiskFlatVer2BackingInfo{ + DiskMode: string(types.VirtualDiskModePersistent), + ThinProvisioned: types.NewBool(dc.DiskThinProvisioned), + EagerlyScrub: types.NewBool(dc.DiskEagerlyScrub), + }, }, - }, - CapacityInKB: config.DiskSize * 1024, - } + CapacityInKB: dc.DiskSize * 1024, + } - devices.AssignController(disk, controller) - devices = append(devices, disk) + devices.AssignController(disk, controller) + devices = append(devices, disk) + } return devices, nil } diff --git a/builder/vsphere/iso/config.hcl2spec.go b/builder/vsphere/iso/config.hcl2spec.go index cd7d0b474..6f1eeaeac 100644 --- a/builder/vsphere/iso/config.hcl2spec.go +++ b/builder/vsphere/iso/config.hcl2spec.go @@ -31,6 +31,7 @@ type FlatConfig struct { DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size"` DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"` DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub"` + Storage []FlatDiskConfig `mapstructure:"storage" cty:"storage"` Network *string `mapstructure:"network" cty:"network"` NetworkCard *string `mapstructure:"network_card" cty:"network_card"` NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters"` @@ -153,6 +154,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false}, "disk_thin_provisioned": &hcldec.AttrSpec{Name: "disk_thin_provisioned", Type: cty.Bool, Required: false}, "disk_eagerly_scrub": &hcldec.AttrSpec{Name: "disk_eagerly_scrub", Type: cty.Bool, Required: false}, + "storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*FlatDiskConfig)(nil).HCL2Spec())}, "network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false}, "network_card": &hcldec.AttrSpec{Name: "network_card", Type: cty.String, Required: false}, "network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())}, diff --git a/builder/vsphere/iso/step_create.go b/builder/vsphere/iso/step_create.go index dade6847f..eb44c961d 100644 --- a/builder/vsphere/iso/step_create.go +++ b/builder/vsphere/iso/step_create.go @@ -1,5 +1,5 @@ //go:generate struct-markdown -//go:generate mapstructure-to-hcl2 -type NIC,CreateConfig +//go:generate mapstructure-to-hcl2 -type NIC,CreateConfig,DiskConfig package iso @@ -24,6 +24,15 @@ type NIC struct { Passthrough *bool `mapstructure:"passthrough"` } +type DiskConfig struct { + // Set the size of the disk + DiskSize int64 `mapstructure:"disk_size" required:"true"` + // Enable VMDK thin provisioning for VM. Defaults to `false`. + DiskThinProvisioned bool `mapstructure:"disk_thin_provisioned"` + // Enable VMDK eager scrubbing for VM. Defaults to `false`. + DiskEagerlyScrub bool `mapstructure:"disk_eagerly_scrub"` +} + type CreateConfig struct { // Set VM hardware version. Defaults to the most current VM hardware // version supported by vCenter. See @@ -44,6 +53,8 @@ type CreateConfig struct { DiskThinProvisioned bool `mapstructure:"disk_thin_provisioned"` // Enable VMDK eager scrubbing for VM. Defaults to `false`. DiskEagerlyScrub bool `mapstructure:"disk_eagerly_scrub"` + // Storage + Storage []DiskConfig `mapstructure:"storage"` // Set network VM will be connected to. Network string `mapstructure:"network"` // Set VM network card type. Example `vmxnet3`. @@ -115,23 +126,38 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste }) } + // add disk as the first drive for backwards compatibility if the type is defined + var disks []driver.Disk + if s.Config.DiskSize != 0 { + disks = append(disks, driver.Disk{ + DiskSize: s.Config.DiskSize, + DiskEagerlyScrub: s.Config.DiskEagerlyScrub, + DiskThinProvisioned: s.Config.DiskThinProvisioned, + }) + } + for _, disk := range s.Config.Storage { + disks = append(disks, driver.Disk{ + DiskSize: disk.DiskSize, + DiskEagerlyScrub: disk.DiskEagerlyScrub, + DiskThinProvisioned: disk.DiskThinProvisioned, + }) + } + vm, err = d.CreateVM(&driver.CreateConfig{ - DiskThinProvisioned: s.Config.DiskThinProvisioned, - DiskEagerlyScrub: s.Config.DiskEagerlyScrub, - DiskControllerType: s.Config.DiskControllerType, - DiskSize: s.Config.DiskSize, - Name: s.Location.VMName, - Folder: s.Location.Folder, - Cluster: s.Location.Cluster, - Host: s.Location.Host, - ResourcePool: s.Location.ResourcePool, - Datastore: s.Location.Datastore, - GuestOS: s.Config.GuestOSType, - NICs: networkCards, - USBController: s.Config.USBController, - Version: s.Config.Version, - Firmware: s.Config.Firmware, - Annotation: s.Config.Notes, + DiskControllerType: s.Config.DiskControllerType, + Storage: disks, + Annotation: s.Config.Notes, + Name: s.Location.VMName, + Folder: s.Location.Folder, + Cluster: s.Location.Cluster, + Host: s.Location.Host, + ResourcePool: s.Location.ResourcePool, + Datastore: s.Location.Datastore, + GuestOS: s.Config.GuestOSType, + NICs: networkCards, + USBController: s.Config.USBController, + Version: s.Config.Version, + Firmware: s.Config.Firmware, }) if err != nil { state.Put("error", fmt.Errorf("error creating vm: %v", err)) diff --git a/builder/vsphere/iso/step_create.hcl2spec.go b/builder/vsphere/iso/step_create.hcl2spec.go index 0c31cdb83..2bdc5384f 100644 --- a/builder/vsphere/iso/step_create.hcl2spec.go +++ b/builder/vsphere/iso/step_create.hcl2spec.go @@ -1,4 +1,4 @@ -// Code generated by "mapstructure-to-hcl2 -type NIC,CreateConfig"; DO NOT EDIT. +// Code generated by "mapstructure-to-hcl2 -type NIC,CreateConfig,DiskConfig"; DO NOT EDIT. package iso import ( @@ -9,18 +9,19 @@ import ( // FlatCreateConfig is an auto-generated flat version of CreateConfig. // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. type FlatCreateConfig struct { - Version *uint `mapstructure:"vm_version" cty:"vm_version"` - GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type"` - Firmware *string `mapstructure:"firmware" cty:"firmware"` - DiskControllerType *string `mapstructure:"disk_controller_type" cty:"disk_controller_type"` - DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size"` - DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"` - DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub"` - Network *string `mapstructure:"network" cty:"network"` - NetworkCard *string `mapstructure:"network_card" cty:"network_card"` - NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters"` - USBController *bool `mapstructure:"usb_controller" cty:"usb_controller"` - Notes *string `mapstructure:"notes" cty:"notes"` + Version *uint `mapstructure:"vm_version" cty:"vm_version"` + GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type"` + Firmware *string `mapstructure:"firmware" cty:"firmware"` + DiskControllerType *string `mapstructure:"disk_controller_type" cty:"disk_controller_type"` + DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size"` + DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"` + DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub"` + Storage []FlatDiskConfig `mapstructure:"storage" cty:"storage"` + Network *string `mapstructure:"network" cty:"network"` + NetworkCard *string `mapstructure:"network_card" cty:"network_card"` + NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters"` + USBController *bool `mapstructure:"usb_controller" cty:"usb_controller"` + Notes *string `mapstructure:"notes" cty:"notes"` } // FlatMapstructure returns a new FlatCreateConfig. @@ -42,6 +43,7 @@ func (*FlatCreateConfig) HCL2Spec() map[string]hcldec.Spec { "disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false}, "disk_thin_provisioned": &hcldec.AttrSpec{Name: "disk_thin_provisioned", Type: cty.Bool, Required: false}, "disk_eagerly_scrub": &hcldec.AttrSpec{Name: "disk_eagerly_scrub", Type: cty.Bool, Required: false}, + "storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*FlatDiskConfig)(nil).HCL2Spec())}, "network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false}, "network_card": &hcldec.AttrSpec{Name: "network_card", Type: cty.String, Required: false}, "network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())}, @@ -51,6 +53,33 @@ func (*FlatCreateConfig) HCL2Spec() map[string]hcldec.Spec { return s } +// FlatDiskConfig is an auto-generated flat version of DiskConfig. +// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. +type FlatDiskConfig struct { + DiskSize *int64 `mapstructure:"disk_size" required:"true" cty:"disk_size"` + DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"` + DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub"` +} + +// FlatMapstructure returns a new FlatDiskConfig. +// FlatDiskConfig is an auto-generated flat version of DiskConfig. +// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. +func (*DiskConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { + return new(FlatDiskConfig) +} + +// HCL2Spec returns the hcl spec of a DiskConfig. +// This spec is used by HCL to read the fields of DiskConfig. +// The decoded values from this spec will then be applied to a FlatDiskConfig. +func (*FlatDiskConfig) HCL2Spec() map[string]hcldec.Spec { + s := map[string]hcldec.Spec{ + "disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false}, + "disk_thin_provisioned": &hcldec.AttrSpec{Name: "disk_thin_provisioned", Type: cty.Bool, Required: false}, + "disk_eagerly_scrub": &hcldec.AttrSpec{Name: "disk_eagerly_scrub", Type: cty.Bool, Required: false}, + } + return s +} + // FlatNIC is an auto-generated flat version of NIC. // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. type FlatNIC struct { diff --git a/website/source/docs/builders/vsphere-iso.html.md.erb b/website/source/docs/builders/vsphere-iso.html.md.erb index 357268686..3f097eb37 100644 --- a/website/source/docs/builders/vsphere-iso.html.md.erb +++ b/website/source/docs/builders/vsphere-iso.html.md.erb @@ -70,6 +70,12 @@ necessary for this build to succeed and can be found further down the page. ### Network Adapter Configuration <%= partial "partials/builder/vsphere/iso/NIC-required" %> +### Storage Configuration +<%= partial "partials/builder/vsphere/iso/DiskConfig-required" %> + +### Optional Storage Configuration +<%= partial "partials/builder/vsphere/iso/DiskConfig-not-required" %> + ### Floppy Configuration <%= partial "partials/builder/vsphere/iso/FloppyConfig-not-required" %> diff --git a/website/source/partials/builder/vsphere/iso/_CreateConfig-not-required.html.md b/website/source/partials/builder/vsphere/iso/_CreateConfig-not-required.html.md index 204086ae0..e27ed760f 100644 --- a/website/source/partials/builder/vsphere/iso/_CreateConfig-not-required.html.md +++ b/website/source/partials/builder/vsphere/iso/_CreateConfig-not-required.html.md @@ -19,6 +19,8 @@ - `disk_eagerly_scrub` (bool) - Enable VMDK eager scrubbing for VM. Defaults to `false`. +- `storage` ([]DiskConfig) - Storage + - `network` (string) - Set network VM will be connected to. - `network_card` (string) - Set VM network card type. Example `vmxnet3`. diff --git a/website/source/partials/builder/vsphere/iso/_DiskConfig-not-required.html.md b/website/source/partials/builder/vsphere/iso/_DiskConfig-not-required.html.md new file mode 100644 index 000000000..15ca7cc1f --- /dev/null +++ b/website/source/partials/builder/vsphere/iso/_DiskConfig-not-required.html.md @@ -0,0 +1,6 @@ + + +- `disk_thin_provisioned` (bool) - Enable VMDK thin provisioning for VM. Defaults to `false`. + +- `disk_eagerly_scrub` (bool) - Enable VMDK eager scrubbing for VM. Defaults to `false`. + \ No newline at end of file diff --git a/website/source/partials/builder/vsphere/iso/_DiskConfig-required.html.md b/website/source/partials/builder/vsphere/iso/_DiskConfig-required.html.md new file mode 100644 index 000000000..4bdf8c3cb --- /dev/null +++ b/website/source/partials/builder/vsphere/iso/_DiskConfig-required.html.md @@ -0,0 +1,4 @@ + + +- `disk_size` (int64) - Set the size of the disk + \ No newline at end of file From 1dbe5abc14e7c09a463a4fa789a89da0cc09f587 Mon Sep 17 00:00:00 2001 From: Joshua Foster Date: Tue, 3 Mar 2020 11:53:16 -0500 Subject: [PATCH 2/2] update documentation based on feedback --- builder/vsphere/iso/step_create.go | 2 +- website/source/docs/builders/vsphere-iso.html.md.erb | 2 -- .../builder/vsphere/iso/_CreateConfig-not-required.html.md | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/builder/vsphere/iso/step_create.go b/builder/vsphere/iso/step_create.go index eb44c961d..a37f04c53 100644 --- a/builder/vsphere/iso/step_create.go +++ b/builder/vsphere/iso/step_create.go @@ -53,7 +53,7 @@ type CreateConfig struct { DiskThinProvisioned bool `mapstructure:"disk_thin_provisioned"` // Enable VMDK eager scrubbing for VM. Defaults to `false`. DiskEagerlyScrub bool `mapstructure:"disk_eagerly_scrub"` - // Storage + // A collection of one or more disks to be provisioned along with the VM. Storage []DiskConfig `mapstructure:"storage"` // Set network VM will be connected to. Network string `mapstructure:"network"` diff --git a/website/source/docs/builders/vsphere-iso.html.md.erb b/website/source/docs/builders/vsphere-iso.html.md.erb index 3f097eb37..4389aba32 100644 --- a/website/source/docs/builders/vsphere-iso.html.md.erb +++ b/website/source/docs/builders/vsphere-iso.html.md.erb @@ -72,8 +72,6 @@ necessary for this build to succeed and can be found further down the page. ### Storage Configuration <%= partial "partials/builder/vsphere/iso/DiskConfig-required" %> - -### Optional Storage Configuration <%= partial "partials/builder/vsphere/iso/DiskConfig-not-required" %> ### Floppy Configuration diff --git a/website/source/partials/builder/vsphere/iso/_CreateConfig-not-required.html.md b/website/source/partials/builder/vsphere/iso/_CreateConfig-not-required.html.md index e27ed760f..1bf667668 100644 --- a/website/source/partials/builder/vsphere/iso/_CreateConfig-not-required.html.md +++ b/website/source/partials/builder/vsphere/iso/_CreateConfig-not-required.html.md @@ -19,7 +19,7 @@ - `disk_eagerly_scrub` (bool) - Enable VMDK eager scrubbing for VM. Defaults to `false`. -- `storage` ([]DiskConfig) - Storage +- `storage` ([]DiskConfig) - A collection of one or more disks to be provisioned along with the VM. - `network` (string) - Set network VM will be connected to.