From 62e578a075a441160aaacaebfc018895a4de1233 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 24 Jun 2024 18:25:57 +0200 Subject: [PATCH 01/12] refactor: rename func --- proxmox/resource_vm_qemu.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 83e1250f..2d7160e4 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -919,7 +919,7 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte } } - config.Disks = mapToStruct_QemuStorages(d) + config.Disks = mapToSDK_QemuStorages(d) if len(qemuVgaList) > 0 { config.QemuVga = qemuVgaList[0].(map[string]interface{}) @@ -1208,7 +1208,7 @@ func resourceVmQemuUpdate(ctx context.Context, d *schema.ResourceData, meta inte config.QemuVga = qemuVgaList[0].(map[string]interface{}) } - config.Disks = mapToStruct_QemuStorages(d) + config.Disks = mapToSDK_QemuStorages(d) logger.Debug().Int("vmid", vmID).Msgf("Updating VM with the following configuration: %+v", config) @@ -2682,7 +2682,7 @@ func mapToStruct_QemuScsiStorage(scsi *pxapi.QemuScsiStorage, key string, schema scsi.CdRom = mapToStruct_QemuCdRom(storageSchema) } -func mapToStruct_QemuStorages(d *schema.ResourceData) *pxapi.QemuStorages { +func mapToSDK_QemuStorages(d *schema.ResourceData) *pxapi.QemuStorages { storages := pxapi.QemuStorages{ Ide: &pxapi.QemuIdeDisks{ Disk_0: &pxapi.QemuIdeStorage{}, From a2fdd49173e2386f31beefb52ec93c62da22059b Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 19 Aug 2024 18:15:03 +0200 Subject: [PATCH 02/12] feat: `disk` schema --- proxmox/resource_vm_qemu.go | 136 ++++++++++++++++++++++++++---------- 1 file changed, 100 insertions(+), 36 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 2d7160e4..2b7bc4a4 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -477,6 +477,74 @@ func resourceVmQemu() *schema.Resource { }, }, }, + "disk": { + Type: schema.TypeList, + Optional: true, + ConflictsWith: []string{"disks"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "asyncio": schema_DiskAsyncIO(), + "backup": schema_DiskBackup(), + "cache": schema_DiskCache(), + "discard": {Type: schema.TypeBool, Optional: true}, + "disk_file": schema_PassthroughFile(schema.Schema{Optional: true}), + "emulatessd": {Type: schema.TypeBool, Optional: true}, + "format": schema_DiskFormat(), + "id": schema_DiskId(), + "iops_r_burst": schema_DiskBandwidthIopsBurst(), + "iops_r_burst_length": schema_DiskBandwidthIopsBurstLength(), + "iops_r_concurrent": schema_DiskBandwidthIopsConcurrent(), + "iops_wr_burst": schema_DiskBandwidthIopsBurst(), + "iops_wr_burst_length": schema_DiskBandwidthIopsBurstLength(), + "iops_wr_concurrent": schema_DiskBandwidthIopsConcurrent(), + "iothread": {Type: schema.TypeBool, Optional: true}, + "iso": schema_IsoPath(schema.Schema{}), + "linked_disk_id": schema_LinkedDiskId(), + "mbps_r_burst": schema_DiskBandwidthMBpsBurst(), + "mbps_r_concurrent": schema_DiskBandwidthMBpsConcurrent(), + "mbps_wr_burst": schema_DiskBandwidthMBpsBurst(), + "mbps_wr_concurrent": schema_DiskBandwidthMBpsConcurrent(), + "passthrough": {Type: schema.TypeBool, Default: false, Optional: true}, + "readonly": {Type: schema.TypeBool, Optional: true}, + "replicate": {Type: schema.TypeBool, Optional: true}, + "serial": schema_DiskSerial(), + "size": schema_DiskSize(schema.Schema{Computed: true, Optional: true}), + "slot": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: func(i interface{}, k cty.Path) diag.Diagnostics { + v, ok := i.(string) + if !ok { + return diag.Errorf(errorString, k) + } + switch v { + case "ide0", "ide1", "ide2", + "sata0", "sata1", "sata2", "sata3", "sata4", "sata5", + "scsi0", "scsi1", "scsi2", "scsi3", "scsi4", "scsi5", "scsi6", "scsi7", "scsi8", "scsi9", "scsi10", "scsi11", "scsi12", "scsi13", "scsi14", "scsi15", "scsi16", "scsi17", "scsi18", "scsi19", "scsi20", "scsi21", "scsi22", "scsi23", "scsi24", "scsi25", "scsi26", "scsi27", "scsi28", "scsi29", "scsi30", + "virtio0", "virtio1", "virtio2", "virtio3", "virtio4", "virtio5", "virtio6", "virtio7", "virtio8", "virtio9", "virtio10", "virtio11", "virtio12", "virtio13", "virtio14", "virtio15": + return nil + } + return diag.Errorf("slot must be one of 'ide0', 'ide1', 'ide2', 'sata0', 'sata1', 'sata2', 'sata3', 'sata4', 'sata5', 'scsi0', 'scsi1', 'scsi2', 'scsi3', 'scsi4', 'scsi5', 'scsi6', 'scsi7', 'scsi8', 'scsi9', 'scsi10', 'scsi11', 'scsi12', 'scsi13', 'scsi14', 'scsi15', 'scsi16', 'scsi17', 'scsi18', 'scsi19', 'scsi20', 'scsi21', 'scsi22', 'scsi23', 'scsi24', 'scsi25', 'scsi26', 'scsi27', 'scsi28', 'scsi29', 'scsi30', 'virtio0', 'virtio1', 'virtio2', 'virtio3', 'virtio4', 'virtio5', 'virtio6', 'virtio7', 'virtio8', 'virtio9', 'virtio10', 'virtio11', 'virtio12', 'virtio13', 'virtio14', 'virtio15'") + }}, + "storage": schema_DiskStorage(schema.Schema{Optional: true}), + "type": { + Type: schema.TypeString, + Optional: true, + Default: "disk", + ValidateDiagFunc: func(i interface{}, k cty.Path) diag.Diagnostics { + v, ok := i.(string) + if !ok { + return diag.Errorf(errorString, k) + } + switch v { + case "disk", "cdrom", "cloudinit": + return nil + } + return diag.Errorf("type must be one of 'disk', 'cdrom', 'cloudinit'") + }}, + "wwn": schema_DiskWWN(), + }}, + }, "disks": { Type: schema.TypeList, Optional: true, @@ -2859,11 +2927,7 @@ func schema_CdRom(path string, ci bool) *schema.Schema { ConflictsWith: conflicts, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "iso": { - Type: schema.TypeString, - Optional: true, - ConflictsWith: []string{path + ".cdrom.0.passthrough"}, - }, + "iso": schema_IsoPath(schema.Schema{ConflictsWith: []string{path + ".cdrom.0.passthrough"}}), "passthrough": { Type: schema.TypeBool, Optional: true, @@ -3008,7 +3072,7 @@ func schema_CloudInit(path, slot string) *schema.Schema { ConflictsWith: c, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "storage": schema_DiskStorage()}}} + "storage": schema_DiskStorage(schema.Schema{Required: true})}}} } func schema_Ide(slot string) *schema.Schema { @@ -3038,8 +3102,8 @@ func schema_Ide(slot string) *schema.Schema { "linked_disk_id": schema_LinkedDiskId(), "replicate": {Type: schema.TypeBool, Optional: true}, "serial": schema_DiskSerial(), - "size": schema_DiskSize(), - "storage": schema_DiskStorage(), + "size": schema_DiskSize(schema.Schema{Required: true}), + "storage": schema_DiskStorage(schema.Schema{Required: true}), "wwn": schema_DiskWWN(), }), }, @@ -3056,7 +3120,7 @@ func schema_Ide(slot string) *schema.Schema { "cache": schema_DiskCache(), "discard": {Type: schema.TypeBool, Optional: true}, "emulatessd": {Type: schema.TypeBool, Optional: true}, - "file": schema_PassthroughFile(), + "file": schema_PassthroughFile(schema.Schema{Required: true}), "replicate": {Type: schema.TypeBool, Optional: true}, "serial": schema_DiskSerial(), "size": schema_PassthroughSize(), @@ -3096,8 +3160,8 @@ func schema_Sata(slot string) *schema.Schema { "linked_disk_id": schema_LinkedDiskId(), "replicate": {Type: schema.TypeBool, Optional: true}, "serial": schema_DiskSerial(), - "size": schema_DiskSize(), - "storage": schema_DiskStorage(), + "size": schema_DiskSize(schema.Schema{Required: true}), + "storage": schema_DiskStorage(schema.Schema{Required: true}), "wwn": schema_DiskWWN(), }), }, @@ -3114,7 +3178,7 @@ func schema_Sata(slot string) *schema.Schema { "cache": schema_DiskCache(), "discard": {Type: schema.TypeBool, Optional: true}, "emulatessd": {Type: schema.TypeBool, Optional: true}, - "file": schema_PassthroughFile(), + "file": schema_PassthroughFile(schema.Schema{Required: true}), "replicate": {Type: schema.TypeBool, Optional: true}, "serial": schema_DiskSerial(), "size": schema_PassthroughSize(), @@ -3156,8 +3220,8 @@ func schema_Scsi(slot string) *schema.Schema { "readonly": {Type: schema.TypeBool, Optional: true}, "replicate": {Type: schema.TypeBool, Optional: true}, "serial": schema_DiskSerial(), - "size": schema_DiskSize(), - "storage": schema_DiskStorage(), + "size": schema_DiskSize(schema.Schema{Required: true}), + "storage": schema_DiskStorage(schema.Schema{Required: true}), "wwn": schema_DiskWWN(), }), }, @@ -3174,7 +3238,7 @@ func schema_Scsi(slot string) *schema.Schema { "cache": schema_DiskCache(), "discard": {Type: schema.TypeBool, Optional: true}, "emulatessd": {Type: schema.TypeBool, Optional: true}, - "file": schema_PassthroughFile(), + "file": schema_PassthroughFile(schema.Schema{Required: true}), "iothread": {Type: schema.TypeBool, Optional: true}, "readonly": {Type: schema.TypeBool, Optional: true}, "replicate": {Type: schema.TypeBool, Optional: true}, @@ -3216,8 +3280,8 @@ func schema_Virtio(setting string) *schema.Schema { "readonly": {Type: schema.TypeBool, Optional: true}, "replicate": {Type: schema.TypeBool, Optional: true}, "serial": schema_DiskSerial(), - "size": schema_DiskSize(), - "storage": schema_DiskStorage(), + "size": schema_DiskSize(schema.Schema{Required: true}), + "storage": schema_DiskStorage(schema.Schema{Required: true}), "wwn": schema_DiskWWN(), }), }, @@ -3233,7 +3297,7 @@ func schema_Virtio(setting string) *schema.Schema { "backup": schema_DiskBackup(), "cache": schema_DiskCache(), "discard": {Type: schema.TypeBool, Optional: true}, - "file": schema_PassthroughFile(), + "file": schema_PassthroughFile(schema.Schema{Required: true}), "iothread": {Type: schema.TypeBool, Optional: true}, "readonly": {Type: schema.TypeBool, Optional: true}, "replicate": {Type: schema.TypeBool, Optional: true}, @@ -3428,11 +3492,9 @@ func schema_DiskSerial() *schema.Schema { } } -func schema_DiskSize() *schema.Schema { - return &schema.Schema{ - Type: schema.TypeString, - Required: true, - ValidateDiagFunc: func(i interface{}, k cty.Path) diag.Diagnostics { +func schema_DiskSize(s schema.Schema) *schema.Schema { + s.Type = schema.TypeString + s.ValidateDiagFunc = func(i interface{}, k cty.Path) diag.Diagnostics { v, ok := i.(string) if !ok { return diag.Errorf(errorString, k) @@ -3441,18 +3503,16 @@ func schema_DiskSize() *schema.Schema { return diag.Errorf("%s must match the following regex ^[123456789]\\d*[KMGT]?$", k) } return nil - }, - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + } + s.DiffSuppressFunc = func(k, old, new string, d *schema.ResourceData) bool { return convert_SizeStringToKibibytes_Unsafe(old) == convert_SizeStringToKibibytes_Unsafe(new) - }, } + return &s } -func schema_DiskStorage() *schema.Schema { - return &schema.Schema{ - Type: schema.TypeString, - Required: true, - } +func schema_DiskStorage(s schema.Schema) *schema.Schema { + s.Type = schema.TypeString + return &s } func schema_DiskWWN() *schema.Schema { @@ -3472,6 +3532,12 @@ func schema_DiskWWN() *schema.Schema { } } +func schema_IsoPath(s schema.Schema) *schema.Schema { + s.Type = schema.TypeString + s.Optional = true + return &s +} + func schema_LinkedDiskId() *schema.Schema { return &schema.Schema{ Type: schema.TypeInt, @@ -3479,11 +3545,9 @@ func schema_LinkedDiskId() *schema.Schema { } } -func schema_PassthroughFile() *schema.Schema { - return &schema.Schema{ - Type: schema.TypeString, - Required: true, - } +func schema_PassthroughFile(s schema.Schema) *schema.Schema { + s.Type = schema.TypeString + return &s } func schema_PassthroughSize() *schema.Schema { From b2ff76b06b2b02fa4b1f3bf3a31982d896fa6e73 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 19 Aug 2024 18:21:52 +0200 Subject: [PATCH 03/12] refactor: rename function --- proxmox/resource_vm_qemu.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 2b7bc4a4..9e43ed3d 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -948,7 +948,7 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte Tablet: pointer(d.Get("tablet").(bool)), Boot: d.Get("boot").(string), BootDisk: d.Get("bootdisk").(string), - Agent: mapToStruct_QemuGuestAgent(d), + Agent: mapToSDK_QemuGuestAgent(d), Memory: d.Get("memory").(int), Machine: d.Get("machine").(string), Balloon: d.Get("balloon").(int), @@ -1224,7 +1224,7 @@ func resourceVmQemuUpdate(ctx context.Context, d *schema.ResourceData, meta inte Tablet: pointer(d.Get("tablet").(bool)), Boot: d.Get("boot").(string), BootDisk: d.Get("bootdisk").(string), - Agent: mapToStruct_QemuGuestAgent(d), + Agent: mapToSDK_QemuGuestAgent(d), Memory: d.Get("memory").(int), Machine: d.Get("machine").(string), Balloon: d.Get("balloon").(int), @@ -2429,6 +2429,7 @@ func mapFromStruct_QemuVirtIOStorage(config *pxapi.QemuVirtIOStorage) []interfac } // Map the terraform schema to sdk struct + func mapToStruct_IsoFile(iso string) *pxapi.IsoFile { if iso == "" { return nil @@ -2494,7 +2495,7 @@ func mapToStruct_QemuDiskBandwidth(schema map[string]interface{}) pxapi.QemuDisk } } -func mapToStruct_QemuGuestAgent(d *schema.ResourceData) *pxapi.QemuGuestAgent { +func mapToSDK_QemuGuestAgent(d *schema.ResourceData) *pxapi.QemuGuestAgent { var tmpEnable bool if d.Get("agent").(int) == 1 { tmpEnable = true From 6aed72c5ed89dd888c882e9b8dcef5c0d81503e1 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 19 Aug 2024 18:37:58 +0200 Subject: [PATCH 04/12] refactor: rename functions --- proxmox/resource_vm_qemu.go | 182 ++++++++++++++++++------------------ 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 9e43ed3d..1f6ddac3 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -2445,7 +2445,7 @@ func mapToStruct_IsoFile(iso string) *pxapi.IsoFile { return &pxapi.IsoFile{File: file, Storage: storage} } -func mapToStruct_QemuCdRom(schema map[string]interface{}) (cdRom *pxapi.QemuCdRom) { +func mapToSDK_QemuCdRom_Disks(schema map[string]interface{}) (cdRom *pxapi.QemuCdRom) { schemaItem, ok := schema["cdrom"].([]interface{}) if !ok { return @@ -2460,7 +2460,7 @@ func mapToStruct_QemuCdRom(schema map[string]interface{}) (cdRom *pxapi.QemuCdRo } } -func mapToStruct_QemuCloudInit(schemaItem []interface{}) (ci *pxapi.QemuCloudInitDisk) { +func mapToSDK_QemuCloudInit_Disks(schemaItem []interface{}) (ci *pxapi.QemuCloudInitDisk) { ciSchema := schemaItem[0].(map[string]interface{}) return &pxapi.QemuCloudInitDisk{ Format: pxapi.QemuDiskFormat_Raw, @@ -2468,7 +2468,7 @@ func mapToStruct_QemuCloudInit(schemaItem []interface{}) (ci *pxapi.QemuCloudIni } } -func mapToStruct_QemuDiskBandwidth(schema map[string]interface{}) pxapi.QemuDiskBandwidth { +func mapToSDK_QemuDiskBandwidth_Disks(schema map[string]interface{}) pxapi.QemuDiskBandwidth { return pxapi.QemuDiskBandwidth{ MBps: pxapi.QemuDiskBandwidthMBps{ ReadLimit: pxapi.QemuDiskBandwidthMBpsLimit{ @@ -2505,19 +2505,19 @@ func mapToSDK_QemuGuestAgent(d *schema.ResourceData) *pxapi.QemuGuestAgent { } } -func mapToStruct_QemuIdeDisks(ide *pxapi.QemuIdeDisks, schema map[string]interface{}) { +func mapToSDK_QemuIdeDisks_Disks(ide *pxapi.QemuIdeDisks, schema map[string]interface{}) { schemaItem, ok := schema["ide"].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { return } disks := schemaItem[0].(map[string]interface{}) - mapToStruct_QemuIdeStorage(ide.Disk_0, "ide0", disks) - mapToStruct_QemuIdeStorage(ide.Disk_1, "ide1", disks) - mapToStruct_QemuIdeStorage(ide.Disk_2, "ide2", disks) - mapToStruct_QemuIdeStorage(ide.Disk_3, "ide3", disks) + mapToSDK_QemuIdeStorage_Disks(ide.Disk_0, "ide0", disks) + mapToSDK_QemuIdeStorage_Disks(ide.Disk_1, "ide1", disks) + mapToSDK_QemuIdeStorage_Disks(ide.Disk_2, "ide2", disks) + mapToSDK_QemuIdeStorage_Disks(ide.Disk_3, "ide3", disks) } -func mapToStruct_QemuIdeStorage(ide *pxapi.QemuIdeStorage, key string, schema map[string]interface{}) { +func mapToSDK_QemuIdeStorage_Disks(ide *pxapi.QemuIdeStorage, key string, schema map[string]interface{}) { schemaItem, ok := schema[key].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { return @@ -2528,7 +2528,7 @@ func mapToStruct_QemuIdeStorage(ide *pxapi.QemuIdeStorage, key string, schema ma disk := tmpDisk[0].(map[string]interface{}) ide.Disk = &pxapi.QemuIdeDisk{ Backup: disk["backup"].(bool), - Bandwidth: mapToStruct_QemuDiskBandwidth(disk), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disks(disk), Discard: disk["discard"].(bool), EmulateSSD: disk["emulatessd"].(bool), Format: pxapi.QemuDiskFormat(disk["format"].(string)), @@ -2552,7 +2552,7 @@ func mapToStruct_QemuIdeStorage(ide *pxapi.QemuIdeStorage, key string, schema ma passthrough := tmpPassthrough[0].(map[string]interface{}) ide.Passthrough = &pxapi.QemuIdePassthrough{ Backup: passthrough["backup"].(bool), - Bandwidth: mapToStruct_QemuDiskBandwidth(passthrough), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disks(passthrough), Discard: passthrough["discard"].(bool), EmulateSSD: passthrough["emulatessd"].(bool), File: passthrough["file"].(string), @@ -2570,27 +2570,27 @@ func mapToStruct_QemuIdeStorage(ide *pxapi.QemuIdeStorage, key string, schema ma return } if v, ok := storageSchema["cloudinit"].([]interface{}); ok && len(v) == 1 && v[0] != nil { - ide.CloudInit = mapToStruct_QemuCloudInit(v) + ide.CloudInit = mapToSDK_QemuCloudInit_Disks(v) return } - ide.CdRom = mapToStruct_QemuCdRom(storageSchema) + ide.CdRom = mapToSDK_QemuCdRom_Disks(storageSchema) } -func mapToStruct_QemuSataDisks(sata *pxapi.QemuSataDisks, schema map[string]interface{}) { +func mapToSDK_QemuSataDisks_Disks(sata *pxapi.QemuSataDisks, schema map[string]interface{}) { schemaItem, ok := schema["sata"].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { return } disks := schemaItem[0].(map[string]interface{}) - mapToStruct_QemuSataStorage(sata.Disk_0, "sata0", disks) - mapToStruct_QemuSataStorage(sata.Disk_1, "sata1", disks) - mapToStruct_QemuSataStorage(sata.Disk_2, "sata2", disks) - mapToStruct_QemuSataStorage(sata.Disk_3, "sata3", disks) - mapToStruct_QemuSataStorage(sata.Disk_4, "sata4", disks) - mapToStruct_QemuSataStorage(sata.Disk_5, "sata5", disks) + mapToSDK_QemuSataStorage_Disks(sata.Disk_0, "sata0", disks) + mapToSDK_QemuSataStorage_Disks(sata.Disk_1, "sata1", disks) + mapToSDK_QemuSataStorage_Disks(sata.Disk_2, "sata2", disks) + mapToSDK_QemuSataStorage_Disks(sata.Disk_3, "sata3", disks) + mapToSDK_QemuSataStorage_Disks(sata.Disk_4, "sata4", disks) + mapToSDK_QemuSataStorage_Disks(sata.Disk_5, "sata5", disks) } -func mapToStruct_QemuSataStorage(sata *pxapi.QemuSataStorage, key string, schema map[string]interface{}) { +func mapToSDK_QemuSataStorage_Disks(sata *pxapi.QemuSataStorage, key string, schema map[string]interface{}) { schemaItem, ok := schema[key].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { return @@ -2601,7 +2601,7 @@ func mapToStruct_QemuSataStorage(sata *pxapi.QemuSataStorage, key string, schema disk := tmpDisk[0].(map[string]interface{}) sata.Disk = &pxapi.QemuSataDisk{ Backup: disk["backup"].(bool), - Bandwidth: mapToStruct_QemuDiskBandwidth(disk), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disks(disk), Discard: disk["discard"].(bool), EmulateSSD: disk["emulatessd"].(bool), Format: pxapi.QemuDiskFormat(disk["format"].(string)), @@ -2625,7 +2625,7 @@ func mapToStruct_QemuSataStorage(sata *pxapi.QemuSataStorage, key string, schema passthrough := tmpPassthrough[0].(map[string]interface{}) sata.Passthrough = &pxapi.QemuSataPassthrough{ Backup: passthrough["backup"].(bool), - Bandwidth: mapToStruct_QemuDiskBandwidth(passthrough), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disks(passthrough), Discard: passthrough["discard"].(bool), EmulateSSD: passthrough["emulatessd"].(bool), File: passthrough["file"].(string), @@ -2643,52 +2643,52 @@ func mapToStruct_QemuSataStorage(sata *pxapi.QemuSataStorage, key string, schema return } if v, ok := storageSchema["cloudinit"].([]interface{}); ok && len(v) == 1 && v[0] != nil { - sata.CloudInit = mapToStruct_QemuCloudInit(v) + sata.CloudInit = mapToSDK_QemuCloudInit_Disks(v) return } - sata.CdRom = mapToStruct_QemuCdRom(storageSchema) + sata.CdRom = mapToSDK_QemuCdRom_Disks(storageSchema) } -func mapToStruct_QemuScsiDisks(scsi *pxapi.QemuScsiDisks, schema map[string]interface{}) { +func mapToSDK_QemuScsiDisks_Disks(scsi *pxapi.QemuScsiDisks, schema map[string]interface{}) { schemaItem, ok := schema["scsi"].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { return } disks := schemaItem[0].(map[string]interface{}) - mapToStruct_QemuScsiStorage(scsi.Disk_0, "scsi0", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_1, "scsi1", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_2, "scsi2", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_3, "scsi3", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_4, "scsi4", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_5, "scsi5", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_6, "scsi6", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_7, "scsi7", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_8, "scsi8", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_9, "scsi9", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_10, "scsi10", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_11, "scsi11", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_12, "scsi12", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_13, "scsi13", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_14, "scsi14", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_15, "scsi15", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_16, "scsi16", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_17, "scsi17", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_18, "scsi18", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_19, "scsi19", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_20, "scsi20", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_21, "scsi21", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_22, "scsi22", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_23, "scsi23", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_24, "scsi24", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_25, "scsi25", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_26, "scsi26", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_27, "scsi27", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_28, "scsi28", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_29, "scsi29", disks) - mapToStruct_QemuScsiStorage(scsi.Disk_30, "scsi30", disks) -} - -func mapToStruct_QemuScsiStorage(scsi *pxapi.QemuScsiStorage, key string, schema map[string]interface{}) { + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_0, "scsi0", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_1, "scsi1", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_2, "scsi2", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_3, "scsi3", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_4, "scsi4", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_5, "scsi5", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_6, "scsi6", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_7, "scsi7", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_8, "scsi8", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_9, "scsi9", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_10, "scsi10", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_11, "scsi11", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_12, "scsi12", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_13, "scsi13", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_14, "scsi14", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_15, "scsi15", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_16, "scsi16", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_17, "scsi17", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_18, "scsi18", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_19, "scsi19", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_20, "scsi20", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_21, "scsi21", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_22, "scsi22", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_23, "scsi23", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_24, "scsi24", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_25, "scsi25", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_26, "scsi26", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_27, "scsi27", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_28, "scsi28", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_29, "scsi29", disks) + mapToSDK_QemuScsiStorage_Disks(scsi.Disk_30, "scsi30", disks) +} + +func mapToSDK_QemuScsiStorage_Disks(scsi *pxapi.QemuScsiStorage, key string, schema map[string]interface{}) { schemaItem, ok := schema[key].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { return @@ -2699,7 +2699,7 @@ func mapToStruct_QemuScsiStorage(scsi *pxapi.QemuScsiStorage, key string, schema disk := tmpDisk[0].(map[string]interface{}) scsi.Disk = &pxapi.QemuScsiDisk{ Backup: disk["backup"].(bool), - Bandwidth: mapToStruct_QemuDiskBandwidth(disk), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disks(disk), Discard: disk["discard"].(bool), EmulateSSD: disk["emulatessd"].(bool), Format: pxapi.QemuDiskFormat(disk["format"].(string)), @@ -2725,7 +2725,7 @@ func mapToStruct_QemuScsiStorage(scsi *pxapi.QemuScsiStorage, key string, schema passthrough := tmpPassthrough[0].(map[string]interface{}) scsi.Passthrough = &pxapi.QemuScsiPassthrough{ Backup: passthrough["backup"].(bool), - Bandwidth: mapToStruct_QemuDiskBandwidth(passthrough), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disks(passthrough), Discard: passthrough["discard"].(bool), EmulateSSD: passthrough["emulatessd"].(bool), File: passthrough["file"].(string), @@ -2745,10 +2745,10 @@ func mapToStruct_QemuScsiStorage(scsi *pxapi.QemuScsiStorage, key string, schema return } if v, ok := storageSchema["cloudinit"].([]interface{}); ok && len(v) == 1 && v[0] != nil { - scsi.CloudInit = mapToStruct_QemuCloudInit(v) + scsi.CloudInit = mapToSDK_QemuCloudInit_Disks(v) return } - scsi.CdRom = mapToStruct_QemuCdRom(storageSchema) + scsi.CdRom = mapToSDK_QemuCdRom_Disks(storageSchema) } func mapToSDK_QemuStorages(d *schema.ResourceData) *pxapi.QemuStorages { @@ -2823,40 +2823,40 @@ func mapToSDK_QemuStorages(d *schema.ResourceData) *pxapi.QemuStorages { if len(schemaItem) == 1 { schemaStorages, ok := schemaItem[0].(map[string]interface{}) if ok { - mapToStruct_QemuIdeDisks(storages.Ide, schemaStorages) - mapToStruct_QemuSataDisks(storages.Sata, schemaStorages) - mapToStruct_QemuScsiDisks(storages.Scsi, schemaStorages) - mapToStruct_QemuVirtIODisks(storages.VirtIO, schemaStorages) + mapToSDK_QemuIdeDisks_Disks(storages.Ide, schemaStorages) + mapToSDK_QemuSataDisks_Disks(storages.Sata, schemaStorages) + mapToSDK_QemuScsiDisks_Disks(storages.Scsi, schemaStorages) + mapToSDK_QemuVirtIODisks_Disks(storages.VirtIO, schemaStorages) } } return &storages } -func mapToStruct_QemuVirtIODisks(virtio *pxapi.QemuVirtIODisks, schema map[string]interface{}) { +func mapToSDK_QemuVirtIODisks_Disks(virtio *pxapi.QemuVirtIODisks, schema map[string]interface{}) { schemaItem, ok := schema["virtio"].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { return } disks := schemaItem[0].(map[string]interface{}) - mapToStruct_VirtIOStorage(virtio.Disk_0, "virtio0", disks) - mapToStruct_VirtIOStorage(virtio.Disk_1, "virtio1", disks) - mapToStruct_VirtIOStorage(virtio.Disk_2, "virtio2", disks) - mapToStruct_VirtIOStorage(virtio.Disk_3, "virtio3", disks) - mapToStruct_VirtIOStorage(virtio.Disk_4, "virtio4", disks) - mapToStruct_VirtIOStorage(virtio.Disk_5, "virtio5", disks) - mapToStruct_VirtIOStorage(virtio.Disk_6, "virtio6", disks) - mapToStruct_VirtIOStorage(virtio.Disk_7, "virtio7", disks) - mapToStruct_VirtIOStorage(virtio.Disk_8, "virtio8", disks) - mapToStruct_VirtIOStorage(virtio.Disk_9, "virtio9", disks) - mapToStruct_VirtIOStorage(virtio.Disk_10, "virtio10", disks) - mapToStruct_VirtIOStorage(virtio.Disk_11, "virtio11", disks) - mapToStruct_VirtIOStorage(virtio.Disk_12, "virtio12", disks) - mapToStruct_VirtIOStorage(virtio.Disk_13, "virtio13", disks) - mapToStruct_VirtIOStorage(virtio.Disk_14, "virtio14", disks) - mapToStruct_VirtIOStorage(virtio.Disk_15, "virtio15", disks) -} - -func mapToStruct_VirtIOStorage(virtio *pxapi.QemuVirtIOStorage, key string, schema map[string]interface{}) { + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_0, "virtio0", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_1, "virtio1", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_2, "virtio2", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_3, "virtio3", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_4, "virtio4", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_5, "virtio5", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_6, "virtio6", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_7, "virtio7", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_8, "virtio8", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_9, "virtio9", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_10, "virtio10", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_11, "virtio11", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_12, "virtio12", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_13, "virtio13", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_14, "virtio14", disks) + mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_15, "virtio15", disks) +} + +func mapToSDK_QemuVirtIOStorage_Disks(virtio *pxapi.QemuVirtIOStorage, key string, schema map[string]interface{}) { schemaItem, ok := schema[key].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { return @@ -2867,7 +2867,7 @@ func mapToStruct_VirtIOStorage(virtio *pxapi.QemuVirtIOStorage, key string, sche disk := tmpDisk[0].(map[string]interface{}) virtio.Disk = &pxapi.QemuVirtIODisk{ Backup: disk["backup"].(bool), - Bandwidth: mapToStruct_QemuDiskBandwidth(disk), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disks(disk), Discard: disk["discard"].(bool), Format: pxapi.QemuDiskFormat(disk["format"].(string)), IOThread: disk["iothread"].(bool), @@ -2892,7 +2892,7 @@ func mapToStruct_VirtIOStorage(virtio *pxapi.QemuVirtIOStorage, key string, sche passthrough := tmpPassthrough[0].(map[string]interface{}) virtio.Passthrough = &pxapi.QemuVirtIOPassthrough{ Backup: passthrough["backup"].(bool), - Bandwidth: mapToStruct_QemuDiskBandwidth(passthrough), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disks(passthrough), Discard: passthrough["discard"].(bool), File: passthrough["file"].(string), IOThread: passthrough["iothread"].(bool), @@ -2910,7 +2910,7 @@ func mapToStruct_VirtIOStorage(virtio *pxapi.QemuVirtIOStorage, key string, sche } return } - virtio.CdRom = mapToStruct_QemuCdRom(storageSchema) + virtio.CdRom = mapToSDK_QemuCdRom_Disks(storageSchema) } // schema definition From d45648d316e33ff7c8fb372e8238dd36f5244878 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 19 Aug 2024 20:16:38 +0200 Subject: [PATCH 05/12] feat: `disk` mapping and unmapping --- proxmox/errors.go | 12 + proxmox/resource_vm_qemu.go | 456 ++++++++++++++++++++++++++++++++++-- 2 files changed, 445 insertions(+), 23 deletions(-) diff --git a/proxmox/errors.go b/proxmox/errors.go index 58bb1c18..fdf08080 100644 --- a/proxmox/errors.go +++ b/proxmox/errors.go @@ -1,7 +1,19 @@ package proxmox +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" +) + const ( errorUint string = "expected type of %s to be a positive number (uint)" errorFloat string = "expected type of %s to be a float" errorString string = "expected type of %s to be string" ) + +func errorDiskSlotDuplicate(slot string) diag.Diagnostics { + return diag.Diagnostics{ + { + Severity: diag.Error, + Summary: "duplicate disk slot", + Detail: "disk slot " + slot + " is already defined"}} +} diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 1f6ddac3..c2b593a2 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -987,7 +987,11 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte } } - config.Disks = mapToSDK_QemuStorages(d) + var diags diag.Diagnostics + config.Disks, diags = mapToSDK_QemuStorages(d) + if diags.HasError() { + return diags + } if len(qemuVgaList) > 0 { config.QemuVga = qemuVgaList[0].(map[string]interface{}) @@ -1038,7 +1042,7 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte nextid = vmID } else { if err != nil { - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } } @@ -1058,7 +1062,7 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte sourceVmrs, err := client.GetVmRefsByName(d.Get("clone").(string)) if err != nil { - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } // prefer source Vm located on same node @@ -1073,7 +1077,7 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte logger.Debug().Str("vmid", d.Id()).Msgf("Cloning VM") err = config.CloneVm(sourceVmr, vmr, client) if err != nil { - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } // give sometime to proxmox to catchup time.Sleep(time.Duration(d.Get("clone_wait").(int)) * time.Second) @@ -1083,7 +1087,7 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte if err != nil { // Set the id because when update config fail the vm is still created d.SetId(resourceId(targetNode, "qemu", vmr.VmId())) - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } } else if d.Get("pxe").(bool) { @@ -1095,7 +1099,7 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte for _, reg := range regs { re, err := regexp.Compile(reg) if err != nil { - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } found = re.MatchString(bs) @@ -1106,18 +1110,18 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte } if !found { - return diag.FromErr(fmt.Errorf("no network boot option matched in 'boot' config")) + return append(diags, diag.FromErr(fmt.Errorf("no network boot option matched in 'boot' config"))...) } log.Print("[DEBUG][QemuVmCreate] create with PXE") err := config.Create(vmr, client) if err != nil { - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } } else { log.Print("[DEBUG][QemuVmCreate] create with ISO") err := config.Create(vmr, client) if err != nil { - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } } } else { @@ -1129,7 +1133,7 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte if err != nil { // Set the id because when update config fail the vm is still created d.SetId(resourceId(targetNode, "qemu", vmr.VmId())) - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } } @@ -1143,7 +1147,7 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte log.Print("[DEBUG][QemuVmCreate] starting VM") _, err := client.StartVm(vmr) if err != nil { - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } // // give sometime to proxmox to catchup // time.Sleep(time.Duration(d.Get("additional_wait").(int)) * time.Second) @@ -1159,7 +1163,7 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte d.Set("reboot_required", rebootRequired) log.Print("[DEBUG][QemuVmCreate] vm creation done!") lock.unlock() - return resourceVmQemuRead(ctx, d, meta) + return append(diags, resourceVmQemuRead(ctx, d, meta)...) } func resourceVmQemuUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { @@ -1276,7 +1280,11 @@ func resourceVmQemuUpdate(ctx context.Context, d *schema.ResourceData, meta inte config.QemuVga = qemuVgaList[0].(map[string]interface{}) } - config.Disks = mapToSDK_QemuStorages(d) + var diags diag.Diagnostics + config.Disks, diags = mapToSDK_QemuStorages(d) + if diags.HasError() { + return diags + } logger.Debug().Int("vmid", vmID).Msgf("Updating VM with the following configuration: %+v", config) @@ -1368,14 +1376,11 @@ func resourceVmQemuUpdate(ctx context.Context, d *schema.ResourceData, meta inte } } - var diags diag.Diagnostics - // Try rebooting the VM is a reboot is required and automatic_reboot is // enabled. Attempt a graceful shutdown or if that fails, force power-off. vmState, err := client.GetVmState(vmr) if err != nil { - diags = append(diags, diag.FromErr(err)...) - return diags + return append(diags, diag.FromErr(err)...) } switch vmState["status"].(string) { // manage the VM state to match the `vm_state` attribute // case stateStarted: does nothing during update as we don't enforce the VM state @@ -1383,7 +1388,7 @@ func resourceVmQemuUpdate(ctx context.Context, d *schema.ResourceData, meta inte if d.Get("vm_state").(string) == stateRunning { // start the VM log.Print("[DEBUG][QemuVmUpdate] starting VM to match `vm_state`") if _, err = client.StartVm(vmr); err != nil { - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } } case stateRunning: @@ -1394,7 +1399,7 @@ func resourceVmQemuUpdate(ctx context.Context, d *schema.ResourceData, meta inte if err != nil { log.Print("[DEBUG][QemuVmUpdate] shutdown failed, stopping VM forcefully") if _, err = client.StopVm(vmr); err != nil { - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } } } else if rebootRequired { // reboot the VM @@ -1405,14 +1410,14 @@ func resourceVmQemuUpdate(ctx context.Context, d *schema.ResourceData, meta inte if err != nil { log.Print("[DEBUG][QemuVmUpdate] reboot failed, stopping VM forcefully") if _, err := client.StopVm(vmr); err != nil { - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } // give sometime to proxmox to catchup dur := time.Duration(d.Get("additional_wait").(int)) * time.Second log.Printf("[DEBUG][QemuVmUpdate] waiting for (%v) before starting the VM again", dur) time.Sleep(dur) if _, err := client.StartVm(vmr); err != nil { - return diag.FromErr(err) + return append(diags, diag.FromErr(err)...) } } } else { // automatic reboots is disabled @@ -2445,6 +2450,10 @@ func mapToStruct_IsoFile(iso string) *pxapi.IsoFile { return &pxapi.IsoFile{File: file, Storage: storage} } +func mapToSDK_QemuCdRom_Disk(slot string, schema map[string]interface{}) *pxapi.QemuCdRom { + return &pxapi.QemuCdRom{Iso: mapToStruct_IsoFile(schema["iso"].(string))} +} + func mapToSDK_QemuCdRom_Disks(schema map[string]interface{}) (cdRom *pxapi.QemuCdRom) { schemaItem, ok := schema["cdrom"].([]interface{}) if !ok { @@ -2460,6 +2469,13 @@ func mapToSDK_QemuCdRom_Disks(schema map[string]interface{}) (cdRom *pxapi.QemuC } } +func mapToSDK_QemuCloudInit_Disk(slot string, schema map[string]interface{}) *pxapi.QemuCloudInitDisk { + return &pxapi.QemuCloudInitDisk{ + Format: pxapi.QemuDiskFormat_Raw, + Storage: schema["storage"].(string), + } +} + func mapToSDK_QemuCloudInit_Disks(schemaItem []interface{}) (ci *pxapi.QemuCloudInitDisk) { ciSchema := schemaItem[0].(map[string]interface{}) return &pxapi.QemuCloudInitDisk{ @@ -2468,6 +2484,27 @@ func mapToSDK_QemuCloudInit_Disks(schemaItem []interface{}) (ci *pxapi.QemuCloud } } +func mapToSDK_QemuDiskBandwidth_Disk(schema map[string]interface{}) pxapi.QemuDiskBandwidth { + return pxapi.QemuDiskBandwidth{ + MBps: pxapi.QemuDiskBandwidthMBps{ + ReadLimit: pxapi.QemuDiskBandwidthMBpsLimit{ + Burst: pxapi.QemuDiskBandwidthMBpsLimitBurst(schema["mbps_r_burst"].(float64)), + Concurrent: pxapi.QemuDiskBandwidthMBpsLimitConcurrent(schema["mbps_r_concurrent"].(float64))}, + WriteLimit: pxapi.QemuDiskBandwidthMBpsLimit{ + Burst: pxapi.QemuDiskBandwidthMBpsLimitBurst(schema["mbps_wr_burst"].(float64)), + Concurrent: pxapi.QemuDiskBandwidthMBpsLimitConcurrent(schema["mbps_wr_concurrent"].(float64))}}, + Iops: pxapi.QemuDiskBandwidthIops{ + ReadLimit: pxapi.QemuDiskBandwidthIopsLimit{ + Burst: pxapi.QemuDiskBandwidthIopsLimitBurst(schema["iops_r_burst"].(int)), + BurstDuration: uint(schema["iops_r_burst_length"].(int)), + Concurrent: pxapi.QemuDiskBandwidthIopsLimitConcurrent(schema["iops_r_concurrent"].(int))}, + WriteLimit: pxapi.QemuDiskBandwidthIopsLimit{ + Burst: pxapi.QemuDiskBandwidthIopsLimitBurst(schema["iops_wr_burst"].(int)), + BurstDuration: uint(schema["iops_wr_burst_length"].(int)), + Concurrent: pxapi.QemuDiskBandwidthIopsLimitConcurrent(schema["iops_wr_concurrent"].(int))}}, + } +} + func mapToSDK_QemuDiskBandwidth_Disks(schema map[string]interface{}) pxapi.QemuDiskBandwidth { return pxapi.QemuDiskBandwidth{ MBps: pxapi.QemuDiskBandwidthMBps{ @@ -2505,6 +2542,20 @@ func mapToSDK_QemuGuestAgent(d *schema.ResourceData) *pxapi.QemuGuestAgent { } } +func mapToSDK_QemuIdeDisks_Disk(ide *pxapi.QemuIdeDisks, id string, schema map[string]interface{}) diag.Diagnostics { + switch id { + case "0": + return mapToSDK_QemuIdeStorage_Disk(ide.Disk_0, schema, id) + case "1": + return mapToSDK_QemuIdeStorage_Disk(ide.Disk_1, schema, id) + case "2": + return mapToSDK_QemuIdeStorage_Disk(ide.Disk_2, schema, id) + case "3": + return mapToSDK_QemuIdeStorage_Disk(ide.Disk_3, schema, id) + } + return nil +} + func mapToSDK_QemuIdeDisks_Disks(ide *pxapi.QemuIdeDisks, schema map[string]interface{}) { schemaItem, ok := schema["ide"].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { @@ -2517,6 +2568,51 @@ func mapToSDK_QemuIdeDisks_Disks(ide *pxapi.QemuIdeDisks, schema map[string]inte mapToSDK_QemuIdeStorage_Disks(ide.Disk_3, "ide3", disks) } +func mapToSDK_QemuIdeStorage_Disk(ide *pxapi.QemuIdeStorage, schema map[string]interface{}, id string) (diags diag.Diagnostics) { + slot := "ide" + id + if ide.CdRom != nil || ide.Disk != nil || ide.Passthrough != nil || ide.CloudInit != nil { + return errorDiskSlotDuplicate(slot) + } + switch schema["type"].(string) { + case "disk": + if schema["passthrough"].(bool) { // passthrough disk + ide.Passthrough = &pxapi.QemuIdePassthrough{ + AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), + Backup: schema["backup"].(bool), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disk(schema), + Cache: pxapi.QemuDiskCache(schema["cache"].(string)), + Discard: schema["discard"].(bool), + EmulateSSD: schema["emulatessd"].(bool), + File: schema["disk_file"].(string), + Replicate: schema["replicate"].(bool), + Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), + WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + } else { // normal disk + ide.Disk = &pxapi.QemuIdeDisk{ + AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), + Backup: schema["backup"].(bool), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disk(schema), + Cache: pxapi.QemuDiskCache(schema["cache"].(string)), + Discard: schema["discard"].(bool), + EmulateSSD: schema["emulatessd"].(bool), + Format: pxapi.QemuDiskFormat(schema["format"].(string)), + Replicate: schema["replicate"].(bool), + Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), + WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + var tmpDiags diag.Diagnostics + ide.Disk.SizeInKibibytes, tmpDiags = mapToSDK_Size_Disk(slot, schema) + diags = append(diags, tmpDiags...) + ide.Disk.Storage, tmpDiags = mapToSDK_Storage_Disk(slot, schema) + diags = append(diags, tmpDiags...) + } + case "cdrom": + ide.CdRom = mapToSDK_QemuCdRom_Disk(slot, schema) + case "cloudinit": + ide.CloudInit = mapToSDK_QemuCloudInit_Disk(slot, schema) + } + return +} + func mapToSDK_QemuIdeStorage_Disks(ide *pxapi.QemuIdeStorage, key string, schema map[string]interface{}) { schemaItem, ok := schema[key].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { @@ -2576,6 +2672,24 @@ func mapToSDK_QemuIdeStorage_Disks(ide *pxapi.QemuIdeStorage, key string, schema ide.CdRom = mapToSDK_QemuCdRom_Disks(storageSchema) } +func mapToSDK_QemuSataDisks_Disk(sata *pxapi.QemuSataDisks, id string, schema map[string]interface{}) diag.Diagnostics { + switch id { + case "0": + return mapToSDK_QemuSataStorage_Disk(sata.Disk_0, schema, id) + case "1": + return mapToSDK_QemuSataStorage_Disk(sata.Disk_1, schema, id) + case "2": + return mapToSDK_QemuSataStorage_Disk(sata.Disk_2, schema, id) + case "3": + return mapToSDK_QemuSataStorage_Disk(sata.Disk_3, schema, id) + case "4": + return mapToSDK_QemuSataStorage_Disk(sata.Disk_4, schema, id) + case "5": + return mapToSDK_QemuSataStorage_Disk(sata.Disk_5, schema, id) + } + return nil +} + func mapToSDK_QemuSataDisks_Disks(sata *pxapi.QemuSataDisks, schema map[string]interface{}) { schemaItem, ok := schema["sata"].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { @@ -2590,6 +2704,51 @@ func mapToSDK_QemuSataDisks_Disks(sata *pxapi.QemuSataDisks, schema map[string]i mapToSDK_QemuSataStorage_Disks(sata.Disk_5, "sata5", disks) } +func mapToSDK_QemuSataStorage_Disk(sata *pxapi.QemuSataStorage, schema map[string]interface{}, id string) (diags diag.Diagnostics) { + slot := "sata" + id + if sata.CdRom != nil || sata.Disk != nil || sata.Passthrough != nil || sata.CloudInit != nil { + return errorDiskSlotDuplicate(slot) + } + switch schema["type"].(string) { + case "disk": + if schema["passthrough"].(bool) { // passthrough disk + sata.Passthrough = &pxapi.QemuSataPassthrough{ + AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), + Backup: schema["backup"].(bool), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disk(schema), + Cache: pxapi.QemuDiskCache(schema["cache"].(string)), + Discard: schema["discard"].(bool), + EmulateSSD: schema["emulatessd"].(bool), + File: schema["disk_file"].(string), + Replicate: schema["replicate"].(bool), + Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), + WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + } else { // normal disk + sata.Disk = &pxapi.QemuSataDisk{ + AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), + Backup: schema["backup"].(bool), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disk(schema), + Cache: pxapi.QemuDiskCache(schema["cache"].(string)), + Discard: schema["discard"].(bool), + EmulateSSD: schema["emulatessd"].(bool), + Format: pxapi.QemuDiskFormat(schema["format"].(string)), + Replicate: schema["replicate"].(bool), + Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), + WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + var tmpDiags diag.Diagnostics + sata.Disk.SizeInKibibytes, tmpDiags = mapToSDK_Size_Disk(slot, schema) + diags = append(diags, tmpDiags...) + sata.Disk.Storage, tmpDiags = mapToSDK_Storage_Disk(slot, schema) + diags = append(diags, tmpDiags...) + } + case "cdrom": + sata.CdRom = mapToSDK_QemuCdRom_Disk(slot, schema) + case "cloudinit": + sata.CloudInit = mapToSDK_QemuCloudInit_Disk(slot, schema) + } + return +} + func mapToSDK_QemuSataStorage_Disks(sata *pxapi.QemuSataStorage, key string, schema map[string]interface{}) { schemaItem, ok := schema[key].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { @@ -2649,6 +2808,74 @@ func mapToSDK_QemuSataStorage_Disks(sata *pxapi.QemuSataStorage, key string, sch sata.CdRom = mapToSDK_QemuCdRom_Disks(storageSchema) } +func mapToSDK_QemuScsiDisks_Disk(scsi *pxapi.QemuScsiDisks, id string, schema map[string]interface{}) diag.Diagnostics { + switch id { + case "0": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_0, schema, id) + case "1": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_1, schema, id) + case "2": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_2, schema, id) + case "3": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_3, schema, id) + case "4": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_4, schema, id) + case "5": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_5, schema, id) + case "6": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_6, schema, id) + case "7": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_7, schema, id) + case "8": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_8, schema, id) + case "9": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_9, schema, id) + case "10": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_10, schema, id) + case "11": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_11, schema, id) + case "12": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_12, schema, id) + case "13": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_13, schema, id) + case "14": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_14, schema, id) + case "15": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_15, schema, id) + case "16": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_16, schema, id) + case "17": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_17, schema, id) + case "18": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_18, schema, id) + case "19": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_19, schema, id) + case "20": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_20, schema, id) + case "21": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_21, schema, id) + case "22": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_22, schema, id) + case "23": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_23, schema, id) + case "24": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_24, schema, id) + case "25": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_25, schema, id) + case "26": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_26, schema, id) + case "27": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_27, schema, id) + case "28": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_28, schema, id) + case "29": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_29, schema, id) + case "30": + return mapToSDK_QemuScsiStorage_Disk(scsi.Disk_30, schema, id) + } + return nil +} + func mapToSDK_QemuScsiDisks_Disks(scsi *pxapi.QemuScsiDisks, schema map[string]interface{}) { schemaItem, ok := schema["scsi"].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { @@ -2688,6 +2915,55 @@ func mapToSDK_QemuScsiDisks_Disks(scsi *pxapi.QemuScsiDisks, schema map[string]i mapToSDK_QemuScsiStorage_Disks(scsi.Disk_30, "scsi30", disks) } +func mapToSDK_QemuScsiStorage_Disk(scsi *pxapi.QemuScsiStorage, schema map[string]interface{}, id string) (diags diag.Diagnostics) { + slot := "scsi" + id + if scsi.CdRom != nil || scsi.Disk != nil || scsi.Passthrough != nil || scsi.CloudInit != nil { + return errorDiskSlotDuplicate(slot) + } + switch schema["type"].(string) { + case "disk": + if schema["passthrough"].(bool) { // passthrough disk + scsi.Passthrough = &pxapi.QemuScsiPassthrough{ + AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), + Backup: schema["backup"].(bool), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disk(schema), + Cache: pxapi.QemuDiskCache(schema["cache"].(string)), + Discard: schema["discard"].(bool), + EmulateSSD: schema["emulatessd"].(bool), + File: schema["disk_file"].(string), + IOThread: schema["iothread"].(bool), + ReadOnly: schema["readonly"].(bool), + Replicate: schema["replicate"].(bool), + Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), + WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + } else { // normal disk + scsi.Disk = &pxapi.QemuScsiDisk{ + AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), + Backup: schema["backup"].(bool), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disk(schema), + Cache: pxapi.QemuDiskCache(schema["cache"].(string)), + Discard: schema["discard"].(bool), + EmulateSSD: schema["emulatessd"].(bool), + Format: pxapi.QemuDiskFormat(schema["format"].(string)), + IOThread: schema["iothread"].(bool), + ReadOnly: schema["readonly"].(bool), + Replicate: schema["replicate"].(bool), + Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), + WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + var tmpDiags diag.Diagnostics + scsi.Disk.SizeInKibibytes, tmpDiags = mapToSDK_Size_Disk(slot, schema) + diags = append(diags, tmpDiags...) + scsi.Disk.Storage, tmpDiags = mapToSDK_Storage_Disk(slot, schema) + diags = append(diags, tmpDiags...) + } + case "cdrom": + scsi.CdRom = mapToSDK_QemuCdRom_Disk(slot, schema) + case "cloudinit": + scsi.CloudInit = mapToSDK_QemuCloudInit_Disk(slot, schema) + } + return +} + func mapToSDK_QemuScsiStorage_Disks(scsi *pxapi.QemuScsiStorage, key string, schema map[string]interface{}) { schemaItem, ok := schema[key].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { @@ -2751,7 +3027,7 @@ func mapToSDK_QemuScsiStorage_Disks(scsi *pxapi.QemuScsiStorage, key string, sch scsi.CdRom = mapToSDK_QemuCdRom_Disks(storageSchema) } -func mapToSDK_QemuStorages(d *schema.ResourceData) *pxapi.QemuStorages { +func mapToSDK_QemuStorages(d *schema.ResourceData) (*pxapi.QemuStorages, diag.Diagnostics) { storages := pxapi.QemuStorages{ Ide: &pxapi.QemuIdeDisks{ Disk_0: &pxapi.QemuIdeStorage{}, @@ -2819,6 +3095,29 @@ func mapToSDK_QemuStorages(d *schema.ResourceData) *pxapi.QemuStorages { Disk_15: &pxapi.QemuVirtIOStorage{}, }, } + diags := make(diag.Diagnostics, 0) + if v, ok := d.GetOk("disk"); ok { + for _, disk := range v.([]interface{}) { + tmpDisk := disk.(map[string]interface{}) + slot := tmpDisk["slot"].(string) + if len(slot) > 6 { // virtio + diags = append(diags, mapToSDK_QemuVirtIODisks_Disk(storages.VirtIO, slot[6:], tmpDisk)...) + continue + } + if len(slot) > 4 { + switch slot[0:4] { + case "sata": + diags = append(diags, mapToSDK_QemuSataDisks_Disk(storages.Sata, slot[4:], tmpDisk)...) + case "scsi": + diags = append(diags, mapToSDK_QemuScsiDisks_Disk(storages.Scsi, slot[4:], tmpDisk)...) + } + continue + } + if len(slot) > 3 { // ide + diags = append(diags, mapToSDK_QemuIdeDisks_Disk(storages.Ide, slot[3:], tmpDisk)...) + } + } + } else { schemaItem := d.Get("disks").([]interface{}) if len(schemaItem) == 1 { schemaStorages, ok := schemaItem[0].(map[string]interface{}) @@ -2829,7 +3128,46 @@ func mapToSDK_QemuStorages(d *schema.ResourceData) *pxapi.QemuStorages { mapToSDK_QemuVirtIODisks_Disks(storages.VirtIO, schemaStorages) } } - return &storages + } + return &storages, diags +} + +func mapToSDK_QemuVirtIODisks_Disk(virtio *pxapi.QemuVirtIODisks, id string, schema map[string]interface{}) diag.Diagnostics { + switch id { + case "0": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_0, schema, id) + case "1": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_1, schema, id) + case "2": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_2, schema, id) + case "3": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_3, schema, id) + case "4": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_4, schema, id) + case "5": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_5, schema, id) + case "6": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_6, schema, id) + case "7": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_7, schema, id) + case "8": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_8, schema, id) + case "9": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_9, schema, id) + case "10": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_10, schema, id) + case "11": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_11, schema, id) + case "12": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_12, schema, id) + case "13": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_13, schema, id) + case "14": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_14, schema, id) + case "15": + return mapToSDK_QemuVirtIOStorage_Disk(virtio.Disk_15, schema, id) + } + return nil } func mapToSDK_QemuVirtIODisks_Disks(virtio *pxapi.QemuVirtIODisks, schema map[string]interface{}) { @@ -2856,6 +3194,55 @@ func mapToSDK_QemuVirtIODisks_Disks(virtio *pxapi.QemuVirtIODisks, schema map[st mapToSDK_QemuVirtIOStorage_Disks(virtio.Disk_15, "virtio15", disks) } +func mapToSDK_QemuVirtIOStorage_Disk(virtio *pxapi.QemuVirtIOStorage, schema map[string]interface{}, id string) (diags diag.Diagnostics) { + slot := "virtio" + id + if virtio.CdRom != nil || virtio.Disk != nil || virtio.Passthrough != nil || virtio.CloudInit != nil { + return errorDiskSlotDuplicate(slot) + } + switch schema["type"].(string) { + case "disk": + if schema["passthrough"].(bool) { // passthrough disk + virtio.Passthrough = &pxapi.QemuVirtIOPassthrough{ + AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), + Backup: schema["backup"].(bool), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disk(schema), + Cache: pxapi.QemuDiskCache(schema["cache"].(string)), + Discard: schema["discard"].(bool), + File: schema["disk_file"].(string), + IOThread: schema["iothread"].(bool), + ReadOnly: schema["readonly"].(bool), + Replicate: schema["replicate"].(bool), + Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), + WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + } else { // normal disk + virtio.Disk = &pxapi.QemuVirtIODisk{ + AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), + Backup: schema["backup"].(bool), + Bandwidth: mapToSDK_QemuDiskBandwidth_Disk(schema), + Cache: pxapi.QemuDiskCache(schema["cache"].(string)), + Discard: schema["discard"].(bool), + Format: pxapi.QemuDiskFormat(schema["format"].(string)), + IOThread: schema["iothread"].(bool), + ReadOnly: schema["readonly"].(bool), + Replicate: schema["replicate"].(bool), + Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), + WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + var tmpDiags diag.Diagnostics + virtio.Disk.SizeInKibibytes, tmpDiags = mapToSDK_Size_Disk(slot, schema) + diags = append(diags, tmpDiags...) + virtio.Disk.Storage, tmpDiags = mapToSDK_Storage_Disk(slot, schema) + diags = append(diags, tmpDiags...) + } + case "cdrom": + virtio.CdRom = mapToSDK_QemuCdRom_Disk(slot, schema) + case "cloudinit": + return diag.Diagnostics{{ + Severity: diag.Error, + Summary: "virtio can't have cloudinit disk"}} + } + return +} + func mapToSDK_QemuVirtIOStorage_Disks(virtio *pxapi.QemuVirtIOStorage, key string, schema map[string]interface{}) { schemaItem, ok := schema[key].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { @@ -2913,6 +3300,29 @@ func mapToSDK_QemuVirtIOStorage_Disks(virtio *pxapi.QemuVirtIOStorage, key strin virtio.CdRom = mapToSDK_QemuCdRom_Disks(storageSchema) } +func mapToSDK_Size_Disk(slot string, schema map[string]interface{}) (pxapi.QemuDiskSize, diag.Diagnostics) { + size := convert_SizeStringToKibibytes_Unsafe(schema["size"].(string)) + if size == 0 { + return 0, diag.Diagnostics{{ + Severity: diag.Error, + Summary: "slot: " + slot + " size is required for disk", + Detail: "slot: " + slot + " size must be greater than 0 when type is disk and passthrough is false"}} + } + return pxapi.QemuDiskSize(size), nil + +} + +func mapToSDK_Storage_Disk(slot string, schema map[string]interface{}) (string, diag.Diagnostics) { + v := schema["storage"].(string) + if v == "" { + return "", diag.Diagnostics{{ + Severity: diag.Error, + Summary: "slot: " + slot + " storage is required for disk", + Detail: "slot: " + slot + " storage may not be empty when type is disk and passthrough is false"}} + } + return v, nil +} + // schema definition func schema_CdRom(path string, ci bool) *schema.Schema { var conflicts []string From 3ef50258775969b9c89b4ff2815420e9833ab5d9 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 26 Aug 2024 21:35:27 +0200 Subject: [PATCH 06/12] feat: read disks into terraform --- proxmox/resource_vm_qemu.go | 460 +++++++++++++++++++++++++++++++++++- 1 file changed, 455 insertions(+), 5 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index c2b593a2..5e70f2cd 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -1580,7 +1580,9 @@ func resourceVmQemuRead(ctx context.Context, d *schema.ResourceData, meta interf d.Set("smbios", ReadSmbiosArgs(config.Smbios1)) d.Set("linked_vmid", config.LinkedVmId) - d.Set("disks", mapFromStruct_ConfigQemu(config.Disks)) + if config.Disks != nil { + mapToTerraform_QemuStorage(d, *config.Disks) + } mapFromStruct_QemuGuestAgent(d, config.Agent) // Some dirty hacks to populate undefined keys with default values. @@ -2044,10 +2046,8 @@ func getPrimaryIP(config *pxapi.ConfigQemu, vmr *pxapi.VmRef, client *pxapi.Clie } // Map struct to the terraform schema -func mapFromStruct_ConfigQemu(config *pxapi.QemuStorages) []interface{} { - if config == nil { - return nil - } + +func mapToTerraform_QemuDisks_Disks(config pxapi.QemuStorages) []interface{} { ide := mapFromStruct_QemuIdeDisks(config.Ide) sata := mapFromStruct_QemuSataDisks(config.Sata) scsi := mapFromStruct_QemuScsiDisks(config.Scsi) @@ -2079,6 +2079,14 @@ func mapFromStruct_LinkedCloneId(id *uint) int { return -1 } +// nil check is done by the caller +func mapToTerraform_QemuCdRom_Disk_unsafe(config *pxapi.QemuCdRom) map[string]interface{} { + return map[string]interface{}{ + "type": "cdrom", + "passthrough": config.Passthrough, + "iso": mapFormStruct_IsoFile(config.Iso)} +} + func mapFormStruct_QemuCdRom(config *pxapi.QemuCdRom) []interface{} { if config == nil { return nil @@ -2095,6 +2103,13 @@ func mapFormStruct_QemuCdRom(config *pxapi.QemuCdRom) []interface{} { } } +// nil check is done by the caller +func mapToTerraform_QemuCloudInit_Disk_unsafe(config *pxapi.QemuCloudInitDisk) map[string]interface{} { + return map[string]interface{}{ + "type": "cloudinit", + "storage": config.Storage} +} + // nil pointer check is done by the caller func mapFromStruct_QemuCloudInit_unsafe(config *pxapi.QemuCloudInitDisk) []interface{} { return []interface{}{ @@ -2104,6 +2119,26 @@ func mapFromStruct_QemuCloudInit_unsafe(config *pxapi.QemuCloudInitDisk) []inter "storage": string(config.Storage)}}}} } +func mapToTerraform_QemuDisks_Disk(config pxapi.QemuStorages) []map[string]interface{} { + disks := make([]map[string]interface{}, 0, 56) // max is sum of underlying arrays + if ideDisks := mapToTerraform_QemuIdeDisks_Disk(config.Ide); ideDisks != nil { + disks = append(disks, ideDisks...) + } + if sataDisks := mapToTerraform_QemuSataDisks_Disk(config.Sata); sataDisks != nil { + disks = append(disks, sataDisks...) + } + if scsiDisks := mapToTerraform_QemuScsiDisks_Disk(config.Scsi); scsiDisks != nil { + disks = append(disks, scsiDisks...) + } + if virtioDisks := mapToTerraform_QemuVirtIODisks_Disk(config.VirtIO); virtioDisks != nil { + disks = append(disks, virtioDisks...) + } + if len(disks) == 0 { + return nil + } + return disks +} + func mapFormStruct_QemuDiskBandwidth(params map[string]interface{}, config pxapi.QemuDiskBandwidth) { params["mbps_r_burst"] = float64(config.MBps.ReadLimit.Burst) params["mbps_r_concurrent"] = float64(config.MBps.ReadLimit.Concurrent) @@ -2130,6 +2165,26 @@ func mapFromStruct_QemuGuestAgent(d *schema.ResourceData, config *pxapi.QemuGues } } +func mapToTerraform_QemuIdeDisks_Disk(config *pxapi.QemuIdeDisks) []map[string]interface{} { + if config == nil { + return nil + } + disks := make([]map[string]interface{}, 0, 3) + if disk := mapToTerraform_QemuIdeStorage_Disk(config.Disk_0, "ide0"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuIdeStorage_Disk(config.Disk_1, "ide1"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuIdeStorage_Disk(config.Disk_2, "ide2"); disk != nil { + disks = append(disks, disk) + } + if len(disks) == 0 { + return nil + } + return disks +} + func mapFromStruct_QemuIdeDisks(config *pxapi.QemuIdeDisks) []interface{} { if config == nil { return nil @@ -2142,6 +2197,54 @@ func mapFromStruct_QemuIdeDisks(config *pxapi.QemuIdeDisks) []interface{} { "ide3": mapFromStruct_QemuIdeStorage(config.Disk_3)}} } +func mapToTerraform_QemuIdeStorage_Disk(config *pxapi.QemuIdeStorage, slot string) (settings map[string]interface{}) { + if config == nil { + return nil + } + if config.Disk != nil { + settings = map[string]interface{}{ + "asyncio": string(config.Disk.AsyncIO), + "backup": config.Disk.Backup, + "cache": string(config.Disk.Cache), + "discard": config.Disk.Discard, + "emulatessd": config.Disk.EmulateSSD, + "format": string(config.Disk.Format), + "id": int(config.Disk.Id), + "linked_disk_id": mapFromStruct_LinkedCloneId(config.Disk.LinkedDiskId), + "replicate": config.Disk.Replicate, + "serial": string(config.Disk.Serial), + "size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)), + "storage": string(config.Disk.Storage), + "type": "disk", + "wwn": string(config.Disk.WorldWideName)} + mapFormStruct_QemuDiskBandwidth(settings, config.Disk.Bandwidth) + } + if config.Passthrough != nil { + settings = map[string]interface{}{ + "asyncio": string(config.Disk.AsyncIO), + "backup": config.Disk.Backup, + "cache": string(config.Disk.Cache), + "discard": config.Disk.Discard, + "emulatessd": config.Disk.EmulateSSD, + "file": config.Passthrough.File, + "passthrough": true, + "replicate": config.Disk.Replicate, + "serial": string(config.Disk.Serial), + "size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)), + "type": "disk", + "wwn": string(config.Disk.WorldWideName)} + mapFormStruct_QemuDiskBandwidth(settings, config.Passthrough.Bandwidth) + } + if config.CdRom != nil { + settings = mapToTerraform_QemuCdRom_Disk_unsafe(config.CdRom) + } + if config.CloudInit != nil { + settings = mapToTerraform_QemuCloudInit_Disk_unsafe(config.CloudInit) + } + settings["slot"] = slot + return settings +} + func mapFromStruct_QemuIdeStorage(config *pxapi.QemuIdeStorage) []interface{} { if config == nil { return nil @@ -2193,6 +2296,35 @@ func mapFromStruct_QemuIdeStorage(config *pxapi.QemuIdeStorage) []interface{} { return mapFormStruct_QemuCdRom(config.CdRom) } +func mapToTerraform_QemuSataDisks_Disk(config *pxapi.QemuSataDisks) []map[string]interface{} { + if config == nil { + return nil + } + disks := make([]map[string]interface{}, 0, 6) + if disk := mapToTerraform_QemuSataStorage_Disk(config.Disk_0, "sata0"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuSataStorage_Disk(config.Disk_1, "sata1"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuSataStorage_Disk(config.Disk_2, "sata2"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuSataStorage_Disk(config.Disk_2, "sata3"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuSataStorage_Disk(config.Disk_2, "sata4"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuSataStorage_Disk(config.Disk_2, "sata5"); disk != nil { + disks = append(disks, disk) + } + if len(disks) == 0 { + return nil + } + return disks +} + func mapFromStruct_QemuSataDisks(config *pxapi.QemuSataDisks) []interface{} { if config == nil { return nil @@ -2209,6 +2341,54 @@ func mapFromStruct_QemuSataDisks(config *pxapi.QemuSataDisks) []interface{} { } } +func mapToTerraform_QemuSataStorage_Disk(config *pxapi.QemuSataStorage, slot string) (settings map[string]interface{}) { + if config == nil { + return nil + } + if config.Disk != nil { + settings = map[string]interface{}{ + "asyncio": string(config.Disk.AsyncIO), + "backup": config.Disk.Backup, + "cache": string(config.Disk.Cache), + "discard": config.Disk.Discard, + "emulatessd": config.Disk.EmulateSSD, + "format": string(config.Disk.Format), + "id": int(config.Disk.Id), + "linked_disk_id": mapFromStruct_LinkedCloneId(config.Disk.LinkedDiskId), + "replicate": config.Disk.Replicate, + "serial": string(config.Disk.Serial), + "size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)), + "storage": string(config.Disk.Storage), + "type": "disk", + "wwn": string(config.Disk.WorldWideName)} + mapFormStruct_QemuDiskBandwidth(settings, config.Disk.Bandwidth) + } + if config.Passthrough != nil { + settings = map[string]interface{}{ + "asyncio": string(config.Disk.AsyncIO), + "backup": config.Disk.Backup, + "cache": string(config.Disk.Cache), + "discard": config.Disk.Discard, + "emulatessd": config.Disk.EmulateSSD, + "file": config.Passthrough.File, + "passthrough": true, + "replicate": config.Disk.Replicate, + "serial": string(config.Disk.Serial), + "size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)), + "type": "disk", + "wwn": string(config.Disk.WorldWideName)} + mapFormStruct_QemuDiskBandwidth(settings, config.Passthrough.Bandwidth) + } + if config.CdRom != nil { + settings = mapToTerraform_QemuCdRom_Disk_unsafe(config.CdRom) + } + if config.CloudInit != nil { + settings = mapToTerraform_QemuCloudInit_Disk_unsafe(config.CloudInit) + } + settings["slot"] = slot + return settings +} + func mapFromStruct_QemuSataStorage(config *pxapi.QemuSataStorage) []interface{} { if config == nil { return nil @@ -2260,6 +2440,110 @@ func mapFromStruct_QemuSataStorage(config *pxapi.QemuSataStorage) []interface{} return mapFormStruct_QemuCdRom(config.CdRom) } +func mapToTerraform_QemuScsiDisks_Disk(config *pxapi.QemuScsiDisks) []map[string]interface{} { + if config == nil { + return nil + } + disks := make([]map[string]interface{}, 0, 31) + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_0, "scsi0"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_1, "scsi1"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_2, "scsi2"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_3, "scsi3"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_4, "scsi4"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_5, "scsi5"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_6, "scsi6"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_7, "scsi7"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_8, "scsi8"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_9, "scsi9"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_10, "scsi10"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_11, "scsi11"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_12, "scsi12"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_13, "scsi13"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_14, "scsi14"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_15, "scsi15"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_16, "scsi16"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_17, "scsi17"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_18, "scsi18"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_19, "scsi19"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_20, "scsi20"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_21, "scsi21"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_22, "scsi22"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_23, "scsi23"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_24, "scsi24"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_25, "scsi25"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_26, "scsi26"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_27, "scsi27"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_28, "scsi28"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_29, "scsi29"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuScsiStorage_Disk(config.Disk_30, "scsi30"); disk != nil { + disks = append(disks, disk) + } + if len(disks) == 0 { + return nil + } + return disks +} + func mapFromStruct_QemuScsiDisks(config *pxapi.QemuScsiDisks) []interface{} { if config == nil { return nil @@ -2301,6 +2585,58 @@ func mapFromStruct_QemuScsiDisks(config *pxapi.QemuScsiDisks) []interface{} { } } +func mapToTerraform_QemuScsiStorage_Disk(config *pxapi.QemuScsiStorage, slot string) (settings map[string]interface{}) { + if config == nil { + return nil + } + if config.Disk != nil { + settings = map[string]interface{}{ + "asyncio": string(config.Disk.AsyncIO), + "backup": config.Disk.Backup, + "cache": string(config.Disk.Cache), + "discard": config.Disk.Discard, + "emulatessd": config.Disk.EmulateSSD, + "format": string(config.Disk.Format), + "id": int(config.Disk.Id), + "iothread": config.Disk.IOThread, + "linked_disk_id": mapFromStruct_LinkedCloneId(config.Disk.LinkedDiskId), + "readonly": config.Disk.ReadOnly, + "replicate": config.Disk.Replicate, + "serial": string(config.Disk.Serial), + "size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)), + "storage": string(config.Disk.Storage), + "type": "disk", + "wwn": string(config.Disk.WorldWideName)} + mapFormStruct_QemuDiskBandwidth(settings, config.Disk.Bandwidth) + } + if config.Passthrough != nil { + settings = map[string]interface{}{ + "asyncio": string(config.Disk.AsyncIO), + "backup": config.Disk.Backup, + "cache": string(config.Disk.Cache), + "discard": config.Disk.Discard, + "emulatessd": config.Disk.EmulateSSD, + "file": config.Passthrough.File, + "iothread": config.Disk.IOThread, + "passthrough": true, + "readonly": config.Disk.ReadOnly, + "replicate": config.Disk.Replicate, + "serial": string(config.Disk.Serial), + "size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)), + "type": "disk", + "wwn": string(config.Disk.WorldWideName)} + mapFormStruct_QemuDiskBandwidth(settings, config.Passthrough.Bandwidth) + } + if config.CdRom != nil { + settings = mapToTerraform_QemuCdRom_Disk_unsafe(config.CdRom) + } + if config.CloudInit != nil { + settings = mapToTerraform_QemuCloudInit_Disk_unsafe(config.CloudInit) + } + settings["slot"] = slot + return settings +} + func mapFromStruct_QemuScsiStorage(config *pxapi.QemuScsiStorage) []interface{} { if config == nil { return nil @@ -2356,6 +2692,73 @@ func mapFromStruct_QemuScsiStorage(config *pxapi.QemuScsiStorage) []interface{} return mapFormStruct_QemuCdRom(config.CdRom) } +func mapToTerraform_QemuStorage(d *schema.ResourceData, config pxapi.QemuStorages) { + if _, ok := d.GetOk("disk"); ok { + d.Set("disk", mapToTerraform_QemuDisks_Disk(config)) + } else { + d.Set("disks", mapToTerraform_QemuDisks_Disks(config)) + } +} + +func mapToTerraform_QemuVirtIODisks_Disk(config *pxapi.QemuVirtIODisks) []map[string]interface{} { + if config == nil { + return nil + } + disks := make([]map[string]interface{}, 0, 16) + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_0, "virtio0"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_1, "virtio1"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_2, "virtio2"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_3, "virtio3"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_4, "virtio4"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_5, "virtio5"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_6, "virtio6"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_7, "virtio7"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_8, "virtio8"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_9, "virtio9"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_10, "virtio10"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_11, "virtio11"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_12, "virtio12"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_13, "virtio13"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_14, "virtio14"); disk != nil { + disks = append(disks, disk) + } + if disk := mapToTerraform_QemuVirtIOStorage_Disk(config.Disk_15, "virtio15"); disk != nil { + disks = append(disks, disk) + } + if len(disks) == 0 { + return nil + } + return disks +} + func mapFromStruct_QemuVirtIODisks(config *pxapi.QemuVirtIODisks) []interface{} { if config == nil { return nil @@ -2382,6 +2785,53 @@ func mapFromStruct_QemuVirtIODisks(config *pxapi.QemuVirtIODisks) []interface{} } } +func mapToTerraform_QemuVirtIOStorage_Disk(config *pxapi.QemuVirtIOStorage, slot string) (settings map[string]interface{}) { + if config == nil { + return nil + } + if config.Disk != nil { + settings = map[string]interface{}{ + "asyncio": string(config.Disk.AsyncIO), + "backup": config.Disk.Backup, + "cache": string(config.Disk.Cache), + "discard": config.Disk.Discard, + "format": string(config.Disk.Format), + "id": int(config.Disk.Id), + "iothread": config.Disk.IOThread, + "linked_disk_id": mapFromStruct_LinkedCloneId(config.Disk.LinkedDiskId), + "readonly": config.Disk.ReadOnly, + "replicate": config.Disk.Replicate, + "serial": string(config.Disk.Serial), + "size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)), + "storage": string(config.Disk.Storage), + "type": "disk", + "wwn": string(config.Disk.WorldWideName)} + mapFormStruct_QemuDiskBandwidth(settings, config.Disk.Bandwidth) + } + if config.Passthrough != nil { + settings = map[string]interface{}{ + "asyncio": string(config.Passthrough.AsyncIO), + "backup": config.Passthrough.Backup, + "cache": string(config.Passthrough.Cache), + "discard": config.Passthrough.Discard, + "file": config.Passthrough.File, + "iothread": config.Passthrough.IOThread, + "passthrough": true, + "readonly": config.Passthrough.ReadOnly, + "replicate": config.Passthrough.Replicate, + "serial": string(config.Passthrough.Serial), + "size": convert_KibibytesToString(int64(config.Passthrough.SizeInKibibytes)), + "type": "disk", + "wwn": string(config.Passthrough.WorldWideName)} + mapFormStruct_QemuDiskBandwidth(settings, config.Passthrough.Bandwidth) + } + if config.CdRom != nil { + settings = mapToTerraform_QemuCdRom_Disk_unsafe(config.CdRom) + } + settings["slot"] = slot + return settings +} + func mapFromStruct_QemuVirtIOStorage(config *pxapi.QemuVirtIOStorage) []interface{} { if config == nil { return nil From 000d4ba0111573145502516928aec4a3e600fe7e Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 27 Aug 2024 07:56:39 +0200 Subject: [PATCH 07/12] feat: warnings when settings are ignored --- proxmox/resource_vm_qemu.go | 170 +++++++++++++++++++++++++++++++++--- 1 file changed, 159 insertions(+), 11 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 5e70f2cd..2e234489 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -2900,8 +2900,15 @@ func mapToStruct_IsoFile(iso string) *pxapi.IsoFile { return &pxapi.IsoFile{File: file, Storage: storage} } -func mapToSDK_QemuCdRom_Disk(slot string, schema map[string]interface{}) *pxapi.QemuCdRom { - return &pxapi.QemuCdRom{Iso: mapToStruct_IsoFile(schema["iso"].(string))} +func mapToSDK_QemuCdRom_Disk(slot string, schema map[string]interface{}) (*pxapi.QemuCdRom, diag.Diagnostics) { + diags := warnings_CdromAndCloudinit(slot, "cdrom", schema) + if schema["storage"].(string) != "" { + diags = append(diags, warningDisk(slot, "storage", "type", "cdrom", "")) + } + if schema["passthrough"].(bool) { + return &pxapi.QemuCdRom{Passthrough: true}, diags + } + return &pxapi.QemuCdRom{Iso: mapToStruct_IsoFile(schema["iso"].(string))}, diags } func mapToSDK_QemuCdRom_Disks(schema map[string]interface{}) (cdRom *pxapi.QemuCdRom) { @@ -2919,11 +2926,18 @@ func mapToSDK_QemuCdRom_Disks(schema map[string]interface{}) (cdRom *pxapi.QemuC } } -func mapToSDK_QemuCloudInit_Disk(slot string, schema map[string]interface{}) *pxapi.QemuCloudInitDisk { +func mapToSDK_QemuCloudInit_Disk(slot string, schema map[string]interface{}) (*pxapi.QemuCloudInitDisk, diag.Diagnostics) { + diags := warnings_CdromAndCloudinit(slot, "cloudinit", schema) + if schema["iso"].(string) != "" { + diags = append(diags, warningDisk(slot, "iso", "type", "cloudinit", "")) + } + if schema["passthrough"].(bool) { + diags = append(diags, warningDisk(slot, "passthrough", "type", "cloudinit", "")) + } return &pxapi.QemuCloudInitDisk{ Format: pxapi.QemuDiskFormat_Raw, Storage: schema["storage"].(string), - } + }, diags } func mapToSDK_QemuCloudInit_Disks(schemaItem []interface{}) (ci *pxapi.QemuCloudInitDisk) { @@ -3025,6 +3039,15 @@ func mapToSDK_QemuIdeStorage_Disk(ide *pxapi.QemuIdeStorage, schema map[string]i } switch schema["type"].(string) { case "disk": + if schema["iothread"].(bool) { + diags = append(diags, warningDisk(slot, "iothread", "slot", slot, "")) + } + if schema["iso"].(string) != "" { + diags = append(diags, warningDisk(slot, "iso", "slot", slot, "")) + } + if schema["readonly"].(bool) { + diags = append(diags, warningDisk(slot, "readonly", "slot", slot, "")) + } if schema["passthrough"].(bool) { // passthrough disk ide.Passthrough = &pxapi.QemuIdePassthrough{ AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), @@ -3037,6 +3060,7 @@ func mapToSDK_QemuIdeStorage_Disk(ide *pxapi.QemuIdeStorage, schema map[string]i Replicate: schema["replicate"].(bool), Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + diags = append(diags, warnings_DiskPassthrough(slot, schema)...) } else { // normal disk ide.Disk = &pxapi.QemuIdeDisk{ AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), @@ -3054,11 +3078,14 @@ func mapToSDK_QemuIdeStorage_Disk(ide *pxapi.QemuIdeStorage, schema map[string]i diags = append(diags, tmpDiags...) ide.Disk.Storage, tmpDiags = mapToSDK_Storage_Disk(slot, schema) diags = append(diags, tmpDiags...) + if schema["disk_file"].(string) != "" { + diags = append(diags, warningDisk(slot, "disk_file", "type", "disk", "")) + } } case "cdrom": - ide.CdRom = mapToSDK_QemuCdRom_Disk(slot, schema) + ide.CdRom, diags = mapToSDK_QemuCdRom_Disk(slot, schema) case "cloudinit": - ide.CloudInit = mapToSDK_QemuCloudInit_Disk(slot, schema) + ide.CloudInit, diags = mapToSDK_QemuCloudInit_Disk(slot, schema) } return } @@ -3161,6 +3188,15 @@ func mapToSDK_QemuSataStorage_Disk(sata *pxapi.QemuSataStorage, schema map[strin } switch schema["type"].(string) { case "disk": + if schema["iothread"].(bool) { + diags = append(diags, warningDisk(slot, "iothread", "slot", slot, "")) + } + if schema["iso"].(string) != "" { + diags = append(diags, warningDisk(slot, "iso", "slot", slot, "")) + } + if schema["readonly"].(bool) { + diags = append(diags, warningDisk(slot, "readonly", "slot", slot, "")) + } if schema["passthrough"].(bool) { // passthrough disk sata.Passthrough = &pxapi.QemuSataPassthrough{ AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), @@ -3173,6 +3209,7 @@ func mapToSDK_QemuSataStorage_Disk(sata *pxapi.QemuSataStorage, schema map[strin Replicate: schema["replicate"].(bool), Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + diags = append(diags, warnings_DiskPassthrough(slot, schema)...) } else { // normal disk sata.Disk = &pxapi.QemuSataDisk{ AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), @@ -3190,11 +3227,14 @@ func mapToSDK_QemuSataStorage_Disk(sata *pxapi.QemuSataStorage, schema map[strin diags = append(diags, tmpDiags...) sata.Disk.Storage, tmpDiags = mapToSDK_Storage_Disk(slot, schema) diags = append(diags, tmpDiags...) + if schema["disk_file"].(string) != "" { + diags = append(diags, warningDisk(slot, "disk_file", "type", "disk", "")) + } } case "cdrom": - sata.CdRom = mapToSDK_QemuCdRom_Disk(slot, schema) + sata.CdRom, diags = mapToSDK_QemuCdRom_Disk(slot, schema) case "cloudinit": - sata.CloudInit = mapToSDK_QemuCloudInit_Disk(slot, schema) + sata.CloudInit, diags = mapToSDK_QemuCloudInit_Disk(slot, schema) } return } @@ -3372,6 +3412,9 @@ func mapToSDK_QemuScsiStorage_Disk(scsi *pxapi.QemuScsiStorage, schema map[strin } switch schema["type"].(string) { case "disk": + if schema["iso"].(string) != "" { + diags = append(diags, warningDisk(slot, "iso", "slot", slot, "")) + } if schema["passthrough"].(bool) { // passthrough disk scsi.Passthrough = &pxapi.QemuScsiPassthrough{ AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), @@ -3386,6 +3429,7 @@ func mapToSDK_QemuScsiStorage_Disk(scsi *pxapi.QemuScsiStorage, schema map[strin Replicate: schema["replicate"].(bool), Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + diags = append(diags, warnings_DiskPassthrough(slot, schema)...) } else { // normal disk scsi.Disk = &pxapi.QemuScsiDisk{ AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), @@ -3405,11 +3449,14 @@ func mapToSDK_QemuScsiStorage_Disk(scsi *pxapi.QemuScsiStorage, schema map[strin diags = append(diags, tmpDiags...) scsi.Disk.Storage, tmpDiags = mapToSDK_Storage_Disk(slot, schema) diags = append(diags, tmpDiags...) + if schema["disk_file"].(string) != "" { + diags = append(diags, warningDisk(slot, "disk_file", "type", "disk", "")) + } } case "cdrom": - scsi.CdRom = mapToSDK_QemuCdRom_Disk(slot, schema) + scsi.CdRom, diags = mapToSDK_QemuCdRom_Disk(slot, schema) case "cloudinit": - scsi.CloudInit = mapToSDK_QemuCloudInit_Disk(slot, schema) + scsi.CloudInit, diags = mapToSDK_QemuCloudInit_Disk(slot, schema) } return } @@ -3651,6 +3698,12 @@ func mapToSDK_QemuVirtIOStorage_Disk(virtio *pxapi.QemuVirtIOStorage, schema map } switch schema["type"].(string) { case "disk": + if schema["emulatessd"].(bool) { + diags = append(diags, warningDisk(slot, "emulatessd", "slot", slot, "")) + } + if schema["iso"].(string) != "" { + diags = append(diags, warningDisk(slot, "iso", "slot", slot, "")) + } if schema["passthrough"].(bool) { // passthrough disk virtio.Passthrough = &pxapi.QemuVirtIOPassthrough{ AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), @@ -3664,6 +3717,7 @@ func mapToSDK_QemuVirtIOStorage_Disk(virtio *pxapi.QemuVirtIOStorage, schema map Replicate: schema["replicate"].(bool), Serial: pxapi.QemuDiskSerial(schema["serial"].(string)), WorldWideName: pxapi.QemuWorldWideName(schema["wwn"].(string))} + diags = append(diags, warnings_DiskPassthrough(slot, schema)...) } else { // normal disk virtio.Disk = &pxapi.QemuVirtIODisk{ AsyncIO: pxapi.QemuDiskAsyncIO(schema["asyncio"].(string)), @@ -3682,9 +3736,12 @@ func mapToSDK_QemuVirtIOStorage_Disk(virtio *pxapi.QemuVirtIOStorage, schema map diags = append(diags, tmpDiags...) virtio.Disk.Storage, tmpDiags = mapToSDK_Storage_Disk(slot, schema) diags = append(diags, tmpDiags...) + if schema["disk_file"].(string) != "" { + diags = append(diags, warningDisk(slot, "disk_file", "type", "disk", "")) + } } case "cdrom": - virtio.CdRom = mapToSDK_QemuCdRom_Disk(slot, schema) + virtio.CdRom, diags = mapToSDK_QemuCdRom_Disk(slot, schema) case "cloudinit": return diag.Diagnostics{{ Severity: diag.Error, @@ -4417,3 +4474,94 @@ func schema_PassthroughSize() *schema.Schema { Computed: true, } } + +func warningDisk(slot, setting, property, value, extra string) diag.Diagnostic { + return diag.Diagnostic{ + Severity: diag.Warning, + Summary: "slot: " + slot + " " + setting + " is ignored when " + property + " = " + value + extra} +} + +func warnings_CdromAndCloudinit(slot, kind string, schema map[string]interface{}) (diags diag.Diagnostics) { + if schema["asyncio"].(string) != "" { + diags = append(diags, warningDisk(slot, "asyncio", "type", kind, "")) + } + if schema["cache"].(string) != "" { + diags = append(diags, warningDisk(slot, "cache", "type", kind, "")) + } + if schema["discard"].(bool) { + diags = append(diags, warningDisk(slot, "discard", "type", kind, "")) + } + if schema["disk_file"].(string) != "" { + diags = append(diags, warningDisk(slot, "disk_file", "type", kind, "")) + } + if schema["emulatessd"].(bool) { + diags = append(diags, warningDisk(slot, "emulatessd", "type", kind, "")) + } + if schema["iops_r_burst"].(int) != 0 { + diags = append(diags, warningDisk(slot, "iops_r_burst", "type", kind, "")) + } + if schema["iops_r_burst_length"].(int) != 0 { + diags = append(diags, warningDisk(slot, "iops_r_burst_length", "type", kind, "")) + } + if schema["iops_r_concurrent"].(int) != 0 { + diags = append(diags, warningDisk(slot, "iops_r_concurrent", "type", kind, "")) + } + if schema["iops_wr_burst"].(int) != 0 { + diags = append(diags, warningDisk(slot, "iops_wr_burst", "type", kind, "")) + } + if schema["iops_wr_burst_length"].(int) != 0 { + diags = append(diags, warningDisk(slot, "iops_wr_burst_length", "type", kind, "")) + } + if schema["iops_wr_concurrent"].(int) != 0 { + diags = append(diags, warningDisk(slot, "iops_wr_concurrent", "type", kind, "")) + } + if schema["iothread"].(bool) { + diags = append(diags, warningDisk(slot, "iothread", "type", kind, "")) + } + if schema["mbps_r_burst"].(float64) != 0.0 { + diags = append(diags, warningDisk(slot, "mbps_r_burst", "type", kind, "")) + } + if schema["mbps_r_concurrent"].(float64) != 0.0 { + diags = append(diags, warningDisk(slot, "mbps_r_concurrent", "type", kind, "")) + } + if schema["mbps_wr_burst"].(float64) != 0.0 { + diags = append(diags, warningDisk(slot, "mbps_wr_burst", "type", kind, "")) + } + if schema["mbps_wr_concurrent"].(float64) != 0.0 { + diags = append(diags, warningDisk(slot, "mbps_wr_concurrent", "type", kind, "")) + } + if schema["readonly"].(bool) { + diags = append(diags, warningDisk(slot, "readonly", "type", kind, "")) + } + if schema["replicate"].(bool) { + diags = append(diags, warningDisk(slot, "replicate", "type", kind, "")) + } + if schema["serial"].(string) != "" { + diags = append(diags, warningDisk(slot, "serial", "type", kind, "")) + } + if schema["size"].(string) != "" { + diags = append(diags, warningDisk(slot, "size", "type", kind, "")) + } + if schema["wwn"].(string) != "" { + diags = append(diags, warningDisk(slot, "wwn", "type", kind, "")) + } + return +} + +func warnings_DiskPassthrough(slot string, schema map[string]interface{}) diag.Diagnostics { + if schema["storage"].(string) != "" { + return diag.Diagnostics{warningDisk(slot, "storage", "type", "passthrough", "and slot = "+slot)} + } + return diag.Diagnostics{} +} + +func warning_iothread_Disk(slot, property, value, extra string) diag.Diagnostic { + return warningDisk(slot, "iothread", property, value, extra) +} + +func warning_iso_Disk(slot string, schema map[string]interface{}) diag.Diagnostics { + if schema["iso"].(string) != "" { + return diag.Diagnostics{warningDisk(slot, "iso", "type", "disk", "")} + } + return nil +} From 5d72c11327b2a516181c399dbe4036b5f88bf053 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 27 Aug 2024 08:16:03 +0200 Subject: [PATCH 08/12] refactor: rename functions --- proxmox/resource_vm_qemu.go | 158 ++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 2e234489..1ce95896 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -2048,10 +2048,10 @@ func getPrimaryIP(config *pxapi.ConfigQemu, vmr *pxapi.VmRef, client *pxapi.Clie // Map struct to the terraform schema func mapToTerraform_QemuDisks_Disks(config pxapi.QemuStorages) []interface{} { - ide := mapFromStruct_QemuIdeDisks(config.Ide) - sata := mapFromStruct_QemuSataDisks(config.Sata) - scsi := mapFromStruct_QemuScsiDisks(config.Scsi) - virtio := mapFromStruct_QemuVirtIODisks(config.VirtIO) + ide := mapToTerraform_QemuIdeDisks_Disks(config.Ide) + sata := mapToTerraform_QemuSataDisks_Disks(config.Sata) + scsi := mapToTerraform_QemuScsiDisks_Disks(config.Scsi) + virtio := mapToTerraform_QemuVirtIODisks_Disks(config.VirtIO) if ide == nil && sata == nil && scsi == nil && virtio == nil { return nil } @@ -2087,7 +2087,7 @@ func mapToTerraform_QemuCdRom_Disk_unsafe(config *pxapi.QemuCdRom) map[string]in "iso": mapFormStruct_IsoFile(config.Iso)} } -func mapFormStruct_QemuCdRom(config *pxapi.QemuCdRom) []interface{} { +func mapToTerraform_QemuCdRom_Disks(config *pxapi.QemuCdRom) []interface{} { if config == nil { return nil } @@ -2111,7 +2111,7 @@ func mapToTerraform_QemuCloudInit_Disk_unsafe(config *pxapi.QemuCloudInitDisk) m } // nil pointer check is done by the caller -func mapFromStruct_QemuCloudInit_unsafe(config *pxapi.QemuCloudInitDisk) []interface{} { +func mapToTerraform_QemuCloudInit_Disks_unsafe(config *pxapi.QemuCloudInitDisk) []interface{} { return []interface{}{ map[string]interface{}{ "cloudinit": []interface{}{ @@ -2185,16 +2185,16 @@ func mapToTerraform_QemuIdeDisks_Disk(config *pxapi.QemuIdeDisks) []map[string]i return disks } -func mapFromStruct_QemuIdeDisks(config *pxapi.QemuIdeDisks) []interface{} { +func mapToTerraform_QemuIdeDisks_Disks(config *pxapi.QemuIdeDisks) []interface{} { if config == nil { return nil } return []interface{}{ map[string]interface{}{ - "ide0": mapFromStruct_QemuIdeStorage(config.Disk_0), - "ide1": mapFromStruct_QemuIdeStorage(config.Disk_1), - "ide2": mapFromStruct_QemuIdeStorage(config.Disk_2), - "ide3": mapFromStruct_QemuIdeStorage(config.Disk_3)}} + "ide0": mapToTerraform_QemuIdeStorage_Disks(config.Disk_0), + "ide1": mapToTerraform_QemuIdeStorage_Disks(config.Disk_1), + "ide2": mapToTerraform_QemuIdeStorage_Disks(config.Disk_2), + "ide3": mapToTerraform_QemuIdeStorage_Disks(config.Disk_3)}} } func mapToTerraform_QemuIdeStorage_Disk(config *pxapi.QemuIdeStorage, slot string) (settings map[string]interface{}) { @@ -2245,7 +2245,7 @@ func mapToTerraform_QemuIdeStorage_Disk(config *pxapi.QemuIdeStorage, slot strin return settings } -func mapFromStruct_QemuIdeStorage(config *pxapi.QemuIdeStorage) []interface{} { +func mapToTerraform_QemuIdeStorage_Disks(config *pxapi.QemuIdeStorage) []interface{} { if config == nil { return nil } @@ -2291,9 +2291,9 @@ func mapFromStruct_QemuIdeStorage(config *pxapi.QemuIdeStorage) []interface{} { } } if config.CloudInit != nil { - return mapFromStruct_QemuCloudInit_unsafe(config.CloudInit) + return mapToTerraform_QemuCloudInit_Disks_unsafe(config.CloudInit) } - return mapFormStruct_QemuCdRom(config.CdRom) + return mapToTerraform_QemuCdRom_Disks(config.CdRom) } func mapToTerraform_QemuSataDisks_Disk(config *pxapi.QemuSataDisks) []map[string]interface{} { @@ -2325,18 +2325,18 @@ func mapToTerraform_QemuSataDisks_Disk(config *pxapi.QemuSataDisks) []map[string return disks } -func mapFromStruct_QemuSataDisks(config *pxapi.QemuSataDisks) []interface{} { +func mapToTerraform_QemuSataDisks_Disks(config *pxapi.QemuSataDisks) []interface{} { if config == nil { return nil } return []interface{}{ map[string]interface{}{ - "sata0": mapFromStruct_QemuSataStorage(config.Disk_0), - "sata1": mapFromStruct_QemuSataStorage(config.Disk_1), - "sata2": mapFromStruct_QemuSataStorage(config.Disk_2), - "sata3": mapFromStruct_QemuSataStorage(config.Disk_3), - "sata4": mapFromStruct_QemuSataStorage(config.Disk_4), - "sata5": mapFromStruct_QemuSataStorage(config.Disk_5), + "sata0": mapToTerraform_QemuSataStorage_DIsks(config.Disk_0), + "sata1": mapToTerraform_QemuSataStorage_DIsks(config.Disk_1), + "sata2": mapToTerraform_QemuSataStorage_DIsks(config.Disk_2), + "sata3": mapToTerraform_QemuSataStorage_DIsks(config.Disk_3), + "sata4": mapToTerraform_QemuSataStorage_DIsks(config.Disk_4), + "sata5": mapToTerraform_QemuSataStorage_DIsks(config.Disk_5), }, } } @@ -2389,7 +2389,7 @@ func mapToTerraform_QemuSataStorage_Disk(config *pxapi.QemuSataStorage, slot str return settings } -func mapFromStruct_QemuSataStorage(config *pxapi.QemuSataStorage) []interface{} { +func mapToTerraform_QemuSataStorage_DIsks(config *pxapi.QemuSataStorage) []interface{} { if config == nil { return nil } @@ -2435,9 +2435,9 @@ func mapFromStruct_QemuSataStorage(config *pxapi.QemuSataStorage) []interface{} } } if config.CloudInit != nil { - return mapFromStruct_QemuCloudInit_unsafe(config.CloudInit) + return mapToTerraform_QemuCloudInit_Disks_unsafe(config.CloudInit) } - return mapFormStruct_QemuCdRom(config.CdRom) + return mapToTerraform_QemuCdRom_Disks(config.CdRom) } func mapToTerraform_QemuScsiDisks_Disk(config *pxapi.QemuScsiDisks) []map[string]interface{} { @@ -2544,43 +2544,43 @@ func mapToTerraform_QemuScsiDisks_Disk(config *pxapi.QemuScsiDisks) []map[string return disks } -func mapFromStruct_QemuScsiDisks(config *pxapi.QemuScsiDisks) []interface{} { +func mapToTerraform_QemuScsiDisks_Disks(config *pxapi.QemuScsiDisks) []interface{} { if config == nil { return nil } return []interface{}{ map[string]interface{}{ - "scsi0": mapFromStruct_QemuScsiStorage(config.Disk_0), - "scsi1": mapFromStruct_QemuScsiStorage(config.Disk_1), - "scsi2": mapFromStruct_QemuScsiStorage(config.Disk_2), - "scsi3": mapFromStruct_QemuScsiStorage(config.Disk_3), - "scsi4": mapFromStruct_QemuScsiStorage(config.Disk_4), - "scsi5": mapFromStruct_QemuScsiStorage(config.Disk_5), - "scsi6": mapFromStruct_QemuScsiStorage(config.Disk_6), - "scsi7": mapFromStruct_QemuScsiStorage(config.Disk_7), - "scsi8": mapFromStruct_QemuScsiStorage(config.Disk_8), - "scsi9": mapFromStruct_QemuScsiStorage(config.Disk_9), - "scsi10": mapFromStruct_QemuScsiStorage(config.Disk_10), - "scsi11": mapFromStruct_QemuScsiStorage(config.Disk_11), - "scsi12": mapFromStruct_QemuScsiStorage(config.Disk_12), - "scsi13": mapFromStruct_QemuScsiStorage(config.Disk_13), - "scsi14": mapFromStruct_QemuScsiStorage(config.Disk_14), - "scsi15": mapFromStruct_QemuScsiStorage(config.Disk_15), - "scsi16": mapFromStruct_QemuScsiStorage(config.Disk_16), - "scsi17": mapFromStruct_QemuScsiStorage(config.Disk_17), - "scsi18": mapFromStruct_QemuScsiStorage(config.Disk_18), - "scsi19": mapFromStruct_QemuScsiStorage(config.Disk_19), - "scsi20": mapFromStruct_QemuScsiStorage(config.Disk_20), - "scsi21": mapFromStruct_QemuScsiStorage(config.Disk_21), - "scsi22": mapFromStruct_QemuScsiStorage(config.Disk_22), - "scsi23": mapFromStruct_QemuScsiStorage(config.Disk_23), - "scsi24": mapFromStruct_QemuScsiStorage(config.Disk_24), - "scsi25": mapFromStruct_QemuScsiStorage(config.Disk_25), - "scsi26": mapFromStruct_QemuScsiStorage(config.Disk_26), - "scsi27": mapFromStruct_QemuScsiStorage(config.Disk_27), - "scsi28": mapFromStruct_QemuScsiStorage(config.Disk_28), - "scsi29": mapFromStruct_QemuScsiStorage(config.Disk_29), - "scsi30": mapFromStruct_QemuScsiStorage(config.Disk_30), + "scsi0": mapToTerraform_QemuScsiStorage_Disks(config.Disk_0), + "scsi1": mapToTerraform_QemuScsiStorage_Disks(config.Disk_1), + "scsi2": mapToTerraform_QemuScsiStorage_Disks(config.Disk_2), + "scsi3": mapToTerraform_QemuScsiStorage_Disks(config.Disk_3), + "scsi4": mapToTerraform_QemuScsiStorage_Disks(config.Disk_4), + "scsi5": mapToTerraform_QemuScsiStorage_Disks(config.Disk_5), + "scsi6": mapToTerraform_QemuScsiStorage_Disks(config.Disk_6), + "scsi7": mapToTerraform_QemuScsiStorage_Disks(config.Disk_7), + "scsi8": mapToTerraform_QemuScsiStorage_Disks(config.Disk_8), + "scsi9": mapToTerraform_QemuScsiStorage_Disks(config.Disk_9), + "scsi10": mapToTerraform_QemuScsiStorage_Disks(config.Disk_10), + "scsi11": mapToTerraform_QemuScsiStorage_Disks(config.Disk_11), + "scsi12": mapToTerraform_QemuScsiStorage_Disks(config.Disk_12), + "scsi13": mapToTerraform_QemuScsiStorage_Disks(config.Disk_13), + "scsi14": mapToTerraform_QemuScsiStorage_Disks(config.Disk_14), + "scsi15": mapToTerraform_QemuScsiStorage_Disks(config.Disk_15), + "scsi16": mapToTerraform_QemuScsiStorage_Disks(config.Disk_16), + "scsi17": mapToTerraform_QemuScsiStorage_Disks(config.Disk_17), + "scsi18": mapToTerraform_QemuScsiStorage_Disks(config.Disk_18), + "scsi19": mapToTerraform_QemuScsiStorage_Disks(config.Disk_19), + "scsi20": mapToTerraform_QemuScsiStorage_Disks(config.Disk_20), + "scsi21": mapToTerraform_QemuScsiStorage_Disks(config.Disk_21), + "scsi22": mapToTerraform_QemuScsiStorage_Disks(config.Disk_22), + "scsi23": mapToTerraform_QemuScsiStorage_Disks(config.Disk_23), + "scsi24": mapToTerraform_QemuScsiStorage_Disks(config.Disk_24), + "scsi25": mapToTerraform_QemuScsiStorage_Disks(config.Disk_25), + "scsi26": mapToTerraform_QemuScsiStorage_Disks(config.Disk_26), + "scsi27": mapToTerraform_QemuScsiStorage_Disks(config.Disk_27), + "scsi28": mapToTerraform_QemuScsiStorage_Disks(config.Disk_28), + "scsi29": mapToTerraform_QemuScsiStorage_Disks(config.Disk_29), + "scsi30": mapToTerraform_QemuScsiStorage_Disks(config.Disk_30), }, } } @@ -2637,7 +2637,7 @@ func mapToTerraform_QemuScsiStorage_Disk(config *pxapi.QemuScsiStorage, slot str return settings } -func mapFromStruct_QemuScsiStorage(config *pxapi.QemuScsiStorage) []interface{} { +func mapToTerraform_QemuScsiStorage_Disks(config *pxapi.QemuScsiStorage) []interface{} { if config == nil { return nil } @@ -2687,9 +2687,9 @@ func mapFromStruct_QemuScsiStorage(config *pxapi.QemuScsiStorage) []interface{} } } if config.CloudInit != nil { - return mapFromStruct_QemuCloudInit_unsafe(config.CloudInit) + return mapToTerraform_QemuCloudInit_Disks_unsafe(config.CloudInit) } - return mapFormStruct_QemuCdRom(config.CdRom) + return mapToTerraform_QemuCdRom_Disks(config.CdRom) } func mapToTerraform_QemuStorage(d *schema.ResourceData, config pxapi.QemuStorages) { @@ -2759,28 +2759,28 @@ func mapToTerraform_QemuVirtIODisks_Disk(config *pxapi.QemuVirtIODisks) []map[st return disks } -func mapFromStruct_QemuVirtIODisks(config *pxapi.QemuVirtIODisks) []interface{} { +func mapToTerraform_QemuVirtIODisks_Disks(config *pxapi.QemuVirtIODisks) []interface{} { if config == nil { return nil } return []interface{}{ map[string]interface{}{ - "virtio0": mapFromStruct_QemuVirtIOStorage(config.Disk_0), - "virtio1": mapFromStruct_QemuVirtIOStorage(config.Disk_1), - "virtio2": mapFromStruct_QemuVirtIOStorage(config.Disk_2), - "virtio3": mapFromStruct_QemuVirtIOStorage(config.Disk_3), - "virtio4": mapFromStruct_QemuVirtIOStorage(config.Disk_4), - "virtio5": mapFromStruct_QemuVirtIOStorage(config.Disk_5), - "virtio6": mapFromStruct_QemuVirtIOStorage(config.Disk_6), - "virtio7": mapFromStruct_QemuVirtIOStorage(config.Disk_7), - "virtio8": mapFromStruct_QemuVirtIOStorage(config.Disk_8), - "virtio9": mapFromStruct_QemuVirtIOStorage(config.Disk_9), - "virtio10": mapFromStruct_QemuVirtIOStorage(config.Disk_10), - "virtio11": mapFromStruct_QemuVirtIOStorage(config.Disk_11), - "virtio12": mapFromStruct_QemuVirtIOStorage(config.Disk_12), - "virtio13": mapFromStruct_QemuVirtIOStorage(config.Disk_13), - "virtio14": mapFromStruct_QemuVirtIOStorage(config.Disk_14), - "virtio15": mapFromStruct_QemuVirtIOStorage(config.Disk_15), + "virtio0": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_0), + "virtio1": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_1), + "virtio2": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_2), + "virtio3": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_3), + "virtio4": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_4), + "virtio5": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_5), + "virtio6": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_6), + "virtio7": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_7), + "virtio8": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_8), + "virtio9": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_9), + "virtio10": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_10), + "virtio11": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_11), + "virtio12": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_12), + "virtio13": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_13), + "virtio14": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_14), + "virtio15": mapToTerraform_QemuVirtIOStorage_Disks(config.Disk_15), }, } } @@ -2832,11 +2832,11 @@ func mapToTerraform_QemuVirtIOStorage_Disk(config *pxapi.QemuVirtIOStorage, slot return settings } -func mapFromStruct_QemuVirtIOStorage(config *pxapi.QemuVirtIOStorage) []interface{} { +func mapToTerraform_QemuVirtIOStorage_Disks(config *pxapi.QemuVirtIOStorage) []interface{} { if config == nil { return nil } - mapFormStruct_QemuCdRom(config.CdRom) + mapToTerraform_QemuCdRom_Disks(config.CdRom) if config.Disk != nil { mapParams := map[string]interface{}{ "asyncio": string(config.Disk.AsyncIO), @@ -2880,7 +2880,7 @@ func mapFromStruct_QemuVirtIOStorage(config *pxapi.QemuVirtIOStorage) []interfac }, } } - return mapFormStruct_QemuCdRom(config.CdRom) + return mapToTerraform_QemuCdRom_Disks(config.CdRom) } // Map the terraform schema to sdk struct From 738e5404100eda1dcf96281ad2b22f5411d6e3e5 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 27 Aug 2024 08:19:08 +0200 Subject: [PATCH 09/12] refactor: put code in correct order --- proxmox/resource_vm_qemu.go | 39 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 1ce95896..a65332c2 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -543,8 +543,7 @@ func resourceVmQemu() *schema.Resource { return diag.Errorf("type must be one of 'disk', 'cdrom', 'cloudinit'") }}, "wwn": schema_DiskWWN(), - }}, - }, + }}}, "disks": { Type: schema.TypeList, Optional: true, @@ -2047,24 +2046,6 @@ func getPrimaryIP(config *pxapi.ConfigQemu, vmr *pxapi.VmRef, client *pxapi.Clie // Map struct to the terraform schema -func mapToTerraform_QemuDisks_Disks(config pxapi.QemuStorages) []interface{} { - ide := mapToTerraform_QemuIdeDisks_Disks(config.Ide) - sata := mapToTerraform_QemuSataDisks_Disks(config.Sata) - scsi := mapToTerraform_QemuScsiDisks_Disks(config.Scsi) - virtio := mapToTerraform_QemuVirtIODisks_Disks(config.VirtIO) - if ide == nil && sata == nil && scsi == nil && virtio == nil { - return nil - } - return []interface{}{ - map[string]interface{}{ - "ide": ide, - "sata": sata, - "scsi": scsi, - "virtio": virtio, - }, - } -} - func mapFormStruct_IsoFile(config *pxapi.IsoFile) string { if config == nil { return "" @@ -2139,6 +2120,24 @@ func mapToTerraform_QemuDisks_Disk(config pxapi.QemuStorages) []map[string]inter return disks } +func mapToTerraform_QemuDisks_Disks(config pxapi.QemuStorages) []interface{} { + ide := mapToTerraform_QemuIdeDisks_Disks(config.Ide) + sata := mapToTerraform_QemuSataDisks_Disks(config.Sata) + scsi := mapToTerraform_QemuScsiDisks_Disks(config.Scsi) + virtio := mapToTerraform_QemuVirtIODisks_Disks(config.VirtIO) + if ide == nil && sata == nil && scsi == nil && virtio == nil { + return nil + } + return []interface{}{ + map[string]interface{}{ + "ide": ide, + "sata": sata, + "scsi": scsi, + "virtio": virtio, + }, + } +} + func mapFormStruct_QemuDiskBandwidth(params map[string]interface{}, config pxapi.QemuDiskBandwidth) { params["mbps_r_burst"] = float64(config.MBps.ReadLimit.Burst) params["mbps_r_concurrent"] = float64(config.MBps.ReadLimit.Concurrent) From d337d4d04cbeda6f161dc932f04ee107d0e74bde Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 27 Aug 2024 08:19:47 +0200 Subject: [PATCH 10/12] style: fix white-space --- proxmox/resource_vm_qemu.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index a65332c2..a2f64083 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -3614,17 +3614,17 @@ func mapToSDK_QemuStorages(d *schema.ResourceData) (*pxapi.QemuStorages, diag.Di } } } else { - schemaItem := d.Get("disks").([]interface{}) - if len(schemaItem) == 1 { - schemaStorages, ok := schemaItem[0].(map[string]interface{}) - if ok { + schemaItem := d.Get("disks").([]interface{}) + if len(schemaItem) == 1 { + schemaStorages, ok := schemaItem[0].(map[string]interface{}) + if ok { mapToSDK_QemuIdeDisks_Disks(storages.Ide, schemaStorages) mapToSDK_QemuSataDisks_Disks(storages.Sata, schemaStorages) mapToSDK_QemuScsiDisks_Disks(storages.Scsi, schemaStorages) mapToSDK_QemuVirtIODisks_Disks(storages.VirtIO, schemaStorages) + } } } - } return &storages, diags } @@ -4412,17 +4412,17 @@ func schema_DiskSerial() *schema.Schema { func schema_DiskSize(s schema.Schema) *schema.Schema { s.Type = schema.TypeString s.ValidateDiagFunc = func(i interface{}, k cty.Path) diag.Diagnostics { - v, ok := i.(string) - if !ok { - return diag.Errorf(errorString, k) - } - if !regexp.MustCompile(`^[123456789]\d*[KMGT]?$`).MatchString(v) { - return diag.Errorf("%s must match the following regex ^[123456789]\\d*[KMGT]?$", k) - } - return nil + v, ok := i.(string) + if !ok { + return diag.Errorf(errorString, k) + } + if !regexp.MustCompile(`^[123456789]\d*[KMGT]?$`).MatchString(v) { + return diag.Errorf("%s must match the following regex ^[123456789]\\d*[KMGT]?$", k) + } + return nil } s.DiffSuppressFunc = func(k, old, new string, d *schema.ResourceData) bool { - return convert_SizeStringToKibibytes_Unsafe(old) == convert_SizeStringToKibibytes_Unsafe(new) + return convert_SizeStringToKibibytes_Unsafe(old) == convert_SizeStringToKibibytes_Unsafe(new) } return &s } From dab68335250b4c21df1f3efa619f7358c155ae6c Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 27 Aug 2024 08:23:52 +0200 Subject: [PATCH 11/12] docs: `disk` block --- docs/resources/vm_qemu.md | 76 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/docs/resources/vm_qemu.md b/docs/resources/vm_qemu.md index 39e8ea35..74b0721a 100644 --- a/docs/resources/vm_qemu.md +++ b/docs/resources/vm_qemu.md @@ -175,6 +175,82 @@ details. | `queues` | `int` | `1` | Number of packet queues to be used on the device. Requires `virtio` model to have an effect. | | `link_down` | `bool` | `false` | Whether this interface should be disconnected (like pulling the plug). | +### Disk Block + +The `disk` block is used to configure the disk devices. It may be specified multiple times. This block does not diff as pretty as the `disks` block, but it is more flexible for modules. Putting the disks in alphanumeric order based on the value of `slot` is recommended for readability. + +Due to the complexity of the `disk` block, there is a settings matrix that can be found in the [Disk compatibility matrix](#disk-compatibility-matrix). + +| Argument | Type |Default| Description| +|:---------------------|:------:|:-----:|:-----------| +|`asyncio` |`string`| |The drive's asyncio setting. Options: `io_uring`, `native`, `threads`| +|`backup` |`bool` |`true` |Whether the drive should be included when making backups.| +|`cache` |`string`| |The drive’s cache mode. Options: `directsync`, `none`, `unsafe`, `writeback`, `writethrough`.| +|`discard` |`bool` |`false`|Controls whether to pass discard/trim requests to the underlying storage. Only effective when the underlying storage supports thin provisioning. There are other caveats too, see the [docs about disks](https://pve.proxmox.com/pve-docs/chapter-qm.html#qm_hard_disk) for more info.| +|`disk_file` |`string`| |The path to the disk file. **Required** when `type`=`disk` and `passthrough`=`true`| +|`emulatessd` |`bool` |`false`|Whether to expose this drive as an SSD, rather than a rotational hard disk.| +|`format` |`string`|`raw` |The drive’s backing file’s data format.| +|`id` |`int` | |**Computed** Unique id of the disk.| +|`iops_r_burst` |`int` |`0` |Maximum number of iops while reading in short bursts. `0` means unlimited.| +|`iops_r_burst_length` |`int` |`0` |Length of the read burst duration in seconds. `0` means the default duration dictated by proxmox.| +|`iops_r_concurrent` |`int` |`0` |Maximum number of iops while reading concurrently. `0` means unlimited.| +|`iops_wr_burst` |`int` |`0` |Maximum number of iops while writing in short bursts. `0` means unlimited.| +|`iops_wr_burst_length`|`int` |`0` |Length of the write burst duration in seconds. `0` means the default duration dictated by proxmox.| +|`iops_wr_concurrent` |`int` |`0` |Maximum number of iops while writing concurrently. `0` means unlimited.| +|`iothread` |`bool` |`false`|Whether to use iothreads for this drive. Only effective when the the emulated controller type (`scsihw` top level block argument) is `virtio-scsi-single`.| +|`iso` |`string`| |The name of the ISO image to mount to the VM in the format: [storage pool]:iso/[name of iso file]. Note that `iso` is mutually exclusive with `passthrough`.| +|`linked_disk_id` |`int` | |**Computed** The `vmid` of the linked vm this disk was cloned from.| +|`mbps_r_burst` |`float` |`0.0` |Maximum read speed in megabytes per second. `0` means unlimited.| +|`mbps_r_concurrent` |`float` |`0.0` |Maximum read speed in megabytes per second. `0` means unlimited.| +|`mbps_wr_burst` |`float` |`0.0` |Maximum write speed in megabytes per second. `0` means unlimited.| +|`mbps_wr_concurrent` |`float` |`0.0` |Maximum throttled write pool in megabytes per second. `0` means unlimited.| +|`passthrough` |`bool` |`false`|Wether the physical cdrom drive should be passed through.| +|`readonly` |`bool` |`false`|Whether the drive should be readonly.| +|`replicate` |`bool` |`false`|Whether the drive should considered for replication jobs.| +|`serial` |`string`| |The serial number of the disk.| +|`size` |`string`| |The size of the created disk. Accepts `K` for kibibytes, `M` for mebibytes, `G` for gibibytes, `T` for tibibytes. When only a number is provided gibibytes is assumed. **Required** when `type`=`disk` and `passthrough`=`false`, **Computed** when `type`=`disk` and `passthrough`=`true`. | +|`slot` |`string`| |**Required** The slot id of the disk.| +|`storage` |`string`| |Required when `type`=`disk` and `passthrough`=`false`. The name of the storage pool on which to store the disk.| +|`type` |`string`|`disk` |The type of disk to create. Options: `cdrom`, `cloudinit` ,`disk`.| +|`wwn` |`string`| |The WWN of the disk.| + +#### Disk compatibility matrix + +**Note** `cloudinit` can only be used with `ide`, `sata` and `scsi` disk types. + +| Argument | Disk Type | Disk Slot |Passthrough| +|:---------------------|:-----------------:|:-------------------:|:---------:| +|`asyncio` |`disk` |`all` |`both` | +|`backup` |`disk` |`all` |`both` | +|`cache` |`disk` |`all` |`both` | +|`discard` |`disk` |`all` |`both` | +|`disk_file` |`disk` |`all` |`true` | +|`emulatessd` |`disk` |`ide`, `sata`, `scsi`|`both` | +|`format` |`disk` |`all` |`both` | +|`id` |`disk` |`all` |`false` | +|`iops_r_burst` |`disk` |`all` |`both` | +|`iops_r_burst_length` |`disk` |`all` |`both` | +|`iops_r_concurrent` |`disk` |`all` |`both` | +|`iops_wr_burst` |`disk` |`all` |`both` | +|`iops_wr_burst_length`|`disk` |`all` |`both` | +|`iops_wr_concurrent` |`disk` |`all` |`false` | +|`iothread` |`disk` |`scsi`, `virtio` |`false` | +|`iso` |`iso` |`all` |`false` | +|`linked_disk_id` |`disk` |`all` |`false` | +|`mbps_r_burst` |`disk` |`all` |`false` | +|`mbps_r_concurrent` |`disk` |`all` |`false` | +|`mbps_wr_burst` |`disk` |`all` |`false` | +|`mbps_wr_concurrent` |`disk` |`all` |`false` | +|`passthrough` |`disk`, `iso` |`all` |`false` | +|`readonly` |`disk` |`scsi`, `virtio` |`false` | +|`replicate` |`disk` |`all` |`false` | +|`serial` |`disk` |`all` |`false` | +|`size` |`disk` |`all` |`false` | +|`slot` |`disk`, `iso` |`all` |`false` | +|`storage` |`disk`, `cloudinit`|`all` |`false` | +|`type` |`disk` |`all` |`false` | +|`wwn` |`disk` |`all` |`false` | + ### Disks Block The `disks` block is used to configure the disk devices. It may be specified once. There are four types of disk `ide`,`sata`,`scsi` and `virtio`. Configuration for these sub types can be found in their respective chapters: From 97cb9717ef0ec2def2c1b372236d07bfc0585c2e Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 27 Aug 2024 17:29:54 +0200 Subject: [PATCH 12/12] refactor: remove unused code --- proxmox/resource_vm_qemu.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 2ade81a7..7c474dc8 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -4678,14 +4678,3 @@ func warnings_DiskPassthrough(slot string, schema map[string]interface{}) diag.D } return diag.Diagnostics{} } - -func warning_iothread_Disk(slot, property, value, extra string) diag.Diagnostic { - return warningDisk(slot, "iothread", property, value, extra) -} - -func warning_iso_Disk(slot string, schema map[string]interface{}) diag.Diagnostics { - if schema["iso"].(string) != "" { - return diag.Diagnostics{warningDisk(slot, "iso", "type", "disk", "")} - } - return nil -}