Merge pull request #10287 from hashicorp/implement_9990
Add configuration options to add additional storage to a cloned vm
This commit is contained in:
commit
60e62bbb51
|
@ -37,6 +37,8 @@ type FlatConfig struct {
|
||||||
MacAddress *string `mapstructure:"mac_address" cty:"mac_address" hcl:"mac_address"`
|
MacAddress *string `mapstructure:"mac_address" cty:"mac_address" hcl:"mac_address"`
|
||||||
Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"`
|
Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"`
|
||||||
VAppConfig *FlatvAppConfig `mapstructure:"vapp" cty:"vapp" hcl:"vapp"`
|
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"`
|
VMName *string `mapstructure:"vm_name" cty:"vm_name" hcl:"vm_name"`
|
||||||
Folder *string `mapstructure:"folder" cty:"folder" hcl:"folder"`
|
Folder *string `mapstructure:"folder" cty:"folder" hcl:"folder"`
|
||||||
Cluster *string `mapstructure:"cluster" cty:"cluster" hcl:"cluster"`
|
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},
|
"mac_address": &hcldec.AttrSpec{Name: "mac_address", Type: cty.String, Required: false},
|
||||||
"notes": &hcldec.AttrSpec{Name: "notes", 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())},
|
"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},
|
"vm_name": &hcldec.AttrSpec{Name: "vm_name", Type: cty.String, Required: false},
|
||||||
"folder": &hcldec.AttrSpec{Name: "folder", 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},
|
"cluster": &hcldec.AttrSpec{Name: "cluster", Type: cty.String, Required: false},
|
||||||
|
|
|
@ -44,11 +44,13 @@ type CloneConfig struct {
|
||||||
// Set the vApp Options to a virtual machine.
|
// Set the vApp Options to a virtual machine.
|
||||||
// See the [vApp Options Configuration](/docs/builders/vmware/vsphere-clone#vapp-options-configuration)
|
// See the [vApp Options Configuration](/docs/builders/vmware/vsphere-clone#vapp-options-configuration)
|
||||||
// to know the available options and how to use it.
|
// 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 {
|
func (c *CloneConfig) Prepare() []error {
|
||||||
var errs []error
|
var errs []error
|
||||||
|
errs = append(errs, c.StorageConfig.Prepare()...)
|
||||||
|
|
||||||
if c.Template == "" {
|
if c.Template == "" {
|
||||||
errs = append(errs, fmt.Errorf("'template' is required"))
|
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
|
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{
|
vm, err := template.Clone(ctx, &driver.CloneConfig{
|
||||||
Name: s.Location.VMName,
|
Name: s.Location.VMName,
|
||||||
Folder: s.Location.Folder,
|
Folder: s.Location.Folder,
|
||||||
|
@ -101,6 +113,10 @@ func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multist
|
||||||
MacAddress: s.Config.MacAddress,
|
MacAddress: s.Config.MacAddress,
|
||||||
Annotation: s.Config.Notes,
|
Annotation: s.Config.Notes,
|
||||||
VAppProperties: s.Config.VAppConfig.Properties,
|
VAppProperties: s.Config.VAppConfig.Properties,
|
||||||
|
StorageConfig: driver.StorageConfig{
|
||||||
|
DiskControllerType: s.Config.StorageConfig.DiskControllerType,
|
||||||
|
Storage: disks,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
|
|
@ -3,19 +3,22 @@ package clone
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hashicorp/hcl/v2/hcldec"
|
"github.com/hashicorp/hcl/v2/hcldec"
|
||||||
|
"github.com/hashicorp/packer/builder/vsphere/common"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FlatCloneConfig is an auto-generated flat version of CloneConfig.
|
// FlatCloneConfig is an auto-generated flat version of CloneConfig.
|
||||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||||
type FlatCloneConfig struct {
|
type FlatCloneConfig struct {
|
||||||
Template *string `mapstructure:"template" cty:"template" hcl:"template"`
|
Template *string `mapstructure:"template" cty:"template" hcl:"template"`
|
||||||
DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size" hcl:"disk_size"`
|
DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size" hcl:"disk_size"`
|
||||||
LinkedClone *bool `mapstructure:"linked_clone" cty:"linked_clone" hcl:"linked_clone"`
|
LinkedClone *bool `mapstructure:"linked_clone" cty:"linked_clone" hcl:"linked_clone"`
|
||||||
Network *string `mapstructure:"network" cty:"network" hcl:"network"`
|
Network *string `mapstructure:"network" cty:"network" hcl:"network"`
|
||||||
MacAddress *string `mapstructure:"mac_address" cty:"mac_address" hcl:"mac_address"`
|
MacAddress *string `mapstructure:"mac_address" cty:"mac_address" hcl:"mac_address"`
|
||||||
Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"`
|
Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"`
|
||||||
VAppConfig *FlatvAppConfig `mapstructure:"vapp" cty:"vapp" hcl:"vapp"`
|
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.
|
// 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.
|
// The decoded values from this spec will then be applied to a FlatCloneConfig.
|
||||||
func (*FlatCloneConfig) HCL2Spec() map[string]hcldec.Spec {
|
func (*FlatCloneConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
s := map[string]hcldec.Spec{
|
s := map[string]hcldec.Spec{
|
||||||
"template": &hcldec.AttrSpec{Name: "template", Type: cty.String, Required: false},
|
"template": &hcldec.AttrSpec{Name: "template", Type: cty.String, Required: false},
|
||||||
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, 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},
|
"linked_clone": &hcldec.AttrSpec{Name: "linked_clone", Type: cty.Bool, Required: false},
|
||||||
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
|
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
|
||||||
"mac_address": &hcldec.AttrSpec{Name: "mac_address", 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},
|
"notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false},
|
||||||
"vapp": &hcldec.BlockSpec{TypeName: "vapp", Nested: hcldec.ObjectSpec((*FlatvAppConfig)(nil).HCL2Spec())},
|
"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
|
return s
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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")
|
||||||
|
}
|
|
@ -79,6 +79,7 @@ type CloneConfig struct {
|
||||||
MacAddress string
|
MacAddress string
|
||||||
Annotation string
|
Annotation string
|
||||||
VAppProperties map[string]string
|
VAppProperties map[string]string
|
||||||
|
StorageConfig StorageConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type HardwareConfig struct {
|
type HardwareConfig struct {
|
||||||
|
@ -106,8 +107,6 @@ type NIC struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateConfig struct {
|
type CreateConfig struct {
|
||||||
DiskControllerType []string // example: "scsi", "pvscsi", "nvme", "lsilogic"
|
|
||||||
|
|
||||||
Annotation string
|
Annotation string
|
||||||
Name string
|
Name string
|
||||||
Folder string
|
Folder string
|
||||||
|
@ -119,14 +118,7 @@ type CreateConfig struct {
|
||||||
NICs []NIC
|
NICs []NIC
|
||||||
USBController []string
|
USBController []string
|
||||||
Version uint // example: 10
|
Version uint // example: 10
|
||||||
Storage []Disk
|
StorageConfig StorageConfig
|
||||||
}
|
|
||||||
|
|
||||||
type Disk struct {
|
|
||||||
DiskSize int64
|
|
||||||
DiskEagerlyScrub bool
|
|
||||||
DiskThinProvisioned bool
|
|
||||||
ControllerIndex int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *VCenterDriver) NewVM(ref *types.ManagedObjectReference) VirtualMachine {
|
func (d *VCenterDriver) NewVM(ref *types.ManagedObjectReference) VirtualMachine {
|
||||||
|
@ -207,11 +199,12 @@ func (d *VCenterDriver) CreateVM(config *CreateConfig) (VirtualMachine, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
devices := object.VirtualDeviceList{}
|
devices := object.VirtualDeviceList{}
|
||||||
|
storageConfigSpec, err := config.StorageConfig.AddStorageDevices(devices)
|
||||||
devices, err = addDisk(d, devices, config)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
createSpec.DeviceChange = append(createSpec.DeviceChange, storageConfigSpec...)
|
||||||
|
|
||||||
devices, err = addNetwork(d, devices, config)
|
devices, err = addNetwork(d, devices, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -235,10 +228,11 @@ func (d *VCenterDriver) CreateVM(config *CreateConfig) (VirtualMachine, error) {
|
||||||
devices = append(devices, usb)
|
devices = append(devices, usb)
|
||||||
}
|
}
|
||||||
|
|
||||||
createSpec.DeviceChange, err = devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
|
devicesConfigSpec, err := devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
createSpec.DeviceChange = append(createSpec.DeviceChange, devicesConfigSpec...)
|
||||||
|
|
||||||
createSpec.Files = &types.VirtualMachineFileInfo{
|
createSpec.Files = &types.VirtualMachineFileInfo{
|
||||||
VmPathName: fmt.Sprintf("[%s]", datastore.Name()),
|
VmPathName: fmt.Sprintf("[%s]", datastore.Name()),
|
||||||
|
@ -341,6 +335,24 @@ func (vm *VirtualMachineDriver) Clone(ctx context.Context, config *CloneConfig)
|
||||||
configSpec.Annotation = config.Annotation
|
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 != "" {
|
if config.Network != "" {
|
||||||
net, err := vm.driver.FindNetwork(config.Network)
|
net, err := vm.driver.FindNetwork(config.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -616,24 +628,6 @@ func (vm *VirtualMachineDriver) ResizeDisk(diskSize int64) error {
|
||||||
return err
|
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 {
|
func (vm *VirtualMachineDriver) PowerOn() error {
|
||||||
task, err := vm.vm.PowerOn(vm.driver.ctx)
|
task, err := vm.vm.PowerOn(vm.driver.ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -849,55 +843,6 @@ func (vm *VirtualMachineDriver) GetDir() (string, error) {
|
||||||
return "", fmt.Errorf("cannot find '%s'", vmxName)
|
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) {
|
func addNetwork(d *VCenterDriver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) {
|
||||||
if len(config.NICs) == 0 {
|
if len(config.NICs) == 0 {
|
||||||
return nil, errors.New("no network adapters have been defined")
|
return nil, errors.New("no network adapters have been defined")
|
||||||
|
|
|
@ -33,7 +33,7 @@ type FlatConfig struct {
|
||||||
Version *uint `mapstructure:"vm_version" cty:"vm_version" hcl:"vm_version"`
|
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"`
|
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"`
|
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"`
|
NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters" hcl:"network_adapters"`
|
||||||
USBController []string `mapstructure:"usb_controller" cty:"usb_controller" hcl:"usb_controller"`
|
USBController []string `mapstructure:"usb_controller" cty:"usb_controller" hcl:"usb_controller"`
|
||||||
Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"`
|
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},
|
"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},
|
"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},
|
"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())},
|
"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},
|
"usb_controller": &hcldec.AttrSpec{Name: "usb_controller", Type: cty.List(cty.String), Required: false},
|
||||||
"notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false},
|
"notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//go:generate struct-markdown
|
//go:generate struct-markdown
|
||||||
//go:generate mapstructure-to-hcl2 -type NIC,CreateConfig,DiskConfig
|
//go:generate mapstructure-to-hcl2 -type NIC,CreateConfig
|
||||||
|
|
||||||
package iso
|
package iso
|
||||||
|
|
||||||
|
@ -56,89 +56,6 @@ type NIC struct {
|
||||||
Passthrough *bool `mapstructure:"passthrough"`
|
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 {
|
type CreateConfig struct {
|
||||||
// Set VM hardware version. Defaults to the most current VM hardware
|
// Set VM hardware version. Defaults to the most current VM hardware
|
||||||
// version supported by vCenter. See
|
// version supported by vCenter. See
|
||||||
|
@ -148,14 +65,8 @@ type CreateConfig struct {
|
||||||
// Set VM OS type. Defaults to `otherGuest`. See [
|
// Set VM OS type. Defaults to `otherGuest`. See [
|
||||||
// here](https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html)
|
// here](https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html)
|
||||||
// for a full list of possible values.
|
// for a full list of possible values.
|
||||||
GuestOSType string `mapstructure:"guest_os_type"`
|
GuestOSType string `mapstructure:"guest_os_type"`
|
||||||
// Set VM disk controller type. Example `lsilogic`, `pvscsi`, `nvme`, or `scsi`. Use a list to define additional controllers.
|
StorageConfig common.StorageConfig `mapstructure:",squash"`
|
||||||
// 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"`
|
|
||||||
// Network adapters
|
// Network adapters
|
||||||
NICs []NIC `mapstructure:"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.
|
// 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 {
|
func (c *CreateConfig) Prepare() []error {
|
||||||
var errs []error
|
var errs []error
|
||||||
|
|
||||||
// there should be at least one
|
if len(c.StorageConfig.DiskControllerType) == 0 {
|
||||||
if len(c.DiskControllerType) == 0 {
|
c.StorageConfig.DiskControllerType = append(c.StorageConfig.DiskControllerType, "")
|
||||||
c.DiskControllerType = append(c.DiskControllerType, "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.Storage) > 0 {
|
// there should be at least one
|
||||||
for i, storage := range c.Storage {
|
if len(c.StorageConfig.Storage) == 0 {
|
||||||
if storage.DiskSize == 0 {
|
errs = append(errs, fmt.Errorf("no storage devices have been defined"))
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
errs = append(errs, c.StorageConfig.Prepare()...)
|
||||||
|
|
||||||
if c.GuestOSType == "" {
|
if c.GuestOSType == "" {
|
||||||
c.GuestOSType = "otherGuest"
|
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
|
// add disk as the first drive for backwards compatibility if the type is defined
|
||||||
var disks []driver.Disk
|
var disks []driver.Disk
|
||||||
for _, disk := range s.Config.Storage {
|
for _, disk := range s.Config.StorageConfig.Storage {
|
||||||
disks = append(disks, driver.Disk{
|
disks = append(disks, driver.Disk{
|
||||||
DiskSize: disk.DiskSize,
|
DiskSize: disk.DiskSize,
|
||||||
DiskEagerlyScrub: disk.DiskEagerlyScrub,
|
DiskEagerlyScrub: disk.DiskEagerlyScrub,
|
||||||
|
@ -253,19 +158,21 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste
|
||||||
}
|
}
|
||||||
|
|
||||||
vm, err := d.CreateVM(&driver.CreateConfig{
|
vm, err := d.CreateVM(&driver.CreateConfig{
|
||||||
DiskControllerType: s.Config.DiskControllerType,
|
StorageConfig: driver.StorageConfig{
|
||||||
Storage: disks,
|
DiskControllerType: s.Config.StorageConfig.DiskControllerType,
|
||||||
Annotation: s.Config.Notes,
|
Storage: disks,
|
||||||
Name: s.Location.VMName,
|
},
|
||||||
Folder: s.Location.Folder,
|
Annotation: s.Config.Notes,
|
||||||
Cluster: s.Location.Cluster,
|
Name: s.Location.VMName,
|
||||||
Host: s.Location.Host,
|
Folder: s.Location.Folder,
|
||||||
ResourcePool: s.Location.ResourcePool,
|
Cluster: s.Location.Cluster,
|
||||||
Datastore: s.Location.Datastore,
|
Host: s.Location.Host,
|
||||||
GuestOS: s.Config.GuestOSType,
|
ResourcePool: s.Location.ResourcePool,
|
||||||
NICs: networkCards,
|
Datastore: s.Location.Datastore,
|
||||||
USBController: s.Config.USBController,
|
GuestOS: s.Config.GuestOSType,
|
||||||
Version: s.Config.Version,
|
NICs: networkCards,
|
||||||
|
USBController: s.Config.USBController,
|
||||||
|
Version: s.Config.Version,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", fmt.Errorf("error creating vm: %v", err))
|
state.Put("error", fmt.Errorf("error creating vm: %v", err))
|
||||||
|
|
|
@ -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
|
package iso
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hashicorp/hcl/v2/hcldec"
|
"github.com/hashicorp/hcl/v2/hcldec"
|
||||||
|
"github.com/hashicorp/packer/builder/vsphere/common"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FlatCreateConfig is an auto-generated flat version of CreateConfig.
|
// FlatCreateConfig is an auto-generated flat version of CreateConfig.
|
||||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||||
type FlatCreateConfig struct {
|
type FlatCreateConfig struct {
|
||||||
Version *uint `mapstructure:"vm_version" cty:"vm_version" hcl:"vm_version"`
|
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"`
|
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"`
|
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"`
|
NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters" hcl:"network_adapters"`
|
||||||
USBController []string `mapstructure:"usb_controller" cty:"usb_controller" hcl:"usb_controller"`
|
USBController []string `mapstructure:"usb_controller" cty:"usb_controller" hcl:"usb_controller"`
|
||||||
Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"`
|
Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlatMapstructure returns a new FlatCreateConfig.
|
// 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},
|
"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},
|
"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},
|
"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())},
|
"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},
|
"usb_controller": &hcldec.AttrSpec{Name: "usb_controller", Type: cty.List(cty.String), Required: false},
|
||||||
"notes": &hcldec.AttrSpec{Name: "notes", Type: 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
|
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.
|
// FlatNIC is an auto-generated flat version of NIC.
|
||||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||||
type FlatNIC struct {
|
type FlatNIC struct {
|
||||||
|
|
|
@ -17,14 +17,23 @@ import (
|
||||||
|
|
||||||
func TestCreateConfig_Prepare(t *testing.T) {
|
func TestCreateConfig_Prepare(t *testing.T) {
|
||||||
// Empty config - check defaults
|
// 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 {
|
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" {
|
if config.GuestOSType != "otherGuest" {
|
||||||
t.Fatalf("GuestOSType should default to '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")
|
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",
|
name: "Storage validate disk_size",
|
||||||
config: &CreateConfig{
|
config: &CreateConfig{
|
||||||
Storage: []DiskConfig{
|
StorageConfig: common.StorageConfig{
|
||||||
{
|
Storage: []common.DiskConfig{
|
||||||
DiskSize: 0,
|
{
|
||||||
DiskThinProvisioned: true,
|
DiskSize: 0,
|
||||||
|
DiskThinProvisioned: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -51,10 +62,12 @@ func TestCreateConfig_Prepare(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "Storage validate disk_controller_index",
|
name: "Storage validate disk_controller_index",
|
||||||
config: &CreateConfig{
|
config: &CreateConfig{
|
||||||
Storage: []DiskConfig{
|
StorageConfig: common.StorageConfig{
|
||||||
{
|
Storage: []common.DiskConfig{
|
||||||
DiskSize: 32768,
|
{
|
||||||
DiskControllerIndex: 3,
|
DiskSize: 32768,
|
||||||
|
DiskControllerIndex: 3,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -65,6 +78,13 @@ func TestCreateConfig_Prepare(t *testing.T) {
|
||||||
name: "USBController validate 'usb' and 'xhci' can be set together",
|
name: "USBController validate 'usb' and 'xhci' can be set together",
|
||||||
config: &CreateConfig{
|
config: &CreateConfig{
|
||||||
USBController: []string{"usb", "xhci"},
|
USBController: []string{"usb", "xhci"},
|
||||||
|
StorageConfig: common.StorageConfig{
|
||||||
|
Storage: []common.DiskConfig{
|
||||||
|
{
|
||||||
|
DiskSize: 32768,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
fail: false,
|
fail: false,
|
||||||
},
|
},
|
||||||
|
@ -72,6 +92,13 @@ func TestCreateConfig_Prepare(t *testing.T) {
|
||||||
name: "USBController validate '1' and '0' can be set together",
|
name: "USBController validate '1' and '0' can be set together",
|
||||||
config: &CreateConfig{
|
config: &CreateConfig{
|
||||||
USBController: []string{"1", "0"},
|
USBController: []string{"1", "0"},
|
||||||
|
StorageConfig: common.StorageConfig{
|
||||||
|
Storage: []common.DiskConfig{
|
||||||
|
{
|
||||||
|
DiskSize: 32768,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
fail: false,
|
fail: false,
|
||||||
},
|
},
|
||||||
|
@ -79,6 +106,13 @@ func TestCreateConfig_Prepare(t *testing.T) {
|
||||||
name: "USBController validate 'true' and 'false' can be set together",
|
name: "USBController validate 'true' and 'false' can be set together",
|
||||||
config: &CreateConfig{
|
config: &CreateConfig{
|
||||||
USBController: []string{"true", "false"},
|
USBController: []string{"true", "false"},
|
||||||
|
StorageConfig: common.StorageConfig{
|
||||||
|
Storage: []common.DiskConfig{
|
||||||
|
{
|
||||||
|
DiskSize: 32768,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
fail: false,
|
fail: false,
|
||||||
},
|
},
|
||||||
|
@ -86,6 +120,13 @@ func TestCreateConfig_Prepare(t *testing.T) {
|
||||||
name: "USBController validate 'true' and 'usb' cannot be set together",
|
name: "USBController validate 'true' and 'usb' cannot be set together",
|
||||||
config: &CreateConfig{
|
config: &CreateConfig{
|
||||||
USBController: []string{"true", "usb"},
|
USBController: []string{"true", "usb"},
|
||||||
|
StorageConfig: common.StorageConfig{
|
||||||
|
Storage: []common.DiskConfig{
|
||||||
|
{
|
||||||
|
DiskSize: 32768,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
fail: true,
|
fail: true,
|
||||||
expectedErrMsg: "there can only be one usb controller and one xhci controller",
|
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",
|
name: "USBController validate '1' and 'usb' cannot be set together",
|
||||||
config: &CreateConfig{
|
config: &CreateConfig{
|
||||||
USBController: []string{"1", "usb"},
|
USBController: []string{"1", "usb"},
|
||||||
|
StorageConfig: common.StorageConfig{
|
||||||
|
Storage: []common.DiskConfig{
|
||||||
|
{
|
||||||
|
DiskSize: 32768,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
fail: true,
|
fail: true,
|
||||||
expectedErrMsg: "there can only be one usb controller and one xhci controller",
|
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",
|
name: "USBController validate 'xhci' cannot be set more that once",
|
||||||
config: &CreateConfig{
|
config: &CreateConfig{
|
||||||
USBController: []string{"xhci", "xhci"},
|
USBController: []string{"xhci", "xhci"},
|
||||||
|
StorageConfig: common.StorageConfig{
|
||||||
|
Storage: []common.DiskConfig{
|
||||||
|
{
|
||||||
|
DiskSize: 32768,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
fail: true,
|
fail: true,
|
||||||
expectedErrMsg: "there can only be one usb controller and one xhci controller",
|
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",
|
name: "USBController validate unknown value cannot be set",
|
||||||
config: &CreateConfig{
|
config: &CreateConfig{
|
||||||
USBController: []string{"unknown"},
|
USBController: []string{"unknown"},
|
||||||
|
StorageConfig: common.StorageConfig{
|
||||||
|
Storage: []common.DiskConfig{
|
||||||
|
{
|
||||||
|
DiskSize: 32768,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
fail: true,
|
fail: true,
|
||||||
expectedErrMsg: "usb_controller[0] references an unknown usb controller",
|
expectedErrMsg: "usb_controller[0] references an unknown usb controller",
|
||||||
|
@ -127,7 +189,7 @@ func TestCreateConfig_Prepare(t *testing.T) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if len(errs) != 0 {
|
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 {
|
func createConfig() *CreateConfig {
|
||||||
return &CreateConfig{
|
return &CreateConfig{
|
||||||
Version: 1,
|
Version: 1,
|
||||||
GuestOSType: "ubuntu64Guest",
|
GuestOSType: "ubuntu64Guest",
|
||||||
DiskControllerType: []string{"pvscsi"},
|
StorageConfig: common.StorageConfig{
|
||||||
Storage: []DiskConfig{
|
DiskControllerType: []string{"pvscsi"},
|
||||||
{
|
Storage: []common.DiskConfig{
|
||||||
DiskSize: 32768,
|
{
|
||||||
DiskThinProvisioned: true,
|
DiskSize: 32768,
|
||||||
|
DiskThinProvisioned: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
NICs: []NIC{
|
NICs: []NIC{
|
||||||
|
@ -324,7 +388,7 @@ func driverCreateConfig(config *CreateConfig, location *common.LocationConfig) *
|
||||||
}
|
}
|
||||||
|
|
||||||
var disks []driver.Disk
|
var disks []driver.Disk
|
||||||
for _, disk := range config.Storage {
|
for _, disk := range config.StorageConfig.Storage {
|
||||||
disks = append(disks, driver.Disk{
|
disks = append(disks, driver.Disk{
|
||||||
DiskSize: disk.DiskSize,
|
DiskSize: disk.DiskSize,
|
||||||
DiskEagerlyScrub: disk.DiskEagerlyScrub,
|
DiskEagerlyScrub: disk.DiskEagerlyScrub,
|
||||||
|
@ -334,18 +398,20 @@ func driverCreateConfig(config *CreateConfig, location *common.LocationConfig) *
|
||||||
}
|
}
|
||||||
|
|
||||||
return &driver.CreateConfig{
|
return &driver.CreateConfig{
|
||||||
DiskControllerType: config.DiskControllerType,
|
StorageConfig: driver.StorageConfig{
|
||||||
Storage: disks,
|
DiskControllerType: config.StorageConfig.DiskControllerType,
|
||||||
Annotation: config.Notes,
|
Storage: disks,
|
||||||
Name: location.VMName,
|
},
|
||||||
Folder: location.Folder,
|
Annotation: config.Notes,
|
||||||
Cluster: location.Cluster,
|
Name: location.VMName,
|
||||||
Host: location.Host,
|
Folder: location.Folder,
|
||||||
ResourcePool: location.ResourcePool,
|
Cluster: location.Cluster,
|
||||||
Datastore: location.Datastore,
|
Host: location.Host,
|
||||||
GuestOS: config.GuestOSType,
|
ResourcePool: location.ResourcePool,
|
||||||
NICs: networkCards,
|
Datastore: location.Datastore,
|
||||||
USBController: config.USBController,
|
GuestOS: config.GuestOSType,
|
||||||
Version: config.Version,
|
NICs: networkCards,
|
||||||
|
USBController: config.USBController,
|
||||||
|
Version: config.Version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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/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
|
### vApp Options Configuration
|
||||||
|
|
||||||
@include 'builder/vsphere/clone/vAppConfig-not-required.mdx'
|
@include 'builder/vsphere/clone/vAppConfig-not-required.mdx'
|
||||||
|
|
|
@ -186,6 +186,8 @@ iso_paths = [
|
||||||
|
|
||||||
@include 'builder/vsphere/iso/CreateConfig-not-required.mdx'
|
@include 'builder/vsphere/iso/CreateConfig-not-required.mdx'
|
||||||
|
|
||||||
|
@include 'builder/vsphere/common/StorageConfig-not-required.mdx'
|
||||||
|
|
||||||
### Network Adapter Configuration
|
### Network Adapter Configuration
|
||||||
|
|
||||||
@include 'builder/vsphere/iso/NIC.mdx'
|
@include 'builder/vsphere/iso/NIC.mdx'
|
||||||
|
@ -198,13 +200,13 @@ iso_paths = [
|
||||||
|
|
||||||
### Storage Configuration
|
### 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
|
#### Optional
|
||||||
|
|
||||||
@include 'builder/vsphere/iso/DiskConfig-not-required.mdx'
|
@include 'builder/vsphere/common/DiskConfig-not-required.mdx'
|
||||||
|
|
||||||
### Export Configuration
|
### Export Configuration
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- Code generated from the comments of the DiskConfig struct in builder/vsphere/iso/step_create.go; DO NOT EDIT MANUALLY -->
|
<!-- Code generated from the comments of the DiskConfig struct in builder/vsphere/common/storage_config.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
- `disk_thin_provisioned` (bool) - Enable VMDK thin provisioning for VM. Defaults to `false`.
|
- `disk_thin_provisioned` (bool) - Enable VMDK thin provisioning for VM. Defaults to `false`.
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
<!-- Code generated from the comments of the DiskConfig struct in builder/vsphere/iso/step_create.go; DO NOT EDIT MANUALLY -->
|
<!-- Code generated from the comments of the DiskConfig struct in builder/vsphere/common/storage_config.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
- `disk_size` (int64) - The size of the disk in MB.
|
- `disk_size` (int64) - The size of the disk in MB.
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- Code generated from the comments of the DiskConfig struct in builder/vsphere/iso/step_create.go; DO NOT EDIT MANUALLY -->
|
<!-- Code generated from the comments of the DiskConfig struct in builder/vsphere/common/storage_config.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
Defines the disk storage for a VM.
|
Defines the disk storage for a VM.
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<!-- Code generated from the comments of the StorageConfig struct in builder/vsphere/common/storage_config.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
|
- `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).
|
|
@ -9,13 +9,6 @@
|
||||||
here](https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html)
|
here](https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html)
|
||||||
for a full list of possible values.
|
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
|
- `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.
|
- `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.
|
||||||
|
|
Loading…
Reference in New Issue