add config opt to additional storage to cloned vm
This commit is contained in:
parent
aff33f057a
commit
3b523e147e
|
@ -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},
|
||||
|
|
|
@ -45,10 +45,12 @@ type CloneConfig struct {
|
|||
// 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"`
|
||||
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)
|
||||
|
|
|
@ -3,6 +3,7 @@ package clone
|
|||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer/builder/vsphere/common"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
|
@ -16,6 +17,8 @@ type FlatCloneConfig 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"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatCloneConfig.
|
||||
|
@ -37,6 +40,8 @@ func (*FlatCloneConfig) 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())},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package clone
|
|||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer/packer-plugin-sdk/template/config"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
|
@ -96,7 +97,7 @@ func (*FlatGlobalRoutingSettings) HCL2Spec() map[string]hcldec.Spec {
|
|||
type FlatLinuxOptions struct {
|
||||
Domain *string `mapstructure:"domain" cty:"domain" hcl:"domain"`
|
||||
Hostname *string `mapstructure:"host_name" cty:"host_name" hcl:"host_name"`
|
||||
HWClockUTC *bool `mapstructure:"hw_clock_utc" cty:"hw_clock_utc" hcl:"hw_clock_utc"`
|
||||
HWClockUTC *config.Trilean `mapstructure:"hw_clock_utc" cty:"hw_clock_utc" hcl:"hw_clock_utc"`
|
||||
Timezone *string `mapstructure:"time_zone" cty:"time_zone" hcl:"time_zone"`
|
||||
}
|
||||
|
||||
|
@ -114,7 +115,7 @@ func (*FlatLinuxOptions) HCL2Spec() map[string]hcldec.Spec {
|
|||
s := map[string]hcldec.Spec{
|
||||
"domain": &hcldec.AttrSpec{Name: "domain", Type: cty.String, Required: false},
|
||||
"host_name": &hcldec.AttrSpec{Name: "host_name", Type: cty.String, Required: false},
|
||||
"hw_clock_utc": &hcldec.AttrSpec{Name: "hw_clock_utc", Type: cty.Bool, Required: false},
|
||||
"hw_clock_utc": &hcldec.AttrSpec{Name: "hw_clock_utc", Type: cty.Number, Required: false},
|
||||
"time_zone": &hcldec.AttrSpec{Name: "time_zone", Type: cty.String, Required: false},
|
||||
}
|
||||
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
|
||||
Annotation string
|
||||
VAppProperties map[string]string
|
||||
StorageConfig StorageConfig
|
||||
}
|
||||
|
||||
type HardwareConfig struct {
|
||||
|
@ -96,6 +97,7 @@ type HardwareConfig struct {
|
|||
VGPUProfile string
|
||||
Firmware string
|
||||
ForceBIOSSetup bool
|
||||
StorageConfig StorageConfig
|
||||
}
|
||||
|
||||
type NIC struct {
|
||||
|
@ -106,8 +108,6 @@ type NIC struct {
|
|||
}
|
||||
|
||||
type CreateConfig struct {
|
||||
DiskControllerType []string // example: "scsi", "pvscsi", "nvme", "lsilogic"
|
||||
|
||||
Annotation string
|
||||
Name string
|
||||
Folder string
|
||||
|
@ -119,14 +119,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 +200,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 +229,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 +336,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 {
|
||||
|
@ -508,6 +521,76 @@ func (vm *VirtualMachineDriver) Configure(config *HardwareConfig) error {
|
|||
|
||||
confSpec.CpuHotAddEnabled = &config.CpuHotAddEnabled
|
||||
confSpec.MemoryHotAddEnabled = &config.MemoryHotAddEnabled
|
||||
//
|
||||
//if len(config.StorageConfig.Storage) > 0 {
|
||||
// ds, err := vm.vm.Device(vm.driver.ctx)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// vd := ds.SelectByType((*types.VirtualDisk)(nil))
|
||||
// vc := ds.SelectByType((*types.VirtualController)(nil))
|
||||
//
|
||||
// // Use existing devices to avoid wrong configuration
|
||||
// devices := object.VirtualDeviceList{}
|
||||
// devices = append(devices, vd...)
|
||||
// devices = append(devices, vc...)
|
||||
//
|
||||
// newDevices := object.VirtualDeviceList{}
|
||||
//
|
||||
// // Adds new controllers
|
||||
// var controllers []types.BaseVirtualController
|
||||
// for _, controllerType := range config.StorageConfig.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 err
|
||||
// }
|
||||
// devices = append(devices, device)
|
||||
// newDevices = append(newDevices, device)
|
||||
// name := devices.Name(device)
|
||||
// log.Printf("MOSS controller name %s", name)
|
||||
// controller, err := devices.FindDiskController(name)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// controllers = append(controllers, controller)
|
||||
// }
|
||||
//
|
||||
// for _, dc := range config.StorageConfig.Storage {
|
||||
// key := devices.NewKey()
|
||||
// disk := &types.VirtualDisk{
|
||||
// VirtualDevice: types.VirtualDevice{
|
||||
// Key: key,
|
||||
// Backing: &types.VirtualDiskFlatVer2BackingInfo{
|
||||
// DiskMode: string(types.VirtualDiskModePersistent),
|
||||
// ThinProvisioned: types.NewBool(dc.DiskThinProvisioned),
|
||||
// EagerlyScrub: types.NewBool(dc.DiskEagerlyScrub),
|
||||
// },
|
||||
// },
|
||||
// CapacityInKB: dc.DiskSize * 1024,
|
||||
// }
|
||||
//
|
||||
// log.Printf("MOSS device key %d", key)
|
||||
//
|
||||
// devices.AssignController(disk, controllers[dc.ControllerIndex])
|
||||
// newDevices = append(newDevices, disk)
|
||||
// }
|
||||
// //devices, err = config.StorageConfig.AddStorageDevices(devices)
|
||||
// //if err != nil {
|
||||
// // return err
|
||||
// //}
|
||||
//
|
||||
// devicesConfigSpec, err := newDevices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// confSpec.DeviceChange = append(confSpec.DeviceChange, devicesConfigSpec...)
|
||||
//}
|
||||
|
||||
if config.VideoRAM != 0 {
|
||||
devices, err := vm.vm.Device(vm.driver.ctx)
|
||||
|
@ -616,24 +699,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 +914,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")
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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
|
||||
|
@ -149,13 +66,7 @@ type CreateConfig struct {
|
|||
// 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"`
|
||||
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,8 +158,10 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste
|
|||
}
|
||||
|
||||
vm, err := d.CreateVM(&driver.CreateConfig{
|
||||
DiskControllerType: s.Config.DiskControllerType,
|
||||
StorageConfig: driver.StorageConfig{
|
||||
DiskControllerType: s.Config.StorageConfig.DiskControllerType,
|
||||
Storage: disks,
|
||||
},
|
||||
Annotation: s.Config.Notes,
|
||||
Name: s.Location.VMName,
|
||||
Folder: s.Location.Folder,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
// 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"
|
||||
)
|
||||
|
||||
|
@ -12,7 +13,7 @@ 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"`
|
||||
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"`
|
||||
|
@ -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 {
|
||||
|
|
|
@ -24,7 +24,7 @@ func TestCreateConfig_Prepare(t *testing.T) {
|
|||
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,26 +38,30 @@ func TestCreateConfig_Prepare(t *testing.T) {
|
|||
{
|
||||
name: "Storage validate disk_size",
|
||||
config: &CreateConfig{
|
||||
Storage: []DiskConfig{
|
||||
StorageConfig: common.StorageConfig{
|
||||
Storage: []common.DiskConfig{
|
||||
{
|
||||
DiskSize: 0,
|
||||
DiskThinProvisioned: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
fail: true,
|
||||
expectedErrMsg: "storage[0].'disk_size' is required",
|
||||
},
|
||||
{
|
||||
name: "Storage validate disk_controller_index",
|
||||
config: &CreateConfig{
|
||||
Storage: []DiskConfig{
|
||||
StorageConfig: common.StorageConfig{
|
||||
Storage: []common.DiskConfig{
|
||||
{
|
||||
DiskSize: 32768,
|
||||
DiskControllerIndex: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
fail: true,
|
||||
expectedErrMsg: "storage[0].'disk_controller_index' references an unknown disk controller",
|
||||
},
|
||||
|
@ -296,13 +300,15 @@ func createConfig() *CreateConfig {
|
|||
return &CreateConfig{
|
||||
Version: 1,
|
||||
GuestOSType: "ubuntu64Guest",
|
||||
StorageConfig: common.StorageConfig{
|
||||
DiskControllerType: []string{"pvscsi"},
|
||||
Storage: []DiskConfig{
|
||||
Storage: []common.DiskConfig{
|
||||
{
|
||||
DiskSize: 32768,
|
||||
DiskThinProvisioned: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
NICs: []NIC{
|
||||
{
|
||||
Network: "VM Network",
|
||||
|
@ -324,7 +330,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,8 +340,10 @@ func driverCreateConfig(config *CreateConfig, location *common.LocationConfig) *
|
|||
}
|
||||
|
||||
return &driver.CreateConfig{
|
||||
DiskControllerType: config.DiskControllerType,
|
||||
StorageConfig: driver.StorageConfig{
|
||||
DiskControllerType: config.StorageConfig.DiskControllerType,
|
||||
Storage: disks,
|
||||
},
|
||||
Annotation: config.Notes,
|
||||
Name: location.VMName,
|
||||
Folder: location.Folder,
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<!-- 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_eagerly_scrub` (bool) - Enable VMDK eager scrubbing for VM. Defaults to `false`.
|
||||
|
||||
- `disk_controller_index` (int) - The assigned disk controller. Defaults to the first one (0)
|
|
@ -0,0 +1,3 @@
|
|||
<!-- 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.
|
|
@ -0,0 +1,74 @@
|
|||
<!-- 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.
|
||||
|
||||
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
|
||||
}
|
||||
```
|
|
@ -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)
|
||||
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.
|
||||
|
|
Loading…
Reference in New Issue