mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-08-22 19:38:35 +00:00
feat(vm): efi disk, cpu numa (#384)
* efi disks support * make size a string * add cpu numa support * add docs * fix description * string size fixes (cherry picked from commit 254724d1d10c5191d294f0377adac49ad41dc880) * fix lints * fix(vm): replace `size` with `type` for efi disk also - add support for `pre-enrolled-keys` - add example - fix handling of `numa` flag when it's not in the template - cleanup linter errors --------- Co-authored-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
parent
23a519475d
commit
e9a74e9037
@ -165,6 +165,7 @@ output "ubuntu_vm_public_key" {
|
||||
protection for AMD models.
|
||||
- `hotplugged` - (Optional) The number of hotplugged vCPUs (defaults
|
||||
to `0`).
|
||||
- `numa` - (Boolean) Enable/disable NUMA. (default to `false`)
|
||||
- `sockets` - (Optional) The number of CPU sockets (defaults to `1`).
|
||||
- `type` - (Optional) The emulated CPU type (defaults to `qemu64`).
|
||||
- `486` - Intel 486.
|
||||
@ -241,6 +242,19 @@ output "ubuntu_vm_public_key" {
|
||||
- `ssd` - (Optional) Whether to use an SSD emulation option for this disk (
|
||||
defaults to `false`). Note that SSD emulation is not supported on VirtIO
|
||||
Block drives.
|
||||
- `efi_disk` - (Optional) The efi disk device (required if `bios` is set
|
||||
to `ovmf`)
|
||||
- `datastore_id` (Optional) The identifier for the datastore to create
|
||||
the disk in (defaults to `local-lvm`).
|
||||
- `file_format` (Optional) The file format.
|
||||
- `type` (Optional) Size and type of the OVMF EFI disk. `4m` is newer and
|
||||
recommended, and required for Secure Boot. For backwards compatibility
|
||||
use `2m`. Ignored for VMs with cpu.architecture=`aarch64` (defaults
|
||||
to `2m`).
|
||||
- `pre_enrolled_keys` (Optional) Use am EFI vars template with
|
||||
distribution-specific and Microsoft Standard keys enrolled, if used with
|
||||
EFI type=`4m`. Ignored for VMs with cpu.architecture=`aarch64` (defaults
|
||||
to `false`).
|
||||
- `hostpci` - (Optional) A host PCI device mapping (multiple blocks supported).
|
||||
- `device` - (Required) The PCI device name for Proxmox, in form
|
||||
of `hostpciX` where `X` is a sequential number from 0 to 3.
|
||||
@ -284,7 +298,7 @@ output "ubuntu_vm_public_key" {
|
||||
- `user_data_file_id` - (Optional) The identifier for a file containing
|
||||
custom user data (conflicts with `user_account`).
|
||||
- `vendor_data_file_id` - (Optional) The identifier for a file containing
|
||||
all vendor data passed to the VM via cloud-init.
|
||||
all vendor data passed to the VM via cloud-init.
|
||||
- `meta_data_file_id` - (Optional) The identifier for a file containing
|
||||
all meta data passed to the VM via cloud-init.
|
||||
- `keyboard_layout` - (Optional) The keyboard layout (defaults to `en-us`).
|
||||
|
@ -9,6 +9,16 @@ resource "proxmox_virtual_environment_vm" "example_template" {
|
||||
|
||||
description = "Managed by Terraform"
|
||||
|
||||
cpu {
|
||||
numa = true
|
||||
}
|
||||
|
||||
efi_disk {
|
||||
datastore_id = local.datastore_id
|
||||
file_format = "raw"
|
||||
type = "4m"
|
||||
}
|
||||
|
||||
# disk {
|
||||
# datastore_id = local.datastore_id
|
||||
# file_id = proxmox_virtual_environment_file.ubuntu_cloud_image.id
|
||||
|
@ -82,9 +82,10 @@ type CustomCPUEmulation struct {
|
||||
|
||||
// CustomEFIDisk handles QEMU EFI disk parameters.
|
||||
type CustomEFIDisk struct {
|
||||
Size *types.DiskSize `json:"size,omitempty" url:"size,omitempty"`
|
||||
FileVolume string `json:"file" url:"file"`
|
||||
Format *string `json:"format,omitempty" url:"format,omitempty"`
|
||||
FileVolume string `json:"file" url:"file"`
|
||||
Format *string `json:"format,omitempty" url:"format,omitempty"`
|
||||
Type *string `json:"efitype,omitempty" url:"efitype,omitempty"`
|
||||
PreEnrolledKeys *types2.CustomBool `json:"pre-enrolled-keys,omitempty" url:"pre-enrolled-keys,omitempty,int"`
|
||||
}
|
||||
|
||||
// CustomNetworkDevice handles QEMU network device parameters.
|
||||
@ -784,8 +785,16 @@ func (r CustomEFIDisk) EncodeValues(key string, v *url.Values) error {
|
||||
values = append(values, fmt.Sprintf("format=%s", *r.Format))
|
||||
}
|
||||
|
||||
if r.Size != nil {
|
||||
values = append(values, fmt.Sprintf("size=%s", *r.Size))
|
||||
if r.Type != nil {
|
||||
values = append(values, fmt.Sprintf("efitype=%s", *r.Type))
|
||||
}
|
||||
|
||||
if r.PreEnrolledKeys != nil {
|
||||
if *r.PreEnrolledKeys {
|
||||
values = append(values, "pre-enrolled-keys=1")
|
||||
} else {
|
||||
values = append(values, "pre-enrolled-keys=0")
|
||||
}
|
||||
}
|
||||
|
||||
v.Add(key, strings.Join(values, ","))
|
||||
@ -1472,22 +1481,25 @@ func (r *CustomEFIDisk) UnmarshalJSON(b []byte) error {
|
||||
|
||||
pairs := strings.Split(s, ",")
|
||||
|
||||
for _, p := range pairs {
|
||||
for i, p := range pairs {
|
||||
v := strings.Split(strings.TrimSpace(p), "=")
|
||||
|
||||
if len(v) == 1 && i == 0 {
|
||||
r.FileVolume = v[0]
|
||||
}
|
||||
|
||||
if len(v) == 2 {
|
||||
switch v[0] {
|
||||
case "format":
|
||||
r.Format = &v[1]
|
||||
case "file":
|
||||
r.FileVolume = v[1]
|
||||
case "size":
|
||||
r.Size = new(types.DiskSize)
|
||||
|
||||
err := r.Size.UnmarshalJSON([]byte(v[1]))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal disk size: %w", err)
|
||||
}
|
||||
case "format":
|
||||
r.Format = &v[1]
|
||||
case "efitype":
|
||||
t := strings.ToLower(v[1])
|
||||
r.Type = &t
|
||||
case "pre-enrolled-keys":
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.PreEnrolledKeys = &bv
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,12 @@ type DiskSize int64
|
||||
|
||||
// String returns the string representation of the disk size.
|
||||
func (r DiskSize) String() string {
|
||||
return formatDiskSize(int64(r))
|
||||
return FormatDiskSize(r)
|
||||
}
|
||||
|
||||
// InMegabytes returns the disk size in megabytes.
|
||||
func (r DiskSize) InMegabytes() int {
|
||||
return int(int64(r) / 1024 / 1024)
|
||||
}
|
||||
|
||||
// InGigabytes returns the disk size in gigabytes.
|
||||
@ -39,7 +44,7 @@ func DiskSizeFromGigabytes(size int) DiskSize {
|
||||
|
||||
// MarshalJSON marshals a disk size into a Proxmox API `<DiskSize>` string.
|
||||
func (r DiskSize) MarshalJSON() ([]byte, error) {
|
||||
bytes, err := json.Marshal(formatDiskSize(int64(r)))
|
||||
bytes, err := json.Marshal(FormatDiskSize(r))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot marshal disk size: %w", err)
|
||||
}
|
||||
@ -51,27 +56,23 @@ func (r DiskSize) MarshalJSON() ([]byte, error) {
|
||||
func (r *DiskSize) UnmarshalJSON(b []byte) error {
|
||||
s := string(b)
|
||||
|
||||
size, err := parseDiskSize(&s)
|
||||
size, err := ParseDiskSize(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*r = DiskSize(size)
|
||||
*r = size
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseDiskSize parses a disk size string into a number of bytes.
|
||||
func parseDiskSize(size *string) (int64, error) {
|
||||
if size == nil {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
matches := sizeRegex.FindStringSubmatch(*size)
|
||||
// ParseDiskSize parses a disk size string into a number of bytes.
|
||||
func ParseDiskSize(size string) (DiskSize, error) {
|
||||
matches := sizeRegex.FindStringSubmatch(size)
|
||||
if len(matches) > 0 {
|
||||
fsize, err := strconv.ParseFloat(matches[1], 64)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("cannot parse disk size \"%s\": %w", *size, err)
|
||||
return -1, fmt.Errorf("cannot parse disk size \"%s\": %w", size, err)
|
||||
}
|
||||
|
||||
switch strings.ToLower(matches[3]) {
|
||||
@ -85,13 +86,14 @@ func parseDiskSize(size *string) (int64, error) {
|
||||
fsize = fsize * 1024 * 1024 * 1024 * 1024
|
||||
}
|
||||
|
||||
return int64(math.Ceil(fsize)), nil
|
||||
return DiskSize(math.Ceil(fsize)), nil
|
||||
}
|
||||
|
||||
return -1, fmt.Errorf("cannot parse disk size \"%s\"", *size)
|
||||
return -1, fmt.Errorf("cannot parse disk size \"%s\"", size)
|
||||
}
|
||||
|
||||
func formatDiskSize(size int64) string {
|
||||
// FormatDiskSize turns a number of bytes into a disk size string.
|
||||
func FormatDiskSize(size DiskSize) string {
|
||||
if size < 0 {
|
||||
return ""
|
||||
}
|
||||
|
@ -17,37 +17,36 @@ func TestParseDiskSize(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
size *string
|
||||
size string
|
||||
want int64
|
||||
wantErr bool
|
||||
}{
|
||||
{"handle null size", nil, 0, false},
|
||||
{"parse TB", StrPtr("2TB"), 2199023255552, false},
|
||||
{"parse T", StrPtr("2T"), 2199023255552, false},
|
||||
{"parse fraction T", StrPtr("2.2T"), 2418925581108, false},
|
||||
{"parse GB", StrPtr("2GB"), 2147483648, false},
|
||||
{"parse G", StrPtr("2G"), 2147483648, false},
|
||||
{"parse M", StrPtr("2048M"), 2147483648, false},
|
||||
{"parse MB", StrPtr("2048MB"), 2147483648, false},
|
||||
{"parse MiB", StrPtr("2048MiB"), 2147483648, false},
|
||||
{"parse K", StrPtr("1K"), 1024, false},
|
||||
{"parse KB", StrPtr("2KB"), 2048, false},
|
||||
{"parse KiB", StrPtr("4KiB"), 4096, false},
|
||||
{"parse no units as bytes", StrPtr("12345"), 12345, false},
|
||||
{"error on bad format string", StrPtr("20l8G"), -1, true},
|
||||
{"error on unknown unit string", StrPtr("2048W"), -1, true},
|
||||
{"error on arbitrary string", StrPtr("something"), -1, true},
|
||||
{"parse TB", "2TB", 2199023255552, false},
|
||||
{"parse T", "2T", 2199023255552, false},
|
||||
{"parse fraction T", "2.2T", 2418925581108, false},
|
||||
{"parse GB", "2GB", 2147483648, false},
|
||||
{"parse G", "2G", 2147483648, false},
|
||||
{"parse M", "2048M", 2147483648, false},
|
||||
{"parse MB", "2048MB", 2147483648, false},
|
||||
{"parse MiB", "2048MiB", 2147483648, false},
|
||||
{"parse K", "1K", 1024, false},
|
||||
{"parse KB", "2KB", 2048, false},
|
||||
{"parse KiB", "4KiB", 4096, false},
|
||||
{"parse no units as bytes", "12345", 12345, false},
|
||||
{"error on bad format string", "20l8G", -1, true},
|
||||
{"error on unknown unit string", "2048W", -1, true},
|
||||
{"error on arbitrary string", "something", -1, true},
|
||||
}
|
||||
for _, test := range tests {
|
||||
tt := test
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got, err := parseDiskSize(tt.size)
|
||||
got, err := ParseDiskSize(tt.size)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("parseDiskSize() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
if int64(got) != tt.want {
|
||||
t.Errorf("parseDiskSize() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
@ -73,7 +72,7 @@ func TestFormatDiskSize(t *testing.T) {
|
||||
tt := test
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if got := formatDiskSize(tt.size); got != tt.want {
|
||||
if got := FormatDiskSize(DiskSize(tt.size)); got != tt.want {
|
||||
t.Errorf("formatDiskSize() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/vms"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
)
|
||||
|
||||
func getBIOSValidator() schema.SchemaValidateDiagFunc {
|
||||
@ -186,6 +187,29 @@ func getFileIDValidator() schema.SchemaValidateDiagFunc {
|
||||
})
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func getFileSizeValidator() schema.SchemaValidateDiagFunc {
|
||||
return validation.ToDiagFunc(func(i interface{}, k string) ([]string, []error) {
|
||||
v, ok := i.(string)
|
||||
var es []error
|
||||
|
||||
if !ok {
|
||||
es = append(es, fmt.Errorf("expected type of %s to be string", k))
|
||||
return nil, es
|
||||
}
|
||||
|
||||
if v != "" {
|
||||
_, err := types.ParseDiskSize(v)
|
||||
if err != nil {
|
||||
es = append(es, fmt.Errorf("expected %s to be a valid file size (100, 1M, 1G), got %s", k, v))
|
||||
return nil, es
|
||||
}
|
||||
}
|
||||
|
||||
return []string{}, es
|
||||
})
|
||||
}
|
||||
|
||||
func getKeyboardLayoutValidator() schema.SchemaValidateDiagFunc {
|
||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||
"da",
|
||||
@ -506,6 +530,11 @@ func getDiskDatastores(vm *vms.GetResponseData, d *schema.ResourceData) []string
|
||||
datastoresSet[fileIDParts[0]] = 1
|
||||
}
|
||||
|
||||
if vm.EFIDisk != nil {
|
||||
fileIDParts := strings.Split(vm.EFIDisk.FileVolume, ":")
|
||||
datastoresSet[fileIDParts[0]] = 1
|
||||
}
|
||||
|
||||
datastores := []string{}
|
||||
for datastore := range datastoresSet {
|
||||
datastores = append(datastores, datastore)
|
||||
|
@ -47,6 +47,7 @@ const (
|
||||
dvResourceVirtualEnvironmentVMCPUArchitecture = "x86_64"
|
||||
dvResourceVirtualEnvironmentVMCPUCores = 1
|
||||
dvResourceVirtualEnvironmentVMCPUHotplugged = 0
|
||||
dvResourceVirtualEnvironmentVMCPUNUMA = false
|
||||
dvResourceVirtualEnvironmentVMCPUSockets = 1
|
||||
dvResourceVirtualEnvironmentVMCPUType = "qemu64"
|
||||
dvResourceVirtualEnvironmentVMCPUUnits = 1024
|
||||
@ -63,6 +64,10 @@ const (
|
||||
dvResourceVirtualEnvironmentVMDiskSpeedReadBurstable = 0
|
||||
dvResourceVirtualEnvironmentVMDiskSpeedWrite = 0
|
||||
dvResourceVirtualEnvironmentVMDiskSpeedWriteBurstable = 0
|
||||
dvResourceVirtualEnvironmentVMEFIDiskDatastoreID = "local-lvm"
|
||||
dvResourceVirtualEnvironmentVMEFIDiskFileFormat = "qcow2"
|
||||
dvResourceVirtualEnvironmentVMEFIDiskType = "2m"
|
||||
dvResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys = false
|
||||
dvResourceVirtualEnvironmentVMInitializationDatastoreID = "local-lvm"
|
||||
dvResourceVirtualEnvironmentVMInitializationDNSDomain = ""
|
||||
dvResourceVirtualEnvironmentVMInitializationDNSServer = ""
|
||||
@ -139,6 +144,7 @@ const (
|
||||
mkResourceVirtualEnvironmentVMCPUCores = "cores"
|
||||
mkResourceVirtualEnvironmentVMCPUFlags = "flags"
|
||||
mkResourceVirtualEnvironmentVMCPUHotplugged = "hotplugged"
|
||||
mkResourceVirtualEnvironmentVMCPUNUMA = "numa"
|
||||
mkResourceVirtualEnvironmentVMCPUSockets = "sockets"
|
||||
mkResourceVirtualEnvironmentVMCPUType = "type"
|
||||
mkResourceVirtualEnvironmentVMCPUUnits = "units"
|
||||
@ -157,6 +163,11 @@ const (
|
||||
mkResourceVirtualEnvironmentVMDiskSpeedReadBurstable = "read_burstable"
|
||||
mkResourceVirtualEnvironmentVMDiskSpeedWrite = "write"
|
||||
mkResourceVirtualEnvironmentVMDiskSpeedWriteBurstable = "write_burstable"
|
||||
mkResourceVirtualEnvironmentVMEFIDisk = "efi_disk"
|
||||
mkResourceVirtualEnvironmentVMEFIDiskDatastoreID = "datastore_id"
|
||||
mkResourceVirtualEnvironmentVMEFIDiskFileFormat = "file_format"
|
||||
mkResourceVirtualEnvironmentVMEFIDiskType = "type"
|
||||
mkResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys = "pre_enrolled_keys"
|
||||
mkResourceVirtualEnvironmentVMHostPCI = "hostpci"
|
||||
mkResourceVirtualEnvironmentVMHostPCIDevice = "device"
|
||||
mkResourceVirtualEnvironmentVMHostPCIDeviceID = "id"
|
||||
@ -449,6 +460,7 @@ func VM() *schema.Resource {
|
||||
mkResourceVirtualEnvironmentVMCPUArchitecture: dvResourceVirtualEnvironmentVMCPUArchitecture,
|
||||
mkResourceVirtualEnvironmentVMCPUCores: dvResourceVirtualEnvironmentVMCPUCores,
|
||||
mkResourceVirtualEnvironmentVMCPUFlags: []interface{}{},
|
||||
mkResourceVirtualEnvironmentVMCPUNUMA: dvResourceVirtualEnvironmentVMCPUNUMA,
|
||||
mkResourceVirtualEnvironmentVMCPUHotplugged: dvResourceVirtualEnvironmentVMCPUHotplugged,
|
||||
mkResourceVirtualEnvironmentVMCPUSockets: dvResourceVirtualEnvironmentVMCPUSockets,
|
||||
mkResourceVirtualEnvironmentVMCPUType: dvResourceVirtualEnvironmentVMCPUType,
|
||||
@ -488,6 +500,12 @@ func VM() *schema.Resource {
|
||||
Default: dvResourceVirtualEnvironmentVMCPUHotplugged,
|
||||
ValidateDiagFunc: validation.ToDiagFunc(validation.IntBetween(0, 2304)),
|
||||
},
|
||||
mkResourceVirtualEnvironmentVMCPUNUMA: {
|
||||
Type: schema.TypeBool,
|
||||
Description: "Enable/disable NUMA.",
|
||||
Optional: true,
|
||||
Default: dvResourceVirtualEnvironmentVMCPUNUMA,
|
||||
},
|
||||
mkResourceVirtualEnvironmentVMCPUSockets: {
|
||||
Type: schema.TypeInt,
|
||||
Description: "The number of CPU sockets",
|
||||
@ -644,6 +662,61 @@ func VM() *schema.Resource {
|
||||
MaxItems: 14,
|
||||
MinItems: 0,
|
||||
},
|
||||
mkResourceVirtualEnvironmentVMEFIDisk: {
|
||||
Type: schema.TypeList,
|
||||
Description: "The efidisk device",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
DefaultFunc: func() (interface{}, error) {
|
||||
return []interface{}{
|
||||
map[string]interface{}{
|
||||
mkResourceVirtualEnvironmentVMEFIDiskDatastoreID: dvResourceVirtualEnvironmentVMEFIDiskDatastoreID,
|
||||
mkResourceVirtualEnvironmentVMEFIDiskType: dvResourceVirtualEnvironmentVMEFIDiskType,
|
||||
mkResourceVirtualEnvironmentVMEFIDiskFileFormat: dvResourceVirtualEnvironmentVMEFIDiskFileFormat,
|
||||
mkResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys: dvResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
mkResourceVirtualEnvironmentVMEFIDiskDatastoreID: {
|
||||
Type: schema.TypeString,
|
||||
Description: "The datastore id",
|
||||
Optional: true,
|
||||
Default: dvResourceVirtualEnvironmentVMEFIDiskDatastoreID,
|
||||
},
|
||||
mkResourceVirtualEnvironmentVMEFIDiskFileFormat: {
|
||||
Type: schema.TypeString,
|
||||
Description: "The file format",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Computed: true,
|
||||
ValidateDiagFunc: getFileFormatValidator(),
|
||||
},
|
||||
mkResourceVirtualEnvironmentVMEFIDiskType: {
|
||||
Type: schema.TypeString,
|
||||
Description: "Size and type of the OVMF EFI disk",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Default: dvResourceVirtualEnvironmentVMEFIDiskType,
|
||||
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||
"2m",
|
||||
"4m",
|
||||
}, true)),
|
||||
},
|
||||
mkResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys: {
|
||||
Type: schema.TypeBool,
|
||||
Description: "Use an EFI vars template with distribution-specific and Microsoft Standard " +
|
||||
"keys enrolled, if used with efi type=`4m`.",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Default: dvResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys,
|
||||
},
|
||||
},
|
||||
},
|
||||
MaxItems: 1,
|
||||
MinItems: 0,
|
||||
},
|
||||
mkResourceVirtualEnvironmentVMInitialization: {
|
||||
Type: schema.TypeList,
|
||||
Description: "The cloud-init configuration",
|
||||
@ -1544,6 +1617,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
cpuCores := cpuBlock[mkResourceVirtualEnvironmentVMCPUCores].(int)
|
||||
cpuFlags := cpuBlock[mkResourceVirtualEnvironmentVMCPUFlags].([]interface{})
|
||||
cpuHotplugged := cpuBlock[mkResourceVirtualEnvironmentVMCPUHotplugged].(int)
|
||||
cpuNUMA := types2.CustomBool(cpuBlock[mkResourceVirtualEnvironmentVMCPUNUMA].(bool))
|
||||
cpuSockets := cpuBlock[mkResourceVirtualEnvironmentVMCPUSockets].(int)
|
||||
cpuType := cpuBlock[mkResourceVirtualEnvironmentVMCPUType].(string)
|
||||
cpuUnits := cpuBlock[mkResourceVirtualEnvironmentVMCPUUnits].(int)
|
||||
@ -1565,6 +1639,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
Flags: &cpuFlagsConverted,
|
||||
Type: cpuType,
|
||||
}
|
||||
updateBody.NUMAEnabled = &cpuNUMA
|
||||
updateBody.CPUSockets = &cpuSockets
|
||||
updateBody.CPUUnits = &cpuUnits
|
||||
|
||||
@ -1694,6 +1769,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
}
|
||||
|
||||
disk := d.Get(mkResourceVirtualEnvironmentVMDisk).([]interface{})
|
||||
efiDisk := d.Get(mkResourceVirtualEnvironmentVMEFIDisk).([]interface{})
|
||||
|
||||
vmConfig, e := vmAPI.GetVM(ctx)
|
||||
if e != nil {
|
||||
@ -1805,6 +1881,65 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
}
|
||||
}
|
||||
|
||||
efiDiskInfo := vmGetEfiDisk(d, nil) // from the resource config
|
||||
|
||||
for i := range efiDisk {
|
||||
diskBlock := efiDisk[i].(map[string]interface{})
|
||||
diskInterface := "efidisk0"
|
||||
dataStoreID := diskBlock[mkResourceVirtualEnvironmentVMEFIDiskDatastoreID].(string)
|
||||
efiType := diskBlock[mkResourceVirtualEnvironmentVMEFIDiskType].(string)
|
||||
|
||||
currentDiskInfo := vmConfig.EFIDisk
|
||||
configuredDiskInfo := efiDiskInfo
|
||||
|
||||
if currentDiskInfo == nil {
|
||||
diskUpdateBody := &vms.UpdateRequestBody{}
|
||||
|
||||
diskUpdateBody.EFIDisk = configuredDiskInfo
|
||||
|
||||
e = vmAPI.UpdateVM(ctx, diskUpdateBody)
|
||||
if e != nil {
|
||||
return diag.FromErr(e)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if &efiType != currentDiskInfo.Type {
|
||||
return diag.Errorf(
|
||||
"resizing of efidisks is not supported.",
|
||||
)
|
||||
}
|
||||
|
||||
deleteOriginalDisk := types2.CustomBool(true)
|
||||
|
||||
diskMoveBody := &vms.MoveDiskRequestBody{
|
||||
DeleteOriginalDisk: &deleteOriginalDisk,
|
||||
Disk: diskInterface,
|
||||
TargetStorage: dataStoreID,
|
||||
}
|
||||
|
||||
moveDisk := false
|
||||
|
||||
if dataStoreID != "" {
|
||||
moveDisk = true
|
||||
|
||||
if allDiskInfo[diskInterface] != nil {
|
||||
fileIDParts := strings.Split(allDiskInfo[diskInterface].FileVolume, ":")
|
||||
moveDisk = dataStoreID != fileIDParts[0]
|
||||
}
|
||||
}
|
||||
|
||||
if moveDisk {
|
||||
moveDiskTimeout := d.Get(mkResourceVirtualEnvironmentVMTimeoutMoveDisk).(int)
|
||||
|
||||
e = vmAPI.MoveVMDisk(ctx, diskMoveBody, moveDiskTimeout)
|
||||
if e != nil {
|
||||
return diag.FromErr(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vmCreateStart(ctx, d, m)
|
||||
}
|
||||
|
||||
@ -1879,6 +2014,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
||||
cpuFlags := cpuBlock[mkResourceVirtualEnvironmentVMCPUFlags].([]interface{})
|
||||
cpuHotplugged := cpuBlock[mkResourceVirtualEnvironmentVMCPUHotplugged].(int)
|
||||
cpuSockets := cpuBlock[mkResourceVirtualEnvironmentVMCPUSockets].(int)
|
||||
cpuNUMA := types2.CustomBool(cpuBlock[mkResourceVirtualEnvironmentVMCPUNUMA].(bool))
|
||||
cpuType := cpuBlock[mkResourceVirtualEnvironmentVMCPUType].(string)
|
||||
cpuUnits := cpuBlock[mkResourceVirtualEnvironmentVMCPUUnits].(int)
|
||||
|
||||
@ -1888,6 +2024,29 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
var efiDisk *vms.CustomEFIDisk
|
||||
|
||||
efiDiskBlock := d.Get(mkResourceVirtualEnvironmentVMEFIDisk).([]interface{})
|
||||
if len(efiDiskBlock) > 0 {
|
||||
block := efiDiskBlock[0].(map[string]interface{})
|
||||
|
||||
datastoreID, _ := block[mkResourceVirtualEnvironmentVMEFIDiskDatastoreID].(string)
|
||||
fileFormat, _ := block[mkResourceVirtualEnvironmentVMEFIDiskFileFormat].(string)
|
||||
efiType, _ := block[mkResourceVirtualEnvironmentVMEFIDiskType].(string)
|
||||
preEnrolledKeys := types2.CustomBool(block[mkResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys].(bool))
|
||||
|
||||
if fileFormat == "" {
|
||||
fileFormat = dvResourceVirtualEnvironmentVMEFIDiskFileFormat
|
||||
}
|
||||
|
||||
efiDisk = &vms.CustomEFIDisk{
|
||||
Type: &efiType,
|
||||
FileVolume: fmt.Sprintf("%s:1", datastoreID),
|
||||
Format: &fileFormat,
|
||||
PreEnrolledKeys: &preEnrolledKeys,
|
||||
}
|
||||
}
|
||||
|
||||
virtioDeviceObjects := diskDeviceObjects["virtio"]
|
||||
scsiDeviceObjects := diskDeviceObjects["scsi"]
|
||||
// ideDeviceObjects := getOrderedDiskDeviceList(diskDeviceObjects, "ide")
|
||||
@ -2055,10 +2214,12 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
||||
CPUSockets: &cpuSockets,
|
||||
CPUUnits: &cpuUnits,
|
||||
DedicatedMemory: &memoryDedicated,
|
||||
EFIDisk: efiDisk,
|
||||
FloatingMemory: &memoryFloating,
|
||||
IDEDevices: ideDevices,
|
||||
KeyboardLayout: &keyboardLayout,
|
||||
NetworkDevices: networkDeviceObjects,
|
||||
NUMAEnabled: &cpuNUMA,
|
||||
OSType: &operatingSystemType,
|
||||
PCIDevices: pciDeviceObjects,
|
||||
SCSIHardware: &scsiHardware,
|
||||
@ -2616,6 +2777,69 @@ func vmGetDiskDeviceObjects(
|
||||
return diskDeviceObjects, nil
|
||||
}
|
||||
|
||||
func vmGetEfiDisk(d *schema.ResourceData, disk []interface{}) *vms.CustomEFIDisk {
|
||||
var efiDisk []interface{}
|
||||
|
||||
if disk != nil {
|
||||
efiDisk = disk
|
||||
} else {
|
||||
efiDisk = d.Get(mkResourceVirtualEnvironmentVMEFIDisk).([]interface{})
|
||||
}
|
||||
|
||||
var efiDiskConfig *vms.CustomEFIDisk
|
||||
|
||||
if len(efiDisk) > 0 {
|
||||
efiDiskConfig = &vms.CustomEFIDisk{}
|
||||
|
||||
block := efiDisk[0].(map[string]interface{})
|
||||
datastoreID, _ := block[mkResourceVirtualEnvironmentVMEFIDiskDatastoreID].(string)
|
||||
fileFormat, _ := block[mkResourceVirtualEnvironmentVMEFIDiskFileFormat].(string)
|
||||
efiType, _ := block[mkResourceVirtualEnvironmentVMEFIDiskType].(string)
|
||||
preEnrolledKeys := types2.CustomBool(block[mkResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys].(bool))
|
||||
|
||||
// special case for efi disk, the size is ignored, see docs for more info
|
||||
efiDiskConfig.FileVolume = fmt.Sprintf("%s:1", datastoreID)
|
||||
efiDiskConfig.Format = &fileFormat
|
||||
efiDiskConfig.Type = &efiType
|
||||
efiDiskConfig.PreEnrolledKeys = &preEnrolledKeys
|
||||
}
|
||||
|
||||
return efiDiskConfig
|
||||
}
|
||||
|
||||
func vmGetEfiDiskAsStorageDevice(d *schema.ResourceData, disk []interface{}) (*vms.CustomStorageDevice, error) {
|
||||
efiDisk := vmGetEfiDisk(d, disk)
|
||||
|
||||
var storageDevice *vms.CustomStorageDevice
|
||||
|
||||
if efiDisk != nil {
|
||||
id := "0"
|
||||
baseDiskInterface := "efidisk"
|
||||
diskInterface := fmt.Sprint(baseDiskInterface, id)
|
||||
|
||||
storageDevice = &vms.CustomStorageDevice{
|
||||
Enabled: true,
|
||||
FileVolume: efiDisk.FileVolume,
|
||||
Format: efiDisk.Format,
|
||||
Interface: &diskInterface,
|
||||
ID: &id,
|
||||
}
|
||||
|
||||
if efiDisk.Type != nil {
|
||||
ds, err := types.ParseDiskSize(*efiDisk.Type)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid efi disk type: %s", err.Error())
|
||||
}
|
||||
|
||||
sizeInt := ds.InMegabytes()
|
||||
storageDevice.Size = &ds
|
||||
storageDevice.SizeInt = &sizeInt
|
||||
}
|
||||
}
|
||||
|
||||
return storageDevice, nil
|
||||
}
|
||||
|
||||
func vmGetHostPCIDeviceObjects(d *schema.ResourceData) vms.CustomPCIDevices {
|
||||
pciDevice := d.Get(mkResourceVirtualEnvironmentVMHostPCI).([]interface{})
|
||||
pciDeviceObjects := make(vms.CustomPCIDevices, len(pciDevice))
|
||||
@ -3038,6 +3262,13 @@ func vmReadCustom(
|
||||
cpu[mkResourceVirtualEnvironmentVMCPUHotplugged] = 0
|
||||
}
|
||||
|
||||
if vmConfig.NUMAEnabled != nil {
|
||||
cpu[mkResourceVirtualEnvironmentVMCPUNUMA] = *vmConfig.NUMAEnabled
|
||||
} else {
|
||||
// Default value of "numa" is "false" according to the API documentation.
|
||||
cpu[mkResourceVirtualEnvironmentVMCPUNUMA] = false
|
||||
}
|
||||
|
||||
if vmConfig.CPUSockets != nil {
|
||||
cpu[mkResourceVirtualEnvironmentVMCPUSockets] = *vmConfig.CPUSockets
|
||||
} else {
|
||||
@ -3212,6 +3443,60 @@ func vmReadCustom(
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
}
|
||||
|
||||
//nolint:nestif
|
||||
if vmConfig.EFIDisk != nil {
|
||||
efiDisk := map[string]interface{}{}
|
||||
|
||||
fileIDParts := strings.Split(vmConfig.EFIDisk.FileVolume, ":")
|
||||
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskDatastoreID] = fileIDParts[0]
|
||||
|
||||
if vmConfig.EFIDisk.Format != nil {
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskFileFormat] = *vmConfig.EFIDisk.Format
|
||||
} else {
|
||||
// disk format may not be returned by config API if it is default for the storage, and that may be different
|
||||
// from the default qcow2, so we need to read it from the storage API to make sure we have the correct value
|
||||
files, err := api.Node(nodeName).ListDatastoreFiles(ctx, fileIDParts[0])
|
||||
if err != nil {
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
} else {
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskFileFormat] = ""
|
||||
for _, v := range files {
|
||||
if v.VolumeID == vmConfig.EFIDisk.FileVolume {
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskFileFormat] = v.FileFormat
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if vmConfig.EFIDisk.Type != nil {
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskType] = *vmConfig.EFIDisk.Type
|
||||
} else {
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskType] = dvResourceVirtualEnvironmentVMEFIDiskType
|
||||
}
|
||||
|
||||
if vmConfig.EFIDisk.PreEnrolledKeys != nil {
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys] = *vmConfig.EFIDisk.PreEnrolledKeys
|
||||
} else {
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys] = false
|
||||
}
|
||||
|
||||
currentEfiDisk := d.Get(mkResourceVirtualEnvironmentVMEFIDisk).([]interface{})
|
||||
|
||||
if len(clone) > 0 && len(currentEfiDisk) > 0 {
|
||||
err := d.Set(mkResourceVirtualEnvironmentVMEFIDisk, []interface{}{efiDisk})
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
} else if len(currentEfiDisk) > 0 ||
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskDatastoreID] != dvResourceVirtualEnvironmentVMEFIDiskDatastoreID ||
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskType] != dvResourceVirtualEnvironmentVMEFIDiskType ||
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys] != dvResourceVirtualEnvironmentVMEFIDiskPreEnrolledKeys || //nolint:lll
|
||||
efiDisk[mkResourceVirtualEnvironmentVMEFIDiskFileFormat] != dvResourceVirtualEnvironmentVMEFIDiskFileFormat {
|
||||
err := d.Set(mkResourceVirtualEnvironmentVMEFIDisk, []interface{}{efiDisk})
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
}
|
||||
}
|
||||
|
||||
currentPCIList := d.Get(mkResourceVirtualEnvironmentVMHostPCI).([]interface{})
|
||||
pciMap := map[string]interface{}{}
|
||||
var orderedPCIList []interface{}
|
||||
@ -4216,6 +4501,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
cpuCores := cpuBlock[mkResourceVirtualEnvironmentVMCPUCores].(int)
|
||||
cpuFlags := cpuBlock[mkResourceVirtualEnvironmentVMCPUFlags].([]interface{})
|
||||
cpuHotplugged := cpuBlock[mkResourceVirtualEnvironmentVMCPUHotplugged].(int)
|
||||
cpuNUMA := types2.CustomBool(cpuBlock[mkResourceVirtualEnvironmentVMCPUNUMA].(bool))
|
||||
cpuSockets := cpuBlock[mkResourceVirtualEnvironmentVMCPUSockets].(int)
|
||||
cpuType := cpuBlock[mkResourceVirtualEnvironmentVMCPUType].(string)
|
||||
cpuUnits := cpuBlock[mkResourceVirtualEnvironmentVMCPUUnits].(int)
|
||||
@ -4229,6 +4515,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
updateBody.CPUCores = &cpuCores
|
||||
updateBody.CPUSockets = &cpuSockets
|
||||
updateBody.CPUUnits = &cpuUnits
|
||||
updateBody.NUMAEnabled = &cpuNUMA
|
||||
|
||||
if cpuHotplugged > 0 {
|
||||
updateBody.VirtualCPUCount = &cpuHotplugged
|
||||
@ -4311,6 +4598,15 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the new efi disk configuration.
|
||||
if d.HasChange(mkResourceVirtualEnvironmentVMEFIDisk) {
|
||||
efiDisk := vmGetEfiDisk(d, nil)
|
||||
|
||||
updateBody.EFIDisk = efiDisk
|
||||
|
||||
rebootRequired = true
|
||||
}
|
||||
|
||||
// Prepare the new cloud-init configuration.
|
||||
if d.HasChange(mkResourceVirtualEnvironmentVMInitialization) {
|
||||
initializationConfig := vmGetCloudInitConfig(d)
|
||||
@ -4330,15 +4626,14 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
Media: &cdromMedia,
|
||||
}
|
||||
|
||||
if vmConfig.IDEDevice2 != nil {
|
||||
if strings.Contains(
|
||||
if vmConfig.IDEDevice2 != nil &&
|
||||
strings.Contains(
|
||||
vmConfig.IDEDevice2.FileVolume,
|
||||
fmt.Sprintf("vm-%d-cloudinit", vmID),
|
||||
) {
|
||||
tmp := updateBody.IDEDevices["ide2"]
|
||||
tmp.Enabled = true
|
||||
updateBody.IDEDevices["ide2"] = tmp
|
||||
}
|
||||
tmp := updateBody.IDEDevices["ide2"]
|
||||
tmp.Enabled = true
|
||||
updateBody.IDEDevices["ide2"] = tmp
|
||||
}
|
||||
}
|
||||
|
||||
@ -4535,6 +4830,37 @@ func vmUpdateDiskLocationAndSize(
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
// Add efidisk if it has changes
|
||||
if d.HasChange(mkResourceVirtualEnvironmentVMEFIDisk) {
|
||||
diskOld, diskNew := d.GetChange(mkResourceVirtualEnvironmentVMEFIDisk)
|
||||
|
||||
oldEfiDisk, e := vmGetEfiDiskAsStorageDevice(d, diskOld.([]interface{}))
|
||||
if e != nil {
|
||||
return diag.FromErr(e)
|
||||
}
|
||||
|
||||
newEfiDisk, e := vmGetEfiDiskAsStorageDevice(d, diskNew.([]interface{}))
|
||||
if e != nil {
|
||||
return diag.FromErr(e)
|
||||
}
|
||||
|
||||
if oldEfiDisk != nil {
|
||||
baseDiskInterface := diskDigitPrefix(*oldEfiDisk.Interface)
|
||||
diskOldEntries[baseDiskInterface][*oldEfiDisk.Interface] = *oldEfiDisk
|
||||
}
|
||||
|
||||
if newEfiDisk != nil {
|
||||
baseDiskInterface := diskDigitPrefix(*newEfiDisk.Interface)
|
||||
diskNewEntries[baseDiskInterface][*newEfiDisk.Interface] = *newEfiDisk
|
||||
}
|
||||
|
||||
if oldEfiDisk != nil && newEfiDisk != nil && oldEfiDisk.Size != newEfiDisk.Size {
|
||||
return diag.Errorf(
|
||||
"resizing of efidisks is not supported.",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var diskMoveBodies []*vms.MoveDiskRequestBody
|
||||
|
||||
var diskResizeBodies []*vms.ResizeDiskRequestBody
|
||||
@ -4566,7 +4892,7 @@ func vmUpdateDiskLocationAndSize(
|
||||
shutdownForDisksRequired = true
|
||||
}
|
||||
|
||||
if *oldDisk.SizeInt <= *diskNewEntries[prefix][oldKey].SizeInt {
|
||||
if *oldDisk.SizeInt < *diskNewEntries[prefix][oldKey].SizeInt {
|
||||
diskResizeBodies = append(
|
||||
diskResizeBodies,
|
||||
&vms.ResizeDiskRequestBody{
|
||||
|
@ -45,6 +45,7 @@ func TestVMSchema(t *testing.T) {
|
||||
mkResourceVirtualEnvironmentVMCPU,
|
||||
mkResourceVirtualEnvironmentVMDescription,
|
||||
mkResourceVirtualEnvironmentVMDisk,
|
||||
mkResourceVirtualEnvironmentVMEFIDisk,
|
||||
mkResourceVirtualEnvironmentVMInitialization,
|
||||
mkResourceVirtualEnvironmentVMHostPCI,
|
||||
mkResourceVirtualEnvironmentVMKeyboardLayout,
|
||||
@ -80,6 +81,7 @@ func TestVMSchema(t *testing.T) {
|
||||
mkResourceVirtualEnvironmentVMCPU: schema.TypeList,
|
||||
mkResourceVirtualEnvironmentVMDescription: schema.TypeString,
|
||||
mkResourceVirtualEnvironmentVMDisk: schema.TypeList,
|
||||
mkResourceVirtualEnvironmentVMEFIDisk: schema.TypeList,
|
||||
mkResourceVirtualEnvironmentVMHostPCI: schema.TypeList,
|
||||
mkResourceVirtualEnvironmentVMInitialization: schema.TypeList,
|
||||
mkResourceVirtualEnvironmentVMIPv4Addresses: schema.TypeList,
|
||||
@ -165,6 +167,7 @@ func TestVMSchema(t *testing.T) {
|
||||
mkResourceVirtualEnvironmentVMCPUCores,
|
||||
mkResourceVirtualEnvironmentVMCPUFlags,
|
||||
mkResourceVirtualEnvironmentVMCPUHotplugged,
|
||||
mkResourceVirtualEnvironmentVMCPUNUMA,
|
||||
mkResourceVirtualEnvironmentVMCPUSockets,
|
||||
mkResourceVirtualEnvironmentVMCPUType,
|
||||
mkResourceVirtualEnvironmentVMCPUUnits,
|
||||
@ -175,6 +178,7 @@ func TestVMSchema(t *testing.T) {
|
||||
mkResourceVirtualEnvironmentVMCPUCores: schema.TypeInt,
|
||||
mkResourceVirtualEnvironmentVMCPUFlags: schema.TypeList,
|
||||
mkResourceVirtualEnvironmentVMCPUHotplugged: schema.TypeInt,
|
||||
mkResourceVirtualEnvironmentVMCPUNUMA: schema.TypeBool,
|
||||
mkResourceVirtualEnvironmentVMCPUSockets: schema.TypeInt,
|
||||
mkResourceVirtualEnvironmentVMCPUType: schema.TypeString,
|
||||
mkResourceVirtualEnvironmentVMCPUUnits: schema.TypeInt,
|
||||
@ -216,6 +220,20 @@ func TestVMSchema(t *testing.T) {
|
||||
mkResourceVirtualEnvironmentVMDiskSpeedWriteBurstable: schema.TypeInt,
|
||||
})
|
||||
|
||||
efiDiskSchema := test.AssertNestedSchemaExistence(t, s, mkResourceVirtualEnvironmentVMEFIDisk)
|
||||
|
||||
test.AssertOptionalArguments(t, efiDiskSchema, []string{
|
||||
mkResourceVirtualEnvironmentVMEFIDiskDatastoreID,
|
||||
mkResourceVirtualEnvironmentVMEFIDiskFileFormat,
|
||||
mkResourceVirtualEnvironmentVMEFIDiskType,
|
||||
})
|
||||
|
||||
test.AssertValueTypes(t, efiDiskSchema, map[string]schema.ValueType{
|
||||
mkResourceVirtualEnvironmentVMEFIDiskDatastoreID: schema.TypeString,
|
||||
mkResourceVirtualEnvironmentVMEFIDiskFileFormat: schema.TypeString,
|
||||
mkResourceVirtualEnvironmentVMEFIDiskType: schema.TypeString,
|
||||
})
|
||||
|
||||
initializationSchema := test.AssertNestedSchemaExistence(
|
||||
t,
|
||||
s,
|
||||
|
Loading…
Reference in New Issue
Block a user