diff --git a/builder/vsphere/clone/config.hcl2spec.go b/builder/vsphere/clone/config.hcl2spec.go index ec26d8d42..ca49332d2 100644 --- a/builder/vsphere/clone/config.hcl2spec.go +++ b/builder/vsphere/clone/config.hcl2spec.go @@ -37,6 +37,8 @@ type FlatConfig struct { MacAddress *string `mapstructure:"mac_address" cty:"mac_address" hcl:"mac_address"` Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"` VAppConfig *FlatvAppConfig `mapstructure:"vapp" cty:"vapp" hcl:"vapp"` + DiskControllerType []string `mapstructure:"disk_controller_type" cty:"disk_controller_type" hcl:"disk_controller_type"` + Storage []common.FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"` VMName *string `mapstructure:"vm_name" cty:"vm_name" hcl:"vm_name"` Folder *string `mapstructure:"folder" cty:"folder" hcl:"folder"` Cluster *string `mapstructure:"cluster" cty:"cluster" hcl:"cluster"` @@ -174,6 +176,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "mac_address": &hcldec.AttrSpec{Name: "mac_address", Type: cty.String, Required: false}, "notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false}, "vapp": &hcldec.BlockSpec{TypeName: "vapp", Nested: hcldec.ObjectSpec((*FlatvAppConfig)(nil).HCL2Spec())}, + "disk_controller_type": &hcldec.AttrSpec{Name: "disk_controller_type", Type: cty.List(cty.String), Required: false}, + "storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*common.FlatDiskConfig)(nil).HCL2Spec())}, "vm_name": &hcldec.AttrSpec{Name: "vm_name", Type: cty.String, Required: false}, "folder": &hcldec.AttrSpec{Name: "folder", Type: cty.String, Required: false}, "cluster": &hcldec.AttrSpec{Name: "cluster", Type: cty.String, Required: false}, diff --git a/builder/vsphere/clone/step_clone.go b/builder/vsphere/clone/step_clone.go index 8a8ca1ccf..850d2b3d5 100644 --- a/builder/vsphere/clone/step_clone.go +++ b/builder/vsphere/clone/step_clone.go @@ -44,11 +44,13 @@ type CloneConfig struct { // Set the vApp Options to a virtual machine. // See the [vApp Options Configuration](/docs/builders/vmware/vsphere-clone#vapp-options-configuration) // to know the available options and how to use it. - VAppConfig vAppConfig `mapstructure:"vapp"` + VAppConfig vAppConfig `mapstructure:"vapp"` + StorageConfig common.StorageConfig `mapstructure:",squash"` } func (c *CloneConfig) Prepare() []error { var errs []error + errs = append(errs, c.StorageConfig.Prepare()...) if c.Template == "" { errs = append(errs, fmt.Errorf("'template' is required")) @@ -89,6 +91,16 @@ func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multist return multistep.ActionHalt } + var disks []driver.Disk + for _, disk := range s.Config.StorageConfig.Storage { + disks = append(disks, driver.Disk{ + DiskSize: disk.DiskSize, + DiskEagerlyScrub: disk.DiskEagerlyScrub, + DiskThinProvisioned: disk.DiskThinProvisioned, + ControllerIndex: disk.DiskControllerIndex, + }) + } + vm, err := template.Clone(ctx, &driver.CloneConfig{ Name: s.Location.VMName, Folder: s.Location.Folder, @@ -101,6 +113,10 @@ func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multist MacAddress: s.Config.MacAddress, Annotation: s.Config.Notes, VAppProperties: s.Config.VAppConfig.Properties, + StorageConfig: driver.StorageConfig{ + DiskControllerType: s.Config.StorageConfig.DiskControllerType, + Storage: disks, + }, }) if err != nil { state.Put("error", err) diff --git a/builder/vsphere/clone/step_clone.hcl2spec.go b/builder/vsphere/clone/step_clone.hcl2spec.go index ad55ebfa8..a0422e28e 100644 --- a/builder/vsphere/clone/step_clone.hcl2spec.go +++ b/builder/vsphere/clone/step_clone.hcl2spec.go @@ -3,19 +3,22 @@ package clone import ( "github.com/hashicorp/hcl/v2/hcldec" + "github.com/hashicorp/packer/builder/vsphere/common" "github.com/zclconf/go-cty/cty" ) // FlatCloneConfig is an auto-generated flat version of CloneConfig. // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. type FlatCloneConfig struct { - Template *string `mapstructure:"template" cty:"template" hcl:"template"` - DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size" hcl:"disk_size"` - LinkedClone *bool `mapstructure:"linked_clone" cty:"linked_clone" hcl:"linked_clone"` - Network *string `mapstructure:"network" cty:"network" hcl:"network"` - MacAddress *string `mapstructure:"mac_address" cty:"mac_address" hcl:"mac_address"` - Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"` - VAppConfig *FlatvAppConfig `mapstructure:"vapp" cty:"vapp" hcl:"vapp"` + Template *string `mapstructure:"template" cty:"template" hcl:"template"` + DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size" hcl:"disk_size"` + LinkedClone *bool `mapstructure:"linked_clone" cty:"linked_clone" hcl:"linked_clone"` + Network *string `mapstructure:"network" cty:"network" hcl:"network"` + MacAddress *string `mapstructure:"mac_address" cty:"mac_address" hcl:"mac_address"` + Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"` + VAppConfig *FlatvAppConfig `mapstructure:"vapp" cty:"vapp" hcl:"vapp"` + DiskControllerType []string `mapstructure:"disk_controller_type" cty:"disk_controller_type" hcl:"disk_controller_type"` + Storage []common.FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"` } // FlatMapstructure returns a new FlatCloneConfig. @@ -30,13 +33,15 @@ func (*CloneConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.S // The decoded values from this spec will then be applied to a FlatCloneConfig. func (*FlatCloneConfig) HCL2Spec() map[string]hcldec.Spec { s := map[string]hcldec.Spec{ - "template": &hcldec.AttrSpec{Name: "template", Type: cty.String, Required: false}, - "disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false}, - "linked_clone": &hcldec.AttrSpec{Name: "linked_clone", Type: cty.Bool, Required: false}, - "network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false}, - "mac_address": &hcldec.AttrSpec{Name: "mac_address", Type: cty.String, Required: false}, - "notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false}, - "vapp": &hcldec.BlockSpec{TypeName: "vapp", Nested: hcldec.ObjectSpec((*FlatvAppConfig)(nil).HCL2Spec())}, + "template": &hcldec.AttrSpec{Name: "template", Type: cty.String, Required: false}, + "disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false}, + "linked_clone": &hcldec.AttrSpec{Name: "linked_clone", Type: cty.Bool, Required: false}, + "network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false}, + "mac_address": &hcldec.AttrSpec{Name: "mac_address", Type: cty.String, Required: false}, + "notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false}, + "vapp": &hcldec.BlockSpec{TypeName: "vapp", Nested: hcldec.ObjectSpec((*FlatvAppConfig)(nil).HCL2Spec())}, + "disk_controller_type": &hcldec.AttrSpec{Name: "disk_controller_type", Type: cty.List(cty.String), Required: false}, + "storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*common.FlatDiskConfig)(nil).HCL2Spec())}, } return s } diff --git a/builder/vsphere/common/storage_config.go b/builder/vsphere/common/storage_config.go new file mode 100644 index 000000000..6650616d5 --- /dev/null +++ b/builder/vsphere/common/storage_config.go @@ -0,0 +1,118 @@ +//go:generate struct-markdown +//go:generate mapstructure-to-hcl2 -type StorageConfig,DiskConfig + +package common + +import ( + "fmt" +) + +// Defines the disk storage for a VM. +// +// Example that will create a 15GB and a 20GB disk on the VM. The second disk will be thin provisioned: +// +// In JSON: +// ```json +// "storage": [ +// { +// "disk_size": 15000 +// }, +// { +// "disk_size": 20000, +// "disk_thin_provisioned": true +// } +// ], +// ``` +// In HCL2: +// ```hcl +// storage { +// disk_size = 15000 +// } +// storage { +// disk_size = 20000 +// disk_thin_provisioned = true +// } +// ``` +// +// Example that creates 2 pvscsi controllers and adds 2 disks to each one: +// +// In JSON: +// ```json +// "disk_controller_type": ["pvscsi", "pvscsi"], +// "storage": [ +// { +// "disk_size": 15000, +// "disk_controller_index": 0 +// }, +// { +// "disk_size": 15000, +// "disk_controller_index": 0 +// }, +// { +// "disk_size": 15000, +// "disk_controller_index": 1 +// }, +// { +// "disk_size": 15000, +// "disk_controller_index": 1 +// } +// ], +// ``` +// +// In HCL2: +// ```hcl +// disk_controller_type = ["pvscsi", "pvscsi"] +// storage { +// disk_size = 15000, +// disk_controller_index = 0 +// } +// storage { +// disk_size = 15000 +// disk_controller_index = 0 +// } +// storage { +// disk_size = 15000 +// disk_controller_index = 1 +// } +// storage { +// disk_size = 15000 +// disk_controller_index = 1 +// } +// ``` +type DiskConfig struct { + // The size of the disk in MB. + 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"` + // The assigned disk controller. Defaults to the first one (0) + DiskControllerIndex int `mapstructure:"disk_controller_index"` +} + +type StorageConfig struct { + // Set VM disk controller type. Example `lsilogic`, `pvscsi`, `nvme`, or `scsi`. Use a list to define additional controllers. + // Defaults to `lsilogic`. See + // [SCSI, SATA, and NVMe Storage Controller Conditions, Limitations, and Compatibility](https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-5872D173-A076-42FE-8D0B-9DB0EB0E7362.html#GUID-5872D173-A076-42FE-8D0B-9DB0EB0E7362) + // for additional details. + DiskControllerType []string `mapstructure:"disk_controller_type"` + // Configures a collection of one or more disks to be provisioned along with the VM. See the [Storage Configuration](#storage-configuration). + Storage []DiskConfig `mapstructure:"storage"` +} + +func (c *StorageConfig) Prepare() []error { + var errs []error + + if len(c.Storage) > 0 { + for i, storage := range c.Storage { + if storage.DiskSize == 0 { + errs = append(errs, fmt.Errorf("storage[%d].'disk_size' is required", i)) + } + if storage.DiskControllerIndex >= len(c.DiskControllerType) { + errs = append(errs, fmt.Errorf("storage[%d].'disk_controller_index' references an unknown disk controller", i)) + } + } + } + + return errs +} diff --git a/builder/vsphere/common/storage_config.hcl2spec.go b/builder/vsphere/common/storage_config.hcl2spec.go new file mode 100644 index 000000000..37d8722a2 --- /dev/null +++ b/builder/vsphere/common/storage_config.hcl2spec.go @@ -0,0 +1,61 @@ +// Code generated by "mapstructure-to-hcl2 -type StorageConfig,DiskConfig"; DO NOT EDIT. +package common + +import ( + "github.com/hashicorp/hcl/v2/hcldec" + "github.com/zclconf/go-cty/cty" +) + +// 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" hcl:"disk_size"` + DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned" hcl:"disk_thin_provisioned"` + DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub" hcl:"disk_eagerly_scrub"` + DiskControllerIndex *int `mapstructure:"disk_controller_index" cty:"disk_controller_index" hcl:"disk_controller_index"` +} + +// 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}, + "disk_controller_index": &hcldec.AttrSpec{Name: "disk_controller_index", Type: cty.Number, Required: false}, + } + return s +} + +// FlatStorageConfig is an auto-generated flat version of StorageConfig. +// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. +type FlatStorageConfig struct { + DiskControllerType []string `mapstructure:"disk_controller_type" cty:"disk_controller_type" hcl:"disk_controller_type"` + Storage []FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"` +} + +// FlatMapstructure returns a new FlatStorageConfig. +// FlatStorageConfig is an auto-generated flat version of StorageConfig. +// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. +func (*StorageConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { + return new(FlatStorageConfig) +} + +// HCL2Spec returns the hcl spec of a StorageConfig. +// This spec is used by HCL to read the fields of StorageConfig. +// The decoded values from this spec will then be applied to a FlatStorageConfig. +func (*FlatStorageConfig) HCL2Spec() map[string]hcldec.Spec { + s := map[string]hcldec.Spec{ + "disk_controller_type": &hcldec.AttrSpec{Name: "disk_controller_type", Type: cty.List(cty.String), Required: false}, + "storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*FlatDiskConfig)(nil).HCL2Spec())}, + } + return s +} diff --git a/builder/vsphere/driver/disk.go b/builder/vsphere/driver/disk.go new file mode 100644 index 000000000..07553e212 --- /dev/null +++ b/builder/vsphere/driver/disk.go @@ -0,0 +1,84 @@ +package driver + +import ( + "errors" + + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25/types" +) + +type Disk struct { + DiskSize int64 + DiskEagerlyScrub bool + DiskThinProvisioned bool + ControllerIndex int +} + +type StorageConfig struct { + DiskControllerType []string // example: "scsi", "pvscsi", "nvme", "lsilogic" + Storage []Disk +} + +func (c *StorageConfig) AddStorageDevices(existingDevices object.VirtualDeviceList) ([]types.BaseVirtualDeviceConfigSpec, error) { + newDevices := object.VirtualDeviceList{} + + // Create new controller based on existing devices list and add it to the new devices list + // to confirm creation + var controllers []types.BaseVirtualController + for _, controllerType := range c.DiskControllerType { + var device types.BaseVirtualDevice + var err error + if controllerType == "nvme" { + device, err = existingDevices.CreateNVMEController() + } else { + device, err = existingDevices.CreateSCSIController(controllerType) + } + if err != nil { + return nil, err + } + existingDevices = append(existingDevices, device) + newDevices = append(newDevices, device) + controller, err := existingDevices.FindDiskController(existingDevices.Name(device)) + if err != nil { + return nil, err + } + controllers = append(controllers, controller) + } + + for _, dc := range c.Storage { + disk := &types.VirtualDisk{ + VirtualDevice: types.VirtualDevice{ + Key: existingDevices.NewKey(), + Backing: &types.VirtualDiskFlatVer2BackingInfo{ + DiskMode: string(types.VirtualDiskModePersistent), + ThinProvisioned: types.NewBool(dc.DiskThinProvisioned), + EagerlyScrub: types.NewBool(dc.DiskEagerlyScrub), + }, + }, + CapacityInKB: dc.DiskSize * 1024, + } + + existingDevices.AssignController(disk, controllers[dc.ControllerIndex]) + newDevices = append(newDevices, disk) + } + + return newDevices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd) +} + +func findDisk(devices object.VirtualDeviceList) (*types.VirtualDisk, error) { + var disks []*types.VirtualDisk + for _, device := range devices { + switch d := device.(type) { + case *types.VirtualDisk: + disks = append(disks, d) + } + } + + switch len(disks) { + case 0: + return nil, errors.New("VM has no disks") + case 1: + return disks[0], nil + } + return nil, errors.New("VM has multiple disks") +} diff --git a/builder/vsphere/driver/vm.go b/builder/vsphere/driver/vm.go index 8481f3716..acc80ec4e 100644 --- a/builder/vsphere/driver/vm.go +++ b/builder/vsphere/driver/vm.go @@ -79,6 +79,7 @@ type CloneConfig struct { MacAddress string Annotation string VAppProperties map[string]string + StorageConfig StorageConfig } type HardwareConfig struct { @@ -106,8 +107,6 @@ type NIC struct { } type CreateConfig struct { - DiskControllerType []string // example: "scsi", "pvscsi", "nvme", "lsilogic" - Annotation string Name string Folder string @@ -119,14 +118,7 @@ type CreateConfig struct { NICs []NIC USBController []string Version uint // example: 10 - Storage []Disk -} - -type Disk struct { - DiskSize int64 - DiskEagerlyScrub bool - DiskThinProvisioned bool - ControllerIndex int + StorageConfig StorageConfig } func (d *VCenterDriver) NewVM(ref *types.ManagedObjectReference) VirtualMachine { @@ -207,11 +199,12 @@ func (d *VCenterDriver) CreateVM(config *CreateConfig) (VirtualMachine, error) { } devices := object.VirtualDeviceList{} - - devices, err = addDisk(d, devices, config) + storageConfigSpec, err := config.StorageConfig.AddStorageDevices(devices) if err != nil { return nil, err } + createSpec.DeviceChange = append(createSpec.DeviceChange, storageConfigSpec...) + devices, err = addNetwork(d, devices, config) if err != nil { return nil, err @@ -235,10 +228,11 @@ func (d *VCenterDriver) CreateVM(config *CreateConfig) (VirtualMachine, error) { devices = append(devices, usb) } - createSpec.DeviceChange, err = devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd) + devicesConfigSpec, err := devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd) if err != nil { return nil, err } + createSpec.DeviceChange = append(createSpec.DeviceChange, devicesConfigSpec...) createSpec.Files = &types.VirtualMachineFileInfo{ VmPathName: fmt.Sprintf("[%s]", datastore.Name()), @@ -341,6 +335,24 @@ func (vm *VirtualMachineDriver) Clone(ctx context.Context, config *CloneConfig) configSpec.Annotation = config.Annotation } + devices, err := vm.vm.Device(vm.driver.ctx) + if err != nil { + return nil, err + } + virtualDisks := devices.SelectByType((*types.VirtualDisk)(nil)) + virtualControllers := devices.SelectByType((*types.VirtualController)(nil)) + + // Use existing devices to avoid overlapping configuration + existingDevices := object.VirtualDeviceList{} + existingDevices = append(existingDevices, virtualDisks...) + existingDevices = append(existingDevices, virtualControllers...) + + storageConfigSpec, err := config.StorageConfig.AddStorageDevices(existingDevices) + if err != nil { + return nil, err + } + configSpec.DeviceChange = append(configSpec.DeviceChange, storageConfigSpec...) + if config.Network != "" { net, err := vm.driver.FindNetwork(config.Network) if err != nil { @@ -616,24 +628,6 @@ func (vm *VirtualMachineDriver) ResizeDisk(diskSize int64) error { return err } -func findDisk(devices object.VirtualDeviceList) (*types.VirtualDisk, error) { - var disks []*types.VirtualDisk - for _, device := range devices { - switch d := device.(type) { - case *types.VirtualDisk: - disks = append(disks, d) - } - } - - switch len(disks) { - case 0: - return nil, errors.New("VM has no disks") - case 1: - return disks[0], nil - } - return nil, errors.New("VM has multiple disks") -} - func (vm *VirtualMachineDriver) PowerOn() error { task, err := vm.vm.PowerOn(vm.driver.ctx) if err != nil { @@ -849,55 +843,6 @@ func (vm *VirtualMachineDriver) GetDir() (string, error) { return "", fmt.Errorf("cannot find '%s'", vmxName) } -func addDisk(_ *VCenterDriver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) { - if len(config.Storage) == 0 { - return nil, errors.New("no storage devices have been defined") - } - - if len(config.DiskControllerType) == 0 { - return nil, errors.New("no controllers have been defined") - } - - var controllers []types.BaseVirtualController - for _, controllerType := range config.DiskControllerType { - var device types.BaseVirtualDevice - var err error - if controllerType == "nvme" { - device, err = devices.CreateNVMEController() - } else { - device, err = devices.CreateSCSIController(controllerType) - } - if err != nil { - return nil, err - } - devices = append(devices, device) - controller, err := devices.FindDiskController(devices.Name(device)) - if err != nil { - return nil, err - } - controllers = append(controllers, controller) - } - - 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: dc.DiskSize * 1024, - } - - devices.AssignController(disk, controllers[dc.ControllerIndex]) - devices = append(devices, disk) - } - - return devices, nil -} - func addNetwork(d *VCenterDriver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) { if len(config.NICs) == 0 { return nil, errors.New("no network adapters have been defined") diff --git a/builder/vsphere/iso/config.hcl2spec.go b/builder/vsphere/iso/config.hcl2spec.go index 41061b95a..f8f31ec3b 100644 --- a/builder/vsphere/iso/config.hcl2spec.go +++ b/builder/vsphere/iso/config.hcl2spec.go @@ -33,7 +33,7 @@ type FlatConfig struct { Version *uint `mapstructure:"vm_version" cty:"vm_version" hcl:"vm_version"` GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type" hcl:"guest_os_type"` DiskControllerType []string `mapstructure:"disk_controller_type" cty:"disk_controller_type" hcl:"disk_controller_type"` - Storage []FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"` + Storage []common.FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"` NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters" hcl:"network_adapters"` USBController []string `mapstructure:"usb_controller" cty:"usb_controller" hcl:"usb_controller"` Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"` @@ -174,7 +174,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "vm_version": &hcldec.AttrSpec{Name: "vm_version", Type: cty.Number, Required: false}, "guest_os_type": &hcldec.AttrSpec{Name: "guest_os_type", Type: cty.String, Required: false}, "disk_controller_type": &hcldec.AttrSpec{Name: "disk_controller_type", Type: cty.List(cty.String), Required: false}, - "storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*FlatDiskConfig)(nil).HCL2Spec())}, + "storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*common.FlatDiskConfig)(nil).HCL2Spec())}, "network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())}, "usb_controller": &hcldec.AttrSpec{Name: "usb_controller", Type: cty.List(cty.String), Required: false}, "notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false}, diff --git a/builder/vsphere/iso/step_create.go b/builder/vsphere/iso/step_create.go index 562d2cf24..7b13f151a 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,DiskConfig +//go:generate mapstructure-to-hcl2 -type NIC,CreateConfig package iso @@ -56,89 +56,6 @@ type NIC struct { Passthrough *bool `mapstructure:"passthrough"` } -// Defines the disk storage for a VM. -// -// Example that will create a 15GB and a 20GB disk on the VM. The second disk will be thin provisioned: -// -// In JSON: -// ```json -// "storage": [ -// { -// "disk_size": 15000 -// }, -// { -// "disk_size": 20000, -// "disk_thin_provisioned": true -// } -// ], -// ``` -// In HCL2: -// ```hcl -// storage { -// disk_size = 15000 -// } -// storage { -// disk_size = 20000 -// disk_thin_provisioned = true -// } -// ``` -// -// Example that creates 2 pvscsi controllers and adds 2 disks to each one: -// -// In JSON: -// ```json -// "disk_controller_type": ["pvscsi", "pvscsi"], -// "storage": [ -// { -// "disk_size": 15000, -// "disk_controller_index": 0 -// }, -// { -// "disk_size": 15000, -// "disk_controller_index": 0 -// }, -// { -// "disk_size": 15000, -// "disk_controller_index": 1 -// }, -// { -// "disk_size": 15000, -// "disk_controller_index": 1 -// } -// ], -// ``` -// -// In HCL2: -// ```hcl -// disk_controller_type = ["pvscsi", "pvscsi"] -// storage { -// disk_size = 15000, -// disk_controller_index = 0 -// } -// storage { -// disk_size = 15000 -// disk_controller_index = 0 -// } -// storage { -// disk_size = 15000 -// disk_controller_index = 1 -// } -// storage { -// disk_size = 15000 -// disk_controller_index = 1 -// } -// ``` -type DiskConfig struct { - // The size of the disk in MB. - 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"` - // The assigned disk controller. Defaults to the first one (0) - DiskControllerIndex int `mapstructure:"disk_controller_index"` -} - type CreateConfig struct { // Set VM hardware version. Defaults to the most current VM hardware // version supported by vCenter. See @@ -148,14 +65,8 @@ type CreateConfig struct { // Set VM OS type. Defaults to `otherGuest`. See [ // here](https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html) // for a full list of possible values. - GuestOSType string `mapstructure:"guest_os_type"` - // Set VM disk controller type. Example `lsilogic`, `pvscsi`, `nvme`, or `scsi`. Use a list to define additional controllers. - // Defaults to `lsilogic`. See - // [SCSI, SATA, and NVMe Storage Controller Conditions, Limitations, and Compatibility](https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-5872D173-A076-42FE-8D0B-9DB0EB0E7362.html#GUID-5872D173-A076-42FE-8D0B-9DB0EB0E7362) - // for additional details. - DiskControllerType []string `mapstructure:"disk_controller_type"` - // A collection of one or more disks to be provisioned along with the VM. - Storage []DiskConfig `mapstructure:"storage"` + GuestOSType string `mapstructure:"guest_os_type"` + StorageConfig common.StorageConfig `mapstructure:",squash"` // Network adapters NICs []NIC `mapstructure:"network_adapters"` // Create USB controllers for the virtual machine. "usb" for a usb 2.0 controller. "xhci" for a usb 3.0 controller. There can only be at most one of each. @@ -167,21 +78,15 @@ type CreateConfig struct { func (c *CreateConfig) Prepare() []error { var errs []error - // there should be at least one - if len(c.DiskControllerType) == 0 { - c.DiskControllerType = append(c.DiskControllerType, "") + if len(c.StorageConfig.DiskControllerType) == 0 { + c.StorageConfig.DiskControllerType = append(c.StorageConfig.DiskControllerType, "") } - if len(c.Storage) > 0 { - for i, storage := range c.Storage { - if storage.DiskSize == 0 { - errs = append(errs, fmt.Errorf("storage[%d].'disk_size' is required", i)) - } - if storage.DiskControllerIndex >= len(c.DiskControllerType) { - errs = append(errs, fmt.Errorf("storage[%d].'disk_controller_index' references an unknown disk controller", i)) - } - } + // there should be at least one + if len(c.StorageConfig.Storage) == 0 { + errs = append(errs, fmt.Errorf("no storage devices have been defined")) } + errs = append(errs, c.StorageConfig.Prepare()...) if c.GuestOSType == "" { c.GuestOSType = "otherGuest" @@ -243,7 +148,7 @@ 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 - for _, disk := range s.Config.Storage { + for _, disk := range s.Config.StorageConfig.Storage { disks = append(disks, driver.Disk{ DiskSize: disk.DiskSize, DiskEagerlyScrub: disk.DiskEagerlyScrub, @@ -253,19 +158,21 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste } vm, err := d.CreateVM(&driver.CreateConfig{ - 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, + StorageConfig: driver.StorageConfig{ + DiskControllerType: s.Config.StorageConfig.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, }) 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 dadf605d5..06360e6ac 100644 --- a/builder/vsphere/iso/step_create.hcl2spec.go +++ b/builder/vsphere/iso/step_create.hcl2spec.go @@ -1,21 +1,22 @@ -// Code generated by "mapstructure-to-hcl2 -type NIC,CreateConfig,DiskConfig"; DO NOT EDIT. +// Code generated by "mapstructure-to-hcl2 -type NIC,CreateConfig"; DO NOT EDIT. package iso import ( "github.com/hashicorp/hcl/v2/hcldec" + "github.com/hashicorp/packer/builder/vsphere/common" "github.com/zclconf/go-cty/cty" ) // 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" hcl:"vm_version"` - GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type" hcl:"guest_os_type"` - DiskControllerType []string `mapstructure:"disk_controller_type" cty:"disk_controller_type" hcl:"disk_controller_type"` - Storage []FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"` - NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters" hcl:"network_adapters"` - USBController []string `mapstructure:"usb_controller" cty:"usb_controller" hcl:"usb_controller"` - Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"` + Version *uint `mapstructure:"vm_version" cty:"vm_version" hcl:"vm_version"` + GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type" hcl:"guest_os_type"` + DiskControllerType []string `mapstructure:"disk_controller_type" cty:"disk_controller_type" hcl:"disk_controller_type"` + Storage []common.FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"` + NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters" hcl:"network_adapters"` + USBController []string `mapstructure:"usb_controller" cty:"usb_controller" hcl:"usb_controller"` + Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"` } // FlatMapstructure returns a new FlatCreateConfig. @@ -33,7 +34,7 @@ func (*FlatCreateConfig) HCL2Spec() map[string]hcldec.Spec { "vm_version": &hcldec.AttrSpec{Name: "vm_version", Type: cty.Number, Required: false}, "guest_os_type": &hcldec.AttrSpec{Name: "guest_os_type", Type: cty.String, Required: false}, "disk_controller_type": &hcldec.AttrSpec{Name: "disk_controller_type", Type: cty.List(cty.String), Required: false}, - "storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*FlatDiskConfig)(nil).HCL2Spec())}, + "storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*common.FlatDiskConfig)(nil).HCL2Spec())}, "network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())}, "usb_controller": &hcldec.AttrSpec{Name: "usb_controller", Type: cty.List(cty.String), Required: false}, "notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false}, @@ -41,35 +42,6 @@ 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" hcl:"disk_size"` - DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned" hcl:"disk_thin_provisioned"` - DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub" hcl:"disk_eagerly_scrub"` - DiskControllerIndex *int `mapstructure:"disk_controller_index" cty:"disk_controller_index" hcl:"disk_controller_index"` -} - -// 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}, - "disk_controller_index": &hcldec.AttrSpec{Name: "disk_controller_index", Type: cty.Number, 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/builder/vsphere/iso/step_create_test.go b/builder/vsphere/iso/step_create_test.go index aca46d155..cd0b4fa57 100644 --- a/builder/vsphere/iso/step_create_test.go +++ b/builder/vsphere/iso/step_create_test.go @@ -17,14 +17,23 @@ import ( func TestCreateConfig_Prepare(t *testing.T) { // Empty config - check defaults - config := &CreateConfig{} + config := &CreateConfig{ + // Storage is required + StorageConfig: common.StorageConfig{ + Storage: []common.DiskConfig{ + { + DiskSize: 32768, + }, + }, + }, + } if errs := config.Prepare(); len(errs) != 0 { - t.Fatalf("Config preprare should not fail") + t.Fatalf("Config preprare should not fail: %s", errs[0]) } if config.GuestOSType != "otherGuest" { t.Fatalf("GuestOSType should default to 'otherGuest'") } - if len(config.DiskControllerType) != 1 { + if len(config.StorageConfig.DiskControllerType) != 1 { t.Fatalf("DiskControllerType should have at least one element as default") } @@ -38,10 +47,12 @@ func TestCreateConfig_Prepare(t *testing.T) { { name: "Storage validate disk_size", config: &CreateConfig{ - Storage: []DiskConfig{ - { - DiskSize: 0, - DiskThinProvisioned: true, + StorageConfig: common.StorageConfig{ + Storage: []common.DiskConfig{ + { + DiskSize: 0, + DiskThinProvisioned: true, + }, }, }, }, @@ -51,10 +62,12 @@ func TestCreateConfig_Prepare(t *testing.T) { { name: "Storage validate disk_controller_index", config: &CreateConfig{ - Storage: []DiskConfig{ - { - DiskSize: 32768, - DiskControllerIndex: 3, + StorageConfig: common.StorageConfig{ + Storage: []common.DiskConfig{ + { + DiskSize: 32768, + DiskControllerIndex: 3, + }, }, }, }, @@ -65,6 +78,13 @@ func TestCreateConfig_Prepare(t *testing.T) { name: "USBController validate 'usb' and 'xhci' can be set together", config: &CreateConfig{ USBController: []string{"usb", "xhci"}, + StorageConfig: common.StorageConfig{ + Storage: []common.DiskConfig{ + { + DiskSize: 32768, + }, + }, + }, }, fail: false, }, @@ -72,6 +92,13 @@ func TestCreateConfig_Prepare(t *testing.T) { name: "USBController validate '1' and '0' can be set together", config: &CreateConfig{ USBController: []string{"1", "0"}, + StorageConfig: common.StorageConfig{ + Storage: []common.DiskConfig{ + { + DiskSize: 32768, + }, + }, + }, }, fail: false, }, @@ -79,6 +106,13 @@ func TestCreateConfig_Prepare(t *testing.T) { name: "USBController validate 'true' and 'false' can be set together", config: &CreateConfig{ USBController: []string{"true", "false"}, + StorageConfig: common.StorageConfig{ + Storage: []common.DiskConfig{ + { + DiskSize: 32768, + }, + }, + }, }, fail: false, }, @@ -86,6 +120,13 @@ func TestCreateConfig_Prepare(t *testing.T) { name: "USBController validate 'true' and 'usb' cannot be set together", config: &CreateConfig{ USBController: []string{"true", "usb"}, + StorageConfig: common.StorageConfig{ + Storage: []common.DiskConfig{ + { + DiskSize: 32768, + }, + }, + }, }, fail: true, expectedErrMsg: "there can only be one usb controller and one xhci controller", @@ -94,6 +135,13 @@ func TestCreateConfig_Prepare(t *testing.T) { name: "USBController validate '1' and 'usb' cannot be set together", config: &CreateConfig{ USBController: []string{"1", "usb"}, + StorageConfig: common.StorageConfig{ + Storage: []common.DiskConfig{ + { + DiskSize: 32768, + }, + }, + }, }, fail: true, expectedErrMsg: "there can only be one usb controller and one xhci controller", @@ -102,6 +150,13 @@ func TestCreateConfig_Prepare(t *testing.T) { name: "USBController validate 'xhci' cannot be set more that once", config: &CreateConfig{ USBController: []string{"xhci", "xhci"}, + StorageConfig: common.StorageConfig{ + Storage: []common.DiskConfig{ + { + DiskSize: 32768, + }, + }, + }, }, fail: true, expectedErrMsg: "there can only be one usb controller and one xhci controller", @@ -110,6 +165,13 @@ func TestCreateConfig_Prepare(t *testing.T) { name: "USBController validate unknown value cannot be set", config: &CreateConfig{ USBController: []string{"unknown"}, + StorageConfig: common.StorageConfig{ + Storage: []common.DiskConfig{ + { + DiskSize: 32768, + }, + }, + }, }, fail: true, expectedErrMsg: "usb_controller[0] references an unknown usb controller", @@ -127,7 +189,7 @@ func TestCreateConfig_Prepare(t *testing.T) { } } else { if len(errs) != 0 { - t.Fatalf("Config preprare should not fail") + t.Fatalf("Config preprare should not fail: %s", errs[0]) } } } @@ -294,13 +356,15 @@ func basicLocationConfig() *common.LocationConfig { func createConfig() *CreateConfig { return &CreateConfig{ - Version: 1, - GuestOSType: "ubuntu64Guest", - DiskControllerType: []string{"pvscsi"}, - Storage: []DiskConfig{ - { - DiskSize: 32768, - DiskThinProvisioned: true, + Version: 1, + GuestOSType: "ubuntu64Guest", + StorageConfig: common.StorageConfig{ + DiskControllerType: []string{"pvscsi"}, + Storage: []common.DiskConfig{ + { + DiskSize: 32768, + DiskThinProvisioned: true, + }, }, }, NICs: []NIC{ @@ -324,7 +388,7 @@ func driverCreateConfig(config *CreateConfig, location *common.LocationConfig) * } var disks []driver.Disk - for _, disk := range config.Storage { + for _, disk := range config.StorageConfig.Storage { disks = append(disks, driver.Disk{ DiskSize: disk.DiskSize, DiskEagerlyScrub: disk.DiskEagerlyScrub, @@ -334,18 +398,20 @@ func driverCreateConfig(config *CreateConfig, location *common.LocationConfig) * } return &driver.CreateConfig{ - DiskControllerType: config.DiskControllerType, - Storage: disks, - Annotation: config.Notes, - Name: location.VMName, - Folder: location.Folder, - Cluster: location.Cluster, - Host: location.Host, - ResourcePool: location.ResourcePool, - Datastore: location.Datastore, - GuestOS: config.GuestOSType, - NICs: networkCards, - USBController: config.USBController, - Version: config.Version, + StorageConfig: driver.StorageConfig{ + DiskControllerType: config.StorageConfig.DiskControllerType, + Storage: disks, + }, + Annotation: config.Notes, + Name: location.VMName, + Folder: location.Folder, + Cluster: location.Cluster, + Host: location.Host, + ResourcePool: location.ResourcePool, + Datastore: location.Datastore, + GuestOS: config.GuestOSType, + NICs: networkCards, + USBController: config.USBController, + Version: config.Version, } } diff --git a/website/pages/docs/builders/vmware/vsphere-clone.mdx b/website/pages/docs/builders/vmware/vsphere-clone.mdx index e91bf3734..a9b68e4be 100644 --- a/website/pages/docs/builders/vmware/vsphere-clone.mdx +++ b/website/pages/docs/builders/vmware/vsphere-clone.mdx @@ -45,6 +45,21 @@ necessary for this build to succeed and can be found further down the page. @include 'builder/vsphere/clone/CloneConfig-not-required.mdx' +@include 'builder/vsphere/common/StorageConfig-not-required.mdx' + +### Storage Configuration + +When cloning a VM, the storage configuration can be used to add additional storage and disk controllers. The resulting VM +will contain the origin VM storage and disk controller plus the new configured ones. + +@include 'builder/vsphere/common/DiskConfig.mdx' + +@include 'builder/vsphere/common/DiskConfig-required.mdx' + +#### Optional + +@include 'builder/vsphere/common/DiskConfig-not-required.mdx' + ### vApp Options Configuration @include 'builder/vsphere/clone/vAppConfig-not-required.mdx' diff --git a/website/pages/docs/builders/vmware/vsphere-iso.mdx b/website/pages/docs/builders/vmware/vsphere-iso.mdx index 34c5db6f2..a6b06b6ec 100644 --- a/website/pages/docs/builders/vmware/vsphere-iso.mdx +++ b/website/pages/docs/builders/vmware/vsphere-iso.mdx @@ -186,6 +186,8 @@ iso_paths = [ @include 'builder/vsphere/iso/CreateConfig-not-required.mdx' +@include 'builder/vsphere/common/StorageConfig-not-required.mdx' + ### Network Adapter Configuration @include 'builder/vsphere/iso/NIC.mdx' @@ -198,13 +200,13 @@ iso_paths = [ ### Storage Configuration -@include 'builder/vsphere/iso/DiskConfig.mdx' +@include 'builder/vsphere/common/DiskConfig.mdx' -@include 'builder/vsphere/iso/DiskConfig-required.mdx' +@include 'builder/vsphere/common/DiskConfig-required.mdx' #### Optional -@include 'builder/vsphere/iso/DiskConfig-not-required.mdx' +@include 'builder/vsphere/common/DiskConfig-not-required.mdx' ### Export Configuration diff --git a/website/pages/partials/builder/vsphere/iso/DiskConfig-not-required.mdx b/website/pages/partials/builder/vsphere/common/DiskConfig-not-required.mdx similarity index 83% rename from website/pages/partials/builder/vsphere/iso/DiskConfig-not-required.mdx rename to website/pages/partials/builder/vsphere/common/DiskConfig-not-required.mdx index 8e31b90d4..f7267b405 100644 --- a/website/pages/partials/builder/vsphere/iso/DiskConfig-not-required.mdx +++ b/website/pages/partials/builder/vsphere/common/DiskConfig-not-required.mdx @@ -1,4 +1,4 @@ - + - `disk_thin_provisioned` (bool) - Enable VMDK thin provisioning for VM. Defaults to `false`. diff --git a/website/pages/partials/builder/vsphere/iso/DiskConfig-required.mdx b/website/pages/partials/builder/vsphere/common/DiskConfig-required.mdx similarity index 62% rename from website/pages/partials/builder/vsphere/iso/DiskConfig-required.mdx rename to website/pages/partials/builder/vsphere/common/DiskConfig-required.mdx index 83683c366..29a583222 100644 --- a/website/pages/partials/builder/vsphere/iso/DiskConfig-required.mdx +++ b/website/pages/partials/builder/vsphere/common/DiskConfig-required.mdx @@ -1,3 +1,3 @@ - + - `disk_size` (int64) - The size of the disk in MB. diff --git a/website/pages/partials/builder/vsphere/iso/DiskConfig.mdx b/website/pages/partials/builder/vsphere/common/DiskConfig.mdx similarity index 94% rename from website/pages/partials/builder/vsphere/iso/DiskConfig.mdx rename to website/pages/partials/builder/vsphere/common/DiskConfig.mdx index 988ce2819..44040b0f7 100644 --- a/website/pages/partials/builder/vsphere/iso/DiskConfig.mdx +++ b/website/pages/partials/builder/vsphere/common/DiskConfig.mdx @@ -1,4 +1,4 @@ - + Defines the disk storage for a VM. diff --git a/website/pages/partials/builder/vsphere/common/StorageConfig-not-required.mdx b/website/pages/partials/builder/vsphere/common/StorageConfig-not-required.mdx new file mode 100644 index 000000000..2146f4442 --- /dev/null +++ b/website/pages/partials/builder/vsphere/common/StorageConfig-not-required.mdx @@ -0,0 +1,8 @@ + + +- `disk_controller_type` ([]string) - Set VM disk controller type. Example `lsilogic`, `pvscsi`, `nvme`, or `scsi`. Use a list to define additional controllers. + Defaults to `lsilogic`. See + [SCSI, SATA, and NVMe Storage Controller Conditions, Limitations, and Compatibility](https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-5872D173-A076-42FE-8D0B-9DB0EB0E7362.html#GUID-5872D173-A076-42FE-8D0B-9DB0EB0E7362) + for additional details. + +- `storage` ([]DiskConfig) - Configures a collection of one or more disks to be provisioned along with the VM. See the [Storage Configuration](#storage-configuration). diff --git a/website/pages/partials/builder/vsphere/iso/CreateConfig-not-required.mdx b/website/pages/partials/builder/vsphere/iso/CreateConfig-not-required.mdx index a69992f04..cd2ddc28d 100644 --- a/website/pages/partials/builder/vsphere/iso/CreateConfig-not-required.mdx +++ b/website/pages/partials/builder/vsphere/iso/CreateConfig-not-required.mdx @@ -9,13 +9,6 @@ here](https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html) for a full list of possible values. -- `disk_controller_type` ([]string) - Set VM disk controller type. Example `lsilogic`, `pvscsi`, `nvme`, or `scsi`. Use a list to define additional controllers. - Defaults to `lsilogic`. See - [SCSI, SATA, and NVMe Storage Controller Conditions, Limitations, and Compatibility](https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-5872D173-A076-42FE-8D0B-9DB0EB0E7362.html#GUID-5872D173-A076-42FE-8D0B-9DB0EB0E7362) - for additional details. - -- `storage` ([]DiskConfig) - A collection of one or more disks to be provisioned along with the VM. - - `network_adapters` ([]NIC) - Network adapters - `usb_controller` ([]string) - Create USB controllers for the virtual machine. "usb" for a usb 2.0 controller. "xhci" for a usb 3.0 controller. There can only be at most one of each.