From 339baf9bfa15b8bceea272c2436debf1a83c3ae0 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Feb 2023 11:23:19 +0000 Subject: [PATCH 001/120] feat: add parsing of qemu disks into struct --- proxmox/config_qemu_disk.go | 266 +++++++++++++++++++++++++++++ proxmox/config_qemu_disk_ide.go | 105 ++++++++++++ proxmox/config_qemu_disk_sata.go | 115 +++++++++++++ proxmox/config_qemu_disk_scsi.go | 249 +++++++++++++++++++++++++++ proxmox/config_qemu_disk_virtio.go | 165 ++++++++++++++++++ proxmox/util.go | 9 + proxmox/util_test.go | 28 +++ 7 files changed, 937 insertions(+) create mode 100644 proxmox/config_qemu_disk.go create mode 100644 proxmox/config_qemu_disk_ide.go create mode 100644 proxmox/config_qemu_disk_sata.go create mode 100644 proxmox/config_qemu_disk_scsi.go create mode 100644 proxmox/config_qemu_disk_virtio.go create mode 100644 proxmox/util_test.go diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go new file mode 100644 index 00000000..5e110e96 --- /dev/null +++ b/proxmox/config_qemu_disk.go @@ -0,0 +1,266 @@ +package proxmox + +import ( + "math" + "strconv" + "strings" +) + +type IsoFile struct { + Storage string + File string + // Size can only be retrieved, setting it has no effect + Size string +} + +type QemuCdRom struct { + Iso *IsoFile + // Passthrough and File are mutually exclusive + Passthrough bool +} + +func (QemuCdRom) mapToStruct(settings qemuCdRom) *QemuCdRom { + if !settings.Passthrough { + return &QemuCdRom{ + Iso: &IsoFile{ + Storage: settings.Storage, + File: settings.File, + Size: settings.Size, + }, + } + } + return &QemuCdRom{Passthrough: false} +} + +type qemuCdRom struct { + // "local:iso/debian-11.0.0-amd64-netinst.iso,media=cdrom,size=377M" + Passthrough bool + Storage string + // FileType is only set for Cloud init drives, this value will be used to check if it is a normal cdrom or cloud init drive. + FileType string + File string + Size string +} + +func (qemuCdRom) mapToStruct(settings [][]string) *qemuCdRom { + var isCdRom bool + for _, e := range settings { + if e[0] == "media" { + if e[1] == "cdrom" { + isCdRom = true + break + } + } + } + if !isCdRom { + return nil + } + if settings[0][0] == "none" { + return &qemuCdRom{} + } + if settings[0][0] == "cdrom" { + return &qemuCdRom{Passthrough: true} + } + tmpStorage := strings.Split(settings[0][0], ":") + if len(tmpStorage) > 1 { + tmpFile := strings.Split(settings[0][0], "/") + if len(tmpFile) == 2 { + tmpFileType := strings.Split(tmpFile[1], ".") + if len(tmpFileType) > 1 { + fileType := tmpFileType[len(tmpFileType)-1] + if fileType == "iso" { + for _, e := range settings { + if e[0] == "size" { + return &qemuCdRom{ + Storage: tmpStorage[0], + File: tmpFile[1], + Size: e[1], + } + } + } + } else { + return &qemuCdRom{ + Storage: tmpStorage[0], + File: tmpFile[1], + FileType: fileType, + } + } + } + } + } + return nil +} + +type QemuCloudInitDisk struct { + Storage string + FileType string +} + +func (QemuCloudInitDisk) mapToStruct(settings qemuCdRom) *QemuCloudInitDisk { + return &QemuCloudInitDisk{ + Storage: settings.Storage, + FileType: settings.FileType, + } +} + +// TODO add enum +type QemuDiskAsyncIO string + +type QemuDiskBandwidth struct { + ReadLimit_Data QemuDisk_Bandwidth_Data + WriteLimit_Data QemuDisk_Bandwidth_Data + ReadLimit_Iops QemuDisk_Bandwidth_Iops + WriteLimit_Iops QemuDisk_Bandwidth_Iops +} + +type QemuDisk_Bandwidth_Data struct { + Concurrent float32 + Burst float32 +} + +type QemuDisk_Bandwidth_Iops struct { + Concurrent uint + Burst uint +} + +// TODO add enum +type QemuDiskCache string + +// TODO add enum +type QemuDiskFormat string + +func (QemuDiskFormat) mapToStruct(setting string) QemuDiskFormat { + settings := strings.Split(setting, ".") + if len(settings) < 2 { + return "" + } + return QemuDiskFormat(settings[len(settings)-1]) +} + +type qemuDisk struct { + AsyncIO QemuDiskAsyncIO + Backup bool + Bandwidth QemuDiskBandwidth + Cache QemuDiskCache + Discard bool + EmulateSSD bool + // TODO custom type + // File is only set for Passthrough. + File string + Format QemuDiskFormat + IOThread bool + ReadOnly bool + Replicate bool + Size uint + // TODO custom type + // Storage is only set for Disk + Storage string +} + +// Maps all the disk related settings +func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { + if len(settings) == 0 { + return nil + } + disk := qemuDisk{Backup: true} + + if settings[0][0][0:1] == "/" { + disk.File = settings[0][0] + } else { + // "test2:105/vm-105-disk-53.qcow2, + disk.Storage = strings.Split(settings[0][0], ":")[0] + disk.Format = QemuDiskFormat("").mapToStruct(settings[0][0]) + } + + for _, e := range settings { + if e[0] == "aio" { + disk.AsyncIO = QemuDiskAsyncIO(e[1]) + continue + } + if e[0] == "backup" { + disk.Backup, _ = strconv.ParseBool(e[1]) + continue + } + if e[0] == "cache" { + disk.Cache = QemuDiskCache(e[1]) + continue + } + if e[0] == "discard" { + disk.Discard, _ = strconv.ParseBool(e[1]) + continue + } + if e[0] == "iops_rd" { + tmp, _ := strconv.Atoi(e[1]) + disk.Bandwidth.ReadLimit_Iops.Concurrent = uint(tmp) + } + if e[0] == "iops_rd_max" { + tmp, _ := strconv.Atoi(e[1]) + disk.Bandwidth.ReadLimit_Iops.Burst = uint(tmp) + } + if e[0] == "iops_wr" { + tmp, _ := strconv.Atoi(e[1]) + disk.Bandwidth.WriteLimit_Iops.Concurrent = uint(tmp) + } + if e[0] == "iops_wr_max" { + tmp, _ := strconv.Atoi(e[1]) + disk.Bandwidth.WriteLimit_Iops.Burst = uint(tmp) + } + if e[0] == "iothread" { + disk.IOThread, _ = strconv.ParseBool(e[1]) + continue + } + if e[0] == "mbps_rd" { + tmp, _ := strconv.ParseFloat(e[1], 32) + disk.Bandwidth.ReadLimit_Data.Concurrent = float32(math.Round(tmp*100) / 100) + } + if e[0] == "mbps_rd_max" { + tmp, _ := strconv.ParseFloat(e[1], 32) + disk.Bandwidth.ReadLimit_Data.Burst = float32(math.Round(tmp*100) / 100) + } + if e[0] == "mbps_wr" { + tmp, _ := strconv.ParseFloat(e[1], 32) + disk.Bandwidth.WriteLimit_Data.Concurrent = float32(math.Round(tmp*100) / 100) + } + if e[0] == "mbps_wr_max" { + tmp, _ := strconv.ParseFloat(e[1], 32) + disk.Bandwidth.WriteLimit_Data.Burst = float32(math.Round(tmp*100) / 100) + } + if e[0] == "replicate" { + disk.Replicate, _ = strconv.ParseBool(e[1]) + continue + } + if e[0] == "ro" { + disk.ReadOnly, _ = strconv.ParseBool(e[1]) + continue + } + if e[0] == "size" { + diskSize, _ := strconv.Atoi(strings.TrimSuffix(e[1], "G")) + disk.Size = uint(diskSize) + continue + } + if e[0] == "ssd" { + disk.EmulateSSD, _ = strconv.ParseBool(e[1]) + } + } + return &disk +} + +type QemuStorages struct { + Ide *QemuIdeDisks + Sata *QemuSataDisks + Scsi *QemuScsiDisks + VirtIO *QemuVirtIODisks +} + +func (QemuStorages) mapToStruct(params map[string]interface{}) *QemuStorages { + storage := QemuStorages{ + Ide: QemuIdeDisks{}.mapToStruct(params), + Sata: QemuSataDisks{}.mapToStruct(params), + Scsi: QemuScsiDisks{}.mapToStruct(params), + VirtIO: QemuVirtIODisks{}.mapToStruct(params), + } + if storage.Ide != nil || storage.Sata != nil || storage.Scsi != nil || storage.VirtIO != nil { + return &storage + } + return nil +} diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go new file mode 100644 index 00000000..9db3ba5b --- /dev/null +++ b/proxmox/config_qemu_disk_ide.go @@ -0,0 +1,105 @@ +package proxmox + +type QemuIdeDisk struct { + AsyncIO QemuDiskAsyncIO + Backup bool + Bandwidth QemuDiskBandwidth + Cache QemuDiskCache + Discard bool + EmulateSSD bool + Replicate bool + Size uint + Storage string +} + +type QemuIdeDisks struct { + Disk_0 *QemuIdeStorage + Disk_1 *QemuIdeStorage + Disk_2 *QemuIdeStorage + Disk_3 *QemuIdeStorage +} + +func (QemuIdeDisks) mapToStruct(params map[string]interface{}) *QemuIdeDisks { + disks := QemuIdeDisks{} + var structPopulated bool + if _, isSet := params["ide0"]; isSet { + disks.Disk_0 = QemuIdeStorage{}.mapToStruct(params["ide0"].(string)) + structPopulated = true + } + if _, isSet := params["ide1"]; isSet { + disks.Disk_1 = QemuIdeStorage{}.mapToStruct(params["ide1"].(string)) + structPopulated = true + } + if _, isSet := params["ide2"]; isSet { + disks.Disk_2 = QemuIdeStorage{}.mapToStruct(params["ide2"].(string)) + structPopulated = true + } + if _, isSet := params["ide3"]; isSet { + disks.Disk_3 = QemuIdeStorage{}.mapToStruct(params["ide3"].(string)) + structPopulated = true + } + if structPopulated { + return &disks + } + return nil +} + +type QemuIdePassthrough struct { + AsyncIO QemuDiskAsyncIO + Backup bool + Bandwidth QemuDiskBandwidth + Cache QemuDiskCache + Discard bool + EmulateSSD bool + File string + Replicate bool + Size uint +} + +type QemuIdeStorage struct { + CdRom *QemuCdRom + CloudInit *QemuCloudInitDisk + Disk *QemuIdeDisk + Passthrough *QemuIdePassthrough +} + +func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { + settings := splitStringOfSettings(param) + tmpCdRom := qemuCdRom{}.mapToStruct(settings) + if tmpCdRom != nil { + if tmpCdRom.FileType == "" { + return &QemuIdeStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} + } else { + return &QemuIdeStorage{CloudInit: QemuCloudInitDisk{}.mapToStruct(*tmpCdRom)} + } + } + + tmpDisk := qemuDisk{}.mapToStruct(settings) + if tmpDisk == nil { + return nil + } + if tmpDisk.File == "" { + return &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + Replicate: tmpDisk.Replicate, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, + }} + } + return &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + File: tmpDisk.File, + Replicate: tmpDisk.Replicate, + Size: tmpDisk.Size, + }} +} diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go new file mode 100644 index 00000000..ac1555c9 --- /dev/null +++ b/proxmox/config_qemu_disk_sata.go @@ -0,0 +1,115 @@ +package proxmox + +type QemuSataDisk struct { + AsyncIO QemuDiskAsyncIO + Backup bool + Bandwidth QemuDiskBandwidth + Cache QemuDiskCache + Discard bool + EmulateSSD bool + Replicate bool + Size uint + Storage string +} + +type QemuSataDisks struct { + Disk_0 *QemuSataStorage + Disk_1 *QemuSataStorage + Disk_2 *QemuSataStorage + Disk_3 *QemuSataStorage + Disk_4 *QemuSataStorage + Disk_5 *QemuSataStorage +} + +func (QemuSataDisks) mapToStruct(params map[string]interface{}) *QemuSataDisks { + disks := QemuSataDisks{} + var structPopulated bool + if _, isSet := params["sata0"]; isSet { + disks.Disk_0 = QemuSataStorage{}.mapToStruct(params["sata0"].(string)) + structPopulated = true + } + if _, isSet := params["sata1"]; isSet { + disks.Disk_1 = QemuSataStorage{}.mapToStruct(params["sata1"].(string)) + structPopulated = true + } + if _, isSet := params["sata2"]; isSet { + disks.Disk_2 = QemuSataStorage{}.mapToStruct(params["sata2"].(string)) + structPopulated = true + } + if _, isSet := params["sata3"]; isSet { + disks.Disk_3 = QemuSataStorage{}.mapToStruct(params["sata3"].(string)) + structPopulated = true + } + if _, isSet := params["sata4"]; isSet { + disks.Disk_4 = QemuSataStorage{}.mapToStruct(params["sata4"].(string)) + structPopulated = true + } + if _, isSet := params["sata5"]; isSet { + disks.Disk_5 = QemuSataStorage{}.mapToStruct(params["sata5"].(string)) + structPopulated = true + } + if structPopulated { + return &disks + } + return nil +} + +type QemuSataPassthrough struct { + AsyncIO QemuDiskAsyncIO + Backup bool + Bandwidth QemuDiskBandwidth + Cache QemuDiskCache + Discard bool + EmulateSSD bool + File string + Replicate bool + Size uint +} + +type QemuSataStorage struct { + CdRom *QemuCdRom + CloudInit *QemuCloudInitDisk + Disk *QemuSataDisk + Passthrough *QemuSataPassthrough +} + +func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { + settings := splitStringOfSettings(param) + tmpCdRom := qemuCdRom{}.mapToStruct(settings) + if tmpCdRom != nil { + if tmpCdRom.FileType == "" { + return &QemuSataStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} + } else { + return &QemuSataStorage{CloudInit: QemuCloudInitDisk{}.mapToStruct(*tmpCdRom)} + } + } + + tmpDisk := qemuDisk{}.mapToStruct(settings) + if tmpDisk == nil { + return nil + } + if tmpDisk.File == "" { + return &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + Replicate: tmpDisk.Replicate, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, + }} + } + return &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + File: tmpDisk.File, + Replicate: tmpDisk.Replicate, + Size: tmpDisk.Size, + }} +} diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go new file mode 100644 index 00000000..5aa56e0b --- /dev/null +++ b/proxmox/config_qemu_disk_scsi.go @@ -0,0 +1,249 @@ +package proxmox + +type QemuScsiDisk struct { + AsyncIO QemuDiskAsyncIO + Backup bool + Bandwidth QemuDiskBandwidth + Cache QemuDiskCache + Discard bool + EmulateSSD bool + IOThread bool + ReadOnly bool + Replicate bool + Size uint + Storage string +} + +type QemuScsiDisks struct { + Disk_0 *QemuScsiStorage + Disk_1 *QemuScsiStorage + Disk_2 *QemuScsiStorage + Disk_3 *QemuScsiStorage + Disk_4 *QemuScsiStorage + Disk_5 *QemuScsiStorage + Disk_6 *QemuScsiStorage + Disk_7 *QemuScsiStorage + Disk_8 *QemuScsiStorage + Disk_9 *QemuScsiStorage + Disk_10 *QemuScsiStorage + Disk_11 *QemuScsiStorage + Disk_12 *QemuScsiStorage + Disk_13 *QemuScsiStorage + Disk_14 *QemuScsiStorage + Disk_15 *QemuScsiStorage + Disk_16 *QemuScsiStorage + Disk_17 *QemuScsiStorage + Disk_18 *QemuScsiStorage + Disk_19 *QemuScsiStorage + Disk_20 *QemuScsiStorage + Disk_21 *QemuScsiStorage + Disk_22 *QemuScsiStorage + Disk_23 *QemuScsiStorage + Disk_24 *QemuScsiStorage + Disk_25 *QemuScsiStorage + Disk_26 *QemuScsiStorage + Disk_27 *QemuScsiStorage + Disk_28 *QemuScsiStorage + Disk_29 *QemuScsiStorage + Disk_30 *QemuScsiStorage +} + +func (QemuScsiDisks) mapToStruct(params map[string]interface{}) *QemuScsiDisks { + disks := QemuScsiDisks{} + var structPopulated bool + if _, isSet := params["scsi0"]; isSet { + disks.Disk_0 = QemuScsiStorage{}.mapToStruct(params["scsi0"].(string)) + structPopulated = true + } + if _, isSet := params["scsi1"]; isSet { + disks.Disk_1 = QemuScsiStorage{}.mapToStruct(params["scsi1"].(string)) + structPopulated = true + } + if _, isSet := params["scsi2"]; isSet { + disks.Disk_2 = QemuScsiStorage{}.mapToStruct(params["scsi2"].(string)) + structPopulated = true + } + if _, isSet := params["scsi3"]; isSet { + disks.Disk_3 = QemuScsiStorage{}.mapToStruct(params["scsi3"].(string)) + structPopulated = true + } + if _, isSet := params["scsi4"]; isSet { + disks.Disk_4 = QemuScsiStorage{}.mapToStruct(params["scsi4"].(string)) + structPopulated = true + } + if _, isSet := params["scsi5"]; isSet { + disks.Disk_5 = QemuScsiStorage{}.mapToStruct(params["scsi5"].(string)) + structPopulated = true + } + if _, isSet := params["scsi6"]; isSet { + disks.Disk_6 = QemuScsiStorage{}.mapToStruct(params["scsi6"].(string)) + structPopulated = true + } + if _, isSet := params["scsi7"]; isSet { + disks.Disk_7 = QemuScsiStorage{}.mapToStruct(params["scsi7"].(string)) + structPopulated = true + } + if _, isSet := params["scsi8"]; isSet { + disks.Disk_8 = QemuScsiStorage{}.mapToStruct(params["scsi8"].(string)) + structPopulated = true + } + if _, isSet := params["scsi9"]; isSet { + disks.Disk_9 = QemuScsiStorage{}.mapToStruct(params["scsi9"].(string)) + structPopulated = true + } + if _, isSet := params["scsi10"]; isSet { + disks.Disk_10 = QemuScsiStorage{}.mapToStruct(params["scsi10"].(string)) + structPopulated = true + } + if _, isSet := params["scsi11"]; isSet { + disks.Disk_11 = QemuScsiStorage{}.mapToStruct(params["scsi11"].(string)) + structPopulated = true + } + if _, isSet := params["scsi12"]; isSet { + disks.Disk_12 = QemuScsiStorage{}.mapToStruct(params["scsi12"].(string)) + structPopulated = true + } + if _, isSet := params["scsi13"]; isSet { + disks.Disk_13 = QemuScsiStorage{}.mapToStruct(params["scsi13"].(string)) + structPopulated = true + } + if _, isSet := params["scsi14"]; isSet { + disks.Disk_14 = QemuScsiStorage{}.mapToStruct(params["scsi14"].(string)) + structPopulated = true + } + if _, isSet := params["scsi15"]; isSet { + disks.Disk_15 = QemuScsiStorage{}.mapToStruct(params["scsi15"].(string)) + structPopulated = true + } + if _, isSet := params["scsi16"]; isSet { + disks.Disk_16 = QemuScsiStorage{}.mapToStruct(params["scsi16"].(string)) + structPopulated = true + } + if _, isSet := params["scsi17"]; isSet { + disks.Disk_17 = QemuScsiStorage{}.mapToStruct(params["scsi17"].(string)) + structPopulated = true + } + if _, isSet := params["scsi18"]; isSet { + disks.Disk_18 = QemuScsiStorage{}.mapToStruct(params["scsi18"].(string)) + structPopulated = true + } + if _, isSet := params["scsi19"]; isSet { + disks.Disk_19 = QemuScsiStorage{}.mapToStruct(params["scsi19"].(string)) + structPopulated = true + } + if _, isSet := params["scsi20"]; isSet { + disks.Disk_20 = QemuScsiStorage{}.mapToStruct(params["scsi20"].(string)) + structPopulated = true + } + if _, isSet := params["scsi21"]; isSet { + disks.Disk_21 = QemuScsiStorage{}.mapToStruct(params["scsi21"].(string)) + structPopulated = true + } + if _, isSet := params["scsi22"]; isSet { + disks.Disk_22 = QemuScsiStorage{}.mapToStruct(params["scsi22"].(string)) + structPopulated = true + } + if _, isSet := params["scsi23"]; isSet { + disks.Disk_23 = QemuScsiStorage{}.mapToStruct(params["scsi23"].(string)) + structPopulated = true + } + if _, isSet := params["scsi24"]; isSet { + disks.Disk_24 = QemuScsiStorage{}.mapToStruct(params["scsi24"].(string)) + structPopulated = true + } + if _, isSet := params["scsi25"]; isSet { + disks.Disk_25 = QemuScsiStorage{}.mapToStruct(params["scsi25"].(string)) + structPopulated = true + } + if _, isSet := params["scsi26"]; isSet { + disks.Disk_26 = QemuScsiStorage{}.mapToStruct(params["scsi26"].(string)) + structPopulated = true + } + if _, isSet := params["scsi27"]; isSet { + disks.Disk_27 = QemuScsiStorage{}.mapToStruct(params["scsi27"].(string)) + structPopulated = true + } + if _, isSet := params["scsi28"]; isSet { + disks.Disk_28 = QemuScsiStorage{}.mapToStruct(params["scsi28"].(string)) + structPopulated = true + } + if _, isSet := params["scsi29"]; isSet { + disks.Disk_29 = QemuScsiStorage{}.mapToStruct(params["scsi29"].(string)) + structPopulated = true + } + if _, isSet := params["scsi30"]; isSet { + disks.Disk_30 = QemuScsiStorage{}.mapToStruct(params["scsi30"].(string)) + structPopulated = true + } + if structPopulated { + return &disks + } + return nil +} + +type QemuScsiPassthrough struct { + AsyncIO QemuDiskAsyncIO + Backup bool + Bandwidth QemuDiskBandwidth + Cache QemuDiskCache + Discard bool + EmulateSSD bool + File string + IOThread bool + ReadOnly bool + Replicate bool + Size uint +} + +type QemuScsiStorage struct { + CdRom *QemuCdRom + CloudInit *QemuCloudInitDisk + Disk *QemuScsiDisk + Passthrough *QemuScsiPassthrough +} + +func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { + settings := splitStringOfSettings(param) + tmpCdRom := qemuCdRom{}.mapToStruct(settings) + if tmpCdRom != nil { + if tmpCdRom.FileType == "" { + return &QemuScsiStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} + } else { + return &QemuScsiStorage{CloudInit: QemuCloudInitDisk{}.mapToStruct(*tmpCdRom)} + } + } + + tmpDisk := qemuDisk{}.mapToStruct(settings) + if tmpDisk == nil { + return nil + } + if tmpDisk.File == "" { + return &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + IOThread: tmpDisk.IOThread, + ReadOnly: tmpDisk.ReadOnly, + Replicate: tmpDisk.Replicate, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, + }} + } + return &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + File: tmpDisk.File, + IOThread: tmpDisk.IOThread, + ReadOnly: tmpDisk.ReadOnly, + Replicate: tmpDisk.Replicate, + Size: tmpDisk.Size, + }} + +} diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go new file mode 100644 index 00000000..66f07dad --- /dev/null +++ b/proxmox/config_qemu_disk_virtio.go @@ -0,0 +1,165 @@ +package proxmox + +type QemuVirtIODisk struct { + AsyncIO QemuDiskAsyncIO + Backup bool + Bandwidth QemuDiskBandwidth + Cache QemuDiskCache + Discard bool + IOThread bool + ReadOnly bool + Size uint + Storage string +} + +type QemuVirtIODisks struct { + Disk_0 *QemuVirtIOStorage + Disk_1 *QemuVirtIOStorage + Disk_2 *QemuVirtIOStorage + Disk_3 *QemuVirtIOStorage + Disk_4 *QemuVirtIOStorage + Disk_5 *QemuVirtIOStorage + Disk_6 *QemuVirtIOStorage + Disk_7 *QemuVirtIOStorage + Disk_8 *QemuVirtIOStorage + Disk_9 *QemuVirtIOStorage + Disk_10 *QemuVirtIOStorage + Disk_11 *QemuVirtIOStorage + Disk_12 *QemuVirtIOStorage + Disk_13 *QemuVirtIOStorage + Disk_14 *QemuVirtIOStorage + Disk_15 *QemuVirtIOStorage +} + +func (QemuVirtIODisks) mapToStruct(params map[string]interface{}) *QemuVirtIODisks { + disks := QemuVirtIODisks{} + var structPopulated bool + if _, isSet := params["virtio0"]; isSet { + disks.Disk_0 = QemuVirtIOStorage{}.mapToStruct(params["virtio0"].(string)) + structPopulated = true + } + if _, isSet := params["virtio1"]; isSet { + disks.Disk_1 = QemuVirtIOStorage{}.mapToStruct(params["virtio1"].(string)) + structPopulated = true + } + if _, isSet := params["virtio2"]; isSet { + disks.Disk_2 = QemuVirtIOStorage{}.mapToStruct(params["virtio2"].(string)) + structPopulated = true + } + if _, isSet := params["virtio3"]; isSet { + disks.Disk_3 = QemuVirtIOStorage{}.mapToStruct(params["virtio3"].(string)) + structPopulated = true + } + if _, isSet := params["virtio4"]; isSet { + disks.Disk_4 = QemuVirtIOStorage{}.mapToStruct(params["virtio4"].(string)) + structPopulated = true + } + if _, isSet := params["virtio5"]; isSet { + disks.Disk_5 = QemuVirtIOStorage{}.mapToStruct(params["virtio5"].(string)) + structPopulated = true + } + if _, isSet := params["virtio6"]; isSet { + disks.Disk_6 = QemuVirtIOStorage{}.mapToStruct(params["virtio6"].(string)) + structPopulated = true + } + if _, isSet := params["virtio7"]; isSet { + disks.Disk_7 = QemuVirtIOStorage{}.mapToStruct(params["virtio7"].(string)) + structPopulated = true + } + if _, isSet := params["virtio8"]; isSet { + disks.Disk_8 = QemuVirtIOStorage{}.mapToStruct(params["virtio8"].(string)) + structPopulated = true + } + if _, isSet := params["virtio9"]; isSet { + disks.Disk_9 = QemuVirtIOStorage{}.mapToStruct(params["virtio9"].(string)) + structPopulated = true + } + if _, isSet := params["virtio10"]; isSet { + disks.Disk_10 = QemuVirtIOStorage{}.mapToStruct(params["virtio10"].(string)) + structPopulated = true + } + if _, isSet := params["virtio11"]; isSet { + disks.Disk_11 = QemuVirtIOStorage{}.mapToStruct(params["virtio11"].(string)) + structPopulated = true + } + if _, isSet := params["virtio12"]; isSet { + disks.Disk_12 = QemuVirtIOStorage{}.mapToStruct(params["virtio12"].(string)) + structPopulated = true + } + if _, isSet := params["virtio13"]; isSet { + disks.Disk_13 = QemuVirtIOStorage{}.mapToStruct(params["virtio13"].(string)) + structPopulated = true + } + if _, isSet := params["virtio14"]; isSet { + disks.Disk_14 = QemuVirtIOStorage{}.mapToStruct(params["virtio14"].(string)) + structPopulated = true + } + if _, isSet := params["virtio15"]; isSet { + disks.Disk_15 = QemuVirtIOStorage{}.mapToStruct(params["virtio15"].(string)) + structPopulated = true + } + if structPopulated { + return &disks + } + return nil +} + +type QemuVirtIOPassthrough struct { + AsyncIO QemuDiskAsyncIO + Backup bool + Bandwidth QemuDiskBandwidth + Cache QemuDiskCache + Discard bool + File string + IOThread bool + ReadOnly bool + Size uint +} + +type QemuVirtIOStorage struct { + CdRom *QemuCdRom + CloudInit *QemuCloudInitDisk + Disk *QemuVirtIODisk + Passthrough *QemuVirtIOPassthrough +} + +func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { + settings := splitStringOfSettings(param) + tmpCdRom := qemuCdRom{}.mapToStruct(settings) + if tmpCdRom != nil { + if tmpCdRom.FileType == "" { + return &QemuVirtIOStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} + } else { + return &QemuVirtIOStorage{CloudInit: QemuCloudInitDisk{}.mapToStruct(*tmpCdRom)} + } + } + + tmpDisk := qemuDisk{}.mapToStruct(settings) + if tmpDisk == nil { + return nil + } + if tmpDisk.File == "" { + return &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + IOThread: tmpDisk.IOThread, + ReadOnly: tmpDisk.ReadOnly, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, + }} + } + return &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + File: tmpDisk.File, + IOThread: tmpDisk.IOThread, + ReadOnly: tmpDisk.ReadOnly, + Size: tmpDisk.Size, + }} +} diff --git a/proxmox/util.go b/proxmox/util.go index 806f3a73..253fa4ea 100644 --- a/proxmox/util.go +++ b/proxmox/util.go @@ -204,3 +204,12 @@ func createHeaderList(header_string string, sess *Session) (*Session, error) { } return sess, nil } + +func splitStringOfSettings(settings string) (settingArray [][]string) { + settingValuePairs := strings.Split(settings, ",") + settingArray = make([][]string, len(settingValuePairs)) + for i, e := range settingValuePairs { + settingArray[i] = strings.SplitN(e, "=", 2) + } + return +} diff --git a/proxmox/util_test.go b/proxmox/util_test.go new file mode 100644 index 00000000..38b2c45a --- /dev/null +++ b/proxmox/util_test.go @@ -0,0 +1,28 @@ +package proxmox + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_splitStringOfSettings(t *testing.T) { + testData := []struct { + Input string + Output [][]string + }{ + { + Input: "setting=a,thing=b,randomString,doubleTest=value=equals,object=test", + Output: [][]string{ + {"setting", "a"}, + {"thing", "b"}, + {"randomString"}, + {"doubleTest", "value=equals"}, + {"object", "test"}, + }, + }, + } + for _, e := range testData { + require.Equal(t, e.Output, splitStringOfSettings(e.Input)) + } +} From a4ec1a168366171cfe2b9243c218044a7349af02 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 10:58:33 +0000 Subject: [PATCH 002/120] feat: Add Disks parameter in ConfigQemu struct --- proxmox/config_qemu.go | 80 ++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 1010a300..38efb72d 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -35,45 +35,46 @@ type AgentNetworkInterface struct { // ConfigQemu - Proxmox API QEMU options type ConfigQemu struct { - VmID int `json:"vmid,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - Pool string `json:"pool,omitempty"` - Bios string `json:"bios,omitempty"` - EFIDisk QemuDevice `json:"efidisk,omitempty"` - Machine string `json:"machine,omitempty"` - Onboot *bool `json:"onboot,omitempty"` - Startup string `json:"startup,omitempty"` - Tablet *bool `json:"tablet,omitempty"` - Agent int `json:"agent,omitempty"` - Memory int `json:"memory,omitempty"` - Balloon int `json:"balloon,omitempty"` - QemuOs string `json:"ostype,omitempty"` - QemuCores int `json:"cores,omitempty"` - QemuSockets int `json:"sockets,omitempty"` - QemuVcpus int `json:"vcpus,omitempty"` - QemuCpu string `json:"cpu,omitempty"` - QemuNuma *bool `json:"numa,omitempty"` - QemuKVM *bool `json:"kvm,omitempty"` - Hotplug string `json:"hotplug,omitempty"` - QemuIso string `json:"iso,omitempty"` - QemuPxe bool `json:"pxe,omitempty"` - FullClone *int `json:"fullclone,omitempty"` - Boot string `json:"boot,omitempty"` - BootDisk string `json:"bootdisk,omitempty"` - Scsihw string `json:"scsihw,omitempty"` - QemuDisks QemuDevices `json:"disk,omitempty"` - QemuUnusedDisks QemuDevices `json:"unused,omitempty"` - QemuVga QemuDevice `json:"vga,omitempty"` - QemuNetworks QemuDevices `json:"network,omitempty"` - QemuSerials QemuDevices `json:"serial,omitempty"` - QemuUsbs QemuDevices `json:"usb,omitempty"` - QemuPCIDevices QemuDevices `json:"hostpci,omitempty"` - Hookscript string `json:"hookscript,omitempty"` - HaState string `json:"hastate,omitempty"` - HaGroup string `json:"hagroup,omitempty"` - Tags string `json:"tags,omitempty"` - Args string `json:"args,omitempty"` + VmID int `json:"vmid,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Pool string `json:"pool,omitempty"` + Bios string `json:"bios,omitempty"` + EFIDisk QemuDevice `json:"efidisk,omitempty"` + Machine string `json:"machine,omitempty"` + Onboot *bool `json:"onboot,omitempty"` + Startup string `json:"startup,omitempty"` + Tablet *bool `json:"tablet,omitempty"` + Agent int `json:"agent,omitempty"` + Memory int `json:"memory,omitempty"` + Balloon int `json:"balloon,omitempty"` + QemuOs string `json:"ostype,omitempty"` + QemuCores int `json:"cores,omitempty"` + QemuSockets int `json:"sockets,omitempty"` + QemuVcpus int `json:"vcpus,omitempty"` + QemuCpu string `json:"cpu,omitempty"` + QemuNuma *bool `json:"numa,omitempty"` + QemuKVM *bool `json:"kvm,omitempty"` + Hotplug string `json:"hotplug,omitempty"` + QemuIso string `json:"iso,omitempty"` + QemuPxe bool `json:"pxe,omitempty"` + FullClone *int `json:"fullclone,omitempty"` + Boot string `json:"boot,omitempty"` + BootDisk string `json:"bootdisk,omitempty"` + Scsihw string `json:"scsihw,omitempty"` + Disks *QemuStorages `json:"disks,omitempty"` + QemuDisks QemuDevices `json:"disk,omitempty"` + QemuUnusedDisks QemuDevices `json:"unused,omitempty"` + QemuVga QemuDevice `json:"vga,omitempty"` + QemuNetworks QemuDevices `json:"network,omitempty"` + QemuSerials QemuDevices `json:"serial,omitempty"` + QemuUsbs QemuDevices `json:"usb,omitempty"` + QemuPCIDevices QemuDevices `json:"hostpci,omitempty"` + Hookscript string `json:"hookscript,omitempty"` + HaState string `json:"hastate,omitempty"` + HaGroup string `json:"hagroup,omitempty"` + Tags string `json:"tags,omitempty"` + Args string `json:"args,omitempty"` // cloud-init options CIuser string `json:"ciuser,omitempty"` @@ -127,6 +128,7 @@ func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { params["onboot"] = *config.Onboot } + // TODO conflicts with new mapping if config.QemuIso != "" { params["ide2"] = config.QemuIso + ",media=cdrom" } From 5fc83d2851fd8288fa60e2247f4d839b74cd1f4a Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 11:05:39 +0000 Subject: [PATCH 003/120] feat: Map Qemu Disks to api values --- proxmox/config_qemu_disk.go | 147 +++++++++++++++++++++++---- proxmox/config_qemu_disk_ide.go | 85 ++++++++++++---- proxmox/config_qemu_disk_sata.go | 75 ++++++++++++-- proxmox/config_qemu_disk_scsi.go | 156 +++++++++++++++++++++++++++-- proxmox/config_qemu_disk_virtio.go | 107 ++++++++++++++++++-- 5 files changed, 503 insertions(+), 67 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 5e110e96..37be8dbc 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -1,6 +1,7 @@ package proxmox import ( + "fmt" "math" "strconv" "strings" @@ -19,6 +20,11 @@ type QemuCdRom struct { Passthrough bool } +// TODO write function +func (cdRom QemuCdRom) mapToApiValues() string { + return "" +} + func (QemuCdRom) mapToStruct(settings qemuCdRom) *QemuCdRom { if !settings.Passthrough { return &QemuCdRom{ @@ -96,6 +102,11 @@ type QemuCloudInitDisk struct { FileType string } +// TODO write function +func (cloudInit QemuCloudInitDisk) mapToApiValues() string { + return "" +} + func (QemuCloudInitDisk) mapToStruct(settings qemuCdRom) *QemuCloudInitDisk { return &QemuCloudInitDisk{ Storage: settings.Storage, @@ -129,32 +140,91 @@ type QemuDiskCache string // TODO add enum type QemuDiskFormat string -func (QemuDiskFormat) mapToStruct(setting string) QemuDiskFormat { - settings := strings.Split(setting, ".") - if len(settings) < 2 { - return "" - } - return QemuDiskFormat(settings[len(settings)-1]) -} - type qemuDisk struct { AsyncIO QemuDiskAsyncIO Backup bool Bandwidth QemuDiskBandwidth Cache QemuDiskCache Discard bool - EmulateSSD bool + EmulateSSD bool // Only set for ide,sata,scsi // TODO custom type - // File is only set for Passthrough. - File string + File string // Only set for Passthrough. Format QemuDiskFormat - IOThread bool - ReadOnly bool + IOThread bool // Only set for scsi,virtio + Number uint // Only set for Disk + ReadOnly bool // Only set for scsi,virtio Replicate bool Size uint // TODO custom type - // Storage is only set for Disk - Storage string + Storage string // Only set for Disk + Type qemuDiskType +} + +func (disk qemuDisk) mapToApiValues(create bool) (settings string) { + if create { + if disk.Storage != "" { + settings = disk.Storage + ":" + strconv.Itoa(int(disk.Size)) + } + } + + // Set File + + if disk.AsyncIO != "" { + settings = settings + ",aio=" + string(disk.AsyncIO) + } + if !disk.Backup { + settings = settings + ",backup=0" + } + if disk.Cache != "" { + settings = settings + ",cache=" + string(disk.Cache) + } + if disk.Discard { + settings = settings + ",discard=on" + } + // format + // media + + if disk.Bandwidth.ReadLimit_Iops.Concurrent >= 10 { + settings = settings + ",iops_rd=" + strconv.Itoa(int(disk.Bandwidth.ReadLimit_Iops.Concurrent)) + } + if disk.Bandwidth.ReadLimit_Iops.Burst >= 10 { + settings = settings + ",iops_rd_max=" + strconv.Itoa(int(disk.Bandwidth.ReadLimit_Iops.Burst)) + } + if disk.Bandwidth.WriteLimit_Iops.Concurrent >= 10 { + settings = settings + ",iops_wr=" + strconv.Itoa(int(disk.Bandwidth.WriteLimit_Iops.Concurrent)) + } + if disk.Bandwidth.WriteLimit_Iops.Burst >= 10 { + settings = settings + ",iops_wr_max=" + strconv.Itoa(int(disk.Bandwidth.WriteLimit_Iops.Burst)) + } + + if (disk.Type == scsi || disk.Type == virtIO) && disk.IOThread { + settings = settings + ",iothread=1" + } + + if disk.Bandwidth.ReadLimit_Data.Concurrent >= float32(1) { + settings = settings + fmt.Sprintf(",mbps_rd=%.2f", disk.Bandwidth.ReadLimit_Data.Concurrent) + } + if disk.Bandwidth.ReadLimit_Data.Burst >= float32(1) { + settings = settings + fmt.Sprintf(",mbps_rd_max=%.2f", disk.Bandwidth.ReadLimit_Data.Burst) + } + if disk.Bandwidth.WriteLimit_Data.Concurrent >= float32(1) { + settings = settings + fmt.Sprintf(",mbps_wr=%.2f", disk.Bandwidth.WriteLimit_Data.Concurrent) + } + if disk.Bandwidth.WriteLimit_Data.Burst >= float32(1) { + settings = settings + fmt.Sprintf(",mbps_wr_max=%.2f", disk.Bandwidth.WriteLimit_Data.Burst) + } + + if !disk.Replicate { + settings = settings + ",replicate=0" + } + if (disk.Type == scsi || disk.Type == virtIO) && disk.ReadOnly { + settings = settings + ",ro=1" + } + if disk.Type != virtIO && disk.EmulateSSD { + settings = settings + ",ssd=1" + } + + return } // Maps all the disk related settings @@ -168,8 +238,19 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { disk.File = settings[0][0] } else { // "test2:105/vm-105-disk-53.qcow2, - disk.Storage = strings.Split(settings[0][0], ":")[0] - disk.Format = QemuDiskFormat("").mapToStruct(settings[0][0]) + diskAndNumberAndFormat := strings.Split(settings[0][0], ":") + disk.Storage = diskAndNumberAndFormat[0] + if len(diskAndNumberAndFormat) == 2 { + numberAndFormat := strings.Split(diskAndNumberAndFormat[1], "-") + if len(numberAndFormat) == 2 { + tmp := strings.Split(numberAndFormat[1], ".") + tmpNumber, _ := strconv.Atoi(tmp[0]) + disk.Number = uint(tmpNumber) + if len(tmp) == 2 { + disk.Format = QemuDiskFormat(tmp[1]) + } + } + } } for _, e := range settings { @@ -245,11 +326,35 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { return &disk } +type qemuDiskType int + +const ( + ide qemuDiskType = 0 + sata qemuDiskType = 1 + scsi qemuDiskType = 2 + virtIO qemuDiskType = 3 +) + type QemuStorages struct { - Ide *QemuIdeDisks - Sata *QemuSataDisks - Scsi *QemuScsiDisks - VirtIO *QemuVirtIODisks + Ide *QemuIdeDisks `json:"ide,omitempty"` + Sata *QemuSataDisks `json:"sata,omitempty"` + Scsi *QemuScsiDisks `json:"scsi,omitempty"` + VirtIO *QemuVirtIODisks `json:"virtio,omitempty"` +} + +func (storages QemuStorages) mapToApiValues(create bool, params map[string]interface{}) { + if storages.Ide != nil { + storages.Ide.mapToApiValues(create, params) + } + if storages.Sata != nil { + storages.Sata.mapToApiValues(create, params) + } + if storages.Scsi != nil { + storages.Scsi.mapToApiValues(create, params) + } + if storages.VirtIO != nil { + storages.VirtIO.mapToApiValues(create, params) + } } func (QemuStorages) mapToStruct(params map[string]interface{}) *QemuStorages { diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 9db3ba5b..69986585 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -1,22 +1,52 @@ package proxmox type QemuIdeDisk struct { - AsyncIO QemuDiskAsyncIO - Backup bool - Bandwidth QemuDiskBandwidth - Cache QemuDiskCache - Discard bool - EmulateSSD bool - Replicate bool - Size uint - Storage string + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup,omitempty"` + Bandwidth QemuDiskBandwidth `json:"bandwith,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard,omitempty"` + EmulateSSD bool `json:"emulatessd,omitempty"` + Replicate bool `json:"replicate,omitempty"` + Size uint `json:"size,omitempty"` + Storage string `json:"storage,omitempty"` +} + +func (disk QemuIdeDisk) mapToApiValues(create bool) string { + return qemuDisk{ + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + EmulateSSD: disk.EmulateSSD, + Replicate: disk.Replicate, + Size: disk.Size, + Storage: disk.Storage, + Type: ide, + }.mapToApiValues(create) } type QemuIdeDisks struct { - Disk_0 *QemuIdeStorage - Disk_1 *QemuIdeStorage - Disk_2 *QemuIdeStorage - Disk_3 *QemuIdeStorage + Disk_0 *QemuIdeStorage `json:"0,omitempty"` + Disk_1 *QemuIdeStorage `json:"1,omitempty"` + Disk_2 *QemuIdeStorage `json:"2,omitempty"` + Disk_3 *QemuIdeStorage `json:"3,omitempty"` +} + +func (disks QemuIdeDisks) mapToApiValues(create bool, params map[string]interface{}) { + if disks.Disk_0 != nil { + params["ide0"] = disks.Disk_0.mapToApiValues(create) + } + if disks.Disk_1 != nil { + params["ide1"] = disks.Disk_0.mapToApiValues(create) + } + if disks.Disk_2 != nil { + params["ide2"] = disks.Disk_0.mapToApiValues(create) + } + if disks.Disk_3 != nil { + params["ide3"] = disks.Disk_0.mapToApiValues(create) + } } func (QemuIdeDisks) mapToStruct(params map[string]interface{}) *QemuIdeDisks { @@ -56,11 +86,32 @@ type QemuIdePassthrough struct { Size uint } +// TODO write function +func (passthrough QemuIdePassthrough) mapToApiValues() string { + return "" +} + type QemuIdeStorage struct { - CdRom *QemuCdRom - CloudInit *QemuCloudInitDisk - Disk *QemuIdeDisk - Passthrough *QemuIdePassthrough + CdRom *QemuCdRom `json:"cdrom,omitempty"` + CloudInit *QemuCloudInitDisk `json:"cloudinit,omitempty"` + Disk *QemuIdeDisk `json:"disk,omitempty"` + Passthrough *QemuIdePassthrough `json:"passthrough,omitempty"` +} + +func (storage QemuIdeStorage) mapToApiValues(create bool) string { + if storage.Disk != nil { + return storage.Disk.mapToApiValues(create) + } + if storage.CdRom != nil { + return storage.CdRom.mapToApiValues() + } + if storage.CloudInit != nil { + return storage.CloudInit.mapToApiValues() + } + if storage.Passthrough != nil { + return storage.Passthrough.mapToApiValues() + } + return "" } func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index ac1555c9..c1a447b3 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -1,15 +1,30 @@ package proxmox type QemuSataDisk struct { - AsyncIO QemuDiskAsyncIO - Backup bool - Bandwidth QemuDiskBandwidth - Cache QemuDiskCache - Discard bool - EmulateSSD bool - Replicate bool - Size uint - Storage string + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup,omitempty"` + Bandwidth QemuDiskBandwidth `json:"bandwith,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard,omitempty"` + EmulateSSD bool `json:"emulatessd,omitempty"` + Replicate bool `json:"replicate,omitempty"` + Size uint `json:"size,omitempty"` + Storage string `json:"storage,omitempty"` +} + +func (disk QemuSataDisk) mapToApiValues(create bool) string { + return qemuDisk{ + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + EmulateSSD: disk.EmulateSSD, + Replicate: disk.Replicate, + Size: disk.Size, + Storage: disk.Storage, + Type: sata, + }.mapToApiValues(create) } type QemuSataDisks struct { @@ -21,6 +36,27 @@ type QemuSataDisks struct { Disk_5 *QemuSataStorage } +func (disks QemuSataDisks) mapToApiValues(create bool, params map[string]interface{}) { + if disks.Disk_0 != nil { + params["sata0"] = disks.Disk_0.mapToApiValues(create) + } + if disks.Disk_1 != nil { + params["sata1"] = disks.Disk_1.mapToApiValues(create) + } + if disks.Disk_2 != nil { + params["sata2"] = disks.Disk_2.mapToApiValues(create) + } + if disks.Disk_3 != nil { + params["sata3"] = disks.Disk_3.mapToApiValues(create) + } + if disks.Disk_4 != nil { + params["sata4"] = disks.Disk_4.mapToApiValues(create) + } + if disks.Disk_5 != nil { + params["sata5"] = disks.Disk_5.mapToApiValues(create) + } +} + func (QemuSataDisks) mapToStruct(params map[string]interface{}) *QemuSataDisks { disks := QemuSataDisks{} var structPopulated bool @@ -66,6 +102,11 @@ type QemuSataPassthrough struct { Size uint } +// TODO write function +func (passthrough QemuSataPassthrough) mapToApiValues() string { + return "" +} + type QemuSataStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -73,6 +114,22 @@ type QemuSataStorage struct { Passthrough *QemuSataPassthrough } +func (storage QemuSataStorage) mapToApiValues(create bool) string { + if storage.Disk != nil { + return storage.Disk.mapToApiValues(create) + } + if storage.CdRom != nil { + return storage.CdRom.mapToApiValues() + } + if storage.CloudInit != nil { + return storage.CloudInit.mapToApiValues() + } + if storage.Passthrough != nil { + return storage.Passthrough.mapToApiValues() + } + return "" +} + func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 5aa56e0b..de46ccce 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -1,17 +1,34 @@ package proxmox type QemuScsiDisk struct { - AsyncIO QemuDiskAsyncIO - Backup bool - Bandwidth QemuDiskBandwidth - Cache QemuDiskCache - Discard bool - EmulateSSD bool - IOThread bool - ReadOnly bool - Replicate bool - Size uint - Storage string + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup,omitempty"` + Bandwidth QemuDiskBandwidth `json:"bandwith,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard,omitempty"` + EmulateSSD bool `json:"emulatessd,omitempty"` + IOThread bool `json:"iothread,omitempty"` + ReadOnly bool `json:"readonly,omitempty"` + Replicate bool `json:"replicate,omitempty"` + Size uint `json:"size,omitempty"` + Storage string `json:"storage,omitempty"` +} + +func (disk QemuScsiDisk) mapToApiValues(create bool) string { + return qemuDisk{ + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + EmulateSSD: disk.EmulateSSD, + IOThread: disk.IOThread, + ReadOnly: disk.ReadOnly, + Replicate: disk.Replicate, + Size: disk.Size, + Storage: disk.Storage, + Type: scsi, + }.mapToApiValues(create) } type QemuScsiDisks struct { @@ -48,6 +65,102 @@ type QemuScsiDisks struct { Disk_30 *QemuScsiStorage } +func (disks QemuScsiDisks) mapToApiValues(create bool, params map[string]interface{}) { + if disks.Disk_0 != nil { + params["scsi0"] = disks.Disk_0.mapToApiValues(create) + } + if disks.Disk_1 != nil { + params["scsi1"] = disks.Disk_1.mapToApiValues(create) + } + if disks.Disk_2 != nil { + params["scsi2"] = disks.Disk_2.mapToApiValues(create) + } + if disks.Disk_3 != nil { + params["scsi3"] = disks.Disk_3.mapToApiValues(create) + } + if disks.Disk_4 != nil { + params["scsi4"] = disks.Disk_4.mapToApiValues(create) + } + if disks.Disk_5 != nil { + params["scsi5"] = disks.Disk_5.mapToApiValues(create) + } + if disks.Disk_6 != nil { + params["scsi6"] = disks.Disk_6.mapToApiValues(create) + } + if disks.Disk_7 != nil { + params["scsi7"] = disks.Disk_7.mapToApiValues(create) + } + if disks.Disk_8 != nil { + params["scsi8"] = disks.Disk_8.mapToApiValues(create) + } + if disks.Disk_9 != nil { + params["scsi9"] = disks.Disk_9.mapToApiValues(create) + } + if disks.Disk_10 != nil { + params["scsi10"] = disks.Disk_10.mapToApiValues(create) + } + if disks.Disk_11 != nil { + params["scsi11"] = disks.Disk_11.mapToApiValues(create) + } + if disks.Disk_12 != nil { + params["scsi12"] = disks.Disk_12.mapToApiValues(create) + } + if disks.Disk_13 != nil { + params["scsi13"] = disks.Disk_13.mapToApiValues(create) + } + if disks.Disk_14 != nil { + params["scsi14"] = disks.Disk_14.mapToApiValues(create) + } + if disks.Disk_15 != nil { + params["scsi15"] = disks.Disk_15.mapToApiValues(create) + } + if disks.Disk_16 != nil { + params["scsi16"] = disks.Disk_16.mapToApiValues(create) + } + if disks.Disk_17 != nil { + params["scsi17"] = disks.Disk_17.mapToApiValues(create) + } + if disks.Disk_18 != nil { + params["scsi18"] = disks.Disk_18.mapToApiValues(create) + } + if disks.Disk_19 != nil { + params["scsi19"] = disks.Disk_19.mapToApiValues(create) + } + if disks.Disk_20 != nil { + params["scsi20"] = disks.Disk_20.mapToApiValues(create) + } + if disks.Disk_21 != nil { + params["scsi21"] = disks.Disk_21.mapToApiValues(create) + } + if disks.Disk_22 != nil { + params["scsi22"] = disks.Disk_22.mapToApiValues(create) + } + if disks.Disk_23 != nil { + params["scsi23"] = disks.Disk_23.mapToApiValues(create) + } + if disks.Disk_24 != nil { + params["scsi24"] = disks.Disk_24.mapToApiValues(create) + } + if disks.Disk_25 != nil { + params["scsi25"] = disks.Disk_25.mapToApiValues(create) + } + if disks.Disk_26 != nil { + params["scsi26"] = disks.Disk_26.mapToApiValues(create) + } + if disks.Disk_27 != nil { + params["scsi27"] = disks.Disk_27.mapToApiValues(create) + } + if disks.Disk_28 != nil { + params["scsi28"] = disks.Disk_28.mapToApiValues(create) + } + if disks.Disk_29 != nil { + params["scsi29"] = disks.Disk_29.mapToApiValues(create) + } + if disks.Disk_30 != nil { + params["scsi30"] = disks.Disk_30.mapToApiValues(create) + } +} + func (QemuScsiDisks) mapToStruct(params map[string]interface{}) *QemuScsiDisks { disks := QemuScsiDisks{} var structPopulated bool @@ -195,6 +308,11 @@ type QemuScsiPassthrough struct { Size uint } +// TODO write function +func (passthrough QemuScsiPassthrough) mapToApiValues() string { + return "" +} + type QemuScsiStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -202,6 +320,22 @@ type QemuScsiStorage struct { Passthrough *QemuScsiPassthrough } +func (storage QemuScsiStorage) mapToApiValues(create bool) string { + if storage.Disk != nil { + return storage.Disk.mapToApiValues(create) + } + if storage.CdRom != nil { + return storage.CdRom.mapToApiValues() + } + if storage.CloudInit != nil { + return storage.CloudInit.mapToApiValues() + } + if storage.Passthrough != nil { + return storage.Passthrough.mapToApiValues() + } + return "" +} + func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 66f07dad..f4f30e74 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -1,15 +1,31 @@ package proxmox type QemuVirtIODisk struct { - AsyncIO QemuDiskAsyncIO - Backup bool - Bandwidth QemuDiskBandwidth - Cache QemuDiskCache - Discard bool - IOThread bool - ReadOnly bool - Size uint - Storage string + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup,omitempty"` + Bandwidth QemuDiskBandwidth `json:"bandwith,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard,omitempty"` + IOThread bool `json:"iothread,omitempty"` + ReadOnly bool `json:"readonly,omitempty"` + Replicate bool `json:"replicate,omitempty"` + Size uint `json:"size,omitempty"` + Storage string `json:"storage,omitempty"` +} + +func (disk QemuVirtIODisk) mapToApiValues(create bool) string { + return qemuDisk{ + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + IOThread: disk.IOThread, + ReadOnly: disk.ReadOnly, + Size: disk.Size, + Storage: disk.Storage, + Type: virtIO, + }.mapToApiValues(create) } type QemuVirtIODisks struct { @@ -31,6 +47,57 @@ type QemuVirtIODisks struct { Disk_15 *QemuVirtIOStorage } +func (disks QemuVirtIODisks) mapToApiValues(create bool, params map[string]interface{}) { + if disks.Disk_0 != nil { + params["virtio0"] = disks.Disk_0.mapToApiValues(create) + } + if disks.Disk_1 != nil { + params["virtio1"] = disks.Disk_1.mapToApiValues(create) + } + if disks.Disk_2 != nil { + params["virtio2"] = disks.Disk_2.mapToApiValues(create) + } + if disks.Disk_3 != nil { + params["virtio3"] = disks.Disk_3.mapToApiValues(create) + } + if disks.Disk_4 != nil { + params["virtio4"] = disks.Disk_4.mapToApiValues(create) + } + if disks.Disk_5 != nil { + params["virtio5"] = disks.Disk_5.mapToApiValues(create) + } + if disks.Disk_6 != nil { + params["virtio6"] = disks.Disk_6.mapToApiValues(create) + } + if disks.Disk_7 != nil { + params["virtio7"] = disks.Disk_7.mapToApiValues(create) + } + if disks.Disk_8 != nil { + params["virtio8"] = disks.Disk_8.mapToApiValues(create) + } + if disks.Disk_9 != nil { + params["virtio9"] = disks.Disk_9.mapToApiValues(create) + } + if disks.Disk_10 != nil { + params["virtio10"] = disks.Disk_10.mapToApiValues(create) + } + if disks.Disk_11 != nil { + params["virtio11"] = disks.Disk_11.mapToApiValues(create) + } + if disks.Disk_12 != nil { + params["virtio12"] = disks.Disk_12.mapToApiValues(create) + } + if disks.Disk_13 != nil { + params["virtio13"] = disks.Disk_13.mapToApiValues(create) + } + if disks.Disk_14 != nil { + params["virtio14"] = disks.Disk_14.mapToApiValues(create) + } + if disks.Disk_15 != nil { + params["virtio15"] = disks.Disk_15.mapToApiValues(create) + } +} + func (QemuVirtIODisks) mapToStruct(params map[string]interface{}) *QemuVirtIODisks { disks := QemuVirtIODisks{} var structPopulated bool @@ -116,6 +183,11 @@ type QemuVirtIOPassthrough struct { Size uint } +// TODO write function +func (passthrough QemuVirtIOPassthrough) mapToApiValues() string { + return "" +} + type QemuVirtIOStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -123,6 +195,22 @@ type QemuVirtIOStorage struct { Passthrough *QemuVirtIOPassthrough } +func (storage QemuVirtIOStorage) mapToApiValues(create bool) string { + if storage.Disk != nil { + return storage.Disk.mapToApiValues(create) + } + if storage.CdRom != nil { + return storage.CdRom.mapToApiValues() + } + if storage.CloudInit != nil { + return storage.CloudInit.mapToApiValues() + } + if storage.Passthrough != nil { + return storage.Passthrough.mapToApiValues() + } + return "" +} + func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) @@ -147,6 +235,7 @@ func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { Discard: tmpDisk.Discard, IOThread: tmpDisk.IOThread, ReadOnly: tmpDisk.ReadOnly, + Replicate: tmpDisk.Replicate, Size: tmpDisk.Size, Storage: tmpDisk.Storage, }} From a89a72e1db7f831e665220cea64d65a9122d093e Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 11:34:13 +0000 Subject: [PATCH 004/120] style: put in alphabetical order --- proxmox/config_qemu_disk.go | 52 ++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 37be8dbc..79f9f8f6 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -114,32 +114,6 @@ func (QemuCloudInitDisk) mapToStruct(settings qemuCdRom) *QemuCloudInitDisk { } } -// TODO add enum -type QemuDiskAsyncIO string - -type QemuDiskBandwidth struct { - ReadLimit_Data QemuDisk_Bandwidth_Data - WriteLimit_Data QemuDisk_Bandwidth_Data - ReadLimit_Iops QemuDisk_Bandwidth_Iops - WriteLimit_Iops QemuDisk_Bandwidth_Iops -} - -type QemuDisk_Bandwidth_Data struct { - Concurrent float32 - Burst float32 -} - -type QemuDisk_Bandwidth_Iops struct { - Concurrent uint - Burst uint -} - -// TODO add enum -type QemuDiskCache string - -// TODO add enum -type QemuDiskFormat string - type qemuDisk struct { AsyncIO QemuDiskAsyncIO Backup bool @@ -326,6 +300,32 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { return &disk } +// TODO add enum +type QemuDiskAsyncIO string + +type QemuDiskBandwidth struct { + ReadLimit_Data QemuDisk_Bandwidth_Data + WriteLimit_Data QemuDisk_Bandwidth_Data + ReadLimit_Iops QemuDisk_Bandwidth_Iops + WriteLimit_Iops QemuDisk_Bandwidth_Iops +} + +type QemuDisk_Bandwidth_Data struct { + Concurrent float32 + Burst float32 +} + +type QemuDisk_Bandwidth_Iops struct { + Concurrent uint + Burst uint +} + +// TODO add enum +type QemuDiskCache string + +// TODO add enum +type QemuDiskFormat string + type qemuDiskType int const ( From 8e45a16075ab16fcf174f025c27580917be7a30c Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 12:23:59 +0000 Subject: [PATCH 005/120] feat: Add serial key to disks --- proxmox/config_qemu_disk.go | 26 ++++++++++++++++++++++++++ proxmox/config_qemu_disk_ide.go | 5 +++++ proxmox/config_qemu_disk_sata.go | 5 +++++ proxmox/config_qemu_disk_scsi.go | 5 +++++ proxmox/config_qemu_disk_virtio.go | 5 +++++ 5 files changed, 46 insertions(+) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 79f9f8f6..a8bb2642 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -1,8 +1,10 @@ package proxmox import ( + "errors" "fmt" "math" + "regexp" "strconv" "strings" ) @@ -128,6 +130,7 @@ type qemuDisk struct { Number uint // Only set for Disk ReadOnly bool // Only set for scsi,virtio Replicate bool + Serial QemuDiskSerial Size uint // TODO custom type Storage string // Only set for Disk @@ -194,6 +197,9 @@ func (disk qemuDisk) mapToApiValues(create bool) (settings string) { if (disk.Type == scsi || disk.Type == virtIO) && disk.ReadOnly { settings = settings + ",ro=1" } + if disk.Serial != "" { + settings = settings + ",serial=" + string(disk.Serial) + } if disk.Type != virtIO && disk.EmulateSSD { settings = settings + ",ssd=1" } @@ -288,6 +294,10 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { disk.ReadOnly, _ = strconv.ParseBool(e[1]) continue } + if e[0] == "serial" { + disk.Serial = QemuDiskSerial(e[1]) + continue + } if e[0] == "size" { diskSize, _ := strconv.Atoi(strings.TrimSuffix(e[1], "G")) disk.Size = uint(diskSize) @@ -326,6 +336,22 @@ type QemuDiskCache string // TODO add enum type QemuDiskFormat string +type QemuDiskSerial string + +// QemuDiskSerial may only contain the following characters: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_ +// And has a max length of 60 characters +// TODO create test +func (serial QemuDiskSerial) Validate() error { + regex, _ := regexp.Compile(`^([a-z]|[A-Z]|[0-9]|_|-)*$`) + if !regex.Match([]byte(serial)) { + return errors.New("serial may only contain the following characters: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_") + } + if len(serial) > 60 { + return errors.New("serial may only be 60 characters long") + } + return nil +} + type qemuDiskType int const ( diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 69986585..f02bb471 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -8,6 +8,7 @@ type QemuIdeDisk struct { Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` Replicate bool `json:"replicate,omitempty"` + Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size,omitempty"` Storage string `json:"storage,omitempty"` } @@ -21,6 +22,7 @@ func (disk QemuIdeDisk) mapToApiValues(create bool) string { Discard: disk.Discard, EmulateSSD: disk.EmulateSSD, Replicate: disk.Replicate, + Serial: disk.Serial, Size: disk.Size, Storage: disk.Storage, Type: ide, @@ -83,6 +85,7 @@ type QemuIdePassthrough struct { EmulateSSD bool File string Replicate bool + Serial QemuDiskSerial `json:"serial,omitempty"` Size uint } @@ -138,6 +141,7 @@ func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { Discard: tmpDisk.Discard, EmulateSSD: tmpDisk.EmulateSSD, Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, Size: tmpDisk.Size, Storage: tmpDisk.Storage, }} @@ -151,6 +155,7 @@ func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { EmulateSSD: tmpDisk.EmulateSSD, File: tmpDisk.File, Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, Size: tmpDisk.Size, }} } diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index c1a447b3..12134229 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -8,6 +8,7 @@ type QemuSataDisk struct { Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` Replicate bool `json:"replicate,omitempty"` + Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size,omitempty"` Storage string `json:"storage,omitempty"` } @@ -21,6 +22,7 @@ func (disk QemuSataDisk) mapToApiValues(create bool) string { Discard: disk.Discard, EmulateSSD: disk.EmulateSSD, Replicate: disk.Replicate, + Serial: disk.Serial, Size: disk.Size, Storage: disk.Storage, Type: sata, @@ -99,6 +101,7 @@ type QemuSataPassthrough struct { EmulateSSD bool File string Replicate bool + Serial QemuDiskSerial `json:"serial,omitempty"` Size uint } @@ -154,6 +157,7 @@ func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { Discard: tmpDisk.Discard, EmulateSSD: tmpDisk.EmulateSSD, Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, Size: tmpDisk.Size, Storage: tmpDisk.Storage, }} @@ -167,6 +171,7 @@ func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { EmulateSSD: tmpDisk.EmulateSSD, File: tmpDisk.File, Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, Size: tmpDisk.Size, }} } diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index de46ccce..281558ce 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -10,6 +10,7 @@ type QemuScsiDisk struct { IOThread bool `json:"iothread,omitempty"` ReadOnly bool `json:"readonly,omitempty"` Replicate bool `json:"replicate,omitempty"` + Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size,omitempty"` Storage string `json:"storage,omitempty"` } @@ -25,6 +26,7 @@ func (disk QemuScsiDisk) mapToApiValues(create bool) string { IOThread: disk.IOThread, ReadOnly: disk.ReadOnly, Replicate: disk.Replicate, + Serial: disk.Serial, Size: disk.Size, Storage: disk.Storage, Type: scsi, @@ -305,6 +307,7 @@ type QemuScsiPassthrough struct { IOThread bool ReadOnly bool Replicate bool + Serial QemuDiskSerial `json:"serial,omitempty"` Size uint } @@ -362,6 +365,7 @@ func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { IOThread: tmpDisk.IOThread, ReadOnly: tmpDisk.ReadOnly, Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, Size: tmpDisk.Size, Storage: tmpDisk.Storage, }} @@ -377,6 +381,7 @@ func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { IOThread: tmpDisk.IOThread, ReadOnly: tmpDisk.ReadOnly, Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, Size: tmpDisk.Size, }} diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index f4f30e74..3ea6ed1b 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -9,6 +9,7 @@ type QemuVirtIODisk struct { IOThread bool `json:"iothread,omitempty"` ReadOnly bool `json:"readonly,omitempty"` Replicate bool `json:"replicate,omitempty"` + Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size,omitempty"` Storage string `json:"storage,omitempty"` } @@ -22,6 +23,7 @@ func (disk QemuVirtIODisk) mapToApiValues(create bool) string { Discard: disk.Discard, IOThread: disk.IOThread, ReadOnly: disk.ReadOnly, + Serial: disk.Serial, Size: disk.Size, Storage: disk.Storage, Type: virtIO, @@ -180,6 +182,7 @@ type QemuVirtIOPassthrough struct { File string IOThread bool ReadOnly bool + Serial QemuDiskSerial `json:"serial,omitempty"` Size uint } @@ -236,6 +239,7 @@ func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { IOThread: tmpDisk.IOThread, ReadOnly: tmpDisk.ReadOnly, Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, Size: tmpDisk.Size, Storage: tmpDisk.Storage, }} @@ -249,6 +253,7 @@ func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { File: tmpDisk.File, IOThread: tmpDisk.IOThread, ReadOnly: tmpDisk.ReadOnly, + Serial: tmpDisk.Serial, Size: tmpDisk.Size, }} } From 4967e1bb6be59685a3e23fc4bcb0bc97a6b00644 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 12:25:02 +0000 Subject: [PATCH 006/120] docs: Add TODO --- proxmox/config_qemu_disk.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index a8bb2642..2b529eb1 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -137,6 +137,7 @@ type qemuDisk struct { Type qemuDiskType } +// TODO write test func (disk qemuDisk) mapToApiValues(create bool) (settings string) { if create { if disk.Storage != "" { @@ -208,6 +209,7 @@ func (disk qemuDisk) mapToApiValues(create bool) (settings string) { } // Maps all the disk related settings +// TODO write test func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { if len(settings) == 0 { return nil From 7f697adb62c567dcd3edb15f23f7fbc697c16781 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 15:28:00 +0000 Subject: [PATCH 007/120] test: add test for QemuDiskSerial.Validate --- proxmox/config_qemu_disk.go | 1 - proxmox/config_qemu_disk_test.go | 24 ++++++ .../test_data_qemu/type_QemuDiskSerial.go | 80 +++++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 proxmox/config_qemu_disk_test.go create mode 100644 test/data/test_data_qemu/type_QemuDiskSerial.go diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 2b529eb1..24b88cbd 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -342,7 +342,6 @@ type QemuDiskSerial string // QemuDiskSerial may only contain the following characters: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_ // And has a max length of 60 characters -// TODO create test func (serial QemuDiskSerial) Validate() error { regex, _ := regexp.Compile(`^([a-z]|[A-Z]|[0-9]|_|-)*$`) if !regex.Match([]byte(serial)) { diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go new file mode 100644 index 00000000..829b1b5c --- /dev/null +++ b/proxmox/config_qemu_disk_test.go @@ -0,0 +1,24 @@ +package proxmox + +import ( + "testing" + + "github.com/Telmate/proxmox-api-go/test/data/test_data_qemu" + "github.com/stretchr/testify/require" +) + +func Test_QemuDiskSerial_Validate(t *testing.T) { + testRunes := struct { + legal []string + illegal []string + }{ + legal: test_data_qemu.QemuDiskSerial_Legal(), + illegal: test_data_qemu.QemuDiskSerial_Illegal(), + } + for _, e := range testRunes.legal { + require.NoError(t, QemuDiskSerial(e).Validate()) + } + for _, e := range testRunes.illegal { + require.Error(t, QemuDiskSerial(e).Validate()) + } +} diff --git a/test/data/test_data_qemu/type_QemuDiskSerial.go b/test/data/test_data_qemu/type_QemuDiskSerial.go new file mode 100644 index 00000000..2bc96254 --- /dev/null +++ b/test/data/test_data_qemu/type_QemuDiskSerial.go @@ -0,0 +1,80 @@ +package test_data_qemu + +import "strings" + +// 60 valid charaters +func QemuDiskSerial_Max_Legal() string { + return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678" +} + +// 61 valid charaters +func QemuDiskSerial_Max_Illegal() string { + return QemuDiskSerial_Max_Legal() + "A" +} + +// Has all the legal runes for the QemuDiskSerial type. +func QemuDiskSerial_Legal() []string { + legalRunes := strings.Split("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_", "") + legalStrings := []string{ + "85__2-_2-p-d-___3GEEJ_6__--ccli_-_8--e-RJ3-_A_f_S_Z8-7Gga__5", + "___7_7-G-_rsMa_6---___a-TmE-H-AD_oV_K-0_9W_-y_4_k-_FU__fev-q", + "mU_a-8-_-3U--_D--o01_-T4E__4fsV-nX4kk_Nb-S_wYR7TktI-_vn1mcfR", + "5_GX4DevvIZ-_2-_u-_4_dKK19_P-K-kLpj-Hzw-b_12L20UU3--__Y_5_O-", + "h-m_B_J-mH_o3-r-JmE4-WqZ_tly--3aT-w_wznK_Q-0Hkk7W6b-Z____1IQ", + "-D-aS-dJSG_-s9_6_BWnt9z_6m_67oW__d4V8m-wb_6_8-_A--__-e--1X1-", + "0gLe0_P-r53-BfDk--1__23_-Zo0_V---f-__7_b52u6f72", + "dg-5d_Y1_v-7g-__I7__79_-j8-_-_", + "-7_G_-I-__a-w_-5GK-_9BMr-I_-_-f_7_-F-----6-FE-q7__0NJY-vL-e-", + "Xlgd__41_0E-S---1--_--_X1p8-_5YHt_1hO__2Op_73-5r-4", + "_0-Nn6__-u_07_A-1dqt-EG-_4-w90--A-ur_-3_", + "8_-xO-lN1_O_Q-4__-_7d-k-__s-p-_uQ2S_Ft_OR_-Ct_--Pb__U_U_g2t-", + "-q_-6h4--bbIl_A-xc_zl-v6Y-b-6__EG5_G__6_-q__pa5lAvq_F-Fhl-d3", + "53X-j50-ix--Iv_i", + "0_-7O6--51_4____-_-Zm4E__s-4_c_xN_Ik3_g-_t__-__C_---e-_--K_m", + "--_8__BvpmE6t-r_Ho_x-VZ_0___g__ui1v28ne--_-_k74_E3x_T_s--__B", + "__--9--c__7__9r-s-__yDTi-JSk-M_fH_-hGO9", + "_J-q_f_o_--l-MSe--9I_L_-lAs_-G-0--l-9_-6", + "--1tcB8J210JwYy22--c-_oXhHQ-Zyy--A1-dZ9394ieAaZrvC_U--KS2-r7", + "442_h_M-2-4G3K-_bN", + "b_NDX_3e6-k9_-HWZL_A5T_L-_-je66", + "__-_DfxD-9_l2_-n__Tn_-n_6aE_Bj_8chVS5p7Z_2812---h_4-_hsh-wAb", + "T08_-bRb-_zRKF1MPN6j7vyp0Pt_Q_x44__Y6_7_-XX-_-VqsRi_-0-s2-", + "Z___e_UT--G_9-9_E--__--ZT---1Leg__7-92_KErs-S-_t-K21_-OK_6Nx", + "-Plro-431-_", + "b__-_2_-u-K8--3-1-1", + "3_T40b6-Q__-Lz_3_4qN_", + "-p-_-T__MK-4D46-r7F_", + "Cn_f1-3J5T4x-g_-yoX3__0K_lV_W-glt-_eC_c_A_3l-m-_d_5_-5-iC___", + "-v7Y--G8T6-5k64-2-4kz-zqn70C__", + "7-7S70i_e-_a_8E---1X-_cW_--4z_8_4rm--6KCp_5_os8-_-4pvE_UC-_X", + "-mjp2--E8z-K-__2t", + "2b6-_-4jx6nM-Mm_-Sf_Wz-cv_---keD_6-_x_O0_D__d_Q-v04-h__x__6g", + "_-t0_Et_1_P0C5xSp_-3G2u68q4--YU7zQ_-_4-Y3OwT-8k-2F__Zf7_K78k", + "_R_-9-_5-K2R5zF_UJWfH_--_YQe8P4_nQ--JQ-Xu--lH-e_V0-c1_--e", + "J_y_-1X-_N84-Y-Ik6h-Y5Hz-_S__0-_-Y_V_-305-9i38TP_T--4y7Gb0g-", + "0Yl7_-Sn-_H__D_--_-_y-h-j1_-7mDVS9__R8Ty_-mwOJ-h__VmAy__q-_N", + "Yk-3Pt9VJqW-uu45w_f__a-TH_M_vkWq-O6__tk-P4-2-_CP-_7_owV_GyLZ", + "-3-M2362g3_9-___X404__0-E01TFHW3HV-1n_E_Ev_-_-E_-S----_F_k--", + "-0-5l1u_D_-Hyk_-_-s-3663_JE2-k", + "_-ML", + "75BHJ-tj-2Q-m-s4-f-y5-9L_-_dPC6A-_3y-3-Rp_-0V-3_I-6--_4THR2-", + "V__HM_guP-__ltfk___Et9V_v7U-83-TK15Xun", + "ax2_-7u_-GqG7d1BAe_4-dW3S0-1Vbj--_r_-63Hvn36P0---6N--e-_89_b", + "__-h_L-_3_Q__3czJ1_J_", + "-_-_-_9xGr-8207h9-4WerP5_-v0G_G9_-K9T8-gvQg-d__g____xf-F_---", + "M_6K2LVn--73f__-__A5V_t-l-_--5s92_u_f_n-R2Iy580M7J2vPe76GIt-", + "-f5oc-MG_GhR-8oxJ_---G____5--2-5___b-cTmfyO18-6Vip__-c_i5uV_", + "7-_17B__b113_9-cZ8S-", + "VvF1-MX6--Pj-M_-F_tU_6T-G___3U3-F4-5L__x-9uzgz_-_y4_-_-J--kE", + "", + QemuDiskSerial_Max_Legal(), + } + return append(legalRunes, legalStrings[:]...) +} + +// Has all the legal runes for the QemuDiskSerial type. +func QemuDiskSerial_Illegal() []string { + illegalRunes := strings.Split("`~!@#$%^&*()=+{}[]|\\;:'\"<,>.?/", "") + illegalSrings := []string{QemuDiskSerial_Max_Illegal()} + return append(illegalRunes, illegalSrings[:]...) +} From 4454dca2ba811e2fcadcea5a1017ee6a9d3b5a34 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 16:04:50 +0000 Subject: [PATCH 008/120] refactor: Add enum and validate allowed values --- proxmox/config_qemu_disk.go | 17 ++++++++++++++++- proxmox/config_qemu_disk_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 24b88cbd..f484aaa1 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -332,9 +332,24 @@ type QemuDisk_Bandwidth_Iops struct { Burst uint } -// TODO add enum type QemuDiskCache string +const ( + QemuDiskCache_None QemuDiskCache = "none" + QemuDiskCache_WriteThrough QemuDiskCache = "writethrough" + QemuDiskCache_WriteBack QemuDiskCache = "writeback" + QemuDiskCache_Unsafe QemuDiskCache = "unsafe" + QemuDiskCache_DirectSync QemuDiskCache = "directsync" +) + +func (cache QemuDiskCache) Validate() error { + switch cache { + case QemuDiskCache_None, QemuDiskCache_WriteThrough, QemuDiskCache_WriteBack, QemuDiskCache_Unsafe, QemuDiskCache_DirectSync: + return nil + } + return fmt.Errorf("cache can only be one of the following values: %s,%s,%s,%s,%s,", QemuDiskCache_None, QemuDiskCache_WriteThrough, QemuDiskCache_WriteBack, QemuDiskCache_Unsafe, QemuDiskCache_DirectSync) +} + // TODO add enum type QemuDiskFormat string diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 829b1b5c..e6fc3c03 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -7,6 +7,31 @@ import ( "github.com/stretchr/testify/require" ) +func Test_QemuDiskCache_Validate(t *testing.T) { + testData := []struct { + input QemuDiskCache + err bool + }{ + // Valid + {input: QemuDiskCache_None}, + {input: QemuDiskCache_WriteThrough}, + {input: QemuDiskCache_WriteBack}, + {input: QemuDiskCache_Unsafe}, + {input: QemuDiskCache_DirectSync}, + // Invalid + {input: "bla", err: true}, + {input: "invalid value", err: true}, + {input: "!@#$", err: true}, + } + for _, e := range testData { + if e.err { + require.Error(t, e.input.Validate()) + } else { + require.NoError(t, e.input.Validate()) + } + } +} + func Test_QemuDiskSerial_Validate(t *testing.T) { testRunes := struct { legal []string From 327c98ae91318d68f7a5ae750d6bca0814c9d564 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 16:51:21 +0000 Subject: [PATCH 009/120] fix: typo --- proxmox/config_qemu_disk.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index f484aaa1..3c093f16 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -347,7 +347,7 @@ func (cache QemuDiskCache) Validate() error { case QemuDiskCache_None, QemuDiskCache_WriteThrough, QemuDiskCache_WriteBack, QemuDiskCache_Unsafe, QemuDiskCache_DirectSync: return nil } - return fmt.Errorf("cache can only be one of the following values: %s,%s,%s,%s,%s,", QemuDiskCache_None, QemuDiskCache_WriteThrough, QemuDiskCache_WriteBack, QemuDiskCache_Unsafe, QemuDiskCache_DirectSync) + return fmt.Errorf("cache can only be one of the following values: %s,%s,%s,%s,%s", QemuDiskCache_None, QemuDiskCache_WriteThrough, QemuDiskCache_WriteBack, QemuDiskCache_Unsafe, QemuDiskCache_DirectSync) } // TODO add enum From aec9e6d928f9435fad4e5efbc7d26d2ad0160481 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 16:58:34 +0000 Subject: [PATCH 010/120] feat: Add enum for QemuDiskFormat and validate allowed values --- proxmox/config_qemu_disk.go | 19 ++++++++++++++++++- proxmox/config_qemu_disk_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 3c093f16..83b45e1b 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -350,9 +350,26 @@ func (cache QemuDiskCache) Validate() error { return fmt.Errorf("cache can only be one of the following values: %s,%s,%s,%s,%s", QemuDiskCache_None, QemuDiskCache_WriteThrough, QemuDiskCache_WriteBack, QemuDiskCache_Unsafe, QemuDiskCache_DirectSync) } -// TODO add enum type QemuDiskFormat string +const ( + QemuDiskFormat_Cow QemuDiskFormat = "cow" + QemuDiskFormat_Cloop QemuDiskFormat = "cloop" + QemuDiskFormat_Qcow QemuDiskFormat = "qcow" + QemuDiskFormat_Qcow2 QemuDiskFormat = "qcow2" + QemuDiskFormat_Qed QemuDiskFormat = "qed" + QemuDiskFormat_Vmdk QemuDiskFormat = "vmdk" + QemuDiskFormat_Raw QemuDiskFormat = "raw" +) + +func (format QemuDiskFormat) Validate() error { + switch format { + case QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw: + return nil + } + return fmt.Errorf("cache can only be one of the following values: %s,%s,%s,%s,%s,%s,%s", QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw) +} + type QemuDiskSerial string // QemuDiskSerial may only contain the following characters: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_ diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index e6fc3c03..b10e6811 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -32,6 +32,33 @@ func Test_QemuDiskCache_Validate(t *testing.T) { } } +func Test_QemuDiskFormat_Validate(t *testing.T) { + testData := []struct { + input QemuDiskFormat + err bool + }{ + // Valid + {input: QemuDiskFormat_Cow}, + {input: QemuDiskFormat_Cloop}, + {input: QemuDiskFormat_Qcow}, + {input: QemuDiskFormat_Qcow2}, + {input: QemuDiskFormat_Qed}, + {input: QemuDiskFormat_Vmdk}, + {input: QemuDiskFormat_Raw}, + // Invalid + {input: "bla", err: true}, + {input: "invalid value", err: true}, + {input: "!@#$", err: true}, + } + for _, e := range testData { + if e.err { + require.Error(t, e.input.Validate()) + } else { + require.NoError(t, e.input.Validate()) + } + } +} + func Test_QemuDiskSerial_Validate(t *testing.T) { testRunes := struct { legal []string From 01714f439f30262febe1d76d4fb6087be7776801 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 17:05:49 +0000 Subject: [PATCH 011/120] feat: Add enum for QemuDiskAsyncIO and validate allowed values --- proxmox/config_qemu_disk.go | 15 ++++++++++++++- proxmox/config_qemu_disk_test.go | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 83b45e1b..a6f499c4 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -312,9 +312,22 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { return &disk } -// TODO add enum type QemuDiskAsyncIO string +const ( + QemuDiskAsyncIO_Native QemuDiskAsyncIO = "native" + QemuDiskAsyncIO_Threads QemuDiskAsyncIO = "threads" + QemuDiskAsyncIO_IOuring QemuDiskAsyncIO = "io_uring" +) + +func (asyncIO QemuDiskAsyncIO) Validate() error { + switch asyncIO { + case QemuDiskAsyncIO_Native, QemuDiskAsyncIO_Threads, QemuDiskAsyncIO_IOuring: + return nil + } + return fmt.Errorf("asyncio can only be one of the following values: %s,%s,%s", QemuDiskAsyncIO_Native, QemuDiskAsyncIO_Threads, QemuDiskAsyncIO_IOuring) +} + type QemuDiskBandwidth struct { ReadLimit_Data QemuDisk_Bandwidth_Data WriteLimit_Data QemuDisk_Bandwidth_Data diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index b10e6811..25274d88 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -7,6 +7,29 @@ import ( "github.com/stretchr/testify/require" ) +func Test_QemuDiskAsyncIO_Validate(t *testing.T) { + testData := []struct { + input QemuDiskAsyncIO + err bool + }{ + // Valid + {input: QemuDiskAsyncIO_Native}, + {input: QemuDiskAsyncIO_Threads}, + {input: QemuDiskAsyncIO_IOuring}, + // Invalid + {input: "bla", err: true}, + {input: "invalid value", err: true}, + {input: "!@#$", err: true}, + } + for _, e := range testData { + if e.err { + require.Error(t, e.input.Validate()) + } else { + require.NoError(t, e.input.Validate()) + } + } +} + func Test_QemuDiskCache_Validate(t *testing.T) { testData := []struct { input QemuDiskCache From 79d897d2ad090c0eda0f4c337f76d0020de379a1 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 17:06:35 +0000 Subject: [PATCH 012/120] fix: change setting name in error message --- proxmox/config_qemu_disk.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index a6f499c4..4ee0e749 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -380,7 +380,7 @@ func (format QemuDiskFormat) Validate() error { case QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw: return nil } - return fmt.Errorf("cache can only be one of the following values: %s,%s,%s,%s,%s,%s,%s", QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw) + return fmt.Errorf("format can only be one of the following values: %s,%s,%s,%s,%s,%s,%s", QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw) } type QemuDiskSerial string From 02819355e94b6c868d17ef5216b11eb9cdb36a26 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 17:31:16 +0000 Subject: [PATCH 013/120] refactor: Add Json keys --- proxmox/config_qemu_disk_sata.go | 12 +++--- proxmox/config_qemu_disk_scsi.go | 62 +++++++++++++++--------------- proxmox/config_qemu_disk_virtio.go | 32 +++++++-------- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 12134229..4033b00d 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -30,12 +30,12 @@ func (disk QemuSataDisk) mapToApiValues(create bool) string { } type QemuSataDisks struct { - Disk_0 *QemuSataStorage - Disk_1 *QemuSataStorage - Disk_2 *QemuSataStorage - Disk_3 *QemuSataStorage - Disk_4 *QemuSataStorage - Disk_5 *QemuSataStorage + Disk_0 *QemuSataStorage `json:"0,omitempty"` + Disk_1 *QemuSataStorage `json:"1,omitempty"` + Disk_2 *QemuSataStorage `json:"2,omitempty"` + Disk_3 *QemuSataStorage `json:"3,omitempty"` + Disk_4 *QemuSataStorage `json:"4,omitempty"` + Disk_5 *QemuSataStorage `json:"5,omitempty"` } func (disks QemuSataDisks) mapToApiValues(create bool, params map[string]interface{}) { diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 281558ce..b5db0189 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -34,37 +34,37 @@ func (disk QemuScsiDisk) mapToApiValues(create bool) string { } type QemuScsiDisks struct { - Disk_0 *QemuScsiStorage - Disk_1 *QemuScsiStorage - Disk_2 *QemuScsiStorage - Disk_3 *QemuScsiStorage - Disk_4 *QemuScsiStorage - Disk_5 *QemuScsiStorage - Disk_6 *QemuScsiStorage - Disk_7 *QemuScsiStorage - Disk_8 *QemuScsiStorage - Disk_9 *QemuScsiStorage - Disk_10 *QemuScsiStorage - Disk_11 *QemuScsiStorage - Disk_12 *QemuScsiStorage - Disk_13 *QemuScsiStorage - Disk_14 *QemuScsiStorage - Disk_15 *QemuScsiStorage - Disk_16 *QemuScsiStorage - Disk_17 *QemuScsiStorage - Disk_18 *QemuScsiStorage - Disk_19 *QemuScsiStorage - Disk_20 *QemuScsiStorage - Disk_21 *QemuScsiStorage - Disk_22 *QemuScsiStorage - Disk_23 *QemuScsiStorage - Disk_24 *QemuScsiStorage - Disk_25 *QemuScsiStorage - Disk_26 *QemuScsiStorage - Disk_27 *QemuScsiStorage - Disk_28 *QemuScsiStorage - Disk_29 *QemuScsiStorage - Disk_30 *QemuScsiStorage + Disk_0 *QemuScsiStorage `json:"0,omitempty"` + Disk_1 *QemuScsiStorage `json:"1,omitempty"` + Disk_2 *QemuScsiStorage `json:"2,omitempty"` + Disk_3 *QemuScsiStorage `json:"3,omitempty"` + Disk_4 *QemuScsiStorage `json:"4,omitempty"` + Disk_5 *QemuScsiStorage `json:"5,omitempty"` + Disk_6 *QemuScsiStorage `json:"6,omitempty"` + Disk_7 *QemuScsiStorage `json:"7,omitempty"` + Disk_8 *QemuScsiStorage `json:"8,omitempty"` + Disk_9 *QemuScsiStorage `json:"9,omitempty"` + Disk_10 *QemuScsiStorage `json:"10,omitempty"` + Disk_11 *QemuScsiStorage `json:"11,omitempty"` + Disk_12 *QemuScsiStorage `json:"12,omitempty"` + Disk_13 *QemuScsiStorage `json:"13,omitempty"` + Disk_14 *QemuScsiStorage `json:"14,omitempty"` + Disk_15 *QemuScsiStorage `json:"15,omitempty"` + Disk_16 *QemuScsiStorage `json:"16,omitempty"` + Disk_17 *QemuScsiStorage `json:"17,omitempty"` + Disk_18 *QemuScsiStorage `json:"18,omitempty"` + Disk_19 *QemuScsiStorage `json:"19,omitempty"` + Disk_20 *QemuScsiStorage `json:"20,omitempty"` + Disk_21 *QemuScsiStorage `json:"21,omitempty"` + Disk_22 *QemuScsiStorage `json:"22,omitempty"` + Disk_23 *QemuScsiStorage `json:"23,omitempty"` + Disk_24 *QemuScsiStorage `json:"24,omitempty"` + Disk_25 *QemuScsiStorage `json:"25,omitempty"` + Disk_26 *QemuScsiStorage `json:"26,omitempty"` + Disk_27 *QemuScsiStorage `json:"27,omitempty"` + Disk_28 *QemuScsiStorage `json:"28,omitempty"` + Disk_29 *QemuScsiStorage `json:"29,omitempty"` + Disk_30 *QemuScsiStorage `json:"30,omitempty"` } func (disks QemuScsiDisks) mapToApiValues(create bool, params map[string]interface{}) { diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 3ea6ed1b..3e60a558 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -31,22 +31,22 @@ func (disk QemuVirtIODisk) mapToApiValues(create bool) string { } type QemuVirtIODisks struct { - Disk_0 *QemuVirtIOStorage - Disk_1 *QemuVirtIOStorage - Disk_2 *QemuVirtIOStorage - Disk_3 *QemuVirtIOStorage - Disk_4 *QemuVirtIOStorage - Disk_5 *QemuVirtIOStorage - Disk_6 *QemuVirtIOStorage - Disk_7 *QemuVirtIOStorage - Disk_8 *QemuVirtIOStorage - Disk_9 *QemuVirtIOStorage - Disk_10 *QemuVirtIOStorage - Disk_11 *QemuVirtIOStorage - Disk_12 *QemuVirtIOStorage - Disk_13 *QemuVirtIOStorage - Disk_14 *QemuVirtIOStorage - Disk_15 *QemuVirtIOStorage + Disk_0 *QemuVirtIOStorage `json:"0,omitempty"` + Disk_1 *QemuVirtIOStorage `json:"1,omitempty"` + Disk_2 *QemuVirtIOStorage `json:"2,omitempty"` + Disk_3 *QemuVirtIOStorage `json:"3,omitempty"` + Disk_4 *QemuVirtIOStorage `json:"4,omitempty"` + Disk_5 *QemuVirtIOStorage `json:"5,omitempty"` + Disk_6 *QemuVirtIOStorage `json:"6,omitempty"` + Disk_7 *QemuVirtIOStorage `json:"7,omitempty"` + Disk_8 *QemuVirtIOStorage `json:"8,omitempty"` + Disk_9 *QemuVirtIOStorage `json:"9,omitempty"` + Disk_10 *QemuVirtIOStorage `json:"10,omitempty"` + Disk_11 *QemuVirtIOStorage `json:"11,omitempty"` + Disk_12 *QemuVirtIOStorage `json:"12,omitempty"` + Disk_13 *QemuVirtIOStorage `json:"13,omitempty"` + Disk_14 *QemuVirtIOStorage `json:"14,omitempty"` + Disk_15 *QemuVirtIOStorage `json:"15,omitempty"` } func (disks QemuVirtIODisks) mapToApiValues(create bool, params map[string]interface{}) { From aab856e3646b94359a26d438e480a4460ab6b6fe Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Feb 2023 17:34:34 +0000 Subject: [PATCH 014/120] feat: Map QemuCdRom to API values --- proxmox/config_qemu_disk.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 4ee0e749..7dafb33a 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -10,21 +10,27 @@ import ( ) type IsoFile struct { - Storage string - File string + Storage string `json:"storage"` + File string `json:"file"` // Size can only be retrieved, setting it has no effect - Size string + Size string `json:"size"` } type QemuCdRom struct { - Iso *IsoFile + Iso *IsoFile `json:"iso,omitempty"` // Passthrough and File are mutually exclusive - Passthrough bool + Passthrough bool `json:"passthrough,omitempty"` } -// TODO write function +// TODO write test func (cdRom QemuCdRom) mapToApiValues() string { - return "" + if cdRom.Passthrough { + return "cdrom,media=cdrom" + } + if cdRom.Iso != nil { + return cdRom.Iso.Storage + ":iso/" + cdRom.Iso.File + ",media=cdrom" + } + return "none,media=cdrom" } func (QemuCdRom) mapToStruct(settings qemuCdRom) *QemuCdRom { From 13226066fa3d31a7d8184e917ffef775cd107819 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 12:55:54 +0000 Subject: [PATCH 015/120] feat: create logic for creating, updating, migrating and deleting disks --- proxmox/config_qemu_disk.go | 51 ++++++-- proxmox/config_qemu_disk_ide.go | 96 ++++++++++++-- proxmox/config_qemu_disk_sata.go | 104 ++++++++++++--- proxmox/config_qemu_disk_scsi.go | 204 ++++++++++++++++------------- proxmox/config_qemu_disk_virtio.go | 144 +++++++++++++------- 5 files changed, 413 insertions(+), 186 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 7dafb33a..3079ad02 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -132,8 +132,9 @@ type qemuDisk struct { // TODO custom type File string // Only set for Passthrough. Format QemuDiskFormat + ID uint // Only set for Disk IOThread bool // Only set for scsi,virtio - Number uint // Only set for Disk + Number uint ReadOnly bool // Only set for scsi,virtio Replicate bool Serial QemuDiskSerial @@ -229,11 +230,11 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { diskAndNumberAndFormat := strings.Split(settings[0][0], ":") disk.Storage = diskAndNumberAndFormat[0] if len(diskAndNumberAndFormat) == 2 { - numberAndFormat := strings.Split(diskAndNumberAndFormat[1], "-") - if len(numberAndFormat) == 2 { - tmp := strings.Split(numberAndFormat[1], ".") - tmpNumber, _ := strconv.Atoi(tmp[0]) - disk.Number = uint(tmpNumber) + idAndFormat := strings.Split(diskAndNumberAndFormat[1], "-") + if len(idAndFormat) == 2 { + tmp := strings.Split(idAndFormat[1], ".") + tmpId, _ := strconv.Atoi(tmp[0]) + disk.ID = uint(tmpId) if len(tmp) == 2 { disk.Format = QemuDiskFormat(tmp[1]) } @@ -404,6 +405,11 @@ func (serial QemuDiskSerial) Validate() error { return nil } +type qemuDiskShort struct { + Storage string + Id string +} + type qemuDiskType int const ( @@ -420,18 +426,35 @@ type QemuStorages struct { VirtIO *QemuVirtIODisks `json:"virtio,omitempty"` } -func (storages QemuStorages) mapToApiValues(create bool, params map[string]interface{}) { +func (storages QemuStorages) markDiskChanges(currentStorages QemuStorages, params map[string]interface{}) *qemuUpdateChanges { + changes := &qemuUpdateChanges{} + if currentStorages.Ide != nil { + storages.Ide.mapToApiValues(currentStorages.Ide, params, changes) + } + if currentStorages.Sata != nil { + storages.Sata.mapToApiValues(currentStorages.Sata, params, changes) + } + if currentStorages.Scsi != nil { + storages.Scsi.mapToApiValues(currentStorages.Scsi, params, changes) + } + if currentStorages.VirtIO != nil { + storages.VirtIO.mapToApiValues(currentStorages.VirtIO, params, changes) + } + return changes +} + +func (storages QemuStorages) mapToApiValues(params map[string]interface{}) { if storages.Ide != nil { - storages.Ide.mapToApiValues(create, params) + storages.Ide.mapToApiValues(nil, params, nil) } if storages.Sata != nil { - storages.Sata.mapToApiValues(create, params) + storages.Sata.mapToApiValues(nil, params, nil) } if storages.Scsi != nil { - storages.Scsi.mapToApiValues(create, params) + storages.Scsi.mapToApiValues(nil, params, nil) } if storages.VirtIO != nil { - storages.VirtIO.mapToApiValues(create, params) + storages.VirtIO.mapToApiValues(nil, params, nil) } } @@ -447,3 +470,9 @@ func (QemuStorages) mapToStruct(params map[string]interface{}) *QemuStorages { } return nil } + +type qemuUpdateChanges struct { + Move []qemuDiskShort + Delete []string + MigrationImpossible bool +} diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index f02bb471..d49d55ac 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -13,6 +13,7 @@ type QemuIdeDisk struct { Storage string `json:"storage,omitempty"` } +// TODO write test func (disk QemuIdeDisk) mapToApiValues(create bool) string { return qemuDisk{ AsyncIO: disk.AsyncIO, @@ -36,21 +37,19 @@ type QemuIdeDisks struct { Disk_3 *QemuIdeStorage `json:"3,omitempty"` } -func (disks QemuIdeDisks) mapToApiValues(create bool, params map[string]interface{}) { - if disks.Disk_0 != nil { - params["ide0"] = disks.Disk_0.mapToApiValues(create) - } - if disks.Disk_1 != nil { - params["ide1"] = disks.Disk_0.mapToApiValues(create) - } - if disks.Disk_2 != nil { - params["ide2"] = disks.Disk_0.mapToApiValues(create) - } - if disks.Disk_3 != nil { - params["ide3"] = disks.Disk_0.mapToApiValues(create) - } +// TODO write test +func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, params map[string]interface{}, changes *qemuUpdateChanges) { + tmpCurrentDisks := QemuIdeDisks{} + if currentDisks != nil { + tmpCurrentDisks = *currentDisks + } + disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, "ide0", params, changes) + disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, "ide1", params, changes) + disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, "ide2", params, changes) + disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, "ide3", params, changes) } +// TODO write test func (QemuIdeDisks) mapToStruct(params map[string]interface{}) *QemuIdeDisks { disks := QemuIdeDisks{} var structPopulated bool @@ -90,6 +89,7 @@ type QemuIdePassthrough struct { } // TODO write function +// TODO write test func (passthrough QemuIdePassthrough) mapToApiValues() string { return "" } @@ -101,6 +101,7 @@ type QemuIdeStorage struct { Passthrough *QemuIdePassthrough `json:"passthrough,omitempty"` } +// TODO write test func (storage QemuIdeStorage) mapToApiValues(create bool) string { if storage.Disk != nil { return storage.Disk.mapToApiValues(create) @@ -117,6 +118,75 @@ func (storage QemuIdeStorage) mapToApiValues(create bool) string { return "" } +// TODO write test +func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { + if storage == nil { + if currentStorage != nil { + changes.Delete = append(changes.Delete, id) + } + return + } + // CDROM + if storage.CdRom != nil { + // Create or Update + params[id] = storage.CdRom.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.CdRom != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // CloudInit + if storage.CloudInit != nil { + // Create or Update + params[id] = storage.CloudInit.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.CloudInit != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // Disk + if storage.Disk != nil { + if currentStorage == nil || currentStorage.Disk == nil { + // Create + params[id] = storage.Disk.mapToApiValues(true) + } else { + if storage.Disk.Size >= currentStorage.Disk.Size { + // Update + if storage.Disk.Storage != currentStorage.Disk.Storage { + changes.Move = append(changes.Move, qemuDiskShort{ + Id: id, + Storage: storage.Disk.Storage, + }) + } + params[id] = storage.Disk.mapToApiValues(false) + } else { + // Delete and Create + changes.Delete = append(changes.Delete, id) + params[id] = storage.Disk.mapToApiValues(true) + } + } + return + } else if currentStorage != nil && currentStorage.Disk != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // Passthrough + if storage.Passthrough != nil { + // Create or Update + changes.MigrationImpossible = true + params[id] = storage.Passthrough.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.Passthrough != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } +} + +// TODO write test func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 4033b00d..f39fd8b8 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -13,6 +13,7 @@ type QemuSataDisk struct { Storage string `json:"storage,omitempty"` } +// TODO write test func (disk QemuSataDisk) mapToApiValues(create bool) string { return qemuDisk{ AsyncIO: disk.AsyncIO, @@ -38,27 +39,21 @@ type QemuSataDisks struct { Disk_5 *QemuSataStorage `json:"5,omitempty"` } -func (disks QemuSataDisks) mapToApiValues(create bool, params map[string]interface{}) { - if disks.Disk_0 != nil { - params["sata0"] = disks.Disk_0.mapToApiValues(create) - } - if disks.Disk_1 != nil { - params["sata1"] = disks.Disk_1.mapToApiValues(create) - } - if disks.Disk_2 != nil { - params["sata2"] = disks.Disk_2.mapToApiValues(create) - } - if disks.Disk_3 != nil { - params["sata3"] = disks.Disk_3.mapToApiValues(create) - } - if disks.Disk_4 != nil { - params["sata4"] = disks.Disk_4.mapToApiValues(create) - } - if disks.Disk_5 != nil { - params["sata5"] = disks.Disk_5.mapToApiValues(create) - } +// TODO write test +func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, params map[string]interface{}, changes *qemuUpdateChanges) { + tmpCurrentDisks := QemuSataDisks{} + if currentDisks != nil { + tmpCurrentDisks = *currentDisks + } + disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, "sata0", params, changes) + disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, "sata1", params, changes) + disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, "sata2", params, changes) + disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, "sata3", params, changes) + disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, "sata4", params, changes) + disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, "sata5", params, changes) } +// TODO write test func (QemuSataDisks) mapToStruct(params map[string]interface{}) *QemuSataDisks { disks := QemuSataDisks{} var structPopulated bool @@ -106,6 +101,7 @@ type QemuSataPassthrough struct { } // TODO write function +// TODO write test func (passthrough QemuSataPassthrough) mapToApiValues() string { return "" } @@ -117,6 +113,7 @@ type QemuSataStorage struct { Passthrough *QemuSataPassthrough } +// TODO write test func (storage QemuSataStorage) mapToApiValues(create bool) string { if storage.Disk != nil { return storage.Disk.mapToApiValues(create) @@ -133,6 +130,75 @@ func (storage QemuSataStorage) mapToApiValues(create bool) string { return "" } +// TODO write test +func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { + if storage == nil { + if currentStorage != nil { + changes.Delete = append(changes.Delete, id) + } + return + } + // CDROM + if storage.CdRom != nil { + // Create or Update + params[id] = storage.CdRom.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.CdRom != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // CloudInit + if storage.CloudInit != nil { + // Create or Update + params[id] = storage.CloudInit.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.CloudInit != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // Disk + if storage.Disk != nil { + if currentStorage == nil || currentStorage.Disk == nil { + // Create + params[id] = storage.Disk.mapToApiValues(true) + } else { + if storage.Disk.Size >= currentStorage.Disk.Size { + // Update + if storage.Disk.Storage != currentStorage.Disk.Storage { + changes.Move = append(changes.Move, qemuDiskShort{ + Id: id, + Storage: storage.Disk.Storage, + }) + } + params[id] = storage.Disk.mapToApiValues(false) + } else { + // Delete and Create + changes.Delete = append(changes.Delete, id) + params[id] = storage.Disk.mapToApiValues(true) + } + } + return + } else if currentStorage != nil && currentStorage.Disk != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // Passthrough + if storage.Passthrough != nil { + // Create or Update + changes.MigrationImpossible = true + params[id] = storage.Passthrough.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.Passthrough != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } +} + +// TODO write test func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index b5db0189..b91f2eb3 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -15,6 +15,7 @@ type QemuScsiDisk struct { Storage string `json:"storage,omitempty"` } +// TODO write test func (disk QemuScsiDisk) mapToApiValues(create bool) string { return qemuDisk{ AsyncIO: disk.AsyncIO, @@ -67,102 +68,46 @@ type QemuScsiDisks struct { Disk_30 *QemuScsiStorage `json:"30,omitempty"` } -func (disks QemuScsiDisks) mapToApiValues(create bool, params map[string]interface{}) { - if disks.Disk_0 != nil { - params["scsi0"] = disks.Disk_0.mapToApiValues(create) - } - if disks.Disk_1 != nil { - params["scsi1"] = disks.Disk_1.mapToApiValues(create) - } - if disks.Disk_2 != nil { - params["scsi2"] = disks.Disk_2.mapToApiValues(create) - } - if disks.Disk_3 != nil { - params["scsi3"] = disks.Disk_3.mapToApiValues(create) - } - if disks.Disk_4 != nil { - params["scsi4"] = disks.Disk_4.mapToApiValues(create) - } - if disks.Disk_5 != nil { - params["scsi5"] = disks.Disk_5.mapToApiValues(create) - } - if disks.Disk_6 != nil { - params["scsi6"] = disks.Disk_6.mapToApiValues(create) - } - if disks.Disk_7 != nil { - params["scsi7"] = disks.Disk_7.mapToApiValues(create) - } - if disks.Disk_8 != nil { - params["scsi8"] = disks.Disk_8.mapToApiValues(create) - } - if disks.Disk_9 != nil { - params["scsi9"] = disks.Disk_9.mapToApiValues(create) - } - if disks.Disk_10 != nil { - params["scsi10"] = disks.Disk_10.mapToApiValues(create) - } - if disks.Disk_11 != nil { - params["scsi11"] = disks.Disk_11.mapToApiValues(create) - } - if disks.Disk_12 != nil { - params["scsi12"] = disks.Disk_12.mapToApiValues(create) - } - if disks.Disk_13 != nil { - params["scsi13"] = disks.Disk_13.mapToApiValues(create) - } - if disks.Disk_14 != nil { - params["scsi14"] = disks.Disk_14.mapToApiValues(create) - } - if disks.Disk_15 != nil { - params["scsi15"] = disks.Disk_15.mapToApiValues(create) - } - if disks.Disk_16 != nil { - params["scsi16"] = disks.Disk_16.mapToApiValues(create) - } - if disks.Disk_17 != nil { - params["scsi17"] = disks.Disk_17.mapToApiValues(create) - } - if disks.Disk_18 != nil { - params["scsi18"] = disks.Disk_18.mapToApiValues(create) - } - if disks.Disk_19 != nil { - params["scsi19"] = disks.Disk_19.mapToApiValues(create) - } - if disks.Disk_20 != nil { - params["scsi20"] = disks.Disk_20.mapToApiValues(create) - } - if disks.Disk_21 != nil { - params["scsi21"] = disks.Disk_21.mapToApiValues(create) - } - if disks.Disk_22 != nil { - params["scsi22"] = disks.Disk_22.mapToApiValues(create) - } - if disks.Disk_23 != nil { - params["scsi23"] = disks.Disk_23.mapToApiValues(create) - } - if disks.Disk_24 != nil { - params["scsi24"] = disks.Disk_24.mapToApiValues(create) - } - if disks.Disk_25 != nil { - params["scsi25"] = disks.Disk_25.mapToApiValues(create) - } - if disks.Disk_26 != nil { - params["scsi26"] = disks.Disk_26.mapToApiValues(create) - } - if disks.Disk_27 != nil { - params["scsi27"] = disks.Disk_27.mapToApiValues(create) - } - if disks.Disk_28 != nil { - params["scsi28"] = disks.Disk_28.mapToApiValues(create) - } - if disks.Disk_29 != nil { - params["scsi29"] = disks.Disk_29.mapToApiValues(create) - } - if disks.Disk_30 != nil { - params["scsi30"] = disks.Disk_30.mapToApiValues(create) - } +// TODO write test +func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, params map[string]interface{}, changes *qemuUpdateChanges) { + tmpCurrentDisks := QemuScsiDisks{} + if currentDisks != nil { + tmpCurrentDisks = *currentDisks + } + disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, "scsi0", params, changes) + disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, "scsi1", params, changes) + disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, "scsi2", params, changes) + disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, "scsi3", params, changes) + disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, "scsi4", params, changes) + disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, "scsi5", params, changes) + disks.Disk_6.markDiskChanges(tmpCurrentDisks.Disk_6, "scsi6", params, changes) + disks.Disk_7.markDiskChanges(tmpCurrentDisks.Disk_7, "scsi7", params, changes) + disks.Disk_8.markDiskChanges(tmpCurrentDisks.Disk_8, "scsi8", params, changes) + disks.Disk_9.markDiskChanges(tmpCurrentDisks.Disk_9, "scsi9", params, changes) + disks.Disk_10.markDiskChanges(tmpCurrentDisks.Disk_10, "scsi10", params, changes) + disks.Disk_11.markDiskChanges(tmpCurrentDisks.Disk_11, "scsi11", params, changes) + disks.Disk_12.markDiskChanges(tmpCurrentDisks.Disk_12, "scsi12", params, changes) + disks.Disk_13.markDiskChanges(tmpCurrentDisks.Disk_13, "scsi13", params, changes) + disks.Disk_14.markDiskChanges(tmpCurrentDisks.Disk_14, "scsi14", params, changes) + disks.Disk_15.markDiskChanges(tmpCurrentDisks.Disk_15, "scsi15", params, changes) + disks.Disk_16.markDiskChanges(tmpCurrentDisks.Disk_16, "scsi16", params, changes) + disks.Disk_17.markDiskChanges(tmpCurrentDisks.Disk_17, "scsi17", params, changes) + disks.Disk_18.markDiskChanges(tmpCurrentDisks.Disk_18, "scsi18", params, changes) + disks.Disk_19.markDiskChanges(tmpCurrentDisks.Disk_19, "scsi19", params, changes) + disks.Disk_20.markDiskChanges(tmpCurrentDisks.Disk_20, "scsi20", params, changes) + disks.Disk_21.markDiskChanges(tmpCurrentDisks.Disk_21, "scsi21", params, changes) + disks.Disk_22.markDiskChanges(tmpCurrentDisks.Disk_22, "scsi22", params, changes) + disks.Disk_23.markDiskChanges(tmpCurrentDisks.Disk_23, "scsi23", params, changes) + disks.Disk_24.markDiskChanges(tmpCurrentDisks.Disk_24, "scsi24", params, changes) + disks.Disk_25.markDiskChanges(tmpCurrentDisks.Disk_25, "scsi25", params, changes) + disks.Disk_26.markDiskChanges(tmpCurrentDisks.Disk_26, "scsi26", params, changes) + disks.Disk_27.markDiskChanges(tmpCurrentDisks.Disk_27, "scsi27", params, changes) + disks.Disk_28.markDiskChanges(tmpCurrentDisks.Disk_28, "scsi28", params, changes) + disks.Disk_29.markDiskChanges(tmpCurrentDisks.Disk_29, "scsi29", params, changes) + disks.Disk_30.markDiskChanges(tmpCurrentDisks.Disk_30, "scsi30", params, changes) } +// TODO write test func (QemuScsiDisks) mapToStruct(params map[string]interface{}) *QemuScsiDisks { disks := QemuScsiDisks{} var structPopulated bool @@ -312,6 +257,7 @@ type QemuScsiPassthrough struct { } // TODO write function +// TODO write test func (passthrough QemuScsiPassthrough) mapToApiValues() string { return "" } @@ -323,6 +269,7 @@ type QemuScsiStorage struct { Passthrough *QemuScsiPassthrough } +// TODO write test func (storage QemuScsiStorage) mapToApiValues(create bool) string { if storage.Disk != nil { return storage.Disk.mapToApiValues(create) @@ -339,6 +286,75 @@ func (storage QemuScsiStorage) mapToApiValues(create bool) string { return "" } +// TODO write test +func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { + if storage == nil { + if currentStorage != nil { + changes.Delete = append(changes.Delete, id) + } + return + } + // CDROM + if storage.CdRom != nil { + // Create or Update + params[id] = storage.CdRom.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.CdRom != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // CloudInit + if storage.CloudInit != nil { + // Create or Update + params[id] = storage.CloudInit.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.CloudInit != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // Disk + if storage.Disk != nil { + if currentStorage == nil || currentStorage.Disk == nil { + // Create + params[id] = storage.Disk.mapToApiValues(true) + } else { + if storage.Disk.Size >= currentStorage.Disk.Size { + // Update + if storage.Disk.Storage != currentStorage.Disk.Storage { + changes.Move = append(changes.Move, qemuDiskShort{ + Id: id, + Storage: storage.Disk.Storage, + }) + } + params[id] = storage.Disk.mapToApiValues(false) + } else { + // Delete and Create + changes.Delete = append(changes.Delete, id) + params[id] = storage.Disk.mapToApiValues(true) + } + } + return + } else if currentStorage != nil && currentStorage.Disk != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // Passthrough + if storage.Passthrough != nil { + // Create or Update + changes.MigrationImpossible = true + params[id] = storage.Passthrough.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.Passthrough != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } +} + +// TODO write test func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 3e60a558..a4590b8f 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -14,6 +14,7 @@ type QemuVirtIODisk struct { Storage string `json:"storage,omitempty"` } +// TODO write test func (disk QemuVirtIODisk) mapToApiValues(create bool) string { return qemuDisk{ AsyncIO: disk.AsyncIO, @@ -49,57 +50,31 @@ type QemuVirtIODisks struct { Disk_15 *QemuVirtIOStorage `json:"15,omitempty"` } -func (disks QemuVirtIODisks) mapToApiValues(create bool, params map[string]interface{}) { - if disks.Disk_0 != nil { - params["virtio0"] = disks.Disk_0.mapToApiValues(create) - } - if disks.Disk_1 != nil { - params["virtio1"] = disks.Disk_1.mapToApiValues(create) - } - if disks.Disk_2 != nil { - params["virtio2"] = disks.Disk_2.mapToApiValues(create) - } - if disks.Disk_3 != nil { - params["virtio3"] = disks.Disk_3.mapToApiValues(create) - } - if disks.Disk_4 != nil { - params["virtio4"] = disks.Disk_4.mapToApiValues(create) - } - if disks.Disk_5 != nil { - params["virtio5"] = disks.Disk_5.mapToApiValues(create) - } - if disks.Disk_6 != nil { - params["virtio6"] = disks.Disk_6.mapToApiValues(create) - } - if disks.Disk_7 != nil { - params["virtio7"] = disks.Disk_7.mapToApiValues(create) - } - if disks.Disk_8 != nil { - params["virtio8"] = disks.Disk_8.mapToApiValues(create) - } - if disks.Disk_9 != nil { - params["virtio9"] = disks.Disk_9.mapToApiValues(create) - } - if disks.Disk_10 != nil { - params["virtio10"] = disks.Disk_10.mapToApiValues(create) - } - if disks.Disk_11 != nil { - params["virtio11"] = disks.Disk_11.mapToApiValues(create) - } - if disks.Disk_12 != nil { - params["virtio12"] = disks.Disk_12.mapToApiValues(create) - } - if disks.Disk_13 != nil { - params["virtio13"] = disks.Disk_13.mapToApiValues(create) - } - if disks.Disk_14 != nil { - params["virtio14"] = disks.Disk_14.mapToApiValues(create) - } - if disks.Disk_15 != nil { - params["virtio15"] = disks.Disk_15.mapToApiValues(create) - } +// TODO write test +func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, params map[string]interface{}, changes *qemuUpdateChanges) { + tmpCurrentDisks := QemuVirtIODisks{} + if currentDisks != nil { + tmpCurrentDisks = *currentDisks + } + disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, "virtio0", params, changes) + disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, "virtio1", params, changes) + disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, "virtio2", params, changes) + disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, "virtio3", params, changes) + disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, "virtio4", params, changes) + disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, "virtio5", params, changes) + disks.Disk_6.markDiskChanges(tmpCurrentDisks.Disk_6, "virtio6", params, changes) + disks.Disk_7.markDiskChanges(tmpCurrentDisks.Disk_7, "virtio7", params, changes) + disks.Disk_8.markDiskChanges(tmpCurrentDisks.Disk_8, "virtio8", params, changes) + disks.Disk_9.markDiskChanges(tmpCurrentDisks.Disk_9, "virtio9", params, changes) + disks.Disk_10.markDiskChanges(tmpCurrentDisks.Disk_10, "virtio10", params, changes) + disks.Disk_11.markDiskChanges(tmpCurrentDisks.Disk_11, "virtio11", params, changes) + disks.Disk_12.markDiskChanges(tmpCurrentDisks.Disk_12, "virtio12", params, changes) + disks.Disk_13.markDiskChanges(tmpCurrentDisks.Disk_13, "virtio13", params, changes) + disks.Disk_14.markDiskChanges(tmpCurrentDisks.Disk_14, "virtio14", params, changes) + disks.Disk_15.markDiskChanges(tmpCurrentDisks.Disk_15, "virtio15", params, changes) } +// TODO write test func (QemuVirtIODisks) mapToStruct(params map[string]interface{}) *QemuVirtIODisks { disks := QemuVirtIODisks{} var structPopulated bool @@ -187,6 +162,7 @@ type QemuVirtIOPassthrough struct { } // TODO write function +// TODO write test func (passthrough QemuVirtIOPassthrough) mapToApiValues() string { return "" } @@ -198,6 +174,7 @@ type QemuVirtIOStorage struct { Passthrough *QemuVirtIOPassthrough } +// TODO write test func (storage QemuVirtIOStorage) mapToApiValues(create bool) string { if storage.Disk != nil { return storage.Disk.mapToApiValues(create) @@ -214,6 +191,75 @@ func (storage QemuVirtIOStorage) mapToApiValues(create bool) string { return "" } +// TODO write test +func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { + if storage == nil { + if currentStorage != nil { + changes.Delete = append(changes.Delete, id) + } + return + } + // CDROM + if storage.CdRom != nil { + // Create or Update + params[id] = storage.CdRom.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.CdRom != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // CloudInit + if storage.CloudInit != nil { + // Create or Update + params[id] = storage.CloudInit.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.CloudInit != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // Disk + if storage.Disk != nil { + if currentStorage == nil || currentStorage.Disk == nil { + // Create + params[id] = storage.Disk.mapToApiValues(true) + } else { + if storage.Disk.Size >= currentStorage.Disk.Size { + // Update + if storage.Disk.Storage != currentStorage.Disk.Storage { + changes.Move = append(changes.Move, qemuDiskShort{ + Id: id, + Storage: storage.Disk.Storage, + }) + } + params[id] = storage.Disk.mapToApiValues(false) + } else { + // Delete and Create + changes.Delete = append(changes.Delete, id) + params[id] = storage.Disk.mapToApiValues(true) + } + } + return + } else if currentStorage != nil && currentStorage.Disk != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } + // Passthrough + if storage.Passthrough != nil { + // Create or Update + changes.MigrationImpossible = true + params[id] = storage.Passthrough.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.Passthrough != nil { + // Delete + changes.Delete = append(changes.Delete, id) + return + } +} + +// TODO write test func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) From 9fce801b9f86343a1a98cf0c69607ecdb6430bad Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 15:23:44 +0000 Subject: [PATCH 016/120] refactor: remove errors that always return nil --- proxmox/config_qemu.go | 129 +++++++++-------------------------------- 1 file changed, 26 insertions(+), 103 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 38efb72d..143012ac 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -165,16 +165,10 @@ func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { } // Create disks config. - err = config.CreateQemuDisksParams(vmr.vmId, params, false) - if err != nil { - log.Printf("[ERROR] %q", err) - } + config.CreateQemuDisksParams(params, false) // Create EFI disk - err = config.CreateQemuEfiParams(params) - if err != nil { - log.Printf("[ERROR] %q", err) - } + config.CreateQemuEfiParams(params) // Create vga config. vgaParam := QemuDeviceParam{} @@ -184,33 +178,21 @@ func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { } // Create networks config. - err = config.CreateQemuNetworksParams(vmr.vmId, params) - if err != nil { - log.Printf("[ERROR] %q", err) - } + config.CreateQemuNetworksParams(vmr.vmId, params) // Create ipconfig. - err = config.CreateIpconfigParams(vmr.vmId, params) + err = config.CreateIpconfigParams(params) if err != nil { log.Printf("[ERROR] %q", err) } // Create serial interfaces - err = config.CreateQemuSerialsParams(vmr.vmId, params) - if err != nil { - log.Printf("[ERROR] %q", err) - } + config.CreateQemuSerialsParams(params) - err = config.CreateQemuPCIsParams(vmr.vmId, params) - if err != nil { - log.Printf("[ERROR] %q", err) - } + config.CreateQemuPCIsParams(params) // Create usb interfaces - err = config.CreateQemuUsbsParams(vmr.vmId, params) - if err != nil { - log.Printf("[ERROR] %q", err) - } + config.CreateQemuUsbsParams(params) exitStatus, err := client.CreateQemuVm(vmr.node, params) if err != nil { @@ -385,10 +367,7 @@ func (config ConfigQemu) UpdateConfig(vmr *VmRef, client *Client) (err error) { "vmid": vmr.vmId, } // TODO keep going if error= - err = config.CreateQemuDisksParams(vmr.vmId, configParamsDisk, false) - if err != nil { - log.Printf("[ERROR] %q", err) - } + config.CreateQemuDisksParams(configParamsDisk, false) // TODO keep going if error= _, err = client.createVMDisks(vmr.node, configParamsDisk) if err != nil { @@ -403,10 +382,7 @@ func (config ConfigQemu) UpdateConfig(vmr *VmRef, client *Client) (err error) { } // Create networks config. - err = config.CreateQemuNetworksParams(vmr.vmId, configParams) - if err != nil { - log.Printf("[ERROR] %q", err) - } + config.CreateQemuNetworksParams(vmr.vmId, configParams) // Create vga config. vgaParam := QemuDeviceParam{} @@ -415,21 +391,13 @@ func (config ConfigQemu) UpdateConfig(vmr *VmRef, client *Client) (err error) { configParams["vga"] = strings.Join(vgaParam, ",") } // Create serial interfaces - err = config.CreateQemuSerialsParams(vmr.vmId, configParams) - if err != nil { - log.Printf("[ERROR] %q", err) - } + config.CreateQemuSerialsParams(configParams) // Create usb interfaces - err = config.CreateQemuUsbsParams(vmr.vmId, configParams) - if err != nil { - log.Printf("[ERROR] %q", err) - } + config.CreateQemuUsbsParams(configParams) + + config.CreateQemuPCIsParams(configParams) - err = config.CreateQemuPCIsParams(vmr.vmId, configParams) - if err != nil { - log.Printf("[ERROR] %q", err) - } // cloud-init options if config.CIuser != "" { configParams["ciuser"] = config.CIuser @@ -449,7 +417,7 @@ func (config ConfigQemu) UpdateConfig(vmr *VmRef, client *Client) (err error) { if config.Sshkeys != "" { configParams["sshkeys"] = sshKeyUrlEncode(config.Sshkeys) } - err = config.CreateIpconfigParams(vmr.vmId, configParams) + err = config.CreateIpconfigParams(configParams) if err != nil { log.Printf("[ERROR] %q", err) } @@ -835,11 +803,7 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e vgaList := strings.Split(vga.(string), ",") vgaMap := QemuDevice{} - // TODO: keep going if error? - err = vgaMap.readDeviceConfig(vgaList) - if err != nil { - log.Printf("[ERROR] %q", err) - } + vgaMap.readDeviceConfig(vgaList) if len(vgaMap) > 0 { config.QemuVga = vgaMap } @@ -870,10 +834,7 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e } // Add rest of device config. - err = nicConfMap.readDeviceConfig(nicConfList[1:]) - if err != nil { - log.Printf("[ERROR] %q", err) - } + nicConfMap.readDeviceConfig(nicConfList[1:]) switch nicConfMap["firewall"] { case 1: nicConfMap["firewall"] = true @@ -938,10 +899,7 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e "host": host, } - err = usbConfMap.readDeviceConfig(usbConfList[1:]) - if err != nil { - log.Printf("[ERROR] %q", err) - } + usbConfMap.readDeviceConfig(usbConfList[1:]) if usbConfMap["usb3"] == 1 { usbConfMap["usb3"] = true } @@ -969,11 +927,7 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e hostPCIConfMap := QemuDevice{ "id": hostPCIID, } - err = hostPCIConfMap.readDeviceConfig(hostPCIConfList) - if err != nil { - log.Printf("[ERROR] %q", err) - } - + hostPCIConfMap.readDeviceConfig(hostPCIConfList) // And device config to usbs map. if len(hostPCIConfMap) > 0 { config.QemuPCIDevices[hostPCIID] = hostPCIConfMap @@ -989,7 +943,6 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e //log.Printf("[DEBUG] VM %d(%s) has no HA config", vmr.vmId, vmConfig["hostname"]) return config, nil } - return } @@ -1205,8 +1158,7 @@ func FormatUsbParam(usb QemuDevice) string { } // Create parameters for each Nic device. -func (c ConfigQemu) CreateQemuNetworksParams(vmID int, params map[string]interface{}) error { - +func (c ConfigQemu) CreateQemuNetworksParams(vmID int, params map[string]interface{}) { // For new style with multi net device. for nicID, nicConfMap := range c.QemuNetworks { @@ -1267,12 +1219,10 @@ func (c ConfigQemu) CreateQemuNetworksParams(vmID int, params map[string]interfa // Add nic to Qemu prams. params[qemuNicName] = strings.Join(nicConfParam, ",") } - - return nil } // Create parameters for each Cloud-Init ipconfig entry. -func (c ConfigQemu) CreateIpconfigParams(vmID int, params map[string]interface{}) error { +func (c ConfigQemu) CreateIpconfigParams(params map[string]interface{}) error { for ID, config := range c.Ipconfig { if ID > 15 { @@ -1289,9 +1239,7 @@ func (c ConfigQemu) CreateIpconfigParams(vmID int, params map[string]interface{} } // Create efi parameter. -func (c ConfigQemu) CreateQemuEfiParams( - params map[string]interface{}, -) error { +func (c ConfigQemu) CreateQemuEfiParams(params map[string]interface{}) { efiParam := QemuDeviceParam{} efiParam = efiParam.createDeviceParam(c.EFIDisk, nil) @@ -1312,16 +1260,10 @@ func (c ConfigQemu) CreateQemuEfiParams( } params["efidisk0"] = storage } - return nil } // Create parameters for each disk. -func (c ConfigQemu) CreateQemuDisksParams( - vmID int, - params map[string]interface{}, - cloned bool, -) error { - +func (c ConfigQemu) CreateQemuDisksParams(params map[string]interface{}, cloned bool) { // For new style with multi disk device. for diskID, diskConfMap := range c.QemuDisks { // skip the first disk for clones (may not always be right, but a template probably has at least 1 disk) @@ -1336,16 +1278,10 @@ func (c ConfigQemu) CreateQemuDisksParams( // Add back to Qemu prams. params[qemuDiskName] = FormatDiskParam(diskConfMap) } - - return nil } // Create parameters for each PCI Device -func (c ConfigQemu) CreateQemuPCIsParams( - vmID int, - params map[string]interface{}, -) error { - +func (c ConfigQemu) CreateQemuPCIsParams(params map[string]interface{}) { // For new style with multi pci device. for pciConfID, pciConfMap := range c.QemuPCIDevices { qemuPCIName := "hostpci" + strconv.Itoa(pciConfID) @@ -1360,15 +1296,10 @@ func (c ConfigQemu) CreateQemuPCIsParams( // Add back to Qemu prams. params[qemuPCIName] = strings.TrimSuffix(pcistring.String(), ",") } - return nil } // Create parameters for serial interface -func (c ConfigQemu) CreateQemuSerialsParams( - vmID int, - params map[string]interface{}, -) error { - +func (c ConfigQemu) CreateQemuSerialsParams(params map[string]interface{}) { // For new style with multi disk device. for serialID, serialConfMap := range c.QemuSerials { // Device name. @@ -1378,23 +1309,16 @@ func (c ConfigQemu) CreateQemuSerialsParams( // Add back to Qemu prams. params[qemuSerialName] = deviceType } - - return nil } // Create parameters for usb interface -func (c ConfigQemu) CreateQemuUsbsParams( - vmID int, - params map[string]interface{}, -) error { +func (c ConfigQemu) CreateQemuUsbsParams(params map[string]interface{}) { for usbID, usbConfMap := range c.QemuUsbs { qemuUsbName := "usb" + strconv.Itoa(usbID) // Add back to Qemu prams. params[qemuUsbName] = FormatUsbParam(usbConfMap) } - - return nil } // Create parameters for serial interface @@ -1437,13 +1361,12 @@ func (p QemuDeviceParam) createDeviceParam( } // readDeviceConfig - get standard sub-conf strings where `key=value` and update conf map. -func (confMap QemuDevice) readDeviceConfig(confList []string) error { +func (confMap QemuDevice) readDeviceConfig(confList []string) { // Add device config. for _, conf := range confList { key, value := ParseSubConf(conf, "=") confMap[key] = value } - return nil } func (c ConfigQemu) String() string { From 3f356ba1bd15872b3e86705275b9144aa67e7faa Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 16:30:46 +0000 Subject: [PATCH 017/120] docs: typos and capitalization --- proxmox/config_qemu.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 143012ac..ddb71df7 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -934,7 +934,7 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e } } - // hastate is return by the api for a vm resource type but not the hagroup + // HAstate is return by the api for a vm resource type but not the HAgroup err = client.ReadVMHA(vmr) if err == nil { config.HaState = vmr.HaState() @@ -1100,7 +1100,7 @@ func formatDeviceParam(device QemuDevice) string { return strings.Join(deviceConfParams, ",") } -// Given a QemuDevice (represesting a disk), return a param string to give to ProxMox +// Given a QemuDevice (representing a disk), return a param string to give to ProxMox func FormatDiskParam(disk QemuDevice) string { diskConfParam := QemuDeviceParam{} @@ -1148,7 +1148,7 @@ func FormatDiskParam(disk QemuDevice) string { return strings.Join(diskConfParam, ",") } -// Given a QemuDevice (represesting a usb), return a param string to give to ProxMox +// Given a QemuDevice (representing a usb), return a param string to give to ProxMox func FormatUsbParam(usb QemuDevice) string { usbConfParam := QemuDeviceParam{} @@ -1201,7 +1201,7 @@ func (c ConfigQemu) CreateQemuNetworksParams(vmID int, params map[string]interfa macAddr = nicConfMap["macaddr"].(string) } - // use model=mac format for older proxmox compatability as the parameters which will be sent to Proxmox API. + // use model=mac format for older proxmox compatibility as the parameters which will be sent to Proxmox API. nicConfParam = append(nicConfParam, fmt.Sprintf("%v=%v", nicConfMap["model"], macAddr)) // Set bridge if not nat. From 6671092226101f4804c6af9c27de15f11a335098 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 16:32:14 +0000 Subject: [PATCH 018/120] refactor: make variable camelCase --- proxmox/config_qemu.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index ddb71df7..6032577e 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -237,9 +237,9 @@ storage:xxx func (config ConfigQemu) CloneVm(sourceVmr *VmRef, vmr *VmRef, client *Client) (err error) { vmr.SetVmType("qemu") var storage string - fullclone := "1" + fullClone := "1" if config.FullClone != nil { - fullclone = strconv.Itoa(*config.FullClone) + fullClone = strconv.Itoa(*config.FullClone) } if disk0Storage, ok := config.QemuDisks[0]["storage"].(string); ok && len(disk0Storage) > 0 { storage = disk0Storage @@ -248,13 +248,13 @@ func (config ConfigQemu) CloneVm(sourceVmr *VmRef, vmr *VmRef, client *Client) ( "newid": vmr.vmId, "target": vmr.node, "name": config.Name, - "full": fullclone, + "full": fullClone, } if vmr.pool != "" { params["pool"] = vmr.pool } - if fullclone == "1" && storage != "" { + if fullClone == "1" && storage != "" { params["storage"] = storage } From b9b36c1c23b93b3b8b9009381889fa1246283521 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 17:51:09 +0000 Subject: [PATCH 019/120] refactor: change array to string --- proxmox/config_qemu_disk.go | 2 +- proxmox/config_qemu_disk_ide.go | 12 ++++++------ proxmox/config_qemu_disk_sata.go | 12 ++++++------ proxmox/config_qemu_disk_scsi.go | 12 ++++++------ proxmox/config_qemu_disk_virtio.go | 12 ++++++------ 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 3079ad02..2d2a8746 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -473,6 +473,6 @@ func (QemuStorages) mapToStruct(params map[string]interface{}) *QemuStorages { type qemuUpdateChanges struct { Move []qemuDiskShort - Delete []string + Delete string MigrationImpossible bool } diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index d49d55ac..8e6d1a0d 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -122,7 +122,7 @@ func (storage QemuIdeStorage) mapToApiValues(create bool) string { func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { if storage == nil { if currentStorage != nil { - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) } return } @@ -133,7 +133,7 @@ func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, i return } else if currentStorage != nil && currentStorage.CdRom != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // CloudInit @@ -143,7 +143,7 @@ func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, i return } else if currentStorage != nil && currentStorage.CloudInit != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // Disk @@ -163,14 +163,14 @@ func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, i params[id] = storage.Disk.mapToApiValues(false) } else { // Delete and Create - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) params[id] = storage.Disk.mapToApiValues(true) } } return } else if currentStorage != nil && currentStorage.Disk != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // Passthrough @@ -181,7 +181,7 @@ func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, i return } else if currentStorage != nil && currentStorage.Passthrough != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } } diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index f39fd8b8..e1c1a614 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -134,7 +134,7 @@ func (storage QemuSataStorage) mapToApiValues(create bool) string { func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { if storage == nil { if currentStorage != nil { - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) } return } @@ -145,7 +145,7 @@ func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, return } else if currentStorage != nil && currentStorage.CdRom != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // CloudInit @@ -155,7 +155,7 @@ func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, return } else if currentStorage != nil && currentStorage.CloudInit != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // Disk @@ -175,14 +175,14 @@ func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, params[id] = storage.Disk.mapToApiValues(false) } else { // Delete and Create - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) params[id] = storage.Disk.mapToApiValues(true) } } return } else if currentStorage != nil && currentStorage.Disk != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // Passthrough @@ -193,7 +193,7 @@ func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, return } else if currentStorage != nil && currentStorage.Passthrough != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } } diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index b91f2eb3..51cb5129 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -290,7 +290,7 @@ func (storage QemuScsiStorage) mapToApiValues(create bool) string { func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { if storage == nil { if currentStorage != nil { - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) } return } @@ -301,7 +301,7 @@ func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, return } else if currentStorage != nil && currentStorage.CdRom != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // CloudInit @@ -311,7 +311,7 @@ func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, return } else if currentStorage != nil && currentStorage.CloudInit != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // Disk @@ -331,14 +331,14 @@ func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, params[id] = storage.Disk.mapToApiValues(false) } else { // Delete and Create - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) params[id] = storage.Disk.mapToApiValues(true) } } return } else if currentStorage != nil && currentStorage.Disk != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // Passthrough @@ -349,7 +349,7 @@ func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, return } else if currentStorage != nil && currentStorage.Passthrough != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } } diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index a4590b8f..151ae1a7 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -195,7 +195,7 @@ func (storage QemuVirtIOStorage) mapToApiValues(create bool) string { func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { if storage == nil { if currentStorage != nil { - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) } return } @@ -206,7 +206,7 @@ func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStor return } else if currentStorage != nil && currentStorage.CdRom != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // CloudInit @@ -216,7 +216,7 @@ func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStor return } else if currentStorage != nil && currentStorage.CloudInit != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // Disk @@ -236,14 +236,14 @@ func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStor params[id] = storage.Disk.mapToApiValues(false) } else { // Delete and Create - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) params[id] = storage.Disk.mapToApiValues(true) } } return } else if currentStorage != nil && currentStorage.Disk != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } // Passthrough @@ -254,7 +254,7 @@ func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStor return } else if currentStorage != nil && currentStorage.Passthrough != nil { // Delete - changes.Delete = append(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, id) return } } From f8864f33681bd227a594d328faa25e84fd9d5768 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 17:53:29 +0000 Subject: [PATCH 020/120] refactor: change mapping of qemu api parameters --- proxmox/config_qemu.go | 203 ++++++++++++++++++++++++++++------------- 1 file changed, 142 insertions(+), 61 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 6032577e..0ebd4080 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -89,64 +89,45 @@ type ConfigQemu struct { // CreateVm - Tell Proxmox API to make the VM func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { - if config.HasCloudInit() { - return fmt.Errorf("cloud-init parameters only supported on clones or updates") + params, _, err := config.mapToApiValues(ConfigQemu{}, vmr) + if err != nil { + return } - vmr.SetVmType("qemu") - params := map[string]interface{}{ - "vmid": vmr.vmId, - "name": config.Name, - "startup": config.Startup, - "agent": config.Agent, - "ostype": config.QemuOs, - "sockets": config.QemuSockets, - "cores": config.QemuCores, - "cpu": config.QemuCpu, - "hotplug": config.Hotplug, - "memory": config.Memory, - "boot": config.Boot, - "description": config.Description, - "tags": config.Tags, - "machine": config.Machine, - "args": config.Args, + exitStatus, err := client.CreateQemuVm(vmr.node, params) + if err != nil { + return fmt.Errorf("error creating VM: %v, error status: %s (params: %v)", err, exitStatus, params) } - if config.QemuNuma != nil { - params["numa"] = *config.QemuNuma + _, err = client.UpdateVMHA(vmr, config.HaState, config.HaGroup) + if err != nil { + return fmt.Errorf("[ERROR] %q", err) } - if config.QemuKVM != nil { - params["kvm"] = *config.QemuKVM - } + return +} - if config.Tablet != nil { - params["tablet"] = *config.Tablet - } +func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu, vmr *VmRef) (params map[string]interface{}, markedDisks *qemuUpdateChanges, err error) { - if config.Onboot != nil { - params["onboot"] = *config.Onboot - } + vmr.SetVmType("qemu") - // TODO conflicts with new mapping - if config.QemuIso != "" { - params["ide2"] = config.QemuIso + ",media=cdrom" - } + var itemsToDelete string - if config.Bios != "" { - params["bios"] = config.Bios + params = map[string]interface{}{ + "vmid": vmr.vmId, } + if config.Args != "" { + params["args"] = config.Args + } + if config.Agent != 0 { + params["agent"] = config.Agent + } if config.Balloon >= 1 { params["balloon"] = config.Balloon } - - if config.QemuVcpus >= 1 { - params["vcpus"] = config.QemuVcpus - } - - if vmr.pool != "" { - params["pool"] = vmr.pool + if config.Bios != "" { + params["bios"] = config.Bios } if config.Boot != "" { params["boot"] = config.Boot @@ -154,56 +135,154 @@ func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { if config.BootDisk != "" { params["bootdisk"] = config.BootDisk } - + if config.CIcustom != "" { + params["cicustom"] = config.CIcustom + } + if config.CIpassword != "" { + params["cipassword"] = config.CIpassword + } + if config.CIuser != "" { + params["ciuser"] = config.CIuser + } + if config.QemuCores != 0 { + params["cores"] = config.QemuCores + } + if config.QemuCpu != "" { + params["cpu"] = config.QemuCpu + } + if config.Description != "" { + params["description"] = config.Description + } + if config.Hookscript != "" { + params["hookscript"] = config.Hookscript + } + if config.Hotplug != "" { + params["hotplug"] = config.Hotplug + } + if config.QemuKVM != nil { + params["kvm"] = *config.QemuKVM + } + if config.Machine != "" { + params["machine"] = config.Machine + } + if config.Memory != 0 { + params["memory"] = config.Memory + } + if config.Name != "" { + params["name"] = config.Name + } + if config.Nameserver != "" { + params["nameserver"] = config.Nameserver + } + if config.QemuNuma != nil { + params["numa"] = *config.QemuNuma + } + if config.Onboot != nil { + params["onboot"] = *config.Onboot + } + if config.QemuOs != "" { + params["ostype"] = config.QemuOs + } + if vmr.pool != "" { + params["pool"] = vmr.pool + } if config.Scsihw != "" { params["scsihw"] = config.Scsihw } - - err = config.CreateQemuMachineParam(params) - if err != nil { - log.Printf("[ERROR] %q", err) + if config.Searchdomain != "" { + params["searchdomain"] = config.Searchdomain + } + if config.QemuSockets != 0 { + params["sockets"] = config.QemuSockets + } + if config.Sshkeys != "" { + params["sshkeys"] = sshKeyUrlEncode(config.Sshkeys) + } + if config.Startup != "" { + params["startup"] = config.Startup + } + if config.Tablet != nil { + params["tablet"] = *config.Tablet + } + if config.Tags != "" { + params["tags"] = config.Tags + } + if config.QemuVcpus >= 1 { + params["vcpus"] = config.QemuVcpus } - // Create disks config. - config.CreateQemuDisksParams(params, false) + // Disks + if currentConfig.Disks != nil { + if config.Disks != nil { + markedDisks = config.Disks.markDiskChanges(*currentConfig.Disks, params) + } + if markedDisks.Delete != "" { + itemsToDelete = AddToList(itemsToDelete, markedDisks.Delete) + } + } else { + if config.Disks != nil { + config.Disks.mapToApiValues(params) + } + } // Create EFI disk config.CreateQemuEfiParams(params) + // Create networks config. + config.CreateQemuNetworksParams(vmr.vmId, params) + // Create vga config. vgaParam := QemuDeviceParam{} vgaParam = vgaParam.createDeviceParam(config.QemuVga, nil) if len(vgaParam) > 0 { params["vga"] = strings.Join(vgaParam, ",") } + // Create serial interfaces + config.CreateQemuSerialsParams(params) - // Create networks config. - config.CreateQemuNetworksParams(vmr.vmId, params) + // Create usb interfaces + config.CreateQemuUsbsParams(params) + + config.CreateQemuPCIsParams(params) - // Create ipconfig. err = config.CreateIpconfigParams(params) if err != nil { log.Printf("[ERROR] %q", err) } - // Create serial interfaces - config.CreateQemuSerialsParams(params) + if itemsToDelete != "" { + params["delete"] = itemsToDelete + } + return +} - config.CreateQemuPCIsParams(params) +func (newConfig ConfigQemu) Update(currentConfig *ConfigQemu, vmr *VmRef, client *Client) (err error) { + params, markedDisks, err := newConfig.mapToApiValues(*currentConfig, vmr) + if err != nil { + return + } - // Create usb interfaces - config.CreateQemuUsbsParams(params) + for _, e := range markedDisks.Move { + _, err = client.MoveQemuDisk(vmr, e.Id, e.Storage) + if err != nil { + return + } + } - exitStatus, err := client.CreateQemuVm(vmr.node, params) + // TODO Migrate VM + + _, err = client.SetVmConfig(vmr, params) if err != nil { - return fmt.Errorf("error creating VM: %v, error status: %s (params: %v)", err, exitStatus, params) + log.Print(err) + return err } - _, err = client.UpdateVMHA(vmr, config.HaState, config.HaGroup) + _, err = client.UpdateVMHA(vmr, newConfig.HaState, newConfig.HaGroup) if err != nil { log.Printf("[ERROR] %q", err) } + _, err = client.UpdateVMPool(vmr, newConfig.Pool) return } @@ -680,6 +759,8 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e config.Ipconfig[ipconfigID] = ipConfStr } + config.Disks = QemuStorages{}.mapToStruct(vmConfig) + // Add disks. diskNames := []string{} From a2bb827e66e620972471c8cc593910a3cf7d9d42 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 17:56:18 +0000 Subject: [PATCH 021/120] mark `ConfigQemu.QemuDisks` as Deprecated --- proxmox/config_qemu.go | 85 +----------------------------------------- 1 file changed, 1 insertion(+), 84 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 0ebd4080..f27856ff 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -63,7 +63,7 @@ type ConfigQemu struct { BootDisk string `json:"bootdisk,omitempty"` Scsihw string `json:"scsihw,omitempty"` Disks *QemuStorages `json:"disks,omitempty"` - QemuDisks QemuDevices `json:"disk,omitempty"` + QemuDisks QemuDevices `json:"disk,omitempty"` // DEPRECATED use Disks *QemuStorages instead QemuUnusedDisks QemuDevices `json:"unused,omitempty"` QemuVga QemuDevice `json:"vga,omitempty"` QemuNetworks QemuDevices `json:"network,omitempty"` @@ -761,89 +761,6 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e config.Disks = QemuStorages{}.mapToStruct(vmConfig) - // Add disks. - diskNames := []string{} - - for k := range vmConfig { - if diskName := rxDiskName.FindStringSubmatch(k); len(diskName) > 0 { - diskNames = append(diskNames, diskName[0]) - } - } - - for _, diskName := range diskNames { - var isDiskByID bool = false - diskConfStr := vmConfig[diskName].(string) - - id := rxDeviceID.FindStringSubmatch(diskName) - diskID, _ := strconv.Atoi(id[0]) - diskType := rxDiskType.FindStringSubmatch(diskName)[0] - - diskConfMap := ParsePMConf(diskConfStr, "volume") - diskByID := rxDiskPath.FindStringSubmatch(diskConfMap["volume"].(string)) - if len(diskByID) > 0 && diskByID[0] != "" { - isDiskByID = true - } - - if diskConfMap["volume"].(string) == "none" { - continue - } - - diskConfMap["slot"] = diskID - diskConfMap["type"] = diskType - - storageName, fileName := ParseSubConf(diskConfMap["volume"].(string), ":") - diskConfMap["storage"] = storageName - diskConfMap["file"] = fileName - - filePath := diskConfMap["volume"] - - // Get disk format - storageContent, err := client.GetStorageContent(vmr, storageName) - if err != nil { - log.Fatal(err) - return nil, err - } - var storageFormat string - contents := storageContent["data"].([]interface{}) - for content := range contents { - storageContentMap := contents[content].(map[string]interface{}) - if storageContentMap["volid"] == filePath { - storageFormat = storageContentMap["format"].(string) - break - } - } - diskConfMap["format"] = storageFormat - - // Get storage type for disk - var storageStatus map[string]interface{} - if !isDiskByID { - storageStatus, err = client.GetStorageStatus(vmr, storageName) - if err != nil { - log.Fatal(err) - return nil, err - } - storageType := storageStatus["type"] - - diskConfMap["storage_type"] = storageType - } - // cloud-init disks not always have the size sent by the API, which results in a crash - if diskConfMap["size"] == nil && strings.Contains(fileName.(string), "cloudinit") { - diskConfMap["size"] = "4M" // default cloud-init disk size - } - - var sizeInTerabytes = regexp.MustCompile(`[0-9]+T`) - // Convert to gigabytes if disk size was received in terabytes - matched := sizeInTerabytes.MatchString(diskConfMap["size"].(string)) - if matched { - diskConfMap["size"] = fmt.Sprintf("%.0fG", DiskSizeGB(diskConfMap["size"])) - } - - // And device config to disks map. - if len(diskConfMap) > 0 { - config.QemuDisks[diskID] = diskConfMap - } - } - // Add unused disks // unused0:local:100/vm-100-disk-1.qcow2 unusedDiskNames := []string{} From 967e9fdf70ac555f13a769aa4f8f40f6acde860f Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 17:58:14 +0000 Subject: [PATCH 022/120] Make `ConfigQemu.BootDisk` read only --- proxmox/config_qemu.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index f27856ff..0bf71dc3 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -60,7 +60,7 @@ type ConfigQemu struct { QemuPxe bool `json:"pxe,omitempty"` FullClone *int `json:"fullclone,omitempty"` Boot string `json:"boot,omitempty"` - BootDisk string `json:"bootdisk,omitempty"` + BootDisk string `json:"bootdisk,omitempty"` // Only returned as it's deprecated in the proxmox api Scsihw string `json:"scsihw,omitempty"` Disks *QemuStorages `json:"disks,omitempty"` QemuDisks QemuDevices `json:"disk,omitempty"` // DEPRECATED use Disks *QemuStorages instead @@ -132,9 +132,6 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu, vmr *VmRef) (p if config.Boot != "" { params["boot"] = config.Boot } - if config.BootDisk != "" { - params["bootdisk"] = config.BootDisk - } if config.CIcustom != "" { params["cicustom"] = config.CIcustom } From 50637760aae56452ee7c7310863a22b592fc6319 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 18:06:13 +0000 Subject: [PATCH 023/120] Mark func as Deprecated --- proxmox/config_qemu.go | 1 + 1 file changed, 1 insertion(+) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 0bf71dc3..a72cd1f2 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -338,6 +338,7 @@ func (config ConfigQemu) CloneVm(sourceVmr *VmRef, vmr *VmRef, client *Client) ( return err } +// DEPRECATED use ConfigQemu.Update instead func (config ConfigQemu) UpdateConfig(vmr *VmRef, client *Client) (err error) { configParams := map[string]interface{}{} From 214163e7dac62afb73d2bdafcbb64858c913aa12 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 18:22:34 +0000 Subject: [PATCH 024/120] Mark func as Deprecated --- proxmox/client.go | 2 +- proxmox/config_qemu.go | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/proxmox/client.go b/proxmox/client.go index e0ae4985..b2079ccd 100644 --- a/proxmox/client.go +++ b/proxmox/client.go @@ -696,7 +696,7 @@ func (c *Client) RollbackQemuVm(vmr *VmRef, snapshot string) (exitStatus string, return RollbackSnapshot(c, vmr, snapshot) } -// SetVmConfig - send config options +// DEPRECATED SetVmConfig - send config options func (c *Client) SetVmConfig(vmr *VmRef, params map[string]interface{}) (exitStatus interface{}, err error) { return c.PostWithTask(params, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/config") } diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index a72cd1f2..bd09cc08 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -268,10 +268,9 @@ func (newConfig ConfigQemu) Update(currentConfig *ConfigQemu, vmr *VmRef, client // TODO Migrate VM - _, err = client.SetVmConfig(vmr, params) + _, err = client.PostWithTask(params, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/config") if err != nil { - log.Print(err) - return err + return } _, err = client.UpdateVMHA(vmr, newConfig.HaState, newConfig.HaGroup) From 8ec657cbfba60950547d82fd3c57d4957e817595 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 18:24:47 +0000 Subject: [PATCH 025/120] fix: return error instead of printing it --- proxmox/config_qemu.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index bd09cc08..9c785a89 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -275,7 +275,7 @@ func (newConfig ConfigQemu) Update(currentConfig *ConfigQemu, vmr *VmRef, client _, err = client.UpdateVMHA(vmr, newConfig.HaState, newConfig.HaGroup) if err != nil { - log.Printf("[ERROR] %q", err) + return } _, err = client.UpdateVMPool(vmr, newConfig.Pool) From 7113ce24ebf5c7b1eda6afdb7aeaa847ab1b45ec Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 2 Mar 2023 19:06:16 +0000 Subject: [PATCH 026/120] feat: added `UpdateAdvanced` and `Update` this allows for the user to manually provide the current config or let the library provide the config --- proxmox/config_qemu.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 9c785a89..88b6158e 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -253,7 +253,15 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu, vmr *VmRef) (p return } -func (newConfig ConfigQemu) Update(currentConfig *ConfigQemu, vmr *VmRef, client *Client) (err error) { +func (newConfig ConfigQemu) Update(vmr *VmRef, client *Client) (err error) { + currentConfig, err := NewConfigQemuFromApi(vmr, client) + if err != nil { + return + } + return newConfig.UpdateAdvanced(currentConfig, vmr, client) +} + +func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef, client *Client) (err error) { params, markedDisks, err := newConfig.mapToApiValues(*currentConfig, vmr) if err != nil { return From 1cc8b061254c358f3bd11577079d574eb7c6ed54 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Fri, 10 Mar 2023 09:29:14 +0000 Subject: [PATCH 027/120] feat: Map passthrough disk to api --- proxmox/config_qemu_disk.go | 3 +++ proxmox/config_qemu_disk_ide.go | 15 +++++++++++++-- proxmox/config_qemu_disk_sata.go | 15 +++++++++++++-- proxmox/config_qemu_disk_scsi.go | 17 +++++++++++++++-- proxmox/config_qemu_disk_virtio.go | 15 +++++++++++++-- 5 files changed, 57 insertions(+), 8 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 2d2a8746..b79cd252 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -152,6 +152,9 @@ func (disk qemuDisk) mapToApiValues(create bool) (settings string) { } } + if disk.File != "" { + settings = disk.File + } // Set File if disk.AsyncIO != "" { diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 8e6d1a0d..dda47127 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -88,10 +88,21 @@ type QemuIdePassthrough struct { Size uint } -// TODO write function // TODO write test func (passthrough QemuIdePassthrough) mapToApiValues() string { - return "" + return qemuDisk{ + AsyncIO: passthrough.AsyncIO, + Backup: passthrough.Backup, + Bandwidth: passthrough.Bandwidth, + Cache: passthrough.Cache, + Discard: passthrough.Discard, + EmulateSSD: passthrough.EmulateSSD, + File: passthrough.File, + Replicate: passthrough.Replicate, + Serial: passthrough.Serial, + Size: passthrough.Size, + Type: ide, + }.mapToApiValues(false) } type QemuIdeStorage struct { diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index e1c1a614..e28d7459 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -100,10 +100,21 @@ type QemuSataPassthrough struct { Size uint } -// TODO write function // TODO write test func (passthrough QemuSataPassthrough) mapToApiValues() string { - return "" + return qemuDisk{ + AsyncIO: passthrough.AsyncIO, + Backup: passthrough.Backup, + Bandwidth: passthrough.Bandwidth, + Cache: passthrough.Cache, + Discard: passthrough.Discard, + EmulateSSD: passthrough.EmulateSSD, + File: passthrough.File, + Replicate: passthrough.Replicate, + Serial: passthrough.Serial, + Size: passthrough.Size, + Type: sata, + }.mapToApiValues(false) } type QemuSataStorage struct { diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 51cb5129..28d48598 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -256,10 +256,23 @@ type QemuScsiPassthrough struct { Size uint } -// TODO write function // TODO write test func (passthrough QemuScsiPassthrough) mapToApiValues() string { - return "" + return qemuDisk{ + AsyncIO: passthrough.AsyncIO, + Backup: passthrough.Backup, + Bandwidth: passthrough.Bandwidth, + Cache: passthrough.Cache, + Discard: passthrough.Discard, + EmulateSSD: passthrough.EmulateSSD, + File: passthrough.File, + IOThread: passthrough.IOThread, + ReadOnly: passthrough.ReadOnly, + Replicate: passthrough.Replicate, + Serial: passthrough.Serial, + Size: passthrough.Size, + Type: scsi, + }.mapToApiValues(false) } type QemuScsiStorage struct { diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 151ae1a7..c448df05 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -161,10 +161,21 @@ type QemuVirtIOPassthrough struct { Size uint } -// TODO write function // TODO write test func (passthrough QemuVirtIOPassthrough) mapToApiValues() string { - return "" + return qemuDisk{ + AsyncIO: passthrough.AsyncIO, + Backup: passthrough.Backup, + Bandwidth: passthrough.Bandwidth, + Cache: passthrough.Cache, + Discard: passthrough.Discard, + File: passthrough.File, + IOThread: passthrough.IOThread, + ReadOnly: passthrough.ReadOnly, + Serial: passthrough.Serial, + Size: passthrough.Size, + Type: scsi, + }.mapToApiValues(false) } type QemuVirtIOStorage struct { From 5644d23a3f5a56d26c048716d2aa2ca15f16318d Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Fri, 10 Mar 2023 09:31:44 +0000 Subject: [PATCH 028/120] feat: map cloud-init disk to api --- proxmox/config_qemu_disk.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index b79cd252..0d4a8d4a 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -110,9 +110,9 @@ type QemuCloudInitDisk struct { FileType string } -// TODO write function +// TODO write test func (cloudInit QemuCloudInitDisk) mapToApiValues() string { - return "" + return cloudInit.Storage + ":cloudinit,format=" + cloudInit.FileType } func (QemuCloudInitDisk) mapToStruct(settings qemuCdRom) *QemuCloudInitDisk { From 4e7d7be8b35a69d0a75ba6ca5061272e8ff2389e Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Fri, 10 Mar 2023 09:38:35 +0000 Subject: [PATCH 029/120] refactor: change logic for when a disk needs to be deleted --- proxmox/config_qemu_disk.go | 5 ++--- proxmox/config_qemu_disk_ide.go | 8 ++++---- proxmox/config_qemu_disk_sata.go | 8 ++++---- proxmox/config_qemu_disk_scsi.go | 8 ++++---- proxmox/config_qemu_disk_virtio.go | 8 ++++---- 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 0d4a8d4a..055200ca 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -475,7 +475,6 @@ func (QemuStorages) mapToStruct(params map[string]interface{}) *QemuStorages { } type qemuUpdateChanges struct { - Move []qemuDiskShort - Delete string - MigrationImpossible bool + Move []qemuDiskShort + Delete string } diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index dda47127..5445f090 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -132,9 +132,6 @@ func (storage QemuIdeStorage) mapToApiValues(create bool) string { // TODO write test func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { if storage == nil { - if currentStorage != nil { - changes.Delete = AddToList(changes.Delete, id) - } return } // CDROM @@ -187,7 +184,6 @@ func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, i // Passthrough if storage.Passthrough != nil { // Create or Update - changes.MigrationImpossible = true params[id] = storage.Passthrough.mapToApiValues() return } else if currentStorage != nil && currentStorage.Passthrough != nil { @@ -195,6 +191,10 @@ func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, i changes.Delete = AddToList(changes.Delete, id) return } + // Delete if no subtype was specified + if currentStorage != nil { + changes.Delete = AddToList(changes.Delete, id) + } } // TODO write test diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index e28d7459..bf1f8642 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -144,9 +144,6 @@ func (storage QemuSataStorage) mapToApiValues(create bool) string { // TODO write test func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { if storage == nil { - if currentStorage != nil { - changes.Delete = AddToList(changes.Delete, id) - } return } // CDROM @@ -199,7 +196,6 @@ func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, // Passthrough if storage.Passthrough != nil { // Create or Update - changes.MigrationImpossible = true params[id] = storage.Passthrough.mapToApiValues() return } else if currentStorage != nil && currentStorage.Passthrough != nil { @@ -207,6 +203,10 @@ func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, changes.Delete = AddToList(changes.Delete, id) return } + // Delete if no subtype was specified + if currentStorage != nil { + changes.Delete = AddToList(changes.Delete, id) + } } // TODO write test diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 28d48598..8b2ff2d0 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -302,9 +302,6 @@ func (storage QemuScsiStorage) mapToApiValues(create bool) string { // TODO write test func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { if storage == nil { - if currentStorage != nil { - changes.Delete = AddToList(changes.Delete, id) - } return } // CDROM @@ -357,7 +354,6 @@ func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, // Passthrough if storage.Passthrough != nil { // Create or Update - changes.MigrationImpossible = true params[id] = storage.Passthrough.mapToApiValues() return } else if currentStorage != nil && currentStorage.Passthrough != nil { @@ -365,6 +361,10 @@ func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, changes.Delete = AddToList(changes.Delete, id) return } + // Delete if no subtype was specified + if currentStorage != nil { + changes.Delete = AddToList(changes.Delete, id) + } } // TODO write test diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index c448df05..3f1791b3 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -205,9 +205,6 @@ func (storage QemuVirtIOStorage) mapToApiValues(create bool) string { // TODO write test func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { if storage == nil { - if currentStorage != nil { - changes.Delete = AddToList(changes.Delete, id) - } return } // CDROM @@ -260,7 +257,6 @@ func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStor // Passthrough if storage.Passthrough != nil { // Create or Update - changes.MigrationImpossible = true params[id] = storage.Passthrough.mapToApiValues() return } else if currentStorage != nil && currentStorage.Passthrough != nil { @@ -268,6 +264,10 @@ func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStor changes.Delete = AddToList(changes.Delete, id) return } + // Delete if no subtype was specified + if currentStorage != nil { + changes.Delete = AddToList(changes.Delete, id) + } } // TODO write test From 92dd6f501302277f4dfaf8fdacb8672206cec667 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sat, 11 Mar 2023 20:41:31 +0000 Subject: [PATCH 030/120] feat: Make Size property read only --- proxmox/config_qemu_disk_ide.go | 3 +-- proxmox/config_qemu_disk_sata.go | 3 +-- proxmox/config_qemu_disk_scsi.go | 3 +-- proxmox/config_qemu_disk_virtio.go | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 5445f090..f7fab97d 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -85,7 +85,7 @@ type QemuIdePassthrough struct { File string Replicate bool Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint + Size uint //size is only returned and setting it has no effect } // TODO write test @@ -100,7 +100,6 @@ func (passthrough QemuIdePassthrough) mapToApiValues() string { File: passthrough.File, Replicate: passthrough.Replicate, Serial: passthrough.Serial, - Size: passthrough.Size, Type: ide, }.mapToApiValues(false) } diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index bf1f8642..494e4fad 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -97,7 +97,7 @@ type QemuSataPassthrough struct { File string Replicate bool Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint + Size uint //size is only returned and setting it has no effect } // TODO write test @@ -112,7 +112,6 @@ func (passthrough QemuSataPassthrough) mapToApiValues() string { File: passthrough.File, Replicate: passthrough.Replicate, Serial: passthrough.Serial, - Size: passthrough.Size, Type: sata, }.mapToApiValues(false) } diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 8b2ff2d0..38cb8e67 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -253,7 +253,7 @@ type QemuScsiPassthrough struct { ReadOnly bool Replicate bool Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint + Size uint //size is only returned and setting it has no effect } // TODO write test @@ -270,7 +270,6 @@ func (passthrough QemuScsiPassthrough) mapToApiValues() string { ReadOnly: passthrough.ReadOnly, Replicate: passthrough.Replicate, Serial: passthrough.Serial, - Size: passthrough.Size, Type: scsi, }.mapToApiValues(false) } diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 3f1791b3..0c2b515e 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -158,7 +158,7 @@ type QemuVirtIOPassthrough struct { IOThread bool ReadOnly bool Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint + Size uint //size is only returned and setting it has no effect } // TODO write test @@ -173,7 +173,6 @@ func (passthrough QemuVirtIOPassthrough) mapToApiValues() string { IOThread: passthrough.IOThread, ReadOnly: passthrough.ReadOnly, Serial: passthrough.Serial, - Size: passthrough.Size, Type: scsi, }.mapToApiValues(false) } From 00f46538d15a9b5278d57c928570054bf0e26682 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sat, 11 Mar 2023 21:32:00 +0000 Subject: [PATCH 031/120] refactor: Put in alphabetical order --- proxmox/config_qemu.go | 75 ++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 88b6158e..e9adb27d 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -35,56 +35,53 @@ type AgentNetworkInterface struct { // ConfigQemu - Proxmox API QEMU options type ConfigQemu struct { - VmID int `json:"vmid,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - Pool string `json:"pool,omitempty"` + Agent int `json:"agent,omitempty"` + Args string `json:"args,omitempty"` + Balloon int `json:"balloon,omitempty"` Bios string `json:"bios,omitempty"` + Boot string `json:"boot,omitempty"` + BootDisk string `json:"bootdisk,omitempty"` // Only returned as it's deprecated in the proxmox api + CIcustom string `json:"cicustom,omitempty"` // cloud-init option + CIpassword string `json:"cipassword,omitempty"` // cloud-init option + CIuser string `json:"ciuser,omitempty"` // cloud-init option + Description string `json:"description,omitempty"` + Disks *QemuStorages `json:"disks,omitempty"` EFIDisk QemuDevice `json:"efidisk,omitempty"` + FullClone *int `json:"fullclone,omitempty"` + HaGroup string `json:"hagroup,omitempty"` + HaState string `json:"hastate,omitempty"` + Hookscript string `json:"hookscript,omitempty"` + Hotplug string `json:"hotplug,omitempty"` + Ipconfig IpconfigMap `json:"ipconfig,omitempty"` // cloud-init option Machine string `json:"machine,omitempty"` - Onboot *bool `json:"onboot,omitempty"` - Startup string `json:"startup,omitempty"` - Tablet *bool `json:"tablet,omitempty"` - Agent int `json:"agent,omitempty"` Memory int `json:"memory,omitempty"` - Balloon int `json:"balloon,omitempty"` - QemuOs string `json:"ostype,omitempty"` + Name string `json:"name,omitempty"` + Nameserver string `json:"nameserver,omitempty"` // cloud-init option + Onboot *bool `json:"onboot,omitempty"` + Pool string `json:"pool,omitempty"` QemuCores int `json:"cores,omitempty"` - QemuSockets int `json:"sockets,omitempty"` - QemuVcpus int `json:"vcpus,omitempty"` QemuCpu string `json:"cpu,omitempty"` - QemuNuma *bool `json:"numa,omitempty"` - QemuKVM *bool `json:"kvm,omitempty"` - Hotplug string `json:"hotplug,omitempty"` - QemuIso string `json:"iso,omitempty"` - QemuPxe bool `json:"pxe,omitempty"` - FullClone *int `json:"fullclone,omitempty"` - Boot string `json:"boot,omitempty"` - BootDisk string `json:"bootdisk,omitempty"` // Only returned as it's deprecated in the proxmox api - Scsihw string `json:"scsihw,omitempty"` - Disks *QemuStorages `json:"disks,omitempty"` QemuDisks QemuDevices `json:"disk,omitempty"` // DEPRECATED use Disks *QemuStorages instead - QemuUnusedDisks QemuDevices `json:"unused,omitempty"` - QemuVga QemuDevice `json:"vga,omitempty"` + QemuIso string `json:"iso,omitempty"` + QemuKVM *bool `json:"kvm,omitempty"` QemuNetworks QemuDevices `json:"network,omitempty"` + QemuNuma *bool `json:"numa,omitempty"` + QemuOs string `json:"ostype,omitempty"` + QemuPCIDevices QemuDevices `json:"hostpci,omitempty"` + QemuPxe bool `json:"pxe,omitempty"` QemuSerials QemuDevices `json:"serial,omitempty"` + QemuSockets int `json:"sockets,omitempty"` + QemuUnusedDisks QemuDevices `json:"unused,omitempty"` QemuUsbs QemuDevices `json:"usb,omitempty"` - QemuPCIDevices QemuDevices `json:"hostpci,omitempty"` - Hookscript string `json:"hookscript,omitempty"` - HaState string `json:"hastate,omitempty"` - HaGroup string `json:"hagroup,omitempty"` + QemuVcpus int `json:"vcpus,omitempty"` + QemuVga QemuDevice `json:"vga,omitempty"` + Scsihw string `json:"scsihw,omitempty"` + Searchdomain string `json:"searchdomain,omitempty"` // cloud-init option + Sshkeys string `json:"sshkeys,omitempty"` + Startup string `json:"startup,omitempty"` + Tablet *bool `json:"tablet,omitempty"` Tags string `json:"tags,omitempty"` - Args string `json:"args,omitempty"` - - // cloud-init options - CIuser string `json:"ciuser,omitempty"` - CIpassword string `json:"cipassword,omitempty"` - CIcustom string `json:"cicustom,omitempty"` - Ipconfig IpconfigMap `json:"ipconfig,omitempty"` - - Searchdomain string `json:"searchdomain,omitempty"` - Nameserver string `json:"nameserver,omitempty"` - Sshkeys string `json:"sshkeys,omitempty"` + VmID int `json:"vmid,omitempty"` } // CreateVm - Tell Proxmox API to make the VM From 7c58c8075b93dc15c24a114cd666bdffdad997b4 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sat, 11 Mar 2023 21:47:06 +0000 Subject: [PATCH 032/120] Add TODO for future refactors --- proxmox/config_qemu.go | 68 +++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index e9adb27d..9b3e57c4 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -35,53 +35,53 @@ type AgentNetworkInterface struct { // ConfigQemu - Proxmox API QEMU options type ConfigQemu struct { - Agent int `json:"agent,omitempty"` + Agent int `json:"agent,omitempty"` // TODO should probably be a bool Args string `json:"args,omitempty"` - Balloon int `json:"balloon,omitempty"` + Balloon int `json:"balloon,omitempty"` // TODO should probably be a bool Bios string `json:"bios,omitempty"` - Boot string `json:"boot,omitempty"` + Boot string `json:"boot,omitempty"` // TODO should be an array of custom enums BootDisk string `json:"bootdisk,omitempty"` // Only returned as it's deprecated in the proxmox api - CIcustom string `json:"cicustom,omitempty"` // cloud-init option - CIpassword string `json:"cipassword,omitempty"` // cloud-init option - CIuser string `json:"ciuser,omitempty"` // cloud-init option + CIcustom string `json:"cicustom,omitempty"` // TODO should be part of a cloud-init struct (cloud-init option) + CIpassword string `json:"cipassword,omitempty"` // TODO should be part of a cloud-init struct (cloud-init option) + CIuser string `json:"ciuser,omitempty"` // TODO should be part of a cloud-init struct (cloud-init option) Description string `json:"description,omitempty"` Disks *QemuStorages `json:"disks,omitempty"` - EFIDisk QemuDevice `json:"efidisk,omitempty"` - FullClone *int `json:"fullclone,omitempty"` + EFIDisk QemuDevice `json:"efidisk,omitempty"` // TODO should be a struct + FullClone *int `json:"fullclone,omitempty"` // TODO should probably be a bool HaGroup string `json:"hagroup,omitempty"` - HaState string `json:"hastate,omitempty"` + HaState string `json:"hastate,omitempty"` // TODO should be custom type with enum Hookscript string `json:"hookscript,omitempty"` - Hotplug string `json:"hotplug,omitempty"` - Ipconfig IpconfigMap `json:"ipconfig,omitempty"` // cloud-init option - Machine string `json:"machine,omitempty"` - Memory int `json:"memory,omitempty"` - Name string `json:"name,omitempty"` - Nameserver string `json:"nameserver,omitempty"` // cloud-init option + Hotplug string `json:"hotplug,omitempty"` // TODO should be a struct + Ipconfig IpconfigMap `json:"ipconfig,omitempty"` // TODO should be part of a cloud-init struct (cloud-init option) + Machine string `json:"machine,omitempty"` // TODO should be custom type with enum + Memory int `json:"memory,omitempty"` // TODO should be uint + Name string `json:"name,omitempty"` // TODO should be custom type as there are character and length limitations + Nameserver string `json:"nameserver,omitempty"` // TODO should be part of a cloud-init struct (cloud-init option) Onboot *bool `json:"onboot,omitempty"` - Pool string `json:"pool,omitempty"` - QemuCores int `json:"cores,omitempty"` - QemuCpu string `json:"cpu,omitempty"` - QemuDisks QemuDevices `json:"disk,omitempty"` // DEPRECATED use Disks *QemuStorages instead - QemuIso string `json:"iso,omitempty"` + Pool string `json:"pool,omitempty"` // TODO should be custom type as there are character and length limitations + QemuCores int `json:"cores,omitempty"` // TODO should be uint + QemuCpu string `json:"cpu,omitempty"` // TODO should be custom type with enum + QemuDisks QemuDevices `json:"disk,omitempty"` // DEPRECATED use Disks *QemuStorages instead + QemuIso string `json:"iso,omitempty"` // TODO should be a struct QemuKVM *bool `json:"kvm,omitempty"` - QemuNetworks QemuDevices `json:"network,omitempty"` + QemuNetworks QemuDevices `json:"network,omitempty"` // TODO should be a struct QemuNuma *bool `json:"numa,omitempty"` QemuOs string `json:"ostype,omitempty"` - QemuPCIDevices QemuDevices `json:"hostpci,omitempty"` + QemuPCIDevices QemuDevices `json:"hostpci,omitempty"` // TODO should be a struct QemuPxe bool `json:"pxe,omitempty"` - QemuSerials QemuDevices `json:"serial,omitempty"` - QemuSockets int `json:"sockets,omitempty"` - QemuUnusedDisks QemuDevices `json:"unused,omitempty"` - QemuUsbs QemuDevices `json:"usb,omitempty"` - QemuVcpus int `json:"vcpus,omitempty"` - QemuVga QemuDevice `json:"vga,omitempty"` - Scsihw string `json:"scsihw,omitempty"` - Searchdomain string `json:"searchdomain,omitempty"` // cloud-init option - Sshkeys string `json:"sshkeys,omitempty"` - Startup string `json:"startup,omitempty"` + QemuSerials QemuDevices `json:"serial,omitempty"` // TODO should be a struct + QemuSockets int `json:"sockets,omitempty"` // TODO should be uint + QemuUnusedDisks QemuDevices `json:"unused,omitempty"` // TODO should be a struct + QemuUsbs QemuDevices `json:"usb,omitempty"` // TODO should be a struct + QemuVcpus int `json:"vcpus,omitempty"` // TODO should be uint + QemuVga QemuDevice `json:"vga,omitempty"` // TODO should be a struct + Scsihw string `json:"scsihw,omitempty"` // TODO should be custom type with enum + Searchdomain string `json:"searchdomain,omitempty"` // TODO should be part of a cloud-init struct (cloud-init option) + Sshkeys string `json:"sshkeys,omitempty"` // TODO should be an array of strings + Startup string `json:"startup,omitempty"` // TODO should be a struct? Tablet *bool `json:"tablet,omitempty"` - Tags string `json:"tags,omitempty"` - VmID int `json:"vmid,omitempty"` + Tags string `json:"tags,omitempty"` // TODO should be an array of a custom type as there are character and length limitations + VmID int `json:"vmid,omitempty"` // TODO should be a custom type as there are limitations } // CreateVm - Tell Proxmox API to make the VM From 309c17980540e818786d4b2fd541910d782f68e4 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sat, 11 Mar 2023 22:17:40 +0000 Subject: [PATCH 033/120] refactor: QemuDiskBandwidth struct --- proxmox/config_qemu_disk.go | 68 +++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 055200ca..2b88a1ba 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -172,34 +172,34 @@ func (disk qemuDisk) mapToApiValues(create bool) (settings string) { // format // media - if disk.Bandwidth.ReadLimit_Iops.Concurrent >= 10 { - settings = settings + ",iops_rd=" + strconv.Itoa(int(disk.Bandwidth.ReadLimit_Iops.Concurrent)) + if disk.Bandwidth.Iops.ReadLimit.Concurrent >= 10 { + settings = settings + ",iops_rd=" + strconv.Itoa(int(disk.Bandwidth.Iops.ReadLimit.Concurrent)) } - if disk.Bandwidth.ReadLimit_Iops.Burst >= 10 { - settings = settings + ",iops_rd_max=" + strconv.Itoa(int(disk.Bandwidth.ReadLimit_Iops.Burst)) + if disk.Bandwidth.Iops.ReadLimit.Burst >= 10 { + settings = settings + ",iops_rd_max=" + strconv.Itoa(int(disk.Bandwidth.Iops.ReadLimit.Burst)) } - if disk.Bandwidth.WriteLimit_Iops.Concurrent >= 10 { - settings = settings + ",iops_wr=" + strconv.Itoa(int(disk.Bandwidth.WriteLimit_Iops.Concurrent)) + if disk.Bandwidth.Iops.WriteLimit.Concurrent >= 10 { + settings = settings + ",iops_wr=" + strconv.Itoa(int(disk.Bandwidth.Iops.WriteLimit.Concurrent)) } - if disk.Bandwidth.WriteLimit_Iops.Burst >= 10 { - settings = settings + ",iops_wr_max=" + strconv.Itoa(int(disk.Bandwidth.WriteLimit_Iops.Burst)) + if disk.Bandwidth.Iops.WriteLimit.Burst >= 10 { + settings = settings + ",iops_wr_max=" + strconv.Itoa(int(disk.Bandwidth.Iops.WriteLimit.Burst)) } if (disk.Type == scsi || disk.Type == virtIO) && disk.IOThread { settings = settings + ",iothread=1" } - if disk.Bandwidth.ReadLimit_Data.Concurrent >= float32(1) { - settings = settings + fmt.Sprintf(",mbps_rd=%.2f", disk.Bandwidth.ReadLimit_Data.Concurrent) + if disk.Bandwidth.Data.ReadLimit.Concurrent >= float32(1) { + settings = settings + fmt.Sprintf(",mbps_rd=%.2f", disk.Bandwidth.Data.ReadLimit.Concurrent) } - if disk.Bandwidth.ReadLimit_Data.Burst >= float32(1) { - settings = settings + fmt.Sprintf(",mbps_rd_max=%.2f", disk.Bandwidth.ReadLimit_Data.Burst) + if disk.Bandwidth.Data.ReadLimit.Burst >= float32(1) { + settings = settings + fmt.Sprintf(",mbps_rd_max=%.2f", disk.Bandwidth.Data.ReadLimit.Burst) } - if disk.Bandwidth.WriteLimit_Data.Concurrent >= float32(1) { - settings = settings + fmt.Sprintf(",mbps_wr=%.2f", disk.Bandwidth.WriteLimit_Data.Concurrent) + if disk.Bandwidth.Data.WriteLimit.Concurrent >= float32(1) { + settings = settings + fmt.Sprintf(",mbps_wr=%.2f", disk.Bandwidth.Data.WriteLimit.Concurrent) } - if disk.Bandwidth.WriteLimit_Data.Burst >= float32(1) { - settings = settings + fmt.Sprintf(",mbps_wr_max=%.2f", disk.Bandwidth.WriteLimit_Data.Burst) + if disk.Bandwidth.Data.WriteLimit.Burst >= float32(1) { + settings = settings + fmt.Sprintf(",mbps_wr_max=%.2f", disk.Bandwidth.Data.WriteLimit.Burst) } if !disk.Replicate { @@ -264,19 +264,19 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { } if e[0] == "iops_rd" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.ReadLimit_Iops.Concurrent = uint(tmp) + disk.Bandwidth.Iops.ReadLimit.Concurrent = uint(tmp) } if e[0] == "iops_rd_max" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.ReadLimit_Iops.Burst = uint(tmp) + disk.Bandwidth.Iops.ReadLimit.Burst = uint(tmp) } if e[0] == "iops_wr" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.WriteLimit_Iops.Concurrent = uint(tmp) + disk.Bandwidth.Iops.WriteLimit.Concurrent = uint(tmp) } if e[0] == "iops_wr_max" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.WriteLimit_Iops.Burst = uint(tmp) + disk.Bandwidth.Iops.WriteLimit.Burst = uint(tmp) } if e[0] == "iothread" { disk.IOThread, _ = strconv.ParseBool(e[1]) @@ -284,19 +284,19 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { } if e[0] == "mbps_rd" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.ReadLimit_Data.Concurrent = float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.ReadLimit.Concurrent = float32(math.Round(tmp*100) / 100) } if e[0] == "mbps_rd_max" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.ReadLimit_Data.Burst = float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.ReadLimit.Burst = float32(math.Round(tmp*100) / 100) } if e[0] == "mbps_wr" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.WriteLimit_Data.Concurrent = float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.WriteLimit.Concurrent = float32(math.Round(tmp*100) / 100) } if e[0] == "mbps_wr_max" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.WriteLimit_Data.Burst = float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.WriteLimit.Burst = float32(math.Round(tmp*100) / 100) } if e[0] == "replicate" { disk.Replicate, _ = strconv.ParseBool(e[1]) @@ -339,18 +339,26 @@ func (asyncIO QemuDiskAsyncIO) Validate() error { } type QemuDiskBandwidth struct { - ReadLimit_Data QemuDisk_Bandwidth_Data - WriteLimit_Data QemuDisk_Bandwidth_Data - ReadLimit_Iops QemuDisk_Bandwidth_Iops - WriteLimit_Iops QemuDisk_Bandwidth_Iops + Data QemuDiskBandwidthData + Iops QemuDiskBandwidthIops } -type QemuDisk_Bandwidth_Data struct { +type QemuDiskBandwidthData struct { + ReadLimit QemuDiskBandwidthDataLimit + WriteLimit QemuDiskBandwidthDataLimit +} + +type QemuDiskBandwidthDataLimit struct { Concurrent float32 Burst float32 } -type QemuDisk_Bandwidth_Iops struct { +type QemuDiskBandwidthIops struct { + ReadLimit QemuDiskBandwidthIopsLimit + WriteLimit QemuDiskBandwidthIopsLimit +} + +type QemuDiskBandwidthIopsLimit struct { Concurrent uint Burst uint } From 1864a51c6ec388e9778de20f4bfd4fcc5019cef5 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 10:32:40 +0000 Subject: [PATCH 034/120] refactor: consolidate code for creating/updating disks --- proxmox/config_qemu_disk.go | 109 ++++++++++++++--- proxmox/config_qemu_disk_ide.go | 130 +++++++++----------- proxmox/config_qemu_disk_sata.go | 134 +++++++++----------- proxmox/config_qemu_disk_scsi.go | 189 +++++++++++++---------------- proxmox/config_qemu_disk_virtio.go | 155 +++++++++++------------ 5 files changed, 360 insertions(+), 357 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 2b88a1ba..f12a14c2 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -132,7 +132,7 @@ type qemuDisk struct { // TODO custom type File string // Only set for Passthrough. Format QemuDiskFormat - ID uint // Only set for Disk + Id uint // Only set for Disk IOThread bool // Only set for scsi,virtio Number uint ReadOnly bool // Only set for scsi,virtio @@ -145,9 +145,11 @@ type qemuDisk struct { } // TODO write test -func (disk qemuDisk) mapToApiValues(create bool) (settings string) { - if create { - if disk.Storage != "" { +func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { + if disk.Storage != "" { + if create { + settings = disk.Storage + ":" + strconv.Itoa(int(disk.Size)) + } else { settings = disk.Storage + ":" + strconv.Itoa(int(disk.Size)) } } @@ -237,7 +239,7 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { if len(idAndFormat) == 2 { tmp := strings.Split(idAndFormat[1], ".") tmpId, _ := strconv.Atoi(tmp[0]) - disk.ID = uint(tmpId) + disk.Id = uint(tmpId) if len(tmp) == 2 { disk.Format = QemuDiskFormat(tmp[1]) } @@ -430,6 +432,83 @@ const ( virtIO qemuDiskType = 3 ) +type qemuStorage struct { + CdRom *QemuCdRom `json:"cdrom,omitempty"` + CloudInit *QemuCloudInitDisk `json:"cloudinit,omitempty"` + Disk *qemuDisk `json:"disk,omitempty"` + Passthrough *qemuDisk `json:"passthrough,omitempty"` +} + +func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID uint, id string, params map[string]interface{}, changes *qemuUpdateChanges) { + if storage == nil { + return + } + // CDROM + if storage.CdRom != nil { + // Create or Update + params[id] = storage.CdRom.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.CdRom != nil { + // Delete + changes.Delete = AddToList(changes.Delete, id) + return + } + // CloudInit + if storage.CloudInit != nil { + // Create or Update + params[id] = storage.CloudInit.mapToApiValues() + return + } else if currentStorage != nil && currentStorage.CloudInit != nil { + // Delete + changes.Delete = AddToList(changes.Delete, id) + return + } + // Disk + if storage.Disk != nil { + if currentStorage == nil || currentStorage.Disk == nil { + // Create + params[id] = storage.Disk.mapToApiValues(vmID, true) + } else { + if storage.Disk.Size >= currentStorage.Disk.Size { + // Update + if storage.Disk.Id == 0 { + storage.Disk.Id = currentStorage.Disk.Id + } + if storage.Disk.Storage != currentStorage.Disk.Storage { + changes.Move = append(changes.Move, qemuDiskShort{ + Id: id, + Storage: storage.Disk.Storage, + }) + } + params[id] = storage.Disk.mapToApiValues(vmID, false) + } else { + // Delete and Create + changes.Delete = AddToList(changes.Delete, id) + params[id] = storage.Disk.mapToApiValues(vmID, true) + } + } + return + } else if currentStorage != nil && currentStorage.Disk != nil { + // Delete + changes.Delete = AddToList(changes.Delete, id) + return + } + // Passthrough + if storage.Passthrough != nil { + // Create or Update + params[id] = storage.Passthrough.mapToApiValues(0, false) + return + } else if currentStorage != nil && currentStorage.Passthrough != nil { + // Delete + changes.Delete = AddToList(changes.Delete, id) + return + } + // Delete if no subtype was specified + if currentStorage != nil { + changes.Delete = AddToList(changes.Delete, id) + } +} + type QemuStorages struct { Ide *QemuIdeDisks `json:"ide,omitempty"` Sata *QemuSataDisks `json:"sata,omitempty"` @@ -437,35 +516,35 @@ type QemuStorages struct { VirtIO *QemuVirtIODisks `json:"virtio,omitempty"` } -func (storages QemuStorages) markDiskChanges(currentStorages QemuStorages, params map[string]interface{}) *qemuUpdateChanges { +func (storages QemuStorages) markDiskChanges(currentStorages QemuStorages, vmID uint, params map[string]interface{}) *qemuUpdateChanges { changes := &qemuUpdateChanges{} if currentStorages.Ide != nil { - storages.Ide.mapToApiValues(currentStorages.Ide, params, changes) + storages.Ide.mapToApiValues(currentStorages.Ide, vmID, params, changes) } if currentStorages.Sata != nil { - storages.Sata.mapToApiValues(currentStorages.Sata, params, changes) + storages.Sata.mapToApiValues(currentStorages.Sata, vmID, params, changes) } if currentStorages.Scsi != nil { - storages.Scsi.mapToApiValues(currentStorages.Scsi, params, changes) + storages.Scsi.mapToApiValues(currentStorages.Scsi, vmID, params, changes) } if currentStorages.VirtIO != nil { - storages.VirtIO.mapToApiValues(currentStorages.VirtIO, params, changes) + storages.VirtIO.mapToApiValues(currentStorages.VirtIO, vmID, params, changes) } return changes } -func (storages QemuStorages) mapToApiValues(params map[string]interface{}) { +func (storages QemuStorages) mapToApiValues(vmID uint, params map[string]interface{}) { if storages.Ide != nil { - storages.Ide.mapToApiValues(nil, params, nil) + storages.Ide.mapToApiValues(nil, vmID, params, nil) } if storages.Sata != nil { - storages.Sata.mapToApiValues(nil, params, nil) + storages.Sata.mapToApiValues(nil, vmID, params, nil) } if storages.Scsi != nil { - storages.Scsi.mapToApiValues(nil, params, nil) + storages.Scsi.mapToApiValues(nil, vmID, params, nil) } if storages.VirtIO != nil { - storages.VirtIO.mapToApiValues(nil, params, nil) + storages.VirtIO.mapToApiValues(nil, vmID, params, nil) } } diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index f7fab97d..d4c1304e 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -7,6 +7,7 @@ type QemuIdeDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` + Id uint `json:"id,omitempty"` Replicate bool `json:"replicate,omitempty"` Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size,omitempty"` @@ -14,7 +15,7 @@ type QemuIdeDisk struct { } // TODO write test -func (disk QemuIdeDisk) mapToApiValues(create bool) string { +func (disk QemuIdeDisk) mapToApiValues(vmID uint, create bool) string { return qemuDisk{ AsyncIO: disk.AsyncIO, Backup: disk.Backup, @@ -27,7 +28,7 @@ func (disk QemuIdeDisk) mapToApiValues(create bool) string { Size: disk.Size, Storage: disk.Storage, Type: ide, - }.mapToApiValues(create) + }.mapToApiValues(vmID, create) } type QemuIdeDisks struct { @@ -38,15 +39,15 @@ type QemuIdeDisks struct { } // TODO write test -func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, params map[string]interface{}, changes *qemuUpdateChanges) { +func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, vmID uint, params map[string]interface{}, changes *qemuUpdateChanges) { tmpCurrentDisks := QemuIdeDisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, "ide0", params, changes) - disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, "ide1", params, changes) - disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, "ide2", params, changes) - disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, "ide3", params, changes) + disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, vmID, "ide0", params, changes) + disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, vmID, "ide1", params, changes) + disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, vmID, "ide2", params, changes) + disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, vmID, "ide3", params, changes) } // TODO write test @@ -101,7 +102,7 @@ func (passthrough QemuIdePassthrough) mapToApiValues() string { Replicate: passthrough.Replicate, Serial: passthrough.Serial, Type: ide, - }.mapToApiValues(false) + }.mapToApiValues(0, false) } type QemuIdeStorage struct { @@ -112,9 +113,50 @@ type QemuIdeStorage struct { } // TODO write test -func (storage QemuIdeStorage) mapToApiValues(create bool) string { +// converts to qemuStorage +func (storage *QemuIdeStorage) convertDataStructure() *qemuStorage { + if storage == nil { + return nil + } + generalizedStorage := qemuStorage{ + CdRom: storage.CdRom, + CloudInit: storage.CloudInit, + } if storage.Disk != nil { - return storage.Disk.mapToApiValues(create) + generalizedStorage.Disk = &qemuDisk{ + AsyncIO: storage.Disk.AsyncIO, + Backup: storage.Disk.Backup, + Bandwidth: storage.Disk.Bandwidth, + Cache: storage.Disk.Cache, + Discard: storage.Disk.Discard, + EmulateSSD: storage.Disk.EmulateSSD, + Id: storage.Disk.Id, + Replicate: storage.Disk.Replicate, + Serial: storage.Disk.Serial, + Size: storage.Disk.Size, + Storage: storage.Disk.Storage, + } + } + if storage.Passthrough != nil { + generalizedStorage.Passthrough = &qemuDisk{ + AsyncIO: storage.Passthrough.AsyncIO, + Backup: storage.Passthrough.Backup, + Bandwidth: storage.Passthrough.Bandwidth, + Cache: storage.Passthrough.Cache, + Discard: storage.Passthrough.Discard, + EmulateSSD: storage.Passthrough.EmulateSSD, + File: storage.Passthrough.File, + Replicate: storage.Passthrough.Replicate, + Serial: storage.Passthrough.Serial, + } + } + return &generalizedStorage +} + +// TODO write test +func (storage QemuIdeStorage) mapToApiValues(vmID uint, create bool) string { + if storage.Disk != nil { + return storage.Disk.mapToApiValues(vmID, create) } if storage.CdRom != nil { return storage.CdRom.mapToApiValues() @@ -129,71 +171,8 @@ func (storage QemuIdeStorage) mapToApiValues(create bool) string { } // TODO write test -func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { - if storage == nil { - return - } - // CDROM - if storage.CdRom != nil { - // Create or Update - params[id] = storage.CdRom.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.CdRom != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // CloudInit - if storage.CloudInit != nil { - // Create or Update - params[id] = storage.CloudInit.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.CloudInit != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // Disk - if storage.Disk != nil { - if currentStorage == nil || currentStorage.Disk == nil { - // Create - params[id] = storage.Disk.mapToApiValues(true) - } else { - if storage.Disk.Size >= currentStorage.Disk.Size { - // Update - if storage.Disk.Storage != currentStorage.Disk.Storage { - changes.Move = append(changes.Move, qemuDiskShort{ - Id: id, - Storage: storage.Disk.Storage, - }) - } - params[id] = storage.Disk.mapToApiValues(false) - } else { - // Delete and Create - changes.Delete = AddToList(changes.Delete, id) - params[id] = storage.Disk.mapToApiValues(true) - } - } - return - } else if currentStorage != nil && currentStorage.Disk != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // Passthrough - if storage.Passthrough != nil { - // Create or Update - params[id] = storage.Passthrough.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.Passthrough != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // Delete if no subtype was specified - if currentStorage != nil { - changes.Delete = AddToList(changes.Delete, id) - } +func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, vmID uint, id string, params map[string]interface{}, changes *qemuUpdateChanges) { + storage.convertDataStructure().markDiskChanges(currentStorage.convertDataStructure(), vmID, id, params, changes) } // TODO write test @@ -220,6 +199,7 @@ func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { Cache: tmpDisk.Cache, Discard: tmpDisk.Discard, EmulateSSD: tmpDisk.EmulateSSD, + Id: tmpDisk.Id, Replicate: tmpDisk.Replicate, Serial: tmpDisk.Serial, Size: tmpDisk.Size, diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 494e4fad..bbe8287d 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -7,6 +7,7 @@ type QemuSataDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` + Id uint `json:"id,omitempty"` Replicate bool `json:"replicate,omitempty"` Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size,omitempty"` @@ -14,7 +15,7 @@ type QemuSataDisk struct { } // TODO write test -func (disk QemuSataDisk) mapToApiValues(create bool) string { +func (disk QemuSataDisk) mapToApiValues(vmID uint, create bool) string { return qemuDisk{ AsyncIO: disk.AsyncIO, Backup: disk.Backup, @@ -27,7 +28,7 @@ func (disk QemuSataDisk) mapToApiValues(create bool) string { Size: disk.Size, Storage: disk.Storage, Type: sata, - }.mapToApiValues(create) + }.mapToApiValues(vmID, create) } type QemuSataDisks struct { @@ -40,17 +41,17 @@ type QemuSataDisks struct { } // TODO write test -func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, params map[string]interface{}, changes *qemuUpdateChanges) { +func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, vmID uint, params map[string]interface{}, changes *qemuUpdateChanges) { tmpCurrentDisks := QemuSataDisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, "sata0", params, changes) - disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, "sata1", params, changes) - disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, "sata2", params, changes) - disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, "sata3", params, changes) - disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, "sata4", params, changes) - disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, "sata5", params, changes) + disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, vmID, "sata0", params, changes) + disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, vmID, "sata1", params, changes) + disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, vmID, "sata2", params, changes) + disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, vmID, "sata3", params, changes) + disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, vmID, "sata4", params, changes) + disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, vmID, "sata5", params, changes) } // TODO write test @@ -113,7 +114,7 @@ func (passthrough QemuSataPassthrough) mapToApiValues() string { Replicate: passthrough.Replicate, Serial: passthrough.Serial, Type: sata, - }.mapToApiValues(false) + }.mapToApiValues(0, false) } type QemuSataStorage struct { @@ -124,9 +125,50 @@ type QemuSataStorage struct { } // TODO write test -func (storage QemuSataStorage) mapToApiValues(create bool) string { +// converts to qemuStorage +func (storage *QemuSataStorage) convertDataStructure() *qemuStorage { + if storage == nil { + return nil + } + generalizedStorage := qemuStorage{ + CdRom: storage.CdRom, + CloudInit: storage.CloudInit, + } if storage.Disk != nil { - return storage.Disk.mapToApiValues(create) + generalizedStorage.Disk = &qemuDisk{ + AsyncIO: storage.Disk.AsyncIO, + Backup: storage.Disk.Backup, + Bandwidth: storage.Disk.Bandwidth, + Cache: storage.Disk.Cache, + Discard: storage.Disk.Discard, + EmulateSSD: storage.Disk.EmulateSSD, + Id: storage.Disk.Id, + Replicate: storage.Disk.Replicate, + Serial: storage.Disk.Serial, + Size: storage.Disk.Size, + Storage: storage.Disk.Storage, + } + } + if storage.Passthrough != nil { + generalizedStorage.Passthrough = &qemuDisk{ + AsyncIO: storage.Passthrough.AsyncIO, + Backup: storage.Passthrough.Backup, + Bandwidth: storage.Passthrough.Bandwidth, + Cache: storage.Passthrough.Cache, + Discard: storage.Passthrough.Discard, + EmulateSSD: storage.Passthrough.EmulateSSD, + File: storage.Passthrough.File, + Replicate: storage.Passthrough.Replicate, + Serial: storage.Passthrough.Serial, + } + } + return &generalizedStorage +} + +// TODO write test +func (storage QemuSataStorage) mapToApiValues(vmID uint, create bool) string { + if storage.Disk != nil { + return storage.Disk.mapToApiValues(vmID, create) } if storage.CdRom != nil { return storage.CdRom.mapToApiValues() @@ -141,71 +183,8 @@ func (storage QemuSataStorage) mapToApiValues(create bool) string { } // TODO write test -func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { - if storage == nil { - return - } - // CDROM - if storage.CdRom != nil { - // Create or Update - params[id] = storage.CdRom.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.CdRom != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // CloudInit - if storage.CloudInit != nil { - // Create or Update - params[id] = storage.CloudInit.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.CloudInit != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // Disk - if storage.Disk != nil { - if currentStorage == nil || currentStorage.Disk == nil { - // Create - params[id] = storage.Disk.mapToApiValues(true) - } else { - if storage.Disk.Size >= currentStorage.Disk.Size { - // Update - if storage.Disk.Storage != currentStorage.Disk.Storage { - changes.Move = append(changes.Move, qemuDiskShort{ - Id: id, - Storage: storage.Disk.Storage, - }) - } - params[id] = storage.Disk.mapToApiValues(false) - } else { - // Delete and Create - changes.Delete = AddToList(changes.Delete, id) - params[id] = storage.Disk.mapToApiValues(true) - } - } - return - } else if currentStorage != nil && currentStorage.Disk != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // Passthrough - if storage.Passthrough != nil { - // Create or Update - params[id] = storage.Passthrough.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.Passthrough != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // Delete if no subtype was specified - if currentStorage != nil { - changes.Delete = AddToList(changes.Delete, id) - } +func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, vmID uint, id string, params map[string]interface{}, changes *qemuUpdateChanges) { + storage.convertDataStructure().markDiskChanges(currentStorage.convertDataStructure(), vmID, id, params, changes) } // TODO write test @@ -232,6 +211,7 @@ func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { Cache: tmpDisk.Cache, Discard: tmpDisk.Discard, EmulateSSD: tmpDisk.EmulateSSD, + Id: tmpDisk.Id, Replicate: tmpDisk.Replicate, Serial: tmpDisk.Serial, Size: tmpDisk.Size, diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 38cb8e67..05c202e4 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -7,6 +7,7 @@ type QemuScsiDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` + Id uint `json:"id,omitempty"` IOThread bool `json:"iothread,omitempty"` ReadOnly bool `json:"readonly,omitempty"` Replicate bool `json:"replicate,omitempty"` @@ -16,7 +17,7 @@ type QemuScsiDisk struct { } // TODO write test -func (disk QemuScsiDisk) mapToApiValues(create bool) string { +func (disk QemuScsiDisk) mapToApiValues(vmID uint, create bool) string { return qemuDisk{ AsyncIO: disk.AsyncIO, Backup: disk.Backup, @@ -31,7 +32,7 @@ func (disk QemuScsiDisk) mapToApiValues(create bool) string { Size: disk.Size, Storage: disk.Storage, Type: scsi, - }.mapToApiValues(create) + }.mapToApiValues(vmID, create) } type QemuScsiDisks struct { @@ -69,42 +70,42 @@ type QemuScsiDisks struct { } // TODO write test -func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, params map[string]interface{}, changes *qemuUpdateChanges) { +func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, vmID uint, params map[string]interface{}, changes *qemuUpdateChanges) { tmpCurrentDisks := QemuScsiDisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, "scsi0", params, changes) - disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, "scsi1", params, changes) - disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, "scsi2", params, changes) - disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, "scsi3", params, changes) - disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, "scsi4", params, changes) - disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, "scsi5", params, changes) - disks.Disk_6.markDiskChanges(tmpCurrentDisks.Disk_6, "scsi6", params, changes) - disks.Disk_7.markDiskChanges(tmpCurrentDisks.Disk_7, "scsi7", params, changes) - disks.Disk_8.markDiskChanges(tmpCurrentDisks.Disk_8, "scsi8", params, changes) - disks.Disk_9.markDiskChanges(tmpCurrentDisks.Disk_9, "scsi9", params, changes) - disks.Disk_10.markDiskChanges(tmpCurrentDisks.Disk_10, "scsi10", params, changes) - disks.Disk_11.markDiskChanges(tmpCurrentDisks.Disk_11, "scsi11", params, changes) - disks.Disk_12.markDiskChanges(tmpCurrentDisks.Disk_12, "scsi12", params, changes) - disks.Disk_13.markDiskChanges(tmpCurrentDisks.Disk_13, "scsi13", params, changes) - disks.Disk_14.markDiskChanges(tmpCurrentDisks.Disk_14, "scsi14", params, changes) - disks.Disk_15.markDiskChanges(tmpCurrentDisks.Disk_15, "scsi15", params, changes) - disks.Disk_16.markDiskChanges(tmpCurrentDisks.Disk_16, "scsi16", params, changes) - disks.Disk_17.markDiskChanges(tmpCurrentDisks.Disk_17, "scsi17", params, changes) - disks.Disk_18.markDiskChanges(tmpCurrentDisks.Disk_18, "scsi18", params, changes) - disks.Disk_19.markDiskChanges(tmpCurrentDisks.Disk_19, "scsi19", params, changes) - disks.Disk_20.markDiskChanges(tmpCurrentDisks.Disk_20, "scsi20", params, changes) - disks.Disk_21.markDiskChanges(tmpCurrentDisks.Disk_21, "scsi21", params, changes) - disks.Disk_22.markDiskChanges(tmpCurrentDisks.Disk_22, "scsi22", params, changes) - disks.Disk_23.markDiskChanges(tmpCurrentDisks.Disk_23, "scsi23", params, changes) - disks.Disk_24.markDiskChanges(tmpCurrentDisks.Disk_24, "scsi24", params, changes) - disks.Disk_25.markDiskChanges(tmpCurrentDisks.Disk_25, "scsi25", params, changes) - disks.Disk_26.markDiskChanges(tmpCurrentDisks.Disk_26, "scsi26", params, changes) - disks.Disk_27.markDiskChanges(tmpCurrentDisks.Disk_27, "scsi27", params, changes) - disks.Disk_28.markDiskChanges(tmpCurrentDisks.Disk_28, "scsi28", params, changes) - disks.Disk_29.markDiskChanges(tmpCurrentDisks.Disk_29, "scsi29", params, changes) - disks.Disk_30.markDiskChanges(tmpCurrentDisks.Disk_30, "scsi30", params, changes) + disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, vmID, "scsi0", params, changes) + disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, vmID, "scsi1", params, changes) + disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, vmID, "scsi2", params, changes) + disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, vmID, "scsi3", params, changes) + disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, vmID, "scsi4", params, changes) + disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, vmID, "scsi5", params, changes) + disks.Disk_6.markDiskChanges(tmpCurrentDisks.Disk_6, vmID, "scsi6", params, changes) + disks.Disk_7.markDiskChanges(tmpCurrentDisks.Disk_7, vmID, "scsi7", params, changes) + disks.Disk_8.markDiskChanges(tmpCurrentDisks.Disk_8, vmID, "scsi8", params, changes) + disks.Disk_9.markDiskChanges(tmpCurrentDisks.Disk_9, vmID, "scsi9", params, changes) + disks.Disk_10.markDiskChanges(tmpCurrentDisks.Disk_10, vmID, "scsi10", params, changes) + disks.Disk_11.markDiskChanges(tmpCurrentDisks.Disk_11, vmID, "scsi11", params, changes) + disks.Disk_12.markDiskChanges(tmpCurrentDisks.Disk_12, vmID, "scsi12", params, changes) + disks.Disk_13.markDiskChanges(tmpCurrentDisks.Disk_13, vmID, "scsi13", params, changes) + disks.Disk_14.markDiskChanges(tmpCurrentDisks.Disk_14, vmID, "scsi14", params, changes) + disks.Disk_15.markDiskChanges(tmpCurrentDisks.Disk_15, vmID, "scsi15", params, changes) + disks.Disk_16.markDiskChanges(tmpCurrentDisks.Disk_16, vmID, "scsi16", params, changes) + disks.Disk_17.markDiskChanges(tmpCurrentDisks.Disk_17, vmID, "scsi17", params, changes) + disks.Disk_18.markDiskChanges(tmpCurrentDisks.Disk_18, vmID, "scsi18", params, changes) + disks.Disk_19.markDiskChanges(tmpCurrentDisks.Disk_19, vmID, "scsi19", params, changes) + disks.Disk_20.markDiskChanges(tmpCurrentDisks.Disk_20, vmID, "scsi20", params, changes) + disks.Disk_21.markDiskChanges(tmpCurrentDisks.Disk_21, vmID, "scsi21", params, changes) + disks.Disk_22.markDiskChanges(tmpCurrentDisks.Disk_22, vmID, "scsi22", params, changes) + disks.Disk_23.markDiskChanges(tmpCurrentDisks.Disk_23, vmID, "scsi23", params, changes) + disks.Disk_24.markDiskChanges(tmpCurrentDisks.Disk_24, vmID, "scsi24", params, changes) + disks.Disk_25.markDiskChanges(tmpCurrentDisks.Disk_25, vmID, "scsi25", params, changes) + disks.Disk_26.markDiskChanges(tmpCurrentDisks.Disk_26, vmID, "scsi26", params, changes) + disks.Disk_27.markDiskChanges(tmpCurrentDisks.Disk_27, vmID, "scsi27", params, changes) + disks.Disk_28.markDiskChanges(tmpCurrentDisks.Disk_28, vmID, "scsi28", params, changes) + disks.Disk_29.markDiskChanges(tmpCurrentDisks.Disk_29, vmID, "scsi29", params, changes) + disks.Disk_30.markDiskChanges(tmpCurrentDisks.Disk_30, vmID, "scsi30", params, changes) } // TODO write test @@ -271,7 +272,7 @@ func (passthrough QemuScsiPassthrough) mapToApiValues() string { Replicate: passthrough.Replicate, Serial: passthrough.Serial, Type: scsi, - }.mapToApiValues(false) + }.mapToApiValues(0, false) } type QemuScsiStorage struct { @@ -282,9 +283,54 @@ type QemuScsiStorage struct { } // TODO write test -func (storage QemuScsiStorage) mapToApiValues(create bool) string { +// converts to qemuStorage +func (storage *QemuScsiStorage) convertDataStructure() *qemuStorage { + if storage == nil { + return nil + } + generalizedStorage := qemuStorage{ + CdRom: storage.CdRom, + CloudInit: storage.CloudInit, + } + if storage.Disk != nil { + generalizedStorage.Disk = &qemuDisk{ + AsyncIO: storage.Disk.AsyncIO, + Backup: storage.Disk.Backup, + Bandwidth: storage.Disk.Bandwidth, + Cache: storage.Disk.Cache, + Discard: storage.Disk.Discard, + EmulateSSD: storage.Disk.EmulateSSD, + Id: storage.Disk.Id, + IOThread: storage.Disk.IOThread, + ReadOnly: storage.Disk.ReadOnly, + Replicate: storage.Disk.Replicate, + Serial: storage.Disk.Serial, + Size: storage.Disk.Size, + Storage: storage.Disk.Storage, + } + } + if storage.Passthrough != nil { + generalizedStorage.Passthrough = &qemuDisk{ + AsyncIO: storage.Passthrough.AsyncIO, + Backup: storage.Passthrough.Backup, + Bandwidth: storage.Passthrough.Bandwidth, + Cache: storage.Passthrough.Cache, + Discard: storage.Passthrough.Discard, + EmulateSSD: storage.Passthrough.EmulateSSD, + File: storage.Passthrough.File, + IOThread: storage.Passthrough.IOThread, + ReadOnly: storage.Passthrough.ReadOnly, + Replicate: storage.Passthrough.Replicate, + Serial: storage.Passthrough.Serial, + } + } + return &generalizedStorage +} + +// TODO write test +func (storage QemuScsiStorage) mapToApiValues(vmID uint, create bool) string { if storage.Disk != nil { - return storage.Disk.mapToApiValues(create) + return storage.Disk.mapToApiValues(vmID, create) } if storage.CdRom != nil { return storage.CdRom.mapToApiValues() @@ -299,71 +345,8 @@ func (storage QemuScsiStorage) mapToApiValues(create bool) string { } // TODO write test -func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { - if storage == nil { - return - } - // CDROM - if storage.CdRom != nil { - // Create or Update - params[id] = storage.CdRom.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.CdRom != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // CloudInit - if storage.CloudInit != nil { - // Create or Update - params[id] = storage.CloudInit.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.CloudInit != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // Disk - if storage.Disk != nil { - if currentStorage == nil || currentStorage.Disk == nil { - // Create - params[id] = storage.Disk.mapToApiValues(true) - } else { - if storage.Disk.Size >= currentStorage.Disk.Size { - // Update - if storage.Disk.Storage != currentStorage.Disk.Storage { - changes.Move = append(changes.Move, qemuDiskShort{ - Id: id, - Storage: storage.Disk.Storage, - }) - } - params[id] = storage.Disk.mapToApiValues(false) - } else { - // Delete and Create - changes.Delete = AddToList(changes.Delete, id) - params[id] = storage.Disk.mapToApiValues(true) - } - } - return - } else if currentStorage != nil && currentStorage.Disk != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // Passthrough - if storage.Passthrough != nil { - // Create or Update - params[id] = storage.Passthrough.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.Passthrough != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // Delete if no subtype was specified - if currentStorage != nil { - changes.Delete = AddToList(changes.Delete, id) - } +func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, vmID uint, id string, params map[string]interface{}, changes *qemuUpdateChanges) { + storage.convertDataStructure().markDiskChanges(currentStorage.convertDataStructure(), vmID, id, params, changes) } // TODO write test @@ -390,6 +373,7 @@ func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { Cache: tmpDisk.Cache, Discard: tmpDisk.Discard, EmulateSSD: tmpDisk.EmulateSSD, + Id: tmpDisk.Id, IOThread: tmpDisk.IOThread, ReadOnly: tmpDisk.ReadOnly, Replicate: tmpDisk.Replicate, @@ -412,5 +396,4 @@ func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { Serial: tmpDisk.Serial, Size: tmpDisk.Size, }} - } diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 0c2b515e..97feb0e4 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -6,6 +6,7 @@ type QemuVirtIODisk struct { Bandwidth QemuDiskBandwidth `json:"bandwith,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` + Id uint `json:"id,omitempty"` IOThread bool `json:"iothread,omitempty"` ReadOnly bool `json:"readonly,omitempty"` Replicate bool `json:"replicate,omitempty"` @@ -15,7 +16,7 @@ type QemuVirtIODisk struct { } // TODO write test -func (disk QemuVirtIODisk) mapToApiValues(create bool) string { +func (disk QemuVirtIODisk) mapToApiValues(vmID uint, create bool) string { return qemuDisk{ AsyncIO: disk.AsyncIO, Backup: disk.Backup, @@ -28,7 +29,7 @@ func (disk QemuVirtIODisk) mapToApiValues(create bool) string { Size: disk.Size, Storage: disk.Storage, Type: virtIO, - }.mapToApiValues(create) + }.mapToApiValues(vmID, create) } type QemuVirtIODisks struct { @@ -51,27 +52,27 @@ type QemuVirtIODisks struct { } // TODO write test -func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, params map[string]interface{}, changes *qemuUpdateChanges) { +func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, vmID uint, params map[string]interface{}, changes *qemuUpdateChanges) { tmpCurrentDisks := QemuVirtIODisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, "virtio0", params, changes) - disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, "virtio1", params, changes) - disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, "virtio2", params, changes) - disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, "virtio3", params, changes) - disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, "virtio4", params, changes) - disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, "virtio5", params, changes) - disks.Disk_6.markDiskChanges(tmpCurrentDisks.Disk_6, "virtio6", params, changes) - disks.Disk_7.markDiskChanges(tmpCurrentDisks.Disk_7, "virtio7", params, changes) - disks.Disk_8.markDiskChanges(tmpCurrentDisks.Disk_8, "virtio8", params, changes) - disks.Disk_9.markDiskChanges(tmpCurrentDisks.Disk_9, "virtio9", params, changes) - disks.Disk_10.markDiskChanges(tmpCurrentDisks.Disk_10, "virtio10", params, changes) - disks.Disk_11.markDiskChanges(tmpCurrentDisks.Disk_11, "virtio11", params, changes) - disks.Disk_12.markDiskChanges(tmpCurrentDisks.Disk_12, "virtio12", params, changes) - disks.Disk_13.markDiskChanges(tmpCurrentDisks.Disk_13, "virtio13", params, changes) - disks.Disk_14.markDiskChanges(tmpCurrentDisks.Disk_14, "virtio14", params, changes) - disks.Disk_15.markDiskChanges(tmpCurrentDisks.Disk_15, "virtio15", params, changes) + disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, vmID, "virtio0", params, changes) + disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, vmID, "virtio1", params, changes) + disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, vmID, "virtio2", params, changes) + disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, vmID, "virtio3", params, changes) + disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, vmID, "virtio4", params, changes) + disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, vmID, "virtio5", params, changes) + disks.Disk_6.markDiskChanges(tmpCurrentDisks.Disk_6, vmID, "virtio6", params, changes) + disks.Disk_7.markDiskChanges(tmpCurrentDisks.Disk_7, vmID, "virtio7", params, changes) + disks.Disk_8.markDiskChanges(tmpCurrentDisks.Disk_8, vmID, "virtio8", params, changes) + disks.Disk_9.markDiskChanges(tmpCurrentDisks.Disk_9, vmID, "virtio9", params, changes) + disks.Disk_10.markDiskChanges(tmpCurrentDisks.Disk_10, vmID, "virtio10", params, changes) + disks.Disk_11.markDiskChanges(tmpCurrentDisks.Disk_11, vmID, "virtio11", params, changes) + disks.Disk_12.markDiskChanges(tmpCurrentDisks.Disk_12, vmID, "virtio12", params, changes) + disks.Disk_13.markDiskChanges(tmpCurrentDisks.Disk_13, vmID, "virtio13", params, changes) + disks.Disk_14.markDiskChanges(tmpCurrentDisks.Disk_14, vmID, "virtio14", params, changes) + disks.Disk_15.markDiskChanges(tmpCurrentDisks.Disk_15, vmID, "virtio15", params, changes) } // TODO write test @@ -174,7 +175,7 @@ func (passthrough QemuVirtIOPassthrough) mapToApiValues() string { ReadOnly: passthrough.ReadOnly, Serial: passthrough.Serial, Type: scsi, - }.mapToApiValues(false) + }.mapToApiValues(0, false) } type QemuVirtIOStorage struct { @@ -185,88 +186,67 @@ type QemuVirtIOStorage struct { } // TODO write test -func (storage QemuVirtIOStorage) mapToApiValues(create bool) string { - if storage.Disk != nil { - return storage.Disk.mapToApiValues(create) +// converts to qemuStorage +func (storage *QemuVirtIOStorage) convertDataStructure() *qemuStorage { + if storage == nil { + return nil } - if storage.CdRom != nil { - return storage.CdRom.mapToApiValues() + generalizedStorage := qemuStorage{ + CdRom: storage.CdRom, + CloudInit: storage.CloudInit, } - if storage.CloudInit != nil { - return storage.CloudInit.mapToApiValues() + if storage.Disk != nil { + generalizedStorage.Disk = &qemuDisk{ + AsyncIO: storage.Disk.AsyncIO, + Backup: storage.Disk.Backup, + Bandwidth: storage.Disk.Bandwidth, + Cache: storage.Disk.Cache, + Discard: storage.Disk.Discard, + Id: storage.Disk.Id, + IOThread: storage.Disk.IOThread, + ReadOnly: storage.Disk.ReadOnly, + Replicate: storage.Disk.Replicate, + Serial: storage.Disk.Serial, + Size: storage.Disk.Size, + Storage: storage.Disk.Storage, + } } if storage.Passthrough != nil { - return storage.Passthrough.mapToApiValues() + generalizedStorage.Passthrough = &qemuDisk{ + AsyncIO: storage.Passthrough.AsyncIO, + Backup: storage.Passthrough.Backup, + Bandwidth: storage.Passthrough.Bandwidth, + Cache: storage.Passthrough.Cache, + Discard: storage.Passthrough.Discard, + File: storage.Passthrough.File, + IOThread: storage.Passthrough.IOThread, + ReadOnly: storage.Passthrough.ReadOnly, + Serial: storage.Passthrough.Serial, + } } - return "" + return &generalizedStorage } // TODO write test -func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStorage, id string, params map[string]interface{}, changes *qemuUpdateChanges) { - if storage == nil { - return +func (storage QemuVirtIOStorage) mapToApiValues(vmID uint, create bool) string { + if storage.Disk != nil { + return storage.Disk.mapToApiValues(vmID, create) } - // CDROM if storage.CdRom != nil { - // Create or Update - params[id] = storage.CdRom.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.CdRom != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return + return storage.CdRom.mapToApiValues() } - // CloudInit if storage.CloudInit != nil { - // Create or Update - params[id] = storage.CloudInit.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.CloudInit != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // Disk - if storage.Disk != nil { - if currentStorage == nil || currentStorage.Disk == nil { - // Create - params[id] = storage.Disk.mapToApiValues(true) - } else { - if storage.Disk.Size >= currentStorage.Disk.Size { - // Update - if storage.Disk.Storage != currentStorage.Disk.Storage { - changes.Move = append(changes.Move, qemuDiskShort{ - Id: id, - Storage: storage.Disk.Storage, - }) - } - params[id] = storage.Disk.mapToApiValues(false) - } else { - // Delete and Create - changes.Delete = AddToList(changes.Delete, id) - params[id] = storage.Disk.mapToApiValues(true) - } - } - return - } else if currentStorage != nil && currentStorage.Disk != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return + return storage.CloudInit.mapToApiValues() } - // Passthrough if storage.Passthrough != nil { - // Create or Update - params[id] = storage.Passthrough.mapToApiValues() - return - } else if currentStorage != nil && currentStorage.Passthrough != nil { - // Delete - changes.Delete = AddToList(changes.Delete, id) - return - } - // Delete if no subtype was specified - if currentStorage != nil { - changes.Delete = AddToList(changes.Delete, id) + return storage.Passthrough.mapToApiValues() } + return "" +} + +// TODO write test +func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStorage, vmID uint, id string, params map[string]interface{}, changes *qemuUpdateChanges) { + storage.convertDataStructure().markDiskChanges(currentStorage.convertDataStructure(), vmID, id, params, changes) } // TODO write test @@ -292,6 +272,7 @@ func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { Bandwidth: tmpDisk.Bandwidth, Cache: tmpDisk.Cache, Discard: tmpDisk.Discard, + Id: tmpDisk.Id, IOThread: tmpDisk.IOThread, ReadOnly: tmpDisk.ReadOnly, Replicate: tmpDisk.Replicate, From d338e78a2991dd00fcec97805cc3f0a19b9a4952 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 10:33:39 +0000 Subject: [PATCH 035/120] fix: decoding of disk id --- proxmox/config_qemu_disk.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index f12a14c2..afd4fd2c 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -235,13 +235,13 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { diskAndNumberAndFormat := strings.Split(settings[0][0], ":") disk.Storage = diskAndNumberAndFormat[0] if len(diskAndNumberAndFormat) == 2 { - idAndFormat := strings.Split(diskAndNumberAndFormat[1], "-") + idAndFormat := strings.Split(diskAndNumberAndFormat[1], ".") if len(idAndFormat) == 2 { - tmp := strings.Split(idAndFormat[1], ".") - tmpId, _ := strconv.Atoi(tmp[0]) - disk.Id = uint(tmpId) - if len(tmp) == 2 { - disk.Format = QemuDiskFormat(tmp[1]) + disk.Format = QemuDiskFormat(idAndFormat[1]) + tmp := strings.Split(idAndFormat[0], "-") + if len(tmp) > 1 { + tmpId, _ := strconv.Atoi(tmp[len(tmp)-1]) + disk.Id = uint(tmpId) } } } From 1d567af29bd15581386e7274d735e587a9ec1504 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 10:46:50 +0000 Subject: [PATCH 036/120] refactor: remove unnecessary function --- proxmox/config_qemu_disk_ide.go | 13 ++---- proxmox/config_qemu_disk_sata.go | 17 +++----- proxmox/config_qemu_disk_scsi.go | 67 ++++++++++++++---------------- proxmox/config_qemu_disk_virtio.go | 37 +++++++---------- 4 files changed, 57 insertions(+), 77 deletions(-) diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index d4c1304e..9e1aefad 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -44,10 +44,10 @@ func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, vmID uint, if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, vmID, "ide0", params, changes) - disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, vmID, "ide1", params, changes) - disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, vmID, "ide2", params, changes) - disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, vmID, "ide3", params, changes) + disks.Disk_0.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_0.convertDataStructure(), vmID, "ide0", params, changes) + disks.Disk_1.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_1.convertDataStructure(), vmID, "ide1", params, changes) + disks.Disk_2.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_2.convertDataStructure(), vmID, "ide2", params, changes) + disks.Disk_3.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_3.convertDataStructure(), vmID, "ide3", params, changes) } // TODO write test @@ -170,11 +170,6 @@ func (storage QemuIdeStorage) mapToApiValues(vmID uint, create bool) string { return "" } -// TODO write test -func (storage *QemuIdeStorage) markDiskChanges(currentStorage *QemuIdeStorage, vmID uint, id string, params map[string]interface{}, changes *qemuUpdateChanges) { - storage.convertDataStructure().markDiskChanges(currentStorage.convertDataStructure(), vmID, id, params, changes) -} - // TODO write test func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { settings := splitStringOfSettings(param) diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index bbe8287d..bb640026 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -46,12 +46,12 @@ func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, vmID uint if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, vmID, "sata0", params, changes) - disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, vmID, "sata1", params, changes) - disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, vmID, "sata2", params, changes) - disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, vmID, "sata3", params, changes) - disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, vmID, "sata4", params, changes) - disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, vmID, "sata5", params, changes) + disks.Disk_0.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_0.convertDataStructure(), vmID, "sata0", params, changes) + disks.Disk_1.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_1.convertDataStructure(), vmID, "sata1", params, changes) + disks.Disk_2.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_2.convertDataStructure(), vmID, "sata2", params, changes) + disks.Disk_3.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_3.convertDataStructure(), vmID, "sata3", params, changes) + disks.Disk_4.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_4.convertDataStructure(), vmID, "sata4", params, changes) + disks.Disk_5.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_5.convertDataStructure(), vmID, "sata5", params, changes) } // TODO write test @@ -182,11 +182,6 @@ func (storage QemuSataStorage) mapToApiValues(vmID uint, create bool) string { return "" } -// TODO write test -func (storage *QemuSataStorage) markDiskChanges(currentStorage *QemuSataStorage, vmID uint, id string, params map[string]interface{}, changes *qemuUpdateChanges) { - storage.convertDataStructure().markDiskChanges(currentStorage.convertDataStructure(), vmID, id, params, changes) -} - // TODO write test func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { settings := splitStringOfSettings(param) diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 05c202e4..af094d72 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -75,37 +75,37 @@ func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, vmID uint if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, vmID, "scsi0", params, changes) - disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, vmID, "scsi1", params, changes) - disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, vmID, "scsi2", params, changes) - disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, vmID, "scsi3", params, changes) - disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, vmID, "scsi4", params, changes) - disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, vmID, "scsi5", params, changes) - disks.Disk_6.markDiskChanges(tmpCurrentDisks.Disk_6, vmID, "scsi6", params, changes) - disks.Disk_7.markDiskChanges(tmpCurrentDisks.Disk_7, vmID, "scsi7", params, changes) - disks.Disk_8.markDiskChanges(tmpCurrentDisks.Disk_8, vmID, "scsi8", params, changes) - disks.Disk_9.markDiskChanges(tmpCurrentDisks.Disk_9, vmID, "scsi9", params, changes) - disks.Disk_10.markDiskChanges(tmpCurrentDisks.Disk_10, vmID, "scsi10", params, changes) - disks.Disk_11.markDiskChanges(tmpCurrentDisks.Disk_11, vmID, "scsi11", params, changes) - disks.Disk_12.markDiskChanges(tmpCurrentDisks.Disk_12, vmID, "scsi12", params, changes) - disks.Disk_13.markDiskChanges(tmpCurrentDisks.Disk_13, vmID, "scsi13", params, changes) - disks.Disk_14.markDiskChanges(tmpCurrentDisks.Disk_14, vmID, "scsi14", params, changes) - disks.Disk_15.markDiskChanges(tmpCurrentDisks.Disk_15, vmID, "scsi15", params, changes) - disks.Disk_16.markDiskChanges(tmpCurrentDisks.Disk_16, vmID, "scsi16", params, changes) - disks.Disk_17.markDiskChanges(tmpCurrentDisks.Disk_17, vmID, "scsi17", params, changes) - disks.Disk_18.markDiskChanges(tmpCurrentDisks.Disk_18, vmID, "scsi18", params, changes) - disks.Disk_19.markDiskChanges(tmpCurrentDisks.Disk_19, vmID, "scsi19", params, changes) - disks.Disk_20.markDiskChanges(tmpCurrentDisks.Disk_20, vmID, "scsi20", params, changes) - disks.Disk_21.markDiskChanges(tmpCurrentDisks.Disk_21, vmID, "scsi21", params, changes) - disks.Disk_22.markDiskChanges(tmpCurrentDisks.Disk_22, vmID, "scsi22", params, changes) - disks.Disk_23.markDiskChanges(tmpCurrentDisks.Disk_23, vmID, "scsi23", params, changes) - disks.Disk_24.markDiskChanges(tmpCurrentDisks.Disk_24, vmID, "scsi24", params, changes) - disks.Disk_25.markDiskChanges(tmpCurrentDisks.Disk_25, vmID, "scsi25", params, changes) - disks.Disk_26.markDiskChanges(tmpCurrentDisks.Disk_26, vmID, "scsi26", params, changes) - disks.Disk_27.markDiskChanges(tmpCurrentDisks.Disk_27, vmID, "scsi27", params, changes) - disks.Disk_28.markDiskChanges(tmpCurrentDisks.Disk_28, vmID, "scsi28", params, changes) - disks.Disk_29.markDiskChanges(tmpCurrentDisks.Disk_29, vmID, "scsi29", params, changes) - disks.Disk_30.markDiskChanges(tmpCurrentDisks.Disk_30, vmID, "scsi30", params, changes) + disks.Disk_0.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_0.convertDataStructure(), vmID, "scsi0", params, changes) + disks.Disk_1.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_1.convertDataStructure(), vmID, "scsi1", params, changes) + disks.Disk_2.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_2.convertDataStructure(), vmID, "scsi2", params, changes) + disks.Disk_3.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_3.convertDataStructure(), vmID, "scsi3", params, changes) + disks.Disk_4.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_4.convertDataStructure(), vmID, "scsi4", params, changes) + disks.Disk_5.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_5.convertDataStructure(), vmID, "scsi5", params, changes) + disks.Disk_6.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_6.convertDataStructure(), vmID, "scsi6", params, changes) + disks.Disk_7.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_7.convertDataStructure(), vmID, "scsi7", params, changes) + disks.Disk_8.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_8.convertDataStructure(), vmID, "scsi8", params, changes) + disks.Disk_9.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_9.convertDataStructure(), vmID, "scsi9", params, changes) + disks.Disk_10.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_10.convertDataStructure(), vmID, "scsi10", params, changes) + disks.Disk_11.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_11.convertDataStructure(), vmID, "scsi11", params, changes) + disks.Disk_12.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_12.convertDataStructure(), vmID, "scsi12", params, changes) + disks.Disk_13.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_13.convertDataStructure(), vmID, "scsi13", params, changes) + disks.Disk_14.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_14.convertDataStructure(), vmID, "scsi14", params, changes) + disks.Disk_15.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_15.convertDataStructure(), vmID, "scsi15", params, changes) + disks.Disk_16.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_16.convertDataStructure(), vmID, "scsi16", params, changes) + disks.Disk_17.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_17.convertDataStructure(), vmID, "scsi17", params, changes) + disks.Disk_18.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_18.convertDataStructure(), vmID, "scsi18", params, changes) + disks.Disk_19.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_19.convertDataStructure(), vmID, "scsi19", params, changes) + disks.Disk_20.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_20.convertDataStructure(), vmID, "scsi20", params, changes) + disks.Disk_21.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_21.convertDataStructure(), vmID, "scsi21", params, changes) + disks.Disk_22.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_22.convertDataStructure(), vmID, "scsi22", params, changes) + disks.Disk_23.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_23.convertDataStructure(), vmID, "scsi23", params, changes) + disks.Disk_24.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_24.convertDataStructure(), vmID, "scsi24", params, changes) + disks.Disk_25.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_25.convertDataStructure(), vmID, "scsi25", params, changes) + disks.Disk_26.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_26.convertDataStructure(), vmID, "scsi26", params, changes) + disks.Disk_27.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_27.convertDataStructure(), vmID, "scsi27", params, changes) + disks.Disk_28.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_28.convertDataStructure(), vmID, "scsi28", params, changes) + disks.Disk_29.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_29.convertDataStructure(), vmID, "scsi29", params, changes) + disks.Disk_30.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_30.convertDataStructure(), vmID, "scsi30", params, changes) } // TODO write test @@ -344,11 +344,6 @@ func (storage QemuScsiStorage) mapToApiValues(vmID uint, create bool) string { return "" } -// TODO write test -func (storage *QemuScsiStorage) markDiskChanges(currentStorage *QemuScsiStorage, vmID uint, id string, params map[string]interface{}, changes *qemuUpdateChanges) { - storage.convertDataStructure().markDiskChanges(currentStorage.convertDataStructure(), vmID, id, params, changes) -} - // TODO write test func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { settings := splitStringOfSettings(param) diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 97feb0e4..f61fab77 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -57,22 +57,22 @@ func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, vmID if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.markDiskChanges(tmpCurrentDisks.Disk_0, vmID, "virtio0", params, changes) - disks.Disk_1.markDiskChanges(tmpCurrentDisks.Disk_1, vmID, "virtio1", params, changes) - disks.Disk_2.markDiskChanges(tmpCurrentDisks.Disk_2, vmID, "virtio2", params, changes) - disks.Disk_3.markDiskChanges(tmpCurrentDisks.Disk_3, vmID, "virtio3", params, changes) - disks.Disk_4.markDiskChanges(tmpCurrentDisks.Disk_4, vmID, "virtio4", params, changes) - disks.Disk_5.markDiskChanges(tmpCurrentDisks.Disk_5, vmID, "virtio5", params, changes) - disks.Disk_6.markDiskChanges(tmpCurrentDisks.Disk_6, vmID, "virtio6", params, changes) - disks.Disk_7.markDiskChanges(tmpCurrentDisks.Disk_7, vmID, "virtio7", params, changes) - disks.Disk_8.markDiskChanges(tmpCurrentDisks.Disk_8, vmID, "virtio8", params, changes) - disks.Disk_9.markDiskChanges(tmpCurrentDisks.Disk_9, vmID, "virtio9", params, changes) - disks.Disk_10.markDiskChanges(tmpCurrentDisks.Disk_10, vmID, "virtio10", params, changes) - disks.Disk_11.markDiskChanges(tmpCurrentDisks.Disk_11, vmID, "virtio11", params, changes) - disks.Disk_12.markDiskChanges(tmpCurrentDisks.Disk_12, vmID, "virtio12", params, changes) - disks.Disk_13.markDiskChanges(tmpCurrentDisks.Disk_13, vmID, "virtio13", params, changes) - disks.Disk_14.markDiskChanges(tmpCurrentDisks.Disk_14, vmID, "virtio14", params, changes) - disks.Disk_15.markDiskChanges(tmpCurrentDisks.Disk_15, vmID, "virtio15", params, changes) + disks.Disk_0.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_0.convertDataStructure(), vmID, "virtio0", params, changes) + disks.Disk_1.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_1.convertDataStructure(), vmID, "virtio1", params, changes) + disks.Disk_2.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_2.convertDataStructure(), vmID, "virtio2", params, changes) + disks.Disk_3.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_3.convertDataStructure(), vmID, "virtio3", params, changes) + disks.Disk_4.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_4.convertDataStructure(), vmID, "virtio4", params, changes) + disks.Disk_5.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_5.convertDataStructure(), vmID, "virtio5", params, changes) + disks.Disk_6.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_6.convertDataStructure(), vmID, "virtio6", params, changes) + disks.Disk_7.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_7.convertDataStructure(), vmID, "virtio7", params, changes) + disks.Disk_8.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_8.convertDataStructure(), vmID, "virtio8", params, changes) + disks.Disk_9.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_9.convertDataStructure(), vmID, "virtio9", params, changes) + disks.Disk_10.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_10.convertDataStructure(), vmID, "virtio10", params, changes) + disks.Disk_11.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_11.convertDataStructure(), vmID, "virtio11", params, changes) + disks.Disk_12.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_12.convertDataStructure(), vmID, "virtio12", params, changes) + disks.Disk_13.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_13.convertDataStructure(), vmID, "virtio13", params, changes) + disks.Disk_14.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_14.convertDataStructure(), vmID, "virtio14", params, changes) + disks.Disk_15.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_15.convertDataStructure(), vmID, "virtio15", params, changes) } // TODO write test @@ -244,11 +244,6 @@ func (storage QemuVirtIOStorage) mapToApiValues(vmID uint, create bool) string { return "" } -// TODO write test -func (storage *QemuVirtIOStorage) markDiskChanges(currentStorage *QemuVirtIOStorage, vmID uint, id string, params map[string]interface{}, changes *qemuUpdateChanges) { - storage.convertDataStructure().markDiskChanges(currentStorage.convertDataStructure(), vmID, id, params, changes) -} - // TODO write test func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { settings := splitStringOfSettings(param) From de31a18d8ab86abe784a762772d1aca65dc11fbd Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 10:52:30 +0000 Subject: [PATCH 037/120] feat: make id optional --- proxmox/config_qemu_disk.go | 9 +++++---- proxmox/config_qemu_disk_ide.go | 2 +- proxmox/config_qemu_disk_sata.go | 2 +- proxmox/config_qemu_disk_scsi.go | 2 +- proxmox/config_qemu_disk_virtio.go | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index afd4fd2c..0a37e5df 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -132,8 +132,8 @@ type qemuDisk struct { // TODO custom type File string // Only set for Passthrough. Format QemuDiskFormat - Id uint // Only set for Disk - IOThread bool // Only set for scsi,virtio + Id *uint // Only set for Disk + IOThread bool // Only set for scsi,virtio Number uint ReadOnly bool // Only set for scsi,virtio Replicate bool @@ -241,7 +241,8 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { tmp := strings.Split(idAndFormat[0], "-") if len(tmp) > 1 { tmpId, _ := strconv.Atoi(tmp[len(tmp)-1]) - disk.Id = uint(tmpId) + idPointer := uint(tmpId) + disk.Id = &idPointer } } } @@ -471,7 +472,7 @@ func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID ui } else { if storage.Disk.Size >= currentStorage.Disk.Size { // Update - if storage.Disk.Id == 0 { + if storage.Disk.Id == nil { storage.Disk.Id = currentStorage.Disk.Id } if storage.Disk.Storage != currentStorage.Disk.Storage { diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 9e1aefad..fee64099 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -7,7 +7,7 @@ type QemuIdeDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` - Id uint `json:"id,omitempty"` + Id *uint `json:"id,omitempty"` Replicate bool `json:"replicate,omitempty"` Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size,omitempty"` diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index bb640026..e9521bc8 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -7,7 +7,7 @@ type QemuSataDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` - Id uint `json:"id,omitempty"` + Id *uint `json:"id,omitempty"` Replicate bool `json:"replicate,omitempty"` Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size,omitempty"` diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index af094d72..4a0b28f7 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -7,7 +7,7 @@ type QemuScsiDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` - Id uint `json:"id,omitempty"` + Id *uint `json:"id,omitempty"` IOThread bool `json:"iothread,omitempty"` ReadOnly bool `json:"readonly,omitempty"` Replicate bool `json:"replicate,omitempty"` diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index f61fab77..c385c691 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -6,7 +6,7 @@ type QemuVirtIODisk struct { Bandwidth QemuDiskBandwidth `json:"bandwith,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` - Id uint `json:"id,omitempty"` + Id *uint `json:"id,omitempty"` IOThread bool `json:"iothread,omitempty"` ReadOnly bool `json:"readonly,omitempty"` Replicate bool `json:"replicate,omitempty"` From b594866e86b85b148a0bd2a2c5600905d0c4290a Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 12:50:18 +0000 Subject: [PATCH 038/120] feat: add disk resizing --- proxmox/config_qemu_disk.go | 38 ++++++++++++++++++++++++------ proxmox/config_qemu_disk_ide.go | 3 +++ proxmox/config_qemu_disk_sata.go | 3 +++ proxmox/config_qemu_disk_scsi.go | 3 +++ proxmox/config_qemu_disk_virtio.go | 3 +++ 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 0a37e5df..b4204e91 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -130,10 +130,10 @@ type qemuDisk struct { Discard bool EmulateSSD bool // Only set for ide,sata,scsi // TODO custom type - File string // Only set for Passthrough. - Format QemuDiskFormat - Id *uint // Only set for Disk - IOThread bool // Only set for scsi,virtio + File string // Only set for Passthrough. + Format *QemuDiskFormat // Only set for Disk + Id *uint // Only set for Disk + IOThread bool // Only set for scsi,virtio Number uint ReadOnly bool // Only set for scsi,virtio Replicate bool @@ -150,7 +150,9 @@ func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { if create { settings = disk.Storage + ":" + strconv.Itoa(int(disk.Size)) } else { - settings = disk.Storage + ":" + strconv.Itoa(int(disk.Size)) + // test:100/vm-100-disk-0.raw + tmpId := strconv.Itoa(int(vmID)) + settings = disk.Storage + ":" + tmpId + "/vm-" + tmpId + "-disk-" + strconv.Itoa(int(*disk.Id)) + "." + string(*disk.Format) } } @@ -237,7 +239,8 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { if len(diskAndNumberAndFormat) == 2 { idAndFormat := strings.Split(diskAndNumberAndFormat[1], ".") if len(idAndFormat) == 2 { - disk.Format = QemuDiskFormat(idAndFormat[1]) + tmpFormat := QemuDiskFormat(idAndFormat[1]) + disk.Format = &tmpFormat tmp := strings.Split(idAndFormat[0], "-") if len(tmp) > 1 { tmpId, _ := strconv.Atoi(tmp[len(tmp)-1]) @@ -419,6 +422,17 @@ func (serial QemuDiskSerial) Validate() error { return nil } +type qemuDiskResize struct { + Id string + SizeInGigaBytes uint +} + +// Increase the disk size to the specified amount in gigabytes +// Decrease of disk size is not permitted. +func (disk qemuDiskResize) resize(vmr *VmRef, client *Client) (exitStatus string, err error) { + return client.PutWithTask(map[string]interface{}{"disk": disk.Id, "size": strconv.Itoa(int(disk.SizeInGigaBytes)) + "G"}, fmt.Sprintf("/nodes/%s/%s/%d/resize", vmr.node, vmr.vmType, vmr.vmId)) +} + type qemuDiskShort struct { Storage string Id string @@ -472,9 +486,18 @@ func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID ui } else { if storage.Disk.Size >= currentStorage.Disk.Size { // Update + if storage.Disk.Size > currentStorage.Disk.Size { + changes.Resize = append(changes.Resize, qemuDiskResize{ + Id: id, + SizeInGigaBytes: storage.Disk.Size, + }) + } if storage.Disk.Id == nil { storage.Disk.Id = currentStorage.Disk.Id } + if storage.Disk.Format == nil { + storage.Disk.Format = currentStorage.Disk.Format + } if storage.Disk.Storage != currentStorage.Disk.Storage { changes.Move = append(changes.Move, qemuDiskShort{ Id: id, @@ -563,6 +586,7 @@ func (QemuStorages) mapToStruct(params map[string]interface{}) *QemuStorages { } type qemuUpdateChanges struct { - Move []qemuDiskShort Delete string + Move []qemuDiskShort + Resize []qemuDiskResize } diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index fee64099..0bd82dc0 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -7,6 +7,7 @@ type QemuIdeDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` + Format *QemuDiskFormat `json:"format,omitempty"` Id *uint `json:"id,omitempty"` Replicate bool `json:"replicate,omitempty"` Serial QemuDiskSerial `json:"serial,omitempty"` @@ -130,6 +131,7 @@ func (storage *QemuIdeStorage) convertDataStructure() *qemuStorage { Cache: storage.Disk.Cache, Discard: storage.Disk.Discard, EmulateSSD: storage.Disk.EmulateSSD, + Format: storage.Disk.Format, Id: storage.Disk.Id, Replicate: storage.Disk.Replicate, Serial: storage.Disk.Serial, @@ -194,6 +196,7 @@ func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { Cache: tmpDisk.Cache, Discard: tmpDisk.Discard, EmulateSSD: tmpDisk.EmulateSSD, + Format: tmpDisk.Format, Id: tmpDisk.Id, Replicate: tmpDisk.Replicate, Serial: tmpDisk.Serial, diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index e9521bc8..0cadba80 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -7,6 +7,7 @@ type QemuSataDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` + Format *QemuDiskFormat `json:"format,omitempty"` Id *uint `json:"id,omitempty"` Replicate bool `json:"replicate,omitempty"` Serial QemuDiskSerial `json:"serial,omitempty"` @@ -142,6 +143,7 @@ func (storage *QemuSataStorage) convertDataStructure() *qemuStorage { Cache: storage.Disk.Cache, Discard: storage.Disk.Discard, EmulateSSD: storage.Disk.EmulateSSD, + Format: storage.Disk.Format, Id: storage.Disk.Id, Replicate: storage.Disk.Replicate, Serial: storage.Disk.Serial, @@ -206,6 +208,7 @@ func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { Cache: tmpDisk.Cache, Discard: tmpDisk.Discard, EmulateSSD: tmpDisk.EmulateSSD, + Format: tmpDisk.Format, Id: tmpDisk.Id, Replicate: tmpDisk.Replicate, Serial: tmpDisk.Serial, diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 4a0b28f7..b98c67f3 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -7,6 +7,7 @@ type QemuScsiDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` + Format *QemuDiskFormat `json:"format,omitempty"` Id *uint `json:"id,omitempty"` IOThread bool `json:"iothread,omitempty"` ReadOnly bool `json:"readonly,omitempty"` @@ -300,6 +301,7 @@ func (storage *QemuScsiStorage) convertDataStructure() *qemuStorage { Cache: storage.Disk.Cache, Discard: storage.Disk.Discard, EmulateSSD: storage.Disk.EmulateSSD, + Format: storage.Disk.Format, Id: storage.Disk.Id, IOThread: storage.Disk.IOThread, ReadOnly: storage.Disk.ReadOnly, @@ -368,6 +370,7 @@ func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { Cache: tmpDisk.Cache, Discard: tmpDisk.Discard, EmulateSSD: tmpDisk.EmulateSSD, + Format: tmpDisk.Format, Id: tmpDisk.Id, IOThread: tmpDisk.IOThread, ReadOnly: tmpDisk.ReadOnly, diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index c385c691..96f86a12 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -6,6 +6,7 @@ type QemuVirtIODisk struct { Bandwidth QemuDiskBandwidth `json:"bandwith,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` + Format *QemuDiskFormat `json:"format,omitempty"` Id *uint `json:"id,omitempty"` IOThread bool `json:"iothread,omitempty"` ReadOnly bool `json:"readonly,omitempty"` @@ -202,6 +203,7 @@ func (storage *QemuVirtIOStorage) convertDataStructure() *qemuStorage { Bandwidth: storage.Disk.Bandwidth, Cache: storage.Disk.Cache, Discard: storage.Disk.Discard, + Format: storage.Disk.Format, Id: storage.Disk.Id, IOThread: storage.Disk.IOThread, ReadOnly: storage.Disk.ReadOnly, @@ -267,6 +269,7 @@ func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { Bandwidth: tmpDisk.Bandwidth, Cache: tmpDisk.Cache, Discard: tmpDisk.Discard, + Format: tmpDisk.Format, Id: tmpDisk.Id, IOThread: tmpDisk.IOThread, ReadOnly: tmpDisk.ReadOnly, From 1665b1b5ce40038961d995b4a62542a2d8b30627 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 12:51:48 +0000 Subject: [PATCH 039/120] Commit missing changes --- proxmox/config_qemu.go | 69 ++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 9b3e57c4..d9c74425 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -3,6 +3,7 @@ package proxmox import ( "bytes" "encoding/json" + "errors" "fmt" "log" "math/rand" @@ -86,7 +87,11 @@ type ConfigQemu struct { // CreateVm - Tell Proxmox API to make the VM func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { - params, _, err := config.mapToApiValues(ConfigQemu{}, vmr) + err = config.setVmr(vmr) + if err != nil { + return + } + params, _, err := config.mapToApiValues(ConfigQemu{}) if err != nil { return } @@ -104,16 +109,15 @@ func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { return } -func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu, vmr *VmRef) (params map[string]interface{}, markedDisks *qemuUpdateChanges, err error) { - - vmr.SetVmType("qemu") +func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (params map[string]interface{}, markedDisks *qemuUpdateChanges, err error) { var itemsToDelete string - params = map[string]interface{}{ - "vmid": vmr.vmId, - } + params = map[string]interface{}{} + if config.VmID != 0 { + params["vmid"] = config.VmID + } if config.Args != "" { params["args"] = config.Args } @@ -177,8 +181,8 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu, vmr *VmRef) (p if config.QemuOs != "" { params["ostype"] = config.QemuOs } - if vmr.pool != "" { - params["pool"] = vmr.pool + if config.Pool != "" { + params["pool"] = config.Pool } if config.Scsihw != "" { params["scsihw"] = config.Scsihw @@ -208,14 +212,14 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu, vmr *VmRef) (p // Disks if currentConfig.Disks != nil { if config.Disks != nil { - markedDisks = config.Disks.markDiskChanges(*currentConfig.Disks, params) + markedDisks = config.Disks.markDiskChanges(*currentConfig.Disks, uint(config.VmID), params) } if markedDisks.Delete != "" { itemsToDelete = AddToList(itemsToDelete, markedDisks.Delete) } } else { if config.Disks != nil { - config.Disks.mapToApiValues(params) + config.Disks.mapToApiValues(uint(config.VmID), params) } } @@ -223,7 +227,7 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu, vmr *VmRef) (p config.CreateQemuEfiParams(params) // Create networks config. - config.CreateQemuNetworksParams(vmr.vmId, params) + config.CreateQemuNetworksParams(params) // Create vga config. vgaParam := QemuDeviceParam{} @@ -258,16 +262,40 @@ func (newConfig ConfigQemu) Update(vmr *VmRef, client *Client) (err error) { return newConfig.UpdateAdvanced(currentConfig, vmr, client) } +func (config *ConfigQemu) setVmr(vmr *VmRef) error { + if config == nil { + return errors.New("config may not be nil") + } + if vmr == nil { + return errors.New("vm reference may not be nil") + } + vmr.SetVmType("qemu") + config.VmID = vmr.vmId + return nil +} + func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef, client *Client) (err error) { - params, markedDisks, err := newConfig.mapToApiValues(*currentConfig, vmr) + err = newConfig.setVmr(vmr) + if err != nil { + return + } + params, markedDisks, err := newConfig.mapToApiValues(*currentConfig) if err != nil { return } - for _, e := range markedDisks.Move { - _, err = client.MoveQemuDisk(vmr, e.Id, e.Storage) - if err != nil { - return + if markedDisks != nil { + for _, e := range markedDisks.Move { + _, err = client.MoveQemuDisk(vmr, e.Id, e.Storage) + if err != nil { + return + } + } + for _, e := range markedDisks.Resize { + _, err = e.resize(vmr, client) + if err != nil { + return + } } } @@ -463,7 +491,8 @@ func (config ConfigQemu) UpdateConfig(vmr *VmRef, client *Client) (err error) { } // Create networks config. - config.CreateQemuNetworksParams(vmr.vmId, configParams) + config.VmID = vmr.vmId + config.CreateQemuNetworksParams(configParams) // Create vga config. vgaParam := QemuDeviceParam{} @@ -1158,7 +1187,7 @@ func FormatUsbParam(usb QemuDevice) string { } // Create parameters for each Nic device. -func (c ConfigQemu) CreateQemuNetworksParams(vmID int, params map[string]interface{}) { +func (c ConfigQemu) CreateQemuNetworksParams(params map[string]interface{}) { // For new style with multi net device. for nicID, nicConfMap := range c.QemuNetworks { @@ -1184,7 +1213,7 @@ func (c ConfigQemu) CreateQemuNetworksParams(vmID int, params map[string]interfa // Generate deterministic Mac based on VmID and NicID // Assume that rare VM has more than 32 nics macaddr := make(net.HardwareAddr, 6) - pairing := vmID<<5 | nicID + pairing := c.VmID<<5 | nicID // Linux MAC vendor - 00:18:59 macaddr[0] = 0x00 macaddr[1] = 0x18 From a05ef20771b8755a48d8686fb0d8cf856989ffe9 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 12:52:04 +0000 Subject: [PATCH 040/120] Add TODO --- proxmox/client.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proxmox/client.go b/proxmox/client.go index b2079ccd..dffd7b7b 100644 --- a/proxmox/client.go +++ b/proxmox/client.go @@ -736,6 +736,7 @@ func (c *Client) MigrateNode(vmr *VmRef, newTargetNode string, online bool) (exi } // ResizeQemuDisk allows the caller to increase the size of a disk by the indicated number of gigabytes +// TODO Deprecate once LXC is able to resize disk by itself (qemu can already do this) func (c *Client) ResizeQemuDisk(vmr *VmRef, disk string, moreSizeGB int) (exitStatus interface{}, err error) { size := fmt.Sprintf("+%dG", moreSizeGB) return c.ResizeQemuDiskRaw(vmr, disk, size) @@ -746,6 +747,7 @@ func (c *Client) ResizeQemuDisk(vmr *VmRef, disk string, moreSizeGB int) (exitSt // your desired size with a '+' character it will ADD size to the disk. If you just specify the size by // itself it will do an absolute resizing to the specified size. Permitted suffixes are K, M, G, T // to indicate order of magnitude (kilobyte, megabyte, etc). Decrease of disk size is not permitted. +// TODO Deprecate once LXC is able to resize disk by itself (qemu can already do this) func (c *Client) ResizeQemuDiskRaw(vmr *VmRef, disk string, size string) (exitStatus interface{}, err error) { // PUT //disk:virtio0 From bd13540819136417063562da0048d2bde8265d2c Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 14:35:40 +0000 Subject: [PATCH 041/120] refactor: remove dead code --- proxmox/config_qemu_disk_ide.go | 52 ++------------------------- proxmox/config_qemu_disk_sata.go | 52 ++------------------------- proxmox/config_qemu_disk_scsi.go | 56 ++---------------------------- proxmox/config_qemu_disk_virtio.go | 52 ++------------------------- 4 files changed, 8 insertions(+), 204 deletions(-) diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 0bd82dc0..06292bab 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -15,23 +15,6 @@ type QemuIdeDisk struct { Storage string `json:"storage,omitempty"` } -// TODO write test -func (disk QemuIdeDisk) mapToApiValues(vmID uint, create bool) string { - return qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - EmulateSSD: disk.EmulateSSD, - Replicate: disk.Replicate, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: ide, - }.mapToApiValues(vmID, create) -} - type QemuIdeDisks struct { Disk_0 *QemuIdeStorage `json:"0,omitempty"` Disk_1 *QemuIdeStorage `json:"1,omitempty"` @@ -90,22 +73,6 @@ type QemuIdePassthrough struct { Size uint //size is only returned and setting it has no effect } -// TODO write test -func (passthrough QemuIdePassthrough) mapToApiValues() string { - return qemuDisk{ - AsyncIO: passthrough.AsyncIO, - Backup: passthrough.Backup, - Bandwidth: passthrough.Bandwidth, - Cache: passthrough.Cache, - Discard: passthrough.Discard, - EmulateSSD: passthrough.EmulateSSD, - File: passthrough.File, - Replicate: passthrough.Replicate, - Serial: passthrough.Serial, - Type: ide, - }.mapToApiValues(0, false) -} - type QemuIdeStorage struct { CdRom *QemuCdRom `json:"cdrom,omitempty"` CloudInit *QemuCloudInitDisk `json:"cloudinit,omitempty"` @@ -137,6 +104,7 @@ func (storage *QemuIdeStorage) convertDataStructure() *qemuStorage { Serial: storage.Disk.Serial, Size: storage.Disk.Size, Storage: storage.Disk.Storage, + Type: ide, } } if storage.Passthrough != nil { @@ -150,28 +118,12 @@ func (storage *QemuIdeStorage) convertDataStructure() *qemuStorage { File: storage.Passthrough.File, Replicate: storage.Passthrough.Replicate, Serial: storage.Passthrough.Serial, + Type: ide, } } return &generalizedStorage } -// TODO write test -func (storage QemuIdeStorage) mapToApiValues(vmID uint, create bool) string { - if storage.Disk != nil { - return storage.Disk.mapToApiValues(vmID, create) - } - if storage.CdRom != nil { - return storage.CdRom.mapToApiValues() - } - if storage.CloudInit != nil { - return storage.CloudInit.mapToApiValues() - } - if storage.Passthrough != nil { - return storage.Passthrough.mapToApiValues() - } - return "" -} - // TODO write test func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { settings := splitStringOfSettings(param) diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 0cadba80..dfd50c70 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -15,23 +15,6 @@ type QemuSataDisk struct { Storage string `json:"storage,omitempty"` } -// TODO write test -func (disk QemuSataDisk) mapToApiValues(vmID uint, create bool) string { - return qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - EmulateSSD: disk.EmulateSSD, - Replicate: disk.Replicate, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: sata, - }.mapToApiValues(vmID, create) -} - type QemuSataDisks struct { Disk_0 *QemuSataStorage `json:"0,omitempty"` Disk_1 *QemuSataStorage `json:"1,omitempty"` @@ -102,22 +85,6 @@ type QemuSataPassthrough struct { Size uint //size is only returned and setting it has no effect } -// TODO write test -func (passthrough QemuSataPassthrough) mapToApiValues() string { - return qemuDisk{ - AsyncIO: passthrough.AsyncIO, - Backup: passthrough.Backup, - Bandwidth: passthrough.Bandwidth, - Cache: passthrough.Cache, - Discard: passthrough.Discard, - EmulateSSD: passthrough.EmulateSSD, - File: passthrough.File, - Replicate: passthrough.Replicate, - Serial: passthrough.Serial, - Type: sata, - }.mapToApiValues(0, false) -} - type QemuSataStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -149,6 +116,7 @@ func (storage *QemuSataStorage) convertDataStructure() *qemuStorage { Serial: storage.Disk.Serial, Size: storage.Disk.Size, Storage: storage.Disk.Storage, + Type: sata, } } if storage.Passthrough != nil { @@ -162,28 +130,12 @@ func (storage *QemuSataStorage) convertDataStructure() *qemuStorage { File: storage.Passthrough.File, Replicate: storage.Passthrough.Replicate, Serial: storage.Passthrough.Serial, + Type: sata, } } return &generalizedStorage } -// TODO write test -func (storage QemuSataStorage) mapToApiValues(vmID uint, create bool) string { - if storage.Disk != nil { - return storage.Disk.mapToApiValues(vmID, create) - } - if storage.CdRom != nil { - return storage.CdRom.mapToApiValues() - } - if storage.CloudInit != nil { - return storage.CloudInit.mapToApiValues() - } - if storage.Passthrough != nil { - return storage.Passthrough.mapToApiValues() - } - return "" -} - // TODO write test func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { settings := splitStringOfSettings(param) diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index b98c67f3..2c1c0a8d 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -17,25 +17,6 @@ type QemuScsiDisk struct { Storage string `json:"storage,omitempty"` } -// TODO write test -func (disk QemuScsiDisk) mapToApiValues(vmID uint, create bool) string { - return qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - EmulateSSD: disk.EmulateSSD, - IOThread: disk.IOThread, - ReadOnly: disk.ReadOnly, - Replicate: disk.Replicate, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: scsi, - }.mapToApiValues(vmID, create) -} - type QemuScsiDisks struct { Disk_0 *QemuScsiStorage `json:"0,omitempty"` Disk_1 *QemuScsiStorage `json:"1,omitempty"` @@ -258,24 +239,6 @@ type QemuScsiPassthrough struct { Size uint //size is only returned and setting it has no effect } -// TODO write test -func (passthrough QemuScsiPassthrough) mapToApiValues() string { - return qemuDisk{ - AsyncIO: passthrough.AsyncIO, - Backup: passthrough.Backup, - Bandwidth: passthrough.Bandwidth, - Cache: passthrough.Cache, - Discard: passthrough.Discard, - EmulateSSD: passthrough.EmulateSSD, - File: passthrough.File, - IOThread: passthrough.IOThread, - ReadOnly: passthrough.ReadOnly, - Replicate: passthrough.Replicate, - Serial: passthrough.Serial, - Type: scsi, - }.mapToApiValues(0, false) -} - type QemuScsiStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -309,6 +272,7 @@ func (storage *QemuScsiStorage) convertDataStructure() *qemuStorage { Serial: storage.Disk.Serial, Size: storage.Disk.Size, Storage: storage.Disk.Storage, + Type: scsi, } } if storage.Passthrough != nil { @@ -324,28 +288,12 @@ func (storage *QemuScsiStorage) convertDataStructure() *qemuStorage { ReadOnly: storage.Passthrough.ReadOnly, Replicate: storage.Passthrough.Replicate, Serial: storage.Passthrough.Serial, + Type: scsi, } } return &generalizedStorage } -// TODO write test -func (storage QemuScsiStorage) mapToApiValues(vmID uint, create bool) string { - if storage.Disk != nil { - return storage.Disk.mapToApiValues(vmID, create) - } - if storage.CdRom != nil { - return storage.CdRom.mapToApiValues() - } - if storage.CloudInit != nil { - return storage.CloudInit.mapToApiValues() - } - if storage.Passthrough != nil { - return storage.Passthrough.mapToApiValues() - } - return "" -} - // TODO write test func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { settings := splitStringOfSettings(param) diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 96f86a12..9f08493e 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -16,23 +16,6 @@ type QemuVirtIODisk struct { Storage string `json:"storage,omitempty"` } -// TODO write test -func (disk QemuVirtIODisk) mapToApiValues(vmID uint, create bool) string { - return qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - IOThread: disk.IOThread, - ReadOnly: disk.ReadOnly, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: virtIO, - }.mapToApiValues(vmID, create) -} - type QemuVirtIODisks struct { Disk_0 *QemuVirtIOStorage `json:"0,omitempty"` Disk_1 *QemuVirtIOStorage `json:"1,omitempty"` @@ -163,22 +146,6 @@ type QemuVirtIOPassthrough struct { Size uint //size is only returned and setting it has no effect } -// TODO write test -func (passthrough QemuVirtIOPassthrough) mapToApiValues() string { - return qemuDisk{ - AsyncIO: passthrough.AsyncIO, - Backup: passthrough.Backup, - Bandwidth: passthrough.Bandwidth, - Cache: passthrough.Cache, - Discard: passthrough.Discard, - File: passthrough.File, - IOThread: passthrough.IOThread, - ReadOnly: passthrough.ReadOnly, - Serial: passthrough.Serial, - Type: scsi, - }.mapToApiValues(0, false) -} - type QemuVirtIOStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -211,6 +178,7 @@ func (storage *QemuVirtIOStorage) convertDataStructure() *qemuStorage { Serial: storage.Disk.Serial, Size: storage.Disk.Size, Storage: storage.Disk.Storage, + Type: virtIO, } } if storage.Passthrough != nil { @@ -224,28 +192,12 @@ func (storage *QemuVirtIOStorage) convertDataStructure() *qemuStorage { IOThread: storage.Passthrough.IOThread, ReadOnly: storage.Passthrough.ReadOnly, Serial: storage.Passthrough.Serial, + Type: virtIO, } } return &generalizedStorage } -// TODO write test -func (storage QemuVirtIOStorage) mapToApiValues(vmID uint, create bool) string { - if storage.Disk != nil { - return storage.Disk.mapToApiValues(vmID, create) - } - if storage.CdRom != nil { - return storage.CdRom.mapToApiValues() - } - if storage.CloudInit != nil { - return storage.CloudInit.mapToApiValues() - } - if storage.Passthrough != nil { - return storage.Passthrough.mapToApiValues() - } - return "" -} - // TODO write test func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { settings := splitStringOfSettings(param) From 56949b20d8742eb94e87ec8dd1efc25ea1e2b5b2 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 15:18:03 +0000 Subject: [PATCH 042/120] refactor: put in alphabetical order --- proxmox/config_qemu_disk.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index b4204e91..621a7335 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -106,8 +106,8 @@ func (qemuCdRom) mapToStruct(settings [][]string) *qemuCdRom { } type QemuCloudInitDisk struct { - Storage string FileType string + Storage string } // TODO write test From 343c2c854be47509a61495a37df5979969f3b872 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 15:59:07 +0000 Subject: [PATCH 043/120] fix: panic --- proxmox/config_qemu.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index d9c74425..9ff15b10 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -213,9 +213,10 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (params map[st if currentConfig.Disks != nil { if config.Disks != nil { markedDisks = config.Disks.markDiskChanges(*currentConfig.Disks, uint(config.VmID), params) - } - if markedDisks.Delete != "" { - itemsToDelete = AddToList(itemsToDelete, markedDisks.Delete) + if markedDisks.Delete != "" { + itemsToDelete = AddToList(itemsToDelete, markedDisks.Delete) + markedDisks.Delete = "" + } } } else { if config.Disks != nil { From a988d64fdc76219f547c79258fa1976e038c1660 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 20:07:49 +0000 Subject: [PATCH 044/120] fix: bugs caused by conditionals --- proxmox/config_qemu_disk.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 621a7335..6ac8ddd5 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -463,7 +463,7 @@ func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID ui // Create or Update params[id] = storage.CdRom.mapToApiValues() return - } else if currentStorage != nil && currentStorage.CdRom != nil { + } else if currentStorage != nil && currentStorage.CdRom != nil && storage.CloudInit == nil && storage.Disk == nil && storage.Passthrough == nil { // Delete changes.Delete = AddToList(changes.Delete, id) return @@ -473,7 +473,7 @@ func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID ui // Create or Update params[id] = storage.CloudInit.mapToApiValues() return - } else if currentStorage != nil && currentStorage.CloudInit != nil { + } else if currentStorage != nil && currentStorage.CloudInit != nil && storage.Disk == nil && storage.Passthrough == nil { // Delete changes.Delete = AddToList(changes.Delete, id) return @@ -483,6 +483,7 @@ func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID ui if currentStorage == nil || currentStorage.Disk == nil { // Create params[id] = storage.Disk.mapToApiValues(vmID, true) + return } else { if storage.Disk.Size >= currentStorage.Disk.Size { // Update @@ -507,12 +508,12 @@ func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID ui params[id] = storage.Disk.mapToApiValues(vmID, false) } else { // Delete and Create - changes.Delete = AddToList(changes.Delete, id) + // creating a disk on top of an existing disk is the same as detaching the disk and creating a new one. params[id] = storage.Disk.mapToApiValues(vmID, true) } + return } - return - } else if currentStorage != nil && currentStorage.Disk != nil { + } else if currentStorage != nil && currentStorage.Disk != nil && storage.Passthrough == nil { // Delete changes.Delete = AddToList(changes.Delete, id) return @@ -542,16 +543,16 @@ type QemuStorages struct { func (storages QemuStorages) markDiskChanges(currentStorages QemuStorages, vmID uint, params map[string]interface{}) *qemuUpdateChanges { changes := &qemuUpdateChanges{} - if currentStorages.Ide != nil { + if storages.Ide != nil { storages.Ide.mapToApiValues(currentStorages.Ide, vmID, params, changes) } - if currentStorages.Sata != nil { + if storages.Sata != nil { storages.Sata.mapToApiValues(currentStorages.Sata, vmID, params, changes) } - if currentStorages.Scsi != nil { + if storages.Scsi != nil { storages.Scsi.mapToApiValues(currentStorages.Scsi, vmID, params, changes) } - if currentStorages.VirtIO != nil { + if storages.VirtIO != nil { storages.VirtIO.mapToApiValues(currentStorages.VirtIO, vmID, params, changes) } return changes From 90e6dba2013de3aeb4db8395daa3fad371b9d621 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 20:18:40 +0000 Subject: [PATCH 045/120] feat: add new Iso setting --- proxmox/config_qemu.go | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 9ff15b10..4b21e76d 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -54,16 +54,17 @@ type ConfigQemu struct { Hookscript string `json:"hookscript,omitempty"` Hotplug string `json:"hotplug,omitempty"` // TODO should be a struct Ipconfig IpconfigMap `json:"ipconfig,omitempty"` // TODO should be part of a cloud-init struct (cloud-init option) + Iso *IsoFile `json:"iso,omitempty"` // Same as Disks.Ide.Disk_2.CdRom.Iso Machine string `json:"machine,omitempty"` // TODO should be custom type with enum Memory int `json:"memory,omitempty"` // TODO should be uint Name string `json:"name,omitempty"` // TODO should be custom type as there are character and length limitations Nameserver string `json:"nameserver,omitempty"` // TODO should be part of a cloud-init struct (cloud-init option) Onboot *bool `json:"onboot,omitempty"` - Pool string `json:"pool,omitempty"` // TODO should be custom type as there are character and length limitations - QemuCores int `json:"cores,omitempty"` // TODO should be uint - QemuCpu string `json:"cpu,omitempty"` // TODO should be custom type with enum - QemuDisks QemuDevices `json:"disk,omitempty"` // DEPRECATED use Disks *QemuStorages instead - QemuIso string `json:"iso,omitempty"` // TODO should be a struct + Pool string `json:"pool,omitempty"` // TODO should be custom type as there are character and length limitations + QemuCores int `json:"cores,omitempty"` // TODO should be uint + QemuCpu string `json:"cpu,omitempty"` // TODO should be custom type with enum + QemuDisks QemuDevices `json:"disk,omitempty"` // DEPRECATED use Disks *QemuStorages instead + QemuIso string `json:"qemuiso,omitempty"` // DEPRECATED use Iso *IsoFile instead QemuKVM *bool `json:"kvm,omitempty"` QemuNetworks QemuDevices `json:"network,omitempty"` // TODO should be a struct QemuNuma *bool `json:"numa,omitempty"` @@ -209,6 +210,20 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (params map[st params["vcpus"] = config.QemuVcpus } + if config.Iso != nil { + if config.Disks == nil { + config.Disks = &QemuStorages{} + } + if config.Disks.Ide == nil { + config.Disks.Ide = &QemuIdeDisks{} + } + if config.Disks.Ide.Disk_2 == nil { + config.Disks.Ide.Disk_2 = &QemuIdeStorage{} + } + if config.Disks.Ide.Disk_2.CdRom == nil { + config.Disks.Ide.Disk_2.CdRom = &QemuCdRom{Iso: config.Iso} + } + } // Disks if currentConfig.Disks != nil { if config.Disks != nil { @@ -751,11 +766,6 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e config.QemuVcpus = int(vcpus) } - if vmConfig["ide2"] != nil { - isoMatch := rxIso.FindStringSubmatch(vmConfig["ide2"].(string)) - config.QemuIso = isoMatch[1] - } - // Add Cloud-Init options if _, isSet := vmConfig["ciuser"]; isSet { config.CIuser = vmConfig["ciuser"].(string) @@ -793,6 +803,10 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e config.Disks = QemuStorages{}.mapToStruct(vmConfig) + if config.Disks != nil && config.Disks.Ide != nil && config.Disks.Ide.Disk_2 != nil && config.Disks.Ide.Disk_2.CdRom != nil { + config.Iso = config.Disks.Ide.Disk_2.CdRom.Iso + } + // Add unused disks // unused0:local:100/vm-100-disk-1.qcow2 unusedDiskNames := []string{} From c9718e1e1f5b13eb4cac9c210b9145975d402eec Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 20:21:29 +0000 Subject: [PATCH 046/120] refactor: change post to put --- proxmox/config_qemu.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 4b21e76d..122015e9 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -317,7 +317,7 @@ func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef // TODO Migrate VM - _, err = client.PostWithTask(params, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/config") + _, err = client.PutWithTask(params, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/config") if err != nil { return } From 2ab981216ffb70fe8cd0b95793e0db5f7ac6fc39 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 20:35:15 +0000 Subject: [PATCH 047/120] feat: logic for node migration --- proxmox/config_qemu.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 122015e9..a8952eb6 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -59,6 +59,7 @@ type ConfigQemu struct { Memory int `json:"memory,omitempty"` // TODO should be uint Name string `json:"name,omitempty"` // TODO should be custom type as there are character and length limitations Nameserver string `json:"nameserver,omitempty"` // TODO should be part of a cloud-init struct (cloud-init option) + Node string `json:"node,omitempty"` Onboot *bool `json:"onboot,omitempty"` Pool string `json:"pool,omitempty"` // TODO should be custom type as there are character and length limitations QemuCores int `json:"cores,omitempty"` // TODO should be uint @@ -315,7 +316,14 @@ func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef } } - // TODO Migrate VM + if newConfig.Node != currentConfig.Node { + vmr.SetNode(currentConfig.Node) + _, err = client.MigrateNode(vmr, newConfig.Node, true) + if err != nil { + return + } + vmr.SetNode(newConfig.Node) + } _, err = client.PutWithTask(params, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/config") if err != nil { From c0f97853fbc42a763e7bcc6df811772f1e6d0287 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 21:31:24 +0000 Subject: [PATCH 048/120] refactor: move converting from api to struct into its own function --- proxmox/config_qemu.go | 709 ++++++++++++++++++++--------------------- 1 file changed, 345 insertions(+), 364 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index a8952eb6..602bacf8 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -271,6 +271,348 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (params map[st return } +func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu, err error) { + // vmConfig Sample: map[ cpu:host + // net0:virtio=62:DF:XX:XX:XX:XX,bridge=vmbr0 + // ide2:local:iso/xxx-xx.iso,media=cdrom memory:2048 + // smbios1:uuid=8b3bf833-aad8-4545-xxx-xxxxxxx digest:aa6ce5xxxxx1b9ce33e4aaeff564d4 sockets:1 + // name:terraform-ubuntu1404-template bootdisk:virtio0 + // virtio0:ProxmoxxxxISCSI:vm-1014-disk-2,size=4G + // description:Base image + // cores:2 ostype:l26 + + config = &ConfigQemu{ + EFIDisk: QemuDevice{}, + QemuDisks: QemuDevices{}, + QemuUnusedDisks: QemuDevices{}, + QemuVga: QemuDevice{}, + QemuNetworks: QemuDevices{}, + QemuSerials: QemuDevices{}, + QemuPCIDevices: QemuDevices{}, + QemuUsbs: QemuDevices{}, + Ipconfig: IpconfigMap{}, + } + + if _, isSet := params["agent"]; isSet { + switch params["agent"].(type) { + case float64: + config.Agent = int(params["agent"].(float64)) + case string: + AgentConfList := strings.Split(params["agent"].(string), ",") + config.Agent, _ = strconv.Atoi(AgentConfList[0]) + } + } + if _, isSet := params["args"]; isSet { + config.Args = strings.TrimSpace(params["args"].(string)) + } + if _, isSet := params["balloon"]; isSet { + balloon := int(params["balloon"].(float64)) + if balloon > 0 { + config.Balloon = balloon + } + } + //boot by default from hard disk (c), CD-ROM (d), network (n). + if _, isSet := params["boot"]; isSet { + config.Boot = params["boot"].(string) + } else { + config.Boot = "cdn" + } + if _, isSet := params["bootdisk"]; isSet { + config.BootDisk = params["bootdisk"].(string) + } + if _, isSet := params["bios"]; isSet { + config.Bios = params["bios"].(string) + } else { + config.Bios = "seabios" + } + if _, isSet := params["cicustom"]; isSet { + config.CIcustom = params["cicustom"].(string) + } + if _, isSet := params["cipassword"]; isSet { + config.CIpassword = params["cipassword"].(string) + } + if _, isSet := params["ciuser"]; isSet { + config.CIuser = params["ciuser"].(string) + } + if _, isSet := params["description"]; isSet { + config.Description = strings.TrimSpace(params["description"].(string)) + } + //Can be network,disk,cpu,memory,usb + if _, isSet := params["hotplug"]; isSet { + config.Hotplug = params["hotplug"].(string) + } else { + config.Hotplug = "network,disk,usb" + } + if _, isSet := params["hookscript"]; isSet { + config.Hookscript = params["hookscript"].(string) + } + if _, isSet := params["memory"]; isSet { + config.Memory = int(params["memory"].(float64)) + } + if _, isSet := params["name"]; isSet { + config.Name = params["name"].(string) + } + if _, isSet := params["nameserver"]; isSet { + config.Nameserver = params["nameserver"].(string) + } + if _, isSet := params["onboot"]; isSet { + config.Onboot = PointerBool(Itob(int(params["onboot"].(float64)))) + } else { + config.Onboot = PointerBool(true) + } + if _, isSet := params["cores"]; isSet { + config.QemuCores = int(params["cores"].(float64)) + } else { + config.QemuCores = 1 + } + if _, isSet := params["cpu"]; isSet { + config.QemuCpu = params["cpu"].(string) + } else { + config.QemuCpu = "host" + } + if _, isSet := params["kvm"]; isSet { + config.QemuKVM = PointerBool(Itob(int(params["kvm"].(float64)))) + } else { + config.QemuKVM = PointerBool(true) + } + if _, isSet := params["numa"]; isSet { + config.QemuNuma = PointerBool(Itob(int(params["numa"].(float64)))) + } + if _, isSet := params["ostype"]; isSet { + config.QemuOs = params["ostype"].(string) + } else { + config.QemuOs = "other" + } + if _, isSet := params["sockets"]; isSet { + config.QemuSockets = int(params["sockets"].(float64)) + } else { + config.QemuSockets = 1 + } + if _, isSet := params["vcpus"]; isSet { + vCpu := int(params["vcpus"].(float64)) + if vCpu > 0 { + config.QemuVcpus = vCpu + } + } + if _, isSet := params["scsihw"]; isSet { + config.Scsihw = params["scsihw"].(string) + } else { + config.Scsihw = "lsi" + } + if _, isSet := params["searchdomain"]; isSet { + config.Searchdomain = params["searchdomain"].(string) + } + if _, isSet := params["sshkeys"]; isSet { + config.Sshkeys, _ = url.PathUnescape(params["sshkeys"].(string)) + } + if _, isSet := params["startup"]; isSet { + config.Startup = params["startup"].(string) + } + if _, isSet := params["tablet"]; isSet { + config.Tablet = PointerBool(Itob(int(params["tablet"].(float64)))) + } else { + config.Tablet = PointerBool(true) + } + if _, isSet := params["tags"]; isSet { + config.Tags = strings.TrimSpace(params["tags"].(string)) + } + + ipconfigNames := []string{} + + for k := range params { + if ipconfigName := rxIpconfigName.FindStringSubmatch(k); len(ipconfigName) > 0 { + ipconfigNames = append(ipconfigNames, ipconfigName[0]) + } + } + + for _, ipconfigName := range ipconfigNames { + ipConfStr := params[ipconfigName] + id := rxDeviceID.FindStringSubmatch(ipconfigName) + ipconfigID, _ := strconv.Atoi(id[0]) + config.Ipconfig[ipconfigID] = ipConfStr + } + + config.Disks = QemuStorages{}.mapToStruct(params) + + if config.Disks != nil && config.Disks.Ide != nil && config.Disks.Ide.Disk_2 != nil && config.Disks.Ide.Disk_2.CdRom != nil { + config.Iso = config.Disks.Ide.Disk_2.CdRom.Iso + } + + // Add unused disks + // unused0:local:100/vm-100-disk-1.qcow2 + unusedDiskNames := []string{} + for k := range params { + // look for entries from the config in the format "unusedX:" where X is an integer + if unusedDiskName := rxUnusedDiskName.FindStringSubmatch(k); len(unusedDiskName) > 0 { + unusedDiskNames = append(unusedDiskNames, unusedDiskName[0]) + } + } + // if len(unusedDiskNames) > 0 { + // log.Printf("[DEBUG] unusedDiskNames: %v", unusedDiskNames) + // } + + for _, unusedDiskName := range unusedDiskNames { + unusedDiskConfStr := params[unusedDiskName].(string) + finalDiskConfMap := QemuDevice{} + + // parse "unused0" to get the id '0' as an int + id := rxDeviceID.FindStringSubmatch(unusedDiskName) + diskID, err := strconv.Atoi(id[0]) + if err != nil { + return nil, fmt.Errorf(fmt.Sprintf("Unable to parse unused disk id from input string '%v' tried to convert '%v' to integer.", unusedDiskName, diskID)) + } + finalDiskConfMap["slot"] = diskID + + // parse the attributes from the unused disk + // extract the storage and file path from the unused disk entry + parsedUnusedDiskMap := ParsePMConf(unusedDiskConfStr, "storage+file") + storageName, fileName := ParseSubConf(parsedUnusedDiskMap["storage+file"].(string), ":") + finalDiskConfMap["storage"] = storageName + finalDiskConfMap["file"] = fileName + + config.QemuUnusedDisks[diskID] = finalDiskConfMap + } + + //Display + if vga, isSet := params["vga"]; isSet { + vgaList := strings.Split(vga.(string), ",") + vgaMap := QemuDevice{} + + vgaMap.readDeviceConfig(vgaList) + if len(vgaMap) > 0 { + config.QemuVga = vgaMap + } + } + + // Add networks. + nicNames := []string{} + + for k := range params { + if nicName := rxNicName.FindStringSubmatch(k); len(nicName) > 0 { + nicNames = append(nicNames, nicName[0]) + } + } + + for _, nicName := range nicNames { + nicConfStr := params[nicName] + nicConfList := strings.Split(nicConfStr.(string), ",") + + id := rxDeviceID.FindStringSubmatch(nicName) + nicID, _ := strconv.Atoi(id[0]) + model, macaddr := ParseSubConf(nicConfList[0], "=") + + // Add model and MAC address. + nicConfMap := QemuDevice{ + "id": nicID, + "model": model, + "macaddr": macaddr, + } + + // Add rest of device config. + nicConfMap.readDeviceConfig(nicConfList[1:]) + switch nicConfMap["firewall"] { + case 1: + nicConfMap["firewall"] = true + case 0: + nicConfMap["firewall"] = false + } + switch nicConfMap["link_down"] { + case 1: + nicConfMap["link_down"] = true + case 0: + nicConfMap["link_down"] = false + } + + // And device config to networks. + if len(nicConfMap) > 0 { + config.QemuNetworks[nicID] = nicConfMap + } + } + + // Add serials + serialNames := []string{} + + for k := range params { + if serialName := rxSerialName.FindStringSubmatch(k); len(serialName) > 0 { + serialNames = append(serialNames, serialName[0]) + } + } + + for _, serialName := range serialNames { + id := rxDeviceID.FindStringSubmatch(serialName) + serialID, _ := strconv.Atoi(id[0]) + + serialConfMap := QemuDevice{ + "id": serialID, + "type": params[serialName], + } + + // And device config to serials map. + if len(serialConfMap) > 0 { + config.QemuSerials[serialID] = serialConfMap + } + } + + // Add usbs + usbNames := []string{} + + for k := range params { + if usbName := rxUsbName.FindStringSubmatch(k); len(usbName) > 0 { + usbNames = append(usbNames, usbName[0]) + } + } + + for _, usbName := range usbNames { + usbConfStr := params[usbName] + usbConfList := strings.Split(usbConfStr.(string), ",") + id := rxDeviceID.FindStringSubmatch(usbName) + usbID, _ := strconv.Atoi(id[0]) + _, host := ParseSubConf(usbConfList[0], "=") + + usbConfMap := QemuDevice{ + "id": usbID, + "host": host, + } + + usbConfMap.readDeviceConfig(usbConfList[1:]) + if usbConfMap["usb3"] == 1 { + usbConfMap["usb3"] = true + } + + // And device config to usbs map. + if len(usbConfMap) > 0 { + config.QemuUsbs[usbID] = usbConfMap + } + } + + // hostpci + hostPCInames := []string{} + + for k := range params { + if hostPCIname := rxPCIName.FindStringSubmatch(k); len(hostPCIname) > 0 { + hostPCInames = append(hostPCInames, hostPCIname[0]) + } + } + + for _, hostPCIname := range hostPCInames { + hostPCIConfStr := params[hostPCIname] + hostPCIConfList := strings.Split(hostPCIConfStr.(string), ",") + id := rxPCIName.FindStringSubmatch(hostPCIname) + hostPCIID, _ := strconv.Atoi(id[0]) + hostPCIConfMap := QemuDevice{ + "id": hostPCIID, + } + hostPCIConfMap.readDeviceConfig(hostPCIConfList) + // And device config to usbs map. + if len(hostPCIConfMap) > 0 { + config.QemuPCIDevices[hostPCIID] = hostPCIConfMap + } + } + + return + +} + func (newConfig ConfigQemu) Update(vmr *VmRef, client *Client) (err error) { currentConfig, err := NewConfigQemuFromApi(vmr, client) if err != nil { @@ -620,370 +962,9 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e if vmConfig["lock"] != nil { return nil, fmt.Errorf("vm locked, could not obtain config") } - - // vmConfig Sample: map[ cpu:host - // net0:virtio=62:DF:XX:XX:XX:XX,bridge=vmbr0 - // ide2:local:iso/xxx-xx.iso,media=cdrom memory:2048 - // smbios1:uuid=8b3bf833-aad8-4545-xxx-xxxxxxx digest:aa6ce5xxxxx1b9ce33e4aaeff564d4 sockets:1 - // name:terraform-ubuntu1404-template bootdisk:virtio0 - // virtio0:ProxmoxxxxISCSI:vm-1014-disk-2,size=4G - // description:Base image - // cores:2 ostype:l26 - - name := "" - if _, isSet := vmConfig["name"]; isSet { - name = vmConfig["name"].(string) - } - description := "" - if _, isSet := vmConfig["description"]; isSet { - description = vmConfig["description"].(string) - } - tags := "" - if _, isSet := vmConfig["tags"]; isSet { - tags = vmConfig["tags"].(string) - } - args := "" - if _, isSet := vmConfig["args"]; isSet { - args = vmConfig["args"].(string) - } - - bios := "seabios" - if _, isSet := vmConfig["bios"]; isSet { - bios = vmConfig["bios"].(string) - } - onboot := true - if _, isSet := vmConfig["onboot"]; isSet { - onboot = Itob(int(vmConfig["onboot"].(float64))) - } - startup := "" - if _, isSet := vmConfig["startup"]; isSet { - startup = vmConfig["startup"].(string) - } - tablet := true - if _, isSet := vmConfig["tablet"]; isSet { - tablet = Itob(int(vmConfig["tablet"].(float64))) - } - - agent := 0 - if _, isSet := vmConfig["agent"]; isSet { - switch vmConfig["agent"].(type) { - case float64: - agent = int(vmConfig["agent"].(float64)) - case string: - AgentConfList := strings.Split(vmConfig["agent"].(string), ",") - agent, _ = strconv.Atoi(AgentConfList[0]) - } - - } - ostype := "other" - if _, isSet := vmConfig["ostype"]; isSet { - ostype = vmConfig["ostype"].(string) - } - memory := 0.0 - if _, isSet := vmConfig["memory"]; isSet { - memory = vmConfig["memory"].(float64) - } - balloon := 0.0 - if _, isSet := vmConfig["balloon"]; isSet { - balloon = vmConfig["balloon"].(float64) - } - cores := 1.0 - if _, isSet := vmConfig["cores"]; isSet { - cores = vmConfig["cores"].(float64) - } - vcpus := 0.0 - if _, isSet := vmConfig["vcpus"]; isSet { - vcpus = vmConfig["vcpus"].(float64) - } - sockets := 1.0 - if _, isSet := vmConfig["sockets"]; isSet { - sockets = vmConfig["sockets"].(float64) - } - cpu := "host" - if _, isSet := vmConfig["cpu"]; isSet { - cpu = vmConfig["cpu"].(string) - } - numa := false - if _, isSet := vmConfig["numa"]; isSet { - numa = Itob(int(vmConfig["numa"].(float64))) - } - //Can be network,disk,cpu,memory,usb - hotplug := "network,disk,usb" - if _, isSet := vmConfig["hotplug"]; isSet { - hotplug = vmConfig["hotplug"].(string) - } - //boot by default from hard disk (c), CD-ROM (d), network (n). - boot := "cdn" - if _, isSet := vmConfig["boot"]; isSet { - boot = vmConfig["boot"].(string) - } - bootdisk := "" - if _, isSet := vmConfig["bootdisk"]; isSet { - bootdisk = vmConfig["bootdisk"].(string) - } - kvm := true - if _, isSet := vmConfig["kvm"]; isSet { - kvm = Itob(int(vmConfig["kvm"].(float64))) - } - scsihw := "lsi" - if _, isSet := vmConfig["scsihw"]; isSet { - scsihw = vmConfig["scsihw"].(string) - } - hookscript := "" - if _, isSet := vmConfig["hookscript"]; isSet { - hookscript = vmConfig["hookscript"].(string) - } - - config = &ConfigQemu{ - Name: name, - Description: strings.TrimSpace(description), - Tags: strings.TrimSpace(tags), - Args: strings.TrimSpace(args), - Bios: bios, - EFIDisk: QemuDevice{}, - Onboot: &onboot, - Startup: startup, - Tablet: &tablet, - Agent: agent, - QemuOs: ostype, - Memory: int(memory), - QemuCores: int(cores), - QemuSockets: int(sockets), - QemuCpu: cpu, - QemuNuma: &numa, - QemuKVM: &kvm, - Hotplug: hotplug, - Boot: boot, - BootDisk: bootdisk, - Scsihw: scsihw, - Hookscript: hookscript, - QemuDisks: QemuDevices{}, - QemuUnusedDisks: QemuDevices{}, - QemuVga: QemuDevice{}, - QemuNetworks: QemuDevices{}, - QemuSerials: QemuDevices{}, - QemuPCIDevices: QemuDevices{}, - QemuUsbs: QemuDevices{}, - Ipconfig: IpconfigMap{}, - } - - if balloon >= 1 { - config.Balloon = int(balloon) - } - if vcpus >= 1 { - config.QemuVcpus = int(vcpus) - } - - // Add Cloud-Init options - if _, isSet := vmConfig["ciuser"]; isSet { - config.CIuser = vmConfig["ciuser"].(string) - } - if _, isSet := vmConfig["cipassword"]; isSet { - config.CIpassword = vmConfig["cipassword"].(string) - } - if _, isSet := vmConfig["cicustom"]; isSet { - config.CIcustom = vmConfig["cicustom"].(string) - } - if _, isSet := vmConfig["searchdomain"]; isSet { - config.Searchdomain = vmConfig["searchdomain"].(string) - } - if _, isSet := vmConfig["nameserver"]; isSet { - config.Nameserver = vmConfig["nameserver"].(string) - } - if _, isSet := vmConfig["sshkeys"]; isSet { - config.Sshkeys, _ = url.PathUnescape(vmConfig["sshkeys"].(string)) - } - - ipconfigNames := []string{} - - for k := range vmConfig { - if ipconfigName := rxIpconfigName.FindStringSubmatch(k); len(ipconfigName) > 0 { - ipconfigNames = append(ipconfigNames, ipconfigName[0]) - } - } - - for _, ipconfigName := range ipconfigNames { - ipConfStr := vmConfig[ipconfigName] - id := rxDeviceID.FindStringSubmatch(ipconfigName) - ipconfigID, _ := strconv.Atoi(id[0]) - config.Ipconfig[ipconfigID] = ipConfStr - } - - config.Disks = QemuStorages{}.mapToStruct(vmConfig) - - if config.Disks != nil && config.Disks.Ide != nil && config.Disks.Ide.Disk_2 != nil && config.Disks.Ide.Disk_2.CdRom != nil { - config.Iso = config.Disks.Ide.Disk_2.CdRom.Iso - } - - // Add unused disks - // unused0:local:100/vm-100-disk-1.qcow2 - unusedDiskNames := []string{} - for k := range vmConfig { - // look for entries from the config in the format "unusedX:" where X is an integer - if unusedDiskName := rxUnusedDiskName.FindStringSubmatch(k); len(unusedDiskName) > 0 { - unusedDiskNames = append(unusedDiskNames, unusedDiskName[0]) - } - } - // if len(unusedDiskNames) > 0 { - // log.Printf("[DEBUG] unusedDiskNames: %v", unusedDiskNames) - // } - - for _, unusedDiskName := range unusedDiskNames { - unusedDiskConfStr := vmConfig[unusedDiskName].(string) - finalDiskConfMap := QemuDevice{} - - // parse "unused0" to get the id '0' as an int - id := rxDeviceID.FindStringSubmatch(unusedDiskName) - diskID, err := strconv.Atoi(id[0]) - if err != nil { - return nil, fmt.Errorf(fmt.Sprintf("Unable to parse unused disk id from input string '%v' tried to convert '%v' to integer.", unusedDiskName, diskID)) - } - finalDiskConfMap["slot"] = diskID - - // parse the attributes from the unused disk - // extract the storage and file path from the unused disk entry - parsedUnusedDiskMap := ParsePMConf(unusedDiskConfStr, "storage+file") - storageName, fileName := ParseSubConf(parsedUnusedDiskMap["storage+file"].(string), ":") - finalDiskConfMap["storage"] = storageName - finalDiskConfMap["file"] = fileName - - config.QemuUnusedDisks[diskID] = finalDiskConfMap - } - - //Display - if vga, isSet := vmConfig["vga"]; isSet { - vgaList := strings.Split(vga.(string), ",") - vgaMap := QemuDevice{} - - vgaMap.readDeviceConfig(vgaList) - if len(vgaMap) > 0 { - config.QemuVga = vgaMap - } - } - - // Add networks. - nicNames := []string{} - - for k := range vmConfig { - if nicName := rxNicName.FindStringSubmatch(k); len(nicName) > 0 { - nicNames = append(nicNames, nicName[0]) - } - } - - for _, nicName := range nicNames { - nicConfStr := vmConfig[nicName] - nicConfList := strings.Split(nicConfStr.(string), ",") - - id := rxDeviceID.FindStringSubmatch(nicName) - nicID, _ := strconv.Atoi(id[0]) - model, macaddr := ParseSubConf(nicConfList[0], "=") - - // Add model and MAC address. - nicConfMap := QemuDevice{ - "id": nicID, - "model": model, - "macaddr": macaddr, - } - - // Add rest of device config. - nicConfMap.readDeviceConfig(nicConfList[1:]) - switch nicConfMap["firewall"] { - case 1: - nicConfMap["firewall"] = true - case 0: - nicConfMap["firewall"] = false - } - switch nicConfMap["link_down"] { - case 1: - nicConfMap["link_down"] = true - case 0: - nicConfMap["link_down"] = false - } - - // And device config to networks. - if len(nicConfMap) > 0 { - config.QemuNetworks[nicID] = nicConfMap - } - } - - // Add serials - serialNames := []string{} - - for k := range vmConfig { - if serialName := rxSerialName.FindStringSubmatch(k); len(serialName) > 0 { - serialNames = append(serialNames, serialName[0]) - } - } - - for _, serialName := range serialNames { - id := rxDeviceID.FindStringSubmatch(serialName) - serialID, _ := strconv.Atoi(id[0]) - - serialConfMap := QemuDevice{ - "id": serialID, - "type": vmConfig[serialName], - } - - // And device config to serials map. - if len(serialConfMap) > 0 { - config.QemuSerials[serialID] = serialConfMap - } - } - - // Add usbs - usbNames := []string{} - - for k := range vmConfig { - if usbName := rxUsbName.FindStringSubmatch(k); len(usbName) > 0 { - usbNames = append(usbNames, usbName[0]) - } - } - - for _, usbName := range usbNames { - usbConfStr := vmConfig[usbName] - usbConfList := strings.Split(usbConfStr.(string), ",") - id := rxDeviceID.FindStringSubmatch(usbName) - usbID, _ := strconv.Atoi(id[0]) - _, host := ParseSubConf(usbConfList[0], "=") - - usbConfMap := QemuDevice{ - "id": usbID, - "host": host, - } - - usbConfMap.readDeviceConfig(usbConfList[1:]) - if usbConfMap["usb3"] == 1 { - usbConfMap["usb3"] = true - } - - // And device config to usbs map. - if len(usbConfMap) > 0 { - config.QemuUsbs[usbID] = usbConfMap - } - } - - // hostpci - hostPCInames := []string{} - - for k := range vmConfig { - if hostPCIname := rxPCIName.FindStringSubmatch(k); len(hostPCIname) > 0 { - hostPCInames = append(hostPCInames, hostPCIname[0]) - } - } - - for _, hostPCIname := range hostPCInames { - hostPCIConfStr := vmConfig[hostPCIname] - hostPCIConfList := strings.Split(hostPCIConfStr.(string), ",") - id := rxPCIName.FindStringSubmatch(hostPCIname) - hostPCIID, _ := strconv.Atoi(id[0]) - hostPCIConfMap := QemuDevice{ - "id": hostPCIID, - } - hostPCIConfMap.readDeviceConfig(hostPCIConfList) - // And device config to usbs map. - if len(hostPCIConfMap) > 0 { - config.QemuPCIDevices[hostPCIID] = hostPCIConfMap - } + config, err = ConfigQemu{}.mapToStruct(vmConfig) + if err != nil { + return } // HAstate is return by the api for a vm resource type but not the HAgroup From 6395895354a80355f5622fa7643106c565802f34 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 12 Mar 2023 21:51:43 +0000 Subject: [PATCH 049/120] refactor: put in alphabetical order --- proxmox/config_qemu_disk.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 6ac8ddd5..f393abd7 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -541,23 +541,6 @@ type QemuStorages struct { VirtIO *QemuVirtIODisks `json:"virtio,omitempty"` } -func (storages QemuStorages) markDiskChanges(currentStorages QemuStorages, vmID uint, params map[string]interface{}) *qemuUpdateChanges { - changes := &qemuUpdateChanges{} - if storages.Ide != nil { - storages.Ide.mapToApiValues(currentStorages.Ide, vmID, params, changes) - } - if storages.Sata != nil { - storages.Sata.mapToApiValues(currentStorages.Sata, vmID, params, changes) - } - if storages.Scsi != nil { - storages.Scsi.mapToApiValues(currentStorages.Scsi, vmID, params, changes) - } - if storages.VirtIO != nil { - storages.VirtIO.mapToApiValues(currentStorages.VirtIO, vmID, params, changes) - } - return changes -} - func (storages QemuStorages) mapToApiValues(vmID uint, params map[string]interface{}) { if storages.Ide != nil { storages.Ide.mapToApiValues(nil, vmID, params, nil) @@ -586,6 +569,23 @@ func (QemuStorages) mapToStruct(params map[string]interface{}) *QemuStorages { return nil } +func (storages QemuStorages) markDiskChanges(currentStorages QemuStorages, vmID uint, params map[string]interface{}) *qemuUpdateChanges { + changes := &qemuUpdateChanges{} + if storages.Ide != nil { + storages.Ide.mapToApiValues(currentStorages.Ide, vmID, params, changes) + } + if storages.Sata != nil { + storages.Sata.mapToApiValues(currentStorages.Sata, vmID, params, changes) + } + if storages.Scsi != nil { + storages.Scsi.mapToApiValues(currentStorages.Scsi, vmID, params, changes) + } + if storages.VirtIO != nil { + storages.VirtIO.mapToApiValues(currentStorages.VirtIO, vmID, params, changes) + } + return changes +} + type qemuUpdateChanges struct { Delete string Move []qemuDiskShort From 645cac6e737c41f4d4cad365cfadb617a2976a84 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 13 Mar 2023 16:37:28 +0000 Subject: [PATCH 050/120] refactor: extract to func --- proxmox/config_qemu_disk_ide.go | 62 ++++++++++++++------------ proxmox/config_qemu_disk_sata.go | 62 ++++++++++++++------------ proxmox/config_qemu_disk_scsi.go | 70 +++++++++++++++++------------- proxmox/config_qemu_disk_virtio.go | 64 +++++++++++++++------------ 4 files changed, 145 insertions(+), 113 deletions(-) diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 06292bab..9b485388 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -15,6 +15,24 @@ type QemuIdeDisk struct { Storage string `json:"storage,omitempty"` } +func (disk *QemuIdeDisk) convertDataStructure() *qemuDisk { + return &qemuDisk{ + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + EmulateSSD: disk.EmulateSSD, + Format: disk.Format, + Id: disk.Id, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: ide, + } +} + type QemuIdeDisks struct { Disk_0 *QemuIdeStorage `json:"0,omitempty"` Disk_1 *QemuIdeStorage `json:"1,omitempty"` @@ -73,6 +91,21 @@ type QemuIdePassthrough struct { Size uint //size is only returned and setting it has no effect } +func (passthrough *QemuIdePassthrough) convertDataStructure() *qemuDisk { + return &qemuDisk{ + AsyncIO: passthrough.AsyncIO, + Backup: passthrough.Backup, + Bandwidth: passthrough.Bandwidth, + Cache: passthrough.Cache, + Discard: passthrough.Discard, + EmulateSSD: passthrough.EmulateSSD, + File: passthrough.File, + Replicate: passthrough.Replicate, + Serial: passthrough.Serial, + Type: ide, + } +} + type QemuIdeStorage struct { CdRom *QemuCdRom `json:"cdrom,omitempty"` CloudInit *QemuCloudInitDisk `json:"cloudinit,omitempty"` @@ -91,35 +124,10 @@ func (storage *QemuIdeStorage) convertDataStructure() *qemuStorage { CloudInit: storage.CloudInit, } if storage.Disk != nil { - generalizedStorage.Disk = &qemuDisk{ - AsyncIO: storage.Disk.AsyncIO, - Backup: storage.Disk.Backup, - Bandwidth: storage.Disk.Bandwidth, - Cache: storage.Disk.Cache, - Discard: storage.Disk.Discard, - EmulateSSD: storage.Disk.EmulateSSD, - Format: storage.Disk.Format, - Id: storage.Disk.Id, - Replicate: storage.Disk.Replicate, - Serial: storage.Disk.Serial, - Size: storage.Disk.Size, - Storage: storage.Disk.Storage, - Type: ide, - } + generalizedStorage.Disk = storage.Disk.convertDataStructure() } if storage.Passthrough != nil { - generalizedStorage.Passthrough = &qemuDisk{ - AsyncIO: storage.Passthrough.AsyncIO, - Backup: storage.Passthrough.Backup, - Bandwidth: storage.Passthrough.Bandwidth, - Cache: storage.Passthrough.Cache, - Discard: storage.Passthrough.Discard, - EmulateSSD: storage.Passthrough.EmulateSSD, - File: storage.Passthrough.File, - Replicate: storage.Passthrough.Replicate, - Serial: storage.Passthrough.Serial, - Type: ide, - } + generalizedStorage.Passthrough = storage.Passthrough.convertDataStructure() } return &generalizedStorage } diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index dfd50c70..1079e424 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -15,6 +15,24 @@ type QemuSataDisk struct { Storage string `json:"storage,omitempty"` } +func (disk *QemuSataDisk) convertDataStructure() *qemuDisk { + return &qemuDisk{ + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + EmulateSSD: disk.EmulateSSD, + Format: disk.Format, + Id: disk.Id, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: sata, + } +} + type QemuSataDisks struct { Disk_0 *QemuSataStorage `json:"0,omitempty"` Disk_1 *QemuSataStorage `json:"1,omitempty"` @@ -85,6 +103,21 @@ type QemuSataPassthrough struct { Size uint //size is only returned and setting it has no effect } +func (passthrough *QemuSataPassthrough) convertDataStructure() *qemuDisk { + return &qemuDisk{ + AsyncIO: passthrough.AsyncIO, + Backup: passthrough.Backup, + Bandwidth: passthrough.Bandwidth, + Cache: passthrough.Cache, + Discard: passthrough.Discard, + EmulateSSD: passthrough.EmulateSSD, + File: passthrough.File, + Replicate: passthrough.Replicate, + Serial: passthrough.Serial, + Type: sata, + } +} + type QemuSataStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -103,35 +136,10 @@ func (storage *QemuSataStorage) convertDataStructure() *qemuStorage { CloudInit: storage.CloudInit, } if storage.Disk != nil { - generalizedStorage.Disk = &qemuDisk{ - AsyncIO: storage.Disk.AsyncIO, - Backup: storage.Disk.Backup, - Bandwidth: storage.Disk.Bandwidth, - Cache: storage.Disk.Cache, - Discard: storage.Disk.Discard, - EmulateSSD: storage.Disk.EmulateSSD, - Format: storage.Disk.Format, - Id: storage.Disk.Id, - Replicate: storage.Disk.Replicate, - Serial: storage.Disk.Serial, - Size: storage.Disk.Size, - Storage: storage.Disk.Storage, - Type: sata, - } + generalizedStorage.Disk = storage.Disk.convertDataStructure() } if storage.Passthrough != nil { - generalizedStorage.Passthrough = &qemuDisk{ - AsyncIO: storage.Passthrough.AsyncIO, - Backup: storage.Passthrough.Backup, - Bandwidth: storage.Passthrough.Bandwidth, - Cache: storage.Passthrough.Cache, - Discard: storage.Passthrough.Discard, - EmulateSSD: storage.Passthrough.EmulateSSD, - File: storage.Passthrough.File, - Replicate: storage.Passthrough.Replicate, - Serial: storage.Passthrough.Serial, - Type: sata, - } + generalizedStorage.Passthrough = storage.Passthrough.convertDataStructure() } return &generalizedStorage } diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 2c1c0a8d..dd1cd340 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -17,6 +17,26 @@ type QemuScsiDisk struct { Storage string `json:"storage,omitempty"` } +func (disk *QemuScsiDisk) convertDataStructure() *qemuDisk { + return &qemuDisk{ + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + EmulateSSD: disk.EmulateSSD, + Format: disk.Format, + Id: disk.Id, + IOThread: disk.IOThread, + ReadOnly: disk.ReadOnly, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: scsi, + } +} + type QemuScsiDisks struct { Disk_0 *QemuScsiStorage `json:"0,omitempty"` Disk_1 *QemuScsiStorage `json:"1,omitempty"` @@ -239,6 +259,23 @@ type QemuScsiPassthrough struct { Size uint //size is only returned and setting it has no effect } +func (passthrough *QemuScsiPassthrough) convertDataStructure() *qemuDisk { + return &qemuDisk{ + AsyncIO: passthrough.AsyncIO, + Backup: passthrough.Backup, + Bandwidth: passthrough.Bandwidth, + Cache: passthrough.Cache, + Discard: passthrough.Discard, + EmulateSSD: passthrough.EmulateSSD, + File: passthrough.File, + IOThread: passthrough.IOThread, + ReadOnly: passthrough.ReadOnly, + Replicate: passthrough.Replicate, + Serial: passthrough.Serial, + Type: scsi, + } +} + type QemuScsiStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -257,39 +294,10 @@ func (storage *QemuScsiStorage) convertDataStructure() *qemuStorage { CloudInit: storage.CloudInit, } if storage.Disk != nil { - generalizedStorage.Disk = &qemuDisk{ - AsyncIO: storage.Disk.AsyncIO, - Backup: storage.Disk.Backup, - Bandwidth: storage.Disk.Bandwidth, - Cache: storage.Disk.Cache, - Discard: storage.Disk.Discard, - EmulateSSD: storage.Disk.EmulateSSD, - Format: storage.Disk.Format, - Id: storage.Disk.Id, - IOThread: storage.Disk.IOThread, - ReadOnly: storage.Disk.ReadOnly, - Replicate: storage.Disk.Replicate, - Serial: storage.Disk.Serial, - Size: storage.Disk.Size, - Storage: storage.Disk.Storage, - Type: scsi, - } + generalizedStorage.Disk = storage.Disk.convertDataStructure() } if storage.Passthrough != nil { - generalizedStorage.Passthrough = &qemuDisk{ - AsyncIO: storage.Passthrough.AsyncIO, - Backup: storage.Passthrough.Backup, - Bandwidth: storage.Passthrough.Bandwidth, - Cache: storage.Passthrough.Cache, - Discard: storage.Passthrough.Discard, - EmulateSSD: storage.Passthrough.EmulateSSD, - File: storage.Passthrough.File, - IOThread: storage.Passthrough.IOThread, - ReadOnly: storage.Passthrough.ReadOnly, - Replicate: storage.Passthrough.Replicate, - Serial: storage.Passthrough.Serial, - Type: scsi, - } + generalizedStorage.Passthrough = storage.Passthrough.convertDataStructure() } return &generalizedStorage } diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 9f08493e..8101307c 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -16,6 +16,25 @@ type QemuVirtIODisk struct { Storage string `json:"storage,omitempty"` } +func (disk *QemuVirtIODisk) convertDataStructure() *qemuDisk { + return &qemuDisk{ + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + Format: disk.Format, + Id: disk.Id, + IOThread: disk.IOThread, + ReadOnly: disk.ReadOnly, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: virtIO, + } +} + type QemuVirtIODisks struct { Disk_0 *QemuVirtIOStorage `json:"0,omitempty"` Disk_1 *QemuVirtIOStorage `json:"1,omitempty"` @@ -146,6 +165,21 @@ type QemuVirtIOPassthrough struct { Size uint //size is only returned and setting it has no effect } +func (passthrough *QemuVirtIOPassthrough) convertDataStructure() *qemuDisk { + return &qemuDisk{ + AsyncIO: passthrough.AsyncIO, + Backup: passthrough.Backup, + Bandwidth: passthrough.Bandwidth, + Cache: passthrough.Cache, + Discard: passthrough.Discard, + File: passthrough.File, + IOThread: passthrough.IOThread, + ReadOnly: passthrough.ReadOnly, + Serial: passthrough.Serial, + Type: virtIO, + } +} + type QemuVirtIOStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -164,36 +198,10 @@ func (storage *QemuVirtIOStorage) convertDataStructure() *qemuStorage { CloudInit: storage.CloudInit, } if storage.Disk != nil { - generalizedStorage.Disk = &qemuDisk{ - AsyncIO: storage.Disk.AsyncIO, - Backup: storage.Disk.Backup, - Bandwidth: storage.Disk.Bandwidth, - Cache: storage.Disk.Cache, - Discard: storage.Disk.Discard, - Format: storage.Disk.Format, - Id: storage.Disk.Id, - IOThread: storage.Disk.IOThread, - ReadOnly: storage.Disk.ReadOnly, - Replicate: storage.Disk.Replicate, - Serial: storage.Disk.Serial, - Size: storage.Disk.Size, - Storage: storage.Disk.Storage, - Type: virtIO, - } + generalizedStorage.Disk = storage.Disk.convertDataStructure() } if storage.Passthrough != nil { - generalizedStorage.Passthrough = &qemuDisk{ - AsyncIO: storage.Passthrough.AsyncIO, - Backup: storage.Passthrough.Backup, - Bandwidth: storage.Passthrough.Bandwidth, - Cache: storage.Passthrough.Cache, - Discard: storage.Passthrough.Discard, - File: storage.Passthrough.File, - IOThread: storage.Passthrough.IOThread, - ReadOnly: storage.Passthrough.ReadOnly, - Serial: storage.Passthrough.Serial, - Type: virtIO, - } + generalizedStorage.Passthrough = storage.Passthrough.convertDataStructure() } return &generalizedStorage } From 02dd49a1bf5ca0483c349e3ec3961de2f9f4f7e3 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 13 Mar 2023 17:46:25 +0000 Subject: [PATCH 051/120] feat: change to pointer changed to pointer to handle the unspecified case --- proxmox/config_qemu_disk.go | 64 +++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index f393abd7..cf089e5f 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -176,34 +176,34 @@ func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { // format // media - if disk.Bandwidth.Iops.ReadLimit.Concurrent >= 10 { - settings = settings + ",iops_rd=" + strconv.Itoa(int(disk.Bandwidth.Iops.ReadLimit.Concurrent)) + if disk.Bandwidth.Iops.ReadLimit.Concurrent != nil { + settings = settings + ",iops_rd=" + strconv.Itoa(int(*disk.Bandwidth.Iops.ReadLimit.Concurrent)) } - if disk.Bandwidth.Iops.ReadLimit.Burst >= 10 { - settings = settings + ",iops_rd_max=" + strconv.Itoa(int(disk.Bandwidth.Iops.ReadLimit.Burst)) + if disk.Bandwidth.Iops.ReadLimit.Burst != nil { + settings = settings + ",iops_rd_max=" + strconv.Itoa(int(*disk.Bandwidth.Iops.ReadLimit.Burst)) } - if disk.Bandwidth.Iops.WriteLimit.Concurrent >= 10 { - settings = settings + ",iops_wr=" + strconv.Itoa(int(disk.Bandwidth.Iops.WriteLimit.Concurrent)) + if disk.Bandwidth.Iops.WriteLimit.Concurrent != nil { + settings = settings + ",iops_wr=" + strconv.Itoa(int(*disk.Bandwidth.Iops.WriteLimit.Concurrent)) } - if disk.Bandwidth.Iops.WriteLimit.Burst >= 10 { - settings = settings + ",iops_wr_max=" + strconv.Itoa(int(disk.Bandwidth.Iops.WriteLimit.Burst)) + if disk.Bandwidth.Iops.WriteLimit.Burst != nil { + settings = settings + ",iops_wr_max=" + strconv.Itoa(int(*disk.Bandwidth.Iops.WriteLimit.Burst)) } if (disk.Type == scsi || disk.Type == virtIO) && disk.IOThread { settings = settings + ",iothread=1" } - if disk.Bandwidth.Data.ReadLimit.Concurrent >= float32(1) { - settings = settings + fmt.Sprintf(",mbps_rd=%.2f", disk.Bandwidth.Data.ReadLimit.Concurrent) + if disk.Bandwidth.Data.ReadLimit.Concurrent != nil { + settings = settings + fmt.Sprintf(",mbps_rd=%.2f", *disk.Bandwidth.Data.ReadLimit.Concurrent) } - if disk.Bandwidth.Data.ReadLimit.Burst >= float32(1) { - settings = settings + fmt.Sprintf(",mbps_rd_max=%.2f", disk.Bandwidth.Data.ReadLimit.Burst) + if disk.Bandwidth.Data.ReadLimit.Burst != nil { + settings = settings + fmt.Sprintf(",mbps_rd_max=%.2f", *disk.Bandwidth.Data.ReadLimit.Burst) } - if disk.Bandwidth.Data.WriteLimit.Concurrent >= float32(1) { - settings = settings + fmt.Sprintf(",mbps_wr=%.2f", disk.Bandwidth.Data.WriteLimit.Concurrent) + if disk.Bandwidth.Data.WriteLimit.Concurrent != nil { + settings = settings + fmt.Sprintf(",mbps_wr=%.2f", *disk.Bandwidth.Data.WriteLimit.Concurrent) } - if disk.Bandwidth.Data.WriteLimit.Burst >= float32(1) { - settings = settings + fmt.Sprintf(",mbps_wr_max=%.2f", disk.Bandwidth.Data.WriteLimit.Burst) + if disk.Bandwidth.Data.WriteLimit.Burst != nil { + settings = settings + fmt.Sprintf(",mbps_wr_max=%.2f", *disk.Bandwidth.Data.WriteLimit.Burst) } if !disk.Replicate { @@ -270,19 +270,23 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { } if e[0] == "iops_rd" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.ReadLimit.Concurrent = uint(tmp) + pointer := uint(tmp) + disk.Bandwidth.Iops.ReadLimit.Concurrent = &pointer } if e[0] == "iops_rd_max" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.ReadLimit.Burst = uint(tmp) + pointer := uint(tmp) + disk.Bandwidth.Iops.ReadLimit.Burst = &pointer } if e[0] == "iops_wr" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.WriteLimit.Concurrent = uint(tmp) + pointer := uint(tmp) + disk.Bandwidth.Iops.WriteLimit.Concurrent = &pointer } if e[0] == "iops_wr_max" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.WriteLimit.Burst = uint(tmp) + pointer := uint(tmp) + disk.Bandwidth.Iops.WriteLimit.Burst = &pointer } if e[0] == "iothread" { disk.IOThread, _ = strconv.ParseBool(e[1]) @@ -290,19 +294,23 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { } if e[0] == "mbps_rd" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.ReadLimit.Concurrent = float32(math.Round(tmp*100) / 100) + pointer := float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.ReadLimit.Concurrent = &pointer } if e[0] == "mbps_rd_max" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.ReadLimit.Burst = float32(math.Round(tmp*100) / 100) + pointer := float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.ReadLimit.Burst = &pointer } if e[0] == "mbps_wr" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.WriteLimit.Concurrent = float32(math.Round(tmp*100) / 100) + pointer := float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.WriteLimit.Concurrent = &pointer } if e[0] == "mbps_wr_max" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.WriteLimit.Burst = float32(math.Round(tmp*100) / 100) + pointer := float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.WriteLimit.Burst = &pointer } if e[0] == "replicate" { disk.Replicate, _ = strconv.ParseBool(e[1]) @@ -355,8 +363,8 @@ type QemuDiskBandwidthData struct { } type QemuDiskBandwidthDataLimit struct { - Concurrent float32 - Burst float32 + Burst *float32 // nil = default + Concurrent *float32 // nil = unlimited } type QemuDiskBandwidthIops struct { @@ -365,8 +373,8 @@ type QemuDiskBandwidthIops struct { } type QemuDiskBandwidthIopsLimit struct { - Concurrent uint - Burst uint + Burst *uint // nil = default + Concurrent *uint // nil = unlimited } type QemuDiskCache string From 297dc143d06b17849935285f8fab7c73a40db915 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 13 Mar 2023 17:49:56 +0000 Subject: [PATCH 052/120] fix: typo --- proxmox/config_qemu_disk_ide.go | 2 +- proxmox/config_qemu_disk_sata.go | 2 +- proxmox/config_qemu_disk_scsi.go | 2 +- proxmox/config_qemu_disk_virtio.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 9b485388..36ed4a60 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -3,7 +3,7 @@ package proxmox type QemuIdeDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` Backup bool `json:"backup,omitempty"` - Bandwidth QemuDiskBandwidth `json:"bandwith,omitempty"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 1079e424..b299e413 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -3,7 +3,7 @@ package proxmox type QemuSataDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` Backup bool `json:"backup,omitempty"` - Bandwidth QemuDiskBandwidth `json:"bandwith,omitempty"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index dd1cd340..6694d3dd 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -3,7 +3,7 @@ package proxmox type QemuScsiDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` Backup bool `json:"backup,omitempty"` - Bandwidth QemuDiskBandwidth `json:"bandwith,omitempty"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 8101307c..13310837 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -3,7 +3,7 @@ package proxmox type QemuVirtIODisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` Backup bool `json:"backup,omitempty"` - Bandwidth QemuDiskBandwidth `json:"bandwith,omitempty"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` Format *QemuDiskFormat `json:"format,omitempty"` From 34ea69232c6b6e5ea8043f983574125335cdeb19 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 14 Mar 2023 14:07:15 +0000 Subject: [PATCH 053/120] feat: add Validator for `QemuDiskBandwidth` and sub types --- proxmox/config_qemu_disk.go | 44 ++++++++ proxmox/config_qemu_disk_test.go | 178 +++++++++++++++++++++++++++++++ 2 files changed, 222 insertions(+) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index cf089e5f..6c018fa2 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -357,26 +357,70 @@ type QemuDiskBandwidth struct { Iops QemuDiskBandwidthIops } +func (bandwidth QemuDiskBandwidth) Validate() error { + err := bandwidth.Data.Validate() + if err != nil { + return err + } + return bandwidth.Iops.Validate() +} + type QemuDiskBandwidthData struct { ReadLimit QemuDiskBandwidthDataLimit WriteLimit QemuDiskBandwidthDataLimit } +func (data QemuDiskBandwidthData) Validate() error { + err := data.ReadLimit.Validate() + if err != nil { + return err + } + return data.WriteLimit.Validate() +} + type QemuDiskBandwidthDataLimit struct { Burst *float32 // nil = default Concurrent *float32 // nil = unlimited } +func (limit QemuDiskBandwidthDataLimit) Validate() error { + if limit.Burst != nil && *limit.Burst < 1 { + return errors.New("burst may not be lower then 1") + } + if limit.Concurrent != nil && *limit.Concurrent < 1 { + return errors.New("concurrent may not be lower then 1") + } + return nil +} + type QemuDiskBandwidthIops struct { ReadLimit QemuDiskBandwidthIopsLimit WriteLimit QemuDiskBandwidthIopsLimit } +func (iops QemuDiskBandwidthIops) Validate() error { + err := iops.ReadLimit.Validate() + if err != nil { + return err + } + return iops.WriteLimit.Validate() +} + type QemuDiskBandwidthIopsLimit struct { Burst *uint // nil = default Concurrent *uint // nil = unlimited } +func (limit QemuDiskBandwidthIopsLimit) Validate() error { + if limit.Burst != nil && *limit.Burst < 10 { + return errors.New("burst may not be lower then 10") + } + if limit.Concurrent != nil && *limit.Concurrent < 10 { + return errors.New("concurrent may not be lower then 1") + } + return nil +} + type QemuDiskCache string const ( diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 25274d88..e83ff256 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -30,6 +30,184 @@ func Test_QemuDiskAsyncIO_Validate(t *testing.T) { } } +func Test_QemuDiskBandwidth_Validate(t *testing.T) { + float0 := float32(0) + float0a := float32(0.99) + float1 := float32(1) + uint0 := uint(0) + uint9 := uint(9) + uint10 := uint(10) + testData := []struct { + input QemuDiskBandwidth + err bool + }{ + // Valid + {input: QemuDiskBandwidth{}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float1}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float1}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float1}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float1}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint10}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint10}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint10}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint10}}}}, + // Invalid + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float0}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float0a}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0a}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float0}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float0a}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0a}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint9}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint0}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint9}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint0}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint9}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint0}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint9}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint0}}}, err: true}, + } + for _, e := range testData { + if e.err { + require.Error(t, e.input.Validate()) + } else { + require.NoError(t, e.input.Validate()) + } + } +} + +func Test_QemuDiskBandwidthData_Validate(t *testing.T) { + float0 := float32(0) + float0a := float32(0.99) + float1 := float32(1) + testData := []struct { + input QemuDiskBandwidthData + err bool + }{ + // Valid + {input: QemuDiskBandwidthData{}}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float1}}}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float1}}}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float1}}}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float1}}}, + // Invalid + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float0}}, err: true}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float0a}}, err: true}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0}}, err: true}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0a}}, err: true}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float0}}, err: true}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float0a}}, err: true}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0}}, err: true}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0a}}, err: true}, + } + for _, e := range testData { + if e.err { + require.Error(t, e.input.Validate()) + } else { + require.NoError(t, e.input.Validate()) + } + } +} + +func Test_QemuDiskBandwidthDataLimit_Validate(t *testing.T) { + float0 := float32(0) + float0a := float32(0.99) + float1 := float32(1) + testData := []struct { + input QemuDiskBandwidthDataLimit + err bool + }{ + // Valid + {input: QemuDiskBandwidthDataLimit{}}, + {input: QemuDiskBandwidthDataLimit{Burst: &float1}}, + {input: QemuDiskBandwidthDataLimit{Concurrent: &float1}}, + // Invalid + {input: QemuDiskBandwidthDataLimit{Burst: &float0}, err: true}, + {input: QemuDiskBandwidthDataLimit{Burst: &float0a}, err: true}, + {input: QemuDiskBandwidthDataLimit{Concurrent: &float0}, err: true}, + {input: QemuDiskBandwidthDataLimit{Concurrent: &float0a}, err: true}, + } + for _, e := range testData { + if e.err { + require.Error(t, e.input.Validate()) + } else { + require.NoError(t, e.input.Validate()) + } + } +} + +func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { + uint0 := uint(0) + uint9 := uint(9) + uint10 := uint(10) + testData := []struct { + input QemuDiskBandwidthIops + err bool + }{ + // Valid + {input: QemuDiskBandwidthIops{}}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint10}}}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint10}}}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint10}}}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint10}}}, + // Invalid + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint0}}, err: true}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint9}}, err: true}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint0}}, err: true}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint9}}, err: true}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint0}}, err: true}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint9}}, err: true}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint0}}, err: true}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint9}}, err: true}, + } + for _, e := range testData { + if e.err { + require.Error(t, e.input.Validate()) + } else { + require.NoError(t, e.input.Validate()) + } + } +} + +func Test_QemuDiskBandwidthIopsLimit_Validate(t *testing.T) { + uint0 := uint(0) + uint9 := uint(9) + uint10 := uint(10) + testData := []struct { + input QemuDiskBandwidthIopsLimit + err bool + }{ + // Valid + {input: QemuDiskBandwidthIopsLimit{}}, + {input: QemuDiskBandwidthIopsLimit{Burst: &uint10}}, + {input: QemuDiskBandwidthIopsLimit{Concurrent: &uint10}}, + // Invalid + {input: QemuDiskBandwidthIopsLimit{Burst: &uint0}, err: true}, + {input: QemuDiskBandwidthIopsLimit{Burst: &uint9}, err: true}, + {input: QemuDiskBandwidthIopsLimit{Concurrent: &uint0}, err: true}, + {input: QemuDiskBandwidthIopsLimit{Concurrent: &uint9}, err: true}, + } + for _, e := range testData { + if e.err { + require.Error(t, e.input.Validate()) + } else { + require.NoError(t, e.input.Validate()) + } + } +} + func Test_QemuDiskCache_Validate(t *testing.T) { testData := []struct { input QemuDiskCache From 5412645083ab6bf5cd82d26ea6612faf5ef6e442 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 14 Mar 2023 14:14:46 +0000 Subject: [PATCH 054/120] feat: add Validate func for `IsoFile` --- proxmox/config_qemu_disk.go | 12 +++++++++++- proxmox/config_qemu_disk_test.go | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 6c018fa2..af47d24b 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -10,12 +10,22 @@ import ( ) type IsoFile struct { - Storage string `json:"storage"` File string `json:"file"` + Storage string `json:"storage"` // Size can only be retrieved, setting it has no effect Size string `json:"size"` } +func (iso IsoFile) Validate() error { + if iso.File == "" { + return errors.New("file may not be empty") + } + if iso.Storage == "" { + return errors.New("storage may not be empty") + } + return nil +} + type QemuCdRom struct { Iso *IsoFile `json:"iso,omitempty"` // Passthrough and File are mutually exclusive diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index e83ff256..6aab269b 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -7,6 +7,28 @@ import ( "github.com/stretchr/testify/require" ) +func Test_IsoFile_Validate(t *testing.T) { + testData := []struct { + input IsoFile + err bool + }{ + // Valid + {input: IsoFile{File: "anything", Storage: "something"}}, + // Invalid + {input: IsoFile{}, err: true}, + {input: IsoFile{File: "anything"}, err: true}, + {input: IsoFile{Storage: "something"}, err: true}, + {input: IsoFile{Size: "something"}, err: true}, + } + for _, e := range testData { + if e.err { + require.Error(t, e.input.Validate()) + } else { + require.NoError(t, e.input.Validate()) + } + } +} + func Test_QemuDiskAsyncIO_Validate(t *testing.T) { testData := []struct { input QemuDiskAsyncIO From 40731aa396d2af6feab9ef5c746b9bace44c1a19 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 14 Mar 2023 14:23:27 +0000 Subject: [PATCH 055/120] feat: add Validate func for `QemuCdRom` --- proxmox/config_qemu_disk.go | 13 +++++++++++++ proxmox/config_qemu_disk_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index af47d24b..c9b9d7be 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -56,6 +56,19 @@ func (QemuCdRom) mapToStruct(settings qemuCdRom) *QemuCdRom { return &QemuCdRom{Passthrough: false} } +func (cdRom QemuCdRom) Validate() error { + if cdRom.Iso != nil { + err := cdRom.Iso.Validate() + if err != nil { + return err + } + if cdRom.Passthrough { + return errors.New("iso and passthrough are mutually exclusive") + } + } + return nil +} + type qemuCdRom struct { // "local:iso/debian-11.0.0-amd64-netinst.iso,media=cdrom,size=377M" Passthrough bool diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 6aab269b..f42a094b 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -29,6 +29,31 @@ func Test_IsoFile_Validate(t *testing.T) { } } +func Test_QemuCdRom_Validate(t *testing.T) { + testData := []struct { + input QemuCdRom + err bool + }{ + // Valid + {input: QemuCdRom{}}, + {input: QemuCdRom{Iso: &IsoFile{File: "anything", Storage: "Something"}}}, + {input: QemuCdRom{Passthrough: true}}, + // Invalid + {input: QemuCdRom{Iso: &IsoFile{}}, err: true}, + {input: QemuCdRom{Iso: &IsoFile{File: "anything"}}, err: true}, + {input: QemuCdRom{Iso: &IsoFile{Storage: "something"}}, err: true}, + {input: QemuCdRom{Iso: &IsoFile{Size: "something"}}, err: true}, + {input: QemuCdRom{Iso: &IsoFile{File: "anything", Storage: "something"}, Passthrough: true}, err: true}, + } + for _, e := range testData { + if e.err { + require.Error(t, e.input.Validate()) + } else { + require.NoError(t, e.input.Validate()) + } + } +} + func Test_QemuDiskAsyncIO_Validate(t *testing.T) { testData := []struct { input QemuDiskAsyncIO From 65ea0b2c1155db04de9e55b5860ef09a94a0c019 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 14 Mar 2023 15:45:01 +0000 Subject: [PATCH 056/120] feat: make format optional --- proxmox/config_qemu_disk.go | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index c9b9d7be..308b6b65 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -70,13 +70,13 @@ func (cdRom QemuCdRom) Validate() error { } type qemuCdRom struct { + CdRom bool // "local:iso/debian-11.0.0-amd64-netinst.iso,media=cdrom,size=377M" Passthrough bool Storage string - // FileType is only set for Cloud init drives, this value will be used to check if it is a normal cdrom or cloud init drive. - FileType string - File string - Size string + Format *QemuDiskFormat // Only set for Cloud-init drives + File string + Size string } func (qemuCdRom) mapToStruct(settings [][]string) *qemuCdRom { @@ -104,11 +104,12 @@ func (qemuCdRom) mapToStruct(settings [][]string) *qemuCdRom { if len(tmpFile) == 2 { tmpFileType := strings.Split(tmpFile[1], ".") if len(tmpFileType) > 1 { - fileType := tmpFileType[len(tmpFileType)-1] + fileType := QemuDiskFormat(tmpFileType[len(tmpFileType)-1]) if fileType == "iso" { for _, e := range settings { if e[0] == "size" { return &qemuCdRom{ + CdRom: true, Storage: tmpStorage[0], File: tmpFile[1], Size: e[1], @@ -117,9 +118,9 @@ func (qemuCdRom) mapToStruct(settings [][]string) *qemuCdRom { } } else { return &qemuCdRom{ - Storage: tmpStorage[0], - File: tmpFile[1], - FileType: fileType, + Storage: tmpStorage[0], + File: tmpFile[1], + Format: &fileType, } } } @@ -129,19 +130,25 @@ func (qemuCdRom) mapToStruct(settings [][]string) *qemuCdRom { } type QemuCloudInitDisk struct { - FileType string - Storage string + Format *QemuDiskFormat `json:"format,omitempty"` + Storage string `json:"storage,omitempty"` } // TODO write test func (cloudInit QemuCloudInitDisk) mapToApiValues() string { - return cloudInit.Storage + ":cloudinit,format=" + cloudInit.FileType + var fileType string + if cloudInit.Format == nil { + fileType = "raw" + } else { + fileType = string(*cloudInit.Format) + } + return cloudInit.Storage + ":cloudinit,format=" + fileType } func (QemuCloudInitDisk) mapToStruct(settings qemuCdRom) *QemuCloudInitDisk { return &QemuCloudInitDisk{ - Storage: settings.Storage, - FileType: settings.FileType, + Storage: settings.Storage, + Format: settings.Format, } } From 3d39fd5381fcf415bef28c524226673ae645d9b1 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 14 Mar 2023 15:49:20 +0000 Subject: [PATCH 057/120] feat: allow for empty case --- proxmox/config_qemu_disk.go | 2 +- proxmox/config_qemu_disk_test.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 308b6b65..38c5a840 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -483,7 +483,7 @@ const ( func (format QemuDiskFormat) Validate() error { switch format { - case QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw: + case "", QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw: return nil } return fmt.Errorf("format can only be one of the following values: %s,%s,%s,%s,%s,%s,%s", QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw) diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index f42a094b..8604e492 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -286,6 +286,7 @@ func Test_QemuDiskFormat_Validate(t *testing.T) { err bool }{ // Valid + {input: ""}, {input: QemuDiskFormat_Cow}, {input: QemuDiskFormat_Cloop}, {input: QemuDiskFormat_Qcow}, From f5c740e73d14d3c23034754b43c7173463cb26cb Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 14 Mar 2023 15:59:38 +0000 Subject: [PATCH 058/120] fix: format should never be empty --- proxmox/config_qemu_disk.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 38c5a840..308b6b65 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -483,7 +483,7 @@ const ( func (format QemuDiskFormat) Validate() error { switch format { - case "", QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw: + case QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw: return nil } return fmt.Errorf("format can only be one of the following values: %s,%s,%s,%s,%s,%s,%s", QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw) From 9ef20edd26bf8e244600f2fff66e48f900cea6c1 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:03:05 +0000 Subject: [PATCH 059/120] feat: add Validate func for `QemuCloudInitDisk` --- proxmox/config_qemu_disk.go | 12 ++++++++++++ proxmox/config_qemu_disk_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 308b6b65..ab78a883 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -152,6 +152,18 @@ func (QemuCloudInitDisk) mapToStruct(settings qemuCdRom) *QemuCloudInitDisk { } } +func (cloudInit QemuCloudInitDisk) Validate() error { + if cloudInit.Format != nil { + if err := cloudInit.Format.Validate(); err != nil { + return err + } + } + if cloudInit.Storage == "" { + return errors.New("storage should not be empty") + } + return nil +} + type qemuDisk struct { AsyncIO QemuDiskAsyncIO Backup bool diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 8604e492..87af395a 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -54,6 +54,32 @@ func Test_QemuCdRom_Validate(t *testing.T) { } } +func Test_QemuCloudInitDisk_Validate(t *testing.T) { + formatRaw := QemuDiskFormat_Raw + formatEmpty := QemuDiskFormat("") + formatInvalid := QemuDiskFormat("invalid") + testData := []struct { + input QemuCloudInitDisk + err bool + }{ + // Valid + {input: QemuCloudInitDisk{Storage: "anything"}}, + {input: QemuCloudInitDisk{Storage: "anything", Format: &formatRaw}}, + // Invalid + {input: QemuCloudInitDisk{}, err: true}, + {input: QemuCloudInitDisk{Format: &formatRaw}, err: true}, + {input: QemuCloudInitDisk{Storage: "anything", Format: &formatEmpty}, err: true}, + {input: QemuCloudInitDisk{Storage: "anything", Format: &formatInvalid}, err: true}, + } + for _, e := range testData { + if e.err { + require.Error(t, e.input.Validate()) + } else { + require.NoError(t, e.input.Validate()) + } + } +} + func Test_QemuDiskAsyncIO_Validate(t *testing.T) { testData := []struct { input QemuDiskAsyncIO From e9d6cc101bcf91243246a73ca9c747ee5d84a5d2 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:04:58 +0000 Subject: [PATCH 060/120] fix: remove empty case --- proxmox/config_qemu_disk_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 87af395a..a981ef83 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -312,7 +312,6 @@ func Test_QemuDiskFormat_Validate(t *testing.T) { err bool }{ // Valid - {input: ""}, {input: QemuDiskFormat_Cow}, {input: QemuDiskFormat_Cloop}, {input: QemuDiskFormat_Qcow}, From 01808d2aef6c32b94e0bafabc6e4b7ad9079679c Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:06:39 +0000 Subject: [PATCH 061/120] fix: allow for empty case --- proxmox/config_qemu_disk.go | 2 +- proxmox/config_qemu_disk_test.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index ab78a883..797bc296 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -388,7 +388,7 @@ const ( func (asyncIO QemuDiskAsyncIO) Validate() error { switch asyncIO { - case QemuDiskAsyncIO_Native, QemuDiskAsyncIO_Threads, QemuDiskAsyncIO_IOuring: + case "", QemuDiskAsyncIO_Native, QemuDiskAsyncIO_Threads, QemuDiskAsyncIO_IOuring: return nil } return fmt.Errorf("asyncio can only be one of the following values: %s,%s,%s", QemuDiskAsyncIO_Native, QemuDiskAsyncIO_Threads, QemuDiskAsyncIO_IOuring) diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index a981ef83..444041a5 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -86,6 +86,7 @@ func Test_QemuDiskAsyncIO_Validate(t *testing.T) { err bool }{ // Valid + {input: ""}, {input: QemuDiskAsyncIO_Native}, {input: QemuDiskAsyncIO_Threads}, {input: QemuDiskAsyncIO_IOuring}, From ddfe86605018f6ff5900e5f48bc1ac4daf68a23f Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:14:24 +0000 Subject: [PATCH 062/120] refactor: make code more reusable --- proxmox/config_qemu_disk_ide.go | 20 ++++++-- proxmox/config_qemu_disk_sata.go | 24 +++++++--- proxmox/config_qemu_disk_scsi.go | 74 +++++++++++++++++------------- proxmox/config_qemu_disk_virtio.go | 44 +++++++++++------- 4 files changed, 105 insertions(+), 57 deletions(-) diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 36ed4a60..444bb035 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -1,5 +1,7 @@ package proxmox +import "strconv" + type QemuIdeDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` Backup bool `json:"backup,omitempty"` @@ -46,10 +48,20 @@ func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, vmID uint, if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_0.convertDataStructure(), vmID, "ide0", params, changes) - disks.Disk_1.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_1.convertDataStructure(), vmID, "ide1", params, changes) - disks.Disk_2.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_2.convertDataStructure(), vmID, "ide2", params, changes) - disks.Disk_3.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_3.convertDataStructure(), vmID, "ide3", params, changes) + diskMap := disks.mapToIntMap() + currentDiskMap := tmpCurrentDisks.mapToIntMap() + for i := range diskMap { + diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, "ide"+strconv.Itoa(int(i)), params, changes) + } +} + +func (disks QemuIdeDisks) mapToIntMap() map[uint8]*QemuIdeStorage { + return map[uint8]*QemuIdeStorage{ + 0: disks.Disk_0, + 1: disks.Disk_1, + 2: disks.Disk_2, + 3: disks.Disk_3, + } } // TODO write test diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index b299e413..44d472f9 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -1,5 +1,7 @@ package proxmox +import "strconv" + type QemuSataDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` Backup bool `json:"backup,omitempty"` @@ -48,12 +50,22 @@ func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, vmID uint if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_0.convertDataStructure(), vmID, "sata0", params, changes) - disks.Disk_1.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_1.convertDataStructure(), vmID, "sata1", params, changes) - disks.Disk_2.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_2.convertDataStructure(), vmID, "sata2", params, changes) - disks.Disk_3.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_3.convertDataStructure(), vmID, "sata3", params, changes) - disks.Disk_4.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_4.convertDataStructure(), vmID, "sata4", params, changes) - disks.Disk_5.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_5.convertDataStructure(), vmID, "sata5", params, changes) + diskMap := disks.mapToIntMap() + currentDiskMap := tmpCurrentDisks.mapToIntMap() + for i := range diskMap { + diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, "sata"+strconv.Itoa(int(i)), params, changes) + } +} + +func (disks QemuSataDisks) mapToIntMap() map[uint8]*QemuSataStorage { + return map[uint8]*QemuSataStorage{ + 0: disks.Disk_0, + 1: disks.Disk_1, + 2: disks.Disk_2, + 3: disks.Disk_3, + 4: disks.Disk_4, + 5: disks.Disk_5, + } } // TODO write test diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 6694d3dd..22fc98c0 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -1,5 +1,7 @@ package proxmox +import "strconv" + type QemuScsiDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` Backup bool `json:"backup,omitempty"` @@ -77,37 +79,47 @@ func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, vmID uint if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_0.convertDataStructure(), vmID, "scsi0", params, changes) - disks.Disk_1.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_1.convertDataStructure(), vmID, "scsi1", params, changes) - disks.Disk_2.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_2.convertDataStructure(), vmID, "scsi2", params, changes) - disks.Disk_3.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_3.convertDataStructure(), vmID, "scsi3", params, changes) - disks.Disk_4.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_4.convertDataStructure(), vmID, "scsi4", params, changes) - disks.Disk_5.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_5.convertDataStructure(), vmID, "scsi5", params, changes) - disks.Disk_6.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_6.convertDataStructure(), vmID, "scsi6", params, changes) - disks.Disk_7.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_7.convertDataStructure(), vmID, "scsi7", params, changes) - disks.Disk_8.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_8.convertDataStructure(), vmID, "scsi8", params, changes) - disks.Disk_9.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_9.convertDataStructure(), vmID, "scsi9", params, changes) - disks.Disk_10.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_10.convertDataStructure(), vmID, "scsi10", params, changes) - disks.Disk_11.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_11.convertDataStructure(), vmID, "scsi11", params, changes) - disks.Disk_12.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_12.convertDataStructure(), vmID, "scsi12", params, changes) - disks.Disk_13.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_13.convertDataStructure(), vmID, "scsi13", params, changes) - disks.Disk_14.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_14.convertDataStructure(), vmID, "scsi14", params, changes) - disks.Disk_15.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_15.convertDataStructure(), vmID, "scsi15", params, changes) - disks.Disk_16.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_16.convertDataStructure(), vmID, "scsi16", params, changes) - disks.Disk_17.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_17.convertDataStructure(), vmID, "scsi17", params, changes) - disks.Disk_18.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_18.convertDataStructure(), vmID, "scsi18", params, changes) - disks.Disk_19.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_19.convertDataStructure(), vmID, "scsi19", params, changes) - disks.Disk_20.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_20.convertDataStructure(), vmID, "scsi20", params, changes) - disks.Disk_21.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_21.convertDataStructure(), vmID, "scsi21", params, changes) - disks.Disk_22.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_22.convertDataStructure(), vmID, "scsi22", params, changes) - disks.Disk_23.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_23.convertDataStructure(), vmID, "scsi23", params, changes) - disks.Disk_24.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_24.convertDataStructure(), vmID, "scsi24", params, changes) - disks.Disk_25.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_25.convertDataStructure(), vmID, "scsi25", params, changes) - disks.Disk_26.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_26.convertDataStructure(), vmID, "scsi26", params, changes) - disks.Disk_27.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_27.convertDataStructure(), vmID, "scsi27", params, changes) - disks.Disk_28.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_28.convertDataStructure(), vmID, "scsi28", params, changes) - disks.Disk_29.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_29.convertDataStructure(), vmID, "scsi29", params, changes) - disks.Disk_30.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_30.convertDataStructure(), vmID, "scsi30", params, changes) + diskMap := disks.mapToIntMap() + currentDiskMap := tmpCurrentDisks.mapToIntMap() + for i := range diskMap { + diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, "scsi"+strconv.Itoa(int(i)), params, changes) + } +} + +func (disks QemuScsiDisks) mapToIntMap() map[uint8]*QemuScsiStorage { + return map[uint8]*QemuScsiStorage{ + 0: disks.Disk_0, + 1: disks.Disk_1, + 2: disks.Disk_2, + 3: disks.Disk_3, + 4: disks.Disk_4, + 5: disks.Disk_5, + 6: disks.Disk_6, + 7: disks.Disk_7, + 8: disks.Disk_8, + 9: disks.Disk_9, + 10: disks.Disk_10, + 11: disks.Disk_11, + 12: disks.Disk_12, + 13: disks.Disk_13, + 14: disks.Disk_14, + 15: disks.Disk_15, + 16: disks.Disk_16, + 17: disks.Disk_17, + 18: disks.Disk_18, + 19: disks.Disk_19, + 20: disks.Disk_20, + 21: disks.Disk_21, + 22: disks.Disk_22, + 23: disks.Disk_23, + 24: disks.Disk_24, + 25: disks.Disk_25, + 26: disks.Disk_26, + 27: disks.Disk_27, + 28: disks.Disk_28, + 29: disks.Disk_29, + 30: disks.Disk_30, + } } // TODO write test diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 13310837..69389b7f 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -1,5 +1,7 @@ package proxmox +import "strconv" + type QemuVirtIODisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` Backup bool `json:"backup,omitempty"` @@ -60,22 +62,32 @@ func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, vmID if currentDisks != nil { tmpCurrentDisks = *currentDisks } - disks.Disk_0.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_0.convertDataStructure(), vmID, "virtio0", params, changes) - disks.Disk_1.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_1.convertDataStructure(), vmID, "virtio1", params, changes) - disks.Disk_2.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_2.convertDataStructure(), vmID, "virtio2", params, changes) - disks.Disk_3.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_3.convertDataStructure(), vmID, "virtio3", params, changes) - disks.Disk_4.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_4.convertDataStructure(), vmID, "virtio4", params, changes) - disks.Disk_5.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_5.convertDataStructure(), vmID, "virtio5", params, changes) - disks.Disk_6.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_6.convertDataStructure(), vmID, "virtio6", params, changes) - disks.Disk_7.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_7.convertDataStructure(), vmID, "virtio7", params, changes) - disks.Disk_8.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_8.convertDataStructure(), vmID, "virtio8", params, changes) - disks.Disk_9.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_9.convertDataStructure(), vmID, "virtio9", params, changes) - disks.Disk_10.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_10.convertDataStructure(), vmID, "virtio10", params, changes) - disks.Disk_11.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_11.convertDataStructure(), vmID, "virtio11", params, changes) - disks.Disk_12.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_12.convertDataStructure(), vmID, "virtio12", params, changes) - disks.Disk_13.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_13.convertDataStructure(), vmID, "virtio13", params, changes) - disks.Disk_14.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_14.convertDataStructure(), vmID, "virtio14", params, changes) - disks.Disk_15.convertDataStructure().markDiskChanges(tmpCurrentDisks.Disk_15.convertDataStructure(), vmID, "virtio15", params, changes) + diskMap := disks.mapToIntMap() + currentDiskMap := tmpCurrentDisks.mapToIntMap() + for i := range diskMap { + diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, "virtio"+strconv.Itoa(int(i)), params, changes) + } +} + +func (disks QemuVirtIODisks) mapToIntMap() map[uint8]*QemuVirtIOStorage { + return map[uint8]*QemuVirtIOStorage{ + 0: disks.Disk_0, + 1: disks.Disk_1, + 2: disks.Disk_2, + 3: disks.Disk_3, + 4: disks.Disk_4, + 5: disks.Disk_5, + 6: disks.Disk_6, + 7: disks.Disk_7, + 8: disks.Disk_8, + 9: disks.Disk_9, + 10: disks.Disk_10, + 11: disks.Disk_11, + 12: disks.Disk_12, + 13: disks.Disk_13, + 14: disks.Disk_14, + 15: disks.Disk_15, + } } // TODO write test From 1c1908c6d9ecf123e1c44b79929376be306bcf16 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:16:59 +0000 Subject: [PATCH 063/120] fix: check correct value --- proxmox/config_qemu_disk_ide.go | 2 +- proxmox/config_qemu_disk_sata.go | 2 +- proxmox/config_qemu_disk_scsi.go | 2 +- proxmox/config_qemu_disk_virtio.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 444bb035..09db6719 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -149,7 +149,7 @@ func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) if tmpCdRom != nil { - if tmpCdRom.FileType == "" { + if tmpCdRom.CdRom { return &QemuIdeStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} } else { return &QemuIdeStorage{CloudInit: QemuCloudInitDisk{}.mapToStruct(*tmpCdRom)} diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 44d472f9..49778505 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -161,7 +161,7 @@ func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) if tmpCdRom != nil { - if tmpCdRom.FileType == "" { + if tmpCdRom.CdRom { return &QemuSataStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} } else { return &QemuSataStorage{CloudInit: QemuCloudInitDisk{}.mapToStruct(*tmpCdRom)} diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 22fc98c0..13d32c18 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -319,7 +319,7 @@ func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) if tmpCdRom != nil { - if tmpCdRom.FileType == "" { + if tmpCdRom.CdRom { return &QemuScsiStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} } else { return &QemuScsiStorage{CloudInit: QemuCloudInitDisk{}.mapToStruct(*tmpCdRom)} diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 69389b7f..f983be93 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -223,7 +223,7 @@ func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) if tmpCdRom != nil { - if tmpCdRom.FileType == "" { + if tmpCdRom.CdRom { return &QemuVirtIOStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} } else { return &QemuVirtIOStorage{CloudInit: QemuCloudInitDisk{}.mapToStruct(*tmpCdRom)} From cb072a65e65c7f2b6017da2cb520d932c02662f6 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 13:49:56 +0000 Subject: [PATCH 064/120] feat: add `Disk` property to `qemuDisk` --- proxmox/config_qemu_disk.go | 1 + proxmox/config_qemu_disk_ide.go | 1 + proxmox/config_qemu_disk_sata.go | 1 + proxmox/config_qemu_disk_scsi.go | 1 + proxmox/config_qemu_disk_virtio.go | 1 + 5 files changed, 5 insertions(+) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 797bc296..351d78fc 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -170,6 +170,7 @@ type qemuDisk struct { Bandwidth QemuDiskBandwidth Cache QemuDiskCache Discard bool + Disk bool // true = disk, false = passthrough EmulateSSD bool // Only set for ide,sata,scsi // TODO custom type File string // Only set for Passthrough. diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 09db6719..f66cd482 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -24,6 +24,7 @@ func (disk *QemuIdeDisk) convertDataStructure() *qemuDisk { Bandwidth: disk.Bandwidth, Cache: disk.Cache, Discard: disk.Discard, + Disk: true, EmulateSSD: disk.EmulateSSD, Format: disk.Format, Id: disk.Id, diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 49778505..19c4f313 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -24,6 +24,7 @@ func (disk *QemuSataDisk) convertDataStructure() *qemuDisk { Bandwidth: disk.Bandwidth, Cache: disk.Cache, Discard: disk.Discard, + Disk: true, EmulateSSD: disk.EmulateSSD, Format: disk.Format, Id: disk.Id, diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 13d32c18..dee205a6 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -26,6 +26,7 @@ func (disk *QemuScsiDisk) convertDataStructure() *qemuDisk { Bandwidth: disk.Bandwidth, Cache: disk.Cache, Discard: disk.Discard, + Disk: true, EmulateSSD: disk.EmulateSSD, Format: disk.Format, Id: disk.Id, diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index f983be93..6cba1280 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -25,6 +25,7 @@ func (disk *QemuVirtIODisk) convertDataStructure() *qemuDisk { Bandwidth: disk.Bandwidth, Cache: disk.Cache, Discard: disk.Discard, + Disk: true, Format: disk.Format, Id: disk.Id, IOThread: disk.IOThread, From 7952dd3bcecbd997a015a57c4d455803417fea7d Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 14:46:22 +0000 Subject: [PATCH 065/120] refactor: make `QemuDiskFormat` required reduce config complexity for now --- proxmox/config_qemu_disk.go | 22 +++++++--------------- proxmox/config_qemu_disk_test.go | 9 ++++----- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 351d78fc..74b8d6d6 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -74,7 +74,7 @@ type qemuCdRom struct { // "local:iso/debian-11.0.0-amd64-netinst.iso,media=cdrom,size=377M" Passthrough bool Storage string - Format *QemuDiskFormat // Only set for Cloud-init drives + Format QemuDiskFormat // Only set for Cloud-init drives File string Size string } @@ -120,7 +120,7 @@ func (qemuCdRom) mapToStruct(settings [][]string) *qemuCdRom { return &qemuCdRom{ Storage: tmpStorage[0], File: tmpFile[1], - Format: &fileType, + Format: fileType, } } } @@ -130,19 +130,13 @@ func (qemuCdRom) mapToStruct(settings [][]string) *qemuCdRom { } type QemuCloudInitDisk struct { - Format *QemuDiskFormat `json:"format,omitempty"` - Storage string `json:"storage,omitempty"` + Format QemuDiskFormat `json:"format,omitempty"` + Storage string `json:"storage,omitempty"` } // TODO write test func (cloudInit QemuCloudInitDisk) mapToApiValues() string { - var fileType string - if cloudInit.Format == nil { - fileType = "raw" - } else { - fileType = string(*cloudInit.Format) - } - return cloudInit.Storage + ":cloudinit,format=" + fileType + return cloudInit.Storage + ":cloudinit,format=" + string(cloudInit.Format) } func (QemuCloudInitDisk) mapToStruct(settings qemuCdRom) *QemuCloudInitDisk { @@ -153,10 +147,8 @@ func (QemuCloudInitDisk) mapToStruct(settings qemuCdRom) *QemuCloudInitDisk { } func (cloudInit QemuCloudInitDisk) Validate() error { - if cloudInit.Format != nil { - if err := cloudInit.Format.Validate(); err != nil { - return err - } + if err := cloudInit.Format.Validate(); err != nil { + return err } if cloudInit.Storage == "" { return errors.New("storage should not be empty") diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 444041a5..b58fecbd 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -63,13 +63,12 @@ func Test_QemuCloudInitDisk_Validate(t *testing.T) { err bool }{ // Valid - {input: QemuCloudInitDisk{Storage: "anything"}}, - {input: QemuCloudInitDisk{Storage: "anything", Format: &formatRaw}}, + {input: QemuCloudInitDisk{Storage: "anything", Format: formatRaw}}, // Invalid {input: QemuCloudInitDisk{}, err: true}, - {input: QemuCloudInitDisk{Format: &formatRaw}, err: true}, - {input: QemuCloudInitDisk{Storage: "anything", Format: &formatEmpty}, err: true}, - {input: QemuCloudInitDisk{Storage: "anything", Format: &formatInvalid}, err: true}, + {input: QemuCloudInitDisk{Format: formatRaw}, err: true}, + {input: QemuCloudInitDisk{Storage: "anything", Format: formatEmpty}, err: true}, + {input: QemuCloudInitDisk{Storage: "anything", Format: formatInvalid}, err: true}, } for _, e := range testData { if e.err { From 1a3d4ed766349254ccda8b16c4997f479a140f3f Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 14:57:03 +0000 Subject: [PATCH 066/120] refactor: make `QemuDiskFormat` required reduce config complexity for now --- proxmox/config_qemu_disk.go | 16 ++++++---------- proxmox/config_qemu_disk_ide.go | 2 +- proxmox/config_qemu_disk_sata.go | 2 +- proxmox/config_qemu_disk_scsi.go | 2 +- proxmox/config_qemu_disk_virtio.go | 2 +- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 74b8d6d6..f2a942e7 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -165,10 +165,10 @@ type qemuDisk struct { Disk bool // true = disk, false = passthrough EmulateSSD bool // Only set for ide,sata,scsi // TODO custom type - File string // Only set for Passthrough. - Format *QemuDiskFormat // Only set for Disk - Id *uint // Only set for Disk - IOThread bool // Only set for scsi,virtio + File string // Only set for Passthrough. + Format QemuDiskFormat // Only set for Disk + Id *uint // Only set for Disk + IOThread bool // Only set for scsi,virtio Number uint ReadOnly bool // Only set for scsi,virtio Replicate bool @@ -187,7 +187,7 @@ func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { } else { // test:100/vm-100-disk-0.raw tmpId := strconv.Itoa(int(vmID)) - settings = disk.Storage + ":" + tmpId + "/vm-" + tmpId + "-disk-" + strconv.Itoa(int(*disk.Id)) + "." + string(*disk.Format) + settings = disk.Storage + ":" + tmpId + "/vm-" + tmpId + "-disk-" + strconv.Itoa(int(*disk.Id)) + "." + string(disk.Format) } } @@ -274,8 +274,7 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { if len(diskAndNumberAndFormat) == 2 { idAndFormat := strings.Split(diskAndNumberAndFormat[1], ".") if len(idAndFormat) == 2 { - tmpFormat := QemuDiskFormat(idAndFormat[1]) - disk.Format = &tmpFormat + disk.Format = QemuDiskFormat(idAndFormat[1]) tmp := strings.Split(idAndFormat[0], "-") if len(tmp) > 1 { tmpId, _ := strconv.Atoi(tmp[len(tmp)-1]) @@ -583,9 +582,6 @@ func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID ui if storage.Disk.Id == nil { storage.Disk.Id = currentStorage.Disk.Id } - if storage.Disk.Format == nil { - storage.Disk.Format = currentStorage.Disk.Format - } if storage.Disk.Storage != currentStorage.Disk.Storage { changes.Move = append(changes.Move, qemuDiskShort{ Id: id, diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index f66cd482..e8b2ec8d 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -9,7 +9,7 @@ type QemuIdeDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` - Format *QemuDiskFormat `json:"format,omitempty"` + Format QemuDiskFormat `json:"format,omitempty"` Id *uint `json:"id,omitempty"` Replicate bool `json:"replicate,omitempty"` Serial QemuDiskSerial `json:"serial,omitempty"` diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 19c4f313..d8f30216 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -9,7 +9,7 @@ type QemuSataDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` - Format *QemuDiskFormat `json:"format,omitempty"` + Format QemuDiskFormat `json:"format,omitempty"` Id *uint `json:"id,omitempty"` Replicate bool `json:"replicate,omitempty"` Serial QemuDiskSerial `json:"serial,omitempty"` diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index dee205a6..964a5752 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -9,7 +9,7 @@ type QemuScsiDisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` EmulateSSD bool `json:"emulatessd,omitempty"` - Format *QemuDiskFormat `json:"format,omitempty"` + Format QemuDiskFormat `json:"format,omitempty"` Id *uint `json:"id,omitempty"` IOThread bool `json:"iothread,omitempty"` ReadOnly bool `json:"readonly,omitempty"` diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 6cba1280..2e041885 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -8,7 +8,7 @@ type QemuVirtIODisk struct { Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard,omitempty"` - Format *QemuDiskFormat `json:"format,omitempty"` + Format QemuDiskFormat `json:"format,omitempty"` Id *uint `json:"id,omitempty"` IOThread bool `json:"iothread,omitempty"` ReadOnly bool `json:"readonly,omitempty"` From 3a188d7b57bb621878e54d2dd1f0ca3d3d9e289d Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 17:39:44 +0000 Subject: [PATCH 067/120] test: match exact error --- proxmox/config_qemu_disk.go | 6 +++++- proxmox/config_qemu_disk_test.go | 12 ++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index f2a942e7..244c4d9a 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -378,12 +378,16 @@ const ( QemuDiskAsyncIO_IOuring QemuDiskAsyncIO = "io_uring" ) +func (QemuDiskAsyncIO) Error() error { + return fmt.Errorf("asyncio can only be one of the following values: %s,%s,%s", QemuDiskAsyncIO_Native, QemuDiskAsyncIO_Threads, QemuDiskAsyncIO_IOuring) +} + func (asyncIO QemuDiskAsyncIO) Validate() error { switch asyncIO { case "", QemuDiskAsyncIO_Native, QemuDiskAsyncIO_Threads, QemuDiskAsyncIO_IOuring: return nil } - return fmt.Errorf("asyncio can only be one of the following values: %s,%s,%s", QemuDiskAsyncIO_Native, QemuDiskAsyncIO_Threads, QemuDiskAsyncIO_IOuring) + return QemuDiskAsyncIO("").Error() } type QemuDiskBandwidth struct { diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index b58fecbd..c345ca6b 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -82,7 +82,7 @@ func Test_QemuCloudInitDisk_Validate(t *testing.T) { func Test_QemuDiskAsyncIO_Validate(t *testing.T) { testData := []struct { input QemuDiskAsyncIO - err bool + err error }{ // Valid {input: ""}, @@ -90,13 +90,13 @@ func Test_QemuDiskAsyncIO_Validate(t *testing.T) { {input: QemuDiskAsyncIO_Threads}, {input: QemuDiskAsyncIO_IOuring}, // Invalid - {input: "bla", err: true}, - {input: "invalid value", err: true}, - {input: "!@#$", err: true}, + {input: "bla", err: QemuDiskAsyncIO("").Error()}, + {input: "invalid value", err: QemuDiskAsyncIO("").Error()}, + {input: "!@#$", err: QemuDiskAsyncIO("").Error()}, } for _, e := range testData { - if e.err { - require.Error(t, e.input.Validate()) + if e.err != nil { + require.Equal(t, e.input.Validate(), e.err) } else { require.NoError(t, e.input.Validate()) } From ddf2acfe40129c6ca0aca4f006e0091bd5871614 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 17:50:31 +0000 Subject: [PATCH 068/120] test: match exact error --- proxmox/config_qemu_disk.go | 8 ++++++-- proxmox/config_qemu_disk_test.go | 13 +++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 244c4d9a..b8aec495 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -469,12 +469,16 @@ const ( QemuDiskCache_DirectSync QemuDiskCache = "directsync" ) +func (QemuDiskCache) Error() error { + return fmt.Errorf("cache can only be one of the following values: %s,%s,%s,%s,%s", QemuDiskCache_None, QemuDiskCache_WriteThrough, QemuDiskCache_WriteBack, QemuDiskCache_Unsafe, QemuDiskCache_DirectSync) +} + func (cache QemuDiskCache) Validate() error { switch cache { - case QemuDiskCache_None, QemuDiskCache_WriteThrough, QemuDiskCache_WriteBack, QemuDiskCache_Unsafe, QemuDiskCache_DirectSync: + case "", QemuDiskCache_None, QemuDiskCache_WriteThrough, QemuDiskCache_WriteBack, QemuDiskCache_Unsafe, QemuDiskCache_DirectSync: return nil } - return fmt.Errorf("cache can only be one of the following values: %s,%s,%s,%s,%s", QemuDiskCache_None, QemuDiskCache_WriteThrough, QemuDiskCache_WriteBack, QemuDiskCache_Unsafe, QemuDiskCache_DirectSync) + return QemuDiskCache("").Error() } type QemuDiskFormat string diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index c345ca6b..7814a7f3 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -284,22 +284,23 @@ func Test_QemuDiskBandwidthIopsLimit_Validate(t *testing.T) { func Test_QemuDiskCache_Validate(t *testing.T) { testData := []struct { input QemuDiskCache - err bool + err error }{ // Valid + {input: ""}, {input: QemuDiskCache_None}, {input: QemuDiskCache_WriteThrough}, {input: QemuDiskCache_WriteBack}, {input: QemuDiskCache_Unsafe}, {input: QemuDiskCache_DirectSync}, // Invalid - {input: "bla", err: true}, - {input: "invalid value", err: true}, - {input: "!@#$", err: true}, + {input: "bla", err: QemuDiskCache("").Error()}, + {input: "invalid value", err: QemuDiskCache("").Error()}, + {input: "!@#$", err: QemuDiskCache("").Error()}, } for _, e := range testData { - if e.err { - require.Error(t, e.input.Validate()) + if e.err != nil { + require.Equal(t, e.input.Validate(), e.err) } else { require.NoError(t, e.input.Validate()) } From d1f36ec7fb793cde568b869bfddffade9221f310 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 17:54:15 +0000 Subject: [PATCH 069/120] test: match exact error --- proxmox/config_qemu_disk.go | 6 +++++- proxmox/config_qemu_disk_test.go | 12 ++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index b8aec495..8112b0ca 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -493,12 +493,16 @@ const ( QemuDiskFormat_Raw QemuDiskFormat = "raw" ) +func (QemuDiskFormat) Error() error { + return fmt.Errorf("format can only be one of the following values: %s,%s,%s,%s,%s,%s,%s", QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw) +} + func (format QemuDiskFormat) Validate() error { switch format { case QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw: return nil } - return fmt.Errorf("format can only be one of the following values: %s,%s,%s,%s,%s,%s,%s", QemuDiskFormat_Cow, QemuDiskFormat_Cloop, QemuDiskFormat_Qcow, QemuDiskFormat_Qcow2, QemuDiskFormat_Qed, QemuDiskFormat_Vmdk, QemuDiskFormat_Raw) + return QemuDiskFormat("").Error() } type QemuDiskSerial string diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 7814a7f3..ae990579 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -310,7 +310,7 @@ func Test_QemuDiskCache_Validate(t *testing.T) { func Test_QemuDiskFormat_Validate(t *testing.T) { testData := []struct { input QemuDiskFormat - err bool + err error }{ // Valid {input: QemuDiskFormat_Cow}, @@ -321,13 +321,13 @@ func Test_QemuDiskFormat_Validate(t *testing.T) { {input: QemuDiskFormat_Vmdk}, {input: QemuDiskFormat_Raw}, // Invalid - {input: "bla", err: true}, - {input: "invalid value", err: true}, - {input: "!@#$", err: true}, + {input: "bla", err: QemuDiskFormat("").Error()}, + {input: "invalid value", err: QemuDiskFormat("").Error()}, + {input: "!@#$", err: QemuDiskFormat("").Error()}, } for _, e := range testData { - if e.err { - require.Error(t, e.input.Validate()) + if e.err != nil { + require.Equal(t, e.input.Validate(), e.err) } else { require.NoError(t, e.input.Validate()) } From d7b9fae8cc905f9f4b614f406d3374edfb2b852a Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 18:15:29 +0000 Subject: [PATCH 070/120] refactor: make `0` default instad of `nil` --- proxmox/config_qemu_disk.go | 80 ++++++++---------- proxmox/config_qemu_disk_test.go | 138 ++++++++++++++----------------- 2 files changed, 96 insertions(+), 122 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 8112b0ca..575b46f7 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -211,34 +211,34 @@ func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { // format // media - if disk.Bandwidth.Iops.ReadLimit.Concurrent != nil { - settings = settings + ",iops_rd=" + strconv.Itoa(int(*disk.Bandwidth.Iops.ReadLimit.Concurrent)) + if disk.Bandwidth.Iops.ReadLimit.Concurrent != 0 { + settings = settings + ",iops_rd=" + strconv.Itoa(int(disk.Bandwidth.Iops.ReadLimit.Concurrent)) } - if disk.Bandwidth.Iops.ReadLimit.Burst != nil { - settings = settings + ",iops_rd_max=" + strconv.Itoa(int(*disk.Bandwidth.Iops.ReadLimit.Burst)) + if disk.Bandwidth.Iops.ReadLimit.Burst != 0 { + settings = settings + ",iops_rd_max=" + strconv.Itoa(int(disk.Bandwidth.Iops.ReadLimit.Burst)) } - if disk.Bandwidth.Iops.WriteLimit.Concurrent != nil { - settings = settings + ",iops_wr=" + strconv.Itoa(int(*disk.Bandwidth.Iops.WriteLimit.Concurrent)) + if disk.Bandwidth.Iops.WriteLimit.Concurrent != 0 { + settings = settings + ",iops_wr=" + strconv.Itoa(int(disk.Bandwidth.Iops.WriteLimit.Concurrent)) } - if disk.Bandwidth.Iops.WriteLimit.Burst != nil { - settings = settings + ",iops_wr_max=" + strconv.Itoa(int(*disk.Bandwidth.Iops.WriteLimit.Burst)) + if disk.Bandwidth.Iops.WriteLimit.Burst != 0 { + settings = settings + ",iops_wr_max=" + strconv.Itoa(int(disk.Bandwidth.Iops.WriteLimit.Burst)) } if (disk.Type == scsi || disk.Type == virtIO) && disk.IOThread { settings = settings + ",iothread=1" } - if disk.Bandwidth.Data.ReadLimit.Concurrent != nil { - settings = settings + fmt.Sprintf(",mbps_rd=%.2f", *disk.Bandwidth.Data.ReadLimit.Concurrent) + if disk.Bandwidth.Data.ReadLimit.Concurrent != 0 { + settings = settings + fmt.Sprintf(",mbps_rd=%.2f", disk.Bandwidth.Data.ReadLimit.Concurrent) } - if disk.Bandwidth.Data.ReadLimit.Burst != nil { - settings = settings + fmt.Sprintf(",mbps_rd_max=%.2f", *disk.Bandwidth.Data.ReadLimit.Burst) + if disk.Bandwidth.Data.ReadLimit.Burst != 0 { + settings = settings + fmt.Sprintf(",mbps_rd_max=%.2f", disk.Bandwidth.Data.ReadLimit.Burst) } - if disk.Bandwidth.Data.WriteLimit.Concurrent != nil { - settings = settings + fmt.Sprintf(",mbps_wr=%.2f", *disk.Bandwidth.Data.WriteLimit.Concurrent) + if disk.Bandwidth.Data.WriteLimit.Concurrent != 0 { + settings = settings + fmt.Sprintf(",mbps_wr=%.2f", disk.Bandwidth.Data.WriteLimit.Concurrent) } - if disk.Bandwidth.Data.WriteLimit.Burst != nil { - settings = settings + fmt.Sprintf(",mbps_wr_max=%.2f", *disk.Bandwidth.Data.WriteLimit.Burst) + if disk.Bandwidth.Data.WriteLimit.Burst != 0 { + settings = settings + fmt.Sprintf(",mbps_wr_max=%.2f", disk.Bandwidth.Data.WriteLimit.Burst) } if !disk.Replicate { @@ -304,23 +304,19 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { } if e[0] == "iops_rd" { tmp, _ := strconv.Atoi(e[1]) - pointer := uint(tmp) - disk.Bandwidth.Iops.ReadLimit.Concurrent = &pointer + disk.Bandwidth.Iops.ReadLimit.Concurrent = uint(tmp) } if e[0] == "iops_rd_max" { tmp, _ := strconv.Atoi(e[1]) - pointer := uint(tmp) - disk.Bandwidth.Iops.ReadLimit.Burst = &pointer + disk.Bandwidth.Iops.ReadLimit.Burst = uint(tmp) } if e[0] == "iops_wr" { tmp, _ := strconv.Atoi(e[1]) - pointer := uint(tmp) - disk.Bandwidth.Iops.WriteLimit.Concurrent = &pointer + disk.Bandwidth.Iops.WriteLimit.Concurrent = uint(tmp) } if e[0] == "iops_wr_max" { tmp, _ := strconv.Atoi(e[1]) - pointer := uint(tmp) - disk.Bandwidth.Iops.WriteLimit.Burst = &pointer + disk.Bandwidth.Iops.WriteLimit.Burst = uint(tmp) } if e[0] == "iothread" { disk.IOThread, _ = strconv.ParseBool(e[1]) @@ -328,23 +324,19 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { } if e[0] == "mbps_rd" { tmp, _ := strconv.ParseFloat(e[1], 32) - pointer := float32(math.Round(tmp*100) / 100) - disk.Bandwidth.Data.ReadLimit.Concurrent = &pointer + disk.Bandwidth.Data.ReadLimit.Concurrent = float32(math.Round(tmp*100) / 100) } if e[0] == "mbps_rd_max" { tmp, _ := strconv.ParseFloat(e[1], 32) - pointer := float32(math.Round(tmp*100) / 100) - disk.Bandwidth.Data.ReadLimit.Burst = &pointer + disk.Bandwidth.Data.ReadLimit.Burst = float32(math.Round(tmp*100) / 100) } if e[0] == "mbps_wr" { tmp, _ := strconv.ParseFloat(e[1], 32) - pointer := float32(math.Round(tmp*100) / 100) - disk.Bandwidth.Data.WriteLimit.Concurrent = &pointer + disk.Bandwidth.Data.WriteLimit.Concurrent = float32(math.Round(tmp*100) / 100) } if e[0] == "mbps_wr_max" { tmp, _ := strconv.ParseFloat(e[1], 32) - pointer := float32(math.Round(tmp*100) / 100) - disk.Bandwidth.Data.WriteLimit.Burst = &pointer + disk.Bandwidth.Data.WriteLimit.Burst = float32(math.Round(tmp*100) / 100) } if e[0] == "replicate" { disk.Replicate, _ = strconv.ParseBool(e[1]) @@ -417,16 +409,16 @@ func (data QemuDiskBandwidthData) Validate() error { } type QemuDiskBandwidthDataLimit struct { - Burst *float32 // nil = default - Concurrent *float32 // nil = unlimited + Burst float32 // 0 = default + Concurrent float32 // 0 = unlimited } func (limit QemuDiskBandwidthDataLimit) Validate() error { - if limit.Burst != nil && *limit.Burst < 1 { - return errors.New("burst may not be lower then 1") + if limit.Burst != 0 && limit.Burst < 1 { + return errors.New("burst may not be lower then 1 except for 0") } - if limit.Concurrent != nil && *limit.Concurrent < 1 { - return errors.New("concurrent may not be lower then 1") + if limit.Concurrent != 0 && limit.Concurrent < 1 { + return errors.New("concurrent may not be lower then 1 except for 0") } return nil } @@ -445,16 +437,16 @@ func (iops QemuDiskBandwidthIops) Validate() error { } type QemuDiskBandwidthIopsLimit struct { - Burst *uint // nil = default - Concurrent *uint // nil = unlimited + Burst uint // 0 = default + Concurrent uint // 0 = unlimited } func (limit QemuDiskBandwidthIopsLimit) Validate() error { - if limit.Burst != nil && *limit.Burst < 10 { - return errors.New("burst may not be lower then 10") + if limit.Burst != 0 && limit.Burst < 10 { + return errors.New("burst may not be lower then 10 except for 0") } - if limit.Concurrent != nil && *limit.Concurrent < 10 { - return errors.New("concurrent may not be lower then 1") + if limit.Concurrent != 0 && limit.Concurrent < 10 { + return errors.New("concurrent may not be lower then 10 except for 0") } return nil } diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index ae990579..45f25946 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -104,12 +104,6 @@ func Test_QemuDiskAsyncIO_Validate(t *testing.T) { } func Test_QemuDiskBandwidth_Validate(t *testing.T) { - float0 := float32(0) - float0a := float32(0.99) - float1 := float32(1) - uint0 := uint(0) - uint9 := uint(9) - uint10 := uint(10) testData := []struct { input QemuDiskBandwidth err bool @@ -118,35 +112,35 @@ func Test_QemuDiskBandwidth_Validate(t *testing.T) { {input: QemuDiskBandwidth{}}, {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}, {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float1}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float1}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}}, {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float1}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float1}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}}, {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}, {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint10}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint10}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}}, {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint10}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint10}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}}, // Invalid - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float0}}}, err: true}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float0a}}}, err: true}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0}}}, err: true}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0a}}}, err: true}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float0}}}, err: true}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float0a}}}, err: true}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0}}}, err: true}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0a}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint9}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint0}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint9}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint0}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint9}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint0}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint9}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint0}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: true}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: true}, } for _, e := range testData { if e.err { @@ -158,9 +152,6 @@ func Test_QemuDiskBandwidth_Validate(t *testing.T) { } func Test_QemuDiskBandwidthData_Validate(t *testing.T) { - float0 := float32(0) - float0a := float32(0.99) - float1 := float32(1) testData := []struct { input QemuDiskBandwidthData err bool @@ -168,20 +159,20 @@ func Test_QemuDiskBandwidthData_Validate(t *testing.T) { // Valid {input: QemuDiskBandwidthData{}}, {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float1}}}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float1}}}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}, {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float1}}}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float1}}}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}, // Invalid - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float0}}, err: true}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: &float0a}}, err: true}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0}}, err: true}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0a}}, err: true}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float0}}, err: true}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: &float0a}}, err: true}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0}}, err: true}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: &float0a}}, err: true}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: true}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: true}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: true}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: true}, } for _, e := range testData { if e.err { @@ -193,22 +184,19 @@ func Test_QemuDiskBandwidthData_Validate(t *testing.T) { } func Test_QemuDiskBandwidthDataLimit_Validate(t *testing.T) { - float0 := float32(0) - float0a := float32(0.99) - float1 := float32(1) testData := []struct { input QemuDiskBandwidthDataLimit err bool }{ // Valid {input: QemuDiskBandwidthDataLimit{}}, - {input: QemuDiskBandwidthDataLimit{Burst: &float1}}, - {input: QemuDiskBandwidthDataLimit{Concurrent: &float1}}, + {input: QemuDiskBandwidthDataLimit{Burst: 0}}, + {input: QemuDiskBandwidthDataLimit{Burst: 1}}, + {input: QemuDiskBandwidthDataLimit{Concurrent: 0}}, + {input: QemuDiskBandwidthDataLimit{Concurrent: 1}}, // Invalid - {input: QemuDiskBandwidthDataLimit{Burst: &float0}, err: true}, - {input: QemuDiskBandwidthDataLimit{Burst: &float0a}, err: true}, - {input: QemuDiskBandwidthDataLimit{Concurrent: &float0}, err: true}, - {input: QemuDiskBandwidthDataLimit{Concurrent: &float0a}, err: true}, + {input: QemuDiskBandwidthDataLimit{Burst: 0.99}, err: true}, + {input: QemuDiskBandwidthDataLimit{Concurrent: 0.99}, err: true}, } for _, e := range testData { if e.err { @@ -220,9 +208,6 @@ func Test_QemuDiskBandwidthDataLimit_Validate(t *testing.T) { } func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { - uint0 := uint(0) - uint9 := uint(9) - uint10 := uint(10) testData := []struct { input QemuDiskBandwidthIops err bool @@ -230,20 +215,20 @@ func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { // Valid {input: QemuDiskBandwidthIops{}}, {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint10}}}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint10}}}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint10}}}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint10}}}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, // Invalid - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint0}}, err: true}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: &uint9}}, err: true}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint0}}, err: true}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint9}}, err: true}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint0}}, err: true}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: &uint9}}, err: true}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint0}}, err: true}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: &uint9}}, err: true}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: true}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: true}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: true}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: true}, } for _, e := range testData { if e.err { @@ -255,22 +240,19 @@ func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { } func Test_QemuDiskBandwidthIopsLimit_Validate(t *testing.T) { - uint0 := uint(0) - uint9 := uint(9) - uint10 := uint(10) testData := []struct { input QemuDiskBandwidthIopsLimit err bool }{ // Valid {input: QemuDiskBandwidthIopsLimit{}}, - {input: QemuDiskBandwidthIopsLimit{Burst: &uint10}}, - {input: QemuDiskBandwidthIopsLimit{Concurrent: &uint10}}, + {input: QemuDiskBandwidthIopsLimit{Burst: 0}}, + {input: QemuDiskBandwidthIopsLimit{Burst: 10}}, + {input: QemuDiskBandwidthIopsLimit{Concurrent: 0}}, + {input: QemuDiskBandwidthIopsLimit{Concurrent: 10}}, // Invalid - {input: QemuDiskBandwidthIopsLimit{Burst: &uint0}, err: true}, - {input: QemuDiskBandwidthIopsLimit{Burst: &uint9}, err: true}, - {input: QemuDiskBandwidthIopsLimit{Concurrent: &uint0}, err: true}, - {input: QemuDiskBandwidthIopsLimit{Concurrent: &uint9}, err: true}, + {input: QemuDiskBandwidthIopsLimit{Burst: 9}, err: true}, + {input: QemuDiskBandwidthIopsLimit{Concurrent: 9}, err: true}, } for _, e := range testData { if e.err { From 25658bf0615593c0e2f65f03a283944465c0c510 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 18:22:07 +0000 Subject: [PATCH 071/120] test: match exact error --- proxmox/config_qemu_disk.go | 18 ++++++-- proxmox/config_qemu_disk_test.go | 71 ++++++++++++++++---------------- 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 575b46f7..f2430f50 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -413,12 +413,17 @@ type QemuDiskBandwidthDataLimit struct { Concurrent float32 // 0 = unlimited } +const ( + Error_QemuDiskBandwidthDataLimit_Burst string = "burst may not be lower then 1 except for 0" + Error_QemuDiskBandwidthDataLimit_Concurrent string = "concurrent may not be lower then 1 except for 0" +) + func (limit QemuDiskBandwidthDataLimit) Validate() error { if limit.Burst != 0 && limit.Burst < 1 { - return errors.New("burst may not be lower then 1 except for 0") + return errors.New(Error_QemuDiskBandwidthDataLimit_Burst) } if limit.Concurrent != 0 && limit.Concurrent < 1 { - return errors.New("concurrent may not be lower then 1 except for 0") + return errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) } return nil } @@ -441,12 +446,17 @@ type QemuDiskBandwidthIopsLimit struct { Concurrent uint // 0 = unlimited } +const ( + Error_QemuDiskBandwidthIopsLimit_Burst string = "burst may not be lower then 10 except for 0" + Error_QemuDiskBandwidthIopsLimit_Concurrent string = "concurrent may not be lower then 10 except for 0" +) + func (limit QemuDiskBandwidthIopsLimit) Validate() error { if limit.Burst != 0 && limit.Burst < 10 { - return errors.New("burst may not be lower then 10 except for 0") + return errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) } if limit.Concurrent != 0 && limit.Concurrent < 10 { - return errors.New("concurrent may not be lower then 10 except for 0") + return errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) } return nil } diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 45f25946..e991e73e 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -1,6 +1,7 @@ package proxmox import ( + "errors" "testing" "github.com/Telmate/proxmox-api-go/test/data/test_data_qemu" @@ -106,7 +107,7 @@ func Test_QemuDiskAsyncIO_Validate(t *testing.T) { func Test_QemuDiskBandwidth_Validate(t *testing.T) { testData := []struct { input QemuDiskBandwidth - err bool + err error }{ // Valid {input: QemuDiskBandwidth{}}, @@ -133,18 +134,18 @@ func Test_QemuDiskBandwidth_Validate(t *testing.T) { {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}}, {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}}, // Invalid - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: true}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: true}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: true}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: true}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: true}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, + {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, + {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, } for _, e := range testData { - if e.err { - require.Error(t, e.input.Validate()) + if e.err != nil { + require.Equal(t, e.input.Validate(), e.err) } else { require.NoError(t, e.input.Validate()) } @@ -154,7 +155,7 @@ func Test_QemuDiskBandwidth_Validate(t *testing.T) { func Test_QemuDiskBandwidthData_Validate(t *testing.T) { testData := []struct { input QemuDiskBandwidthData - err bool + err error }{ // Valid {input: QemuDiskBandwidthData{}}, @@ -169,14 +170,14 @@ func Test_QemuDiskBandwidthData_Validate(t *testing.T) { {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}, {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}, // Invalid - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: true}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: true}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: true}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: true}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, + {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, + {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, } for _, e := range testData { - if e.err { - require.Error(t, e.input.Validate()) + if e.err != nil { + require.Equal(t, e.input.Validate(), e.err) } else { require.NoError(t, e.input.Validate()) } @@ -186,7 +187,7 @@ func Test_QemuDiskBandwidthData_Validate(t *testing.T) { func Test_QemuDiskBandwidthDataLimit_Validate(t *testing.T) { testData := []struct { input QemuDiskBandwidthDataLimit - err bool + err error }{ // Valid {input: QemuDiskBandwidthDataLimit{}}, @@ -195,12 +196,12 @@ func Test_QemuDiskBandwidthDataLimit_Validate(t *testing.T) { {input: QemuDiskBandwidthDataLimit{Concurrent: 0}}, {input: QemuDiskBandwidthDataLimit{Concurrent: 1}}, // Invalid - {input: QemuDiskBandwidthDataLimit{Burst: 0.99}, err: true}, - {input: QemuDiskBandwidthDataLimit{Concurrent: 0.99}, err: true}, + {input: QemuDiskBandwidthDataLimit{Burst: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, + {input: QemuDiskBandwidthDataLimit{Concurrent: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, } for _, e := range testData { - if e.err { - require.Error(t, e.input.Validate()) + if e.err != nil { + require.Equal(t, e.input.Validate(), e.err) } else { require.NoError(t, e.input.Validate()) } @@ -210,7 +211,7 @@ func Test_QemuDiskBandwidthDataLimit_Validate(t *testing.T) { func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { testData := []struct { input QemuDiskBandwidthIops - err bool + err error }{ // Valid {input: QemuDiskBandwidthIops{}}, @@ -225,14 +226,14 @@ func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, // Invalid - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: true}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: true}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: true}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: true}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, + {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, + {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, } for _, e := range testData { - if e.err { - require.Error(t, e.input.Validate()) + if e.err != nil { + require.Equal(t, e.input.Validate(), e.err) } else { require.NoError(t, e.input.Validate()) } @@ -242,7 +243,7 @@ func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { func Test_QemuDiskBandwidthIopsLimit_Validate(t *testing.T) { testData := []struct { input QemuDiskBandwidthIopsLimit - err bool + err error }{ // Valid {input: QemuDiskBandwidthIopsLimit{}}, @@ -251,12 +252,12 @@ func Test_QemuDiskBandwidthIopsLimit_Validate(t *testing.T) { {input: QemuDiskBandwidthIopsLimit{Concurrent: 0}}, {input: QemuDiskBandwidthIopsLimit{Concurrent: 10}}, // Invalid - {input: QemuDiskBandwidthIopsLimit{Burst: 9}, err: true}, - {input: QemuDiskBandwidthIopsLimit{Concurrent: 9}, err: true}, + {input: QemuDiskBandwidthIopsLimit{Burst: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, + {input: QemuDiskBandwidthIopsLimit{Concurrent: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, } for _, e := range testData { - if e.err { - require.Error(t, e.input.Validate()) + if e.err != nil { + require.Equal(t, e.input.Validate(), e.err) } else { require.NoError(t, e.input.Validate()) } From fa66b8b45b6e2329c891d53e1a205bd3703343c5 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 18:26:25 +0000 Subject: [PATCH 072/120] test: match exact error --- proxmox/config_qemu_disk.go | 9 +++++++-- proxmox/config_qemu_disk_test.go | 14 +++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index f2430f50..6dfbffee 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -16,12 +16,17 @@ type IsoFile struct { Size string `json:"size"` } +const ( + Error_IsoFile_File string = "file may not be empty" + Error_IsoFile_Storage string = "storage may not be empty" +) + func (iso IsoFile) Validate() error { if iso.File == "" { - return errors.New("file may not be empty") + return errors.New(Error_IsoFile_File) } if iso.Storage == "" { - return errors.New("storage may not be empty") + return errors.New(Error_IsoFile_Storage) } return nil } diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index e991e73e..da75e66d 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -11,19 +11,19 @@ import ( func Test_IsoFile_Validate(t *testing.T) { testData := []struct { input IsoFile - err bool + err error }{ // Valid {input: IsoFile{File: "anything", Storage: "something"}}, // Invalid - {input: IsoFile{}, err: true}, - {input: IsoFile{File: "anything"}, err: true}, - {input: IsoFile{Storage: "something"}, err: true}, - {input: IsoFile{Size: "something"}, err: true}, + {input: IsoFile{}, err: errors.New(Error_IsoFile_File)}, + {input: IsoFile{File: "anything"}, err: errors.New(Error_IsoFile_Storage)}, + {input: IsoFile{Storage: "something"}, err: errors.New(Error_IsoFile_File)}, + {input: IsoFile{Size: "something"}, err: errors.New(Error_IsoFile_File)}, } for _, e := range testData { - if e.err { - require.Error(t, e.input.Validate()) + if e.err != nil { + require.Equal(t, e.input.Validate(), e.err) } else { require.NoError(t, e.input.Validate()) } From 70f05b03c0cfb5371c5396f7fe5b16bf91064c24 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 18:30:27 +0000 Subject: [PATCH 073/120] test: match exact error --- proxmox/config_qemu_disk.go | 6 +++++- proxmox/config_qemu_disk_test.go | 16 ++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 6dfbffee..72b71c02 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -37,6 +37,10 @@ type QemuCdRom struct { Passthrough bool `json:"passthrough,omitempty"` } +const ( + Error_QemuCdRom_MutuallyExclusive string = "iso and passthrough are mutually exclusive" +) + // TODO write test func (cdRom QemuCdRom) mapToApiValues() string { if cdRom.Passthrough { @@ -68,7 +72,7 @@ func (cdRom QemuCdRom) Validate() error { return err } if cdRom.Passthrough { - return errors.New("iso and passthrough are mutually exclusive") + return errors.New(Error_QemuCdRom_MutuallyExclusive) } } return nil diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index da75e66d..6b46034b 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -33,22 +33,22 @@ func Test_IsoFile_Validate(t *testing.T) { func Test_QemuCdRom_Validate(t *testing.T) { testData := []struct { input QemuCdRom - err bool + err error }{ // Valid {input: QemuCdRom{}}, {input: QemuCdRom{Iso: &IsoFile{File: "anything", Storage: "Something"}}}, {input: QemuCdRom{Passthrough: true}}, // Invalid - {input: QemuCdRom{Iso: &IsoFile{}}, err: true}, - {input: QemuCdRom{Iso: &IsoFile{File: "anything"}}, err: true}, - {input: QemuCdRom{Iso: &IsoFile{Storage: "something"}}, err: true}, - {input: QemuCdRom{Iso: &IsoFile{Size: "something"}}, err: true}, - {input: QemuCdRom{Iso: &IsoFile{File: "anything", Storage: "something"}, Passthrough: true}, err: true}, + {input: QemuCdRom{Iso: &IsoFile{}}, err: errors.New(Error_IsoFile_File)}, + {input: QemuCdRom{Iso: &IsoFile{File: "anything"}}, err: errors.New(Error_IsoFile_Storage)}, + {input: QemuCdRom{Iso: &IsoFile{Storage: "something"}}, err: errors.New(Error_IsoFile_File)}, + {input: QemuCdRom{Iso: &IsoFile{Size: "something"}}, err: errors.New(Error_IsoFile_File)}, + {input: QemuCdRom{Iso: &IsoFile{File: "anything", Storage: "something"}, Passthrough: true}, err: errors.New(Error_QemuCdRom_MutuallyExclusive)}, } for _, e := range testData { - if e.err { - require.Error(t, e.input.Validate()) + if e.err != nil { + require.Equal(t, e.input.Validate(), e.err) } else { require.NoError(t, e.input.Validate()) } From 3ee90fca25a8f50fbef91873f0d0c3b137f27023 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 18:35:19 +0000 Subject: [PATCH 074/120] test: match exact error --- proxmox/config_qemu_disk.go | 6 +++++- proxmox/config_qemu_disk_test.go | 19 ++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 72b71c02..af8aa555 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -143,6 +143,10 @@ type QemuCloudInitDisk struct { Storage string `json:"storage,omitempty"` } +const ( + Error_QemuCloudInitDisk_Storage string = "storage should not be empty" +) + // TODO write test func (cloudInit QemuCloudInitDisk) mapToApiValues() string { return cloudInit.Storage + ":cloudinit,format=" + string(cloudInit.Format) @@ -160,7 +164,7 @@ func (cloudInit QemuCloudInitDisk) Validate() error { return err } if cloudInit.Storage == "" { - return errors.New("storage should not be empty") + return errors.New(Error_QemuCloudInitDisk_Storage) } return nil } diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 6b46034b..66c44ab2 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -56,24 +56,21 @@ func Test_QemuCdRom_Validate(t *testing.T) { } func Test_QemuCloudInitDisk_Validate(t *testing.T) { - formatRaw := QemuDiskFormat_Raw - formatEmpty := QemuDiskFormat("") - formatInvalid := QemuDiskFormat("invalid") testData := []struct { input QemuCloudInitDisk - err bool + err error }{ // Valid - {input: QemuCloudInitDisk{Storage: "anything", Format: formatRaw}}, + {input: QemuCloudInitDisk{Storage: "anything", Format: QemuDiskFormat_Raw}}, // Invalid - {input: QemuCloudInitDisk{}, err: true}, - {input: QemuCloudInitDisk{Format: formatRaw}, err: true}, - {input: QemuCloudInitDisk{Storage: "anything", Format: formatEmpty}, err: true}, - {input: QemuCloudInitDisk{Storage: "anything", Format: formatInvalid}, err: true}, + {input: QemuCloudInitDisk{}, err: QemuDiskFormat("").Error()}, + {input: QemuCloudInitDisk{Format: QemuDiskFormat_Raw}, err: errors.New(Error_QemuCloudInitDisk_Storage)}, + {input: QemuCloudInitDisk{Storage: "anything", Format: QemuDiskFormat("")}, err: QemuDiskFormat("").Error()}, + {input: QemuCloudInitDisk{Storage: "anything", Format: QemuDiskFormat("invalid")}, err: QemuDiskFormat("").Error()}, } for _, e := range testData { - if e.err { - require.Error(t, e.input.Validate()) + if e.err != nil { + require.Equal(t, e.input.Validate(), e.err) } else { require.NoError(t, e.input.Validate()) } From 5e46b85ad4ba3829292b40e678877f056d15a264 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 18:39:54 +0000 Subject: [PATCH 075/120] refactor: create const for errors --- proxmox/config_qemu_disk.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index af8aa555..ddd53f7a 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -522,15 +522,20 @@ func (format QemuDiskFormat) Validate() error { type QemuDiskSerial string +const ( + Error_QemuDiskSerial_IllegalCharacter string = "serial may only contain the following characters: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_" + Error_QemuDiskSerial_IllegalLength string = "serial may only be 60 characters long" +) + // QemuDiskSerial may only contain the following characters: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_ // And has a max length of 60 characters func (serial QemuDiskSerial) Validate() error { regex, _ := regexp.Compile(`^([a-z]|[A-Z]|[0-9]|_|-)*$`) if !regex.Match([]byte(serial)) { - return errors.New("serial may only contain the following characters: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_") + return errors.New(Error_QemuDiskSerial_IllegalCharacter) } if len(serial) > 60 { - return errors.New("serial may only be 60 characters long") + return errors.New(Error_QemuDiskSerial_IllegalLength) } return nil } From ab1df9549c183bb219ddc8ff5d67f715ab85e120 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 15 Mar 2023 20:32:58 +0000 Subject: [PATCH 076/120] test: name all test cases --- proxmox/config_qemu_disk_test.go | 418 +++++++++++++++++-------------- 1 file changed, 229 insertions(+), 189 deletions(-) diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 66c44ab2..99de3fdb 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -2,6 +2,7 @@ package proxmox import ( "errors" + "fmt" "testing" "github.com/Telmate/proxmox-api-go/test/data/test_data_qemu" @@ -10,307 +11,340 @@ import ( func Test_IsoFile_Validate(t *testing.T) { testData := []struct { + name string input IsoFile err error }{ // Valid - {input: IsoFile{File: "anything", Storage: "something"}}, + {name: "Valid 00", input: IsoFile{File: "anything", Storage: "something"}}, // Invalid - {input: IsoFile{}, err: errors.New(Error_IsoFile_File)}, - {input: IsoFile{File: "anything"}, err: errors.New(Error_IsoFile_Storage)}, - {input: IsoFile{Storage: "something"}, err: errors.New(Error_IsoFile_File)}, - {input: IsoFile{Size: "something"}, err: errors.New(Error_IsoFile_File)}, + {name: "Invalid 00", input: IsoFile{}, err: errors.New(Error_IsoFile_File)}, + {name: "Invalid 01", input: IsoFile{File: "anything"}, err: errors.New(Error_IsoFile_Storage)}, + {name: "Invalid 02", input: IsoFile{Storage: "something"}, err: errors.New(Error_IsoFile_File)}, + {name: "Invalid 03", input: IsoFile{Size: "something"}, err: errors.New(Error_IsoFile_File)}, } - for _, e := range testData { - if e.err != nil { - require.Equal(t, e.input.Validate(), e.err) - } else { - require.NoError(t, e.input.Validate()) - } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) } } func Test_QemuCdRom_Validate(t *testing.T) { testData := []struct { + name string input QemuCdRom err error }{ // Valid - {input: QemuCdRom{}}, - {input: QemuCdRom{Iso: &IsoFile{File: "anything", Storage: "Something"}}}, - {input: QemuCdRom{Passthrough: true}}, + {name: "Valid 00", input: QemuCdRom{}}, + {name: "Valid 01", input: QemuCdRom{Iso: &IsoFile{File: "anything", Storage: "Something"}}}, + {name: "Valid 02", input: QemuCdRom{Passthrough: true}}, // Invalid - {input: QemuCdRom{Iso: &IsoFile{}}, err: errors.New(Error_IsoFile_File)}, - {input: QemuCdRom{Iso: &IsoFile{File: "anything"}}, err: errors.New(Error_IsoFile_Storage)}, - {input: QemuCdRom{Iso: &IsoFile{Storage: "something"}}, err: errors.New(Error_IsoFile_File)}, - {input: QemuCdRom{Iso: &IsoFile{Size: "something"}}, err: errors.New(Error_IsoFile_File)}, - {input: QemuCdRom{Iso: &IsoFile{File: "anything", Storage: "something"}, Passthrough: true}, err: errors.New(Error_QemuCdRom_MutuallyExclusive)}, + {name: "Invalid 00", input: QemuCdRom{Iso: &IsoFile{}}, err: errors.New(Error_IsoFile_File)}, + {name: "Invalid 01", input: QemuCdRom{Iso: &IsoFile{File: "anything"}}, err: errors.New(Error_IsoFile_Storage)}, + {name: "Invalid 02", input: QemuCdRom{Iso: &IsoFile{Storage: "something"}}, err: errors.New(Error_IsoFile_File)}, + {name: "Invalid 03", input: QemuCdRom{Iso: &IsoFile{Size: "something"}}, err: errors.New(Error_IsoFile_File)}, + {name: "Invalid 04", input: QemuCdRom{Iso: &IsoFile{File: "anything", Storage: "something"}, Passthrough: true}, err: errors.New(Error_QemuCdRom_MutuallyExclusive)}, } - for _, e := range testData { - if e.err != nil { - require.Equal(t, e.input.Validate(), e.err) - } else { - require.NoError(t, e.input.Validate()) - } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) } } func Test_QemuCloudInitDisk_Validate(t *testing.T) { testData := []struct { + name string input QemuCloudInitDisk err error }{ // Valid - {input: QemuCloudInitDisk{Storage: "anything", Format: QemuDiskFormat_Raw}}, + {name: "Valid 00", input: QemuCloudInitDisk{Storage: "anything", Format: QemuDiskFormat_Raw}}, // Invalid - {input: QemuCloudInitDisk{}, err: QemuDiskFormat("").Error()}, - {input: QemuCloudInitDisk{Format: QemuDiskFormat_Raw}, err: errors.New(Error_QemuCloudInitDisk_Storage)}, - {input: QemuCloudInitDisk{Storage: "anything", Format: QemuDiskFormat("")}, err: QemuDiskFormat("").Error()}, - {input: QemuCloudInitDisk{Storage: "anything", Format: QemuDiskFormat("invalid")}, err: QemuDiskFormat("").Error()}, + {name: "Invalid 00", input: QemuCloudInitDisk{}, err: QemuDiskFormat("").Error()}, + {name: "Invalid 01", input: QemuCloudInitDisk{Format: QemuDiskFormat_Raw}, err: errors.New(Error_QemuCloudInitDisk_Storage)}, + {name: "Invalid 02", input: QemuCloudInitDisk{Storage: "anything", Format: QemuDiskFormat("")}, err: QemuDiskFormat("").Error()}, + {name: "Invalid 03", input: QemuCloudInitDisk{Storage: "anything", Format: QemuDiskFormat("invalid")}, err: QemuDiskFormat("").Error()}, } - for _, e := range testData { - if e.err != nil { - require.Equal(t, e.input.Validate(), e.err) - } else { - require.NoError(t, e.input.Validate()) - } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) } } func Test_QemuDiskAsyncIO_Validate(t *testing.T) { testData := []struct { + name string input QemuDiskAsyncIO err error }{ // Valid - {input: ""}, - {input: QemuDiskAsyncIO_Native}, - {input: QemuDiskAsyncIO_Threads}, - {input: QemuDiskAsyncIO_IOuring}, + {name: "Valid 00", input: ""}, + {name: "Valid 01", input: QemuDiskAsyncIO_Native}, + {name: "Valid 02", input: QemuDiskAsyncIO_Threads}, + {name: "Valid 03", input: QemuDiskAsyncIO_IOuring}, // Invalid - {input: "bla", err: QemuDiskAsyncIO("").Error()}, - {input: "invalid value", err: QemuDiskAsyncIO("").Error()}, - {input: "!@#$", err: QemuDiskAsyncIO("").Error()}, + {name: "Invalid 00", input: "bla", err: QemuDiskAsyncIO("").Error()}, + {name: "Invalid 01", input: "invalid value", err: QemuDiskAsyncIO("").Error()}, + {name: "Invalid 02", input: "!@#$", err: QemuDiskAsyncIO("").Error()}, } - for _, e := range testData { - if e.err != nil { - require.Equal(t, e.input.Validate(), e.err) - } else { - require.NoError(t, e.input.Validate()) - } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) } } func Test_QemuDiskBandwidth_Validate(t *testing.T) { testData := []struct { + name string input QemuDiskBandwidth err error }{ // Valid - {input: QemuDiskBandwidth{}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}}, + {name: "Valid 00", input: QemuDiskBandwidth{}}, + {name: "Valid 01", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}, + {name: "Valid 02", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}, + {name: "Valid 03", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}}, + {name: "Valid 04", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}}, + {name: "Valid 05", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}}, + {name: "Valid 06", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}}, + {name: "Valid 07", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}, + {name: "Valid 08", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}}, + {name: "Valid 09", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}}, + {name: "Valid 10", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}}, + {name: "Valid 11", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}}, + {name: "Valid 12", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}, + {name: "Valid 13", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}, + {name: "Valid 14", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}}, + {name: "Valid 15", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}}, + {name: "Valid 16", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}}, + {name: "Valid 17", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}}, + {name: "Valid 18", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}, + {name: "Valid 19", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}}, + {name: "Valid 20", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}}, + {name: "Valid 21", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}}, + {name: "Valid 22", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}}, // Invalid - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, - {input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, - {input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, + {name: "Invalid 01", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, + {name: "Invalid 02", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, + {name: "Invalid 03", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, + {name: "Invalid 04", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, + {name: "Invalid 05", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, + {name: "Invalid 06", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, + {name: "Invalid 07", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, } - for _, e := range testData { - if e.err != nil { - require.Equal(t, e.input.Validate(), e.err) - } else { - require.NoError(t, e.input.Validate()) - } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) } } func Test_QemuDiskBandwidthData_Validate(t *testing.T) { testData := []struct { + name string input QemuDiskBandwidthData err error }{ // Valid - {input: QemuDiskBandwidthData{}}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}, + {name: "Valid 00", input: QemuDiskBandwidthData{}}, + {name: "Valid 01", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}, + {name: "Valid 02", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}, + {name: "Valid 03", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}, + {name: "Valid 04", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}, + {name: "Valid 05", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}, + {name: "Valid 06", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}, + {name: "Valid 07", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}, + {name: "Valid 08", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}, + {name: "Valid 09", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}, + {name: "Valid 10", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}, // Invalid - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, - {input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, - {input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, + {name: "Invalid 01", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, + {name: "Invalid 02", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, + {name: "Invalid 03", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, } - for _, e := range testData { - if e.err != nil { - require.Equal(t, e.input.Validate(), e.err) - } else { - require.NoError(t, e.input.Validate()) - } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) } } func Test_QemuDiskBandwidthDataLimit_Validate(t *testing.T) { testData := []struct { + name string input QemuDiskBandwidthDataLimit err error }{ // Valid - {input: QemuDiskBandwidthDataLimit{}}, - {input: QemuDiskBandwidthDataLimit{Burst: 0}}, - {input: QemuDiskBandwidthDataLimit{Burst: 1}}, - {input: QemuDiskBandwidthDataLimit{Concurrent: 0}}, - {input: QemuDiskBandwidthDataLimit{Concurrent: 1}}, + {name: "Valid 00", input: QemuDiskBandwidthDataLimit{}}, + {name: "Valid 01", input: QemuDiskBandwidthDataLimit{Burst: 0}}, + {name: "Valid 02", input: QemuDiskBandwidthDataLimit{Burst: 1}}, + {name: "Valid 03", input: QemuDiskBandwidthDataLimit{Concurrent: 0}}, + {name: "Valid 04", input: QemuDiskBandwidthDataLimit{Concurrent: 1}}, // Invalid - {input: QemuDiskBandwidthDataLimit{Burst: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, - {input: QemuDiskBandwidthDataLimit{Concurrent: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthDataLimit{Burst: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, + {name: "Invalid 01", input: QemuDiskBandwidthDataLimit{Concurrent: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, } - for _, e := range testData { - if e.err != nil { - require.Equal(t, e.input.Validate(), e.err) - } else { - require.NoError(t, e.input.Validate()) - } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) } } func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { testData := []struct { + name string input QemuDiskBandwidthIops err error }{ // Valid - {input: QemuDiskBandwidthIops{}}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, + {name: "Valid 00", input: QemuDiskBandwidthIops{}}, + {name: "Valid 01", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}, + {name: "Valid 02", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, + {name: "Valid 03", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, + {name: "Valid 04", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, + {name: "Valid 05", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, + {name: "Valid 06", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}, + {name: "Valid 07", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}, + {name: "Valid 08", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, + {name: "Valid 09", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, + {name: "Valid 10", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, // Invalid - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, - {input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, - {input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, + {name: "Invalid 01", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, + {name: "Invalid 02", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, + {name: "Invalid 03", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, } - for _, e := range testData { - if e.err != nil { - require.Equal(t, e.input.Validate(), e.err) - } else { - require.NoError(t, e.input.Validate()) - } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) } } func Test_QemuDiskBandwidthIopsLimit_Validate(t *testing.T) { testData := []struct { + name string input QemuDiskBandwidthIopsLimit err error }{ // Valid - {input: QemuDiskBandwidthIopsLimit{}}, - {input: QemuDiskBandwidthIopsLimit{Burst: 0}}, - {input: QemuDiskBandwidthIopsLimit{Burst: 10}}, - {input: QemuDiskBandwidthIopsLimit{Concurrent: 0}}, - {input: QemuDiskBandwidthIopsLimit{Concurrent: 10}}, + {name: "Valid 00", input: QemuDiskBandwidthIopsLimit{}}, + {name: "Valid 01", input: QemuDiskBandwidthIopsLimit{Burst: 0}}, + {name: "Valid 02", input: QemuDiskBandwidthIopsLimit{Burst: 10}}, + {name: "Valid 03", input: QemuDiskBandwidthIopsLimit{Concurrent: 0}}, + {name: "Valid 04", input: QemuDiskBandwidthIopsLimit{Concurrent: 10}}, // Invalid - {input: QemuDiskBandwidthIopsLimit{Burst: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, - {input: QemuDiskBandwidthIopsLimit{Concurrent: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthIopsLimit{Burst: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, + {name: "Invalid 01", input: QemuDiskBandwidthIopsLimit{Concurrent: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, } - for _, e := range testData { - if e.err != nil { - require.Equal(t, e.input.Validate(), e.err) - } else { - require.NoError(t, e.input.Validate()) - } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) } } func Test_QemuDiskCache_Validate(t *testing.T) { testData := []struct { + name string input QemuDiskCache err error }{ // Valid - {input: ""}, - {input: QemuDiskCache_None}, - {input: QemuDiskCache_WriteThrough}, - {input: QemuDiskCache_WriteBack}, - {input: QemuDiskCache_Unsafe}, - {input: QemuDiskCache_DirectSync}, + {name: "Valid 00", input: ""}, + {name: "Valid 01", input: QemuDiskCache_None}, + {name: "Valid 02", input: QemuDiskCache_WriteThrough}, + {name: "Valid 03", input: QemuDiskCache_WriteBack}, + {name: "Valid 04", input: QemuDiskCache_Unsafe}, + {name: "Valid 05", input: QemuDiskCache_DirectSync}, // Invalid - {input: "bla", err: QemuDiskCache("").Error()}, - {input: "invalid value", err: QemuDiskCache("").Error()}, - {input: "!@#$", err: QemuDiskCache("").Error()}, + {name: "Invalid 00", input: "bla", err: QemuDiskCache("").Error()}, + {name: "Invalid 01", input: "invalid value", err: QemuDiskCache("").Error()}, + {name: "Invalid 02", input: "!@#$", err: QemuDiskCache("").Error()}, } - for _, e := range testData { - if e.err != nil { - require.Equal(t, e.input.Validate(), e.err) - } else { - require.NoError(t, e.input.Validate()) - } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) } } func Test_QemuDiskFormat_Validate(t *testing.T) { testData := []struct { + name string input QemuDiskFormat err error }{ // Valid - {input: QemuDiskFormat_Cow}, - {input: QemuDiskFormat_Cloop}, - {input: QemuDiskFormat_Qcow}, - {input: QemuDiskFormat_Qcow2}, - {input: QemuDiskFormat_Qed}, - {input: QemuDiskFormat_Vmdk}, - {input: QemuDiskFormat_Raw}, + {name: "Valid 00", input: QemuDiskFormat_Cow}, + {name: "Valid 01", input: QemuDiskFormat_Cloop}, + {name: "Valid 02", input: QemuDiskFormat_Qcow}, + {name: "Valid 03", input: QemuDiskFormat_Qcow2}, + {name: "Valid 04", input: QemuDiskFormat_Qed}, + {name: "Valid 05", input: QemuDiskFormat_Vmdk}, + {name: "Valid 06", input: QemuDiskFormat_Raw}, // Invalid - {input: "bla", err: QemuDiskFormat("").Error()}, - {input: "invalid value", err: QemuDiskFormat("").Error()}, - {input: "!@#$", err: QemuDiskFormat("").Error()}, + {name: "Invalid 00", input: "bla", err: QemuDiskFormat("").Error()}, + {name: "Invalid 01", input: "invalid value", err: QemuDiskFormat("").Error()}, + {name: "Invalid 02", input: "!@#$", err: QemuDiskFormat("").Error()}, } - for _, e := range testData { - if e.err != nil { - require.Equal(t, e.input.Validate(), e.err) - } else { - require.NoError(t, e.input.Validate()) - } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) } } @@ -322,10 +356,16 @@ func Test_QemuDiskSerial_Validate(t *testing.T) { legal: test_data_qemu.QemuDiskSerial_Legal(), illegal: test_data_qemu.QemuDiskSerial_Illegal(), } - for _, e := range testRunes.legal { - require.NoError(t, QemuDiskSerial(e).Validate()) + for i, test := range testRunes.legal { + name := fmt.Sprintf("legal%03d", i) + t.Run(name, func(*testing.T) { + require.NoError(t, QemuDiskSerial(test).Validate(), name) + }) } - for _, e := range testRunes.illegal { - require.Error(t, QemuDiskSerial(e).Validate()) + for i, test := range testRunes.illegal { + name := fmt.Sprintf("illegal%03d", i) + t.Run(name, func(*testing.T) { + require.Error(t, QemuDiskSerial(test).Validate(), name) + }) } } From 8ac0792d3a4be77fa2c4652d14e27feb4a5ae4f6 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Mar 2023 08:16:22 +0000 Subject: [PATCH 077/120] feat: add Validat func for `ConfigQemu.Disks` --- proxmox/config_qemu.go | 20 + proxmox/config_qemu_disk.go | 75 ++ proxmox/config_qemu_disk_ide.go | 66 ++ proxmox/config_qemu_disk_sata.go | 66 ++ proxmox/config_qemu_disk_scsi.go | 66 ++ proxmox/config_qemu_disk_virtio.go | 66 ++ proxmox/config_qemu_test.go | 1186 ++++++++++++++++++++++++++++ 7 files changed, 1545 insertions(+) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 602bacf8..9ce0041f 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -93,6 +93,10 @@ func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { if err != nil { return } + err = config.Validate() + if err != nil { + return + } params, _, err := config.mapToApiValues(ConfigQemu{}) if err != nil { return @@ -638,6 +642,10 @@ func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef if err != nil { return } + err = newConfig.Validate() + if err != nil { + return + } params, markedDisks, err := newConfig.mapToApiValues(*currentConfig) if err != nil { return @@ -681,6 +689,18 @@ func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef return } +func (config ConfigQemu) Validate() (err error) { + // TODO test all other use cases + if config.Disks != nil { + err = config.Disks.Validate() + if err != nil { + return + } + } + + return +} + // HasCloudInit - are there cloud-init options? func (config ConfigQemu) HasCloudInit() bool { for _, config := range config.Ipconfig { diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index ddd53f7a..536d7f6e 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -192,6 +192,13 @@ type qemuDisk struct { Type qemuDiskType } +const ( + Error_QemuDisk_File string = "file may not be empty" + Error_QemuDisk_MutuallyExclusive string = "settings cdrom,cloudinit,disk,passthrough are mutually exclusive" + Error_QemuDisk_Size string = "size must be greater then 0" + Error_QemuDisk_Storage string = "storage may not be empty" +) + // TODO write test func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { if disk.Storage != "" { @@ -375,6 +382,42 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { return &disk } +func (disk *qemuDisk) validate() (err error) { + if disk == nil { + return + } + if err = disk.AsyncIO.Validate(); err != nil { + return + } + if err = disk.Bandwidth.Validate(); err != nil { + return + } + if err = disk.Cache.Validate(); err != nil { + return + } + if err = disk.Serial.Validate(); err != nil { + return + } + if disk.Disk { + // disk + if err = disk.Format.Validate(); err != nil { + return + } + if disk.Size == 0 { + return errors.New(Error_QemuDisk_Size) + } + if disk.Storage == "" { + return errors.New(Error_QemuDisk_Storage) + } + } else { + // passthrough + if disk.File == "" { + return errors.New(Error_QemuDisk_File) + } + } + return +} + type QemuDiskAsyncIO string const ( @@ -701,8 +744,40 @@ func (storages QemuStorages) markDiskChanges(currentStorages QemuStorages, vmID return changes } +func (storages QemuStorages) Validate() (err error) { + if storages.Ide != nil { + err = storages.Ide.Validate() + if err != nil { + return + } + } + if storages.Sata != nil { + err = storages.Sata.Validate() + if err != nil { + return + } + } + if storages.Scsi != nil { + err = storages.Scsi.Validate() + if err != nil { + return + } + } + if storages.VirtIO != nil { + err = storages.VirtIO.Validate() + } + return +} + type qemuUpdateChanges struct { Delete string Move []qemuDiskShort Resize []qemuDiskResize } + +func diskSubtypeSet(set bool) error { + if set { + return errors.New(Error_QemuDisk_MutuallyExclusive) + } + return nil +} diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index e8b2ec8d..69c801be 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -36,6 +36,10 @@ func (disk *QemuIdeDisk) convertDataStructure() *qemuDisk { } } +func (disk QemuIdeDisk) Validate() error { + return disk.convertDataStructure().validate() +} + type QemuIdeDisks struct { Disk_0 *QemuIdeStorage `json:"0,omitempty"` Disk_1 *QemuIdeStorage `json:"1,omitempty"` @@ -91,6 +95,19 @@ func (QemuIdeDisks) mapToStruct(params map[string]interface{}) *QemuIdeDisks { return nil } +func (disks QemuIdeDisks) Validate() error { + diskMap := disks.mapToIntMap() + for _, e := range diskMap { + if e != nil { + err := e.Validate() + if err != nil { + return err + } + } + } + return nil +} + type QemuIdePassthrough struct { AsyncIO QemuDiskAsyncIO Backup bool @@ -119,6 +136,10 @@ func (passthrough *QemuIdePassthrough) convertDataStructure() *qemuDisk { } } +func (passthrough QemuIdePassthrough) Validate() error { + return passthrough.convertDataStructure().validate() +} + type QemuIdeStorage struct { CdRom *QemuCdRom `json:"cdrom,omitempty"` CloudInit *QemuCloudInitDisk `json:"cloudinit,omitempty"` @@ -190,3 +211,48 @@ func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { Size: tmpDisk.Size, }} } + +func (storage QemuIdeStorage) Validate() (err error) { + // First check if more than one item is nil + var subTypeSet bool + if storage.CdRom != nil { + subTypeSet = true + } + if storage.CloudInit != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + subTypeSet = true + } + if storage.Disk != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + subTypeSet = true + } + if storage.Passthrough != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + } + // Validate sub items + if storage.CdRom != nil { + if err = storage.CdRom.Validate(); err != nil { + return + } + } + if storage.CloudInit != nil { + if err = storage.CloudInit.Validate(); err != nil { + return + } + } + if storage.Disk != nil { + if err = storage.Disk.Validate(); err != nil { + return + } + } + if storage.Passthrough != nil { + err = storage.Passthrough.Validate() + } + return +} diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index d8f30216..69759d8e 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -36,6 +36,10 @@ func (disk *QemuSataDisk) convertDataStructure() *qemuDisk { } } +func (disk QemuSataDisk) Validate() error { + return disk.convertDataStructure().validate() +} + type QemuSataDisks struct { Disk_0 *QemuSataStorage `json:"0,omitempty"` Disk_1 *QemuSataStorage `json:"1,omitempty"` @@ -103,6 +107,19 @@ func (QemuSataDisks) mapToStruct(params map[string]interface{}) *QemuSataDisks { return nil } +func (disks QemuSataDisks) Validate() error { + diskMap := disks.mapToIntMap() + for _, e := range diskMap { + if e != nil { + err := e.Validate() + if err != nil { + return err + } + } + } + return nil +} + type QemuSataPassthrough struct { AsyncIO QemuDiskAsyncIO Backup bool @@ -131,6 +148,10 @@ func (passthrough *QemuSataPassthrough) convertDataStructure() *qemuDisk { } } +func (passthrough QemuSataPassthrough) Validate() error { + return passthrough.convertDataStructure().validate() +} + type QemuSataStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -202,3 +223,48 @@ func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { Size: tmpDisk.Size, }} } + +func (storage *QemuSataStorage) Validate() (err error) { + // First check if more than one item is nil + var subTypeSet bool + if storage.CdRom != nil { + subTypeSet = true + } + if storage.CloudInit != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + subTypeSet = true + } + if storage.Disk != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + subTypeSet = true + } + if storage.Passthrough != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + } + // Validate sub items + if storage.CdRom != nil { + if err = storage.CdRom.Validate(); err != nil { + return + } + } + if storage.CloudInit != nil { + if err = storage.CloudInit.Validate(); err != nil { + return + } + } + if storage.Disk != nil { + if err = storage.Disk.Validate(); err != nil { + return + } + } + if storage.Passthrough != nil { + err = storage.Passthrough.Validate() + } + return +} diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 964a5752..851dc1e6 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -40,6 +40,10 @@ func (disk *QemuScsiDisk) convertDataStructure() *qemuDisk { } } +func (disk QemuScsiDisk) Validate() error { + return disk.convertDataStructure().validate() +} + type QemuScsiDisks struct { Disk_0 *QemuScsiStorage `json:"0,omitempty"` Disk_1 *QemuScsiStorage `json:"1,omitempty"` @@ -257,6 +261,19 @@ func (QemuScsiDisks) mapToStruct(params map[string]interface{}) *QemuScsiDisks { return nil } +func (disks QemuScsiDisks) Validate() error { + diskMap := disks.mapToIntMap() + for _, e := range diskMap { + if e != nil { + err := e.Validate() + if err != nil { + return err + } + } + } + return nil +} + type QemuScsiPassthrough struct { AsyncIO QemuDiskAsyncIO Backup bool @@ -289,6 +306,10 @@ func (passthrough *QemuScsiPassthrough) convertDataStructure() *qemuDisk { } } +func (passthrough QemuScsiPassthrough) Validate() error { + return passthrough.convertDataStructure().validate() +} + type QemuScsiStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -364,3 +385,48 @@ func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { Size: tmpDisk.Size, }} } + +func (storage *QemuScsiStorage) Validate() (err error) { + // First check if more than one item is nil + var subTypeSet bool + if storage.CdRom != nil { + subTypeSet = true + } + if storage.CloudInit != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + subTypeSet = true + } + if storage.Disk != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + subTypeSet = true + } + if storage.Passthrough != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + } + // Validate sub items + if storage.CdRom != nil { + if err = storage.CdRom.Validate(); err != nil { + return + } + } + if storage.CloudInit != nil { + if err = storage.CloudInit.Validate(); err != nil { + return + } + } + if storage.Disk != nil { + if err = storage.Disk.Validate(); err != nil { + return + } + } + if storage.Passthrough != nil { + err = storage.Passthrough.Validate() + } + return +} diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 2e041885..a16ab105 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -38,6 +38,10 @@ func (disk *QemuVirtIODisk) convertDataStructure() *qemuDisk { } } +func (disk QemuVirtIODisk) Validate() error { + return disk.convertDataStructure().validate() +} + type QemuVirtIODisks struct { Disk_0 *QemuVirtIOStorage `json:"0,omitempty"` Disk_1 *QemuVirtIOStorage `json:"1,omitempty"` @@ -165,6 +169,19 @@ func (QemuVirtIODisks) mapToStruct(params map[string]interface{}) *QemuVirtIODis return nil } +func (disks QemuVirtIODisks) Validate() error { + diskMap := disks.mapToIntMap() + for _, e := range diskMap { + if e != nil { + err := e.Validate() + if err != nil { + return err + } + } + } + return nil +} + type QemuVirtIOPassthrough struct { AsyncIO QemuDiskAsyncIO Backup bool @@ -193,6 +210,10 @@ func (passthrough *QemuVirtIOPassthrough) convertDataStructure() *qemuDisk { } } +func (passthrough QemuVirtIOPassthrough) Validate() error { + return passthrough.convertDataStructure().validate() +} + type QemuVirtIOStorage struct { CdRom *QemuCdRom CloudInit *QemuCloudInitDisk @@ -265,3 +286,48 @@ func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { Size: tmpDisk.Size, }} } + +func (storage QemuVirtIOStorage) Validate() (err error) { + // First check if more than one item is nil + var subTypeSet bool + if storage.CdRom != nil { + subTypeSet = true + } + if storage.CloudInit != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + subTypeSet = true + } + if storage.Disk != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + subTypeSet = true + } + if storage.Passthrough != nil { + if err = diskSubtypeSet(subTypeSet); err != nil { + return + } + } + // Validate sub items + if storage.CdRom != nil { + if err = storage.CdRom.Validate(); err != nil { + return + } + } + if storage.CloudInit != nil { + if err = storage.CloudInit.Validate(); err != nil { + return + } + } + if storage.Disk != nil { + if err = storage.Disk.Validate(); err != nil { + return + } + } + if storage.Passthrough != nil { + err = storage.Passthrough.Validate() + } + return +} diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index 9ac99e58..ad8bfd0f 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -1,12 +1,1198 @@ package proxmox import ( + "errors" "strings" "testing" + "github.com/Telmate/proxmox-api-go/test/data/test_data_qemu" "github.com/stretchr/testify/require" ) +func Test_ConfigQemu_Validate(t *testing.T) { + BandwidthValid0 := QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{ + Burst: 0, + Concurrent: 0, + }, + WriteLimit: QemuDiskBandwidthDataLimit{ + Burst: 0, + Concurrent: 0, + }, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{ + Burst: 0, + Concurrent: 0, + }, + WriteLimit: QemuDiskBandwidthIopsLimit{ + Burst: 0, + Concurrent: 0, + }, + }, + } + BandwidthValid1 := QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{ + Burst: 1, + Concurrent: 1, + }, + WriteLimit: QemuDiskBandwidthDataLimit{ + Burst: 1, + Concurrent: 1, + }, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{ + Burst: 10, + Concurrent: 10, + }, + WriteLimit: QemuDiskBandwidthIopsLimit{ + Burst: 10, + Concurrent: 10, + }, + }, + } + BandwidthValid2 := QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{ + Burst: 1, + Concurrent: 0, + }, + WriteLimit: QemuDiskBandwidthDataLimit{ + Burst: 1, + Concurrent: 0, + }, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{ + Burst: 10, + Concurrent: 0, + }, + WriteLimit: QemuDiskBandwidthIopsLimit{ + Burst: 10, + Concurrent: 0, + }, + }, + } + BandwidthValid3 := QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{ + Burst: 0, + Concurrent: 1, + }, + WriteLimit: QemuDiskBandwidthDataLimit{ + Burst: 0, + Concurrent: 1, + }, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{ + Burst: 0, + Concurrent: 10, + }, + WriteLimit: QemuDiskBandwidthIopsLimit{ + Burst: 0, + Concurrent: 10, + }, + }, + } + testData := []struct { + name string + input ConfigQemu + err error + }{ + // Valid + // Valid Disks + {name: "Valid Disks Empty 0", + input: ConfigQemu{Disks: &QemuStorages{}}, + }, + {name: "Valid Disks Empty 1", + input: ConfigQemu{Disks: &QemuStorages{ + Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{}}, + Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{}}, + Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{}}, + VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{}}, + }}, + }, + // Valid Disks CdRom + {name: "Valid Disks CdRom", + input: ConfigQemu{Disks: &QemuStorages{ + Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CdRom: &QemuCdRom{}}}, + Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test", Storage: "test"}}}}, + Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}, + VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test", Storage: "test"}}}}, + }}, + }, + // Valid Disks CloudInit + {name: "Valid Disks CloudInit", + input: ConfigQemu{Disks: &QemuStorages{ + Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "Test"}}}, + }}, + }, + // Valid Disks Disk + {name: "Valid Disks Disk", + input: ConfigQemu{Disks: &QemuStorages{ + Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Bandwidth: BandwidthValid0, + Cache: QemuDiskCache_DirectSync, + Format: QemuDiskFormat_Raw, + Size: 32, + Storage: "test", + }}}, + Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Bandwidth: BandwidthValid1, + Cache: QemuDiskCache_None, + Format: QemuDiskFormat_Cow, + Size: 1, + Storage: "test", + }}}, + Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_Threads, + Bandwidth: BandwidthValid2, + Cache: QemuDiskCache_WriteBack, + Format: QemuDiskFormat_Qcow2, + Size: 10, + Storage: "test", + }}}, + VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: "", + Bandwidth: BandwidthValid3, + Cache: "", + Format: QemuDiskFormat_Vmdk, + Size: 1024, + Storage: "test", + }}}, + }}, + }, + // Valid Disks Passthrough + {name: "Valid Disks Passthrough", + input: ConfigQemu{Disks: &QemuStorages{ + Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Bandwidth: BandwidthValid3, + Cache: QemuDiskCache_DirectSync, + File: "test", + }}}, + Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + AsyncIO: QemuDiskAsyncIO_Native, + Bandwidth: BandwidthValid2, + Cache: "", + File: "test", + }}}, + Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + AsyncIO: QemuDiskAsyncIO_Threads, + Bandwidth: BandwidthValid1, + Cache: QemuDiskCache_WriteBack, + File: "test", + }}}, + VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + AsyncIO: "", + Bandwidth: BandwidthValid0, + Cache: QemuDiskCache_WriteThrough, + File: "test", + }}}, + }}, + }, + // Invalid + // Invalid Disks Mutually exclusive Ide + {name: "Invalid Disks MutuallyExclusive Ide 0", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Ide 1", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{ + CdRom: &QemuCdRom{}, + Disk: &QemuIdeDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Ide 2", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{ + CdRom: &QemuCdRom{}, + Passthrough: &QemuIdePassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Ide 3", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{ + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuIdeDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Ide 4", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{ + CloudInit: &QemuCloudInitDisk{}, + Passthrough: &QemuIdePassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Ide 5", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{ + Disk: &QemuIdeDisk{}, + Passthrough: &QemuIdePassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Ide 6", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuIdeDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Ide 7", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{ + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuIdeDisk{}, + Passthrough: &QemuIdePassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Ide 8", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{ + CdRom: &QemuCdRom{}, + Disk: &QemuIdeDisk{}, + Passthrough: &QemuIdePassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Ide 9", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Passthrough: &QemuIdePassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Ide 10", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuIdeDisk{}, + Passthrough: &QemuIdePassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + // Invalid Disks Mutually exclusive Sata + {name: "Invalid Disks MutuallyExclusive Sata 0", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Sata 1", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{ + CdRom: &QemuCdRom{}, + Disk: &QemuSataDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Sata 2", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{ + CdRom: &QemuCdRom{}, + Passthrough: &QemuSataPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Sata 3", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{ + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuSataDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Sata 4", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{ + CloudInit: &QemuCloudInitDisk{}, + Passthrough: &QemuSataPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Sata 5", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{ + Disk: &QemuSataDisk{}, + Passthrough: &QemuSataPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Sata 6", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuSataDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Sata 7", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{ + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuSataDisk{}, + Passthrough: &QemuSataPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Sata 8", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{ + CdRom: &QemuCdRom{}, + Disk: &QemuSataDisk{}, + Passthrough: &QemuSataPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Sata 9", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Passthrough: &QemuSataPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Sata 10", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuSataDisk{}, + Passthrough: &QemuSataPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + // Invalid Disks Mutually exclusive Scsi + {name: "Invalid Disks MutuallyExclusive Scsi 0", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Scsi 1", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{ + CdRom: &QemuCdRom{}, + Disk: &QemuScsiDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Scsi 2", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{ + CdRom: &QemuCdRom{}, + Passthrough: &QemuScsiPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Scsi 3", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{ + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuScsiDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Scsi 4", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{ + CloudInit: &QemuCloudInitDisk{}, + Passthrough: &QemuScsiPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Scsi 5", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{ + Disk: &QemuScsiDisk{}, + Passthrough: &QemuScsiPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Scsi 6", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuScsiDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Scsi 7", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{ + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuScsiDisk{}, + Passthrough: &QemuScsiPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Scsi 8", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{ + CdRom: &QemuCdRom{}, + Disk: &QemuScsiDisk{}, + Passthrough: &QemuScsiPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Scsi 9", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Passthrough: &QemuScsiPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive Scsi 10", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuScsiDisk{}, + Passthrough: &QemuScsiPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + // Invalid Disks Mutually exclusive VirtIO + {name: "Invalid Disks MutuallyExclusive VirtIO 0", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive VirtIO 1", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{ + CdRom: &QemuCdRom{}, + Disk: &QemuVirtIODisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive VirtIO 2", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{ + CdRom: &QemuCdRom{}, + Passthrough: &QemuVirtIOPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive VirtIO 3", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{ + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuVirtIODisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive VirtIO 4", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{ + CloudInit: &QemuCloudInitDisk{}, + Passthrough: &QemuVirtIOPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive VirtIO 5", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{ + Disk: &QemuVirtIODisk{}, + Passthrough: &QemuVirtIOPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive VirtIO 6", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuVirtIODisk{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive VirtIO 7", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{ + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuVirtIODisk{}, + Passthrough: &QemuVirtIOPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive VirtIO 8", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{ + CdRom: &QemuCdRom{}, + Disk: &QemuVirtIODisk{}, + Passthrough: &QemuVirtIOPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive VirtIO 9", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Passthrough: &QemuVirtIOPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + {name: "Invalid Disks MutuallyExclusive VirtIO 10", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{ + CdRom: &QemuCdRom{}, + CloudInit: &QemuCloudInitDisk{}, + Disk: &QemuVirtIODisk{}, + Passthrough: &QemuVirtIOPassthrough{}, + }}}}, + err: errors.New(Error_QemuDisk_MutuallyExclusive), + }, + // Invalid Disks CdRom Ide + {name: "Invalid Disks CdRom Ide errors.New(Error_IsoFile_File) 0", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{}}}}}}, + err: errors.New(Error_IsoFile_File), + }, + {name: "Invalid Disks CdRom Ide errors.New(Error_IsoFile_File) 1", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{Storage: "test"}}}}}}, + err: errors.New(Error_IsoFile_File), + }, + {name: "Invalid Disks CdRom Ide errors.New(Error_IsoFile_Storage)", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test"}}}}}}, + err: errors.New(Error_IsoFile_Storage), + }, + {name: "Invalid Disks CdRom Ide errors.New(Error_QemuCdRom_MutuallyExclusive)", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test", Storage: "test"}, Passthrough: true}}}}}, + err: errors.New(Error_QemuCdRom_MutuallyExclusive), + }, + // Invalid Disks CdRom Sata + {name: "Invalid Disks CdRom Sata errors.New(Error_IsoFile_File) 0", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{}}}}}}, + err: errors.New(Error_IsoFile_File), + }, + {name: "Invalid Disks CdRom Sata errors.New(Error_IsoFile_File) 1", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{Storage: "test"}}}}}}, + err: errors.New(Error_IsoFile_File), + }, + {name: "Invalid Disks CdRom Sata errors.New(Error_IsoFile_Storage)", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test"}}}}}}, + err: errors.New(Error_IsoFile_Storage), + }, + {name: "Invalid Disks CdRom Sata errors.New(Error_QemuCdRom_MutuallyExclusive)", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test", Storage: "test"}, Passthrough: true}}}}}, + err: errors.New(Error_QemuCdRom_MutuallyExclusive), + }, + // Invalid Disks CdRom Scsi + {name: "Invalid Disks CdRom Scsi errors.New(Error_IsoFile_File) 0", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{}}}}}}, + err: errors.New(Error_IsoFile_File), + }, + {name: "Invalid Disks CdRom Scsi errors.New(Error_IsoFile_File) 1", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{Storage: "test"}}}}}}, + err: errors.New(Error_IsoFile_File), + }, + {name: "Invalid Disks CdRom Scsi errors.New(Error_IsoFile_Storage)", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test"}}}}}}, + err: errors.New(Error_IsoFile_Storage), + }, + {name: "Invalid Disks CdRom Scsi errors.New(Error_QemuCdRom_MutuallyExclusive)", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test", Storage: "test"}, Passthrough: true}}}}}, + err: errors.New(Error_QemuCdRom_MutuallyExclusive), + }, + // Invalid Disks CdRom VirtIO + {name: "Invalid Disks CdRom VirtIO errors.New(Error_IsoFile_File) 0", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{}}}}}}, + err: errors.New(Error_IsoFile_File), + }, + {name: "Invalid Disks CdRom VirtIO errors.New(Error_IsoFile_File) 1", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{Storage: "test"}}}}}}, + err: errors.New(Error_IsoFile_File), + }, + {name: "Invalid Disks CdRom VirtIO errors.New(Error_IsoFile_Storage)", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test"}}}}}}, + err: errors.New(Error_IsoFile_Storage), + }, + {name: "Invalid Disks CdRom VirtIO errors.New(Error_QemuCdRom_MutuallyExclusive)", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test", Storage: "test"}, Passthrough: true}}}}}, + err: errors.New(Error_QemuCdRom_MutuallyExclusive), + }, + // Invalid Disks CloudInit Ide + {name: `Invalid Disks CloudInit Ide QemuDiskFormat("").Error() 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks CloudInit Ide QemuDiskFormat("").Error() 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{Storage: "test"}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks CloudInit Ide errors.New(Error_QemuCloudInitDisk_Storage)`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw}}}}}, + err: errors.New(Error_QemuCloudInitDisk_Storage), + }, + // Invalid Disks CloudInit Sata + {name: `Invalid Disks CloudInit Sata QemuDiskFormat("").Error() 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks CloudInit Sata QemuDiskFormat("").Error() 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{Storage: "test"}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks CloudInit Sata errors.New(Error_QemuCloudInitDisk_Storage)`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw}}}}}, + err: errors.New(Error_QemuCloudInitDisk_Storage), + }, + // Invalid Disks CloudInit Scsi + {name: `Invalid Disks CloudInit Scsi QemuDiskFormat("").Error() 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks CloudInit Scsi QemuDiskFormat("").Error() 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{Storage: "test"}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks CloudInit Scsi errors.New(Error_QemuCloudInitDisk_Storage)`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw}}}}}, + err: errors.New(Error_QemuCloudInitDisk_Storage), + }, + // Invalid Disks CloudInit VirtIO + {name: `Invalid Disks CloudInit VirtIO QemuDiskFormat("").Error() 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks CloudInit VirtIO QemuDiskFormat("").Error() 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{Storage: "test"}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks CloudInit VirtIO errors.New(Error_QemuCloudInitDisk_Storage)`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw}}}}}, + err: errors.New(Error_QemuCloudInitDisk_Storage), + }, + // Invalid Disks Disk Ide + {name: `Invalid Disks Disk Ide QemuDiskFormat("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks Disk Ide QemuDiskAsyncIO("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{AsyncIO: "invalid"}}}}}, + err: QemuDiskAsyncIO("").Error(), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Disk Ide QemuDiskCache("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Cache: "invalid"}}}}}, + err: QemuDiskCache("").Error(), + }, + {name: `Invalid Disks Disk Ide QemuDiskFormat("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: ""}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskSerial_IllegalCharacter)`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Serial: "!@^$^&$^&"}, + }}}}, + err: errors.New(Error_QemuDiskSerial_IllegalCharacter), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskSerial_IllegalLength)`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Serial: QemuDiskSerial(test_data_qemu.QemuDiskSerial_Max_Illegal()), + }}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalLength), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDisk_Size)`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Size: 0, + }}}}}, + err: errors.New(Error_QemuDisk_Size), + }, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDisk_Storage)`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Size: 32, + Storage: "", + }}}}}, + err: errors.New(Error_QemuDisk_Storage), + }, + // Invalid Disks Disk Sata + {name: `Invalid Disks Disk Sata QemuDiskFormat("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks Disk Sata QemuDiskAsyncIO("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{AsyncIO: "invalid"}}}}}, + err: QemuDiskAsyncIO("").Error(), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Disk Sata QemuDiskCache("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Cache: "invalid"}}}}}, + err: QemuDiskCache("").Error(), + }, + {name: `Invalid Disks Disk Sata QemuDiskFormat("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Format: ""}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskSerial_IllegalCharacter)`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Serial: "!@^$^&$^&"}, + }}}}, + err: errors.New(Error_QemuDiskSerial_IllegalCharacter), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskSerial_IllegalLength)`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Serial: QemuDiskSerial(test_data_qemu.QemuDiskSerial_Max_Illegal()), + }}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalLength), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDisk_Size)`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Size: 0, + }}}}}, + err: errors.New(Error_QemuDisk_Size), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDisk_Storage)`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Size: 32, + Storage: "", + }}}}}, + err: errors.New(Error_QemuDisk_Storage), + }, + // Invalid Disks Disk Scsi + {name: `Invalid Disks Disk Scsi QemuDiskFormat("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Disk: &QemuScsiDisk{}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks Disk Scsi QemuDiskAsyncIO("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Disk: &QemuScsiDisk{AsyncIO: "invalid"}}}}}, + err: QemuDiskAsyncIO("").Error(), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Disk Scsi QemuDiskCache("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Disk: &QemuScsiDisk{Cache: "invalid"}}}}}, + err: QemuDiskCache("").Error(), + }, + {name: `Invalid Disks Disk Scsi QemuDiskFormat("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: ""}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskSerial_IllegalCharacter)`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Serial: "!@^$^&$^&"}, + }}}}, + err: errors.New(Error_QemuDiskSerial_IllegalCharacter), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskSerial_IllegalLength)`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Serial: QemuDiskSerial(test_data_qemu.QemuDiskSerial_Max_Illegal()), + }}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalLength), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDisk_Size)`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_14: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Size: 0, + }}}}}, + err: errors.New(Error_QemuDisk_Size), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDisk_Storage)`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Size: 32, + Storage: "", + }}}}}, + err: errors.New(Error_QemuDisk_Storage), + }, + // Invalid Disks Disk VirtIO + {name: `Invalid Disks Disk VirtIO QemuDiskFormat("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks Disk VirtIO QemuDiskAsyncIO("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{AsyncIO: "invalid"}}}}}, + err: QemuDiskAsyncIO("").Error(), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Disk VirtIO QemuDiskCache("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Cache: "invalid"}}}}}, + err: QemuDiskCache("").Error(), + }, + {name: `Invalid Disks Disk VirtIO QemuDiskFormat("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: ""}}}}}, + err: QemuDiskFormat("").Error(), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskSerial_IllegalCharacter)`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Serial: "!@^$^&$^&"}, + }}}}, + err: errors.New(Error_QemuDiskSerial_IllegalCharacter), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskSerial_IllegalLength)`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Serial: QemuDiskSerial(test_data_qemu.QemuDiskSerial_Max_Illegal()), + }}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalLength), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDisk_Size)`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_14: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Size: 0, + }}}}}, + err: errors.New(Error_QemuDisk_Size), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDisk_Storage)`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Size: 32, + Storage: "", + }}}}}, + err: errors.New(Error_QemuDisk_Storage), + }, + // Invalid Disks Passthrough Ide + {name: `Invalid Disks Passthrough Ide QemuDiskAsyncIO("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{AsyncIO: "invalid"}}}}}, + err: QemuDiskAsyncIO("").Error(), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Ide QemuDiskCache("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Cache: "invalid"}}}}}, + err: QemuDiskCache("").Error(), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDisk_File)`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{File: ""}}}}}, + err: errors.New(Error_QemuDisk_File), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskSerial_IllegalCharacter)`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{File: "/dev/disk/by-id/scsi1", Serial: "!@^$^&$^&"}}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalCharacter), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskSerial_IllegalLength)`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{File: "/dev/disk/by-id/scsi1", Serial: QemuDiskSerial(test_data_qemu.QemuDiskSerial_Max_Illegal())}}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalLength), + }, + // Invalid Disks Passthrough Sata + {name: `Invalid Disks Passthrough Sata QemuDiskAsyncIO("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{AsyncIO: "invalid"}}}}}, + err: QemuDiskAsyncIO("").Error(), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Sata QemuDiskCache("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Cache: "invalid"}}}}}, + err: QemuDiskCache("").Error(), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDisk_File)`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{File: ""}}}}}, + err: errors.New(Error_QemuDisk_File), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskSerial_IllegalCharacter)`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{File: "/dev/disk/by-id/scsi1", Serial: "!@^$^&$^&"}}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalCharacter), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskSerial_IllegalLength)`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{File: "/dev/disk/by-id/scsi1", Serial: QemuDiskSerial(test_data_qemu.QemuDiskSerial_Max_Illegal())}}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalLength), + }, + // Invalid Disks Passthrough Scsi + {name: `Invalid Disks Passthrough Scsi QemuDiskAsyncIO("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{AsyncIO: "invalid"}}}}}, + err: QemuDiskAsyncIO("").Error(), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough Scsi QemuDiskCache("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Cache: "invalid"}}}}}, + err: QemuDiskCache("").Error(), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDisk_File)`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{File: ""}}}}}, + err: errors.New(Error_QemuDisk_File), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskSerial_IllegalCharacter)`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{File: "/dev/disk/by-id/scsi1", Serial: "!@^$^&$^&"}}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalCharacter), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskSerial_IllegalLength)`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{File: "/dev/disk/by-id/scsi1", Serial: QemuDiskSerial(test_data_qemu.QemuDiskSerial_Max_Illegal())}}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalLength), + }, + // Invalid Disks Passthrough VirtIO + {name: `Invalid Disks Passthrough VirtIO QemuDiskAsyncIO("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{AsyncIO: "invalid"}}}}}, + err: QemuDiskAsyncIO("").Error(), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + }, + {name: `Invalid Disks Passthrough VirtIO QemuDiskCache("").Error()`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Cache: "invalid"}}}}}, + err: QemuDiskCache("").Error(), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDisk_File)`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{File: ""}}}}}, + err: errors.New(Error_QemuDisk_File), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskSerial_IllegalCharacter)`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{File: "/dev/disk/by-id/scsi1", Serial: "!@^$^&$^&"}}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalCharacter), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskSerial_IllegalLength)`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{File: "/dev/disk/by-id/scsi1", Serial: QemuDiskSerial(test_data_qemu.QemuDiskSerial_Max_Illegal())}}}}}, + err: errors.New(Error_QemuDiskSerial_IllegalLength), + }, + } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) + } +} + // Test the encoding logic to encode the ssh keys func Test_sshKeyUrlEncode(t *testing.T) { input := test_sshKeyUrlEncode_Input() From 1fe52d4e55ab1cfcc8140143483926867829c1fc Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Mar 2023 08:45:46 +0000 Subject: [PATCH 078/120] refactor: update json keys --- proxmox/config_qemu_disk.go | 28 ++++++++--------- proxmox/config_qemu_disk_ide.go | 34 ++++++++++---------- proxmox/config_qemu_disk_sata.go | 42 ++++++++++++------------- proxmox/config_qemu_disk_scsi.go | 50 +++++++++++++++--------------- proxmox/config_qemu_disk_virtio.go | 44 +++++++++++++------------- 5 files changed, 99 insertions(+), 99 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 536d7f6e..76edd333 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -439,8 +439,8 @@ func (asyncIO QemuDiskAsyncIO) Validate() error { } type QemuDiskBandwidth struct { - Data QemuDiskBandwidthData - Iops QemuDiskBandwidthIops + Data QemuDiskBandwidthData `json:"data,omitempty"` + Iops QemuDiskBandwidthIops `json:"iops,omitempty"` } func (bandwidth QemuDiskBandwidth) Validate() error { @@ -452,8 +452,8 @@ func (bandwidth QemuDiskBandwidth) Validate() error { } type QemuDiskBandwidthData struct { - ReadLimit QemuDiskBandwidthDataLimit - WriteLimit QemuDiskBandwidthDataLimit + ReadLimit QemuDiskBandwidthDataLimit `json:"read,omitempty"` + WriteLimit QemuDiskBandwidthDataLimit `json:"write,omitempty"` } func (data QemuDiskBandwidthData) Validate() error { @@ -465,8 +465,8 @@ func (data QemuDiskBandwidthData) Validate() error { } type QemuDiskBandwidthDataLimit struct { - Burst float32 // 0 = default - Concurrent float32 // 0 = unlimited + Burst float32 `json:"burst,omitempty"` // 0 = default + Concurrent float32 `json:"concurrent,omitempty"` // 0 = unlimited } const ( @@ -485,8 +485,8 @@ func (limit QemuDiskBandwidthDataLimit) Validate() error { } type QemuDiskBandwidthIops struct { - ReadLimit QemuDiskBandwidthIopsLimit - WriteLimit QemuDiskBandwidthIopsLimit + ReadLimit QemuDiskBandwidthIopsLimit `json:"read,omitempty"` + WriteLimit QemuDiskBandwidthIopsLimit `json:"write,omitempty"` } func (iops QemuDiskBandwidthIops) Validate() error { @@ -498,8 +498,8 @@ func (iops QemuDiskBandwidthIops) Validate() error { } type QemuDiskBandwidthIopsLimit struct { - Burst uint // 0 = default - Concurrent uint // 0 = unlimited + Burst uint `json:"burst,omitempty"` // 0 = default + Concurrent uint `json:"concurrent,omitempty"` // 0 = unlimited } const ( @@ -609,10 +609,10 @@ const ( ) type qemuStorage struct { - CdRom *QemuCdRom `json:"cdrom,omitempty"` - CloudInit *QemuCloudInitDisk `json:"cloudinit,omitempty"` - Disk *qemuDisk `json:"disk,omitempty"` - Passthrough *qemuDisk `json:"passthrough,omitempty"` + CdRom *QemuCdRom + CloudInit *QemuCloudInitDisk + Disk *qemuDisk + Passthrough *qemuDisk } func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID uint, id string, params map[string]interface{}, changes *qemuUpdateChanges) { diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 69c801be..62363a1a 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -4,17 +4,17 @@ import "strconv" type QemuIdeDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup,omitempty"` + Backup bool `json:"backup"` Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard,omitempty"` - EmulateSSD bool `json:"emulatessd,omitempty"` - Format QemuDiskFormat `json:"format,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + Format QemuDiskFormat `json:"format"` Id *uint `json:"id,omitempty"` - Replicate bool `json:"replicate,omitempty"` + Replicate bool `json:"replicate"` Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size,omitempty"` - Storage string `json:"storage,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuIdeDisk) convertDataStructure() *qemuDisk { @@ -109,16 +109,16 @@ func (disks QemuIdeDisks) Validate() error { } type QemuIdePassthrough struct { - AsyncIO QemuDiskAsyncIO - Backup bool - Bandwidth QemuDiskBandwidth - Cache QemuDiskCache - Discard bool - EmulateSSD bool - File string - Replicate bool - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint //size is only returned and setting it has no effect + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + File string `json:"file"` + Replicate bool `json:"replicate"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` //size is only returned and setting it has no effect } func (passthrough *QemuIdePassthrough) convertDataStructure() *qemuDisk { diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 69759d8e..340c663a 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -4,17 +4,17 @@ import "strconv" type QemuSataDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup,omitempty"` + Backup bool `json:"backup"` Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard,omitempty"` - EmulateSSD bool `json:"emulatessd,omitempty"` - Format QemuDiskFormat `json:"format,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + Format QemuDiskFormat `json:"format"` Id *uint `json:"id,omitempty"` - Replicate bool `json:"replicate,omitempty"` + Replicate bool `json:"replicate"` Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size,omitempty"` - Storage string `json:"storage,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuSataDisk) convertDataStructure() *qemuDisk { @@ -121,16 +121,16 @@ func (disks QemuSataDisks) Validate() error { } type QemuSataPassthrough struct { - AsyncIO QemuDiskAsyncIO - Backup bool - Bandwidth QemuDiskBandwidth - Cache QemuDiskCache - Discard bool - EmulateSSD bool - File string - Replicate bool - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint //size is only returned and setting it has no effect + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + File string `json:"file"` + Replicate bool `json:"replicate"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` //size is only returned and setting it has no effect } func (passthrough *QemuSataPassthrough) convertDataStructure() *qemuDisk { @@ -153,10 +153,10 @@ func (passthrough QemuSataPassthrough) Validate() error { } type QemuSataStorage struct { - CdRom *QemuCdRom - CloudInit *QemuCloudInitDisk - Disk *QemuSataDisk - Passthrough *QemuSataPassthrough + CdRom *QemuCdRom `json:"cdrom,omitempty"` + CloudInit *QemuCloudInitDisk `json:"cloudinit,omitempty"` + Disk *QemuSataDisk `json:"disk,omitempty"` + Passthrough *QemuSataPassthrough `json:"passthrough,omitempty"` } // TODO write test diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 851dc1e6..7a304a1f 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -4,19 +4,19 @@ import "strconv" type QemuScsiDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup,omitempty"` + Backup bool `json:"backup"` Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard,omitempty"` - EmulateSSD bool `json:"emulatessd,omitempty"` - Format QemuDiskFormat `json:"format,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + Format QemuDiskFormat `json:"format"` Id *uint `json:"id,omitempty"` - IOThread bool `json:"iothread,omitempty"` - ReadOnly bool `json:"readonly,omitempty"` - Replicate bool `json:"replicate,omitempty"` + IOThread bool `json:"iothread"` + ReadOnly bool `json:"readonly"` + Replicate bool `json:"replicate"` Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size,omitempty"` - Storage string `json:"storage,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuScsiDisk) convertDataStructure() *qemuDisk { @@ -275,18 +275,18 @@ func (disks QemuScsiDisks) Validate() error { } type QemuScsiPassthrough struct { - AsyncIO QemuDiskAsyncIO - Backup bool - Bandwidth QemuDiskBandwidth - Cache QemuDiskCache - Discard bool - EmulateSSD bool - File string - IOThread bool - ReadOnly bool - Replicate bool - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint //size is only returned and setting it has no effect + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + File string `json:"file"` + IOThread bool `json:"iothread"` + ReadOnly bool `json:"readonly"` + Replicate bool `json:"replicate"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` //size is only returned and setting it has no effect } func (passthrough *QemuScsiPassthrough) convertDataStructure() *qemuDisk { @@ -311,10 +311,10 @@ func (passthrough QemuScsiPassthrough) Validate() error { } type QemuScsiStorage struct { - CdRom *QemuCdRom - CloudInit *QemuCloudInitDisk - Disk *QemuScsiDisk - Passthrough *QemuScsiPassthrough + CdRom *QemuCdRom `json:"cdrom,omitempty"` + CloudInit *QemuCloudInitDisk `json:"cloudinit,omitempty"` + Disk *QemuScsiDisk `json:"disk,omitempty"` + Passthrough *QemuScsiPassthrough `json:"passthrough,omitempty"` } // TODO write test diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index a16ab105..fd181109 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -4,18 +4,18 @@ import "strconv" type QemuVirtIODisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup,omitempty"` + Backup bool `json:"backup"` Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard,omitempty"` - Format QemuDiskFormat `json:"format,omitempty"` + Discard bool `json:"discard"` + Format QemuDiskFormat `json:"format"` Id *uint `json:"id,omitempty"` - IOThread bool `json:"iothread,omitempty"` - ReadOnly bool `json:"readonly,omitempty"` - Replicate bool `json:"replicate,omitempty"` + IOThread bool `json:"iothread"` + ReadOnly bool `json:"readonly"` + Replicate bool `json:"replicate"` Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size,omitempty"` - Storage string `json:"storage,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuVirtIODisk) convertDataStructure() *qemuDisk { @@ -183,16 +183,16 @@ func (disks QemuVirtIODisks) Validate() error { } type QemuVirtIOPassthrough struct { - AsyncIO QemuDiskAsyncIO - Backup bool - Bandwidth QemuDiskBandwidth - Cache QemuDiskCache - Discard bool - File string - IOThread bool - ReadOnly bool - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint //size is only returned and setting it has no effect + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + File string `json:"file"` + IOThread bool `json:"iothread"` + ReadOnly bool `json:"readonly"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` //size is only returned and setting it has no effect } func (passthrough *QemuVirtIOPassthrough) convertDataStructure() *qemuDisk { @@ -215,10 +215,10 @@ func (passthrough QemuVirtIOPassthrough) Validate() error { } type QemuVirtIOStorage struct { - CdRom *QemuCdRom - CloudInit *QemuCloudInitDisk - Disk *QemuVirtIODisk - Passthrough *QemuVirtIOPassthrough + CdRom *QemuCdRom `json:"cdrom,omitempty"` + CloudInit *QemuCloudInitDisk `json:"cloudinit,omitempty"` + Disk *QemuVirtIODisk `json:"disk,omitempty"` + Passthrough *QemuVirtIOPassthrough `json:"passthrough,omitempty"` } // TODO write test From 3bf288862f0bbfa76beb1a8acacc0b029c90e96d Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Mar 2023 09:33:32 +0000 Subject: [PATCH 079/120] fix: not checking for duplicate cloudinit disk --- proxmox/config_qemu_disk.go | 35 ++++++++++++++-- proxmox/config_qemu_disk_ide.go | 24 +++++++++-- proxmox/config_qemu_disk_sata.go | 26 +++++++++--- proxmox/config_qemu_disk_scsi.go | 26 +++++++++--- proxmox/config_qemu_disk_virtio.go | 24 +++++++++-- proxmox/config_qemu_test.go | 65 ++++++++++++++++++++++++++---- 6 files changed, 171 insertions(+), 29 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 76edd333..48427dc0 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -145,8 +145,16 @@ type QemuCloudInitDisk struct { const ( Error_QemuCloudInitDisk_Storage string = "storage should not be empty" + Error_QemuCloudInitDisk_OnlyOne string = "only one cloud init disk may exist" ) +func (QemuCloudInitDisk) checkDuplicates(numberOFCloudInitDrives uint8) error { + if numberOFCloudInitDrives > 1 { + return errors.New(Error_QemuCloudInitDisk_OnlyOne) + } + return nil +} + // TODO write test func (cloudInit QemuCloudInitDisk) mapToApiValues() string { return cloudInit.Storage + ":cloudinit,format=" + string(cloudInit.Format) @@ -745,26 +753,45 @@ func (storages QemuStorages) markDiskChanges(currentStorages QemuStorages, vmID } func (storages QemuStorages) Validate() (err error) { + var numberOfCloudInitDevices uint8 + var CloudInit uint8 if storages.Ide != nil { - err = storages.Ide.Validate() + CloudInit, err = storages.Ide.validate() if err != nil { return } + numberOfCloudInitDevices += CloudInit + if err = (QemuCloudInitDisk{}.checkDuplicates(numberOfCloudInitDevices)); err != nil { + return + } } if storages.Sata != nil { - err = storages.Sata.Validate() + CloudInit, err = storages.Sata.validate() if err != nil { return } + numberOfCloudInitDevices += CloudInit + if err = (QemuCloudInitDisk{}.checkDuplicates(numberOfCloudInitDevices)); err != nil { + return + } } if storages.Scsi != nil { - err = storages.Scsi.Validate() + CloudInit, err = storages.Scsi.validate() if err != nil { return } + numberOfCloudInitDevices += CloudInit + if err = (QemuCloudInitDisk{}.checkDuplicates(numberOfCloudInitDevices)); err != nil { + return + } } if storages.VirtIO != nil { - err = storages.VirtIO.Validate() + CloudInit, err = storages.VirtIO.validate() + if err != nil { + return + } + numberOfCloudInitDevices += CloudInit + err = QemuCloudInitDisk{}.checkDuplicates(numberOfCloudInitDevices) } return } diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 62363a1a..5b0491db 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -95,17 +95,27 @@ func (QemuIdeDisks) mapToStruct(params map[string]interface{}) *QemuIdeDisks { return nil } -func (disks QemuIdeDisks) Validate() error { +func (disks QemuIdeDisks) Validate() (err error) { + _, err = disks.validate() + return +} + +func (disks QemuIdeDisks) validate() (numberOfCloudInitDevices uint8, err error) { diskMap := disks.mapToIntMap() + var cloudInit uint8 for _, e := range diskMap { if e != nil { - err := e.Validate() + cloudInit, err = e.validate() if err != nil { - return err + return + } + numberOfCloudInitDevices += cloudInit + if err = (QemuCloudInitDisk{}.checkDuplicates(numberOfCloudInitDevices)); err != nil { + return } } } - return nil + return } type QemuIdePassthrough struct { @@ -213,6 +223,11 @@ func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { } func (storage QemuIdeStorage) Validate() (err error) { + _, err = storage.validate() + return +} + +func (storage QemuIdeStorage) validate() (CloudInit uint8, err error) { // First check if more than one item is nil var subTypeSet bool if storage.CdRom != nil { @@ -223,6 +238,7 @@ func (storage QemuIdeStorage) Validate() (err error) { return } subTypeSet = true + CloudInit = 1 } if storage.Disk != nil { if err = diskSubtypeSet(subTypeSet); err != nil { diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 340c663a..2dcd0732 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -107,17 +107,27 @@ func (QemuSataDisks) mapToStruct(params map[string]interface{}) *QemuSataDisks { return nil } -func (disks QemuSataDisks) Validate() error { +func (disks QemuSataDisks) Validate() (err error) { + _, err = disks.validate() + return +} + +func (disks QemuSataDisks) validate() (numberOfCloudInitDevices uint8, err error) { diskMap := disks.mapToIntMap() + var cloudInit uint8 for _, e := range diskMap { if e != nil { - err := e.Validate() + cloudInit, err = e.validate() if err != nil { - return err + return + } + numberOfCloudInitDevices += cloudInit + if err = (QemuCloudInitDisk{}.checkDuplicates(numberOfCloudInitDevices)); err != nil { + return } } } - return nil + return } type QemuSataPassthrough struct { @@ -224,7 +234,12 @@ func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { }} } -func (storage *QemuSataStorage) Validate() (err error) { +func (storage QemuSataStorage) Validate() (err error) { + _, err = storage.validate() + return +} + +func (storage QemuSataStorage) validate() (CloudInit uint8, err error) { // First check if more than one item is nil var subTypeSet bool if storage.CdRom != nil { @@ -235,6 +250,7 @@ func (storage *QemuSataStorage) Validate() (err error) { return } subTypeSet = true + CloudInit = 1 } if storage.Disk != nil { if err = diskSubtypeSet(subTypeSet); err != nil { diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 7a304a1f..6cb5c12d 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -261,17 +261,27 @@ func (QemuScsiDisks) mapToStruct(params map[string]interface{}) *QemuScsiDisks { return nil } -func (disks QemuScsiDisks) Validate() error { +func (disks QemuScsiDisks) Validate() (err error) { + _, err = disks.validate() + return +} + +func (disks QemuScsiDisks) validate() (numberOfCloudInitDevices uint8, err error) { diskMap := disks.mapToIntMap() + var cloudInit uint8 for _, e := range diskMap { if e != nil { - err := e.Validate() + cloudInit, err = e.validate() if err != nil { - return err + return + } + numberOfCloudInitDevices += cloudInit + if err = (QemuCloudInitDisk{}.checkDuplicates(numberOfCloudInitDevices)); err != nil { + return } } } - return nil + return } type QemuScsiPassthrough struct { @@ -386,7 +396,12 @@ func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { }} } -func (storage *QemuScsiStorage) Validate() (err error) { +func (storage QemuScsiStorage) Validate() (err error) { + _, err = storage.validate() + return +} + +func (storage QemuScsiStorage) validate() (CloudInit uint8, err error) { // First check if more than one item is nil var subTypeSet bool if storage.CdRom != nil { @@ -397,6 +412,7 @@ func (storage *QemuScsiStorage) Validate() (err error) { return } subTypeSet = true + CloudInit = 1 } if storage.Disk != nil { if err = diskSubtypeSet(subTypeSet); err != nil { diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index fd181109..8641ed87 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -169,17 +169,27 @@ func (QemuVirtIODisks) mapToStruct(params map[string]interface{}) *QemuVirtIODis return nil } -func (disks QemuVirtIODisks) Validate() error { +func (disks QemuVirtIODisks) Validate() (err error) { + _, err = disks.validate() + return +} + +func (disks QemuVirtIODisks) validate() (numberOfCloudInitDevices uint8, err error) { diskMap := disks.mapToIntMap() + var cloudInit uint8 for _, e := range diskMap { if e != nil { - err := e.Validate() + cloudInit, err = e.validate() if err != nil { - return err + return + } + numberOfCloudInitDevices += cloudInit + if err = (QemuCloudInitDisk{}.checkDuplicates(numberOfCloudInitDevices)); err != nil { + return } } } - return nil + return } type QemuVirtIOPassthrough struct { @@ -288,6 +298,11 @@ func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { } func (storage QemuVirtIOStorage) Validate() (err error) { + _, err = storage.validate() + return +} + +func (storage QemuVirtIOStorage) validate() (CloudInit uint8, err error) { // First check if more than one item is nil var subTypeSet bool if storage.CdRom != nil { @@ -298,6 +313,7 @@ func (storage QemuVirtIOStorage) Validate() (err error) { return } subTypeSet = true + CloudInit = 1 } if storage.Disk != nil { if err = diskSubtypeSet(subTypeSet); err != nil { diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index ad8bfd0f..68a10e68 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -98,6 +98,7 @@ func Test_ConfigQemu_Validate(t *testing.T) { }, }, } + validCloudInit := QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "Test"} testData := []struct { name string input ConfigQemu @@ -126,13 +127,17 @@ func Test_ConfigQemu_Validate(t *testing.T) { }}, }, // Valid Disks CloudInit - {name: "Valid Disks CloudInit", - input: ConfigQemu{Disks: &QemuStorages{ - Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "Test"}}}, - Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "Test"}}}, - Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "Test"}}}, - VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "Test"}}}, - }}, + {name: "Valid Disks CloudInit Ide", + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CloudInit: &validCloudInit}}}}, + }, + {name: "Valid Disks CloudInit Sata", + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CloudInit: &validCloudInit}}}}, + }, + {name: "Valid Disks CloudInit Scsi", + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{CloudInit: &validCloudInit}}}}, + }, + {name: "Valid Disks CloudInit VirtIO", + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{CloudInit: &validCloudInit}}}}, }, // Valid Disks Disk {name: "Valid Disks Disk", @@ -605,6 +610,52 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test", Storage: "test"}, Passthrough: true}}}}}, err: errors.New(Error_QemuCdRom_MutuallyExclusive), }, + // Invalid Disks CloudInit Duplicate + {name: "Invalid Disks CloudInit Duplicate errors.New(Error_QemuCloudInitDisk_OnlyOne)", + input: ConfigQemu{Disks: &QemuStorages{ + Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CloudInit: &validCloudInit}}, + Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CloudInit: &validCloudInit}}, + Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{CloudInit: &validCloudInit}}, + VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{CloudInit: &validCloudInit}}, + }}, + err: errors.New(Error_QemuCloudInitDisk_OnlyOne), + }, + {name: "Invalid Disks CloudInit Duplicate Ide errors.New(Error_QemuCloudInitDisk_OnlyOne)", + input: ConfigQemu{Disks: &QemuStorages{ + Ide: &QemuIdeDisks{ + Disk_0: &QemuIdeStorage{CloudInit: &validCloudInit}, + Disk_1: &QemuIdeStorage{CloudInit: &validCloudInit}, + }, + }}, + err: errors.New(Error_QemuCloudInitDisk_OnlyOne), + }, + {name: "Invalid Disks CloudInit Duplicate Sata errors.New(Error_QemuCloudInitDisk_OnlyOne)", + input: ConfigQemu{Disks: &QemuStorages{ + Sata: &QemuSataDisks{ + Disk_0: &QemuSataStorage{CloudInit: &validCloudInit}, + Disk_1: &QemuSataStorage{CloudInit: &validCloudInit}, + }, + }}, + err: errors.New(Error_QemuCloudInitDisk_OnlyOne), + }, + {name: "Invalid Disks CloudInit Duplicate Scsi errors.New(Error_QemuCloudInitDisk_OnlyOne)", + input: ConfigQemu{Disks: &QemuStorages{ + Scsi: &QemuScsiDisks{ + Disk_0: &QemuScsiStorage{CloudInit: &validCloudInit}, + Disk_1: &QemuScsiStorage{CloudInit: &validCloudInit}, + }, + }}, + err: errors.New(Error_QemuCloudInitDisk_OnlyOne), + }, + {name: "Invalid Disks CloudInit Duplicate VirtIO errors.New(Error_QemuCloudInitDisk_OnlyOne)", + input: ConfigQemu{Disks: &QemuStorages{ + VirtIO: &QemuVirtIODisks{ + Disk_0: &QemuVirtIOStorage{CloudInit: &validCloudInit}, + Disk_1: &QemuVirtIOStorage{CloudInit: &validCloudInit}, + }, + }}, + err: errors.New(Error_QemuCloudInitDisk_OnlyOne), + }, // Invalid Disks CloudInit Ide {name: `Invalid Disks CloudInit Ide QemuDiskFormat("").Error() 0`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{}}}}}, From 651d6457f5fe068476dc0e2539c94eadec741a80 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Mar 2023 09:39:06 +0000 Subject: [PATCH 080/120] Add TODO --- proxmox/config_qemu.go | 1 + 1 file changed, 1 insertion(+) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 9ce0041f..526e45b0 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -691,6 +691,7 @@ func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef func (config ConfigQemu) Validate() (err error) { // TODO test all other use cases + // TODO has no context about changes caused by updating the vm if config.Disks != nil { err = config.Disks.Validate() if err != nil { From 199a7d1f6e7cb5c5b2b1e8431d5ac6112ac0fcbd Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Mar 2023 10:08:14 +0000 Subject: [PATCH 081/120] refactor: move defaults to seperate fuction moved the defaults to its own function, to make testing easier --- proxmox/config_qemu.go | 60 ++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 526e45b0..10e98bd8 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -115,6 +115,42 @@ func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { return } +func (config *ConfigQemu) defaults() { + if config.Boot == "" { + config.Boot = "cdn" + } + if config.Bios == "" { + config.Bios = "seabios" + } + if config.Onboot == nil { + config.Onboot = PointerBool(true) + } + if config.Hotplug == "" { + config.Hotplug = "network,disk,usb" + } + if config.QemuCores == 0 { + config.QemuCores = 1 + } + if config.QemuCpu == "" { + config.QemuCpu = "host" + } + if config.QemuKVM == nil { + config.QemuKVM = PointerBool(true) + } + if config.QemuOs == "" { + config.QemuOs = "other" + } + if config.QemuSockets == 0 { + config.QemuSockets = 1 + } + if config.Scsihw == "" { + config.Scsihw = "lsi" + } + if config.Tablet == nil { + config.Tablet = PointerBool(true) + } +} + func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (params map[string]interface{}, markedDisks *qemuUpdateChanges, err error) { var itemsToDelete string @@ -318,16 +354,12 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu //boot by default from hard disk (c), CD-ROM (d), network (n). if _, isSet := params["boot"]; isSet { config.Boot = params["boot"].(string) - } else { - config.Boot = "cdn" } if _, isSet := params["bootdisk"]; isSet { config.BootDisk = params["bootdisk"].(string) } if _, isSet := params["bios"]; isSet { config.Bios = params["bios"].(string) - } else { - config.Bios = "seabios" } if _, isSet := params["cicustom"]; isSet { config.CIcustom = params["cicustom"].(string) @@ -344,8 +376,6 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu //Can be network,disk,cpu,memory,usb if _, isSet := params["hotplug"]; isSet { config.Hotplug = params["hotplug"].(string) - } else { - config.Hotplug = "network,disk,usb" } if _, isSet := params["hookscript"]; isSet { config.Hookscript = params["hookscript"].(string) @@ -361,36 +391,24 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu } if _, isSet := params["onboot"]; isSet { config.Onboot = PointerBool(Itob(int(params["onboot"].(float64)))) - } else { - config.Onboot = PointerBool(true) } if _, isSet := params["cores"]; isSet { config.QemuCores = int(params["cores"].(float64)) - } else { - config.QemuCores = 1 } if _, isSet := params["cpu"]; isSet { config.QemuCpu = params["cpu"].(string) - } else { - config.QemuCpu = "host" } if _, isSet := params["kvm"]; isSet { config.QemuKVM = PointerBool(Itob(int(params["kvm"].(float64)))) - } else { - config.QemuKVM = PointerBool(true) } if _, isSet := params["numa"]; isSet { config.QemuNuma = PointerBool(Itob(int(params["numa"].(float64)))) } if _, isSet := params["ostype"]; isSet { config.QemuOs = params["ostype"].(string) - } else { - config.QemuOs = "other" } if _, isSet := params["sockets"]; isSet { config.QemuSockets = int(params["sockets"].(float64)) - } else { - config.QemuSockets = 1 } if _, isSet := params["vcpus"]; isSet { vCpu := int(params["vcpus"].(float64)) @@ -400,8 +418,6 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu } if _, isSet := params["scsihw"]; isSet { config.Scsihw = params["scsihw"].(string) - } else { - config.Scsihw = "lsi" } if _, isSet := params["searchdomain"]; isSet { config.Searchdomain = params["searchdomain"].(string) @@ -414,8 +430,6 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu } if _, isSet := params["tablet"]; isSet { config.Tablet = PointerBool(Itob(int(params["tablet"].(float64)))) - } else { - config.Tablet = PointerBool(true) } if _, isSet := params["tags"]; isSet { config.Tags = strings.TrimSpace(params["tags"].(string)) @@ -987,7 +1001,7 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e if err != nil { return } - + config.defaults() // HAstate is return by the api for a vm resource type but not the HAgroup err = client.ReadVMHA(vmr) if err == nil { From f42049a8c886a2c816fd95c58dfc925f9023ea5e Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Mar 2023 10:35:36 +0000 Subject: [PATCH 082/120] refactor: move defaults to seperate fuction moved more defaults to its own function, to make testing easier --- proxmox/config_qemu.go | 99 +++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 35 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 10e98bd8..b9644154 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -116,39 +116,70 @@ func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { } func (config *ConfigQemu) defaults() { + if config == nil { + return + } if config.Boot == "" { config.Boot = "cdn" } if config.Bios == "" { config.Bios = "seabios" } + if config.EFIDisk == nil { + config.EFIDisk = QemuDevice{} + } if config.Onboot == nil { config.Onboot = PointerBool(true) } if config.Hotplug == "" { config.Hotplug = "network,disk,usb" } + if config.Ipconfig == nil { + config.Ipconfig = IpconfigMap{} + } if config.QemuCores == 0 { config.QemuCores = 1 } if config.QemuCpu == "" { config.QemuCpu = "host" } + if config.QemuDisks == nil { + config.QemuDisks = QemuDevices{} + } if config.QemuKVM == nil { config.QemuKVM = PointerBool(true) } + if config.QemuNetworks == nil { + config.QemuNetworks = QemuDevices{} + } if config.QemuOs == "" { config.QemuOs = "other" } + if config.QemuPCIDevices == nil { + config.QemuPCIDevices = QemuDevices{} + } + if config.QemuSerials == nil { + config.QemuSerials = QemuDevices{} + } if config.QemuSockets == 0 { config.QemuSockets = 1 } + if config.QemuUnusedDisks == nil { + config.QemuUnusedDisks = QemuDevices{} + } + if config.QemuUsbs == nil { + config.QemuUsbs = QemuDevices{} + } + if config.QemuVga == nil { + config.QemuVga = QemuDevice{} + } if config.Scsihw == "" { config.Scsihw = "lsi" } if config.Tablet == nil { config.Tablet = PointerBool(true) } + } func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (params map[string]interface{}, markedDisks *qemuUpdateChanges, err error) { @@ -321,17 +352,7 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu // description:Base image // cores:2 ostype:l26 - config = &ConfigQemu{ - EFIDisk: QemuDevice{}, - QemuDisks: QemuDevices{}, - QemuUnusedDisks: QemuDevices{}, - QemuVga: QemuDevice{}, - QemuNetworks: QemuDevices{}, - QemuSerials: QemuDevices{}, - QemuPCIDevices: QemuDevices{}, - QemuUsbs: QemuDevices{}, - Ipconfig: IpconfigMap{}, - } + config = &ConfigQemu{} if _, isSet := params["agent"]; isSet { switch params["agent"].(type) { @@ -443,11 +464,14 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu } } - for _, ipconfigName := range ipconfigNames { - ipConfStr := params[ipconfigName] - id := rxDeviceID.FindStringSubmatch(ipconfigName) - ipconfigID, _ := strconv.Atoi(id[0]) - config.Ipconfig[ipconfigID] = ipConfStr + if len(ipconfigNames) > 0 { + config.Ipconfig = IpconfigMap{} + for _, ipconfigName := range ipconfigNames { + ipConfStr := params[ipconfigName] + id := rxDeviceID.FindStringSubmatch(ipconfigName) + ipconfigID, _ := strconv.Atoi(id[0]) + config.Ipconfig[ipconfigID] = ipConfStr + } } config.Disks = QemuStorages{}.mapToStruct(params) @@ -469,29 +493,34 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu // log.Printf("[DEBUG] unusedDiskNames: %v", unusedDiskNames) // } - for _, unusedDiskName := range unusedDiskNames { - unusedDiskConfStr := params[unusedDiskName].(string) - finalDiskConfMap := QemuDevice{} + if len(unusedDiskNames) > 0 { + config.QemuUnusedDisks = QemuDevices{} + for _, unusedDiskName := range unusedDiskNames { + unusedDiskConfStr := params[unusedDiskName].(string) + finalDiskConfMap := QemuDevice{} - // parse "unused0" to get the id '0' as an int - id := rxDeviceID.FindStringSubmatch(unusedDiskName) - diskID, err := strconv.Atoi(id[0]) - if err != nil { - return nil, fmt.Errorf(fmt.Sprintf("Unable to parse unused disk id from input string '%v' tried to convert '%v' to integer.", unusedDiskName, diskID)) + // parse "unused0" to get the id '0' as an int + id := rxDeviceID.FindStringSubmatch(unusedDiskName) + diskID, err := strconv.Atoi(id[0]) + if err != nil { + return nil, fmt.Errorf(fmt.Sprintf("Unable to parse unused disk id from input string '%v' tried to convert '%v' to integer.", unusedDiskName, diskID)) + } + finalDiskConfMap["slot"] = diskID + + // parse the attributes from the unused disk + // extract the storage and file path from the unused disk entry + parsedUnusedDiskMap := ParsePMConf(unusedDiskConfStr, "storage+file") + storageName, fileName := ParseSubConf(parsedUnusedDiskMap["storage+file"].(string), ":") + finalDiskConfMap["storage"] = storageName + finalDiskConfMap["file"] = fileName + + config.QemuUnusedDisks[diskID] = finalDiskConfMap + config.QemuUnusedDisks[diskID] = finalDiskConfMap + config.QemuUnusedDisks[diskID] = finalDiskConfMap } - finalDiskConfMap["slot"] = diskID - - // parse the attributes from the unused disk - // extract the storage and file path from the unused disk entry - parsedUnusedDiskMap := ParsePMConf(unusedDiskConfStr, "storage+file") - storageName, fileName := ParseSubConf(parsedUnusedDiskMap["storage+file"].(string), ":") - finalDiskConfMap["storage"] = storageName - finalDiskConfMap["file"] = fileName - - config.QemuUnusedDisks[diskID] = finalDiskConfMap } - //Display + if vga, isSet := params["vga"]; isSet { vgaList := strings.Split(vga.(string), ",") vgaMap := QemuDevice{} From c1438e2a7d438ad9aeb68aca835b3e31e1785487 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Mar 2023 10:39:37 +0000 Subject: [PATCH 083/120] refactor: remove pointer inside func --- proxmox/config_qemu.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index b9644154..eedea685 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -342,7 +342,7 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (params map[st return } -func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu, err error) { +func (ConfigQemu) mapToStruct(params map[string]interface{}) (*ConfigQemu, error) { // vmConfig Sample: map[ cpu:host // net0:virtio=62:DF:XX:XX:XX:XX,bridge=vmbr0 // ide2:local:iso/xxx-xx.iso,media=cdrom memory:2048 @@ -352,7 +352,7 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu // description:Base image // cores:2 ostype:l26 - config = &ConfigQemu{} + config := ConfigQemu{} if _, isSet := params["agent"]; isSet { switch params["agent"].(type) { @@ -656,8 +656,7 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (config *ConfigQemu } } - return - + return &config, nil } func (newConfig ConfigQemu) Update(vmr *VmRef, client *Client) (err error) { From 221764a8ca8bc37549b0c6ec8b5891a70cc46c85 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Mar 2023 11:01:47 +0000 Subject: [PATCH 084/120] fix: item not initialized before use --- proxmox/config_qemu.go | 154 ++++++++++++++++++++++------------------- 1 file changed, 83 insertions(+), 71 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index eedea685..7bc9f87b 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -540,39 +540,42 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (*ConfigQemu, error } } - for _, nicName := range nicNames { - nicConfStr := params[nicName] - nicConfList := strings.Split(nicConfStr.(string), ",") - - id := rxDeviceID.FindStringSubmatch(nicName) - nicID, _ := strconv.Atoi(id[0]) - model, macaddr := ParseSubConf(nicConfList[0], "=") - - // Add model and MAC address. - nicConfMap := QemuDevice{ - "id": nicID, - "model": model, - "macaddr": macaddr, - } + if len(nicNames) > 0 { + config.QemuNetworks = QemuDevices{} + for _, nicName := range nicNames { + nicConfStr := params[nicName] + nicConfList := strings.Split(nicConfStr.(string), ",") + + id := rxDeviceID.FindStringSubmatch(nicName) + nicID, _ := strconv.Atoi(id[0]) + model, macaddr := ParseSubConf(nicConfList[0], "=") + + // Add model and MAC address. + nicConfMap := QemuDevice{ + "id": nicID, + "model": model, + "macaddr": macaddr, + } - // Add rest of device config. - nicConfMap.readDeviceConfig(nicConfList[1:]) - switch nicConfMap["firewall"] { - case 1: - nicConfMap["firewall"] = true - case 0: - nicConfMap["firewall"] = false - } - switch nicConfMap["link_down"] { - case 1: - nicConfMap["link_down"] = true - case 0: - nicConfMap["link_down"] = false - } + // Add rest of device config. + nicConfMap.readDeviceConfig(nicConfList[1:]) + switch nicConfMap["firewall"] { + case 1: + nicConfMap["firewall"] = true + case 0: + nicConfMap["firewall"] = false + } + switch nicConfMap["link_down"] { + case 1: + nicConfMap["link_down"] = true + case 0: + nicConfMap["link_down"] = false + } - // And device config to networks. - if len(nicConfMap) > 0 { - config.QemuNetworks[nicID] = nicConfMap + // And device config to networks. + if len(nicConfMap) > 0 { + config.QemuNetworks[nicID] = nicConfMap + } } } @@ -585,18 +588,21 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (*ConfigQemu, error } } - for _, serialName := range serialNames { - id := rxDeviceID.FindStringSubmatch(serialName) - serialID, _ := strconv.Atoi(id[0]) + if len(serialNames) > 0 { + config.QemuSerials = QemuDevices{} + for _, serialName := range serialNames { + id := rxDeviceID.FindStringSubmatch(serialName) + serialID, _ := strconv.Atoi(id[0]) - serialConfMap := QemuDevice{ - "id": serialID, - "type": params[serialName], - } + serialConfMap := QemuDevice{ + "id": serialID, + "type": params[serialName], + } - // And device config to serials map. - if len(serialConfMap) > 0 { - config.QemuSerials[serialID] = serialConfMap + // And device config to serials map. + if len(serialConfMap) > 0 { + config.QemuSerials[serialID] = serialConfMap + } } } @@ -609,26 +615,29 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (*ConfigQemu, error } } - for _, usbName := range usbNames { - usbConfStr := params[usbName] - usbConfList := strings.Split(usbConfStr.(string), ",") - id := rxDeviceID.FindStringSubmatch(usbName) - usbID, _ := strconv.Atoi(id[0]) - _, host := ParseSubConf(usbConfList[0], "=") - - usbConfMap := QemuDevice{ - "id": usbID, - "host": host, - } + if len(usbNames) > 0 { + config.QemuUsbs = QemuDevices{} + for _, usbName := range usbNames { + usbConfStr := params[usbName] + usbConfList := strings.Split(usbConfStr.(string), ",") + id := rxDeviceID.FindStringSubmatch(usbName) + usbID, _ := strconv.Atoi(id[0]) + _, host := ParseSubConf(usbConfList[0], "=") + + usbConfMap := QemuDevice{ + "id": usbID, + "host": host, + } - usbConfMap.readDeviceConfig(usbConfList[1:]) - if usbConfMap["usb3"] == 1 { - usbConfMap["usb3"] = true - } + usbConfMap.readDeviceConfig(usbConfList[1:]) + if usbConfMap["usb3"] == 1 { + usbConfMap["usb3"] = true + } - // And device config to usbs map. - if len(usbConfMap) > 0 { - config.QemuUsbs[usbID] = usbConfMap + // And device config to usbs map. + if len(usbConfMap) > 0 { + config.QemuUsbs[usbID] = usbConfMap + } } } @@ -641,18 +650,21 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (*ConfigQemu, error } } - for _, hostPCIname := range hostPCInames { - hostPCIConfStr := params[hostPCIname] - hostPCIConfList := strings.Split(hostPCIConfStr.(string), ",") - id := rxPCIName.FindStringSubmatch(hostPCIname) - hostPCIID, _ := strconv.Atoi(id[0]) - hostPCIConfMap := QemuDevice{ - "id": hostPCIID, - } - hostPCIConfMap.readDeviceConfig(hostPCIConfList) - // And device config to usbs map. - if len(hostPCIConfMap) > 0 { - config.QemuPCIDevices[hostPCIID] = hostPCIConfMap + if len(hostPCInames) > 0 { + config.QemuPCIDevices = QemuDevices{} + for _, hostPCIname := range hostPCInames { + hostPCIConfStr := params[hostPCIname] + hostPCIConfList := strings.Split(hostPCIConfStr.(string), ",") + id := rxPCIName.FindStringSubmatch(hostPCIname) + hostPCIID, _ := strconv.Atoi(id[0]) + hostPCIConfMap := QemuDevice{ + "id": hostPCIID, + } + hostPCIConfMap.readDeviceConfig(hostPCIConfList) + // And device config to usbs map. + if len(hostPCIConfMap) > 0 { + config.QemuPCIDevices[hostPCIID] = hostPCIConfMap + } } } From 70d28959042ea46c53ea7eaf17be7c6efcd580f8 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Mar 2023 11:12:46 +0000 Subject: [PATCH 085/120] fix: discard not set to true --- proxmox/config_qemu_disk.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 48427dc0..41b7aeaa 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -327,7 +327,9 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { continue } if e[0] == "discard" { - disk.Discard, _ = strconv.ParseBool(e[1]) + if e[1] == "on" { + disk.Discard = true + } continue } if e[0] == "iops_rd" { From e2022c79df05dfe0eb435e29106d5e1818148fc2 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Mar 2023 12:27:09 +0000 Subject: [PATCH 086/120] fix: make replicate true by default --- proxmox/config_qemu_disk.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 41b7aeaa..95b93a8b 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -313,6 +313,9 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { } } + // Replicate defaults to true + disk.Replicate = true + for _, e := range settings { if e[0] == "aio" { disk.AsyncIO = QemuDiskAsyncIO(e[1]) From 813adfa4509196efbaa4559a06e65bb8c23be026 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 16 Mar 2023 18:40:33 +0000 Subject: [PATCH 087/120] fix: CdRom not properly converted to struct --- proxmox/config_qemu_disk.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 95b93a8b..007193b8 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -53,7 +53,7 @@ func (cdRom QemuCdRom) mapToApiValues() string { } func (QemuCdRom) mapToStruct(settings qemuCdRom) *QemuCdRom { - if !settings.Passthrough { + if settings.File != "" { return &QemuCdRom{ Iso: &IsoFile{ Storage: settings.Storage, @@ -62,7 +62,7 @@ func (QemuCdRom) mapToStruct(settings qemuCdRom) *QemuCdRom { }, } } - return &QemuCdRom{Passthrough: false} + return &QemuCdRom{Passthrough: settings.Passthrough} } func (cdRom QemuCdRom) Validate() error { @@ -102,10 +102,10 @@ func (qemuCdRom) mapToStruct(settings [][]string) *qemuCdRom { return nil } if settings[0][0] == "none" { - return &qemuCdRom{} + return &qemuCdRom{CdRom: true} } if settings[0][0] == "cdrom" { - return &qemuCdRom{Passthrough: true} + return &qemuCdRom{CdRom: true, Passthrough: true} } tmpStorage := strings.Split(settings[0][0], ":") if len(tmpStorage) > 1 { From d8cbbdc680f20b24e24757e3f2bd077fc553d853 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Fri, 17 Mar 2023 14:43:05 +0000 Subject: [PATCH 088/120] fix: missing `Replicate` on `QemuVirtIOPassthrough` --- proxmox/config_qemu_disk_virtio.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 8641ed87..d5f068e2 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -201,6 +201,7 @@ type QemuVirtIOPassthrough struct { File string `json:"file"` IOThread bool `json:"iothread"` ReadOnly bool `json:"readonly"` + Replicate bool `json:"replicate"` Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size"` //size is only returned and setting it has no effect } @@ -215,6 +216,7 @@ func (passthrough *QemuVirtIOPassthrough) convertDataStructure() *qemuDisk { File: passthrough.File, IOThread: passthrough.IOThread, ReadOnly: passthrough.ReadOnly, + Replicate: passthrough.Replicate, Serial: passthrough.Serial, Type: virtIO, } @@ -292,6 +294,7 @@ func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { File: tmpDisk.File, IOThread: tmpDisk.IOThread, ReadOnly: tmpDisk.ReadOnly, + Replicate: tmpDisk.Replicate, Serial: tmpDisk.Serial, Size: tmpDisk.Size, }} From 8dab836d7af8eb40726c6cc078f3894d9095228c Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Fri, 17 Mar 2023 14:49:09 +0000 Subject: [PATCH 089/120] test: add test for mapping `ConfigQemu.Disks` from Api values --- proxmox/config_qemu_test.go | 1764 +++++++++++++++++++++++++++++++++++ 1 file changed, 1764 insertions(+) diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index 68a10e68..3e73d1a4 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -9,6 +9,1770 @@ import ( "github.com/stretchr/testify/require" ) +func Test_ConfigQemu_mapToStruct(t *testing.T) { + uint2 := uint(2) + uint31 := uint(31) + uint47 := uint(47) + uint53 := uint(53) + tests := []struct { + name string + input map[string]interface{} + output *ConfigQemu + err error + }{ + // TODO add test cases for all other items of ConfigQemu{} + // Disks Ide CdRom + {name: "Disks Ide CdRom none", + input: map[string]interface{}{"ide1": "none,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CdRom: &QemuCdRom{}}}}}, + }, + {name: "Disks Ide CdRom passthrough", + input: map[string]interface{}{"ide2": "cdrom,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + }, + {name: "Disks Ide CdRom iso", + input: map[string]interface{}{"ide3": "local:iso/debian-11.0.0-amd64-netinst.iso,media=cdrom,size=377M"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{ + File: "debian-11.0.0-amd64-netinst.iso", + Storage: "local", + Size: "377M", + }}}}}}, + }, + // Disks Ide CloudInit + {name: "Disks Ide CloudInit", + input: map[string]interface{}{"ide0": "Test:100/vm-100-cloudinit.raw,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{ + Format: QemuDiskFormat_Raw, + Storage: "Test", + }}}}}, + }, + // Disks Ide Disk + {name: "Disks Ide Disk", + input: map[string]interface{}{"ide0": "test2:100/vm-100-disk-53.qcow2"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk ALL", + input: map[string]interface{}{"ide1": "test2:100/vm-100-disk-53.qcow2,aio=io_uring,backup=0,cache=writethrough,discard=on,iops_rd=12,iops_rd_max=13,iops_wr=15,iops_wr_max=14,mbps_rd=1.46,mbps_rd_max=3.57,mbps_wr=2.68,mbps_wr_max=4.55,replicate=0,serial=disk-9763,size=1032G,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.57, Concurrent: 1.46}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.55, Concurrent: 2.68}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 12}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 14, Concurrent: 15}, + }, + }, + Cache: QemuDiskCache_WriteThrough, + Discard: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: false, + Serial: "disk-9763", + Size: 1032, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk aio", + input: map[string]interface{}{"ide2": "test2:100/vm-100-disk-53.qcow2,aio=io_uring"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk backup", + input: map[string]interface{}{"ide3": "test2:100/vm-100-disk-53.qcow2,backup=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: false, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk cache", + input: map[string]interface{}{"ide0": "test2:100/vm-100-disk-53.qcow2,cache=writethrough"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Cache: QemuDiskCache_WriteThrough, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk discard", + input: map[string]interface{}{"ide1": "test2:100/vm-100-disk-53.qcow2,discard=on"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Discard: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk iops_rd", + input: map[string]interface{}{"ide2": "test2:100/vm-100-disk-53.qcow2,iops_rd=12"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 12}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk iops_rd_max", + input: map[string]interface{}{"ide3": "test2:100/vm-100-disk-53.qcow2,iops_rd_max=13"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk iops_wr", + input: map[string]interface{}{"ide0": "test2:100/vm-100-disk-53.qcow2,iops_wr=15"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 15}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk iops_wr_max", + input: map[string]interface{}{"ide1": "test2:100/vm-100-disk-53.qcow2,iops_wr_max=14"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 14}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk mbps_rd", + input: map[string]interface{}{"ide2": "test2:100/vm-100-disk-53.qcow2,mbps_rd=1.46"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.46}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk mbps_rd_max", + input: map[string]interface{}{"ide3": "test2:100/vm-100-disk-53.qcow2,mbps_rd_max=3.57"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.57}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk mbps_wr", + input: map[string]interface{}{"ide0": "test2:100/vm-100-disk-53.qcow2,mbps_wr=2.68"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.68}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk mbps_wr_max", + input: map[string]interface{}{"ide1": "test2:100/vm-100-disk-53.qcow2,mbps_wr_max=4.55"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.55}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk replicate", + input: map[string]interface{}{"ide2": "test2:100/vm-100-disk-53.qcow2,replicate=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: false, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk serial", + input: map[string]interface{}{"ide3": "test2:100/vm-100-disk-53.qcow2,serial=disk-9763"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Serial: "disk-9763", + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk size", + input: map[string]interface{}{"ide0": "test2:100/vm-100-disk-53.qcow2,size=1032G"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Size: 1032, + Storage: "test2", + }}}}}, + }, + {name: "Disks Ide Disk ssd", + input: map[string]interface{}{"ide1": "test2:100/vm-100-disk-53.qcow2,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, + // Disks Ide Passthrough + {name: "Disks Ide Passthrough", + input: map[string]interface{}{"ide0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough All", + input: map[string]interface{}{"ide1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,backup=0,cache=unsafe,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=1G,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + }, + }, + Cache: QemuDiskCache_Unsafe, + Discard: true, + EmulateSSD: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: false, + Serial: "disk-9763", + Size: 1, + }}}}}, + }, + {name: "Disks Ide Passthrough aio", + input: map[string]interface{}{"ide2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough backup", + input: map[string]interface{}{"ide3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,backup=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: false, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough cache", + input: map[string]interface{}{"ide0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,cache=unsafe"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Cache: QemuDiskCache_Unsafe, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough discard", + input: map[string]interface{}{"ide1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,discard=on"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Discard: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough iops_rd", + input: map[string]interface{}{"ide2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd=10"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough iops_rd_max", + input: map[string]interface{}{"ide3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd_max=12"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough iops_wr", + input: map[string]interface{}{"ide0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr=11"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 11}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough iops_wr_max", + input: map[string]interface{}{"ide1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr_max=13"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough mbps_rd", + input: map[string]interface{}{"ide2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd=1.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough mbps_rd_max", + input: map[string]interface{}{"ide3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd_max=3.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough mbps_wr", + input: map[string]interface{}{"ide0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr=2.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough mbps_wr_max", + input: map[string]interface{}{"ide1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr_max=4.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Ide Passthrough replicate", + input: map[string]interface{}{"ide2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,replicate=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: false, + }}}}}, + }, + {name: "Disks Ide Passthrough serial", + input: map[string]interface{}{"ide3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,serial=disk-9763"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + Serial: "disk-9763", + }}}}}, + }, + {name: "Disks Ide Passthrough size", + input: map[string]interface{}{"ide0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,size=1G"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + Size: 1, + }}}}}, + }, + {name: "Disks Ide Passthrough ssd", + input: map[string]interface{}{"ide1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + EmulateSSD: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + // Disks Sata CdRom + {name: "Disks Sata CdRom none", + input: map[string]interface{}{"sata5": "none,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{CdRom: &QemuCdRom{}}}}}, + }, + {name: "Disks Sata CdRom passthrough", + input: map[string]interface{}{"sata4": "cdrom,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + }, + {name: "Disks Sata CdRom iso", + input: map[string]interface{}{"sata3": "local:iso/debian-11.0.0-amd64-netinst.iso,media=cdrom,size=377M"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{ + File: "debian-11.0.0-amd64-netinst.iso", + Storage: "local", + Size: "377M", + }}}}}}, + }, + // Disks Sata CloudInit + {name: "Disks Sata CloudInit", + input: map[string]interface{}{"sata0": "Test:100/vm-100-cloudinit.raw,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{ + Format: QemuDiskFormat_Raw, + Storage: "Test", + }}}}}, + }, + // Disks Sata Disk + {name: "Disks Sata Disk", + input: map[string]interface{}{"sata0": "test2:100/vm-100-disk-47.qcow2"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk ALL", + input: map[string]interface{}{"sata1": "test2:100/vm-100-disk-47.qcow2,aio=native,backup=0,cache=none,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=32G,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + }, + }, + Cache: QemuDiskCache_None, + Discard: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: false, + Serial: "disk-9763", + Size: 32, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk aio", + input: map[string]interface{}{"sata2": "test2:100/vm-100-disk-47.qcow2,aio=native"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk backup", + input: map[string]interface{}{"sata3": "test2:100/vm-100-disk-47.qcow2,backup=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: false, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk cache", + input: map[string]interface{}{"sata4": "test2:100/vm-100-disk-47.qcow2,cache=none"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Cache: QemuDiskCache_None, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk discard", + input: map[string]interface{}{"sata5": "test2:100/vm-100-disk-47.qcow2,discard=on"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Discard: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk iops_rd", + input: map[string]interface{}{"sata0": "test2:100/vm-100-disk-47.qcow2,iops_rd=10"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk iops_rd_max", + input: map[string]interface{}{"sata1": "test2:100/vm-100-disk-47.qcow2,iops_rd_max=12"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk iops_wr", + input: map[string]interface{}{"sata2": "test2:100/vm-100-disk-47.qcow2,iops_wr=11"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 11}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk iops_wr_max", + input: map[string]interface{}{"sata3": "test2:100/vm-100-disk-47.qcow2,iops_wr_max=13"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk mbps_rd", + input: map[string]interface{}{"sata4": "test2:100/vm-100-disk-47.qcow2,mbps_rd=1.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk mbps_rd_max", + input: map[string]interface{}{"sata5": "test2:100/vm-100-disk-47.qcow2,mbps_rd_max=3.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk mbps_wr", + input: map[string]interface{}{"sata0": "test2:100/vm-100-disk-47.qcow2,mbps_wr=2.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}, + }, + }, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk mbps_wr_max", + input: map[string]interface{}{"sata1": "test2:100/vm-100-disk-47.qcow2,mbps_wr_max=4.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk replicate", + input: map[string]interface{}{"sata2": "test2:100/vm-100-disk-47.qcow2,replicate=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: false, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk serial", + input: map[string]interface{}{"sata3": "test2:100/vm-100-disk-47.qcow2,serial=disk-9763"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Serial: "disk-9763", + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk size", + input: map[string]interface{}{"sata4": "test2:100/vm-100-disk-47.qcow2,size=32G"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Size: 32, + Storage: "test2", + }}}}}, + }, + {name: "Disks Sata Disk ssd", + input: map[string]interface{}{"sata5": "test2:100/vm-100-disk-47.qcow2,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, + // Disks Sata Passthrough + {name: "Disks Sata Passthrough", + input: map[string]interface{}{"sata1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough All", + input: map[string]interface{}{"sata1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=io_uring,backup=0,cache=directsync,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=1G,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + }, + }, + Cache: QemuDiskCache_DirectSync, + Discard: true, + EmulateSSD: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: false, + Serial: "disk-9763", + Size: 1, + }}}}}, + }, + {name: "Disks Sata Passthrough aio", + input: map[string]interface{}{"sata2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=io_uring"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough backup", + input: map[string]interface{}{"sata3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,backup=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: false, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough cache", + input: map[string]interface{}{"sata4": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,cache=directsync"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Cache: QemuDiskCache_DirectSync, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough discard", + input: map[string]interface{}{"sata5": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,discard=on"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Discard: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough iops_rd", + input: map[string]interface{}{"sata0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd=10"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough iops_rd_max", + input: map[string]interface{}{"sata1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd_max=12"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough iops_wr", + input: map[string]interface{}{"sata2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr=11"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 11}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough iops_wr_max", + input: map[string]interface{}{"sata3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr_max=13"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough mbps_rd", + input: map[string]interface{}{"sata4": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd=1.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough mbps_rd_max", + input: map[string]interface{}{"sata5": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd_max=3.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough mbps_wr", + input: map[string]interface{}{"sata0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr=2.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough mbps_wr_max", + input: map[string]interface{}{"sata1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr_max=4.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Sata Passthrough replicate", + input: map[string]interface{}{"sata2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,replicate=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: false, + }}}}}, + }, + {name: "Disks Sata Passthrough serial", + input: map[string]interface{}{"sata3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,serial=disk-9763"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + Serial: "disk-9763", + }}}}}, + }, + {name: "Disks Sata Passthrough size", + input: map[string]interface{}{"sata4": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,size=1G"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + Size: 1, + }}}}}, + }, + {name: "Disks Sata Passthrough ssd", + input: map[string]interface{}{"sata5": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + EmulateSSD: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + // Disks Scsi CdRom + {name: "Disks Scsi CdRom none", + input: map[string]interface{}{"scsi30": "none,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_30: &QemuScsiStorage{CdRom: &QemuCdRom{}}}}}, + }, + {name: "Disks Scsi CdRom passthrough", + input: map[string]interface{}{"scsi29": "cdrom,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_29: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + }, + {name: "Disks Scsi CdRom iso", + input: map[string]interface{}{"scsi28": "local:iso/debian-11.0.0-amd64-netinst.iso,media=cdrom,size=377M"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_28: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{ + File: "debian-11.0.0-amd64-netinst.iso", + Storage: "local", + Size: "377M", + }}}}}}, + }, + // Disks Scsi CloudInit + {name: "Disks Scsi CloudInit", + input: map[string]interface{}{"scsi0": "Test:100/vm-100-cloudinit.raw,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{ + Format: QemuDiskFormat_Raw, + Storage: "Test", + }}}}}, + }, + // Disks Scsi Disk + {name: "Disks Scsi Disk", + input: map[string]interface{}{"scsi0": "test:100/vm-100-disk-2.qcow2"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk ALL", + input: map[string]interface{}{"scsi1": "test:100/vm-100-disk-2.qcow2,aio=threads,backup=0,cache=writeback,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + }, + }, + Cache: QemuDiskCache_WriteBack, + Discard: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + IOThread: true, + ReadOnly: true, + Replicate: false, + Serial: "disk-9763", + Size: 32, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk aio", + input: map[string]interface{}{"scsi2": "test:100/vm-100-disk-2.qcow2,aio=threads"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk backup", + input: map[string]interface{}{"scsi3": "test:100/vm-100-disk-2.qcow2,backup=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: false, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk cache", + input: map[string]interface{}{"scsi4": "test:100/vm-100-disk-2.qcow2,cache=writeback"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Cache: QemuDiskCache_WriteBack, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk discard", + input: map[string]interface{}{"scsi5": "test:100/vm-100-disk-2.qcow2,discard=on"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Discard: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk iops_rd", + input: map[string]interface{}{"scsi6": "test:100/vm-100-disk-2.qcow2,iops_rd=10"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk iops_rd_max", + input: map[string]interface{}{"scsi7": "test:100/vm-100-disk-2.qcow2,iops_rd_max=12"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk iops_wr", + input: map[string]interface{}{"scsi8": "test:100/vm-100-disk-2.qcow2,iops_wr=11"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 11}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk iops_wr_max", + input: map[string]interface{}{"scsi9": "test:100/vm-100-disk-2.qcow2,iops_wr_max=13"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk iothread", + input: map[string]interface{}{"scsi10": "test:100/vm-100-disk-2.qcow2,iothread=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + IOThread: true, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk mbps_rd", + input: map[string]interface{}{"scsi11": "test:100/vm-100-disk-2.qcow2,mbps_rd=1.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk mbps_rd_max", + input: map[string]interface{}{"scsi12": "test:100/vm-100-disk-2.qcow2,mbps_rd_max=3.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk mbps_wr", + input: map[string]interface{}{"scsi13": "test:100/vm-100-disk-2.qcow2,mbps_wr=2.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk mbps_wr_max", + input: map[string]interface{}{"scsi14": "test:100/vm-100-disk-2.qcow2,mbps_wr_max=4.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_14: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk replicate", + input: map[string]interface{}{"scsi15": "test:100/vm-100-disk-2.qcow2,replicate=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: false, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk ro", + input: map[string]interface{}{"scsi16": "test:100/vm-100-disk-2.qcow2,ro=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + ReadOnly: true, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk serial", + input: map[string]interface{}{"scsi17": "test:100/vm-100-disk-2.qcow2,serial=disk-9763"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Serial: "disk-9763", + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk size", + input: map[string]interface{}{"scsi18": "test:100/vm-100-disk-2.qcow2,size=32G"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Size: 32, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk ssd", + input: map[string]interface{}{"scsi19": "test:100/vm-100-disk-2.qcow2,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + // Disks Scsi Passthrough + {name: "Disks Scsi Passthrough", + input: map[string]interface{}{"scsi0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough All", + input: map[string]interface{}{"scsi1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,backup=0,cache=none,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=1G,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + }, + }, + Cache: QemuDiskCache_None, + Discard: true, + EmulateSSD: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + IOThread: true, + ReadOnly: true, + Replicate: false, + Serial: "disk-9763", + Size: 1, + }}}}}, + }, + {name: "Disks Scsi Passthrough aio", + input: map[string]interface{}{"scsi2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough backup", + input: map[string]interface{}{"scsi3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,backup=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: false, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough cache", + input: map[string]interface{}{"scsi4": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,cache=none"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Cache: QemuDiskCache_None, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough discard", + input: map[string]interface{}{"scsi5": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,discard=on"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Discard: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough iops_rd", + input: map[string]interface{}{"scsi6": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd=10"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough iops_rd_max", + input: map[string]interface{}{"scsi7": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd_max=12"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough iops_wr", + input: map[string]interface{}{"scsi8": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr=11"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 11}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough iops_wr_max", + input: map[string]interface{}{"scsi9": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr_max=13"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough iothread", + input: map[string]interface{}{"scsi10": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iothread=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + IOThread: true, + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough mbps_rd", + input: map[string]interface{}{"scsi11": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd=1.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough mbps_rd_max", + input: map[string]interface{}{"scsi12": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd_max=3.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough mbps_wr", + input: map[string]interface{}{"scsi13": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr=2.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough mbps_wr_max", + input: map[string]interface{}{"scsi14": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr_max=4.51"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_14: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough replicate", + input: map[string]interface{}{"scsi15": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,replicate=0"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: false, + }}}}}, + }, + {name: "Disks Scsi Passthrough ro", + input: map[string]interface{}{"scsi16": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,ro=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + ReadOnly: true, + Replicate: true, + }}}}}, + }, + {name: "Disks Scsi Passthrough serial", + input: map[string]interface{}{"scsi17": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,serial=disk-9763"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + Serial: "disk-9763", + }}}}}, + }, + {name: "Disks Scsi Passthrough size", + input: map[string]interface{}{"scsi18": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,size=1G"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + Size: 1, + }}}}}, + }, + {name: "Disks Scsi Passthrough ssd", + input: map[string]interface{}{"scsi19": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + EmulateSSD: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + // VirtIO CdRom + {name: "Disks VirtIO CdRom none", + input: map[string]interface{}{"virtio11": "none,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{CdRom: &QemuCdRom{}}}}}, + }, + {name: "Disks VirtIO CdRom passthrough", + input: map[string]interface{}{"virtio10": "cdrom,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + }, + {name: "Disks VirtIO CdRom iso", + input: map[string]interface{}{"virtio9": "local:iso/debian-11.0.0-amd64-netinst.iso,media=cdrom,size=377M"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{ + File: "debian-11.0.0-amd64-netinst.iso", + Storage: "local", + Size: "377M", + }}}}}}, + }, + // Disks VirtIO CloudInit + {name: "Disks VirtIO CloudInit", + input: map[string]interface{}{"virtio0": "Test:100/vm-100-cloudinit.raw,media=cdrom"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{ + Format: QemuDiskFormat_Raw, + Storage: "Test", + }}}}}, + }, + // Disks VirtIO Disk + {name: "Disks VirtIO Disk", + input: map[string]interface{}{"virtio0": "test2:100/vm-100-disk-31.qcow2"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk ALL", + input: map[string]interface{}{"virtio1": "test2:100/vm-100-disk-31.qcow2,aio=io_uring,backup=0,cache=directsync,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + }, + }, + Cache: QemuDiskCache_DirectSync, + Discard: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + IOThread: true, + ReadOnly: true, + Replicate: false, + Serial: "disk-9763", + Size: 32, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk aio", + input: map[string]interface{}{"virtio2": "test2:100/vm-100-disk-31.qcow2,aio=io_uring"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk backup", + input: map[string]interface{}{"virtio3": "test2:100/vm-100-disk-31.qcow2,backup=0"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: false, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk cache", + input: map[string]interface{}{"virtio4": "test2:100/vm-100-disk-31.qcow2,cache=directsync"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Cache: QemuDiskCache_DirectSync, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk discard", + input: map[string]interface{}{"virtio5": "test2:100/vm-100-disk-31.qcow2,discard=on"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Discard: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk iops_rd", + input: map[string]interface{}{"virtio6": "test2:100/vm-100-disk-31.qcow2,iops_rd=10"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk iops_rd_max", + input: map[string]interface{}{"virtio7": "test2:100/vm-100-disk-31.qcow2,iops_rd_max=12"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{ + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12}, + }, + }, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk iops_wr", + input: map[string]interface{}{"virtio8": "test2:100/vm-100-disk-31.qcow2,iops_wr=11"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 11}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk iops_wr_max", + input: map[string]interface{}{"virtio9": "test2:100/vm-100-disk-31.qcow2,iops_wr_max=13"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk iothread", + input: map[string]interface{}{"virtio10": "test2:100/vm-100-disk-31.qcow2,iothread=1"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + IOThread: true, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk mbps_rd", + input: map[string]interface{}{"virtio11": "test2:100/vm-100-disk-31.qcow2,mbps_rd=1.51"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}, + }, + }, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk mbps_rd_max", + input: map[string]interface{}{"virtio12": "test2:100/vm-100-disk-31.qcow2,mbps_rd_max=3.51"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk mbps_wr", + input: map[string]interface{}{"virtio13": "test2:100/vm-100-disk-31.qcow2,mbps_wr=2.51"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk mbps_wr_max", + input: map[string]interface{}{"virtio14": "test2:100/vm-100-disk-31.qcow2,mbps_wr_max=4.51"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_14: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk replicate", + input: map[string]interface{}{"virtio15": "test2:100/vm-100-disk-31.qcow2,replicate=0"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: false, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk ro", + input: map[string]interface{}{"virtio0": "test2:100/vm-100-disk-31.qcow2,ro=1"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + ReadOnly: true, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk serial", + input: map[string]interface{}{"virtio1": "test2:100/vm-100-disk-31.qcow2,serial=disk-9763"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Serial: "disk-9763", + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk size", + input: map[string]interface{}{"virtio2": "test2:100/vm-100-disk-31.qcow2,size=32G"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: &uint31, + Replicate: true, + Size: 32, + Storage: "test2", + }}}}}, + }, + // Disks VirtIO Passthrough + {name: "Disks VirtIO Passthrough", + input: map[string]interface{}{"virtio0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough ALL", + input: map[string]interface{}{"virtio1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=native,backup=0,cache=unsafe,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=1G"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + AsyncIO: QemuDiskAsyncIO_Native, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + }, + }, + Cache: QemuDiskCache_Unsafe, + Discard: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + IOThread: true, + ReadOnly: true, + Replicate: false, + Serial: "disk-9763", + Size: 1, + }}}}}, + }, + {name: "Disks VirtIO Passthrough aio", + input: map[string]interface{}{"virtio2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=native"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + AsyncIO: QemuDiskAsyncIO_Native, + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough backup", + input: map[string]interface{}{"virtio3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,backup=0"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: false, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough cache", + input: map[string]interface{}{"virtio4": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,cache=unsafe"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Cache: QemuDiskCache_Unsafe, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough discard", + input: map[string]interface{}{"virtio5": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,discard=on"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Discard: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough iops_rd", + input: map[string]interface{}{"virtio6": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd=10"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough iops_rd_max", + input: map[string]interface{}{"virtio7": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd_max=12"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough iops_wr", + input: map[string]interface{}{"virtio8": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr=11"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 11}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough iops_wr_max", + input: map[string]interface{}{"virtio9": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr_max=13"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough iothread", + input: map[string]interface{}{"virtio10": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iothread=1"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + IOThread: true, + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough mbps_rd", + input: map[string]interface{}{"virtio11": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd=1.51"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough mbps_rd_max", + input: map[string]interface{}{"virtio12": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd_max=3.51"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough mbps_wr", + input: map[string]interface{}{"virtio13": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr=2.51"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough mbps_wr_max", + input: map[string]interface{}{"virtio14": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr_max=4.51"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_14: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough replicate", + input: map[string]interface{}{"virtio15": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,replicate=0"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: false, + }}}}}, + }, + {name: "Disks VirtIO Passthrough ro", + input: map[string]interface{}{"virtio0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,ro=1"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + ReadOnly: true, + Replicate: true, + }}}}}, + }, + {name: "Disks VirtIO Passthrough serial", + input: map[string]interface{}{"virtio1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,serial=disk-9763"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + Serial: "disk-9763", + }}}}}, + }, + {name: "Disks VirtIO Passthrough size", + input: map[string]interface{}{"virtio2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,size=1G"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + Size: 1, + }}}}}, + }, + // Iso + {name: "Iso", + input: map[string]interface{}{"ide2": "local:iso/debian-11.0.0-amd64-netinst.iso,media=cdrom,size=377M"}, + output: &ConfigQemu{ + Iso: &IsoFile{ + File: "debian-11.0.0-amd64-netinst.iso", + Storage: "local", + Size: "377M", + }, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CdRom: &QemuCdRom{ + Iso: &IsoFile{ + File: "debian-11.0.0-amd64-netinst.iso", + Storage: "local", + Size: "377M", + }, + }}}}, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(*testing.T) { + output, err := ConfigQemu{}.mapToStruct(test.input) + if err != nil { + require.Equal(t, test.err, err, test.name) + } else { + require.Equal(t, test.output, output, test.name) + } + }) + } +} func Test_ConfigQemu_Validate(t *testing.T) { BandwidthValid0 := QemuDiskBandwidth{ Data: QemuDiskBandwidthData{ From c36bc0fe2d339f57b1c50550343f2b2c5e784743 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sat, 18 Mar 2023 17:00:26 +0000 Subject: [PATCH 090/120] refactor: disk migration replace `*Client.MoveQemuDisk` with `MoveQemuDisk` --- proxmox/client.go | 1 + proxmox/config_qemu.go | 2 +- proxmox/config_qemu_disk.go | 132 ++++++++++++++++--- proxmox/config_qemu_disk_ide.go | 2 +- proxmox/config_qemu_disk_sata.go | 2 +- proxmox/config_qemu_disk_scsi.go | 2 +- proxmox/config_qemu_disk_test.go | 199 ++++++++++++++++++++++++++++- proxmox/config_qemu_disk_virtio.go | 2 +- 8 files changed, 321 insertions(+), 21 deletions(-) diff --git a/proxmox/client.go b/proxmox/client.go index dffd7b7b..2b73d67f 100644 --- a/proxmox/client.go +++ b/proxmox/client.go @@ -788,6 +788,7 @@ func (c *Client) MoveLxcDisk(vmr *VmRef, disk string, storage string) (exitStatu return } +// DEPRECATED use MoveQemuDisk() instead. // MoveQemuDisk - Move a disk from one storage to another func (c *Client) MoveQemuDisk(vmr *VmRef, disk string, storage string) (exitStatus interface{}, err error) { if disk == "" { diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 7bc9f87b..611de37b 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -707,7 +707,7 @@ func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef if markedDisks != nil { for _, e := range markedDisks.Move { - _, err = client.MoveQemuDisk(vmr, e.Id, e.Storage) + _, err = e.move(true, vmr, client) if err != nil { return } diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 007193b8..e44aec8e 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -576,6 +576,65 @@ func (format QemuDiskFormat) Validate() error { return QemuDiskFormat("").Error() } +type QemuDiskId string + +const ERROR_QemuDiskId_Invalid string = "invalid Disk ID" + +func (id QemuDiskId) Validate() error { + if len(id) >= 7 { + if id[0:6] == "virtio" { + if id[6:] != "0" && strings.HasPrefix(string(id[6:]), "0") { + return errors.New(ERROR_QemuDiskId_Invalid) + } + number, err := strconv.Atoi(string(id[6:])) + if err != nil { + return errors.New(ERROR_QemuDiskId_Invalid) + } + if number >= 0 && number <= 15 { + return nil + } + } + } + if len(id) >= 5 { + if id[0:4] == "sata" { + if id[4:] != "0" && strings.HasPrefix(string(id[4:]), "0") { + return errors.New(ERROR_QemuDiskId_Invalid) + } + number, err := strconv.Atoi(string(id[4:])) + if err != nil { + return errors.New(ERROR_QemuDiskId_Invalid) + } + if number >= 0 && number <= 5 { + return nil + } + } + if id[0:4] == "scsi" { + if id[4:] != "0" && strings.HasPrefix(string(id[4:]), "0") { + return errors.New(ERROR_QemuDiskId_Invalid) + } + number, err := strconv.Atoi(string(id[4:])) + if err != nil { + return errors.New(ERROR_QemuDiskId_Invalid) + } + if number >= 0 && number <= 30 { + return nil + } + } + } + if len(id) == 4 { + if id[0:3] == "ide" { + number, err := strconv.Atoi(string(id[3])) + if err != nil { + return errors.New(ERROR_QemuDiskId_Invalid) + } + if number >= 0 && number <= 3 { + return nil + } + } + } + return errors.New(ERROR_QemuDiskId_Invalid) +} + type QemuDiskSerial string const ( @@ -597,7 +656,7 @@ func (serial QemuDiskSerial) Validate() error { } type qemuDiskResize struct { - Id string + Id QemuDiskId SizeInGigaBytes uint } @@ -608,8 +667,36 @@ func (disk qemuDiskResize) resize(vmr *VmRef, client *Client) (exitStatus string } type qemuDiskShort struct { + Format *QemuDiskFormat + Id QemuDiskId Storage string - Id string +} + +func (disk qemuDiskShort) mapToApiValues(delete bool) (params map[string]interface{}) { + params = map[string]interface{}{"disk": string(disk.Id), "storage": string(disk.Storage)} + if delete { + params["delete"] = "1" + } + if disk.Format != nil { + params["format"] = string(*disk.Format) + } + return +} + +func (disk qemuDiskShort) move(delete bool, vmr *VmRef, client *Client) (exitStatus interface{}, err error) { + return client.PostWithTask(disk.mapToApiValues(delete), fmt.Sprintf("/nodes/%s/%s/%d/move_disk", vmr.node, vmr.vmType, vmr.vmId)) +} + +func (disk qemuDiskShort) Validate() (err error) { + if disk.Format != nil { + err = disk.Format.Validate() + if err != nil { + return + } + } + err = disk.Id.Validate() + // TODO validate storage when it has custom type + return } type qemuDiskType int @@ -628,35 +715,35 @@ type qemuStorage struct { Passthrough *qemuDisk } -func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID uint, id string, params map[string]interface{}, changes *qemuUpdateChanges) { +func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID uint, id QemuDiskId, params map[string]interface{}, changes *qemuUpdateChanges) { if storage == nil { return } // CDROM if storage.CdRom != nil { // Create or Update - params[id] = storage.CdRom.mapToApiValues() + params[string(id)] = storage.CdRom.mapToApiValues() return } else if currentStorage != nil && currentStorage.CdRom != nil && storage.CloudInit == nil && storage.Disk == nil && storage.Passthrough == nil { // Delete - changes.Delete = AddToList(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, string(id)) return } // CloudInit if storage.CloudInit != nil { // Create or Update - params[id] = storage.CloudInit.mapToApiValues() + params[string(id)] = storage.CloudInit.mapToApiValues() return } else if currentStorage != nil && currentStorage.CloudInit != nil && storage.Disk == nil && storage.Passthrough == nil { // Delete - changes.Delete = AddToList(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, string(id)) return } // Disk if storage.Disk != nil { if currentStorage == nil || currentStorage.Disk == nil { // Create - params[id] = storage.Disk.mapToApiValues(vmID, true) + params[string(id)] = storage.Disk.mapToApiValues(vmID, true) return } else { if storage.Disk.Size >= currentStorage.Disk.Size { @@ -670,38 +757,39 @@ func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID ui if storage.Disk.Id == nil { storage.Disk.Id = currentStorage.Disk.Id } - if storage.Disk.Storage != currentStorage.Disk.Storage { + if storage.Disk.Storage != currentStorage.Disk.Storage || storage.Disk.Format != currentStorage.Disk.Format { changes.Move = append(changes.Move, qemuDiskShort{ + Format: &storage.Disk.Format, Id: id, Storage: storage.Disk.Storage, }) } - params[id] = storage.Disk.mapToApiValues(vmID, false) + params[string(id)] = storage.Disk.mapToApiValues(vmID, false) } else { // Delete and Create // creating a disk on top of an existing disk is the same as detaching the disk and creating a new one. - params[id] = storage.Disk.mapToApiValues(vmID, true) + params[string(id)] = storage.Disk.mapToApiValues(vmID, true) } return } } else if currentStorage != nil && currentStorage.Disk != nil && storage.Passthrough == nil { // Delete - changes.Delete = AddToList(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, string(id)) return } // Passthrough if storage.Passthrough != nil { // Create or Update - params[id] = storage.Passthrough.mapToApiValues(0, false) + params[string(id)] = storage.Passthrough.mapToApiValues(0, false) return } else if currentStorage != nil && currentStorage.Passthrough != nil { // Delete - changes.Delete = AddToList(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, string(id)) return } // Delete if no subtype was specified if currentStorage != nil { - changes.Delete = AddToList(changes.Delete, id) + changes.Delete = AddToList(changes.Delete, string(id)) } } @@ -813,3 +901,17 @@ func diskSubtypeSet(set bool) error { } return nil } + +func MoveQemuDisk(format *QemuDiskFormat, diskId QemuDiskId, storage string, deleteAfterMove bool, vmr *VmRef, client *Client) (err error) { + disk := qemuDiskShort{ + Format: format, + Id: diskId, + Storage: storage, + } + err = disk.Validate() + if err != nil { + return + } + _, err = disk.move(deleteAfterMove, vmr, client) + return +} diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 5b0491db..9fda8389 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -56,7 +56,7 @@ func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, vmID uint, diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, "ide"+strconv.Itoa(int(i)), params, changes) + diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("ide"+strconv.Itoa(int(i))), params, changes) } } diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 2dcd0732..2ad8a0b0 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -58,7 +58,7 @@ func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, vmID uint diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, "sata"+strconv.Itoa(int(i)), params, changes) + diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("sata"+strconv.Itoa(int(i))), params, changes) } } diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 6cb5c12d..7cff0dc2 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -87,7 +87,7 @@ func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, vmID uint diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, "scsi"+strconv.Itoa(int(i)), params, changes) + diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("scsi"+strconv.Itoa(int(i))), params, changes) } } diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 99de3fdb..e6d9188a 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -319,7 +319,7 @@ func Test_QemuDiskCache_Validate(t *testing.T) { } func Test_QemuDiskFormat_Validate(t *testing.T) { - testData := []struct { + tests := []struct { name string input QemuDiskFormat err error @@ -337,6 +337,98 @@ func Test_QemuDiskFormat_Validate(t *testing.T) { {name: "Invalid 01", input: "invalid value", err: QemuDiskFormat("").Error()}, {name: "Invalid 02", input: "!@#$", err: QemuDiskFormat("").Error()}, } + for _, test := range tests { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) + } +} + +func Test_QemuDiskId_Validate(t *testing.T) { + testData := []struct { + name string + input QemuDiskId + err error + }{ + // Invalid + {name: "Invalid 00", input: "ide4", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 01", input: "ide01", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 02", input: "ide10", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 03", input: "sata6", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 04", input: "sata01", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 05", input: "sata10", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 06", input: "scsi31", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 07", input: "scsi01", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 08", input: "scsi100", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 09", input: "virtio16", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 10", input: "virtio01", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 11", input: "virtio100", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 12", input: "bla", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 13", input: "invalid value", err: errors.New(ERROR_QemuDiskId_Invalid)}, + {name: "Invalid 14", input: "!@#$", err: errors.New(ERROR_QemuDiskId_Invalid)}, + // Valid + {name: "Valid 01", input: "ide0"}, + {name: "Valid 02", input: "ide1"}, + {name: "Valid 03", input: "ide2"}, + {name: "Valid 04", input: "ide3"}, + {name: "Valid 05", input: "sata0"}, + {name: "Valid 06", input: "sata1"}, + {name: "Valid 07", input: "sata2"}, + {name: "Valid 08", input: "sata3"}, + {name: "Valid 09", input: "sata4"}, + {name: "Valid 10", input: "sata5"}, + {name: "Valid 11", input: "scsi0"}, + {name: "Valid 12", input: "scsi1"}, + {name: "Valid 13", input: "scsi2"}, + {name: "Valid 14", input: "scsi3"}, + {name: "Valid 15", input: "scsi4"}, + {name: "Valid 16", input: "scsi5"}, + {name: "Valid 17", input: "scsi6"}, + {name: "Valid 18", input: "scsi7"}, + {name: "Valid 19", input: "scsi8"}, + {name: "Valid 20", input: "scsi9"}, + {name: "Valid 21", input: "scsi10"}, + {name: "Valid 22", input: "scsi11"}, + {name: "Valid 23", input: "scsi12"}, + {name: "Valid 24", input: "scsi13"}, + {name: "Valid 25", input: "scsi14"}, + {name: "Valid 26", input: "scsi15"}, + {name: "Valid 27", input: "scsi16"}, + {name: "Valid 28", input: "scsi17"}, + {name: "Valid 29", input: "scsi18"}, + {name: "Valid 30", input: "scsi19"}, + {name: "Valid 31", input: "scsi20"}, + {name: "Valid 32", input: "scsi21"}, + {name: "Valid 33", input: "scsi22"}, + {name: "Valid 34", input: "scsi23"}, + {name: "Valid 35", input: "scsi24"}, + {name: "Valid 36", input: "scsi25"}, + {name: "Valid 37", input: "scsi26"}, + {name: "Valid 38", input: "scsi27"}, + {name: "Valid 39", input: "scsi28"}, + {name: "Valid 40", input: "scsi29"}, + {name: "Valid 41", input: "scsi30"}, + {name: "Valid 42", input: "virtio0"}, + {name: "Valid 43", input: "virtio1"}, + {name: "Valid 44", input: "virtio2"}, + {name: "Valid 45", input: "virtio3"}, + {name: "Valid 46", input: "virtio4"}, + {name: "Valid 47", input: "virtio5"}, + {name: "Valid 48", input: "virtio6"}, + {name: "Valid 49", input: "virtio7"}, + {name: "Valid 50", input: "virtio8"}, + {name: "Valid 51", input: "virtio9"}, + {name: "Valid 52", input: "virtio10"}, + {name: "Valid 53", input: "virtio11"}, + {name: "Valid 54", input: "virtio12"}, + {name: "Valid 55", input: "virtio13"}, + {name: "Valid 56", input: "virtio14"}, + {name: "Valid 57", input: "virtio15"}, + } for _, test := range testData { t.Run(test.name, func(*testing.T) { if test.err != nil { @@ -369,3 +461,108 @@ func Test_QemuDiskSerial_Validate(t *testing.T) { }) } } + +func Test_qemuDiskShort_mapToApiValues(t *testing.T) { + format_Raw := QemuDiskFormat_Raw + format_Qcow2 := QemuDiskFormat_Qcow2 + tests := []struct { + name string + delete bool + input qemuDiskShort + output map[string]interface{} + }{ + {name: "ALL", + delete: true, + input: qemuDiskShort{ + Format: &format_Raw, + Id: "ide0", + Storage: "test0", + }, + output: map[string]interface{}{ + "disk": "ide0", + "storage": "test0", + "delete": "1", + "format": "raw", + }, + }, + {name: "Format nil", + delete: true, + input: qemuDiskShort{ + Id: "sata4", + Storage: "aaa0", + }, + output: map[string]interface{}{ + "disk": "sata4", + "storage": "aaa0", + "delete": "1", + }, + }, + {name: "Delete false", + input: qemuDiskShort{ + Format: &format_Qcow2, + Id: "scsi10", + Storage: "test0", + }, + output: map[string]interface{}{ + "format": "qcow2", + "disk": "scsi10", + "storage": "test0", + }, + }, + {name: "MINIMAL", + input: qemuDiskShort{ + Id: "virtio13", + Storage: "Test0", + }, + output: map[string]interface{}{ + "disk": "virtio13", + "storage": "Test0", + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(*testing.T) { + require.Equal(t, test.output, test.input.mapToApiValues(test.delete), test.name) + }) + } +} + +func Test_qemuDiskShort_Validate(t *testing.T) { + format_Raw := QemuDiskFormat_Raw + format_Invalid := QemuDiskFormat("invalid") + format_Empty := QemuDiskFormat("") + tests := []struct { + name string + input qemuDiskShort + err error + }{ + // TODO Add cases when Storage has a custom type + // Invalid + {name: "Invalid 00", input: qemuDiskShort{Format: &format_Invalid}, + err: QemuDiskFormat("").Error(), + }, + {name: "Invalid 01", input: qemuDiskShort{Format: &format_Empty}, + err: QemuDiskFormat("").Error(), + }, + {name: "Invalid 02", input: qemuDiskShort{Id: "invalid"}, + err: errors.New(ERROR_QemuDiskId_Invalid), + }, + // Valid + {name: "Valid 00", input: qemuDiskShort{ + Format: &format_Raw, + Id: "ide0", + }}, + {name: "Valid 01", input: qemuDiskShort{ + Id: "ide0", + }}, + } + for _, test := range tests { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) + } +} diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index d5f068e2..df012dd4 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -70,7 +70,7 @@ func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, vmID diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, "virtio"+strconv.Itoa(int(i)), params, changes) + diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("virtio"+strconv.Itoa(int(i))), params, changes) } } From fda1d507a74cb0a9b72e72b161e620a37b596d94 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sat, 18 Mar 2023 17:03:10 +0000 Subject: [PATCH 091/120] fix: format not set when creating and updating disk --- proxmox/config_qemu_disk.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index e44aec8e..f249403e 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -236,7 +236,9 @@ func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { if disk.Discard { settings = settings + ",discard=on" } - // format + if disk.Format != "" { + settings = settings + ",format=" + string(disk.Format) + } // media if disk.Bandwidth.Iops.ReadLimit.Concurrent != 0 { From 19a17f63b17ca4f104d096682ac42489f6f254d2 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 19 Mar 2023 21:03:56 +0000 Subject: [PATCH 092/120] refactor: format only needs to be set during disk creation --- proxmox/config_qemu_disk.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index f249403e..2e7902f7 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -236,7 +236,7 @@ func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { if disk.Discard { settings = settings + ",discard=on" } - if disk.Format != "" { + if disk.Format != "" && create { settings = settings + ",format=" + string(disk.Format) } // media From 670277e91e152ed28f6f30bbc50318fce69435b4 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 19 Mar 2023 21:08:12 +0000 Subject: [PATCH 093/120] refactor: seperate disk marking logic for mapping logic --- proxmox/config_qemu.go | 37 ++++--- proxmox/config_qemu_disk.go | 109 ++++++++++++--------- proxmox/config_qemu_disk_ide.go | 33 ++++++- proxmox/config_qemu_disk_sata.go | 33 ++++++- proxmox/config_qemu_disk_scsi.go | 33 ++++++- proxmox/config_qemu_disk_test.go | 152 +++++++++++++++++++++++++++++ proxmox/config_qemu_disk_virtio.go | 33 ++++++- 7 files changed, 366 insertions(+), 64 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 611de37b..c0ed60bb 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -97,7 +97,7 @@ func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { if err != nil { return } - params, _, err := config.mapToApiValues(ConfigQemu{}) + params, err := config.mapToApiValues(ConfigQemu{}) if err != nil { return } @@ -182,7 +182,7 @@ func (config *ConfigQemu) defaults() { } -func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (params map[string]interface{}, markedDisks *qemuUpdateChanges, err error) { +func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (params map[string]interface{}, err error) { var itemsToDelete string @@ -299,15 +299,14 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (params map[st // Disks if currentConfig.Disks != nil { if config.Disks != nil { - markedDisks = config.Disks.markDiskChanges(*currentConfig.Disks, uint(config.VmID), params) - if markedDisks.Delete != "" { - itemsToDelete = AddToList(itemsToDelete, markedDisks.Delete) - markedDisks.Delete = "" + delete := config.Disks.mapToApiValues(*currentConfig.Disks, uint(config.VmID), params) + if delete != "" { + itemsToDelete = AddToList(itemsToDelete, delete) } } } else { if config.Disks != nil { - config.Disks.mapToApiValues(uint(config.VmID), params) + config.Disks.mapToApiValues(QemuStorages{}, uint(config.VmID), params) } } @@ -700,12 +699,9 @@ func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef if err != nil { return } - params, markedDisks, err := newConfig.mapToApiValues(*currentConfig) - if err != nil { - return - } - if markedDisks != nil { + if currentConfig != nil { + markedDisks := newConfig.Disks.markDiskChanges(*currentConfig.Disks) for _, e := range markedDisks.Move { _, err = e.move(true, vmr, client) if err != nil { @@ -718,6 +714,13 @@ func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef return } } + // Moving disks changes the disk id. we need to get the config again if any disk was moved + if len(markedDisks.Move) != 0 { + currentConfig, err = NewConfigQemuFromApi(vmr, client) + if err != nil { + return + } + } } if newConfig.Node != currentConfig.Node { @@ -729,6 +732,16 @@ func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef vmr.SetNode(newConfig.Node) } + var params map[string]interface{} + if currentConfig != nil { + params, err = newConfig.mapToApiValues(*currentConfig) + } else { + params, err = newConfig.mapToApiValues(ConfigQemu{}) + } + if err != nil { + return + } + _, err = client.PutWithTask(params, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/config") if err != nil { return diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 2e7902f7..118d316e 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -580,7 +580,9 @@ func (format QemuDiskFormat) Validate() error { type QemuDiskId string -const ERROR_QemuDiskId_Invalid string = "invalid Disk ID" +const ( + ERROR_QemuDiskId_Invalid string = "invalid Disk ID" +) func (id QemuDiskId) Validate() error { if len(id) >= 7 { @@ -637,6 +639,42 @@ func (id QemuDiskId) Validate() error { return errors.New(ERROR_QemuDiskId_Invalid) } +type qemuDiskMark struct { + Format QemuDiskFormat + Id QemuDiskId + Size uint + Storage string + Type qemuDiskType +} + +// Generate lists of disks that need to be moved and or resized +func (disk *qemuDiskMark) markChanges(currentDisk *qemuDiskMark, id QemuDiskId, changes *qemuUpdateChanges) { + if disk == nil || currentDisk == nil { + return + } + // Disk + if disk.Size >= currentDisk.Size { + // Update + if disk.Size > currentDisk.Size { + changes.Resize = append(changes.Resize, qemuDiskResize{ + Id: id, + SizeInGigaBytes: disk.Size, + }) + } + if disk.Storage != currentDisk.Storage || disk.Format != currentDisk.Format { + var format *QemuDiskFormat + if disk.Format != currentDisk.Format { + format = &disk.Format + } + changes.Move = append(changes.Move, qemuDiskShort{ + Format: format, + Id: id, + Storage: disk.Storage, + }) + } + } +} + type QemuDiskSerial string const ( @@ -668,6 +706,7 @@ func (disk qemuDiskResize) resize(vmr *VmRef, client *Client) (exitStatus string return client.PutWithTask(map[string]interface{}{"disk": disk.Id, "size": strconv.Itoa(int(disk.SizeInGigaBytes)) + "G"}, fmt.Sprintf("/nodes/%s/%s/%d/resize", vmr.node, vmr.vmType, vmr.vmId)) } +// TODO rename to qemuDiskMove type qemuDiskShort struct { Format *QemuDiskFormat Id QemuDiskId @@ -717,82 +756,64 @@ type qemuStorage struct { Passthrough *qemuDisk } -func (storage *qemuStorage) markDiskChanges(currentStorage *qemuStorage, vmID uint, id QemuDiskId, params map[string]interface{}, changes *qemuUpdateChanges) { +func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID uint, id QemuDiskId, params map[string]interface{}, delete string) string { if storage == nil { - return + return delete } // CDROM if storage.CdRom != nil { // Create or Update params[string(id)] = storage.CdRom.mapToApiValues() - return + return delete } else if currentStorage != nil && currentStorage.CdRom != nil && storage.CloudInit == nil && storage.Disk == nil && storage.Passthrough == nil { // Delete - changes.Delete = AddToList(changes.Delete, string(id)) - return + return AddToList(delete, string(id)) } // CloudInit if storage.CloudInit != nil { // Create or Update params[string(id)] = storage.CloudInit.mapToApiValues() - return + return delete } else if currentStorage != nil && currentStorage.CloudInit != nil && storage.Disk == nil && storage.Passthrough == nil { // Delete - changes.Delete = AddToList(changes.Delete, string(id)) - return + return AddToList(delete, string(id)) } // Disk if storage.Disk != nil { if currentStorage == nil || currentStorage.Disk == nil { // Create params[string(id)] = storage.Disk.mapToApiValues(vmID, true) - return + return delete } else { if storage.Disk.Size >= currentStorage.Disk.Size { // Update - if storage.Disk.Size > currentStorage.Disk.Size { - changes.Resize = append(changes.Resize, qemuDiskResize{ - Id: id, - SizeInGigaBytes: storage.Disk.Size, - }) - } - if storage.Disk.Id == nil { - storage.Disk.Id = currentStorage.Disk.Id - } - if storage.Disk.Storage != currentStorage.Disk.Storage || storage.Disk.Format != currentStorage.Disk.Format { - changes.Move = append(changes.Move, qemuDiskShort{ - Format: &storage.Disk.Format, - Id: id, - Storage: storage.Disk.Storage, - }) - } + storage.Disk.Id = currentStorage.Disk.Id params[string(id)] = storage.Disk.mapToApiValues(vmID, false) } else { // Delete and Create // creating a disk on top of an existing disk is the same as detaching the disk and creating a new one. params[string(id)] = storage.Disk.mapToApiValues(vmID, true) } - return + return delete } } else if currentStorage != nil && currentStorage.Disk != nil && storage.Passthrough == nil { // Delete - changes.Delete = AddToList(changes.Delete, string(id)) - return + return AddToList(delete, string(id)) } // Passthrough if storage.Passthrough != nil { // Create or Update params[string(id)] = storage.Passthrough.mapToApiValues(0, false) - return + return delete } else if currentStorage != nil && currentStorage.Passthrough != nil { // Delete - changes.Delete = AddToList(changes.Delete, string(id)) - return + return AddToList(delete, string(id)) } // Delete if no subtype was specified if currentStorage != nil { - changes.Delete = AddToList(changes.Delete, string(id)) + return AddToList(delete, string(id)) } + return delete } type QemuStorages struct { @@ -802,19 +823,20 @@ type QemuStorages struct { VirtIO *QemuVirtIODisks `json:"virtio,omitempty"` } -func (storages QemuStorages) mapToApiValues(vmID uint, params map[string]interface{}) { +func (storages QemuStorages) mapToApiValues(currentStorages QemuStorages, vmID uint, params map[string]interface{}) (delete string) { if storages.Ide != nil { - storages.Ide.mapToApiValues(nil, vmID, params, nil) + delete = storages.Ide.mapToApiValues(currentStorages.Ide, vmID, params, delete) } if storages.Sata != nil { - storages.Sata.mapToApiValues(nil, vmID, params, nil) + delete = storages.Sata.mapToApiValues(currentStorages.Sata, vmID, params, delete) } if storages.Scsi != nil { - storages.Scsi.mapToApiValues(nil, vmID, params, nil) + delete = storages.Scsi.mapToApiValues(currentStorages.Scsi, vmID, params, delete) } if storages.VirtIO != nil { - storages.VirtIO.mapToApiValues(nil, vmID, params, nil) + delete = storages.VirtIO.mapToApiValues(currentStorages.VirtIO, vmID, params, delete) } + return delete } func (QemuStorages) mapToStruct(params map[string]interface{}) *QemuStorages { @@ -830,19 +852,19 @@ func (QemuStorages) mapToStruct(params map[string]interface{}) *QemuStorages { return nil } -func (storages QemuStorages) markDiskChanges(currentStorages QemuStorages, vmID uint, params map[string]interface{}) *qemuUpdateChanges { +func (storages QemuStorages) markDiskChanges(currentStorages QemuStorages) *qemuUpdateChanges { changes := &qemuUpdateChanges{} if storages.Ide != nil { - storages.Ide.mapToApiValues(currentStorages.Ide, vmID, params, changes) + storages.Ide.markDiskChanges(currentStorages.Ide, changes) } if storages.Sata != nil { - storages.Sata.mapToApiValues(currentStorages.Sata, vmID, params, changes) + storages.Sata.markDiskChanges(currentStorages.Sata, changes) } if storages.Scsi != nil { - storages.Scsi.mapToApiValues(currentStorages.Scsi, vmID, params, changes) + storages.Scsi.markDiskChanges(currentStorages.Scsi, changes) } if storages.VirtIO != nil { - storages.VirtIO.mapToApiValues(currentStorages.VirtIO, vmID, params, changes) + storages.VirtIO.markDiskChanges(currentStorages.VirtIO, changes) } return changes } @@ -892,7 +914,6 @@ func (storages QemuStorages) Validate() (err error) { } type qemuUpdateChanges struct { - Delete string Move []qemuDiskShort Resize []qemuDiskResize } diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 9fda8389..d6d641b9 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -48,7 +48,7 @@ type QemuIdeDisks struct { } // TODO write test -func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, vmID uint, params map[string]interface{}, changes *qemuUpdateChanges) { +func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, vmID uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuIdeDisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks @@ -56,8 +56,9 @@ func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, vmID uint, diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("ide"+strconv.Itoa(int(i))), params, changes) + delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("ide"+strconv.Itoa(int(i))), params, delete) } + return delete } func (disks QemuIdeDisks) mapToIntMap() map[uint8]*QemuIdeStorage { @@ -95,6 +96,18 @@ func (QemuIdeDisks) mapToStruct(params map[string]interface{}) *QemuIdeDisks { return nil } +func (disks QemuIdeDisks) markDiskChanges(currentDisks *QemuIdeDisks, changes *qemuUpdateChanges) { + tmpCurrentDisks := QemuIdeDisks{} + if currentDisks != nil { + tmpCurrentDisks = *currentDisks + } + diskMap := disks.mapToIntMap() + currentDiskMap := tmpCurrentDisks.mapToIntMap() + for i := range diskMap { + diskMap[i].convertDataStructureMark().markChanges(currentDiskMap[i].convertDataStructureMark(), QemuDiskId("ide"+strconv.Itoa(int(i))), changes) + } +} + func (disks QemuIdeDisks) Validate() (err error) { _, err = disks.validate() return @@ -176,6 +189,22 @@ func (storage *QemuIdeStorage) convertDataStructure() *qemuStorage { return &generalizedStorage } +// converts to qemuDiskMark +func (storage *QemuIdeStorage) convertDataStructureMark() *qemuDiskMark { + if storage == nil { + return nil + } + if storage.Disk != nil { + return &qemuDiskMark{ + Format: storage.Disk.Format, + Size: storage.Disk.Size, + Storage: storage.Disk.Storage, + Type: ide, + } + } + return nil +} + // TODO write test func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { settings := splitStringOfSettings(param) diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 2ad8a0b0..b45570c9 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -50,7 +50,7 @@ type QemuSataDisks struct { } // TODO write test -func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, vmID uint, params map[string]interface{}, changes *qemuUpdateChanges) { +func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, vmID uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuSataDisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks @@ -58,8 +58,9 @@ func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, vmID uint diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("sata"+strconv.Itoa(int(i))), params, changes) + delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("sata"+strconv.Itoa(int(i))), params, delete) } + return delete } func (disks QemuSataDisks) mapToIntMap() map[uint8]*QemuSataStorage { @@ -107,6 +108,18 @@ func (QemuSataDisks) mapToStruct(params map[string]interface{}) *QemuSataDisks { return nil } +func (disks QemuSataDisks) markDiskChanges(currentDisks *QemuSataDisks, changes *qemuUpdateChanges) { + tmpCurrentDisks := QemuSataDisks{} + if currentDisks != nil { + tmpCurrentDisks = *currentDisks + } + diskMap := disks.mapToIntMap() + currentDiskMap := tmpCurrentDisks.mapToIntMap() + for i := range diskMap { + diskMap[i].convertDataStructureMark().markChanges(currentDiskMap[i].convertDataStructureMark(), QemuDiskId("sata"+strconv.Itoa(int(i))), changes) + } +} + func (disks QemuSataDisks) Validate() (err error) { _, err = disks.validate() return @@ -188,6 +201,22 @@ func (storage *QemuSataStorage) convertDataStructure() *qemuStorage { return &generalizedStorage } +// converts to qemuDiskMark +func (storage *QemuSataStorage) convertDataStructureMark() *qemuDiskMark { + if storage == nil { + return nil + } + if storage.Disk != nil { + return &qemuDiskMark{ + Format: storage.Disk.Format, + Size: storage.Disk.Size, + Storage: storage.Disk.Storage, + Type: ide, + } + } + return nil +} + // TODO write test func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { settings := splitStringOfSettings(param) diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 7cff0dc2..c9407e2f 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -79,7 +79,7 @@ type QemuScsiDisks struct { } // TODO write test -func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, vmID uint, params map[string]interface{}, changes *qemuUpdateChanges) { +func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, vmID uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuScsiDisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks @@ -87,8 +87,9 @@ func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, vmID uint diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("scsi"+strconv.Itoa(int(i))), params, changes) + delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("scsi"+strconv.Itoa(int(i))), params, delete) } + return delete } func (disks QemuScsiDisks) mapToIntMap() map[uint8]*QemuScsiStorage { @@ -261,6 +262,18 @@ func (QemuScsiDisks) mapToStruct(params map[string]interface{}) *QemuScsiDisks { return nil } +func (disks QemuScsiDisks) markDiskChanges(currentDisks *QemuScsiDisks, changes *qemuUpdateChanges) { + tmpCurrentDisks := QemuScsiDisks{} + if currentDisks != nil { + tmpCurrentDisks = *currentDisks + } + diskMap := disks.mapToIntMap() + currentDiskMap := tmpCurrentDisks.mapToIntMap() + for i := range diskMap { + diskMap[i].convertDataStructureMark().markChanges(currentDiskMap[i].convertDataStructureMark(), QemuDiskId("scsi"+strconv.Itoa(int(i))), changes) + } +} + func (disks QemuScsiDisks) Validate() (err error) { _, err = disks.validate() return @@ -346,6 +359,22 @@ func (storage *QemuScsiStorage) convertDataStructure() *qemuStorage { return &generalizedStorage } +// converts to qemuDiskMark +func (storage *QemuScsiStorage) convertDataStructureMark() *qemuDiskMark { + if storage == nil { + return nil + } + if storage.Disk != nil { + return &qemuDiskMark{ + Format: storage.Disk.Format, + Size: storage.Disk.Size, + Storage: storage.Disk.Storage, + Type: ide, + } + } + return nil +} + // TODO write test func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { settings := splitStringOfSettings(param) diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index e6d9188a..c691e72a 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -566,3 +566,155 @@ func Test_qemuDiskShort_Validate(t *testing.T) { }) } } + +func Test_QemuStorages_markDiskChanges(t *testing.T) { + format_Raw := QemuDiskFormat_Raw + tests := []struct { + name string + storages QemuStorages + currentStorages QemuStorages + output *qemuUpdateChanges + }{ + {name: "Disk CHANGE", + storages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: format_Raw, Size: 100, Storage: "NewStorage"}}}, + Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{Format: format_Raw, Size: 50, Storage: "NewStorage"}}}, + Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: format_Raw, Size: 33, Storage: "NewStorage"}}}, + VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: format_Raw, Size: 99, Storage: "NewStorage"}}}, + }, + currentStorages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + }, + output: &qemuUpdateChanges{ + Move: []qemuDiskShort{ + {Format: &format_Raw, Id: "ide0", Storage: "NewStorage"}, + {Format: &format_Raw, Id: "sata1", Storage: "NewStorage"}, + {Format: &format_Raw, Id: "scsi2", Storage: "NewStorage"}, + {Format: &format_Raw, Id: "virtio3", Storage: "NewStorage"}, + }, + Resize: []qemuDiskResize{ + {Id: "ide0", SizeInGigaBytes: 100}, + {Id: "sata1", SizeInGigaBytes: 50}, + {Id: "scsi2", SizeInGigaBytes: 33}, + {Id: "virtio3", SizeInGigaBytes: 99}, + }, + }, + }, + {name: "Disk NO CHANGE", + storages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: format_Raw, Size: 100, Storage: "NewStorage"}}}, + Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{Format: format_Raw, Size: 50, Storage: "NewStorage"}}}, + Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: format_Raw, Size: 33, Storage: "NewStorage"}}}, + VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: format_Raw, Size: 99, Storage: "NewStorage"}}}, + }, + currentStorages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + }, + output: &qemuUpdateChanges{}, + }, + {name: "Disk_X.Disk SAME", + storages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + }, + currentStorages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + }, + output: &qemuUpdateChanges{}, + }, + {name: "Disk_X.Disk.Format CHANGE", + storages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + }, + currentStorages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, + }, + output: &qemuUpdateChanges{Move: []qemuDiskShort{ + {Format: &format_Raw, Id: "ide2", Storage: "Test"}, + {Format: &format_Raw, Id: "sata3", Storage: "Test"}, + {Format: &format_Raw, Id: "scsi4", Storage: "Test"}, + {Format: &format_Raw, Id: "virtio5", Storage: "Test"}, + }}, + }, + {name: "Disk.Size BIGGER", + storages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Raw, Size: 90, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Raw, Size: 80, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Raw, Size: 50, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Raw, Size: 33, Storage: "Test"}}}, + }, + currentStorages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + }, + output: &qemuUpdateChanges{Resize: []qemuDiskResize{ + {Id: "ide3", SizeInGigaBytes: 90}, + {Id: "sata4", SizeInGigaBytes: 80}, + {Id: "scsi5", SizeInGigaBytes: 50}, + {Id: "virtio6", SizeInGigaBytes: 33}, + }}, + }, + {name: "Disk.Size SMALLER", + storages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Raw, Size: 1, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Raw, Size: 10, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Raw, Size: 20, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Raw, Size: 31, Storage: "Test"}}}, + }, + currentStorages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + }, + output: &qemuUpdateChanges{}, + }, + {name: "Disk.Storage CHANGE", + storages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "NewStorage"}}}, + Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "NewStorage"}}}, + Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "NewStorage"}}}, + VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "NewStorage"}}}, + }, + currentStorages: QemuStorages{ + Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, + }, + output: &qemuUpdateChanges{Move: []qemuDiskShort{ + {Id: "ide1", Storage: "NewStorage"}, + {Id: "sata0", Storage: "NewStorage"}, + {Id: "scsi7", Storage: "NewStorage"}, + {Id: "virtio8", Storage: "NewStorage"}, + }}, + }, + {name: "nil", + output: &qemuUpdateChanges{}, + }, + } + for _, test := range tests { + t.Run(test.name, func(*testing.T) { + require.Equal(t, test.output, test.storages.markDiskChanges(test.currentStorages), test.name) + }) + } +} diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index df012dd4..07d8c3a1 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -62,7 +62,7 @@ type QemuVirtIODisks struct { } // TODO write test -func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, vmID uint, params map[string]interface{}, changes *qemuUpdateChanges) { +func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, vmID uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuVirtIODisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks @@ -70,8 +70,9 @@ func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, vmID diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - diskMap[i].convertDataStructure().markDiskChanges(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("virtio"+strconv.Itoa(int(i))), params, changes) + delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("virtio"+strconv.Itoa(int(i))), params, delete) } + return delete } func (disks QemuVirtIODisks) mapToIntMap() map[uint8]*QemuVirtIOStorage { @@ -169,6 +170,18 @@ func (QemuVirtIODisks) mapToStruct(params map[string]interface{}) *QemuVirtIODis return nil } +func (disks QemuVirtIODisks) markDiskChanges(currentDisks *QemuVirtIODisks, changes *qemuUpdateChanges) { + tmpCurrentDisks := QemuVirtIODisks{} + if currentDisks != nil { + tmpCurrentDisks = *currentDisks + } + diskMap := disks.mapToIntMap() + currentDiskMap := tmpCurrentDisks.mapToIntMap() + for i := range diskMap { + diskMap[i].convertDataStructureMark().markChanges(currentDiskMap[i].convertDataStructureMark(), QemuDiskId("virtio"+strconv.Itoa(int(i))), changes) + } +} + func (disks QemuVirtIODisks) Validate() (err error) { _, err = disks.validate() return @@ -252,6 +265,22 @@ func (storage *QemuVirtIOStorage) convertDataStructure() *qemuStorage { return &generalizedStorage } +// converts to qemuDiskMark +func (storage *QemuVirtIOStorage) convertDataStructureMark() *qemuDiskMark { + if storage == nil { + return nil + } + if storage.Disk != nil { + return &qemuDiskMark{ + Format: storage.Disk.Format, + Size: storage.Disk.Size, + Storage: storage.Disk.Storage, + Type: ide, + } + } + return nil +} + // TODO write test func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { settings := splitStringOfSettings(param) From 42f007ed621bdc00a4ca763603881e6af50753a3 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 20 Mar 2023 13:58:10 +0000 Subject: [PATCH 094/120] refactor: rename struct --- proxmox/config_qemu_disk.go | 15 +++++++-------- proxmox/config_qemu_disk_test.go | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 118d316e..914f1ffe 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -666,7 +666,7 @@ func (disk *qemuDiskMark) markChanges(currentDisk *qemuDiskMark, id QemuDiskId, if disk.Format != currentDisk.Format { format = &disk.Format } - changes.Move = append(changes.Move, qemuDiskShort{ + changes.Move = append(changes.Move, qemuDiskMove{ Format: format, Id: id, Storage: disk.Storage, @@ -706,14 +706,13 @@ func (disk qemuDiskResize) resize(vmr *VmRef, client *Client) (exitStatus string return client.PutWithTask(map[string]interface{}{"disk": disk.Id, "size": strconv.Itoa(int(disk.SizeInGigaBytes)) + "G"}, fmt.Sprintf("/nodes/%s/%s/%d/resize", vmr.node, vmr.vmType, vmr.vmId)) } -// TODO rename to qemuDiskMove -type qemuDiskShort struct { +type qemuDiskMove struct { Format *QemuDiskFormat Id QemuDiskId Storage string } -func (disk qemuDiskShort) mapToApiValues(delete bool) (params map[string]interface{}) { +func (disk qemuDiskMove) mapToApiValues(delete bool) (params map[string]interface{}) { params = map[string]interface{}{"disk": string(disk.Id), "storage": string(disk.Storage)} if delete { params["delete"] = "1" @@ -724,11 +723,11 @@ func (disk qemuDiskShort) mapToApiValues(delete bool) (params map[string]interfa return } -func (disk qemuDiskShort) move(delete bool, vmr *VmRef, client *Client) (exitStatus interface{}, err error) { +func (disk qemuDiskMove) move(delete bool, vmr *VmRef, client *Client) (exitStatus interface{}, err error) { return client.PostWithTask(disk.mapToApiValues(delete), fmt.Sprintf("/nodes/%s/%s/%d/move_disk", vmr.node, vmr.vmType, vmr.vmId)) } -func (disk qemuDiskShort) Validate() (err error) { +func (disk qemuDiskMove) Validate() (err error) { if disk.Format != nil { err = disk.Format.Validate() if err != nil { @@ -914,7 +913,7 @@ func (storages QemuStorages) Validate() (err error) { } type qemuUpdateChanges struct { - Move []qemuDiskShort + Move []qemuDiskMove Resize []qemuDiskResize } @@ -926,7 +925,7 @@ func diskSubtypeSet(set bool) error { } func MoveQemuDisk(format *QemuDiskFormat, diskId QemuDiskId, storage string, deleteAfterMove bool, vmr *VmRef, client *Client) (err error) { - disk := qemuDiskShort{ + disk := qemuDiskMove{ Format: format, Id: diskId, Storage: storage, diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index c691e72a..1370e50f 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -468,12 +468,12 @@ func Test_qemuDiskShort_mapToApiValues(t *testing.T) { tests := []struct { name string delete bool - input qemuDiskShort + input qemuDiskMove output map[string]interface{} }{ {name: "ALL", delete: true, - input: qemuDiskShort{ + input: qemuDiskMove{ Format: &format_Raw, Id: "ide0", Storage: "test0", @@ -487,7 +487,7 @@ func Test_qemuDiskShort_mapToApiValues(t *testing.T) { }, {name: "Format nil", delete: true, - input: qemuDiskShort{ + input: qemuDiskMove{ Id: "sata4", Storage: "aaa0", }, @@ -498,7 +498,7 @@ func Test_qemuDiskShort_mapToApiValues(t *testing.T) { }, }, {name: "Delete false", - input: qemuDiskShort{ + input: qemuDiskMove{ Format: &format_Qcow2, Id: "scsi10", Storage: "test0", @@ -510,7 +510,7 @@ func Test_qemuDiskShort_mapToApiValues(t *testing.T) { }, }, {name: "MINIMAL", - input: qemuDiskShort{ + input: qemuDiskMove{ Id: "virtio13", Storage: "Test0", }, @@ -533,26 +533,26 @@ func Test_qemuDiskShort_Validate(t *testing.T) { format_Empty := QemuDiskFormat("") tests := []struct { name string - input qemuDiskShort + input qemuDiskMove err error }{ // TODO Add cases when Storage has a custom type // Invalid - {name: "Invalid 00", input: qemuDiskShort{Format: &format_Invalid}, + {name: "Invalid 00", input: qemuDiskMove{Format: &format_Invalid}, err: QemuDiskFormat("").Error(), }, - {name: "Invalid 01", input: qemuDiskShort{Format: &format_Empty}, + {name: "Invalid 01", input: qemuDiskMove{Format: &format_Empty}, err: QemuDiskFormat("").Error(), }, - {name: "Invalid 02", input: qemuDiskShort{Id: "invalid"}, + {name: "Invalid 02", input: qemuDiskMove{Id: "invalid"}, err: errors.New(ERROR_QemuDiskId_Invalid), }, // Valid - {name: "Valid 00", input: qemuDiskShort{ + {name: "Valid 00", input: qemuDiskMove{ Format: &format_Raw, Id: "ide0", }}, - {name: "Valid 01", input: qemuDiskShort{ + {name: "Valid 01", input: qemuDiskMove{ Id: "ide0", }}, } @@ -589,7 +589,7 @@ func Test_QemuStorages_markDiskChanges(t *testing.T) { VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, }, output: &qemuUpdateChanges{ - Move: []qemuDiskShort{ + Move: []qemuDiskMove{ {Format: &format_Raw, Id: "ide0", Storage: "NewStorage"}, {Format: &format_Raw, Id: "sata1", Storage: "NewStorage"}, {Format: &format_Raw, Id: "scsi2", Storage: "NewStorage"}, @@ -646,7 +646,7 @@ func Test_QemuStorages_markDiskChanges(t *testing.T) { Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Vmdk, Size: 32, Storage: "Test"}}}, }, - output: &qemuUpdateChanges{Move: []qemuDiskShort{ + output: &qemuUpdateChanges{Move: []qemuDiskMove{ {Format: &format_Raw, Id: "ide2", Storage: "Test"}, {Format: &format_Raw, Id: "sata3", Storage: "Test"}, {Format: &format_Raw, Id: "scsi4", Storage: "Test"}, @@ -701,7 +701,7 @@ func Test_QemuStorages_markDiskChanges(t *testing.T) { Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Raw, Size: 32, Storage: "Test"}}}, }, - output: &qemuUpdateChanges{Move: []qemuDiskShort{ + output: &qemuUpdateChanges{Move: []qemuDiskMove{ {Id: "ide1", Storage: "NewStorage"}, {Id: "sata0", Storage: "NewStorage"}, {Id: "scsi7", Storage: "NewStorage"}, From b168399e0eb92104a263c12a39e2e6d604ae454b Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 20 Mar 2023 14:07:41 +0000 Subject: [PATCH 095/120] refactor: make `Id` a value that is only returned --- proxmox/config_qemu_disk.go | 7 +- proxmox/config_qemu_disk_ide.go | 2 +- proxmox/config_qemu_disk_sata.go | 2 +- proxmox/config_qemu_disk_scsi.go | 2 +- proxmox/config_qemu_disk_virtio.go | 2 +- proxmox/config_qemu_test.go | 150 ++++++++++++++--------------- 6 files changed, 82 insertions(+), 83 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 914f1ffe..973fcc03 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -188,7 +188,7 @@ type qemuDisk struct { // TODO custom type File string // Only set for Passthrough. Format QemuDiskFormat // Only set for Disk - Id *uint // Only set for Disk + Id uint // Only set for Disk IOThread bool // Only set for scsi,virtio Number uint ReadOnly bool // Only set for scsi,virtio @@ -215,7 +215,7 @@ func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { } else { // test:100/vm-100-disk-0.raw tmpId := strconv.Itoa(int(vmID)) - settings = disk.Storage + ":" + tmpId + "/vm-" + tmpId + "-disk-" + strconv.Itoa(int(*disk.Id)) + "." + string(disk.Format) + settings = disk.Storage + ":" + tmpId + "/vm-" + tmpId + "-disk-" + strconv.Itoa(int(disk.Id)) + "." + string(disk.Format) } } @@ -308,8 +308,7 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { tmp := strings.Split(idAndFormat[0], "-") if len(tmp) > 1 { tmpId, _ := strconv.Atoi(tmp[len(tmp)-1]) - idPointer := uint(tmpId) - disk.Id = &idPointer + disk.Id = uint(tmpId) } } } diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index d6d641b9..9940d8d5 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -10,7 +10,7 @@ type QemuIdeDisk struct { Discard bool `json:"discard"` EmulateSSD bool `json:"emulatessd"` Format QemuDiskFormat `json:"format"` - Id *uint `json:"id,omitempty"` + Id uint `json:"id"` //Id is only returned and setting it has no effect Replicate bool `json:"replicate"` Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size"` diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index b45570c9..fd69d071 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -10,7 +10,7 @@ type QemuSataDisk struct { Discard bool `json:"discard"` EmulateSSD bool `json:"emulatessd"` Format QemuDiskFormat `json:"format"` - Id *uint `json:"id,omitempty"` + Id uint `json:"id"` //Id is only returned and setting it has no effect Replicate bool `json:"replicate"` Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size"` diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index c9407e2f..80f31712 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -10,7 +10,7 @@ type QemuScsiDisk struct { Discard bool `json:"discard"` EmulateSSD bool `json:"emulatessd"` Format QemuDiskFormat `json:"format"` - Id *uint `json:"id,omitempty"` + Id uint `json:"id"` //Id is only returned and setting it has no effect IOThread bool `json:"iothread"` ReadOnly bool `json:"readonly"` Replicate bool `json:"replicate"` diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 07d8c3a1..a7f2390d 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -9,7 +9,7 @@ type QemuVirtIODisk struct { Cache QemuDiskCache `json:"cache,omitempty"` Discard bool `json:"discard"` Format QemuDiskFormat `json:"format"` - Id *uint `json:"id,omitempty"` + Id uint `json:"id"` //Id is only returned and setting it has no effect IOThread bool `json:"iothread"` ReadOnly bool `json:"readonly"` Replicate bool `json:"replicate"` diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index 3e73d1a4..8612d5d7 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -52,7 +52,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -76,7 +76,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Discard: true, EmulateSSD: true, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: false, Serial: "disk-9763", Size: 1032, @@ -89,7 +89,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_IOuring, Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -99,7 +99,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: false, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -110,7 +110,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Cache: QemuDiskCache_WriteThrough, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -121,7 +121,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Discard: true, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -132,7 +132,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 12}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -143,7 +143,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -154,7 +154,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 15}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -165,7 +165,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 14}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -176,7 +176,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.46}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -187,7 +187,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.57}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -198,7 +198,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.68}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -209,7 +209,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.55}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -219,7 +219,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: false, Storage: "test2", }}}}}, @@ -229,7 +229,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Serial: "disk-9763", Storage: "test2", @@ -240,7 +240,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Size: 1032, Storage: "test2", @@ -252,7 +252,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, EmulateSSD: true, Format: QemuDiskFormat_Qcow2, - Id: &uint53, + Id: uint53, Replicate: true, Storage: "test2", }}}}}, @@ -463,7 +463,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -487,7 +487,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Discard: true, EmulateSSD: true, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: false, Serial: "disk-9763", Size: 32, @@ -500,7 +500,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Native, Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -510,7 +510,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: false, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -521,7 +521,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Cache: QemuDiskCache_None, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -532,7 +532,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Discard: true, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -543,7 +543,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -554,7 +554,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -565,7 +565,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 11}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -576,7 +576,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -587,7 +587,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -598,7 +598,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -613,7 +613,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }, }, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -624,7 +624,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -634,7 +634,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: false, Storage: "test2", }}}}}, @@ -644,7 +644,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Serial: "disk-9763", Storage: "test2", @@ -655,7 +655,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Size: 32, Storage: "test2", @@ -667,7 +667,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, EmulateSSD: true, Format: QemuDiskFormat_Qcow2, - Id: &uint47, + Id: uint47, Replicate: true, Storage: "test2", }}}}}, @@ -878,7 +878,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -902,7 +902,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Discard: true, EmulateSSD: true, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, IOThread: true, ReadOnly: true, Replicate: false, @@ -917,7 +917,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Threads, Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -927,7 +927,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: false, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -938,7 +938,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Cache: QemuDiskCache_WriteBack, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -949,7 +949,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Discard: true, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -960,7 +960,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -971,7 +971,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -982,7 +982,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 11}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -993,7 +993,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -1003,7 +1003,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, IOThread: true, Replicate: true, Storage: "test", @@ -1015,7 +1015,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -1026,7 +1026,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -1037,7 +1037,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -1048,7 +1048,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -1058,7 +1058,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: false, Storage: "test", }}}}}, @@ -1068,7 +1068,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, ReadOnly: true, Replicate: true, Storage: "test", @@ -1079,7 +1079,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Serial: "disk-9763", Storage: "test", @@ -1090,7 +1090,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Size: 32, Storage: "test", @@ -1102,7 +1102,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, EmulateSSD: true, Format: QemuDiskFormat_Qcow2, - Id: &uint2, + Id: uint2, Replicate: true, Storage: "test", }}}}}, @@ -1333,7 +1333,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1356,7 +1356,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Cache: QemuDiskCache_DirectSync, Discard: true, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, IOThread: true, ReadOnly: true, Replicate: false, @@ -1371,7 +1371,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_IOuring, Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1381,7 +1381,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: false, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1392,7 +1392,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Cache: QemuDiskCache_DirectSync, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1403,7 +1403,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Discard: true, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1414,7 +1414,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1429,7 +1429,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }, }, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1440,7 +1440,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 11}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1451,7 +1451,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1461,7 +1461,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, IOThread: true, Replicate: true, Storage: "test2", @@ -1477,7 +1477,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }, }, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1488,7 +1488,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1499,7 +1499,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1510,7 +1510,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Storage: "test2", }}}}}, @@ -1520,7 +1520,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: false, Storage: "test2", }}}}}, @@ -1530,7 +1530,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, ReadOnly: true, Replicate: true, Storage: "test2", @@ -1541,7 +1541,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Serial: "disk-9763", Storage: "test2", @@ -1552,7 +1552,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, Format: QemuDiskFormat_Qcow2, - Id: &uint31, + Id: uint31, Replicate: true, Size: 32, Storage: "test2", From c04f9e31e884dc36e199fb3ef43cbfc5bbfd7062 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 20 Mar 2023 14:51:51 +0000 Subject: [PATCH 096/120] test: add test add test for `ConfigQemu{}.mapToApiValues` --- proxmox/config_qemu_test.go | 1791 +++++++++++++++++++++++++++++++++++ 1 file changed, 1791 insertions(+) diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index 8612d5d7..31034762 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -9,6 +9,1797 @@ import ( "github.com/stretchr/testify/require" ) +func Test_ConfigQemu_mapToApiValues(t *testing.T) { + format_Raw := QemuDiskFormat_Raw + float10 := float32(10.3) + float45 := float32(45.23) + float79 := float32(79.23) + float99 := float32(99.2) + uint23 := uint(23) + uint34 := uint(34) + uint78 := uint(78) + uint89 := uint(89) + update_CloudInit := &QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "test"} + ideBase := &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Raw, Id: 23, Size: 10, Storage: "test"}} + sataBase := &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Raw, Id: 23, Size: 10, Storage: "test"}} + scsiBase := &QemuScsiStorage{Disk: &QemuScsiDisk{Format: QemuDiskFormat_Raw, Id: 23, Size: 10, Storage: "test"}} + virtioBase := &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: QemuDiskFormat_Raw, Id: 23, Size: 10, Storage: "test"}} + tests := []struct { + name string + config *ConfigQemu + currentConfig ConfigQemu + vmr *VmRef + output map[string]interface{} + }{ + // Create Disks + + // Create Disks.Ide + {name: "Create Disks.Ide.Disk_X.CdRom none", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"ide0": "none,media=cdrom"}, + }, + {name: "Create Disks.Ide.Disk_X.CdRom.Iso", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"ide1": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Create Disks.Ide.Disk_X.CdRom.Passthrough", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"ide2": "cdrom,media=cdrom"}, + }, + {name: "Create Disks.Ide.Disk_X.CloudInit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + output: map[string]interface{}{"ide1": "Test:cloudinit,format=raw"}, + }, + // Create Disks.Ide.Disk_X.Disk + {name: "Create Disks.Ide.Disk_X.Disk All", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Backup: true, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, + WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, + WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + }, + }, + Cache: QemuDiskCache_DirectSync, + Discard: true, + EmulateSSD: true, + Format: format_Raw, + Replicate: true, + Serial: "558485ef-478", + Size: 32, + Storage: "Test", + }}}}}, + output: map[string]interface{}{"ide0": "Test:32,aio=native,cache=directsync,discard=on,format=raw,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=558485ef-478,ssd=1"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.AsyncIO", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{AsyncIO: QemuDiskAsyncIO_Native}}}}}, + output: map[string]interface{}{"ide1": ",aio=native,backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Backup", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Backup: true}}}}}, + output: map[string]interface{}{"ide2": ",replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{}}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,iops_rd_max=78,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,iops_rd=34,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,iops_wr_max=89,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,iops_wr=23,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Cache", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Cache: QemuDiskCache_DirectSync}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,cache=directsync,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Discard", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Discard: true}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,discard=on,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.EmulateSSD", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{EmulateSSD: true}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0,ssd=1"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Format", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Format: format_Raw}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,format=raw,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Replicate", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Replicate: true}}}}}, + output: map[string]interface{}{"ide1": ",backup=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Serial", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Serial: "558485ef-478"}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,replicate=0,serial=558485ef-478"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Size", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Size: 32}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Storage", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Storage: "Test"}}}}}, + output: map[string]interface{}{"ide0": "Test:0,backup=0,replicate=0"}, + }, + // Create Disks.Ide.Disk_X.Passthrough + {name: "Create Disks.Ide.Disk_X.Passthrough All", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: true, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, + WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, + WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + }, + }, + Cache: QemuDiskCache_Unsafe, + Discard: true, + EmulateSSD: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + Serial: "test-serial_757465-gdg", + }}}}}, + output: map[string]interface{}{"ide0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=test-serial_757465-gdg,ssd=1"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.AsyncIO", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{AsyncIO: QemuDiskAsyncIO_Threads}}}}}, + output: map[string]interface{}{"ide1": ",aio=threads,backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Backup", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Backup: true}}}}}, + output: map[string]interface{}{"ide2": ",replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{}}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,iops_rd_max=78,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,iops_rd=34,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,iops_wr_max=89,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,iops_wr=23,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Cache", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Cache: QemuDiskCache_Unsafe}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,cache=unsafe,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Discard", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Discard: true}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,discard=on,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.EmulateSSD", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{EmulateSSD: true}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0,ssd=1"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.File", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8"}}}}}, + output: map[string]interface{}{"ide1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.replicate", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Replicate: true}}}}}, + output: map[string]interface{}{"ide2": ",backup=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Serial", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Serial: "test-serial_757465-gdg"}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,replicate=0,serial=test-serial_757465-gdg"}, + }, + // Create Disks.Sata + {name: "Create Disks.Sata.Disk_X.Disk_X.CdRom none", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"sata0": "none,media=cdrom"}, + }, + {name: "Create Disks.Sata.Disk_X.CdRom.Iso", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"sata1": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Create Disks.Sata.Disk_X.CdRom.Passthrough", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"sata2": "cdrom,media=cdrom"}, + }, + {name: "Create Disks.Sata.Disk_X.CloudInit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + output: map[string]interface{}{"sata1": "Test:cloudinit,format=raw"}, + }, + // Create Disks.Sata.Disk_X.Disk + {name: "Create Disks.Sata.Disk_X.Disk ALL", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Backup: true, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, + WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, + WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + }, + }, + Cache: QemuDiskCache_Unsafe, + Discard: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Replicate: true, + Serial: "ab_C-12_3", + Size: 32, + Storage: "Test", + }}}}}, + output: map[string]interface{}{"sata0": "Test:32,aio=native,cache=unsafe,discard=on,format=qcow2,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=ab_C-12_3,ssd=1"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.AsyncIO", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{AsyncIO: QemuDiskAsyncIO_Native}}}}}, + output: map[string]interface{}{"sata0": ",aio=native,backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Backup", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{Backup: true}}}}}, + output: map[string]interface{}{"sata1": ",replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{}}}}}}, + output: map[string]interface{}{"sata2": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, + output: map[string]interface{}{"sata3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"sata4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"sata5": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"sata0": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"sata1": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"sata2": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"sata3": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, + output: map[string]interface{}{"sata4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"sata5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, + output: map[string]interface{}{"sata0": ",backup=0,iops_rd_max=78,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, + output: map[string]interface{}{"sata1": ",backup=0,iops_rd=34,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"sata2": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, + output: map[string]interface{}{"sata3": ",backup=0,iops_wr_max=89,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, + output: map[string]interface{}{"sata4": ",backup=0,iops_wr=23,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Cache", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Cache: QemuDiskCache_DirectSync}}}}}, + output: map[string]interface{}{"sata5": ",backup=0,cache=directsync,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Discard", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Discard: true}}}}}, + output: map[string]interface{}{"sata0": ",backup=0,discard=on,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.EmulateSSD", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{EmulateSSD: true}}}}}, + output: map[string]interface{}{"sata1": ",backup=0,replicate=0,ssd=1"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Format", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Format: format_Raw}}}}}, + output: map[string]interface{}{"sata2": ",backup=0,format=raw,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Replicate", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Replicate: true}}}}}, + output: map[string]interface{}{"sata2": ",backup=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Serial", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Serial: "558485ef-478"}}}}}, + output: map[string]interface{}{"sata3": ",backup=0,replicate=0,serial=558485ef-478"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Size", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Size: 32}}}}}, + output: map[string]interface{}{"sata4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Storage", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Storage: "Test"}}}}}, + output: map[string]interface{}{"sata5": "Test:0,backup=0,replicate=0"}, + }, + // Create Disks.Sata.Disk_X.Passthrough + {name: "Create Disks.Sata.Disk_X.Passthrough All", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: true, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, + WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, + WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + }, + }, + Cache: QemuDiskCache_Unsafe, + Discard: true, + EmulateSSD: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + Serial: "test-serial_757465-gdg", + }}}}}, + output: map[string]interface{}{"sata0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=test-serial_757465-gdg,ssd=1"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.AsyncIO", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{AsyncIO: QemuDiskAsyncIO_Threads}}}}}, + output: map[string]interface{}{"sata1": ",aio=threads,backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Backup", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Backup: true}}}}}, + output: map[string]interface{}{"sata2": ",replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{}}}}}}, + output: map[string]interface{}{"sata3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, + output: map[string]interface{}{"sata4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"sata5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"sata0": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"sata1": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"sata2": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"sata3": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"sata4": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, + output: map[string]interface{}{"sata5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"sata0": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, + output: map[string]interface{}{"sata1": ",backup=0,iops_rd_max=78,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, + output: map[string]interface{}{"sata2": ",backup=0,iops_rd=34,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"sata3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, + output: map[string]interface{}{"sata4": ",backup=0,iops_wr_max=89,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, + output: map[string]interface{}{"sata5": ",backup=0,iops_wr=23,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Cache", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Cache: QemuDiskCache_Unsafe}}}}}, + output: map[string]interface{}{"sata0": ",backup=0,cache=unsafe,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Discard", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Discard: true}}}}}, + output: map[string]interface{}{"sata1": ",backup=0,discard=on,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.EmulateSSD", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{EmulateSSD: true}}}}}, + output: map[string]interface{}{"sata2": ",backup=0,replicate=0,ssd=1"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.File", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8"}}}}}, + output: map[string]interface{}{"sata3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Replicate", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Replicate: true}}}}}, + output: map[string]interface{}{"sata4": ",backup=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Serial", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Serial: "test-serial_757465-gdg"}}}}}, + output: map[string]interface{}{"sata5": ",backup=0,replicate=0,serial=test-serial_757465-gdg"}, + }, + // Create Disks.Scsi + {name: "Create Disks.Scsi.CdRom none", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"scsi0": "none,media=cdrom"}, + }, + {name: "Create Disks.Scsi.CdRom.Iso", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"scsi1": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Create Disks.Scsi.CdRom.Passthrough", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"scsi2": "cdrom,media=cdrom"}, + }, + {name: "Create Disks.Scsi.CloudInit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + output: map[string]interface{}{"scsi1": "Test:cloudinit,format=raw"}, + }, + // Create Disks.Scsi.Disk_X.Disk + {name: "Create Disks.Scsi.Disk_X.Disk All", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Backup: true, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, + WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, + WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + }, + }, + Cache: QemuDiskCache_DirectSync, + Discard: true, + EmulateSSD: true, + Format: format_Raw, + IOThread: true, + ReadOnly: true, + Replicate: true, + Serial: "558485ef-478", + Size: 32, + Storage: "Test", + }}}}}, + output: map[string]interface{}{"scsi0": "Test:32,aio=native,cache=directsync,discard=on,format=raw,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=558485ef-478,ssd=1"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.AsyncIO", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Disk: &QemuScsiDisk{AsyncIO: QemuDiskAsyncIO_Native}}}}}, + output: map[string]interface{}{"scsi1": ",aio=native,backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Backup", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Disk: &QemuScsiDisk{Backup: true}}}}}, + output: map[string]interface{}{"scsi2": ",replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{}}}}}}, + output: map[string]interface{}{"scsi3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, + output: map[string]interface{}{"scsi4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"scsi5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"scsi6": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"scsi7": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"scsi8": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"scsi9": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"scsi10": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"scsi11": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"scsi12": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, + output: map[string]interface{}{"scsi13": ",backup=0,iops_rd_max=78,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_14: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, + output: map[string]interface{}{"scsi14": ",backup=0,iops_rd=34,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"scsi15": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, + output: map[string]interface{}{"scsi16": ",backup=0,iops_wr_max=89,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, + output: map[string]interface{}{"scsi17": ",backup=0,iops_wr=23,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Cache", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{Cache: QemuDiskCache_DirectSync}}}}}, + output: map[string]interface{}{"scsi18": ",backup=0,cache=directsync,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Discard", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{Discard: true}}}}}, + output: map[string]interface{}{"scsi19": ",backup=0,discard=on,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.EmulateSSD", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_20: &QemuScsiStorage{Disk: &QemuScsiDisk{EmulateSSD: true}}}}}, + output: map[string]interface{}{"scsi20": ",backup=0,replicate=0,ssd=1"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Format", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_20: &QemuScsiStorage{Disk: &QemuScsiDisk{Format: format_Raw}}}}}, + output: map[string]interface{}{"scsi20": ",backup=0,format=raw,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.IOThread", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{IOThread: true}}}}}, + output: map[string]interface{}{"scsi21": ",backup=0,iothread=1,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.ReadOnly", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_22: &QemuScsiStorage{Disk: &QemuScsiDisk{ReadOnly: true}}}}}, + output: map[string]interface{}{"scsi22": ",backup=0,replicate=0,ro=1"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Replicate", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_23: &QemuScsiStorage{Disk: &QemuScsiDisk{Replicate: true}}}}}, + output: map[string]interface{}{"scsi23": ",backup=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Serial", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_24: &QemuScsiStorage{Disk: &QemuScsiDisk{Serial: "558485ef-478"}}}}}, + output: map[string]interface{}{"scsi24": ",backup=0,replicate=0,serial=558485ef-478"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Size", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_25: &QemuScsiStorage{Disk: &QemuScsiDisk{Size: 32}}}}}, + output: map[string]interface{}{"scsi25": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Storage", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_26: &QemuScsiStorage{Disk: &QemuScsiDisk{Storage: "Test"}}}}}, + output: map[string]interface{}{"scsi26": "Test:0,backup=0,replicate=0"}, + }, + // Create Disks.Scsi.Passthrough + {name: "Create Disks.Scsi.Disk_X.Passthrough All", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: true, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, + WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, + WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + }, + }, + Cache: QemuDiskCache_Unsafe, + Discard: true, + EmulateSSD: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + IOThread: true, + ReadOnly: true, + Replicate: true, + Serial: "test-serial_757465-gdg", + }}}}}, + output: map[string]interface{}{"scsi0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=test-serial_757465-gdg,ssd=1"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.AsyncIO", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{AsyncIO: QemuDiskAsyncIO_Threads}}}}}, + output: map[string]interface{}{"scsi1": ",aio=threads,backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Backup", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Backup: true}}}}}, + output: map[string]interface{}{"scsi2": ",replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{}}}}}}, + output: map[string]interface{}{"scsi3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, + output: map[string]interface{}{"scsi4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"scsi5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"scsi6": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"scsi7": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"scsi8": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"scsi9": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"scsi10": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, + output: map[string]interface{}{"scsi11": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"scsi12": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, + output: map[string]interface{}{"scsi13": ",backup=0,iops_rd_max=78,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_14: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, + output: map[string]interface{}{"scsi14": ",backup=0,iops_rd=34,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"scsi15": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, + output: map[string]interface{}{"scsi16": ",backup=0,iops_wr_max=89,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, + output: map[string]interface{}{"scsi17": ",backup=0,iops_wr=23,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Cache", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Cache: QemuDiskCache_Unsafe}}}}}, + output: map[string]interface{}{"scsi18": ",backup=0,cache=unsafe,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Discard", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Discard: true}}}}}, + output: map[string]interface{}{"scsi19": ",backup=0,discard=on,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.EmulateSSD", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_20: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{EmulateSSD: true}}}}}, + output: map[string]interface{}{"scsi20": ",backup=0,replicate=0,ssd=1"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.File", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8"}}}}}, + output: map[string]interface{}{"scsi21": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.IOThread", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_22: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{IOThread: true}}}}}, + output: map[string]interface{}{"scsi22": ",backup=0,iothread=1,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.ReadOnly", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_23: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ReadOnly: true}}}}}, + output: map[string]interface{}{"scsi23": ",backup=0,replicate=0,ro=1"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Replicate", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_24: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Replicate: true}}}}}, + output: map[string]interface{}{"scsi24": ",backup=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Serial", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_25: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Serial: "test-serial_757465-gdg"}}}}}, + output: map[string]interface{}{"scsi25": ",backup=0,replicate=0,serial=test-serial_757465-gdg"}, + }, + // Create Disks.VirtIO + {name: "Create Disks.VirtIO.Disk_X.CdRom none", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"virtio0": "none,media=cdrom"}, + }, + {name: "Create Disks.VirtIO.Disk_X.CdRom.Iso", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"virtio1": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Create Disks.VirtIO.Disk_X.CdRom.Passthrough", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"virtio2": "cdrom,media=cdrom"}, + }, + {name: "Create Disks.VirtIO.Disk_X.CloudInit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + output: map[string]interface{}{"virtio1": "Test:cloudinit,format=raw"}, + }, + // Create Disks.VirtIO.Disk + {name: "Create Disks.VirtIO.Disk_X.Disk All", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Backup: true, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, + WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, + WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + }, + }, + Cache: QemuDiskCache_DirectSync, + Discard: true, + Format: format_Raw, + IOThread: true, + ReadOnly: true, + Replicate: true, + Serial: "558485ef-478", + Size: 32, + Storage: "Test", + }}}}}, + output: map[string]interface{}{"virtio0": "Test:32,aio=native,cache=directsync,discard=on,format=raw,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=558485ef-478"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.AsyncIO", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{AsyncIO: QemuDiskAsyncIO_Native}}}}}, + output: map[string]interface{}{"virtio1": ",aio=native,backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Backup", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Backup: true}}}}}, + output: map[string]interface{}{"virtio2": ",replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{}}}}}}, + output: map[string]interface{}{"virtio3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, + output: map[string]interface{}{"virtio4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"virtio5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, + output: map[string]interface{}{"virtio6": ",backup=0,iops_rd_max=78,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, + output: map[string]interface{}{"virtio7": ",backup=0,iops_rd=34,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"virtio8": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, + output: map[string]interface{}{"virtio9": ",backup=0,iops_wr_max=89,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, + output: map[string]interface{}{"virtio10": ",backup=0,iops_wr=23,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, + output: map[string]interface{}{"virtio11": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"virtio12": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, + output: map[string]interface{}{"virtio13": ",backup=0,iops_rd_max=78,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_14: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, + output: map[string]interface{}{"virtio14": ",backup=0,iops_rd=34,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"virtio15": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, + output: map[string]interface{}{"virtio0": ",backup=0,iops_wr_max=89,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, + output: map[string]interface{}{"virtio1": ",backup=0,iops_wr=23,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Cache", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Cache: QemuDiskCache_DirectSync}}}}}, + output: map[string]interface{}{"virtio2": ",backup=0,cache=directsync,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Discard", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Discard: true}}}}}, + output: map[string]interface{}{"virtio3": ",backup=0,discard=on,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Format", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Format: format_Raw}}}}}, + output: map[string]interface{}{"virtio4": ",backup=0,format=raw,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.IOThread", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{IOThread: true}}}}}, + output: map[string]interface{}{"virtio4": ",backup=0,iothread=1,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.ReadOnly", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ReadOnly: true}}}}}, + output: map[string]interface{}{"virtio5": ",backup=0,replicate=0,ro=1"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Replicate", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Replicate: true}}}}}, + output: map[string]interface{}{"virtio6": ",backup=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Serial", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Serial: "558485ef-478"}}}}}, + output: map[string]interface{}{"virtio7": ",backup=0,replicate=0,serial=558485ef-478"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Size", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Size: 32}}}}}, + output: map[string]interface{}{"virtio8": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Storage", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Storage: "Test"}}}}}, + output: map[string]interface{}{"virtio9": "Test:0,backup=0,replicate=0"}, + }, + // Create Disks.VirtIO.Disk_X.Passthrough + {name: "Create Disks.VirtIO.Disk_X.Passthrough All", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: true, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, + WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, + WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + }, + }, + Cache: QemuDiskCache_Unsafe, + Discard: true, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + IOThread: true, + ReadOnly: true, + Replicate: true, + Serial: "test-serial_757465-gdg", + }}}}}, + output: map[string]interface{}{"virtio0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=test-serial_757465-gdg"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.AsyncIO", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{AsyncIO: QemuDiskAsyncIO_Threads}}}}}, + output: map[string]interface{}{"virtio1": ",aio=threads,backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Backup", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Backup: true}}}}}, + output: map[string]interface{}{"virtio2": ",replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{}}}}}}, + output: map[string]interface{}{"virtio3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, + output: map[string]interface{}{"virtio4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"virtio5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"virtio6": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"virtio7": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, + output: map[string]interface{}{"virtio8": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"virtio9": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"virtio10": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, + output: map[string]interface{}{"virtio11": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"virtio12": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, + output: map[string]interface{}{"virtio13": ",backup=0,iops_rd_max=78,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_14: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, + output: map[string]interface{}{"virtio14": ",backup=0,iops_rd=34,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"virtio15": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, + output: map[string]interface{}{"virtio0": ",backup=0,iops_wr_max=89,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, + output: map[string]interface{}{"virtio1": ",backup=0,iops_wr=23,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Cache", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Cache: QemuDiskCache_Unsafe}}}}}, + output: map[string]interface{}{"virtio2": ",backup=0,cache=unsafe,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Discard", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Discard: true}}}}}, + output: map[string]interface{}{"virtio3": ",backup=0,discard=on,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.File", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8"}}}}}, + output: map[string]interface{}{"virtio4": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.IOThread", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{IOThread: true}}}}}, + output: map[string]interface{}{"virtio5": ",backup=0,iothread=1,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.ReadOnly", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ReadOnly: true}}}}}, + output: map[string]interface{}{"virtio6": ",backup=0,replicate=0,ro=1"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Replicate", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Replicate: true}}}}}, + output: map[string]interface{}{"virtio6": ",backup=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Serial", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Serial: "test-serial_757465-gdg"}}}}}, + output: map[string]interface{}{"virtio7": ",backup=0,replicate=0,serial=test-serial_757465-gdg"}, + }, + // Create Iso + {name: "Create Iso", + config: &ConfigQemu{Iso: &IsoFile{Storage: "test", File: "file.iso"}}, + output: map[string]interface{}{"ide2": "test:iso/file.iso,media=cdrom"}, + }, + // Update + + // Update Disk.Ide + {name: "Update Disk.Ide.Disk_X DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{}}}}, + output: map[string]interface{}{"delete": "ide0"}, + }, + // Update Disk.Ide.Disk_X.CdRom + {name: "Update Disk.Ide.Disk_X.CdRom CHANGE ISO TO None", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"ide1": "none,media=cdrom"}, + }, + {name: "Update Disk.Ide.Disk_X.CdRom CHANGE ISO TO Passthrough", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"ide2": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.Ide.Disk_X.CdRom CHANGE None TO ISO", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{CdRom: &QemuCdRom{}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"ide3": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Update Disk.Ide.Disk_X.CdRom CHANGE None TO Passthrough", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CdRom: &QemuCdRom{}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"ide0": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.Ide.Disk_X.CdRom CHANGE Passthrough TO ISO", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"ide1": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Update Disk.Ide.Disk_X.CdRom CHANGE Passthrough TO None", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"ide2": "none,media=cdrom"}, + }, + {name: "Update Disk.Ide.Disk_X.CdRom DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{}}}}, + output: map[string]interface{}{"delete": "ide3"}, + }, + {name: "Update Disk.Ide.Disk_X.CdRom SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"ide0": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.Ide.Disk_X.CdRom.Iso.File CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test2.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"ide1": "Test:iso/test2.iso,media=cdrom"}, + }, + {name: "Update Disk.Ide.Disk_X.CdRom.Iso.Storage CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "NewStorage"}}}}}}, + output: map[string]interface{}{"ide2": "NewStorage:iso/test.iso,media=cdrom"}, + }, + // Update Disk.Ide.Disk_X.CloudInit + {name: "Update Disk.Ide.Disk_X.CloudInit DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{CloudInit: update_CloudInit}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{}}}}, + output: map[string]interface{}{"delete": "ide3"}, + }, + {name: "Update Disk.Ide.Disk_X.CloudInit SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CloudInit: update_CloudInit}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CloudInit: update_CloudInit}}}}, + output: map[string]interface{}{"ide0": "test:cloudinit,format=raw"}, + }, + {name: "Update Disk.Ide.Disk_X.CloudInit.Format CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Qcow2, Storage: "Test"}}}}}, + output: map[string]interface{}{"ide1": "Test:cloudinit,format=qcow2"}, + }, + {name: "Update Disk.Ide.Disk_X.CloudInit.Storage CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "NewStorage"}}}}}, + output: map[string]interface{}{"ide2": "NewStorage:cloudinit,format=raw"}, + }, + // Update Disk.Ide.Disk_X.Disk + {name: "Update Disk.Ide.Disk_X.Disk CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"ide3": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: ideBase}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{}}}}, + output: map[string]interface{}{"delete": "ide0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk MIGRATE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test1", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"ide1": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk RESIZE DOWN", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 9, + Storage: "test", + }}}}}, + output: map[string]interface{}{"ide2": "test:9,backup=0,format=raw,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk RESIZE UP", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{"ide3": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: ideBase}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: ideBase}}}, + output: map[string]interface{}{"ide0": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk.Format CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Qcow2, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"ide1": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, + }, + // Update Disk.Sata + {name: "Update Disk.Sata.Disk_X DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{}}}}, + output: map[string]interface{}{"delete": "sata0"}, + }, + // Update Disk.Sata.Disk_X.CdRom + {name: "Update Disk.Sata.Disk_X.CdRom CHANGE ISO TO None", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"sata1": "none,media=cdrom"}, + }, + {name: "Update Disk.Sata.Disk_X.CdRom CHANGE ISO TO Passthrough", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"sata2": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.Sata.Disk_X.CdRom CHANGE None TO ISO", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{CdRom: &QemuCdRom{}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"sata3": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Update Disk.Sata.Disk_X.CdRom CHANGE None TO Passthrough", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{CdRom: &QemuCdRom{}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"sata4": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.Sata.Disk_X.CdRom CHANGE Passthrough TO ISO", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"sata5": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Update Disk.Sata.Disk_X.CdRom CHANGE Passthrough TO None", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"sata0": "none,media=cdrom"}, + }, + {name: "Update Disk.Sata.Disk_X.CdRom DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{}}}}, + output: map[string]interface{}{"delete": "sata1"}, + }, + {name: "Update Disk.Sata.Disk_X.CdRom SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"sata2": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.Sata.Disk_X.CdRom.Iso.File CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test2.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"sata3": "Test:iso/test2.iso,media=cdrom"}, + }, + {name: "Update Disk.Sata.Disk_X.CdRom.Iso.Storage CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "NewStorage"}}}}}}, + output: map[string]interface{}{"sata4": "NewStorage:iso/test.iso,media=cdrom"}, + }, + // Update Disk.Sata.Disk_X.CloudInit + {name: "Update Disk.Sata.Disk_X.CloudInit DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{CloudInit: update_CloudInit}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{}}}}, + output: map[string]interface{}{"delete": "sata5"}, + }, + {name: "Update Disk.Sata.Disk_X.CloudInit SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CloudInit: update_CloudInit}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CloudInit: update_CloudInit}}}}, + output: map[string]interface{}{"sata0": "test:cloudinit,format=raw"}, + }, + {name: "Update Disk.Sata.Disk_X.CloudInit.Format CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Qcow2, Storage: "Test"}}}}}, + output: map[string]interface{}{"sata1": "Test:cloudinit,format=qcow2"}, + }, + {name: "Update Disk.Sata.Disk_X.CloudInit.Storage CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "NewStorage"}}}}}, + output: map[string]interface{}{"sata2": "NewStorage:cloudinit,format=raw"}, + }, + // Update Disk.Sata.Disk_X.Disk + {name: "Update Disk.Sata.Disk_X.Disk CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata3": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: sataBase}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{}}}}, + output: map[string]interface{}{"delete": "sata4"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk MIGRATE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test1", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"sata5": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk RESIZE DOWN", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 9, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata0": "test:9,backup=0,format=raw,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk RESIZE UP", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata1": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: sataBase}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: sataBase}}}, + output: map[string]interface{}{"sata2": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk.Format CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Qcow2, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata3": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, + }, + // Update Disk.Scsi + {name: "Update Disk.Scsi.Disk_X DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{}}}}, + output: map[string]interface{}{"delete": "scsi0"}, + }, + // Update Disk.Scsi.Disk_X.CdRom + {name: "Update Disk.Scsi.Disk_X.CdRom CHANGE ISO TO None", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"scsi1": "none,media=cdrom"}, + }, + {name: "Update Disk.Scsi.Disk_X.CdRom CHANGE ISO TO Passthrough", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"scsi2": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.Scsi.Disk_X.CdRom CHANGE None TO ISO", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{CdRom: &QemuCdRom{}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"scsi3": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Update Disk.Scsi.Disk_X.CdRom CHANGE None TO Passthrough", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{CdRom: &QemuCdRom{}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"scsi4": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.Scsi.Disk_X.CdRom CHANGE Passthrough TO ISO", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"scsi5": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Update Disk.Scsi.Disk_X.CdRom CHANGE Passthrough TO None", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"scsi6": "none,media=cdrom"}, + }, + {name: "Update Disk.Scsi.Disk_X.CdRom DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{}}}}, + output: map[string]interface{}{"delete": "scsi7"}, + }, + {name: "Update Disk.Scsi.Disk_X.CdRom SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"scsi8": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.Scsi.Disk_X.CdRom.Iso.File CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test2.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"scsi9": "Test:iso/test2.iso,media=cdrom"}, + }, + {name: "Update Disk.Scsi.Disk_X.CdRom.Iso.Storage CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "NewStorage"}}}}}}, + output: map[string]interface{}{"scsi10": "NewStorage:iso/test.iso,media=cdrom"}, + }, + // Update Disk.Scsi.Disk_X.CloudInit + {name: "Update Disk.Scsi.Disk_X.CloudInit DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{CloudInit: update_CloudInit}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{}}}}, + output: map[string]interface{}{"delete": "scsi11"}, + }, + {name: "Update Disk.Scsi.Disk_X.CloudInit SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{CloudInit: update_CloudInit}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{CloudInit: update_CloudInit}}}}, + output: map[string]interface{}{"scsi12": "test:cloudinit,format=raw"}, + }, + {name: "Update Disk.Scsi.Disk_X.CloudInit.Format CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Qcow2, Storage: "Test"}}}}}, + output: map[string]interface{}{"scsi13": "Test:cloudinit,format=qcow2"}, + }, + {name: "Update Disk.Scsi.Disk_X.CloudInit.Storage CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_14: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_14: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "NewStorage"}}}}}, + output: map[string]interface{}{"scsi14": "NewStorage:cloudinit,format=raw"}, + }, + // Update Disk.Scsi.Disk_X.Disk + {name: "Update Disk.Scsi.Disk_X.Disk CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"scsi15": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: scsiBase}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: &QemuScsiStorage{}}}}, + output: map[string]interface{}{"delete": "scsi16"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk MIGRATE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test1", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"scsi17": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk RESIZE DOWN", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 9, + Storage: "test", + }}}}}, + output: map[string]interface{}{"scsi18": "test:9,backup=0,format=raw,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk RESIZE UP", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{"scsi19": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_20: scsiBase}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_20: scsiBase}}}, + output: map[string]interface{}{"scsi20": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk.Format CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Qcow2, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"scsi21": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, + }, + // Update Disk.VirtIO + {name: "Update Disk.VirtIO.Disk_X DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{}}}}, + output: map[string]interface{}{"delete": "virtio0"}, + }, + // Update Disk.VirtIO.Disk_X.CdRom + {name: "Update Disk.VirtIO.Disk_X.CdRom CHANGE ISO TO None", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"virtio1": "none,media=cdrom"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CdRom CHANGE ISO TO Passthrough", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"virtio2": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CdRom CHANGE None TO ISO", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{CdRom: &QemuCdRom{}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"virtio3": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CdRom CHANGE None TO Passthrough", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{CdRom: &QemuCdRom{}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"virtio4": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CdRom CHANGE Passthrough TO ISO", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"virtio5": "Test:iso/test.iso,media=cdrom"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CdRom CHANGE Passthrough TO None", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{CdRom: &QemuCdRom{}}}}}, + output: map[string]interface{}{"virtio6": "none,media=cdrom"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CdRom DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{}}}}, + output: map[string]interface{}{"delete": "virtio7"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CdRom SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, + output: map[string]interface{}{"virtio8": "cdrom,media=cdrom"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CdRom.Iso.File CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test2.iso", Storage: "Test"}}}}}}, + output: map[string]interface{}{"virtio9": "Test:iso/test2.iso,media=cdrom"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CdRom.Iso.Storage CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "NewStorage"}}}}}}, + output: map[string]interface{}{"virtio10": "NewStorage:iso/test.iso,media=cdrom"}, + }, + // Update Disk.VirtIO.Disk_X.CloudInit + {name: "Update Disk.VirtIO.Disk_X.CloudInit DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{CloudInit: update_CloudInit}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{}}}}, + output: map[string]interface{}{"delete": "virtio11"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CloudInit SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{CloudInit: update_CloudInit}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{CloudInit: update_CloudInit}}}}, + output: map[string]interface{}{"virtio12": "test:cloudinit,format=raw"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CloudInit.Format CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{Format: QemuDiskFormat_Qcow2, Storage: "Test"}}}}}, + output: map[string]interface{}{"virtio13": "Test:cloudinit,format=qcow2"}, + }, + {name: "Update Disk.VirtIO.Disk_X.CloudInit.Storage CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_14: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_14: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "NewStorage"}}}}}, + output: map[string]interface{}{"virtio14": "NewStorage:cloudinit,format=raw"}, + }, + // Update Disk.VirtIO.Disk_X.Disk + {name: "Update Disk.VirtIO.Disk_X.Disk CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"virtio15": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk DELETE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: virtioBase}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{}}}}, + output: map[string]interface{}{"delete": "virtio0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk MIGRATE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test1", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"virtio1": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE DOWN", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 9, + Storage: "test", + }}}}}, + output: map[string]interface{}{"virtio2": "test:9,backup=0,format=raw,replicate=0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE UP", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{"virtio3": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: virtioBase}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: virtioBase}}}, + output: map[string]interface{}{"virtio4": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk.Format CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Qcow2, + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"virtio5": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, + }, + // Update Iso + {name: "Update Iso nil", + currentConfig: ConfigQemu{Iso: &IsoFile{Storage: "test", File: "file.iso"}}, + config: &ConfigQemu{Iso: nil}, + output: map[string]interface{}{}, + }, + {name: "Update Iso SAME", + currentConfig: ConfigQemu{Iso: &IsoFile{Storage: "test", File: "file.iso"}}, + config: &ConfigQemu{Iso: &IsoFile{Storage: "test", File: "file.iso"}}, + output: map[string]interface{}{"ide2": "test:iso/file.iso,media=cdrom"}, + }, + {name: "Update Iso.File", + currentConfig: ConfigQemu{Iso: &IsoFile{Storage: "test", File: "file.iso"}}, + config: &ConfigQemu{Iso: &IsoFile{Storage: "test", File: "file2.iso"}}, + output: map[string]interface{}{"ide2": "test:iso/file2.iso,media=cdrom"}, + }, + {name: "Update Iso.Storage", + currentConfig: ConfigQemu{Iso: &IsoFile{Storage: "test", File: "file.iso"}}, + config: &ConfigQemu{Iso: &IsoFile{Storage: "NewStorage", File: "file.iso"}}, + output: map[string]interface{}{"ide2": "NewStorage:iso/file.iso,media=cdrom"}, + }, + } + for _, test := range tests { + t.Run(test.name, func(*testing.T) { + tmpParams, _ := test.config.mapToApiValues(test.currentConfig) + require.Equal(t, test.output, tmpParams, test.name) + }) + } +} + func Test_ConfigQemu_mapToStruct(t *testing.T) { uint2 := uint(2) uint31 := uint(31) From 75c1484dbc79bad4e755dd452d4dd1a35237144d Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 20 Mar 2023 14:57:49 +0000 Subject: [PATCH 097/120] test: remove TODO test cases have been covered indirectly --- proxmox/config_qemu_disk.go | 4 ---- proxmox/config_qemu_disk_ide.go | 4 ---- proxmox/config_qemu_disk_sata.go | 4 ---- proxmox/config_qemu_disk_scsi.go | 4 ---- proxmox/config_qemu_disk_virtio.go | 4 ---- 5 files changed, 20 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 973fcc03..d2691913 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -41,7 +41,6 @@ const ( Error_QemuCdRom_MutuallyExclusive string = "iso and passthrough are mutually exclusive" ) -// TODO write test func (cdRom QemuCdRom) mapToApiValues() string { if cdRom.Passthrough { return "cdrom,media=cdrom" @@ -155,7 +154,6 @@ func (QemuCloudInitDisk) checkDuplicates(numberOFCloudInitDrives uint8) error { return nil } -// TODO write test func (cloudInit QemuCloudInitDisk) mapToApiValues() string { return cloudInit.Storage + ":cloudinit,format=" + string(cloudInit.Format) } @@ -207,7 +205,6 @@ const ( Error_QemuDisk_Storage string = "storage may not be empty" ) -// TODO write test func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { if disk.Storage != "" { if create { @@ -288,7 +285,6 @@ func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { } // Maps all the disk related settings -// TODO write test func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { if len(settings) == 0 { return nil diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 9940d8d5..8149eada 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -47,7 +47,6 @@ type QemuIdeDisks struct { Disk_3 *QemuIdeStorage `json:"3,omitempty"` } -// TODO write test func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, vmID uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuIdeDisks{} if currentDisks != nil { @@ -70,7 +69,6 @@ func (disks QemuIdeDisks) mapToIntMap() map[uint8]*QemuIdeStorage { } } -// TODO write test func (QemuIdeDisks) mapToStruct(params map[string]interface{}) *QemuIdeDisks { disks := QemuIdeDisks{} var structPopulated bool @@ -170,7 +168,6 @@ type QemuIdeStorage struct { Passthrough *QemuIdePassthrough `json:"passthrough,omitempty"` } -// TODO write test // converts to qemuStorage func (storage *QemuIdeStorage) convertDataStructure() *qemuStorage { if storage == nil { @@ -205,7 +202,6 @@ func (storage *QemuIdeStorage) convertDataStructureMark() *qemuDiskMark { return nil } -// TODO write test func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index fd69d071..6ca552b8 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -49,7 +49,6 @@ type QemuSataDisks struct { Disk_5 *QemuSataStorage `json:"5,omitempty"` } -// TODO write test func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, vmID uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuSataDisks{} if currentDisks != nil { @@ -74,7 +73,6 @@ func (disks QemuSataDisks) mapToIntMap() map[uint8]*QemuSataStorage { } } -// TODO write test func (QemuSataDisks) mapToStruct(params map[string]interface{}) *QemuSataDisks { disks := QemuSataDisks{} var structPopulated bool @@ -182,7 +180,6 @@ type QemuSataStorage struct { Passthrough *QemuSataPassthrough `json:"passthrough,omitempty"` } -// TODO write test // converts to qemuStorage func (storage *QemuSataStorage) convertDataStructure() *qemuStorage { if storage == nil { @@ -217,7 +214,6 @@ func (storage *QemuSataStorage) convertDataStructureMark() *qemuDiskMark { return nil } -// TODO write test func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 80f31712..483ab68b 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -78,7 +78,6 @@ type QemuScsiDisks struct { Disk_30 *QemuScsiStorage `json:"30,omitempty"` } -// TODO write test func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, vmID uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuScsiDisks{} if currentDisks != nil { @@ -128,7 +127,6 @@ func (disks QemuScsiDisks) mapToIntMap() map[uint8]*QemuScsiStorage { } } -// TODO write test func (QemuScsiDisks) mapToStruct(params map[string]interface{}) *QemuScsiDisks { disks := QemuScsiDisks{} var structPopulated bool @@ -340,7 +338,6 @@ type QemuScsiStorage struct { Passthrough *QemuScsiPassthrough `json:"passthrough,omitempty"` } -// TODO write test // converts to qemuStorage func (storage *QemuScsiStorage) convertDataStructure() *qemuStorage { if storage == nil { @@ -375,7 +372,6 @@ func (storage *QemuScsiStorage) convertDataStructureMark() *qemuDiskMark { return nil } -// TODO write test func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index a7f2390d..a55f45b9 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -61,7 +61,6 @@ type QemuVirtIODisks struct { Disk_15 *QemuVirtIOStorage `json:"15,omitempty"` } -// TODO write test func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, vmID uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuVirtIODisks{} if currentDisks != nil { @@ -96,7 +95,6 @@ func (disks QemuVirtIODisks) mapToIntMap() map[uint8]*QemuVirtIOStorage { } } -// TODO write test func (QemuVirtIODisks) mapToStruct(params map[string]interface{}) *QemuVirtIODisks { disks := QemuVirtIODisks{} var structPopulated bool @@ -246,7 +244,6 @@ type QemuVirtIOStorage struct { Passthrough *QemuVirtIOPassthrough `json:"passthrough,omitempty"` } -// TODO write test // converts to qemuStorage func (storage *QemuVirtIOStorage) convertDataStructure() *qemuStorage { if storage == nil { @@ -281,7 +278,6 @@ func (storage *QemuVirtIOStorage) convertDataStructureMark() *qemuDiskMark { return nil } -// TODO write test func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) From 34b6ee83448e46d1cc3968afd49e3d5fe3f9a4e4 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 20 Mar 2023 20:43:15 +0000 Subject: [PATCH 098/120] feat: add custom type and validate func --- proxmox/config_qemu_disk.go | 90 +++++++--- proxmox/config_qemu_disk_test.go | 132 ++++++++++++--- proxmox/config_qemu_test.go | 272 +++++++++++++++---------------- 3 files changed, 312 insertions(+), 182 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index d2691913..702994f7 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -334,19 +334,19 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { } if e[0] == "iops_rd" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.ReadLimit.Concurrent = uint(tmp) + disk.Bandwidth.Iops.ReadLimit.Concurrent = QemuDiskBandwidthIopsLimitConcurrent(tmp) } if e[0] == "iops_rd_max" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.ReadLimit.Burst = uint(tmp) + disk.Bandwidth.Iops.ReadLimit.Burst = QemuDiskBandwidthIopsLimitBurst(tmp) } if e[0] == "iops_wr" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.WriteLimit.Concurrent = uint(tmp) + disk.Bandwidth.Iops.WriteLimit.Concurrent = QemuDiskBandwidthIopsLimitConcurrent(tmp) } if e[0] == "iops_wr_max" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.WriteLimit.Burst = uint(tmp) + disk.Bandwidth.Iops.WriteLimit.Burst = QemuDiskBandwidthIopsLimitBurst(tmp) } if e[0] == "iothread" { disk.IOThread, _ = strconv.ParseBool(e[1]) @@ -354,19 +354,19 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { } if e[0] == "mbps_rd" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.ReadLimit.Concurrent = float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.ReadLimit.Concurrent = QemuDiskBandwidthDataLimitConcurrent(math.Round(tmp*100) / 100) } if e[0] == "mbps_rd_max" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.ReadLimit.Burst = float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.ReadLimit.Burst = QemuDiskBandwidthDataLimitBurst(math.Round(tmp*100) / 100) } if e[0] == "mbps_wr" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.WriteLimit.Concurrent = float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.WriteLimit.Concurrent = QemuDiskBandwidthDataLimitConcurrent(math.Round(tmp*100) / 100) } if e[0] == "mbps_wr_max" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.WriteLimit.Burst = float32(math.Round(tmp*100) / 100) + disk.Bandwidth.Data.WriteLimit.Burst = QemuDiskBandwidthDataLimitBurst(math.Round(tmp*100) / 100) } if e[0] == "replicate" { disk.Replicate, _ = strconv.ParseBool(e[1]) @@ -475,21 +475,40 @@ func (data QemuDiskBandwidthData) Validate() error { } type QemuDiskBandwidthDataLimit struct { - Burst float32 `json:"burst,omitempty"` // 0 = default - Concurrent float32 `json:"concurrent,omitempty"` // 0 = unlimited + Burst QemuDiskBandwidthDataLimitBurst `json:"burst,omitempty"` // 0 = default + Concurrent QemuDiskBandwidthDataLimitConcurrent `json:"concurrent,omitempty"` // 0 = unlimited +} + +func (limit QemuDiskBandwidthDataLimit) Validate() (err error) { + if err = limit.Burst.Validate(); err != nil { + return + } + err = limit.Concurrent.Validate() + return } const ( - Error_QemuDiskBandwidthDataLimit_Burst string = "burst may not be lower then 1 except for 0" - Error_QemuDiskBandwidthDataLimit_Concurrent string = "concurrent may not be lower then 1 except for 0" + Error_QemuDiskBandwidthDataLimitBurst string = "burst may not be lower then 1 except for 0" ) -func (limit QemuDiskBandwidthDataLimit) Validate() error { - if limit.Burst != 0 && limit.Burst < 1 { - return errors.New(Error_QemuDiskBandwidthDataLimit_Burst) +type QemuDiskBandwidthDataLimitBurst float32 + +func (limit QemuDiskBandwidthDataLimitBurst) Validate() error { + if limit != 0 && limit < 1 { + return errors.New(Error_QemuDiskBandwidthDataLimitBurst) } - if limit.Concurrent != 0 && limit.Concurrent < 1 { - return errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) + return nil +} + +const ( + Error_QemuDiskBandwidthDataLimitConcurrent string = "concurrent may not be lower then 1 except for 0" +) + +type QemuDiskBandwidthDataLimitConcurrent float32 + +func (limit QemuDiskBandwidthDataLimitConcurrent) Validate() error { + if limit != 0 && limit < 1 { + return errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) } return nil } @@ -508,21 +527,40 @@ func (iops QemuDiskBandwidthIops) Validate() error { } type QemuDiskBandwidthIopsLimit struct { - Burst uint `json:"burst,omitempty"` // 0 = default - Concurrent uint `json:"concurrent,omitempty"` // 0 = unlimited + Burst QemuDiskBandwidthIopsLimitBurst `json:"burst,omitempty"` // 0 = default + Concurrent QemuDiskBandwidthIopsLimitConcurrent `json:"concurrent,omitempty"` // 0 = unlimited } +func (limit QemuDiskBandwidthIopsLimit) Validate() (err error) { + if err = limit.Burst.Validate(); err != nil { + return + } + err = limit.Concurrent.Validate() + return +} + +type QemuDiskBandwidthIopsLimitBurst uint + const ( - Error_QemuDiskBandwidthIopsLimit_Burst string = "burst may not be lower then 10 except for 0" - Error_QemuDiskBandwidthIopsLimit_Concurrent string = "concurrent may not be lower then 10 except for 0" + Error_QemuDiskBandwidthIopsLimitBurst string = "burst may not be lower then 10 except for 0" ) -func (limit QemuDiskBandwidthIopsLimit) Validate() error { - if limit.Burst != 0 && limit.Burst < 10 { - return errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) +func (limit QemuDiskBandwidthIopsLimitBurst) Validate() error { + if limit != 0 && limit < 10 { + return errors.New(Error_QemuDiskBandwidthIopsLimitBurst) } - if limit.Concurrent != 0 && limit.Concurrent < 10 { - return errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) + return nil +} + +type QemuDiskBandwidthIopsLimitConcurrent uint + +const ( + Error_QemuDiskBandwidthIopsLimitConcurrent string = "concurrent may not be lower then 10 except for 0" +) + +func (limit QemuDiskBandwidthIopsLimitConcurrent) Validate() error { + if limit != 0 && limit < 10 { + return errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) } return nil } diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 1370e50f..39a54492 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -145,14 +145,14 @@ func Test_QemuDiskBandwidth_Validate(t *testing.T) { {name: "Valid 21", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}}, {name: "Valid 22", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}}, // Invalid - {name: "Invalid 00", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, - {name: "Invalid 01", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, - {name: "Invalid 02", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, - {name: "Invalid 03", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, - {name: "Invalid 04", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, - {name: "Invalid 05", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, - {name: "Invalid 06", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, - {name: "Invalid 07", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, + {name: "Invalid 01", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, + {name: "Invalid 02", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, + {name: "Invalid 03", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, + {name: "Invalid 04", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, + {name: "Invalid 05", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, + {name: "Invalid 06", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, + {name: "Invalid 07", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { @@ -184,10 +184,10 @@ func Test_QemuDiskBandwidthData_Validate(t *testing.T) { {name: "Valid 09", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}, {name: "Valid 10", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}, // Invalid - {name: "Invalid 00", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, - {name: "Invalid 01", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, - {name: "Invalid 02", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, - {name: "Invalid 03", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, + {name: "Invalid 01", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, + {name: "Invalid 02", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, + {name: "Invalid 03", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { @@ -213,8 +213,54 @@ func Test_QemuDiskBandwidthDataLimit_Validate(t *testing.T) { {name: "Valid 03", input: QemuDiskBandwidthDataLimit{Concurrent: 0}}, {name: "Valid 04", input: QemuDiskBandwidthDataLimit{Concurrent: 1}}, // Invalid - {name: "Invalid 00", input: QemuDiskBandwidthDataLimit{Burst: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst)}, - {name: "Invalid 01", input: QemuDiskBandwidthDataLimit{Concurrent: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthDataLimit{Burst: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, + {name: "Invalid 01", input: QemuDiskBandwidthDataLimit{Concurrent: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, + } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) + } +} + +func Test_QemuDiskBandwidthDataLimitBurst_Validate(t *testing.T) { + testData := []struct { + name string + input QemuDiskBandwidthDataLimitBurst + err error + }{ + // Valid + {name: "Valid 01", input: 0}, + {name: "Valid 02", input: 1}, + // Invalid + {name: "Invalid 00", input: 0.99, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, + } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) + } +} + +func Test_QemuDiskBandwidthDataLimitConcurrent_Validate(t *testing.T) { + testData := []struct { + name string + input QemuDiskBandwidthDataLimitConcurrent + err error + }{ + // Valid + {name: "Valid 01", input: 0}, + {name: "Valid 02", input: 1}, + // Invalid + {name: "Invalid 00", input: 0.99, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { @@ -246,10 +292,10 @@ func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { {name: "Valid 09", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, {name: "Valid 10", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, // Invalid - {name: "Invalid 00", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, - {name: "Invalid 01", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, - {name: "Invalid 02", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, - {name: "Invalid 03", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, + {name: "Invalid 01", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, + {name: "Invalid 02", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, + {name: "Invalid 03", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { @@ -275,8 +321,54 @@ func Test_QemuDiskBandwidthIopsLimit_Validate(t *testing.T) { {name: "Valid 03", input: QemuDiskBandwidthIopsLimit{Concurrent: 0}}, {name: "Valid 04", input: QemuDiskBandwidthIopsLimit{Concurrent: 10}}, // Invalid - {name: "Invalid 00", input: QemuDiskBandwidthIopsLimit{Burst: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst)}, - {name: "Invalid 01", input: QemuDiskBandwidthIopsLimit{Concurrent: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthIopsLimit{Burst: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, + {name: "Invalid 01", input: QemuDiskBandwidthIopsLimit{Concurrent: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, + } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) + } +} + +func Test_QemuDiskBandwidthIopsLimitBurst_Validate(t *testing.T) { + testData := []struct { + name string + input QemuDiskBandwidthIopsLimitBurst + err error + }{ + // Valid + {name: "Valid 03", input: 0}, + {name: "Valid 04", input: 10}, + // Invalid + {name: "Invalid 01", input: 9, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, + } + for _, test := range testData { + t.Run(test.name, func(*testing.T) { + if test.err != nil { + require.Equal(t, test.input.Validate(), test.err, test.name) + } else { + require.NoError(t, test.input.Validate(), test.name) + } + }) + } +} + +func Test_QemuDiskBandwidthIopsLimitConcurrent_Validate(t *testing.T) { + testData := []struct { + name string + input QemuDiskBandwidthIopsLimitConcurrent + err error + }{ + // Valid + {name: "Valid 03", input: 0}, + {name: "Valid 04", input: 10}, + // Invalid + {name: "Invalid 01", input: 9, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index 31034762..8f653729 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -11,14 +11,14 @@ import ( func Test_ConfigQemu_mapToApiValues(t *testing.T) { format_Raw := QemuDiskFormat_Raw - float10 := float32(10.3) - float45 := float32(45.23) - float79 := float32(79.23) - float99 := float32(99.2) - uint23 := uint(23) - uint34 := uint(34) - uint78 := uint(78) - uint89 := uint(89) + float10 := QemuDiskBandwidthDataLimitConcurrent(10.3) + float45 := QemuDiskBandwidthDataLimitConcurrent(45.23) + float79 := QemuDiskBandwidthDataLimitBurst(79.23) + float99 := QemuDiskBandwidthDataLimitBurst(99.2) + uint23 := QemuDiskBandwidthIopsLimitConcurrent(23) + uint34 := QemuDiskBandwidthIopsLimitConcurrent(34) + uint78 := QemuDiskBandwidthIopsLimitBurst(78) + uint89 := QemuDiskBandwidthIopsLimitBurst(89) update_CloudInit := &QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "test"} ideBase := &QemuIdeStorage{Disk: &QemuIdeDisk{Format: QemuDiskFormat_Raw, Id: 23, Size: 10, Storage: "test"}} sataBase := &QemuSataStorage{Disk: &QemuSataDisk{Format: QemuDiskFormat_Raw, Id: 23, Size: 10, Storage: "test"}} @@ -4272,37 +4272,37 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, {name: `Invalid Disks Disk Ide QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Cache: "invalid"}}}}}, @@ -4350,37 +4350,37 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, {name: `Invalid Disks Disk Sata QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Cache: "invalid"}}}}}, @@ -4428,37 +4428,37 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Disk: &QemuScsiDisk{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, {name: `Invalid Disks Disk Scsi QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Disk: &QemuScsiDisk{Cache: "invalid"}}}}}, @@ -4506,37 +4506,37 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, {name: `Invalid Disks Disk VirtIO QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Cache: "invalid"}}}}}, @@ -4580,37 +4580,37 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, {name: `Invalid Disks Passthrough Ide QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Cache: "invalid"}}}}}, @@ -4633,37 +4633,37 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, {name: `Invalid Disks Passthrough Sata QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Cache: "invalid"}}}}}, @@ -4686,37 +4686,37 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, {name: `Invalid Disks Passthrough Scsi QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Cache: "invalid"}}}}}, @@ -4739,37 +4739,37 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 0`, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 0`, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Burst) 1`, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent) 1`, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 0`, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 0`, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 0`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 8}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Burst) 1`, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 1`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 7}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Burst), + err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent) 1`, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) 1`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthIopsLimit_Concurrent), + err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, {name: `Invalid Disks Passthrough VirtIO QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Cache: "invalid"}}}}}, From 429c0d7461a2a2e01f268bf29815309558847de8 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 20 Mar 2023 20:44:23 +0000 Subject: [PATCH 099/120] refactor: cahange update flow --- proxmox/config_qemu.go | 46 ++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index c0ed60bb..4eda9af2 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -675,7 +675,7 @@ func (newConfig ConfigQemu) Update(vmr *VmRef, client *Client) (err error) { if err != nil { return } - return newConfig.UpdateAdvanced(currentConfig, vmr, client) + return newConfig.SetAdvanced(currentConfig, vmr, client) } func (config *ConfigQemu) setVmr(vmr *VmRef) error { @@ -690,7 +690,7 @@ func (config *ConfigQemu) setVmr(vmr *VmRef) error { return nil } -func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef, client *Client) (err error) { +func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, vmr *VmRef, client *Client) (err error) { err = newConfig.setVmr(vmr) if err != nil { return @@ -700,14 +700,21 @@ func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef return } + var params map[string]interface{} + var exitStatus string + if currentConfig != nil { + // Update + markedDisks := newConfig.Disks.markDiskChanges(*currentConfig.Disks) + // move disk to different storage or change disk format for _, e := range markedDisks.Move { _, err = e.move(true, vmr, client) if err != nil { return } } + // increase Disks in size for _, e := range markedDisks.Resize { _, err = e.resize(vmr, client) if err != nil { @@ -721,30 +728,35 @@ func (newConfig ConfigQemu) UpdateAdvanced(currentConfig *ConfigQemu, vmr *VmRef return } } - } - if newConfig.Node != currentConfig.Node { - vmr.SetNode(currentConfig.Node) - _, err = client.MigrateNode(vmr, newConfig.Node, true) - if err != nil { - return + // Migrate VM + if newConfig.Node != currentConfig.Node { + vmr.SetNode(currentConfig.Node) + _, err = client.MigrateNode(vmr, newConfig.Node, true) + if err != nil { + return + } + // Set node to the node the VM was migrated to + vmr.SetNode(newConfig.Node) } - vmr.SetNode(newConfig.Node) - } - var params map[string]interface{} - if currentConfig != nil { params, err = newConfig.mapToApiValues(*currentConfig) + if err != nil { + return + } + exitStatus, err = client.PutWithTask(params, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/config") } else { + // Create + params, err = newConfig.mapToApiValues(ConfigQemu{}) - } - if err != nil { - return + if err != nil { + return + } + exitStatus, err = client.CreateQemuVm(vmr.node, params) } - _, err = client.PutWithTask(params, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/config") if err != nil { - return + return fmt.Errorf("error creating VM: %v, error status: %s (params: %v)", err, exitStatus, params) } _, err = client.UpdateVMHA(vmr, newConfig.HaState, newConfig.HaGroup) From 65996e1b95fa23ad734e7a2ec7ac68a601a574ed Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 20 Mar 2023 20:45:10 +0000 Subject: [PATCH 100/120] refactor: add new `ConfigQemu{}.Create` func --- proxmox/config_qemu.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 4eda9af2..ec6bb7ba 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -87,6 +87,13 @@ type ConfigQemu struct { VmID int `json:"vmid,omitempty"` // TODO should be a custom type as there are limitations } +// Create - Tell Proxmox API to make the VM +func (config ConfigQemu) Create(vmr *VmRef, client *Client) error { + return config.SetAdvanced(nil, vmr, client) +} + +// DEPRECATED use ConfigQemu{}.Create Instead. +// // CreateVm - Tell Proxmox API to make the VM func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { err = config.setVmr(vmr) From 6a66cf1806cfa471d7e31d4a642f78783bc9bcb8 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 20 Mar 2023 20:47:16 +0000 Subject: [PATCH 101/120] docs: add comment --- proxmox/config_qemu_disk.go | 1 + 1 file changed, 1 insertion(+) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 702994f7..57724459 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -884,6 +884,7 @@ func (QemuStorages) mapToStruct(params map[string]interface{}) *QemuStorages { return nil } +// mark disk that need to be moved or resized func (storages QemuStorages) markDiskChanges(currentStorages QemuStorages) *qemuUpdateChanges { changes := &qemuUpdateChanges{} if storages.Ide != nil { From cebcfff9008b3293db9246dc324957d9b1ca69d3 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 23 Mar 2023 13:57:26 +0000 Subject: [PATCH 102/120] refactor: move `VmRef` nilCheck to new func --- proxmox/client.go | 7 +++++++ proxmox/config_qemu.go | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/proxmox/client.go b/proxmox/client.go index 2b73d67f..2ea537b8 100644 --- a/proxmox/client.go +++ b/proxmox/client.go @@ -81,6 +81,13 @@ func (vmr *VmRef) HaGroup() string { return vmr.haGroup } +func (vmr *VmRef) nilCheck() error { + if vmr == nil { + return errors.New("vm reference may not be nil") + } + return nil +} + func NewVmRef(vmId int) (vmr *VmRef) { vmr = &VmRef{vmId: vmId, node: "", vmType: ""} return diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index ec6bb7ba..6805c95a 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -685,16 +685,16 @@ func (newConfig ConfigQemu) Update(vmr *VmRef, client *Client) (err error) { return newConfig.SetAdvanced(currentConfig, vmr, client) } -func (config *ConfigQemu) setVmr(vmr *VmRef) error { +func (config *ConfigQemu) setVmr(vmr *VmRef) (err error) { if config == nil { return errors.New("config may not be nil") } - if vmr == nil { - return errors.New("vm reference may not be nil") + if err = vmr.nilCheck(); err != nil { + return } vmr.SetVmType("qemu") config.VmID = vmr.vmId - return nil + return } func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, vmr *VmRef, client *Client) (err error) { From 0ca2aff7edc7373c4f48b511c09fb009b1575f78 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 23 Mar 2023 15:22:15 +0000 Subject: [PATCH 103/120] feat: add func for checking if a key exists in an `[]interface{map[string]interface{}}` --- proxmox/util.go | 11 +++++++++++ proxmox/util_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/proxmox/util.go b/proxmox/util.go index 253fa4ea..f1c4fcfe 100644 --- a/proxmox/util.go +++ b/proxmox/util.go @@ -205,6 +205,17 @@ func createHeaderList(header_string string, sess *Session) (*Session, error) { return sess, nil } +// check if a key exists in a nested array of map[string]interface{} +func keyExists(array []interface{}, key string) (existence bool) { + for i := range array { + item := array[i].(map[string]interface{}) + if _, isSet := item[key]; isSet { + return true + } + } + return false +} + func splitStringOfSettings(settings string) (settingArray [][]string) { settingValuePairs := strings.Split(settings, ",") settingArray = make([][]string, len(settingValuePairs)) diff --git a/proxmox/util_test.go b/proxmox/util_test.go index 38b2c45a..db842767 100644 --- a/proxmox/util_test.go +++ b/proxmox/util_test.go @@ -6,6 +6,52 @@ import ( "github.com/stretchr/testify/require" ) +func Test_keyExists(t *testing.T) { + tests := []struct { + name string + input []interface{} + key string + output bool + }{ + {name: "key empty", + input: []interface{}{ + map[string]interface{}{"aaa": "", "bbb": "", "ccc": ""}, + map[string]interface{}{"aab": "", "bba": "", "cca": ""}, + map[string]interface{}{"aac": "", "bbc": "", "ccb": ""}, + }, + }, + {name: "Key in map", + input: []interface{}{ + map[string]interface{}{"aaa": "", "bbb": "", "ccc": ""}, + map[string]interface{}{"aab": "", "bba": "", "cca": ""}, + map[string]interface{}{"aac": "", "bbc": "", "ccb": ""}, + }, + key: "bba", + output: true, + }, + {name: "Key not in map", + input: []interface{}{ + map[string]interface{}{"aaa": "", "bbb": "", "ccc": ""}, + map[string]interface{}{"aab": "", "bba": "", "cca": ""}, + map[string]interface{}{"aac": "", "bbc": "", "ccb": ""}, + }, + key: "ddd", + }, + {name: "no array", + key: "aaa", + }, + {name: "no keys", + input: []interface{}{map[string]interface{}{}}, + key: "aaa", + }, + } + for _, test := range tests { + t.Run(test.name, func(*testing.T) { + require.Equal(t, test.output, keyExists(test.input, test.key), test.name) + }) + } +} + func Test_splitStringOfSettings(t *testing.T) { testData := []struct { Input string From 0304fcc85d81977933d7eb615e5db1a6a85a3912 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Fri, 24 Mar 2023 11:21:02 +0000 Subject: [PATCH 104/120] feat: check if the Qemu guest has pending changes, and reboot if allowed --- proxmox/config_guest.go | 37 +++++++++++++++++++++++++++++++++ proxmox/config_qemu.go | 46 +++++++++++++++++++++++++++++++++-------- 2 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 proxmox/config_guest.go diff --git a/proxmox/config_guest.go b/proxmox/config_guest.go new file mode 100644 index 00000000..fc5a0cc8 --- /dev/null +++ b/proxmox/config_guest.go @@ -0,0 +1,37 @@ +package proxmox + +import ( + "strconv" +) + +// All code LXC and Qemu have in common should be placed here. + +// Check if there are any pending changes that require a reboot to be applied. +func GuestHasPendingChanges(vmr *VmRef, client *Client) (bool, error) { + params, err := pendingGuestConfigFromApi(vmr, client) + if err != nil { + return false, err + } + return keyExists(params, "pending"), nil +} + +// Reboot the specified guest +func GuestReboot(vmr *VmRef, client *Client) (err error) { + _, err = client.ShutdownVm(vmr) + if err != nil { + return + } + _, err = client.StartVm(vmr) + return +} + +func pendingGuestConfigFromApi(vmr *VmRef, client *Client) ([]interface{}, error) { + err := vmr.nilCheck() + if err != nil { + return nil, err + } + if err = client.CheckVmRef(vmr); err != nil { + return nil, err + } + return client.GetItemConfigInterfaceArray("/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/pending", "Guest", "PENDING CONFIG") +} diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 6805c95a..df835b1c 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -88,8 +88,9 @@ type ConfigQemu struct { } // Create - Tell Proxmox API to make the VM -func (config ConfigQemu) Create(vmr *VmRef, client *Client) error { - return config.SetAdvanced(nil, vmr, client) +func (config ConfigQemu) Create(vmr *VmRef, client *Client) (err error) { + _, err = config.SetAdvanced(nil, false, vmr, client) + return } // DEPRECATED use ConfigQemu{}.Create Instead. @@ -677,12 +678,12 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (*ConfigQemu, error return &config, nil } -func (newConfig ConfigQemu) Update(vmr *VmRef, client *Client) (err error) { +func (newConfig ConfigQemu) Update(rebootIfNeeded bool, vmr *VmRef, client *Client) (rebootRequired bool, err error) { currentConfig, err := NewConfigQemuFromApi(vmr, client) if err != nil { return } - return newConfig.SetAdvanced(currentConfig, vmr, client) + return newConfig.SetAdvanced(currentConfig, rebootIfNeeded, vmr, client) } func (config *ConfigQemu) setVmr(vmr *VmRef) (err error) { @@ -697,7 +698,7 @@ func (config *ConfigQemu) setVmr(vmr *VmRef) (err error) { return } -func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, vmr *VmRef, client *Client) (err error) { +func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, rebootIfNeeded bool, vmr *VmRef, client *Client) (rebootRequired bool, err error) { err = newConfig.setVmr(vmr) if err != nil { return @@ -730,6 +731,19 @@ func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, vmr *VmRef, c } // Moving disks changes the disk id. we need to get the config again if any disk was moved if len(markedDisks.Move) != 0 { + // We also need to check if there are pending changes + rebootRequired, err = GuestHasPendingChanges(vmr, client) + if err != nil { + return + } + if rebootRequired && rebootIfNeeded { + if err = GuestReboot(vmr, client); err != nil { + return + } + rebootRequired = false + } else { + return true, fmt.Errorf("unable to proceed with configuring vm: %d, a reboot is required", vmr.vmId) + } currentConfig, err = NewConfigQemuFromApi(vmr, client) if err != nil { return @@ -752,6 +766,21 @@ func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, vmr *VmRef, c return } exitStatus, err = client.PutWithTask(params, "/nodes/"+vmr.node+"/"+vmr.vmType+"/"+strconv.Itoa(vmr.vmId)+"/config") + if err != nil { + return false, fmt.Errorf("error updating VM: %v, error status: %s (params: %v)", err, exitStatus, params) + } + + rebootRequired, err = GuestHasPendingChanges(vmr, client) + if err != nil { + return + } + + if rebootRequired && rebootIfNeeded { + if err = GuestReboot(vmr, client); err != nil { + return + } + rebootRequired = false + } } else { // Create @@ -760,10 +789,9 @@ func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, vmr *VmRef, c return } exitStatus, err = client.CreateQemuVm(vmr.node, params) - } - - if err != nil { - return fmt.Errorf("error creating VM: %v, error status: %s (params: %v)", err, exitStatus, params) + if err != nil { + return false, fmt.Errorf("error creating VM: %v, error status: %s (params: %v)", err, exitStatus, params) + } } _, err = client.UpdateVMHA(vmr, newConfig.HaState, newConfig.HaGroup) From 9bc03938ed907ebc0e4268f6c3b5e42e47b1c464 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Fri, 24 Mar 2023 11:42:19 +0000 Subject: [PATCH 105/120] refactor: disks can be enlarged while QemuGuest is live --- proxmox/config_qemu.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index df835b1c..12a97b6f 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -731,19 +731,6 @@ func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, rebootIfNeede } // Moving disks changes the disk id. we need to get the config again if any disk was moved if len(markedDisks.Move) != 0 { - // We also need to check if there are pending changes - rebootRequired, err = GuestHasPendingChanges(vmr, client) - if err != nil { - return - } - if rebootRequired && rebootIfNeeded { - if err = GuestReboot(vmr, client); err != nil { - return - } - rebootRequired = false - } else { - return true, fmt.Errorf("unable to proceed with configuring vm: %d, a reboot is required", vmr.vmId) - } currentConfig, err = NewConfigQemuFromApi(vmr, client) if err != nil { return From 54467a697ec9b6a6798829d1861a5939afb34f97 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Fri, 24 Mar 2023 11:53:08 +0000 Subject: [PATCH 106/120] Add TODO for CloudInit and basic logic --- proxmox/config_qemu.go | 18 ++++++++++-------- proxmox/config_qemu_test.go | 4 +++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 12a97b6f..0c4d1a23 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -105,7 +105,7 @@ func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { if err != nil { return } - params, err := config.mapToApiValues(ConfigQemu{}) + _, params, err := config.mapToApiValues(ConfigQemu{}) if err != nil { return } @@ -190,8 +190,8 @@ func (config *ConfigQemu) defaults() { } -func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (params map[string]interface{}, err error) { - +func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (rebootRequired bool, params map[string]interface{}, err error) { + // TODO check if cloudInit settings changed, they require a reboot to take effect. var itemsToDelete string params = map[string]interface{}{} @@ -748,7 +748,7 @@ func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, rebootIfNeede vmr.SetNode(newConfig.Node) } - params, err = newConfig.mapToApiValues(*currentConfig) + rebootRequired, params, err = newConfig.mapToApiValues(*currentConfig) if err != nil { return } @@ -757,9 +757,11 @@ func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, rebootIfNeede return false, fmt.Errorf("error updating VM: %v, error status: %s (params: %v)", err, exitStatus, params) } - rebootRequired, err = GuestHasPendingChanges(vmr, client) - if err != nil { - return + if !rebootRequired { + rebootRequired, err = GuestHasPendingChanges(vmr, client) + if err != nil { + return + } } if rebootRequired && rebootIfNeeded { @@ -771,7 +773,7 @@ func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, rebootIfNeede } else { // Create - params, err = newConfig.mapToApiValues(ConfigQemu{}) + _, params, err = newConfig.mapToApiValues(ConfigQemu{}) if err != nil { return } diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index 8f653729..1b9bff94 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -28,6 +28,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { name string config *ConfigQemu currentConfig ConfigQemu + reboot bool vmr *VmRef output map[string]interface{} }{ @@ -1794,8 +1795,9 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(*testing.T) { - tmpParams, _ := test.config.mapToApiValues(test.currentConfig) + reboot, tmpParams, _ := test.config.mapToApiValues(test.currentConfig) require.Equal(t, test.output, tmpParams, test.name) + require.Equal(t, test.reboot, reboot, test.name) }) } } From 36cb3b689bd73254845ba2f12b3675a6ba553fef Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sat, 25 Mar 2023 20:02:30 +0000 Subject: [PATCH 107/120] fix: panic --- proxmox/config_qemu.go | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 0c4d1a23..1efe307d 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -713,27 +713,28 @@ func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, rebootIfNeede if currentConfig != nil { // Update - - markedDisks := newConfig.Disks.markDiskChanges(*currentConfig.Disks) - // move disk to different storage or change disk format - for _, e := range markedDisks.Move { - _, err = e.move(true, vmr, client) - if err != nil { - return + if newConfig.Disks != nil && currentConfig.Disks != nil { + markedDisks := newConfig.Disks.markDiskChanges(*currentConfig.Disks) + // move disk to different storage or change disk format + for _, e := range markedDisks.Move { + _, err = e.move(true, vmr, client) + if err != nil { + return + } } - } - // increase Disks in size - for _, e := range markedDisks.Resize { - _, err = e.resize(vmr, client) - if err != nil { - return + // increase Disks in size + for _, e := range markedDisks.Resize { + _, err = e.resize(vmr, client) + if err != nil { + return + } } - } - // Moving disks changes the disk id. we need to get the config again if any disk was moved - if len(markedDisks.Move) != 0 { - currentConfig, err = NewConfigQemuFromApi(vmr, client) - if err != nil { - return + // Moving disks changes the disk id. we need to get the config again if any disk was moved + if len(markedDisks.Move) != 0 { + currentConfig, err = NewConfigQemuFromApi(vmr, client) + if err != nil { + return + } } } From af6fde359a77ee8dcdd422c063ff7e4865a27a0f Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 27 Mar 2023 20:44:49 +0000 Subject: [PATCH 108/120] feat: add support for linked clones --- proxmox/config_qemu_disk.go | 81 +++-- proxmox/config_qemu_disk_ide.go | 79 ++--- proxmox/config_qemu_disk_sata.go | 79 ++--- proxmox/config_qemu_disk_scsi.go | 91 +++--- proxmox/config_qemu_disk_virtio.go | 85 +++--- proxmox/config_qemu_test.go | 471 +++++++++++++++++++++++++++-- 6 files changed, 671 insertions(+), 215 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 57724459..5b37c4f9 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -184,15 +184,16 @@ type qemuDisk struct { Disk bool // true = disk, false = passthrough EmulateSSD bool // Only set for ide,sata,scsi // TODO custom type - File string // Only set for Passthrough. - Format QemuDiskFormat // Only set for Disk - Id uint // Only set for Disk - IOThread bool // Only set for scsi,virtio - Number uint - ReadOnly bool // Only set for scsi,virtio - Replicate bool - Serial QemuDiskSerial - Size uint + File string // Only set for Passthrough. + Format QemuDiskFormat // Only set for Disk + Id uint // Only set for Disk + IOThread bool // Only set for scsi,virtio + LinkedClone *QemuDiskLinkedClone // Only set for Disk + Number uint + ReadOnly bool // Only set for scsi,virtio + Replicate bool + Serial QemuDiskSerial + Size uint // TODO custom type Storage string // Only set for Disk Type qemuDiskType @@ -205,14 +206,20 @@ const ( Error_QemuDisk_Storage string = "storage may not be empty" ) -func (disk qemuDisk) mapToApiValues(vmID uint, create bool) (settings string) { +func (disk qemuDisk) mapToApiValues(vmID uint, currentStorage string, currentFormat QemuDiskFormat, create bool) (settings string) { if disk.Storage != "" { if create { settings = disk.Storage + ":" + strconv.Itoa(int(disk.Size)) } else { - // test:100/vm-100-disk-0.raw tmpId := strconv.Itoa(int(vmID)) - settings = disk.Storage + ":" + tmpId + "/vm-" + tmpId + "-disk-" + strconv.Itoa(int(disk.Id)) + "." + string(disk.Format) + settings = tmpId + "/vm-" + tmpId + "-disk-" + strconv.Itoa(int(disk.Id)) + "." + string(disk.Format) + // storage:100/vm-100-disk-0.raw + if disk.LinkedClone != nil && disk.Storage == currentStorage && disk.Format == currentFormat { + // storage:110/base-110-disk-1.raw/100/vm-100-disk-0.raw + tmpId = strconv.Itoa(int(disk.LinkedClone.VmId)) + settings = tmpId + "/base-" + tmpId + "-disk-" + strconv.Itoa(int(disk.LinkedClone.DiskId)) + "." + string(disk.Format) + "/" + settings + } + settings = disk.Storage + ":" + settings } } @@ -294,17 +301,33 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { if settings[0][0][0:1] == "/" { disk.File = settings[0][0] } else { - // "test2:105/vm-105-disk-53.qcow2, - diskAndNumberAndFormat := strings.Split(settings[0][0], ":") - disk.Storage = diskAndNumberAndFormat[0] - if len(diskAndNumberAndFormat) == 2 { - idAndFormat := strings.Split(diskAndNumberAndFormat[1], ".") - if len(idAndFormat) == 2 { - disk.Format = QemuDiskFormat(idAndFormat[1]) - tmp := strings.Split(idAndFormat[0], "-") + // storage:110/base-110-disk-1.qcow2/100/vm-100-disk-0.qcow2, + // storage:100/vm-100-disk-0.qcow2, + diskAndPath := strings.Split(settings[0][0], ":") + disk.Storage = diskAndPath[0] + if len(diskAndPath) == 2 { + pathParts := strings.Split(diskAndPath[1], "/") + if len(pathParts) == 4 { + var tmpDiskId int + tmpVmId, _ := strconv.Atoi(pathParts[0]) + tmp := strings.Split(strings.Split(pathParts[1], ".")[0], "-") if len(tmp) > 1 { - tmpId, _ := strconv.Atoi(tmp[len(tmp)-1]) - disk.Id = uint(tmpId) + tmpDiskId, _ = strconv.Atoi(tmp[len(tmp)-1]) + } + disk.LinkedClone = &QemuDiskLinkedClone{ + VmId: uint(tmpVmId), + DiskId: uint(tmpDiskId), + } + } + if len(pathParts) > 1 { + diskNameAndFormat := strings.Split(pathParts[len(pathParts)-1], ".") + if len(diskNameAndFormat) == 2 { + disk.Format = QemuDiskFormat(diskNameAndFormat[1]) + tmp := strings.Split(diskNameAndFormat[0], "-") + if len(tmp) > 1 { + tmpDiskId, _ := strconv.Atoi(tmp[len(tmp)-1]) + disk.Id = uint(tmpDiskId) + } } } } @@ -672,6 +695,11 @@ func (id QemuDiskId) Validate() error { return errors.New(ERROR_QemuDiskId_Invalid) } +type QemuDiskLinkedClone struct { + DiskId uint `json:"disk"` + VmId uint `json:"vm"` +} + type qemuDiskMark struct { Format QemuDiskFormat Id QemuDiskId @@ -814,17 +842,18 @@ func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID uin if storage.Disk != nil { if currentStorage == nil || currentStorage.Disk == nil { // Create - params[string(id)] = storage.Disk.mapToApiValues(vmID, true) + params[string(id)] = storage.Disk.mapToApiValues(vmID, "", "", true) return delete } else { if storage.Disk.Size >= currentStorage.Disk.Size { // Update storage.Disk.Id = currentStorage.Disk.Id - params[string(id)] = storage.Disk.mapToApiValues(vmID, false) + storage.Disk.LinkedClone = currentStorage.Disk.LinkedClone + params[string(id)] = storage.Disk.mapToApiValues(vmID, currentStorage.Disk.Storage, currentStorage.Disk.Format, false) } else { // Delete and Create // creating a disk on top of an existing disk is the same as detaching the disk and creating a new one. - params[string(id)] = storage.Disk.mapToApiValues(vmID, true) + params[string(id)] = storage.Disk.mapToApiValues(vmID, "", "", true) } return delete } @@ -835,7 +864,7 @@ func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID uin // Passthrough if storage.Passthrough != nil { // Create or Update - params[string(id)] = storage.Passthrough.mapToApiValues(0, false) + params[string(id)] = storage.Passthrough.mapToApiValues(0, "", "", false) return delete } else if currentStorage != nil && currentStorage.Passthrough != nil { // Delete diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 8149eada..b7dd1eb8 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -3,36 +3,38 @@ package proxmox import "strconv" type QemuIdeDisk struct { - AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup"` - Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` - Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard"` - EmulateSSD bool `json:"emulatessd"` - Format QemuDiskFormat `json:"format"` - Id uint `json:"id"` //Id is only returned and setting it has no effect - Replicate bool `json:"replicate"` - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size"` - Storage string `json:"storage"` + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + Format QemuDiskFormat `json:"format"` + Id uint `json:"id"` //Id is only returned and setting it has no effect + LinkedClone *QemuDiskLinkedClone `json:"linked"` //LinkedClone is only returned and setting it has no effect + Replicate bool `json:"replicate"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuIdeDisk) convertDataStructure() *qemuDisk { return &qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - Disk: true, - EmulateSSD: disk.EmulateSSD, - Format: disk.Format, - Id: disk.Id, - Replicate: disk.Replicate, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: ide, + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + Disk: true, + EmulateSSD: disk.EmulateSSD, + Format: disk.Format, + Id: disk.Id, + LinkedClone: disk.LinkedClone, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: ide, } } @@ -219,18 +221,19 @@ func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { } if tmpDisk.File == "" { return &QemuIdeStorage{Disk: &QemuIdeDisk{ - AsyncIO: tmpDisk.AsyncIO, - Backup: tmpDisk.Backup, - Bandwidth: tmpDisk.Bandwidth, - Cache: tmpDisk.Cache, - Discard: tmpDisk.Discard, - EmulateSSD: tmpDisk.EmulateSSD, - Format: tmpDisk.Format, - Id: tmpDisk.Id, - Replicate: tmpDisk.Replicate, - Serial: tmpDisk.Serial, - Size: tmpDisk.Size, - Storage: tmpDisk.Storage, + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + Format: tmpDisk.Format, + Id: tmpDisk.Id, + LinkedClone: tmpDisk.LinkedClone, + Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, }} } return &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 6ca552b8..f0f214e0 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -3,36 +3,38 @@ package proxmox import "strconv" type QemuSataDisk struct { - AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup"` - Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` - Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard"` - EmulateSSD bool `json:"emulatessd"` - Format QemuDiskFormat `json:"format"` - Id uint `json:"id"` //Id is only returned and setting it has no effect - Replicate bool `json:"replicate"` - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size"` - Storage string `json:"storage"` + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + Format QemuDiskFormat `json:"format"` + Id uint `json:"id"` //Id is only returned and setting it has no effect + LinkedClone *QemuDiskLinkedClone `json:"linked"` //LinkedClone is only returned and setting it has no effect + Replicate bool `json:"replicate"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuSataDisk) convertDataStructure() *qemuDisk { return &qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - Disk: true, - EmulateSSD: disk.EmulateSSD, - Format: disk.Format, - Id: disk.Id, - Replicate: disk.Replicate, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: sata, + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + Disk: true, + EmulateSSD: disk.EmulateSSD, + Format: disk.Format, + Id: disk.Id, + LinkedClone: disk.LinkedClone, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: sata, } } @@ -231,18 +233,19 @@ func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { } if tmpDisk.File == "" { return &QemuSataStorage{Disk: &QemuSataDisk{ - AsyncIO: tmpDisk.AsyncIO, - Backup: tmpDisk.Backup, - Bandwidth: tmpDisk.Bandwidth, - Cache: tmpDisk.Cache, - Discard: tmpDisk.Discard, - EmulateSSD: tmpDisk.EmulateSSD, - Format: tmpDisk.Format, - Id: tmpDisk.Id, - Replicate: tmpDisk.Replicate, - Serial: tmpDisk.Serial, - Size: tmpDisk.Size, - Storage: tmpDisk.Storage, + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + Format: tmpDisk.Format, + Id: tmpDisk.Id, + LinkedClone: tmpDisk.LinkedClone, + Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, }} } return &QemuSataStorage{Passthrough: &QemuSataPassthrough{ diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 483ab68b..2cc6cb6d 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -3,40 +3,42 @@ package proxmox import "strconv" type QemuScsiDisk struct { - AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup"` - Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` - Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard"` - EmulateSSD bool `json:"emulatessd"` - Format QemuDiskFormat `json:"format"` - Id uint `json:"id"` //Id is only returned and setting it has no effect - IOThread bool `json:"iothread"` - ReadOnly bool `json:"readonly"` - Replicate bool `json:"replicate"` - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size"` - Storage string `json:"storage"` + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + Format QemuDiskFormat `json:"format"` + Id uint `json:"id"` //Id is only returned and setting it has no effect + IOThread bool `json:"iothread"` + LinkedClone *QemuDiskLinkedClone `json:"linked"` //LinkedCloneId is only returned and setting it has no effect + ReadOnly bool `json:"readonly"` + Replicate bool `json:"replicate"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuScsiDisk) convertDataStructure() *qemuDisk { return &qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - Disk: true, - EmulateSSD: disk.EmulateSSD, - Format: disk.Format, - Id: disk.Id, - IOThread: disk.IOThread, - ReadOnly: disk.ReadOnly, - Replicate: disk.Replicate, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: scsi, + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + Disk: true, + EmulateSSD: disk.EmulateSSD, + Format: disk.Format, + Id: disk.Id, + IOThread: disk.IOThread, + LinkedClone: disk.LinkedClone, + ReadOnly: disk.ReadOnly, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: scsi, } } @@ -389,20 +391,21 @@ func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { } if tmpDisk.File == "" { return &QemuScsiStorage{Disk: &QemuScsiDisk{ - AsyncIO: tmpDisk.AsyncIO, - Backup: tmpDisk.Backup, - Bandwidth: tmpDisk.Bandwidth, - Cache: tmpDisk.Cache, - Discard: tmpDisk.Discard, - EmulateSSD: tmpDisk.EmulateSSD, - Format: tmpDisk.Format, - Id: tmpDisk.Id, - IOThread: tmpDisk.IOThread, - ReadOnly: tmpDisk.ReadOnly, - Replicate: tmpDisk.Replicate, - Serial: tmpDisk.Serial, - Size: tmpDisk.Size, - Storage: tmpDisk.Storage, + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + Format: tmpDisk.Format, + Id: tmpDisk.Id, + IOThread: tmpDisk.IOThread, + LinkedClone: tmpDisk.LinkedClone, + ReadOnly: tmpDisk.ReadOnly, + Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, }} } return &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index a55f45b9..4fd8c273 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -3,38 +3,40 @@ package proxmox import "strconv" type QemuVirtIODisk struct { - AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup"` - Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` - Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard"` - Format QemuDiskFormat `json:"format"` - Id uint `json:"id"` //Id is only returned and setting it has no effect - IOThread bool `json:"iothread"` - ReadOnly bool `json:"readonly"` - Replicate bool `json:"replicate"` - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size"` - Storage string `json:"storage"` + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + Format QemuDiskFormat `json:"format"` + Id uint `json:"id"` //Id is only returned and setting it has no effect + IOThread bool `json:"iothread"` + LinkedClone *QemuDiskLinkedClone `json:"linked"` //LinkedCloneId is only returned and setting it has no effect + ReadOnly bool `json:"readonly"` + Replicate bool `json:"replicate"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuVirtIODisk) convertDataStructure() *qemuDisk { return &qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - Disk: true, - Format: disk.Format, - Id: disk.Id, - IOThread: disk.IOThread, - ReadOnly: disk.ReadOnly, - Replicate: disk.Replicate, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: virtIO, + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + Disk: true, + Format: disk.Format, + Id: disk.Id, + IOThread: disk.IOThread, + LinkedClone: disk.LinkedClone, + ReadOnly: disk.ReadOnly, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: virtIO, } } @@ -295,19 +297,20 @@ func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { } if tmpDisk.File == "" { return &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ - AsyncIO: tmpDisk.AsyncIO, - Backup: tmpDisk.Backup, - Bandwidth: tmpDisk.Bandwidth, - Cache: tmpDisk.Cache, - Discard: tmpDisk.Discard, - Format: tmpDisk.Format, - Id: tmpDisk.Id, - IOThread: tmpDisk.IOThread, - ReadOnly: tmpDisk.ReadOnly, - Replicate: tmpDisk.Replicate, - Serial: tmpDisk.Serial, - Size: tmpDisk.Size, - Storage: tmpDisk.Storage, + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + Format: tmpDisk.Format, + Id: tmpDisk.Id, + IOThread: tmpDisk.IOThread, + LinkedClone: tmpDisk.LinkedClone, + ReadOnly: tmpDisk.ReadOnly, + Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, }} } return &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index 1b9bff94..9d3521f6 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -1197,12 +1197,28 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ AsyncIO: QemuDiskAsyncIO_Native, Format: QemuDiskFormat_Raw, - Id: 23, Size: 10, Storage: "test", }}}}}, output: map[string]interface{}{"ide3": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, }, + {name: "Update Disk.Ide.Disk_X.Disk CHANGE LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Format: QemuDiskFormat_Raw, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"ide3": "test:100/base-100-disk-1.raw/0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, + }, {name: "Update Disk.Ide.Disk_X.Disk DELETE", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: ideBase}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{}}}}, @@ -1217,7 +1233,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Raw, - Id: 23, + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"ide1": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk MIGRATE LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{DiskId: 1, VmId: 100}, + Size: 10, + Storage: "test1", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, Size: 10, Storage: "test2", }}}}}, @@ -1232,7 +1262,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Raw, - Id: 23, + Size: 9, + Storage: "test", + }}}}}, + output: map[string]interface{}{"ide2": "test:9,backup=0,format=raw,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk RESIZE DOWN LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, Size: 9, Storage: "test", }}}}}, @@ -1247,16 +1291,34 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Raw, - Id: 23, Size: 11, Storage: "test", }}}}}, output: map[string]interface{}{"ide3": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, + {name: "Update Disk.Ide.Disk_X.Disk RESIZE UP LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 110, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{"ide3": "test:110/base-110-disk-1.raw/0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, {name: "Update Disk.Ide.Disk_X.Disk SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: ideBase}}}, - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: ideBase}}}, - output: map[string]interface{}{"ide0": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"ide0": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, {name: "Update Disk.Ide.Disk_X.Disk.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -1267,7 +1329,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Qcow2, - Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"ide1": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk.Format CHANGE LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Qcow2, Size: 10, Storage: "test", }}}}}, @@ -1363,12 +1439,28 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ AsyncIO: QemuDiskAsyncIO_Native, Format: QemuDiskFormat_Raw, - Id: 23, Size: 10, Storage: "test", }}}}}, output: map[string]interface{}{"sata3": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, }, + {name: "Update Disk.Sata.Disk_X.Disk CHANGE LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Format: QemuDiskFormat_Raw, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata3": "test:100/base-100-disk-1.raw/0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, + }, {name: "Update Disk.Sata.Disk_X.Disk DELETE", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: sataBase}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{}}}}, @@ -1383,7 +1475,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Raw, - Id: 23, + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"sata5": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk MIGRATE LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{DiskId: 1, VmId: 100}, + Size: 10, + Storage: "test1", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, Size: 10, Storage: "test2", }}}}}, @@ -1398,7 +1504,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Raw, - Id: 23, + Size: 9, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata0": "test:9,backup=0,format=raw,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk RESIZE DOWN LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, Size: 9, Storage: "test", }}}}}, @@ -1413,16 +1533,34 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Raw, - Id: 23, Size: 11, Storage: "test", }}}}}, output: map[string]interface{}{"sata1": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, + {name: "Update Disk.Sata.Disk_X.Disk RESIZE UP LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata1": "test:100/base-100-disk-1.raw/0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, {name: "Update Disk.Sata.Disk_X.Disk SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: sataBase}}}, - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: sataBase}}}, - output: map[string]interface{}{"sata2": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata2": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, {name: "Update Disk.Sata.Disk_X.Disk.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -1433,7 +1571,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Qcow2, - Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata3": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk.Format CHANGE LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Qcow2, Size: 10, Storage: "test", }}}}}, @@ -1529,12 +1681,28 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ AsyncIO: QemuDiskAsyncIO_Native, Format: QemuDiskFormat_Raw, - Id: 23, Size: 10, Storage: "test", }}}}}, output: map[string]interface{}{"scsi15": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, }, + {name: "Update Disk.Scsi.Disk_X.Disk CHANGE LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Format: QemuDiskFormat_Raw, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"scsi15": "test:100/base-100-disk-1.raw/0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, + }, {name: "Update Disk.Scsi.Disk_X.Disk DELETE", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: scsiBase}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: &QemuScsiStorage{}}}}, @@ -1549,7 +1717,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, - Id: 23, + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"scsi17": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk MIGRATE Linked Clone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{DiskId: 1, VmId: 100}, + Size: 10, + Storage: "test1", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, Size: 10, Storage: "test2", }}}}}, @@ -1564,7 +1746,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, - Id: 23, + Size: 9, + Storage: "test", + }}}}}, + output: map[string]interface{}{"scsi18": "test:9,backup=0,format=raw,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk RESIZE DOWN LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, Size: 9, Storage: "test", }}}}}, @@ -1579,16 +1775,34 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, - Id: 23, Size: 11, Storage: "test", }}}}}, output: map[string]interface{}{"scsi19": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, + {name: "Update Disk.Scsi.Disk_X.Disk RESIZE UP LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{"scsi19": "test:100/base-100-disk-1.raw/0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, {name: "Update Disk.Scsi.Disk_X.Disk SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_20: scsiBase}}}, - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_20: scsiBase}}}, - output: map[string]interface{}{"scsi20": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_20: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"scsi20": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, {name: "Update Disk.Scsi.Disk_X.Disk.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -1599,7 +1813,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Qcow2, - Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"scsi21": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk.Format CHANGE LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Qcow2, Size: 10, Storage: "test", }}}}}, @@ -1695,12 +1923,28 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ AsyncIO: QemuDiskAsyncIO_Native, Format: QemuDiskFormat_Raw, - Id: 23, Size: 10, Storage: "test", }}}}}, output: map[string]interface{}{"virtio15": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, }, + {name: "Update Disk.VirtIO.Disk_X.Disk CHANGE LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Format: QemuDiskFormat_Raw, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"virtio15": "test:100/base-100-disk-1.raw/0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, + }, {name: "Update Disk.VirtIO.Disk_X.Disk DELETE", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: virtioBase}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{}}}}, @@ -1715,7 +1959,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Raw, - Id: 23, + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"virtio1": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk MIGRATE LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{DiskId: 1, VmId: 100}, + Size: 10, + Storage: "test1", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, Size: 10, Storage: "test2", }}}}}, @@ -1730,7 +1988,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Raw, - Id: 23, + Size: 9, + Storage: "test", + }}}}}, + output: map[string]interface{}{"virtio2": "test:9,backup=0,format=raw,replicate=0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE DOWN LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, Size: 9, Storage: "test", }}}}}, @@ -1745,16 +2017,34 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Raw, - Id: 23, Size: 11, Storage: "test", }}}}}, output: map[string]interface{}{"virtio3": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, + {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE UP LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{"virtio3": "test:100/base-100-disk-1.raw/0/vm-0-disk-23.raw,backup=0,replicate=0"}, + }, {name: "Update Disk.VirtIO.Disk_X.Disk SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: virtioBase}}}, - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: virtioBase}}}, - output: map[string]interface{}{"virtio4": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"virtio4": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, {name: "Update Disk.VirtIO.Disk_X.Disk.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ @@ -1765,7 +2055,21 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Qcow2, - Id: 23, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"virtio5": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk.Format CHANGE LinkedClone", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Qcow2, Size: 10, Storage: "test", }}}}}, @@ -1876,6 +2180,33 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Ide Disk ALL LinkedClone", + input: map[string]interface{}{"ide1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-53.qcow2,aio=io_uring,backup=0,cache=writethrough,discard=on,iops_rd=12,iops_rd_max=13,iops_wr=15,iops_wr_max=14,mbps_rd=1.46,mbps_rd_max=3.57,mbps_wr=2.68,mbps_wr_max=4.55,replicate=0,serial=disk-9763,size=1032G,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.57, Concurrent: 1.46}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.55, Concurrent: 2.68}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 12}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 14, Concurrent: 15}, + }, + }, + Cache: QemuDiskCache_WriteThrough, + Discard: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: uint53, + LinkedClone: &QemuDiskLinkedClone{VmId: 110, DiskId: 1}, + Replicate: false, + Serial: "disk-9763", + Size: 1032, + Storage: "test2", + }}}}}, + }, {name: "Disks Ide Disk aio", input: map[string]interface{}{"ide2": "test2:100/vm-100-disk-53.qcow2,aio=io_uring"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -2287,6 +2618,33 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Sata Disk ALL LinkedClone", + input: map[string]interface{}{"sata1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-47.qcow2,aio=native,backup=0,cache=none,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=32G,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + }, + }, + Cache: QemuDiskCache_None, + Discard: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: uint47, + LinkedClone: &QemuDiskLinkedClone{VmId: 110, DiskId: 1}, + Replicate: false, + Serial: "disk-9763", + Size: 32, + Storage: "test2", + }}}}}, + }, {name: "Disks Sata Disk aio", input: map[string]interface{}{"sata2": "test2:100/vm-100-disk-47.qcow2,aio=native"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -2704,6 +3062,35 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test", }}}}}, }, + {name: "Disks Scsi Disk ALL LinkedClone", + input: map[string]interface{}{"scsi1": "test:110/base-110-disk-1.qcow2/100/vm-100-disk-2.qcow2,aio=threads,backup=0,cache=writeback,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G,ssd=1"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + }, + }, + Cache: QemuDiskCache_WriteBack, + Discard: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: uint2, + IOThread: true, + LinkedClone: &QemuDiskLinkedClone{VmId: 110, DiskId: 1}, + ReadOnly: true, + Replicate: false, + Serial: "disk-9763", + Size: 32, + Storage: "test", + }}}}}, + }, {name: "Disks Scsi Disk aio", input: map[string]interface{}{"scsi2": "test:100/vm-100-disk-2.qcow2,aio=threads"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -3158,6 +3545,34 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks VirtIO Disk ALL LinkedClone", + input: map[string]interface{}{"virtio1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-31.qcow2,aio=io_uring,backup=0,cache=directsync,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + Data: QemuDiskBandwidthData{ + ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + }, + }, + Cache: QemuDiskCache_DirectSync, + Discard: true, + Format: QemuDiskFormat_Qcow2, + Id: uint31, + IOThread: true, + LinkedClone: &QemuDiskLinkedClone{VmId: 110, DiskId: 1}, + ReadOnly: true, + Replicate: false, + Serial: "disk-9763", + Size: 32, + Storage: "test2", + }}}}}, + }, {name: "Disks VirtIO Disk aio", input: map[string]interface{}{"virtio2": "test2:100/vm-100-disk-31.qcow2,aio=io_uring"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ From 56d99519d14ca47bc84d22c760dd0ac535ddce77 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 2 Apr 2023 17:58:57 +0000 Subject: [PATCH 109/120] refactor: remove unused option --- proxmox/config_qemu_disk.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 5b37c4f9..feed3f62 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -189,8 +189,7 @@ type qemuDisk struct { Id uint // Only set for Disk IOThread bool // Only set for scsi,virtio LinkedClone *QemuDiskLinkedClone // Only set for Disk - Number uint - ReadOnly bool // Only set for scsi,virtio + ReadOnly bool // Only set for scsi,virtio Replicate bool Serial QemuDiskSerial Size uint From 0de34f70b21eb8304e7bbaa621c02e45f431e2d0 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Sun, 2 Apr 2023 18:36:14 +0000 Subject: [PATCH 110/120] fix: disks get updated when nothing changes disks getting updated when nothing changes, adds the current state to the pending state. --- proxmox/config_qemu_disk.go | 44 ++++++++++--- proxmox/config_qemu_test.go | 120 ++++++++++++++++++++++++++++++------ 2 files changed, 135 insertions(+), 29 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index feed3f62..7579e125 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -821,8 +821,16 @@ func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID uin } // CDROM if storage.CdRom != nil { - // Create or Update - params[string(id)] = storage.CdRom.mapToApiValues() + if currentStorage == nil || currentStorage.CdRom == nil { + // Create + params[string(id)] = storage.CdRom.mapToApiValues() + } else { + // Update + cdRom := storage.CdRom.mapToApiValues() + if cdRom != currentStorage.CdRom.mapToApiValues() { + params[string(id)] = cdRom + } + } return delete } else if currentStorage != nil && currentStorage.CdRom != nil && storage.CloudInit == nil && storage.Disk == nil && storage.Passthrough == nil { // Delete @@ -830,8 +838,16 @@ func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID uin } // CloudInit if storage.CloudInit != nil { - // Create or Update - params[string(id)] = storage.CloudInit.mapToApiValues() + if currentStorage == nil || currentStorage.CloudInit == nil { + // Create + params[string(id)] = storage.CloudInit.mapToApiValues() + } else { + // Update + cloudInit := storage.CloudInit.mapToApiValues() + if cloudInit != currentStorage.CloudInit.mapToApiValues() { + params[string(id)] = cloudInit + } + } return delete } else if currentStorage != nil && currentStorage.CloudInit != nil && storage.Disk == nil && storage.Passthrough == nil { // Delete @@ -842,28 +858,38 @@ func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID uin if currentStorage == nil || currentStorage.Disk == nil { // Create params[string(id)] = storage.Disk.mapToApiValues(vmID, "", "", true) - return delete } else { if storage.Disk.Size >= currentStorage.Disk.Size { // Update storage.Disk.Id = currentStorage.Disk.Id storage.Disk.LinkedClone = currentStorage.Disk.LinkedClone - params[string(id)] = storage.Disk.mapToApiValues(vmID, currentStorage.Disk.Storage, currentStorage.Disk.Format, false) + disk := storage.Disk.mapToApiValues(vmID, currentStorage.Disk.Storage, currentStorage.Disk.Format, false) + if disk != currentStorage.Disk.mapToApiValues(vmID, currentStorage.Disk.Storage, currentStorage.Disk.Format, false) { + params[string(id)] = disk + } } else { // Delete and Create // creating a disk on top of an existing disk is the same as detaching the disk and creating a new one. params[string(id)] = storage.Disk.mapToApiValues(vmID, "", "", true) } - return delete } + return delete } else if currentStorage != nil && currentStorage.Disk != nil && storage.Passthrough == nil { // Delete return AddToList(delete, string(id)) } // Passthrough if storage.Passthrough != nil { - // Create or Update - params[string(id)] = storage.Passthrough.mapToApiValues(0, "", "", false) + if currentStorage == nil || currentStorage.Passthrough == nil { + // Create + params[string(id)] = storage.Passthrough.mapToApiValues(0, "", "", false) + } else { + // Update + passthrough := storage.Passthrough.mapToApiValues(0, "", "", false) + if passthrough != currentStorage.Passthrough.mapToApiValues(0, "", "", false) { + params[string(id)] = passthrough + } + } return delete } else if currentStorage != nil && currentStorage.Passthrough != nil { // Delete diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index 9d3521f6..c091c125 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -1152,7 +1152,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { {name: "Update Disk.Ide.Disk_X.CdRom SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, - output: map[string]interface{}{"ide0": "cdrom,media=cdrom"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Ide.Disk_X.CdRom.Iso.File CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, @@ -1173,7 +1173,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { {name: "Update Disk.Ide.Disk_X.CloudInit SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CloudInit: update_CloudInit}}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{CloudInit: update_CloudInit}}}}, - output: map[string]interface{}{"ide0": "test:cloudinit,format=raw"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Ide.Disk_X.CloudInit.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, @@ -1294,7 +1294,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 11, Storage: "test", }}}}}, - output: map[string]interface{}{"ide3": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Ide.Disk_X.Disk RESIZE UP LinkedClone", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -1309,7 +1309,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 11, Storage: "test", }}}}}, - output: map[string]interface{}{"ide3": "test:110/base-110-disk-1.raw/0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Ide.Disk_X.Disk SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: ideBase}}}, @@ -1318,7 +1318,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 10, Storage: "test", }}}}}, - output: map[string]interface{}{"ide0": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Ide.Disk_X.Disk.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -1349,6 +1349,26 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{"ide1": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, }, + // Update Disk.Ide.Disk_X.Passthrough + {name: "Update Disk.Ide.Disk_X.Passthrough CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + File: "/dev/disk/sda", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + AsyncIO: QemuDiskAsyncIO_Native, + File: "/dev/disk/sda", + }}}}}, + output: map[string]interface{}{"ide0": "/dev/disk/sda,aio=native,backup=0,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Passthrough SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + File: "/dev/disk/sda", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + File: "/dev/disk/sda", + }}}}}, + output: map[string]interface{}{}, + }, // Update Disk.Sata {name: "Update Disk.Sata.Disk_X DELETE", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{}}}}, @@ -1394,7 +1414,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { {name: "Update Disk.Sata.Disk_X.CdRom SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, - output: map[string]interface{}{"sata2": "cdrom,media=cdrom"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Sata.Disk_X.CdRom.Iso.File CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, @@ -1415,7 +1435,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { {name: "Update Disk.Sata.Disk_X.CloudInit SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CloudInit: update_CloudInit}}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{CloudInit: update_CloudInit}}}}, - output: map[string]interface{}{"sata0": "test:cloudinit,format=raw"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Sata.Disk_X.CloudInit.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, @@ -1536,7 +1556,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 11, Storage: "test", }}}}}, - output: map[string]interface{}{"sata1": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Sata.Disk_X.Disk RESIZE UP LinkedClone", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -1551,7 +1571,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 11, Storage: "test", }}}}}, - output: map[string]interface{}{"sata1": "test:100/base-100-disk-1.raw/0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Sata.Disk_X.Disk SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: sataBase}}}, @@ -1560,7 +1580,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 10, Storage: "test", }}}}}, - output: map[string]interface{}{"sata2": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Sata.Disk_X.Disk.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -1591,6 +1611,26 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{"sata3": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, }, + // Update Disk.Sata.Disk_X.Passthrough + {name: "Update Disk.Sata.Disk_X.Passthrough CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + File: "/dev/disk/sda", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + AsyncIO: QemuDiskAsyncIO_Native, + File: "/dev/disk/sda", + }}}}}, + output: map[string]interface{}{"sata0": "/dev/disk/sda,aio=native,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Passthrough SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + File: "/dev/disk/sda", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + File: "/dev/disk/sda", + }}}}}, + output: map[string]interface{}{}, + }, // Update Disk.Scsi {name: "Update Disk.Scsi.Disk_X DELETE", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{}}}}, @@ -1636,7 +1676,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { {name: "Update Disk.Scsi.Disk_X.CdRom SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, - output: map[string]interface{}{"scsi8": "cdrom,media=cdrom"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Scsi.Disk_X.CdRom.Iso.File CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, @@ -1657,7 +1697,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { {name: "Update Disk.Scsi.Disk_X.CloudInit SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{CloudInit: update_CloudInit}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{CloudInit: update_CloudInit}}}}, - output: map[string]interface{}{"scsi12": "test:cloudinit,format=raw"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Scsi.Disk_X.CloudInit.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, @@ -1778,7 +1818,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 11, Storage: "test", }}}}}, - output: map[string]interface{}{"scsi19": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Scsi.Disk_X.Disk RESIZE UP LinkedClone", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -1793,7 +1833,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 11, Storage: "test", }}}}}, - output: map[string]interface{}{"scsi19": "test:100/base-100-disk-1.raw/0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Scsi.Disk_X.Disk SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_20: scsiBase}}}, @@ -1802,7 +1842,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 10, Storage: "test", }}}}}, - output: map[string]interface{}{"scsi20": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.Scsi.Disk_X.Disk.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -1833,6 +1873,26 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{"scsi21": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, }, + // Update Disk.Scsi.Disk_X.Passthrough + {name: "Update Disk.Scsi.Disk_X.Passthrough CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + File: "/dev/disk/sda", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + AsyncIO: QemuDiskAsyncIO_Native, + File: "/dev/disk/sda", + }}}}}, + output: map[string]interface{}{"scsi0": "/dev/disk/sda,aio=native,backup=0,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Passthrough SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + File: "/dev/disk/sda", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + File: "/dev/disk/sda", + }}}}}, + output: map[string]interface{}{}, + }, // Update Disk.VirtIO {name: "Update Disk.VirtIO.Disk_X DELETE", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{}}}}, @@ -1878,7 +1938,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { {name: "Update Disk.VirtIO.Disk_X.CdRom SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{CdRom: &QemuCdRom{Passthrough: true}}}}}, - output: map[string]interface{}{"virtio8": "cdrom,media=cdrom"}, + output: map[string]interface{}{}, }, {name: "Update Disk.VirtIO.Disk_X.CdRom.Iso.File CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{CdRom: &QemuCdRom{Iso: &IsoFile{File: "test.iso", Storage: "Test"}}}}}}, @@ -1899,7 +1959,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { {name: "Update Disk.VirtIO.Disk_X.CloudInit SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{CloudInit: update_CloudInit}}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{CloudInit: update_CloudInit}}}}, - output: map[string]interface{}{"virtio12": "test:cloudinit,format=raw"}, + output: map[string]interface{}{}, }, {name: "Update Disk.VirtIO.Disk_X.CloudInit.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{CloudInit: &QemuCloudInitDisk{Format: format_Raw, Storage: "Test"}}}}}, @@ -2020,7 +2080,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 11, Storage: "test", }}}}}, - output: map[string]interface{}{"virtio3": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE UP LinkedClone", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ @@ -2035,7 +2095,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 11, Storage: "test", }}}}}, - output: map[string]interface{}{"virtio3": "test:100/base-100-disk-1.raw/0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.VirtIO.Disk_X.Disk SAME", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: virtioBase}}}, @@ -2044,7 +2104,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 10, Storage: "test", }}}}}, - output: map[string]interface{}{"virtio4": "test:0/vm-0-disk-23.raw,backup=0,replicate=0"}, + output: map[string]interface{}{}, }, {name: "Update Disk.VirtIO.Disk_X.Disk.Format CHANGE", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ @@ -2075,6 +2135,26 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{"virtio5": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, }, + // Update Disk.VirtIO.Disk_X.Passthrough + {name: "Update Disk.VirtIO.Disk_X.Passthrough CHANGE", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + File: "/dev/disk/sda", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + AsyncIO: QemuDiskAsyncIO_Native, + File: "/dev/disk/sda", + }}}}}, + output: map[string]interface{}{"virtio0": "/dev/disk/sda,aio=native,backup=0,replicate=0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Passthrough SAME", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + File: "/dev/disk/sda", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + File: "/dev/disk/sda", + }}}}}, + output: map[string]interface{}{}, + }, // Update Iso {name: "Update Iso nil", currentConfig: ConfigQemu{Iso: &IsoFile{Storage: "test", File: "file.iso"}}, From d5c4ec3cb93132dafdb688a5079c36febe2dbccc Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 3 Apr 2023 09:34:50 +0000 Subject: [PATCH 111/120] feat: Add setting for iops burst duration --- proxmox/config_qemu_disk.go | 29 ++- proxmox/config_qemu_test.go | 392 ++++++++++++++++++++++++++++-------- 2 files changed, 335 insertions(+), 86 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 7579e125..2fe6bdf7 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -205,6 +205,7 @@ const ( Error_QemuDisk_Storage string = "storage may not be empty" ) +// Maps all the disk related settings to api values proxmox understands. func (disk qemuDisk) mapToApiValues(vmID uint, currentStorage string, currentFormat QemuDiskFormat, create bool) (settings string) { if disk.Storage != "" { if create { @@ -250,12 +251,19 @@ func (disk qemuDisk) mapToApiValues(vmID uint, currentStorage string, currentFor if disk.Bandwidth.Iops.ReadLimit.Burst != 0 { settings = settings + ",iops_rd_max=" + strconv.Itoa(int(disk.Bandwidth.Iops.ReadLimit.Burst)) } + if disk.Bandwidth.Iops.ReadLimit.BurstDuration != 0 { + settings = settings + ",iops_rd_max_length=" + strconv.Itoa(int(disk.Bandwidth.Iops.ReadLimit.BurstDuration)) + } + if disk.Bandwidth.Iops.WriteLimit.Concurrent != 0 { settings = settings + ",iops_wr=" + strconv.Itoa(int(disk.Bandwidth.Iops.WriteLimit.Concurrent)) } if disk.Bandwidth.Iops.WriteLimit.Burst != 0 { settings = settings + ",iops_wr_max=" + strconv.Itoa(int(disk.Bandwidth.Iops.WriteLimit.Burst)) } + if disk.Bandwidth.Iops.WriteLimit.BurstDuration != 0 { + settings = settings + ",iops_wr_max_length=" + strconv.Itoa(int(disk.Bandwidth.Iops.WriteLimit.BurstDuration)) + } if (disk.Type == scsi || disk.Type == virtIO) && disk.IOThread { settings = settings + ",iothread=1" @@ -267,6 +275,7 @@ func (disk qemuDisk) mapToApiValues(vmID uint, currentStorage string, currentFor if disk.Bandwidth.Data.ReadLimit.Burst != 0 { settings = settings + fmt.Sprintf(",mbps_rd_max=%.2f", disk.Bandwidth.Data.ReadLimit.Burst) } + if disk.Bandwidth.Data.WriteLimit.Concurrent != 0 { settings = settings + fmt.Sprintf(",mbps_wr=%.2f", disk.Bandwidth.Data.WriteLimit.Concurrent) } @@ -290,7 +299,7 @@ func (disk qemuDisk) mapToApiValues(vmID uint, currentStorage string, currentFor return } -// Maps all the disk related settings +// Maps all the disk related settings to our own data structure. func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { if len(settings) == 0 { return nil @@ -362,6 +371,10 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { tmp, _ := strconv.Atoi(e[1]) disk.Bandwidth.Iops.ReadLimit.Burst = QemuDiskBandwidthIopsLimitBurst(tmp) } + if e[0] == "iops_rd_max_length" { + tmp, _ := strconv.Atoi(e[1]) + disk.Bandwidth.Iops.ReadLimit.BurstDuration = QemuDiskBandwidthBurstDuration(tmp) + } if e[0] == "iops_wr" { tmp, _ := strconv.Atoi(e[1]) disk.Bandwidth.Iops.WriteLimit.Concurrent = QemuDiskBandwidthIopsLimitConcurrent(tmp) @@ -370,6 +383,10 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { tmp, _ := strconv.Atoi(e[1]) disk.Bandwidth.Iops.WriteLimit.Burst = QemuDiskBandwidthIopsLimitBurst(tmp) } + if e[0] == "iops_wr_max_length" { + tmp, _ := strconv.Atoi(e[1]) + disk.Bandwidth.Iops.WriteLimit.BurstDuration = QemuDiskBandwidthBurstDuration(tmp) + } if e[0] == "iothread" { disk.IOThread, _ = strconv.ParseBool(e[1]) continue @@ -483,6 +500,9 @@ func (bandwidth QemuDiskBandwidth) Validate() error { return bandwidth.Iops.Validate() } +// burst duration in seconds +type QemuDiskBandwidthBurstDuration uint + type QemuDiskBandwidthData struct { ReadLimit QemuDiskBandwidthDataLimit `json:"read,omitempty"` WriteLimit QemuDiskBandwidthDataLimit `json:"write,omitempty"` @@ -497,7 +517,7 @@ func (data QemuDiskBandwidthData) Validate() error { } type QemuDiskBandwidthDataLimit struct { - Burst QemuDiskBandwidthDataLimitBurst `json:"burst,omitempty"` // 0 = default + Burst QemuDiskBandwidthDataLimitBurst `json:"burst,omitempty"` // 0 = unlimited Concurrent QemuDiskBandwidthDataLimitConcurrent `json:"concurrent,omitempty"` // 0 = unlimited } @@ -549,8 +569,9 @@ func (iops QemuDiskBandwidthIops) Validate() error { } type QemuDiskBandwidthIopsLimit struct { - Burst QemuDiskBandwidthIopsLimitBurst `json:"burst,omitempty"` // 0 = default - Concurrent QemuDiskBandwidthIopsLimitConcurrent `json:"concurrent,omitempty"` // 0 = unlimited + Burst QemuDiskBandwidthIopsLimitBurst `json:"burst,omitempty"` // 0 = unlimited + BurstDuration QemuDiskBandwidthBurstDuration `json:"burst_duration,omitempty"` + Concurrent QemuDiskBandwidthIopsLimitConcurrent `json:"concurrent,omitempty"` // 0 = unlimited } func (limit QemuDiskBandwidthIopsLimit) Validate() (err error) { diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index c091c125..2755ca46 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -58,12 +58,12 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{ Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, - WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, - WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89, BurstDuration: 4, Concurrent: uint23}, }, }, Cache: QemuDiskCache_DirectSync, @@ -75,7 +75,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 32, Storage: "Test", }}}}}, - output: map[string]interface{}{"ide0": "Test:32,aio=native,cache=directsync,discard=on,format=raw,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=558485ef-478,ssd=1"}, + output: map[string]interface{}{"ide0": "Test:32,aio=native,cache=directsync,discard=on,format=raw,iops_rd=34,iops_rd_max=78,iops_rd_max_length=3,iops_wr=23,iops_wr_max=89,iops_wr_max_length=4,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=558485ef-478,ssd=1"}, }, {name: "Create Disks.Ide.Disk_X.Disk.AsyncIO", config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{AsyncIO: QemuDiskAsyncIO_Native}}}}}, @@ -129,6 +129,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, output: map[string]interface{}{"ide1": ",backup=0,iops_rd_max=78,replicate=0"}, }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops.ReadLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,iops_rd_max_length=3,replicate=0"}, + }, {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops.ReadLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, output: map[string]interface{}{"ide2": ",backup=0,iops_rd=34,replicate=0"}, @@ -141,6 +145,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, output: map[string]interface{}{"ide0": ",backup=0,iops_wr_max=89,replicate=0"}, }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops.WriteLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 4}}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,iops_wr_max_length=4,replicate=0"}, + }, {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops.WriteLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"ide1": ",backup=0,iops_wr=23,replicate=0"}, @@ -184,12 +192,12 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{ Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, - WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, - WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89, BurstDuration: 4, Concurrent: uint23}, }, }, Cache: QemuDiskCache_Unsafe, @@ -199,7 +207,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Replicate: true, Serial: "test-serial_757465-gdg", }}}}}, - output: map[string]interface{}{"ide0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=test-serial_757465-gdg,ssd=1"}, + output: map[string]interface{}{"ide0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_rd_max_length=3,iops_wr=23,iops_wr_max=89,iops_wr_max_length=4,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=test-serial_757465-gdg,ssd=1"}, }, {name: "Create Disks.Ide.Disk_X.Passthrough.AsyncIO", config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{AsyncIO: QemuDiskAsyncIO_Threads}}}}}, @@ -253,6 +261,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, output: map[string]interface{}{"ide1": ",backup=0,iops_rd_max=78,replicate=0"}, }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,iops_rd_max_length=3,replicate=0"}, + }, {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, output: map[string]interface{}{"ide2": ",backup=0,iops_rd=34,replicate=0"}, @@ -265,6 +277,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, output: map[string]interface{}{"ide0": ",backup=0,iops_wr_max=89,replicate=0"}, }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 4}}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,iops_wr_max_length=4,replicate=0"}, + }, {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"ide1": ",backup=0,iops_wr=23,replicate=0"}, @@ -317,12 +333,12 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{ Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, - WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, - WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89, BurstDuration: 4, Concurrent: uint23}, }, }, Cache: QemuDiskCache_Unsafe, @@ -334,7 +350,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 32, Storage: "Test", }}}}}, - output: map[string]interface{}{"sata0": "Test:32,aio=native,cache=unsafe,discard=on,format=qcow2,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=ab_C-12_3,ssd=1"}, + output: map[string]interface{}{"sata0": "Test:32,aio=native,cache=unsafe,discard=on,format=qcow2,iops_rd=34,iops_rd_max=78,iops_rd_max_length=3,iops_wr=23,iops_wr_max=89,iops_wr_max_length=4,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=ab_C-12_3,ssd=1"}, }, {name: "Create Disks.Sata.Disk_X.Disk.AsyncIO", config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{AsyncIO: QemuDiskAsyncIO_Native}}}}}, @@ -388,6 +404,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, output: map[string]interface{}{"sata0": ",backup=0,iops_rd_max=78,replicate=0"}, }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops.ReadLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}}}}}}, + output: map[string]interface{}{"sata0": ",backup=0,iops_rd_max_length=3,replicate=0"}, + }, {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops.ReadLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, output: map[string]interface{}{"sata1": ",backup=0,iops_rd=34,replicate=0"}, @@ -400,6 +420,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, output: map[string]interface{}{"sata3": ",backup=0,iops_wr_max=89,replicate=0"}, }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops.WriteLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 4}}}}}}}}, + output: map[string]interface{}{"sata3": ",backup=0,iops_wr_max_length=4,replicate=0"}, + }, {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops.WriteLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"sata4": ",backup=0,iops_wr=23,replicate=0"}, @@ -443,12 +467,12 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{ Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, - WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, - WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89, BurstDuration: 4, Concurrent: uint23}, }, }, Cache: QemuDiskCache_Unsafe, @@ -458,7 +482,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Replicate: true, Serial: "test-serial_757465-gdg", }}}}}, - output: map[string]interface{}{"sata0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=test-serial_757465-gdg,ssd=1"}, + output: map[string]interface{}{"sata0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_rd_max_length=3,iops_wr=23,iops_wr_max=89,iops_wr_max_length=4,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,serial=test-serial_757465-gdg,ssd=1"}, }, {name: "Create Disks.Sata.Disk_X.Passthrough.AsyncIO", config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{AsyncIO: QemuDiskAsyncIO_Threads}}}}}, @@ -512,6 +536,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, output: map[string]interface{}{"sata1": ",backup=0,iops_rd_max=78,replicate=0"}, }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}}}}}}, + output: map[string]interface{}{"sata1": ",backup=0,iops_rd_max_length=3,replicate=0"}, + }, {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, output: map[string]interface{}{"sata2": ",backup=0,iops_rd=34,replicate=0"}, @@ -524,6 +552,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, output: map[string]interface{}{"sata4": ",backup=0,iops_wr_max=89,replicate=0"}, }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 4}}}}}}}}, + output: map[string]interface{}{"sata4": ",backup=0,iops_wr_max_length=4,replicate=0"}, + }, {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"sata5": ",backup=0,iops_wr=23,replicate=0"}, @@ -576,12 +608,12 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{ Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, - WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, - WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89, BurstDuration: 4, Concurrent: uint23}, }, }, Cache: QemuDiskCache_DirectSync, @@ -595,7 +627,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 32, Storage: "Test", }}}}}, - output: map[string]interface{}{"scsi0": "Test:32,aio=native,cache=directsync,discard=on,format=raw,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=558485ef-478,ssd=1"}, + output: map[string]interface{}{"scsi0": "Test:32,aio=native,cache=directsync,discard=on,format=raw,iops_rd=34,iops_rd_max=78,iops_rd_max_length=3,iops_wr=23,iops_wr_max=89,iops_wr_max_length=4,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=558485ef-478,ssd=1"}, }, {name: "Create Disks.Scsi.Disk_X.Disk.AsyncIO", config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Disk: &QemuScsiDisk{AsyncIO: QemuDiskAsyncIO_Native}}}}}, @@ -649,6 +681,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, output: map[string]interface{}{"scsi13": ",backup=0,iops_rd_max=78,replicate=0"}, }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops.ReadLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}}}}}}, + output: map[string]interface{}{"scsi13": ",backup=0,iops_rd_max_length=3,replicate=0"}, + }, {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops.ReadLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_14: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, output: map[string]interface{}{"scsi14": ",backup=0,iops_rd=34,replicate=0"}, @@ -661,6 +697,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, output: map[string]interface{}{"scsi16": ",backup=0,iops_wr_max=89,replicate=0"}, }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops.WriteLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 4}}}}}}}}, + output: map[string]interface{}{"scsi16": ",backup=0,iops_wr_max_length=4,replicate=0"}, + }, {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops.WriteLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"scsi17": ",backup=0,iops_wr=23,replicate=0"}, @@ -712,12 +752,12 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{ Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, - WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, - WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89, BurstDuration: 4, Concurrent: uint23}, }, }, Cache: QemuDiskCache_Unsafe, @@ -729,7 +769,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Replicate: true, Serial: "test-serial_757465-gdg", }}}}}, - output: map[string]interface{}{"scsi0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=test-serial_757465-gdg,ssd=1"}, + output: map[string]interface{}{"scsi0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_rd_max_length=3,iops_wr=23,iops_wr_max=89,iops_wr_max_length=4,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=test-serial_757465-gdg,ssd=1"}, }, {name: "Create Disks.Scsi.Disk_X.Passthrough.AsyncIO", config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{AsyncIO: QemuDiskAsyncIO_Threads}}}}}, @@ -783,6 +823,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, output: map[string]interface{}{"scsi13": ",backup=0,iops_rd_max=78,replicate=0"}, }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}}}}}}, + output: map[string]interface{}{"scsi13": ",backup=0,iops_rd_max_length=3,replicate=0"}, + }, {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_14: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, output: map[string]interface{}{"scsi14": ",backup=0,iops_rd=34,replicate=0"}, @@ -795,6 +839,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, output: map[string]interface{}{"scsi16": ",backup=0,iops_wr_max=89,replicate=0"}, }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_16: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 4}}}}}}}}, + output: map[string]interface{}{"scsi16": ",backup=0,iops_wr_max_length=4,replicate=0"}, + }, {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"scsi17": ",backup=0,iops_wr=23,replicate=0"}, @@ -855,12 +903,12 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{ Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, - WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, - WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89, BurstDuration: 4, Concurrent: uint23}, }, }, Cache: QemuDiskCache_DirectSync, @@ -873,7 +921,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Size: 32, Storage: "Test", }}}}}, - output: map[string]interface{}{"virtio0": "Test:32,aio=native,cache=directsync,discard=on,format=raw,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=558485ef-478"}, + output: map[string]interface{}{"virtio0": "Test:32,aio=native,cache=directsync,discard=on,format=raw,iops_rd=34,iops_rd_max=78,iops_rd_max_length=3,iops_wr=23,iops_wr_max=89,iops_wr_max_length=4,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=558485ef-478"}, }, {name: "Create Disks.VirtIO.Disk_X.Disk.AsyncIO", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{AsyncIO: QemuDiskAsyncIO_Native}}}}}, @@ -899,6 +947,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, output: map[string]interface{}{"virtio6": ",backup=0,iops_rd_max=78,replicate=0"}, }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.ReadLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 1}}}}}}}}, + output: map[string]interface{}{"virtio6": ",backup=0,iops_rd_max_length=1,replicate=0"}, + }, {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.ReadLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, output: map[string]interface{}{"virtio7": ",backup=0,iops_rd=34,replicate=0"}, @@ -911,6 +963,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, output: map[string]interface{}{"virtio9": ",backup=0,iops_wr_max=89,replicate=0"}, }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.WriteLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 2}}}}}}}}, + output: map[string]interface{}{"virtio9": ",backup=0,iops_wr_max_length=2,replicate=0"}, + }, {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.WriteLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"virtio10": ",backup=0,iops_wr=23,replicate=0"}, @@ -927,6 +983,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, output: map[string]interface{}{"virtio13": ",backup=0,iops_rd_max=78,replicate=0"}, }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops.ReadLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}}}}}}, + output: map[string]interface{}{"virtio13": ",backup=0,iops_rd_max_length=3,replicate=0"}, + }, {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops.ReadLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_14: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, output: map[string]interface{}{"virtio14": ",backup=0,iops_rd=34,replicate=0"}, @@ -939,6 +999,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, output: map[string]interface{}{"virtio0": ",backup=0,iops_wr_max=89,replicate=0"}, }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops.WriteLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 4}}}}}}}}, + output: map[string]interface{}{"virtio0": ",backup=0,iops_wr_max_length=4,replicate=0"}, + }, {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops.WriteLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"virtio1": ",backup=0,iops_wr=23,replicate=0"}, @@ -986,12 +1050,12 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Backup: true, Bandwidth: QemuDiskBandwidth{ Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10, Burst: float99}, - WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45, Burst: float79}, + ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34, Burst: uint78}, - WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23, Burst: uint89}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89, BurstDuration: 4, Concurrent: uint23}, }, }, Cache: QemuDiskCache_Unsafe, @@ -1002,7 +1066,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { Replicate: true, Serial: "test-serial_757465-gdg", }}}}}, - output: map[string]interface{}{"virtio0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_wr=23,iops_wr_max=89,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=test-serial_757465-gdg"}, + output: map[string]interface{}{"virtio0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,cache=unsafe,discard=on,iops_rd=34,iops_rd_max=78,iops_rd_max_length=3,iops_wr=23,iops_wr_max=89,iops_wr_max_length=4,iothread=1,mbps_rd=10.30,mbps_rd_max=99.20,mbps_wr=45.23,mbps_wr_max=79.23,ro=1,serial=test-serial_757465-gdg"}, }, {name: "Create Disks.VirtIO.Disk_X.Passthrough.AsyncIO", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{AsyncIO: QemuDiskAsyncIO_Threads}}}}}, @@ -1056,6 +1120,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, output: map[string]interface{}{"virtio13": ",backup=0,iops_rd_max=78,replicate=0"}, }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}}}}}}, + output: map[string]interface{}{"virtio13": ",backup=0,iops_rd_max_length=3,replicate=0"}, + }, {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops.ReadLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_14: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, output: map[string]interface{}{"virtio14": ",backup=0,iops_rd=34,replicate=0"}, @@ -1068,6 +1136,10 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, output: map[string]interface{}{"virtio0": ",backup=0,iops_wr_max=89,replicate=0"}, }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 4}}}}}}}}, + output: map[string]interface{}{"virtio0": ",backup=0,iops_wr_max_length=4,replicate=0"}, + }, {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops.WriteLimit.Concurrent", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"virtio1": ",backup=0,iops_wr=23,replicate=0"}, @@ -2235,7 +2307,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Ide Disk ALL", - input: map[string]interface{}{"ide1": "test2:100/vm-100-disk-53.qcow2,aio=io_uring,backup=0,cache=writethrough,discard=on,iops_rd=12,iops_rd_max=13,iops_wr=15,iops_wr_max=14,mbps_rd=1.46,mbps_rd_max=3.57,mbps_wr=2.68,mbps_wr_max=4.55,replicate=0,serial=disk-9763,size=1032G,ssd=1"}, + input: map[string]interface{}{"ide1": "test2:100/vm-100-disk-53.qcow2,aio=io_uring,backup=0,cache=writethrough,discard=on,iops_rd=12,iops_rd_max=13,iops_rd_max_length=4,iops_wr=15,iops_wr_max=14,iops_wr_max_length=5,mbps_rd=1.46,mbps_rd_max=3.57,mbps_wr=2.68,mbps_wr_max=4.55,replicate=0,serial=disk-9763,size=1032G,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ AsyncIO: QemuDiskAsyncIO_IOuring, Backup: false, @@ -2245,8 +2317,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.55, Concurrent: 2.68}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 12}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 14, Concurrent: 15}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 4, Concurrent: 12}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 14, BurstDuration: 5, Concurrent: 15}, }, }, Cache: QemuDiskCache_WriteThrough, @@ -2261,7 +2333,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Ide Disk ALL LinkedClone", - input: map[string]interface{}{"ide1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-53.qcow2,aio=io_uring,backup=0,cache=writethrough,discard=on,iops_rd=12,iops_rd_max=13,iops_wr=15,iops_wr_max=14,mbps_rd=1.46,mbps_rd_max=3.57,mbps_wr=2.68,mbps_wr_max=4.55,replicate=0,serial=disk-9763,size=1032G,ssd=1"}, + input: map[string]interface{}{"ide1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-53.qcow2,aio=io_uring,backup=0,cache=writethrough,discard=on,iops_rd=12,iops_rd_max=13,iops_rd_max_length=4,iops_wr=15,iops_wr_max=14,iops_wr_max_length=5,mbps_rd=1.46,mbps_rd_max=3.57,mbps_wr=2.68,mbps_wr_max=4.55,replicate=0,serial=disk-9763,size=1032G,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ AsyncIO: QemuDiskAsyncIO_IOuring, Backup: false, @@ -2271,8 +2343,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.55, Concurrent: 2.68}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 12}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 14, Concurrent: 15}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 4, Concurrent: 12}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 14, BurstDuration: 5, Concurrent: 15}, }, }, Cache: QemuDiskCache_WriteThrough, @@ -2352,6 +2424,17 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Ide Disk iops_rd_max_length", + input: map[string]interface{}{"ide3": "test2:100/vm-100-disk-53.qcow2,iops_rd_max_length=2"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 2}}}, + Format: QemuDiskFormat_Qcow2, + Id: uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, {name: "Disks Ide Disk iops_wr", input: map[string]interface{}{"ide0": "test2:100/vm-100-disk-53.qcow2,iops_wr=15"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -2374,6 +2457,17 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Ide Disk iops_wr_max_length", + input: map[string]interface{}{"ide1": "test2:100/vm-100-disk-53.qcow2,iops_wr_max_length=3"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}, + Format: QemuDiskFormat_Qcow2, + Id: uint53, + Replicate: true, + Storage: "test2", + }}}}}, + }, {name: "Disks Ide Disk mbps_rd", input: map[string]interface{}{"ide2": "test2:100/vm-100-disk-53.qcow2,mbps_rd=1.46"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -2471,7 +2565,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Ide Passthrough All", - input: map[string]interface{}{"ide1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,backup=0,cache=unsafe,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=1G,ssd=1"}, + input: map[string]interface{}{"ide1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,backup=0,cache=unsafe,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=4,iops_wr=11,iops_wr_max=13,iops_wr_max_length=5,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=1G,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ AsyncIO: QemuDiskAsyncIO_Threads, Backup: false, @@ -2481,8 +2575,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 5, Concurrent: 11}, }, }, Cache: QemuDiskCache_Unsafe, @@ -2547,6 +2641,15 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Replicate: true, }}}}}, }, + {name: "Disks Ide Passthrough iops_rd_max_length", + input: map[string]interface{}{"ide3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd_max_length=2"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 2}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, {name: "Disks Ide Passthrough iops_wr", input: map[string]interface{}{"ide0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr=11"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ @@ -2565,6 +2668,15 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Replicate: true, }}}}}, }, + {name: "Disks Ide Passthrough iops_wr_max_length", + input: map[string]interface{}{"ide1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr_max_length=3"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, {name: "Disks Ide Passthrough mbps_rd", input: map[string]interface{}{"ide2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd=1.51"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ @@ -2673,7 +2785,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Sata Disk ALL", - input: map[string]interface{}{"sata1": "test2:100/vm-100-disk-47.qcow2,aio=native,backup=0,cache=none,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=32G,ssd=1"}, + input: map[string]interface{}{"sata1": "test2:100/vm-100-disk-47.qcow2,aio=native,backup=0,cache=none,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=4,iops_wr=11,iops_wr_max=13,iops_wr_max_length=5,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=32G,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ AsyncIO: QemuDiskAsyncIO_Native, Backup: false, @@ -2683,8 +2795,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 5, Concurrent: 11}, }, }, Cache: QemuDiskCache_None, @@ -2699,7 +2811,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Sata Disk ALL LinkedClone", - input: map[string]interface{}{"sata1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-47.qcow2,aio=native,backup=0,cache=none,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=32G,ssd=1"}, + input: map[string]interface{}{"sata1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-47.qcow2,aio=native,backup=0,cache=none,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=4,iops_wr=11,iops_wr_max=13,iops_wr_max_length=5,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=32G,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ AsyncIO: QemuDiskAsyncIO_Native, Backup: false, @@ -2709,8 +2821,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 5, Concurrent: 11}, }, }, Cache: QemuDiskCache_None, @@ -2790,6 +2902,17 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Sata Disk iops_rd_max_length", + input: map[string]interface{}{"sata1": "test2:100/vm-100-disk-47.qcow2,iops_rd_max_length=2"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 2}}}, + Format: QemuDiskFormat_Qcow2, + Id: uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, {name: "Disks Sata Disk iops_wr", input: map[string]interface{}{"sata2": "test2:100/vm-100-disk-47.qcow2,iops_wr=11"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -2812,6 +2935,17 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Sata Disk iops_wr_max_length", + input: map[string]interface{}{"sata3": "test2:100/vm-100-disk-47.qcow2,iops_wr_max_length=3"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}, + Format: QemuDiskFormat_Qcow2, + Id: uint47, + Replicate: true, + Storage: "test2", + }}}}}, + }, {name: "Disks Sata Disk mbps_rd", input: map[string]interface{}{"sata4": "test2:100/vm-100-disk-47.qcow2,mbps_rd=1.51"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -2913,7 +3047,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Sata Passthrough All", - input: map[string]interface{}{"sata1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=io_uring,backup=0,cache=directsync,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=1G,ssd=1"}, + input: map[string]interface{}{"sata1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=io_uring,backup=0,cache=directsync,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=5,iops_wr=11,iops_wr_max=13,iops_wr_max_length=4,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=1G,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ AsyncIO: QemuDiskAsyncIO_IOuring, Backup: false, @@ -2923,8 +3057,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 5, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 4, Concurrent: 11}, }, }, Cache: QemuDiskCache_DirectSync, @@ -2989,6 +3123,15 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Replicate: true, }}}}}, }, + {name: "Disks Sata Passthrough iops_rd_max_length", + input: map[string]interface{}{"sata1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd_max_length=2"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 2}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, {name: "Disks Sata Passthrough iops_wr", input: map[string]interface{}{"sata2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr=11"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ @@ -3007,6 +3150,15 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Replicate: true, }}}}}, }, + {name: "Disks Sata Passthrough iops_wr_max_length", + input: map[string]interface{}{"sata3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr_max_length=3"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, {name: "Disks Sata Passthrough mbps_rd", input: map[string]interface{}{"sata4": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd=1.51"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ @@ -3115,7 +3267,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Scsi Disk ALL", - input: map[string]interface{}{"scsi1": "test:100/vm-100-disk-2.qcow2,aio=threads,backup=0,cache=writeback,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G,ssd=1"}, + input: map[string]interface{}{"scsi1": "test:100/vm-100-disk-2.qcow2,aio=threads,backup=0,cache=writeback,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=4,iops_wr=11,iops_wr_max=13,iops_wr_max_length=5,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Disk: &QemuScsiDisk{ AsyncIO: QemuDiskAsyncIO_Threads, Backup: false, @@ -3125,8 +3277,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 5, Concurrent: 11}, }, }, Cache: QemuDiskCache_WriteBack, @@ -3143,7 +3295,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Scsi Disk ALL LinkedClone", - input: map[string]interface{}{"scsi1": "test:110/base-110-disk-1.qcow2/100/vm-100-disk-2.qcow2,aio=threads,backup=0,cache=writeback,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G,ssd=1"}, + input: map[string]interface{}{"scsi1": "test:110/base-110-disk-1.qcow2/100/vm-100-disk-2.qcow2,aio=threads,backup=0,cache=writeback,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=4,iops_wr=11,iops_wr_max=13,iops_wr_max_length=5,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Disk: &QemuScsiDisk{ AsyncIO: QemuDiskAsyncIO_Threads, Backup: false, @@ -3153,8 +3305,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 5, Concurrent: 11}, }, }, Cache: QemuDiskCache_WriteBack, @@ -3236,6 +3388,17 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test", }}}}}, }, + {name: "Disks Scsi Disk iops_rd_max_length", + input: map[string]interface{}{"scsi7": "test:100/vm-100-disk-2.qcow2,iops_rd_max_length=2"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 2}}}, + Format: QemuDiskFormat_Qcow2, + Id: uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, {name: "Disks Scsi Disk iops_wr", input: map[string]interface{}{"scsi8": "test:100/vm-100-disk-2.qcow2,iops_wr=11"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -3258,6 +3421,17 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test", }}}}}, }, + {name: "Disks Scsi Disk iops_wr_max_length", + input: map[string]interface{}{"scsi9": "test:100/vm-100-disk-2.qcow2,iops_wr_max_length=3"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}, + Format: QemuDiskFormat_Qcow2, + Id: uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, {name: "Disks Scsi Disk iothread", input: map[string]interface{}{"scsi10": "test:100/vm-100-disk-2.qcow2,iothread=1"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -3377,7 +3551,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Scsi Passthrough All", - input: map[string]interface{}{"scsi1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,backup=0,cache=none,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=1G,ssd=1"}, + input: map[string]interface{}{"scsi1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=threads,backup=0,cache=none,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=4,iops_wr=11,iops_wr_max=13,iops_wr_max_length=5,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=1G,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ AsyncIO: QemuDiskAsyncIO_Threads, Backup: false, @@ -3387,8 +3561,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 5, Concurrent: 11}, }, }, Cache: QemuDiskCache_None, @@ -3455,6 +3629,15 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Replicate: true, }}}}}, }, + {name: "Disks Scsi Passthrough iops_rd_max_length", + input: map[string]interface{}{"scsi7": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd_max_length=2"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 2}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, {name: "Disks Scsi Passthrough iops_wr", input: map[string]interface{}{"scsi8": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr=11"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ @@ -3473,6 +3656,15 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Replicate: true, }}}}}, }, + {name: "Disks Scsi Passthrough iops_wr_max_length", + input: map[string]interface{}{"scsi9": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr_max_length=3"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, {name: "Disks Scsi Passthrough iothread", input: map[string]interface{}{"scsi10": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iothread=1"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ @@ -3599,7 +3791,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks VirtIO Disk ALL", - input: map[string]interface{}{"virtio1": "test2:100/vm-100-disk-31.qcow2,aio=io_uring,backup=0,cache=directsync,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G"}, + input: map[string]interface{}{"virtio1": "test2:100/vm-100-disk-31.qcow2,aio=io_uring,backup=0,cache=directsync,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=2,iops_wr=11,iops_wr_max=13,iops_wr_max_length=3,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ AsyncIO: QemuDiskAsyncIO_IOuring, Backup: false, @@ -3609,8 +3801,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 2, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 3, Concurrent: 11}, }, }, Cache: QemuDiskCache_DirectSync, @@ -3626,7 +3818,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks VirtIO Disk ALL LinkedClone", - input: map[string]interface{}{"virtio1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-31.qcow2,aio=io_uring,backup=0,cache=directsync,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G"}, + input: map[string]interface{}{"virtio1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-31.qcow2,aio=io_uring,backup=0,cache=directsync,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=2,iops_wr=11,iops_wr_max=13,iops_wr_max_length=3,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ AsyncIO: QemuDiskAsyncIO_IOuring, Backup: false, @@ -3636,8 +3828,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 2, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 3, Concurrent: 11}, }, }, Cache: QemuDiskCache_DirectSync, @@ -3710,12 +3902,19 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { {name: "Disks VirtIO Disk iops_rd_max", input: map[string]interface{}{"virtio7": "test2:100/vm-100-disk-31.qcow2,iops_rd_max=12"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ - Backup: true, - Bandwidth: QemuDiskBandwidth{ - Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12}, - }, - }, + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12}}}, + Format: QemuDiskFormat_Qcow2, + Id: uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, + {name: "Disks VirtIO Disk iops_rd_max_length", + input: map[string]interface{}{"virtio7": "test2:100/vm-100-disk-31.qcow2,iops_rd_max_length=2"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 2}}}, Format: QemuDiskFormat_Qcow2, Id: uint31, Replicate: true, @@ -3744,6 +3943,17 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks VirtIO Disk iops_wr_max_length", + input: map[string]interface{}{"virtio9": "test2:100/vm-100-disk-31.qcow2,iops_wr_max_length=3"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}, + Format: QemuDiskFormat_Qcow2, + Id: uint31, + Replicate: true, + Storage: "test2", + }}}}}, + }, {name: "Disks VirtIO Disk iothread", input: map[string]interface{}{"virtio10": "test2:100/vm-100-disk-31.qcow2,iothread=1"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ @@ -3856,7 +4066,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks VirtIO Passthrough ALL", - input: map[string]interface{}{"virtio1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=native,backup=0,cache=unsafe,discard=on,iops_rd=10,iops_rd_max=12,iops_wr=11,iops_wr_max=13,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=1G"}, + input: map[string]interface{}{"virtio1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,aio=native,backup=0,cache=unsafe,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=4,iops_wr=11,iops_wr_max=13,iops_wr_max_length=5,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=1G"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ AsyncIO: QemuDiskAsyncIO_Native, Backup: false, @@ -3866,8 +4076,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, Concurrent: 11}, + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 5, Concurrent: 11}, }, }, Cache: QemuDiskCache_Unsafe, @@ -3933,6 +4143,15 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Replicate: true, }}}}}, }, + {name: "Disks VirtIO Passthrough iops_rd_max_length", + input: map[string]interface{}{"virtio7": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_rd_max_length=2"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 2}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, {name: "Disks VirtIO Passthrough iops_wr", input: map[string]interface{}{"virtio8": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr=11"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ @@ -3951,6 +4170,15 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Replicate: true, }}}}}, }, + {name: "Disks VirtIO Passthrough iops_wr_max_length", + input: map[string]interface{}{"virtio9": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iops_wr_max_length=3"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ + Backup: true, + Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 3}}}, + File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", + Replicate: true, + }}}}}, + }, {name: "Disks VirtIO Passthrough iothread", input: map[string]interface{}{"virtio10": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,iothread=1"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ From 72653078f2d15ace2175d73112f0d5c69c1833a9 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 3 Apr 2023 10:06:55 +0000 Subject: [PATCH 112/120] refactor: rename `Data` to `MBps` --- proxmox/config_qemu_disk.go | 118 ++-- proxmox/config_qemu_disk_test.go | 174 +++--- proxmox/config_qemu_test.go | 932 +++++++++++++++---------------- 3 files changed, 612 insertions(+), 612 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 2fe6bdf7..faef43e5 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -269,18 +269,18 @@ func (disk qemuDisk) mapToApiValues(vmID uint, currentStorage string, currentFor settings = settings + ",iothread=1" } - if disk.Bandwidth.Data.ReadLimit.Concurrent != 0 { - settings = settings + fmt.Sprintf(",mbps_rd=%.2f", disk.Bandwidth.Data.ReadLimit.Concurrent) + if disk.Bandwidth.MBps.ReadLimit.Concurrent != 0 { + settings = settings + fmt.Sprintf(",mbps_rd=%.2f", disk.Bandwidth.MBps.ReadLimit.Concurrent) } - if disk.Bandwidth.Data.ReadLimit.Burst != 0 { - settings = settings + fmt.Sprintf(",mbps_rd_max=%.2f", disk.Bandwidth.Data.ReadLimit.Burst) + if disk.Bandwidth.MBps.ReadLimit.Burst != 0 { + settings = settings + fmt.Sprintf(",mbps_rd_max=%.2f", disk.Bandwidth.MBps.ReadLimit.Burst) } - if disk.Bandwidth.Data.WriteLimit.Concurrent != 0 { - settings = settings + fmt.Sprintf(",mbps_wr=%.2f", disk.Bandwidth.Data.WriteLimit.Concurrent) + if disk.Bandwidth.MBps.WriteLimit.Concurrent != 0 { + settings = settings + fmt.Sprintf(",mbps_wr=%.2f", disk.Bandwidth.MBps.WriteLimit.Concurrent) } - if disk.Bandwidth.Data.WriteLimit.Burst != 0 { - settings = settings + fmt.Sprintf(",mbps_wr_max=%.2f", disk.Bandwidth.Data.WriteLimit.Burst) + if disk.Bandwidth.MBps.WriteLimit.Burst != 0 { + settings = settings + fmt.Sprintf(",mbps_wr_max=%.2f", disk.Bandwidth.MBps.WriteLimit.Burst) } if !disk.Replicate { @@ -393,19 +393,19 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { } if e[0] == "mbps_rd" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.ReadLimit.Concurrent = QemuDiskBandwidthDataLimitConcurrent(math.Round(tmp*100) / 100) + disk.Bandwidth.MBps.ReadLimit.Concurrent = QemuDiskBandwidthMBpsLimitConcurrent(math.Round(tmp*100) / 100) } if e[0] == "mbps_rd_max" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.ReadLimit.Burst = QemuDiskBandwidthDataLimitBurst(math.Round(tmp*100) / 100) + disk.Bandwidth.MBps.ReadLimit.Burst = QemuDiskBandwidthMBpsLimitBurst(math.Round(tmp*100) / 100) } if e[0] == "mbps_wr" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.WriteLimit.Concurrent = QemuDiskBandwidthDataLimitConcurrent(math.Round(tmp*100) / 100) + disk.Bandwidth.MBps.WriteLimit.Concurrent = QemuDiskBandwidthMBpsLimitConcurrent(math.Round(tmp*100) / 100) } if e[0] == "mbps_wr_max" { tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.Data.WriteLimit.Burst = QemuDiskBandwidthDataLimitBurst(math.Round(tmp*100) / 100) + disk.Bandwidth.MBps.WriteLimit.Burst = QemuDiskBandwidthMBpsLimitBurst(math.Round(tmp*100) / 100) } if e[0] == "replicate" { disk.Replicate, _ = strconv.ParseBool(e[1]) @@ -488,12 +488,12 @@ func (asyncIO QemuDiskAsyncIO) Validate() error { } type QemuDiskBandwidth struct { - Data QemuDiskBandwidthData `json:"data,omitempty"` + MBps QemuDiskBandwidthMBps `json:"mbps,omitempty"` Iops QemuDiskBandwidthIops `json:"iops,omitempty"` } func (bandwidth QemuDiskBandwidth) Validate() error { - err := bandwidth.Data.Validate() + err := bandwidth.MBps.Validate() if err != nil { return err } @@ -503,25 +503,26 @@ func (bandwidth QemuDiskBandwidth) Validate() error { // burst duration in seconds type QemuDiskBandwidthBurstDuration uint -type QemuDiskBandwidthData struct { - ReadLimit QemuDiskBandwidthDataLimit `json:"read,omitempty"` - WriteLimit QemuDiskBandwidthDataLimit `json:"write,omitempty"` +type QemuDiskBandwidthIops struct { + ReadLimit QemuDiskBandwidthIopsLimit `json:"read,omitempty"` + WriteLimit QemuDiskBandwidthIopsLimit `json:"write,omitempty"` } -func (data QemuDiskBandwidthData) Validate() error { - err := data.ReadLimit.Validate() +func (iops QemuDiskBandwidthIops) Validate() error { + err := iops.ReadLimit.Validate() if err != nil { return err } - return data.WriteLimit.Validate() + return iops.WriteLimit.Validate() } -type QemuDiskBandwidthDataLimit struct { - Burst QemuDiskBandwidthDataLimitBurst `json:"burst,omitempty"` // 0 = unlimited - Concurrent QemuDiskBandwidthDataLimitConcurrent `json:"concurrent,omitempty"` // 0 = unlimited +type QemuDiskBandwidthIopsLimit struct { + Burst QemuDiskBandwidthIopsLimitBurst `json:"burst,omitempty"` // 0 = unlimited + BurstDuration QemuDiskBandwidthBurstDuration `json:"burst_duration,omitempty"` + Concurrent QemuDiskBandwidthIopsLimitConcurrent `json:"concurrent,omitempty"` // 0 = unlimited } -func (limit QemuDiskBandwidthDataLimit) Validate() (err error) { +func (limit QemuDiskBandwidthIopsLimit) Validate() (err error) { if err = limit.Burst.Validate(); err != nil { return } @@ -529,52 +530,51 @@ func (limit QemuDiskBandwidthDataLimit) Validate() (err error) { return } +type QemuDiskBandwidthIopsLimitBurst uint + const ( - Error_QemuDiskBandwidthDataLimitBurst string = "burst may not be lower then 1 except for 0" + Error_QemuDiskBandwidthIopsLimitBurst string = "burst may not be lower then 10 except for 0" ) -type QemuDiskBandwidthDataLimitBurst float32 - -func (limit QemuDiskBandwidthDataLimitBurst) Validate() error { - if limit != 0 && limit < 1 { - return errors.New(Error_QemuDiskBandwidthDataLimitBurst) +func (limit QemuDiskBandwidthIopsLimitBurst) Validate() error { + if limit != 0 && limit < 10 { + return errors.New(Error_QemuDiskBandwidthIopsLimitBurst) } return nil } +type QemuDiskBandwidthIopsLimitConcurrent uint + const ( - Error_QemuDiskBandwidthDataLimitConcurrent string = "concurrent may not be lower then 1 except for 0" + Error_QemuDiskBandwidthIopsLimitConcurrent string = "concurrent may not be lower then 10 except for 0" ) -type QemuDiskBandwidthDataLimitConcurrent float32 - -func (limit QemuDiskBandwidthDataLimitConcurrent) Validate() error { - if limit != 0 && limit < 1 { - return errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) +func (limit QemuDiskBandwidthIopsLimitConcurrent) Validate() error { + if limit != 0 && limit < 10 { + return errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) } return nil } -type QemuDiskBandwidthIops struct { - ReadLimit QemuDiskBandwidthIopsLimit `json:"read,omitempty"` - WriteLimit QemuDiskBandwidthIopsLimit `json:"write,omitempty"` +type QemuDiskBandwidthMBps struct { + ReadLimit QemuDiskBandwidthMBpsLimit `json:"read,omitempty"` + WriteLimit QemuDiskBandwidthMBpsLimit `json:"write,omitempty"` } -func (iops QemuDiskBandwidthIops) Validate() error { - err := iops.ReadLimit.Validate() +func (data QemuDiskBandwidthMBps) Validate() error { + err := data.ReadLimit.Validate() if err != nil { return err } - return iops.WriteLimit.Validate() + return data.WriteLimit.Validate() } -type QemuDiskBandwidthIopsLimit struct { - Burst QemuDiskBandwidthIopsLimitBurst `json:"burst,omitempty"` // 0 = unlimited - BurstDuration QemuDiskBandwidthBurstDuration `json:"burst_duration,omitempty"` - Concurrent QemuDiskBandwidthIopsLimitConcurrent `json:"concurrent,omitempty"` // 0 = unlimited +type QemuDiskBandwidthMBpsLimit struct { + Burst QemuDiskBandwidthMBpsLimitBurst `json:"burst,omitempty"` // 0 = unlimited + Concurrent QemuDiskBandwidthMBpsLimitConcurrent `json:"concurrent,omitempty"` // 0 = unlimited } -func (limit QemuDiskBandwidthIopsLimit) Validate() (err error) { +func (limit QemuDiskBandwidthMBpsLimit) Validate() (err error) { if err = limit.Burst.Validate(); err != nil { return } @@ -582,28 +582,28 @@ func (limit QemuDiskBandwidthIopsLimit) Validate() (err error) { return } -type QemuDiskBandwidthIopsLimitBurst uint - const ( - Error_QemuDiskBandwidthIopsLimitBurst string = "burst may not be lower then 10 except for 0" + Error_QemuDiskBandwidthMBpsLimitBurst string = "burst may not be lower then 1 except for 0" ) -func (limit QemuDiskBandwidthIopsLimitBurst) Validate() error { - if limit != 0 && limit < 10 { - return errors.New(Error_QemuDiskBandwidthIopsLimitBurst) +type QemuDiskBandwidthMBpsLimitBurst float32 + +func (limit QemuDiskBandwidthMBpsLimitBurst) Validate() error { + if limit != 0 && limit < 1 { + return errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) } return nil } -type QemuDiskBandwidthIopsLimitConcurrent uint - const ( - Error_QemuDiskBandwidthIopsLimitConcurrent string = "concurrent may not be lower then 10 except for 0" + Error_QemuDiskBandwidthMBpsLimitConcurrent string = "concurrent may not be lower then 1 except for 0" ) -func (limit QemuDiskBandwidthIopsLimitConcurrent) Validate() error { - if limit != 0 && limit < 10 { - return errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent) +type QemuDiskBandwidthMBpsLimitConcurrent float32 + +func (limit QemuDiskBandwidthMBpsLimitConcurrent) Validate() error { + if limit != 0 && limit < 1 { + return errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) } return nil } diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 39a54492..943048f5 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -122,17 +122,17 @@ func Test_QemuDiskBandwidth_Validate(t *testing.T) { }{ // Valid {name: "Valid 00", input: QemuDiskBandwidth{}}, - {name: "Valid 01", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}, - {name: "Valid 02", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}, - {name: "Valid 03", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}}, - {name: "Valid 04", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}}, - {name: "Valid 05", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}}, - {name: "Valid 06", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}}, - {name: "Valid 07", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}, - {name: "Valid 08", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}}, - {name: "Valid 09", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}}, - {name: "Valid 10", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}}, - {name: "Valid 11", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}}, + {name: "Valid 01", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{}}}, + {name: "Valid 02", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{}}}}, + {name: "Valid 03", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0}}}}, + {name: "Valid 04", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 1}}}}, + {name: "Valid 05", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0}}}}, + {name: "Valid 06", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1}}}}, + {name: "Valid 07", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{}}}}, + {name: "Valid 08", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0}}}}, + {name: "Valid 09", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 1}}}}, + {name: "Valid 10", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0}}}}, + {name: "Valid 11", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1}}}}, {name: "Valid 12", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}, {name: "Valid 13", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}, {name: "Valid 14", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}}, @@ -145,10 +145,10 @@ func Test_QemuDiskBandwidth_Validate(t *testing.T) { {name: "Valid 21", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}}, {name: "Valid 22", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}}, // Invalid - {name: "Invalid 00", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, - {name: "Invalid 01", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, - {name: "Invalid 02", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, - {name: "Invalid 03", input: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst)}, + {name: "Invalid 01", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent)}, + {name: "Invalid 02", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst)}, + {name: "Invalid 03", input: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}, err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent)}, {name: "Invalid 04", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, {name: "Invalid 05", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, {name: "Invalid 06", input: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, @@ -165,29 +165,29 @@ func Test_QemuDiskBandwidth_Validate(t *testing.T) { } } -func Test_QemuDiskBandwidthData_Validate(t *testing.T) { +func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { testData := []struct { name string - input QemuDiskBandwidthData + input QemuDiskBandwidthIops err error }{ // Valid - {name: "Valid 00", input: QemuDiskBandwidthData{}}, - {name: "Valid 01", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}, - {name: "Valid 02", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}, - {name: "Valid 03", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}, - {name: "Valid 04", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}, - {name: "Valid 05", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}, - {name: "Valid 06", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}, - {name: "Valid 07", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0}}}, - {name: "Valid 08", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 1}}}, - {name: "Valid 09", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0}}}, - {name: "Valid 10", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 1}}}, + {name: "Valid 00", input: QemuDiskBandwidthIops{}}, + {name: "Valid 01", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}, + {name: "Valid 02", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, + {name: "Valid 03", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, + {name: "Valid 04", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, + {name: "Valid 05", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, + {name: "Valid 06", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}, + {name: "Valid 07", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}, + {name: "Valid 08", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, + {name: "Valid 09", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, + {name: "Valid 10", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, // Invalid - {name: "Invalid 00", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, - {name: "Invalid 01", input: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, - {name: "Invalid 02", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, - {name: "Invalid 03", input: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, + {name: "Invalid 01", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, + {name: "Invalid 02", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, + {name: "Invalid 03", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { @@ -200,21 +200,21 @@ func Test_QemuDiskBandwidthData_Validate(t *testing.T) { } } -func Test_QemuDiskBandwidthDataLimit_Validate(t *testing.T) { +func Test_QemuDiskBandwidthIopsLimit_Validate(t *testing.T) { testData := []struct { name string - input QemuDiskBandwidthDataLimit + input QemuDiskBandwidthIopsLimit err error }{ // Valid - {name: "Valid 00", input: QemuDiskBandwidthDataLimit{}}, - {name: "Valid 01", input: QemuDiskBandwidthDataLimit{Burst: 0}}, - {name: "Valid 02", input: QemuDiskBandwidthDataLimit{Burst: 1}}, - {name: "Valid 03", input: QemuDiskBandwidthDataLimit{Concurrent: 0}}, - {name: "Valid 04", input: QemuDiskBandwidthDataLimit{Concurrent: 1}}, + {name: "Valid 00", input: QemuDiskBandwidthIopsLimit{}}, + {name: "Valid 01", input: QemuDiskBandwidthIopsLimit{Burst: 0}}, + {name: "Valid 02", input: QemuDiskBandwidthIopsLimit{Burst: 10}}, + {name: "Valid 03", input: QemuDiskBandwidthIopsLimit{Concurrent: 0}}, + {name: "Valid 04", input: QemuDiskBandwidthIopsLimit{Concurrent: 10}}, // Invalid - {name: "Invalid 00", input: QemuDiskBandwidthDataLimit{Burst: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, - {name: "Invalid 01", input: QemuDiskBandwidthDataLimit{Concurrent: 0.99}, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthIopsLimit{Burst: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, + {name: "Invalid 01", input: QemuDiskBandwidthIopsLimit{Concurrent: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { @@ -227,17 +227,17 @@ func Test_QemuDiskBandwidthDataLimit_Validate(t *testing.T) { } } -func Test_QemuDiskBandwidthDataLimitBurst_Validate(t *testing.T) { +func Test_QemuDiskBandwidthIopsLimitBurst_Validate(t *testing.T) { testData := []struct { name string - input QemuDiskBandwidthDataLimitBurst + input QemuDiskBandwidthIopsLimitBurst err error }{ // Valid - {name: "Valid 01", input: 0}, - {name: "Valid 02", input: 1}, + {name: "Valid 03", input: 0}, + {name: "Valid 04", input: 10}, // Invalid - {name: "Invalid 00", input: 0.99, err: errors.New(Error_QemuDiskBandwidthDataLimitBurst)}, + {name: "Invalid 01", input: 9, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { @@ -250,17 +250,17 @@ func Test_QemuDiskBandwidthDataLimitBurst_Validate(t *testing.T) { } } -func Test_QemuDiskBandwidthDataLimitConcurrent_Validate(t *testing.T) { +func Test_QemuDiskBandwidthIopsLimitConcurrent_Validate(t *testing.T) { testData := []struct { name string - input QemuDiskBandwidthDataLimitConcurrent + input QemuDiskBandwidthIopsLimitConcurrent err error }{ // Valid - {name: "Valid 01", input: 0}, - {name: "Valid 02", input: 1}, + {name: "Valid 03", input: 0}, + {name: "Valid 04", input: 10}, // Invalid - {name: "Invalid 00", input: 0.99, err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent)}, + {name: "Invalid 01", input: 9, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { @@ -273,29 +273,29 @@ func Test_QemuDiskBandwidthDataLimitConcurrent_Validate(t *testing.T) { } } -func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { +func Test_QemuDiskBandwidthMBps_Validate(t *testing.T) { testData := []struct { name string - input QemuDiskBandwidthIops + input QemuDiskBandwidthMBps err error }{ // Valid - {name: "Valid 00", input: QemuDiskBandwidthIops{}}, - {name: "Valid 01", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}, - {name: "Valid 02", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, - {name: "Valid 03", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, - {name: "Valid 04", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, - {name: "Valid 05", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, - {name: "Valid 06", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}, - {name: "Valid 07", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 0}}}, - {name: "Valid 08", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 10}}}, - {name: "Valid 09", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 0}}}, - {name: "Valid 10", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 10}}}, + {name: "Valid 00", input: QemuDiskBandwidthMBps{}}, + {name: "Valid 01", input: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{}}}, + {name: "Valid 02", input: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0}}}, + {name: "Valid 03", input: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 1}}}, + {name: "Valid 04", input: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0}}}, + {name: "Valid 05", input: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1}}}, + {name: "Valid 06", input: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{}}}, + {name: "Valid 07", input: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0}}}, + {name: "Valid 08", input: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 1}}}, + {name: "Valid 09", input: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0}}}, + {name: "Valid 10", input: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1}}}, // Invalid - {name: "Invalid 00", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, - {name: "Invalid 01", input: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, - {name: "Invalid 02", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, - {name: "Invalid 03", input: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 9}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst)}, + {name: "Invalid 01", input: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent)}, + {name: "Invalid 02", input: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}, err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst)}, + {name: "Invalid 03", input: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}, err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { @@ -308,21 +308,21 @@ func Test_QemuDiskBandwidthIops_Validate(t *testing.T) { } } -func Test_QemuDiskBandwidthIopsLimit_Validate(t *testing.T) { +func Test_QemuDiskBandwidthMBpsLimit_Validate(t *testing.T) { testData := []struct { name string - input QemuDiskBandwidthIopsLimit + input QemuDiskBandwidthMBpsLimit err error }{ // Valid - {name: "Valid 00", input: QemuDiskBandwidthIopsLimit{}}, - {name: "Valid 01", input: QemuDiskBandwidthIopsLimit{Burst: 0}}, - {name: "Valid 02", input: QemuDiskBandwidthIopsLimit{Burst: 10}}, - {name: "Valid 03", input: QemuDiskBandwidthIopsLimit{Concurrent: 0}}, - {name: "Valid 04", input: QemuDiskBandwidthIopsLimit{Concurrent: 10}}, + {name: "Valid 00", input: QemuDiskBandwidthMBpsLimit{}}, + {name: "Valid 01", input: QemuDiskBandwidthMBpsLimit{Burst: 0}}, + {name: "Valid 02", input: QemuDiskBandwidthMBpsLimit{Burst: 1}}, + {name: "Valid 03", input: QemuDiskBandwidthMBpsLimit{Concurrent: 0}}, + {name: "Valid 04", input: QemuDiskBandwidthMBpsLimit{Concurrent: 1}}, // Invalid - {name: "Invalid 00", input: QemuDiskBandwidthIopsLimit{Burst: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, - {name: "Invalid 01", input: QemuDiskBandwidthIopsLimit{Concurrent: 9}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, + {name: "Invalid 00", input: QemuDiskBandwidthMBpsLimit{Burst: 0.99}, err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst)}, + {name: "Invalid 01", input: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}, err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { @@ -335,17 +335,17 @@ func Test_QemuDiskBandwidthIopsLimit_Validate(t *testing.T) { } } -func Test_QemuDiskBandwidthIopsLimitBurst_Validate(t *testing.T) { +func Test_QemuDiskBandwidthMBpsLimitBurst_Validate(t *testing.T) { testData := []struct { name string - input QemuDiskBandwidthIopsLimitBurst + input QemuDiskBandwidthMBpsLimitBurst err error }{ // Valid - {name: "Valid 03", input: 0}, - {name: "Valid 04", input: 10}, + {name: "Valid 01", input: 0}, + {name: "Valid 02", input: 1}, // Invalid - {name: "Invalid 01", input: 9, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst)}, + {name: "Invalid 00", input: 0.99, err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { @@ -358,17 +358,17 @@ func Test_QemuDiskBandwidthIopsLimitBurst_Validate(t *testing.T) { } } -func Test_QemuDiskBandwidthIopsLimitConcurrent_Validate(t *testing.T) { +func Test_QemuDiskBandwidthMBpsLimitConcurrent_Validate(t *testing.T) { testData := []struct { name string - input QemuDiskBandwidthIopsLimitConcurrent + input QemuDiskBandwidthMBpsLimitConcurrent err error }{ // Valid - {name: "Valid 03", input: 0}, - {name: "Valid 04", input: 10}, + {name: "Valid 01", input: 0}, + {name: "Valid 02", input: 1}, // Invalid - {name: "Invalid 01", input: 9, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent)}, + {name: "Invalid 00", input: 0.99, err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent)}, } for _, test := range testData { t.Run(test.name, func(*testing.T) { diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index 2755ca46..2e8c24cf 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -11,10 +11,10 @@ import ( func Test_ConfigQemu_mapToApiValues(t *testing.T) { format_Raw := QemuDiskFormat_Raw - float10 := QemuDiskBandwidthDataLimitConcurrent(10.3) - float45 := QemuDiskBandwidthDataLimitConcurrent(45.23) - float79 := QemuDiskBandwidthDataLimitBurst(79.23) - float99 := QemuDiskBandwidthDataLimitBurst(99.2) + float10 := QemuDiskBandwidthMBpsLimitConcurrent(10.3) + float45 := QemuDiskBandwidthMBpsLimitConcurrent(45.23) + float79 := QemuDiskBandwidthMBpsLimitBurst(79.23) + float99 := QemuDiskBandwidthMBpsLimitBurst(99.2) uint23 := QemuDiskBandwidthIopsLimitConcurrent(23) uint34 := QemuDiskBandwidthIopsLimitConcurrent(34) uint78 := QemuDiskBandwidthIopsLimitBurst(78) @@ -57,9 +57,9 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Native, Backup: true, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, @@ -89,34 +89,6 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{}}}}}}, output: map[string]interface{}{"ide3": ",backup=0,replicate=0"}, }, - {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, - output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.ReadLimit", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"ide1": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.ReadLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, - output: map[string]interface{}{"ide2": ",backup=0,mbps_rd_max=99.20,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.ReadLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, - output: map[string]interface{}{"ide3": ",backup=0,mbps_rd=10.30,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.WriteLimit", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.WriteLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, - output: map[string]interface{}{"ide1": ",backup=0,mbps_wr_max=79.23,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Data.WriteLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, - output: map[string]interface{}{"ide2": ",backup=0,mbps_wr=45.23,replicate=0"}, - }, {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.Iops", config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, output: map[string]interface{}{"ide3": ",backup=0,replicate=0"}, @@ -153,6 +125,34 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"ide1": ",backup=0,iops_wr=23,replicate=0"}, }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.MBps", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.MBps.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.MBps.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.MBps.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.MBps.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.MBps.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Disk.Bandwidth.MBps.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, {name: "Create Disks.Ide.Disk_X.Disk.Cache", config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Cache: QemuDiskCache_DirectSync}}}}}, output: map[string]interface{}{"ide2": ",backup=0,cache=directsync,replicate=0"}, @@ -191,9 +191,9 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Threads, Backup: true, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, @@ -221,34 +221,6 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{}}}}}}, output: map[string]interface{}{"ide3": ",backup=0,replicate=0"}, }, - {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, - output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.ReadLimit", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"ide1": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, - output: map[string]interface{}{"ide2": ",backup=0,mbps_rd_max=99.20,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, - output: map[string]interface{}{"ide3": ",backup=0,mbps_rd=10.30,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.WriteLimit", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, - output: map[string]interface{}{"ide1": ",backup=0,mbps_wr_max=79.23,replicate=0"}, - }, - {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, - output: map[string]interface{}{"ide2": ",backup=0,mbps_wr_max=79.23,replicate=0"}, - }, {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.Iops", config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, output: map[string]interface{}{"ide3": ",backup=0,replicate=0"}, @@ -285,6 +257,34 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"ide1": ",backup=0,iops_wr=23,replicate=0"}, }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.MBps", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"ide3": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"ide0": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"ide1": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Ide.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"ide2": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, {name: "Create Disks.Ide.Disk_X.Passthrough.Cache", config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Cache: QemuDiskCache_Unsafe}}}}}, output: map[string]interface{}{"ide2": ",backup=0,cache=unsafe,replicate=0"}, @@ -332,9 +332,9 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Native, Backup: true, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, @@ -364,34 +364,6 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{}}}}}}, output: map[string]interface{}{"sata2": ",backup=0,replicate=0"}, }, - {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, - output: map[string]interface{}{"sata3": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.ReadLimit", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"sata4": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.ReadLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, - output: map[string]interface{}{"sata5": ",backup=0,mbps_rd_max=99.20,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.ReadLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, - output: map[string]interface{}{"sata0": ",backup=0,mbps_rd=10.30,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.WriteLimit", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"sata1": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.WriteLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, - output: map[string]interface{}{"sata2": ",backup=0,mbps_wr_max=79.23,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Data.WriteLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, - output: map[string]interface{}{"sata3": ",backup=0,mbps_wr=45.23,replicate=0"}, - }, {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.Iops", config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, output: map[string]interface{}{"sata4": ",backup=0,replicate=0"}, @@ -428,6 +400,34 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"sata4": ",backup=0,iops_wr=23,replicate=0"}, }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.MBps", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{}}}}}}}, + output: map[string]interface{}{"sata3": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.MBps.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"sata4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.MBps.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"sata5": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.MBps.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"sata0": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.MBps.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"sata1": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.MBps.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"sata2": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Disk.Bandwidth.MBps.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"sata3": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, {name: "Create Disks.Sata.Disk_X.Disk.Cache", config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Cache: QemuDiskCache_DirectSync}}}}}, output: map[string]interface{}{"sata5": ",backup=0,cache=directsync,replicate=0"}, @@ -466,9 +466,9 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Threads, Backup: true, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, @@ -496,34 +496,6 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{}}}}}}, output: map[string]interface{}{"sata3": ",backup=0,replicate=0"}, }, - {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, - output: map[string]interface{}{"sata4": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.ReadLimit", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"sata5": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, - output: map[string]interface{}{"sata0": ",backup=0,mbps_rd_max=99.20,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, - output: map[string]interface{}{"sata1": ",backup=0,mbps_rd=10.30,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.WriteLimit", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"sata2": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, - output: map[string]interface{}{"sata3": ",backup=0,mbps_wr_max=79.23,replicate=0"}, - }, - {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, - output: map[string]interface{}{"sata4": ",backup=0,mbps_wr=45.23,replicate=0"}, - }, {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.Iops", config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, output: map[string]interface{}{"sata5": ",backup=0,replicate=0"}, @@ -560,6 +532,34 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"sata5": ",backup=0,iops_wr=23,replicate=0"}, }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.MBps", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{}}}}}}}, + output: map[string]interface{}{"sata4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"sata5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"sata0": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"sata1": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"sata2": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"sata3": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Sata.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"sata4": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, {name: "Create Disks.Sata.Disk_X.Passthrough.Cache", config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Cache: QemuDiskCache_Unsafe}}}}}, output: map[string]interface{}{"sata0": ",backup=0,cache=unsafe,replicate=0"}, @@ -607,9 +607,9 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Native, Backup: true, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, @@ -641,34 +641,6 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{}}}}}}, output: map[string]interface{}{"scsi3": ",backup=0,replicate=0"}, }, - {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, - output: map[string]interface{}{"scsi4": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.ReadLimit", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"scsi5": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.ReadLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, - output: map[string]interface{}{"scsi6": ",backup=0,mbps_rd_max=99.20,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.ReadLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, - output: map[string]interface{}{"scsi7": ",backup=0,mbps_rd=10.30,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.WriteLimit", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"scsi8": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.WriteLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, - output: map[string]interface{}{"scsi9": ",backup=0,mbps_wr_max=79.23,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Data.WriteLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, - output: map[string]interface{}{"scsi10": ",backup=0,mbps_wr=45.23,replicate=0"}, - }, {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.Iops", config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, output: map[string]interface{}{"scsi11": ",backup=0,replicate=0"}, @@ -705,6 +677,34 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"scsi17": ",backup=0,iops_wr=23,replicate=0"}, }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.MBps", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{}}}}}}}, + output: map[string]interface{}{"scsi4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.MBps.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"scsi5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.MBps.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"scsi6": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.MBps.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"scsi7": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.MBps.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"scsi8": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.MBps.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"scsi9": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Disk.Bandwidth.MBps.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"scsi10": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, {name: "Create Disks.Scsi.Disk_X.Disk.Cache", config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{Cache: QemuDiskCache_DirectSync}}}}}, output: map[string]interface{}{"scsi18": ",backup=0,cache=directsync,replicate=0"}, @@ -751,9 +751,9 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Threads, Backup: true, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, @@ -783,34 +783,6 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{}}}}}}, output: map[string]interface{}{"scsi3": ",backup=0,replicate=0"}, }, - {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, - output: map[string]interface{}{"scsi4": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.ReadLimit", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"scsi5": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, - output: map[string]interface{}{"scsi6": ",backup=0,mbps_rd_max=99.20,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, - output: map[string]interface{}{"scsi7": ",backup=0,mbps_rd=10.30,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.WriteLimit", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"scsi8": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, - output: map[string]interface{}{"scsi9": ",backup=0,mbps_wr_max=79.23,replicate=0"}, - }, - {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, - output: map[string]interface{}{"scsi10": ",backup=0,mbps_wr=45.23,replicate=0"}, - }, {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.Iops", config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, output: map[string]interface{}{"scsi11": ",backup=0,replicate=0"}, @@ -847,6 +819,34 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"scsi17": ",backup=0,iops_wr=23,replicate=0"}, }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.MBps", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{}}}}}}}, + output: map[string]interface{}{"scsi4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"scsi5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"scsi6": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"scsi7": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"scsi8": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"scsi9": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.Scsi.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"scsi10": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, {name: "Create Disks.Scsi.Disk_X.Passthrough.Cache", config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Cache: QemuDiskCache_Unsafe}}}}}, output: map[string]interface{}{"scsi18": ",backup=0,cache=unsafe,replicate=0"}, @@ -902,9 +902,9 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Native, Backup: true, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, @@ -935,42 +935,6 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{}}}}}}, output: map[string]interface{}{"virtio3": ",backup=0,replicate=0"}, }, - {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, - output: map[string]interface{}{"virtio4": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.ReadLimit", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, - output: map[string]interface{}{"virtio5": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.ReadLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, - output: map[string]interface{}{"virtio6": ",backup=0,iops_rd_max=78,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.ReadLimit.BurstDuration", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 1}}}}}}}}, - output: map[string]interface{}{"virtio6": ",backup=0,iops_rd_max_length=1,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.ReadLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, - output: map[string]interface{}{"virtio7": ",backup=0,iops_rd=34,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.WriteLimit", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, - output: map[string]interface{}{"virtio8": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.WriteLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, - output: map[string]interface{}{"virtio9": ",backup=0,iops_wr_max=89,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.WriteLimit.BurstDuration", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 2}}}}}}}}, - output: map[string]interface{}{"virtio9": ",backup=0,iops_wr_max_length=2,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.Data.WriteLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, - output: map[string]interface{}{"virtio10": ",backup=0,iops_wr=23,replicate=0"}, - }, {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.iops", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, output: map[string]interface{}{"virtio11": ",backup=0,replicate=0"}, @@ -1007,6 +971,42 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"virtio1": ",backup=0,iops_wr=23,replicate=0"}, }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.MBps", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, + output: map[string]interface{}{"virtio4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.MBps.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"virtio5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.MBps.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78}}}}}}}}, + output: map[string]interface{}{"virtio6": ",backup=0,iops_rd_max=78,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.MBps.ReadLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 1}}}}}}}}, + output: map[string]interface{}{"virtio6": ",backup=0,iops_rd_max_length=1,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.MBps.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint34}}}}}}}}, + output: map[string]interface{}{"virtio7": ",backup=0,iops_rd=34,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.MBps.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{}}}}}}}}, + output: map[string]interface{}{"virtio8": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.MBps.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Burst: uint89}}}}}}}}, + output: map[string]interface{}{"virtio9": ",backup=0,iops_wr_max=89,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.MBps.WriteLimit.BurstDuration", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{BurstDuration: 2}}}}}}}}, + output: map[string]interface{}{"virtio9": ",backup=0,iops_wr_max_length=2,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Disk.Bandwidth.MBps.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, + output: map[string]interface{}{"virtio10": ",backup=0,iops_wr=23,replicate=0"}, + }, {name: "Create Disks.VirtIO.Disk_X.Disk.Cache", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Cache: QemuDiskCache_DirectSync}}}}}, output: map[string]interface{}{"virtio2": ",backup=0,cache=directsync,replicate=0"}, @@ -1049,9 +1049,9 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Threads, Backup: true, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99, Concurrent: float10}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79, Concurrent: float45}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99, Concurrent: float10}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79, Concurrent: float45}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: uint78, BurstDuration: 3, Concurrent: uint34}, @@ -1080,34 +1080,6 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{}}}}}}, output: map[string]interface{}{"virtio3": ",backup=0,replicate=0"}, }, - {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{}}}}}}}, - output: map[string]interface{}{"virtio4": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.ReadLimit", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"virtio5": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: float99}}}}}}}}, - output: map[string]interface{}{"virtio6": ",backup=0,mbps_rd_max=99.20,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.ReadLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: float10}}}}}}}}, - output: map[string]interface{}{"virtio7": ",backup=0,mbps_rd=10.30,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.WriteLimit", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{}}}}}}}}, - output: map[string]interface{}{"virtio8": ",backup=0,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Burst", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: float79}}}}}}}}, - output: map[string]interface{}{"virtio9": ",backup=0,mbps_wr_max=79.23,replicate=0"}, - }, - {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Data.WriteLimit.Concurrent", - config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: float45}}}}}}}}, - output: map[string]interface{}{"virtio10": ",backup=0,mbps_wr=45.23,replicate=0"}, - }, {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.Iops", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{}}}}}}}, output: map[string]interface{}{"virtio11": ",backup=0,replicate=0"}, @@ -1144,6 +1116,34 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: uint23}}}}}}}}, output: map[string]interface{}{"virtio1": ",backup=0,iops_wr=23,replicate=0"}, }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.MBps", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{}}}}}}}, + output: map[string]interface{}{"virtio4": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"virtio5": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: float99}}}}}}}}, + output: map[string]interface{}{"virtio6": ",backup=0,mbps_rd_max=99.20,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.MBps.ReadLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float10}}}}}}}}, + output: map[string]interface{}{"virtio7": ",backup=0,mbps_rd=10.30,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{}}}}}}}}, + output: map[string]interface{}{"virtio8": ",backup=0,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit.Burst", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: float79}}}}}}}}, + output: map[string]interface{}{"virtio9": ",backup=0,mbps_wr_max=79.23,replicate=0"}, + }, + {name: "Create Disks.VirtIO.Disk_X.Passthrough.Bandwidth.MBps.WriteLimit.Concurrent", + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: float45}}}}}}}}, + output: map[string]interface{}{"virtio10": ",backup=0,mbps_wr=45.23,replicate=0"}, + }, {name: "Create Disks.VirtIO.Disk_X.Passthrough.Cache", config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Cache: QemuDiskCache_Unsafe}}}}}, output: map[string]interface{}{"virtio2": ",backup=0,cache=unsafe,replicate=0"}, @@ -2312,9 +2312,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_IOuring, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.57, Concurrent: 1.46}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.55, Concurrent: 2.68}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.57, Concurrent: 1.46}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.55, Concurrent: 2.68}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 4, Concurrent: 12}, @@ -2338,9 +2338,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_IOuring, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.57, Concurrent: 1.46}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.55, Concurrent: 2.68}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.57, Concurrent: 1.46}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.55, Concurrent: 2.68}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 4, Concurrent: 12}, @@ -2472,7 +2472,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"ide2": "test2:100/vm-100-disk-53.qcow2,mbps_rd=1.46"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.46}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1.46}}}, Format: QemuDiskFormat_Qcow2, Id: uint53, Replicate: true, @@ -2483,7 +2483,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"ide3": "test2:100/vm-100-disk-53.qcow2,mbps_rd_max=3.57"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.57}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.57}}}, Format: QemuDiskFormat_Qcow2, Id: uint53, Replicate: true, @@ -2494,7 +2494,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"ide0": "test2:100/vm-100-disk-53.qcow2,mbps_wr=2.68"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.68}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 2.68}}}, Format: QemuDiskFormat_Qcow2, Id: uint53, Replicate: true, @@ -2505,7 +2505,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"ide1": "test2:100/vm-100-disk-53.qcow2,mbps_wr_max=4.55"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.55}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.55}}}, Format: QemuDiskFormat_Qcow2, Id: uint53, Replicate: true, @@ -2570,9 +2570,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Threads, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, @@ -2681,7 +2681,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"ide2": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd=1.51"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -2690,7 +2690,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"ide3": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd_max=3.51"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -2699,7 +2699,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"ide0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr=2.51"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 2.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -2708,7 +2708,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"ide1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr_max=4.51"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -2790,9 +2790,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Native, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, @@ -2816,9 +2816,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Native, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, @@ -2950,7 +2950,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"sata4": "test2:100/vm-100-disk-47.qcow2,mbps_rd=1.51"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1.51}}}, Format: QemuDiskFormat_Qcow2, Id: uint47, Replicate: true, @@ -2961,7 +2961,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"sata5": "test2:100/vm-100-disk-47.qcow2,mbps_rd_max=3.51"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51}}}, Format: QemuDiskFormat_Qcow2, Id: uint47, Replicate: true, @@ -2973,8 +2973,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: true, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}, + MBps: QemuDiskBandwidthMBps{ + WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 2.51}, }, }, Format: QemuDiskFormat_Qcow2, @@ -2987,7 +2987,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"sata1": "test2:100/vm-100-disk-47.qcow2,mbps_wr_max=4.51"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51}}}, Format: QemuDiskFormat_Qcow2, Id: uint47, Replicate: true, @@ -3052,9 +3052,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_IOuring, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 5, Concurrent: 10}, @@ -3163,7 +3163,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"sata4": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd=1.51"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -3172,7 +3172,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"sata5": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd_max=3.51"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -3181,7 +3181,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"sata0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr=2.51"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 2.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -3190,7 +3190,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"sata1": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr_max=4.51"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -3272,9 +3272,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Threads, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, @@ -3300,9 +3300,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Threads, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, @@ -3447,7 +3447,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"scsi11": "test:100/vm-100-disk-2.qcow2,mbps_rd=1.51"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1.51}}}, Format: QemuDiskFormat_Qcow2, Id: uint2, Replicate: true, @@ -3458,7 +3458,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"scsi12": "test:100/vm-100-disk-2.qcow2,mbps_rd_max=3.51"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51}}}, Format: QemuDiskFormat_Qcow2, Id: uint2, Replicate: true, @@ -3469,7 +3469,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"scsi13": "test:100/vm-100-disk-2.qcow2,mbps_wr=2.51"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 2.51}}}, Format: QemuDiskFormat_Qcow2, Id: uint2, Replicate: true, @@ -3480,7 +3480,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"scsi14": "test:100/vm-100-disk-2.qcow2,mbps_wr_max=4.51"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_14: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51}}}, Format: QemuDiskFormat_Qcow2, Id: uint2, Replicate: true, @@ -3556,9 +3556,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Threads, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, @@ -3678,7 +3678,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"scsi11": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd=1.51"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_11: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -3687,7 +3687,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"scsi12": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd_max=3.51"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_12: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -3696,7 +3696,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"scsi13": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr=2.51"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_13: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 2.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -3705,7 +3705,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"scsi14": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr_max=4.51"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_14: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -3796,9 +3796,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_IOuring, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 2, Concurrent: 10}, @@ -3823,9 +3823,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_IOuring, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 2, Concurrent: 10}, @@ -3970,8 +3970,8 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1.51}, }, }, Format: QemuDiskFormat_Qcow2, @@ -3984,7 +3984,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"virtio12": "test2:100/vm-100-disk-31.qcow2,mbps_rd_max=3.51"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51}}}, Format: QemuDiskFormat_Qcow2, Id: uint31, Replicate: true, @@ -3995,7 +3995,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"virtio13": "test2:100/vm-100-disk-31.qcow2,mbps_wr=2.51"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 2.51}}}, Format: QemuDiskFormat_Qcow2, Id: uint31, Replicate: true, @@ -4006,7 +4006,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"virtio14": "test2:100/vm-100-disk-31.qcow2,mbps_wr_max=4.51"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_14: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51}}}, Format: QemuDiskFormat_Qcow2, Id: uint31, Replicate: true, @@ -4071,9 +4071,9 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { AsyncIO: QemuDiskAsyncIO_Native, Backup: false, Bandwidth: QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51, Concurrent: 2.51}, + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, }, Iops: QemuDiskBandwidthIops{ ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, @@ -4192,7 +4192,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"virtio11": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd=1.51"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_11: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 1.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 1.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -4201,7 +4201,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"virtio12": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_rd_max=3.51"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_12: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 3.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -4210,7 +4210,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"virtio13": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr=2.51"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 2.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 2.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -4219,7 +4219,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { input: map[string]interface{}{"virtio14": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8,mbps_wr_max=4.51"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_14: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ Backup: true, - Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 4.51}}}, + Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51}}}, File: "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8", Replicate: true, }}}}}, @@ -4291,12 +4291,12 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { } func Test_ConfigQemu_Validate(t *testing.T) { BandwidthValid0 := QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{ + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{ Burst: 0, Concurrent: 0, }, - WriteLimit: QemuDiskBandwidthDataLimit{ + WriteLimit: QemuDiskBandwidthMBpsLimit{ Burst: 0, Concurrent: 0, }, @@ -4313,12 +4313,12 @@ func Test_ConfigQemu_Validate(t *testing.T) { }, } BandwidthValid1 := QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{ + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{ Burst: 1, Concurrent: 1, }, - WriteLimit: QemuDiskBandwidthDataLimit{ + WriteLimit: QemuDiskBandwidthMBpsLimit{ Burst: 1, Concurrent: 1, }, @@ -4335,12 +4335,12 @@ func Test_ConfigQemu_Validate(t *testing.T) { }, } BandwidthValid2 := QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{ + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{ Burst: 1, Concurrent: 0, }, - WriteLimit: QemuDiskBandwidthDataLimit{ + WriteLimit: QemuDiskBandwidthMBpsLimit{ Burst: 1, Concurrent: 0, }, @@ -4357,12 +4357,12 @@ func Test_ConfigQemu_Validate(t *testing.T) { }, } BandwidthValid3 := QemuDiskBandwidth{ - Data: QemuDiskBandwidthData{ - ReadLimit: QemuDiskBandwidthDataLimit{ + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{ Burst: 0, Concurrent: 1, }, - WriteLimit: QemuDiskBandwidthDataLimit{ + WriteLimit: QemuDiskBandwidthMBpsLimit{ Burst: 0, Concurrent: 1, }, @@ -4997,21 +4997,21 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, - input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, - input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, - input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), }, - {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, - input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), + {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), }, {name: `Invalid Disks Disk Ide errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, @@ -5075,22 +5075,6 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, - input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, - input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, - input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, - input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), @@ -5107,6 +5091,22 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Disk Sata errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, {name: `Invalid Disks Disk Sata QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{Cache: "invalid"}}}}}, err: QemuDiskCache("").Error(), @@ -5153,22 +5153,6 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Disk: &QemuScsiDisk{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, - input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, - input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, - input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, - input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), @@ -5185,6 +5169,22 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Disk Scsi errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Disk: &QemuScsiDisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, {name: `Invalid Disks Disk Scsi QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_10: &QemuScsiStorage{Disk: &QemuScsiDisk{Cache: "invalid"}}}}}, err: QemuDiskCache("").Error(), @@ -5231,22 +5231,6 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, - input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, - input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, - input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, - input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_6: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), @@ -5263,6 +5247,22 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Disk VirtIO errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, {name: `Invalid Disks Disk VirtIO QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_10: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{Cache: "invalid"}}}}}, err: QemuDiskCache("").Error(), @@ -5305,22 +5305,6 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, - input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, - input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, - input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, - input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), @@ -5337,6 +5321,22 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Passthrough Ide errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, {name: `Invalid Disks Passthrough Ide QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Passthrough: &QemuIdePassthrough{Cache: "invalid"}}}}}, err: QemuDiskCache("").Error(), @@ -5358,22 +5358,6 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Passthrough: &QemuSataPassthrough{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, - input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, - input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, - input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, - input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), @@ -5390,6 +5374,22 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_2: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Passthrough Sata errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, {name: `Invalid Disks Passthrough Sata QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Passthrough: &QemuSataPassthrough{Cache: "invalid"}}}}}, err: QemuDiskCache("").Error(), @@ -5411,22 +5411,6 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_0: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, - input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, - input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, - input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, - input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_5: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), @@ -5443,6 +5427,22 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_8: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_2: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_3: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Passthrough Scsi errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_4: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, {name: `Invalid Disks Passthrough Scsi QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_9: &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{Cache: "invalid"}}}}}, err: QemuDiskCache("").Error(), @@ -5464,22 +5464,6 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_0: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{AsyncIO: "invalid"}}}}}, err: QemuDiskAsyncIO("").Error(), }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimitBurst) 0`, - input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 0`, - input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{ReadLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimitBurst) 1`, - input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Burst: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitBurst), - }, - {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthDataLimitConcurrent) 1`, - input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Data: QemuDiskBandwidthData{WriteLimit: QemuDiskBandwidthDataLimit{Concurrent: 0.99}}}}}}}}, - err: errors.New(Error_QemuDiskBandwidthDataLimitConcurrent), - }, {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthIopsLimitBurst) 0`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 9}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitBurst), @@ -5496,6 +5480,22 @@ func Test_ConfigQemu_Validate(t *testing.T) { input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{Iops: QemuDiskBandwidthIops{WriteLimit: QemuDiskBandwidthIopsLimit{Concurrent: 6}}}}}}}}, err: errors.New(Error_QemuDiskBandwidthIopsLimitConcurrent), }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 0`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{ReadLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthMBpsLimitBurst) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitBurst), + }, + {name: `Invalid Disks Passthrough VirtIO errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent) 1`, + input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_4: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Bandwidth: QemuDiskBandwidth{MBps: QemuDiskBandwidthMBps{WriteLimit: QemuDiskBandwidthMBpsLimit{Concurrent: 0.99}}}}}}}}, + err: errors.New(Error_QemuDiskBandwidthMBpsLimitConcurrent), + }, {name: `Invalid Disks Passthrough VirtIO QemuDiskCache("").Error()`, input: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_9: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{Cache: "invalid"}}}}}, err: QemuDiskCache("").Error(), From e2755e4df335fec2642ea53d6f1d54d11f98f5b8 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 3 Apr 2023 11:18:12 +0000 Subject: [PATCH 113/120] fix: merge conflicts Reimplement af4dd9aa7b0409bb150e2f5d3d13ba45933a4e66 and 37bbfd5bb759e04864c8bd575365878826af9dc3 --- proxmox/config_qemu.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 9b8d95be..4568ab39 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -290,6 +290,9 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (rebootRequire if config.QemuVcpus >= 1 { params["vcpus"] = config.QemuVcpus } + if config.Smbios1 != "" { + params["smbios1"] = config.Smbios1 + } if config.Iso != nil { if config.Disks == nil { @@ -463,6 +466,9 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (*ConfigQemu, error if _, isSet := params["tags"]; isSet { config.Tags = strings.TrimSpace(params["tags"].(string)) } + if _, isSet := params["smbios1"]; isSet { + config.Smbios1 = params["smbios1"].(string) + } ipconfigNames := []string{} From 29ce746d02b89607647d0d424d8518aa10828211 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:12:26 +0000 Subject: [PATCH 114/120] refactor: make `LinkedVmId` part of `ConfigQemu` before it was defined of each disk, but it is the same for all linked disk. thats why it's moved to `ConfigQemu`. when the vm has no linked disks `LinkedVmId` becomes `0` --- proxmox/config_qemu.go | 13 +- proxmox/config_qemu_disk.go | 82 +++-- proxmox/config_qemu_disk_ide.go | 100 +++--- proxmox/config_qemu_disk_sata.go | 104 +++--- proxmox/config_qemu_disk_scsi.go | 166 ++++----- proxmox/config_qemu_disk_test.go | 26 ++ proxmox/config_qemu_disk_virtio.go | 130 +++---- proxmox/config_qemu_test.go | 528 ++++++++++++++++------------- 8 files changed, 613 insertions(+), 536 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 4568ab39..14340834 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -55,6 +55,7 @@ type ConfigQemu struct { Hotplug string `json:"hotplug,omitempty"` // TODO should be a struct Ipconfig IpconfigMap `json:"ipconfig,omitempty"` // TODO should be part of a cloud-init struct (cloud-init option) Iso *IsoFile `json:"iso,omitempty"` // Same as Disks.Ide.Disk_2.CdRom.Iso + LinkedVmId uint `json:"linked_id,omitempty"` // Only returned setting it has no effect Machine string `json:"machine,omitempty"` // TODO should be custom type with enum Memory int `json:"memory,omitempty"` // TODO should be uint Name string `json:"name,omitempty"` // TODO should be custom type as there are character and length limitations @@ -311,14 +312,16 @@ func (config ConfigQemu) mapToApiValues(currentConfig ConfigQemu) (rebootRequire // Disks if currentConfig.Disks != nil { if config.Disks != nil { - delete := config.Disks.mapToApiValues(*currentConfig.Disks, uint(config.VmID), params) + // Create,Update,Delete + delete := config.Disks.mapToApiValues(*currentConfig.Disks, uint(config.VmID), currentConfig.LinkedVmId, params) if delete != "" { itemsToDelete = AddToList(itemsToDelete, delete) } } } else { if config.Disks != nil { - config.Disks.mapToApiValues(QemuStorages{}, uint(config.VmID), params) + // Create + config.Disks.mapToApiValues(QemuStorages{}, uint(config.VmID), 0, params) } } @@ -488,7 +491,11 @@ func (ConfigQemu) mapToStruct(params map[string]interface{}) (*ConfigQemu, error } } - config.Disks = QemuStorages{}.mapToStruct(params) + linkedVmId := uint(0) + config.Disks = QemuStorages{}.mapToStruct(params, &linkedVmId) + if linkedVmId != 0 { + config.LinkedVmId = linkedVmId + } if config.Disks != nil && config.Disks.Ide != nil && config.Disks.Ide.Disk_2 != nil && config.Disks.Ide.Disk_2.CdRom != nil { config.Iso = config.Disks.Ide.Disk_2.CdRom.Iso diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index faef43e5..ce2fd9c6 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -184,15 +184,15 @@ type qemuDisk struct { Disk bool // true = disk, false = passthrough EmulateSSD bool // Only set for ide,sata,scsi // TODO custom type - File string // Only set for Passthrough. - Format QemuDiskFormat // Only set for Disk - Id uint // Only set for Disk - IOThread bool // Only set for scsi,virtio - LinkedClone *QemuDiskLinkedClone // Only set for Disk - ReadOnly bool // Only set for scsi,virtio - Replicate bool - Serial QemuDiskSerial - Size uint + File string // Only set for Passthrough. + Format QemuDiskFormat // Only set for Disk + Id uint // Only set for Disk + IOThread bool // Only set for scsi,virtio + LinkedDiskId *uint // Only set for Disk + ReadOnly bool // Only set for scsi,virtio + Replicate bool + Serial QemuDiskSerial + Size uint // TODO custom type Storage string // Only set for Disk Type qemuDiskType @@ -206,7 +206,7 @@ const ( ) // Maps all the disk related settings to api values proxmox understands. -func (disk qemuDisk) mapToApiValues(vmID uint, currentStorage string, currentFormat QemuDiskFormat, create bool) (settings string) { +func (disk qemuDisk) mapToApiValues(vmID, LinkedVmId uint, currentStorage string, currentFormat QemuDiskFormat, create bool) (settings string) { if disk.Storage != "" { if create { settings = disk.Storage + ":" + strconv.Itoa(int(disk.Size)) @@ -214,10 +214,10 @@ func (disk qemuDisk) mapToApiValues(vmID uint, currentStorage string, currentFor tmpId := strconv.Itoa(int(vmID)) settings = tmpId + "/vm-" + tmpId + "-disk-" + strconv.Itoa(int(disk.Id)) + "." + string(disk.Format) // storage:100/vm-100-disk-0.raw - if disk.LinkedClone != nil && disk.Storage == currentStorage && disk.Format == currentFormat { + if disk.LinkedDiskId != nil && disk.Storage == currentStorage && disk.Format == currentFormat { // storage:110/base-110-disk-1.raw/100/vm-100-disk-0.raw - tmpId = strconv.Itoa(int(disk.LinkedClone.VmId)) - settings = tmpId + "/base-" + tmpId + "-disk-" + strconv.Itoa(int(disk.LinkedClone.DiskId)) + "." + string(disk.Format) + "/" + settings + tmpId = strconv.Itoa(int(LinkedVmId)) + settings = tmpId + "/base-" + tmpId + "-disk-" + strconv.Itoa(int(*disk.LinkedDiskId)) + "." + string(disk.Format) + "/" + settings } settings = disk.Storage + ":" + settings } @@ -300,7 +300,7 @@ func (disk qemuDisk) mapToApiValues(vmID uint, currentStorage string, currentFor } // Maps all the disk related settings to our own data structure. -func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { +func (qemuDisk) mapToStruct(settings [][]string, linkedVmId *uint) *qemuDisk { if len(settings) == 0 { return nil } @@ -309,8 +309,8 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { if settings[0][0][0:1] == "/" { disk.File = settings[0][0] } else { - // storage:110/base-110-disk-1.qcow2/100/vm-100-disk-0.qcow2, - // storage:100/vm-100-disk-0.qcow2, + // storage:110/base-110-disk-1.qcow2/100/vm-100-disk-0.qcow2 + // storage:100/vm-100-disk-0.qcow2 diskAndPath := strings.Split(settings[0][0], ":") disk.Storage = diskAndPath[0] if len(diskAndPath) == 2 { @@ -318,13 +318,12 @@ func (qemuDisk) mapToStruct(settings [][]string) *qemuDisk { if len(pathParts) == 4 { var tmpDiskId int tmpVmId, _ := strconv.Atoi(pathParts[0]) + *linkedVmId = uint(tmpVmId) tmp := strings.Split(strings.Split(pathParts[1], ".")[0], "-") if len(tmp) > 1 { tmpDiskId, _ = strconv.Atoi(tmp[len(tmp)-1]) - } - disk.LinkedClone = &QemuDiskLinkedClone{ - VmId: uint(tmpVmId), - DiskId: uint(tmpDiskId), + tmpDiskIdPointer := uint(tmpDiskId) + disk.LinkedDiskId = &tmpDiskIdPointer } } if len(pathParts) > 1 { @@ -715,11 +714,6 @@ func (id QemuDiskId) Validate() error { return errors.New(ERROR_QemuDiskId_Invalid) } -type QemuDiskLinkedClone struct { - DiskId uint `json:"disk"` - VmId uint `json:"vm"` -} - type qemuDiskMark struct { Format QemuDiskFormat Id QemuDiskId @@ -836,7 +830,7 @@ type qemuStorage struct { Passthrough *qemuDisk } -func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID uint, id QemuDiskId, params map[string]interface{}, delete string) string { +func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID, linkedVmId uint, id QemuDiskId, params map[string]interface{}, delete string) string { if storage == nil { return delete } @@ -878,20 +872,20 @@ func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID uin if storage.Disk != nil { if currentStorage == nil || currentStorage.Disk == nil { // Create - params[string(id)] = storage.Disk.mapToApiValues(vmID, "", "", true) + params[string(id)] = storage.Disk.mapToApiValues(vmID, 0, "", "", true) } else { if storage.Disk.Size >= currentStorage.Disk.Size { // Update storage.Disk.Id = currentStorage.Disk.Id - storage.Disk.LinkedClone = currentStorage.Disk.LinkedClone - disk := storage.Disk.mapToApiValues(vmID, currentStorage.Disk.Storage, currentStorage.Disk.Format, false) - if disk != currentStorage.Disk.mapToApiValues(vmID, currentStorage.Disk.Storage, currentStorage.Disk.Format, false) { + storage.Disk.LinkedDiskId = currentStorage.Disk.LinkedDiskId + disk := storage.Disk.mapToApiValues(vmID, linkedVmId, currentStorage.Disk.Storage, currentStorage.Disk.Format, false) + if disk != currentStorage.Disk.mapToApiValues(vmID, linkedVmId, currentStorage.Disk.Storage, currentStorage.Disk.Format, false) { params[string(id)] = disk } } else { // Delete and Create // creating a disk on top of an existing disk is the same as detaching the disk and creating a new one. - params[string(id)] = storage.Disk.mapToApiValues(vmID, "", "", true) + params[string(id)] = storage.Disk.mapToApiValues(vmID, 0, "", "", true) } } return delete @@ -903,11 +897,11 @@ func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID uin if storage.Passthrough != nil { if currentStorage == nil || currentStorage.Passthrough == nil { // Create - params[string(id)] = storage.Passthrough.mapToApiValues(0, "", "", false) + params[string(id)] = storage.Passthrough.mapToApiValues(0, 0, "", "", false) } else { // Update - passthrough := storage.Passthrough.mapToApiValues(0, "", "", false) - if passthrough != currentStorage.Passthrough.mapToApiValues(0, "", "", false) { + passthrough := storage.Passthrough.mapToApiValues(0, 0, "", "", false) + if passthrough != currentStorage.Passthrough.mapToApiValues(0, 0, "", "", false) { params[string(id)] = passthrough } } @@ -930,28 +924,28 @@ type QemuStorages struct { VirtIO *QemuVirtIODisks `json:"virtio,omitempty"` } -func (storages QemuStorages) mapToApiValues(currentStorages QemuStorages, vmID uint, params map[string]interface{}) (delete string) { +func (storages QemuStorages) mapToApiValues(currentStorages QemuStorages, vmID, linkedVmId uint, params map[string]interface{}) (delete string) { if storages.Ide != nil { - delete = storages.Ide.mapToApiValues(currentStorages.Ide, vmID, params, delete) + delete = storages.Ide.mapToApiValues(currentStorages.Ide, vmID, linkedVmId, params, delete) } if storages.Sata != nil { - delete = storages.Sata.mapToApiValues(currentStorages.Sata, vmID, params, delete) + delete = storages.Sata.mapToApiValues(currentStorages.Sata, vmID, linkedVmId, params, delete) } if storages.Scsi != nil { - delete = storages.Scsi.mapToApiValues(currentStorages.Scsi, vmID, params, delete) + delete = storages.Scsi.mapToApiValues(currentStorages.Scsi, vmID, linkedVmId, params, delete) } if storages.VirtIO != nil { - delete = storages.VirtIO.mapToApiValues(currentStorages.VirtIO, vmID, params, delete) + delete = storages.VirtIO.mapToApiValues(currentStorages.VirtIO, vmID, linkedVmId, params, delete) } return delete } -func (QemuStorages) mapToStruct(params map[string]interface{}) *QemuStorages { +func (QemuStorages) mapToStruct(params map[string]interface{}, linkedVmId *uint) *QemuStorages { storage := QemuStorages{ - Ide: QemuIdeDisks{}.mapToStruct(params), - Sata: QemuSataDisks{}.mapToStruct(params), - Scsi: QemuScsiDisks{}.mapToStruct(params), - VirtIO: QemuVirtIODisks{}.mapToStruct(params), + Ide: QemuIdeDisks{}.mapToStruct(params, linkedVmId), + Sata: QemuSataDisks{}.mapToStruct(params, linkedVmId), + Scsi: QemuScsiDisks{}.mapToStruct(params, linkedVmId), + VirtIO: QemuVirtIODisks{}.mapToStruct(params, linkedVmId), } if storage.Ide != nil || storage.Sata != nil || storage.Scsi != nil || storage.VirtIO != nil { return &storage diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index b7dd1eb8..d0746259 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -3,38 +3,38 @@ package proxmox import "strconv" type QemuIdeDisk struct { - AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup"` - Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` - Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard"` - EmulateSSD bool `json:"emulatessd"` - Format QemuDiskFormat `json:"format"` - Id uint `json:"id"` //Id is only returned and setting it has no effect - LinkedClone *QemuDiskLinkedClone `json:"linked"` //LinkedClone is only returned and setting it has no effect - Replicate bool `json:"replicate"` - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size"` - Storage string `json:"storage"` + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + Format QemuDiskFormat `json:"format"` + Id uint `json:"id"` //Id is only returned and setting it has no effect + LinkedDiskId *uint `json:"linked"` //LinkedClone is only returned and setting it has no effect + Replicate bool `json:"replicate"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuIdeDisk) convertDataStructure() *qemuDisk { return &qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - Disk: true, - EmulateSSD: disk.EmulateSSD, - Format: disk.Format, - Id: disk.Id, - LinkedClone: disk.LinkedClone, - Replicate: disk.Replicate, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: ide, + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + Disk: true, + EmulateSSD: disk.EmulateSSD, + Format: disk.Format, + Id: disk.Id, + LinkedDiskId: disk.LinkedDiskId, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: ide, } } @@ -49,7 +49,7 @@ type QemuIdeDisks struct { Disk_3 *QemuIdeStorage `json:"3,omitempty"` } -func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, vmID uint, params map[string]interface{}, delete string) string { +func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, vmID, LinkedVmId uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuIdeDisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks @@ -57,7 +57,7 @@ func (disks QemuIdeDisks) mapToApiValues(currentDisks *QemuIdeDisks, vmID uint, diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("ide"+strconv.Itoa(int(i))), params, delete) + delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, LinkedVmId, QemuDiskId("ide"+strconv.Itoa(int(i))), params, delete) } return delete } @@ -71,23 +71,23 @@ func (disks QemuIdeDisks) mapToIntMap() map[uint8]*QemuIdeStorage { } } -func (QemuIdeDisks) mapToStruct(params map[string]interface{}) *QemuIdeDisks { +func (QemuIdeDisks) mapToStruct(params map[string]interface{}, linkedVmId *uint) *QemuIdeDisks { disks := QemuIdeDisks{} var structPopulated bool if _, isSet := params["ide0"]; isSet { - disks.Disk_0 = QemuIdeStorage{}.mapToStruct(params["ide0"].(string)) + disks.Disk_0 = QemuIdeStorage{}.mapToStruct(params["ide0"].(string), linkedVmId) structPopulated = true } if _, isSet := params["ide1"]; isSet { - disks.Disk_1 = QemuIdeStorage{}.mapToStruct(params["ide1"].(string)) + disks.Disk_1 = QemuIdeStorage{}.mapToStruct(params["ide1"].(string), linkedVmId) structPopulated = true } if _, isSet := params["ide2"]; isSet { - disks.Disk_2 = QemuIdeStorage{}.mapToStruct(params["ide2"].(string)) + disks.Disk_2 = QemuIdeStorage{}.mapToStruct(params["ide2"].(string), linkedVmId) structPopulated = true } if _, isSet := params["ide3"]; isSet { - disks.Disk_3 = QemuIdeStorage{}.mapToStruct(params["ide3"].(string)) + disks.Disk_3 = QemuIdeStorage{}.mapToStruct(params["ide3"].(string), linkedVmId) structPopulated = true } if structPopulated { @@ -204,7 +204,7 @@ func (storage *QemuIdeStorage) convertDataStructureMark() *qemuDiskMark { return nil } -func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { +func (QemuIdeStorage) mapToStruct(param string, LinkedVmId *uint) *QemuIdeStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) if tmpCdRom != nil { @@ -215,25 +215,25 @@ func (QemuIdeStorage) mapToStruct(param string) *QemuIdeStorage { } } - tmpDisk := qemuDisk{}.mapToStruct(settings) + tmpDisk := qemuDisk{}.mapToStruct(settings, LinkedVmId) if tmpDisk == nil { return nil } if tmpDisk.File == "" { return &QemuIdeStorage{Disk: &QemuIdeDisk{ - AsyncIO: tmpDisk.AsyncIO, - Backup: tmpDisk.Backup, - Bandwidth: tmpDisk.Bandwidth, - Cache: tmpDisk.Cache, - Discard: tmpDisk.Discard, - EmulateSSD: tmpDisk.EmulateSSD, - Format: tmpDisk.Format, - Id: tmpDisk.Id, - LinkedClone: tmpDisk.LinkedClone, - Replicate: tmpDisk.Replicate, - Serial: tmpDisk.Serial, - Size: tmpDisk.Size, - Storage: tmpDisk.Storage, + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + Format: tmpDisk.Format, + Id: tmpDisk.Id, + LinkedDiskId: tmpDisk.LinkedDiskId, + Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, }} } return &QemuIdeStorage{Passthrough: &QemuIdePassthrough{ diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index f0f214e0..3e1cb7db 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -3,38 +3,38 @@ package proxmox import "strconv" type QemuSataDisk struct { - AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup"` - Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` - Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard"` - EmulateSSD bool `json:"emulatessd"` - Format QemuDiskFormat `json:"format"` - Id uint `json:"id"` //Id is only returned and setting it has no effect - LinkedClone *QemuDiskLinkedClone `json:"linked"` //LinkedClone is only returned and setting it has no effect - Replicate bool `json:"replicate"` - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size"` - Storage string `json:"storage"` + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + Format QemuDiskFormat `json:"format"` + Id uint `json:"id"` //Id is only returned and setting it has no effect + LinkedDiskId *uint `json:"linked"` //LinkedClone is only returned and setting it has no effect + Replicate bool `json:"replicate"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuSataDisk) convertDataStructure() *qemuDisk { return &qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - Disk: true, - EmulateSSD: disk.EmulateSSD, - Format: disk.Format, - Id: disk.Id, - LinkedClone: disk.LinkedClone, - Replicate: disk.Replicate, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: sata, + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + Disk: true, + EmulateSSD: disk.EmulateSSD, + Format: disk.Format, + Id: disk.Id, + LinkedDiskId: disk.LinkedDiskId, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: sata, } } @@ -51,7 +51,7 @@ type QemuSataDisks struct { Disk_5 *QemuSataStorage `json:"5,omitempty"` } -func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, vmID uint, params map[string]interface{}, delete string) string { +func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, vmID, LinkedVmId uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuSataDisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks @@ -59,7 +59,7 @@ func (disks QemuSataDisks) mapToApiValues(currentDisks *QemuSataDisks, vmID uint diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("sata"+strconv.Itoa(int(i))), params, delete) + delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, LinkedVmId, QemuDiskId("sata"+strconv.Itoa(int(i))), params, delete) } return delete } @@ -75,31 +75,31 @@ func (disks QemuSataDisks) mapToIntMap() map[uint8]*QemuSataStorage { } } -func (QemuSataDisks) mapToStruct(params map[string]interface{}) *QemuSataDisks { +func (QemuSataDisks) mapToStruct(params map[string]interface{}, linkedVmId *uint) *QemuSataDisks { disks := QemuSataDisks{} var structPopulated bool if _, isSet := params["sata0"]; isSet { - disks.Disk_0 = QemuSataStorage{}.mapToStruct(params["sata0"].(string)) + disks.Disk_0 = QemuSataStorage{}.mapToStruct(params["sata0"].(string), linkedVmId) structPopulated = true } if _, isSet := params["sata1"]; isSet { - disks.Disk_1 = QemuSataStorage{}.mapToStruct(params["sata1"].(string)) + disks.Disk_1 = QemuSataStorage{}.mapToStruct(params["sata1"].(string), linkedVmId) structPopulated = true } if _, isSet := params["sata2"]; isSet { - disks.Disk_2 = QemuSataStorage{}.mapToStruct(params["sata2"].(string)) + disks.Disk_2 = QemuSataStorage{}.mapToStruct(params["sata2"].(string), linkedVmId) structPopulated = true } if _, isSet := params["sata3"]; isSet { - disks.Disk_3 = QemuSataStorage{}.mapToStruct(params["sata3"].(string)) + disks.Disk_3 = QemuSataStorage{}.mapToStruct(params["sata3"].(string), linkedVmId) structPopulated = true } if _, isSet := params["sata4"]; isSet { - disks.Disk_4 = QemuSataStorage{}.mapToStruct(params["sata4"].(string)) + disks.Disk_4 = QemuSataStorage{}.mapToStruct(params["sata4"].(string), linkedVmId) structPopulated = true } if _, isSet := params["sata5"]; isSet { - disks.Disk_5 = QemuSataStorage{}.mapToStruct(params["sata5"].(string)) + disks.Disk_5 = QemuSataStorage{}.mapToStruct(params["sata5"].(string), linkedVmId) structPopulated = true } if structPopulated { @@ -216,7 +216,7 @@ func (storage *QemuSataStorage) convertDataStructureMark() *qemuDiskMark { return nil } -func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { +func (QemuSataStorage) mapToStruct(param string, LinkedVmId *uint) *QemuSataStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) if tmpCdRom != nil { @@ -227,25 +227,25 @@ func (QemuSataStorage) mapToStruct(param string) *QemuSataStorage { } } - tmpDisk := qemuDisk{}.mapToStruct(settings) + tmpDisk := qemuDisk{}.mapToStruct(settings, LinkedVmId) if tmpDisk == nil { return nil } if tmpDisk.File == "" { return &QemuSataStorage{Disk: &QemuSataDisk{ - AsyncIO: tmpDisk.AsyncIO, - Backup: tmpDisk.Backup, - Bandwidth: tmpDisk.Bandwidth, - Cache: tmpDisk.Cache, - Discard: tmpDisk.Discard, - EmulateSSD: tmpDisk.EmulateSSD, - Format: tmpDisk.Format, - Id: tmpDisk.Id, - LinkedClone: tmpDisk.LinkedClone, - Replicate: tmpDisk.Replicate, - Serial: tmpDisk.Serial, - Size: tmpDisk.Size, - Storage: tmpDisk.Storage, + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + Format: tmpDisk.Format, + Id: tmpDisk.Id, + LinkedDiskId: tmpDisk.LinkedDiskId, + Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, }} } return &QemuSataStorage{Passthrough: &QemuSataPassthrough{ diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 2cc6cb6d..43b83be8 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -3,42 +3,42 @@ package proxmox import "strconv" type QemuScsiDisk struct { - AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup"` - Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` - Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard"` - EmulateSSD bool `json:"emulatessd"` - Format QemuDiskFormat `json:"format"` - Id uint `json:"id"` //Id is only returned and setting it has no effect - IOThread bool `json:"iothread"` - LinkedClone *QemuDiskLinkedClone `json:"linked"` //LinkedCloneId is only returned and setting it has no effect - ReadOnly bool `json:"readonly"` - Replicate bool `json:"replicate"` - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size"` - Storage string `json:"storage"` + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + EmulateSSD bool `json:"emulatessd"` + Format QemuDiskFormat `json:"format"` + Id uint `json:"id"` //Id is only returned and setting it has no effect + IOThread bool `json:"iothread"` + LinkedDiskId *uint `json:"linked"` //LinkedCloneId is only returned and setting it has no effect + ReadOnly bool `json:"readonly"` + Replicate bool `json:"replicate"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuScsiDisk) convertDataStructure() *qemuDisk { return &qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - Disk: true, - EmulateSSD: disk.EmulateSSD, - Format: disk.Format, - Id: disk.Id, - IOThread: disk.IOThread, - LinkedClone: disk.LinkedClone, - ReadOnly: disk.ReadOnly, - Replicate: disk.Replicate, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: scsi, + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + Disk: true, + EmulateSSD: disk.EmulateSSD, + Format: disk.Format, + Id: disk.Id, + IOThread: disk.IOThread, + LinkedDiskId: disk.LinkedDiskId, + ReadOnly: disk.ReadOnly, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: scsi, } } @@ -80,7 +80,7 @@ type QemuScsiDisks struct { Disk_30 *QemuScsiStorage `json:"30,omitempty"` } -func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, vmID uint, params map[string]interface{}, delete string) string { +func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, vmID, linkedVmId uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuScsiDisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks @@ -88,7 +88,7 @@ func (disks QemuScsiDisks) mapToApiValues(currentDisks *QemuScsiDisks, vmID uint diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("scsi"+strconv.Itoa(int(i))), params, delete) + delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, linkedVmId, QemuDiskId("scsi"+strconv.Itoa(int(i))), params, delete) } return delete } @@ -129,131 +129,131 @@ func (disks QemuScsiDisks) mapToIntMap() map[uint8]*QemuScsiStorage { } } -func (QemuScsiDisks) mapToStruct(params map[string]interface{}) *QemuScsiDisks { +func (QemuScsiDisks) mapToStruct(params map[string]interface{}, linkedVmId *uint) *QemuScsiDisks { disks := QemuScsiDisks{} var structPopulated bool if _, isSet := params["scsi0"]; isSet { - disks.Disk_0 = QemuScsiStorage{}.mapToStruct(params["scsi0"].(string)) + disks.Disk_0 = QemuScsiStorage{}.mapToStruct(params["scsi0"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi1"]; isSet { - disks.Disk_1 = QemuScsiStorage{}.mapToStruct(params["scsi1"].(string)) + disks.Disk_1 = QemuScsiStorage{}.mapToStruct(params["scsi1"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi2"]; isSet { - disks.Disk_2 = QemuScsiStorage{}.mapToStruct(params["scsi2"].(string)) + disks.Disk_2 = QemuScsiStorage{}.mapToStruct(params["scsi2"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi3"]; isSet { - disks.Disk_3 = QemuScsiStorage{}.mapToStruct(params["scsi3"].(string)) + disks.Disk_3 = QemuScsiStorage{}.mapToStruct(params["scsi3"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi4"]; isSet { - disks.Disk_4 = QemuScsiStorage{}.mapToStruct(params["scsi4"].(string)) + disks.Disk_4 = QemuScsiStorage{}.mapToStruct(params["scsi4"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi5"]; isSet { - disks.Disk_5 = QemuScsiStorage{}.mapToStruct(params["scsi5"].(string)) + disks.Disk_5 = QemuScsiStorage{}.mapToStruct(params["scsi5"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi6"]; isSet { - disks.Disk_6 = QemuScsiStorage{}.mapToStruct(params["scsi6"].(string)) + disks.Disk_6 = QemuScsiStorage{}.mapToStruct(params["scsi6"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi7"]; isSet { - disks.Disk_7 = QemuScsiStorage{}.mapToStruct(params["scsi7"].(string)) + disks.Disk_7 = QemuScsiStorage{}.mapToStruct(params["scsi7"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi8"]; isSet { - disks.Disk_8 = QemuScsiStorage{}.mapToStruct(params["scsi8"].(string)) + disks.Disk_8 = QemuScsiStorage{}.mapToStruct(params["scsi8"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi9"]; isSet { - disks.Disk_9 = QemuScsiStorage{}.mapToStruct(params["scsi9"].(string)) + disks.Disk_9 = QemuScsiStorage{}.mapToStruct(params["scsi9"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi10"]; isSet { - disks.Disk_10 = QemuScsiStorage{}.mapToStruct(params["scsi10"].(string)) + disks.Disk_10 = QemuScsiStorage{}.mapToStruct(params["scsi10"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi11"]; isSet { - disks.Disk_11 = QemuScsiStorage{}.mapToStruct(params["scsi11"].(string)) + disks.Disk_11 = QemuScsiStorage{}.mapToStruct(params["scsi11"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi12"]; isSet { - disks.Disk_12 = QemuScsiStorage{}.mapToStruct(params["scsi12"].(string)) + disks.Disk_12 = QemuScsiStorage{}.mapToStruct(params["scsi12"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi13"]; isSet { - disks.Disk_13 = QemuScsiStorage{}.mapToStruct(params["scsi13"].(string)) + disks.Disk_13 = QemuScsiStorage{}.mapToStruct(params["scsi13"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi14"]; isSet { - disks.Disk_14 = QemuScsiStorage{}.mapToStruct(params["scsi14"].(string)) + disks.Disk_14 = QemuScsiStorage{}.mapToStruct(params["scsi14"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi15"]; isSet { - disks.Disk_15 = QemuScsiStorage{}.mapToStruct(params["scsi15"].(string)) + disks.Disk_15 = QemuScsiStorage{}.mapToStruct(params["scsi15"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi16"]; isSet { - disks.Disk_16 = QemuScsiStorage{}.mapToStruct(params["scsi16"].(string)) + disks.Disk_16 = QemuScsiStorage{}.mapToStruct(params["scsi16"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi17"]; isSet { - disks.Disk_17 = QemuScsiStorage{}.mapToStruct(params["scsi17"].(string)) + disks.Disk_17 = QemuScsiStorage{}.mapToStruct(params["scsi17"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi18"]; isSet { - disks.Disk_18 = QemuScsiStorage{}.mapToStruct(params["scsi18"].(string)) + disks.Disk_18 = QemuScsiStorage{}.mapToStruct(params["scsi18"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi19"]; isSet { - disks.Disk_19 = QemuScsiStorage{}.mapToStruct(params["scsi19"].(string)) + disks.Disk_19 = QemuScsiStorage{}.mapToStruct(params["scsi19"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi20"]; isSet { - disks.Disk_20 = QemuScsiStorage{}.mapToStruct(params["scsi20"].(string)) + disks.Disk_20 = QemuScsiStorage{}.mapToStruct(params["scsi20"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi21"]; isSet { - disks.Disk_21 = QemuScsiStorage{}.mapToStruct(params["scsi21"].(string)) + disks.Disk_21 = QemuScsiStorage{}.mapToStruct(params["scsi21"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi22"]; isSet { - disks.Disk_22 = QemuScsiStorage{}.mapToStruct(params["scsi22"].(string)) + disks.Disk_22 = QemuScsiStorage{}.mapToStruct(params["scsi22"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi23"]; isSet { - disks.Disk_23 = QemuScsiStorage{}.mapToStruct(params["scsi23"].(string)) + disks.Disk_23 = QemuScsiStorage{}.mapToStruct(params["scsi23"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi24"]; isSet { - disks.Disk_24 = QemuScsiStorage{}.mapToStruct(params["scsi24"].(string)) + disks.Disk_24 = QemuScsiStorage{}.mapToStruct(params["scsi24"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi25"]; isSet { - disks.Disk_25 = QemuScsiStorage{}.mapToStruct(params["scsi25"].(string)) + disks.Disk_25 = QemuScsiStorage{}.mapToStruct(params["scsi25"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi26"]; isSet { - disks.Disk_26 = QemuScsiStorage{}.mapToStruct(params["scsi26"].(string)) + disks.Disk_26 = QemuScsiStorage{}.mapToStruct(params["scsi26"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi27"]; isSet { - disks.Disk_27 = QemuScsiStorage{}.mapToStruct(params["scsi27"].(string)) + disks.Disk_27 = QemuScsiStorage{}.mapToStruct(params["scsi27"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi28"]; isSet { - disks.Disk_28 = QemuScsiStorage{}.mapToStruct(params["scsi28"].(string)) + disks.Disk_28 = QemuScsiStorage{}.mapToStruct(params["scsi28"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi29"]; isSet { - disks.Disk_29 = QemuScsiStorage{}.mapToStruct(params["scsi29"].(string)) + disks.Disk_29 = QemuScsiStorage{}.mapToStruct(params["scsi29"].(string), linkedVmId) structPopulated = true } if _, isSet := params["scsi30"]; isSet { - disks.Disk_30 = QemuScsiStorage{}.mapToStruct(params["scsi30"].(string)) + disks.Disk_30 = QemuScsiStorage{}.mapToStruct(params["scsi30"].(string), linkedVmId) structPopulated = true } if structPopulated { @@ -374,7 +374,7 @@ func (storage *QemuScsiStorage) convertDataStructureMark() *qemuDiskMark { return nil } -func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { +func (QemuScsiStorage) mapToStruct(param string, LinkedVmId *uint) *QemuScsiStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) if tmpCdRom != nil { @@ -385,27 +385,27 @@ func (QemuScsiStorage) mapToStruct(param string) *QemuScsiStorage { } } - tmpDisk := qemuDisk{}.mapToStruct(settings) + tmpDisk := qemuDisk{}.mapToStruct(settings, LinkedVmId) if tmpDisk == nil { return nil } if tmpDisk.File == "" { return &QemuScsiStorage{Disk: &QemuScsiDisk{ - AsyncIO: tmpDisk.AsyncIO, - Backup: tmpDisk.Backup, - Bandwidth: tmpDisk.Bandwidth, - Cache: tmpDisk.Cache, - Discard: tmpDisk.Discard, - EmulateSSD: tmpDisk.EmulateSSD, - Format: tmpDisk.Format, - Id: tmpDisk.Id, - IOThread: tmpDisk.IOThread, - LinkedClone: tmpDisk.LinkedClone, - ReadOnly: tmpDisk.ReadOnly, - Replicate: tmpDisk.Replicate, - Serial: tmpDisk.Serial, - Size: tmpDisk.Size, - Storage: tmpDisk.Storage, + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + EmulateSSD: tmpDisk.EmulateSSD, + Format: tmpDisk.Format, + Id: tmpDisk.Id, + IOThread: tmpDisk.IOThread, + LinkedDiskId: tmpDisk.LinkedDiskId, + ReadOnly: tmpDisk.ReadOnly, + Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, }} } return &QemuScsiStorage{Passthrough: &QemuScsiPassthrough{ diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 943048f5..167b8f07 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -87,6 +87,32 @@ func Test_QemuCloudInitDisk_Validate(t *testing.T) { } } +func Test_qemuDisk_mapToStruct(t *testing.T) { + tests := []struct { + name string + input [][]string + linkedVmId uint + output uint + }{ + {name: "Don't Update LinkedVmId", + input: [][]string{{"storage:100/vm-100-disk-0.qcow2"}}, + linkedVmId: 110, + output: 110, + }, + {name: "Update LinkedVmId", + input: [][]string{{"storage:110/base-110-disk-1.qcow2/100/vm-100-disk-0.qcow2"}}, + output: 110, + }, + } + for _, test := range tests { + t.Run(test.name, func(*testing.T) { + linkedVmId := uint(test.linkedVmId) + qemuDisk{}.mapToStruct(test.input, &linkedVmId) + require.Equal(t, test.output, linkedVmId, test.name) + }) + } +} + func Test_QemuDiskAsyncIO_Validate(t *testing.T) { testData := []struct { name string diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 4fd8c273..95485877 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -3,40 +3,40 @@ package proxmox import "strconv" type QemuVirtIODisk struct { - AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` - Backup bool `json:"backup"` - Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` - Cache QemuDiskCache `json:"cache,omitempty"` - Discard bool `json:"discard"` - Format QemuDiskFormat `json:"format"` - Id uint `json:"id"` //Id is only returned and setting it has no effect - IOThread bool `json:"iothread"` - LinkedClone *QemuDiskLinkedClone `json:"linked"` //LinkedCloneId is only returned and setting it has no effect - ReadOnly bool `json:"readonly"` - Replicate bool `json:"replicate"` - Serial QemuDiskSerial `json:"serial,omitempty"` - Size uint `json:"size"` - Storage string `json:"storage"` + AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` + Backup bool `json:"backup"` + Bandwidth QemuDiskBandwidth `json:"bandwidth,omitempty"` + Cache QemuDiskCache `json:"cache,omitempty"` + Discard bool `json:"discard"` + Format QemuDiskFormat `json:"format"` + Id uint `json:"id"` //Id is only returned and setting it has no effect + IOThread bool `json:"iothread"` + LinkedDiskId *uint `json:"linked"` //LinkedCloneId is only returned and setting it has no effect + ReadOnly bool `json:"readonly"` + Replicate bool `json:"replicate"` + Serial QemuDiskSerial `json:"serial,omitempty"` + Size uint `json:"size"` + Storage string `json:"storage"` } func (disk *QemuVirtIODisk) convertDataStructure() *qemuDisk { return &qemuDisk{ - AsyncIO: disk.AsyncIO, - Backup: disk.Backup, - Bandwidth: disk.Bandwidth, - Cache: disk.Cache, - Discard: disk.Discard, - Disk: true, - Format: disk.Format, - Id: disk.Id, - IOThread: disk.IOThread, - LinkedClone: disk.LinkedClone, - ReadOnly: disk.ReadOnly, - Replicate: disk.Replicate, - Serial: disk.Serial, - Size: disk.Size, - Storage: disk.Storage, - Type: virtIO, + AsyncIO: disk.AsyncIO, + Backup: disk.Backup, + Bandwidth: disk.Bandwidth, + Cache: disk.Cache, + Discard: disk.Discard, + Disk: true, + Format: disk.Format, + Id: disk.Id, + IOThread: disk.IOThread, + LinkedDiskId: disk.LinkedDiskId, + ReadOnly: disk.ReadOnly, + Replicate: disk.Replicate, + Serial: disk.Serial, + Size: disk.Size, + Storage: disk.Storage, + Type: virtIO, } } @@ -63,7 +63,7 @@ type QemuVirtIODisks struct { Disk_15 *QemuVirtIOStorage `json:"15,omitempty"` } -func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, vmID uint, params map[string]interface{}, delete string) string { +func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, vmID, linkedVmId uint, params map[string]interface{}, delete string) string { tmpCurrentDisks := QemuVirtIODisks{} if currentDisks != nil { tmpCurrentDisks = *currentDisks @@ -71,7 +71,7 @@ func (disks QemuVirtIODisks) mapToApiValues(currentDisks *QemuVirtIODisks, vmID diskMap := disks.mapToIntMap() currentDiskMap := tmpCurrentDisks.mapToIntMap() for i := range diskMap { - delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, QemuDiskId("virtio"+strconv.Itoa(int(i))), params, delete) + delete = diskMap[i].convertDataStructure().mapToApiValues(currentDiskMap[i].convertDataStructure(), vmID, linkedVmId, QemuDiskId("virtio"+strconv.Itoa(int(i))), params, delete) } return delete } @@ -97,71 +97,71 @@ func (disks QemuVirtIODisks) mapToIntMap() map[uint8]*QemuVirtIOStorage { } } -func (QemuVirtIODisks) mapToStruct(params map[string]interface{}) *QemuVirtIODisks { +func (QemuVirtIODisks) mapToStruct(params map[string]interface{}, linkedVmId *uint) *QemuVirtIODisks { disks := QemuVirtIODisks{} var structPopulated bool if _, isSet := params["virtio0"]; isSet { - disks.Disk_0 = QemuVirtIOStorage{}.mapToStruct(params["virtio0"].(string)) + disks.Disk_0 = QemuVirtIOStorage{}.mapToStruct(params["virtio0"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio1"]; isSet { - disks.Disk_1 = QemuVirtIOStorage{}.mapToStruct(params["virtio1"].(string)) + disks.Disk_1 = QemuVirtIOStorage{}.mapToStruct(params["virtio1"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio2"]; isSet { - disks.Disk_2 = QemuVirtIOStorage{}.mapToStruct(params["virtio2"].(string)) + disks.Disk_2 = QemuVirtIOStorage{}.mapToStruct(params["virtio2"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio3"]; isSet { - disks.Disk_3 = QemuVirtIOStorage{}.mapToStruct(params["virtio3"].(string)) + disks.Disk_3 = QemuVirtIOStorage{}.mapToStruct(params["virtio3"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio4"]; isSet { - disks.Disk_4 = QemuVirtIOStorage{}.mapToStruct(params["virtio4"].(string)) + disks.Disk_4 = QemuVirtIOStorage{}.mapToStruct(params["virtio4"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio5"]; isSet { - disks.Disk_5 = QemuVirtIOStorage{}.mapToStruct(params["virtio5"].(string)) + disks.Disk_5 = QemuVirtIOStorage{}.mapToStruct(params["virtio5"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio6"]; isSet { - disks.Disk_6 = QemuVirtIOStorage{}.mapToStruct(params["virtio6"].(string)) + disks.Disk_6 = QemuVirtIOStorage{}.mapToStruct(params["virtio6"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio7"]; isSet { - disks.Disk_7 = QemuVirtIOStorage{}.mapToStruct(params["virtio7"].(string)) + disks.Disk_7 = QemuVirtIOStorage{}.mapToStruct(params["virtio7"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio8"]; isSet { - disks.Disk_8 = QemuVirtIOStorage{}.mapToStruct(params["virtio8"].(string)) + disks.Disk_8 = QemuVirtIOStorage{}.mapToStruct(params["virtio8"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio9"]; isSet { - disks.Disk_9 = QemuVirtIOStorage{}.mapToStruct(params["virtio9"].(string)) + disks.Disk_9 = QemuVirtIOStorage{}.mapToStruct(params["virtio9"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio10"]; isSet { - disks.Disk_10 = QemuVirtIOStorage{}.mapToStruct(params["virtio10"].(string)) + disks.Disk_10 = QemuVirtIOStorage{}.mapToStruct(params["virtio10"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio11"]; isSet { - disks.Disk_11 = QemuVirtIOStorage{}.mapToStruct(params["virtio11"].(string)) + disks.Disk_11 = QemuVirtIOStorage{}.mapToStruct(params["virtio11"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio12"]; isSet { - disks.Disk_12 = QemuVirtIOStorage{}.mapToStruct(params["virtio12"].(string)) + disks.Disk_12 = QemuVirtIOStorage{}.mapToStruct(params["virtio12"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio13"]; isSet { - disks.Disk_13 = QemuVirtIOStorage{}.mapToStruct(params["virtio13"].(string)) + disks.Disk_13 = QemuVirtIOStorage{}.mapToStruct(params["virtio13"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio14"]; isSet { - disks.Disk_14 = QemuVirtIOStorage{}.mapToStruct(params["virtio14"].(string)) + disks.Disk_14 = QemuVirtIOStorage{}.mapToStruct(params["virtio14"].(string), linkedVmId) structPopulated = true } if _, isSet := params["virtio15"]; isSet { - disks.Disk_15 = QemuVirtIOStorage{}.mapToStruct(params["virtio15"].(string)) + disks.Disk_15 = QemuVirtIOStorage{}.mapToStruct(params["virtio15"].(string), linkedVmId) structPopulated = true } if structPopulated { @@ -280,7 +280,7 @@ func (storage *QemuVirtIOStorage) convertDataStructureMark() *qemuDiskMark { return nil } -func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { +func (QemuVirtIOStorage) mapToStruct(param string, LinkedVmId *uint) *QemuVirtIOStorage { settings := splitStringOfSettings(param) tmpCdRom := qemuCdRom{}.mapToStruct(settings) if tmpCdRom != nil { @@ -291,26 +291,26 @@ func (QemuVirtIOStorage) mapToStruct(param string) *QemuVirtIOStorage { } } - tmpDisk := qemuDisk{}.mapToStruct(settings) + tmpDisk := qemuDisk{}.mapToStruct(settings, LinkedVmId) if tmpDisk == nil { return nil } if tmpDisk.File == "" { return &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ - AsyncIO: tmpDisk.AsyncIO, - Backup: tmpDisk.Backup, - Bandwidth: tmpDisk.Bandwidth, - Cache: tmpDisk.Cache, - Discard: tmpDisk.Discard, - Format: tmpDisk.Format, - Id: tmpDisk.Id, - IOThread: tmpDisk.IOThread, - LinkedClone: tmpDisk.LinkedClone, - ReadOnly: tmpDisk.ReadOnly, - Replicate: tmpDisk.Replicate, - Serial: tmpDisk.Serial, - Size: tmpDisk.Size, - Storage: tmpDisk.Storage, + AsyncIO: tmpDisk.AsyncIO, + Backup: tmpDisk.Backup, + Bandwidth: tmpDisk.Bandwidth, + Cache: tmpDisk.Cache, + Discard: tmpDisk.Discard, + Format: tmpDisk.Format, + Id: tmpDisk.Id, + IOThread: tmpDisk.IOThread, + LinkedDiskId: tmpDisk.LinkedDiskId, + ReadOnly: tmpDisk.ReadOnly, + Replicate: tmpDisk.Replicate, + Serial: tmpDisk.Serial, + Size: tmpDisk.Size, + Storage: tmpDisk.Storage, }} } return &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{ diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index 2e8c24cf..6d19150b 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -15,6 +15,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { float45 := QemuDiskBandwidthMBpsLimitConcurrent(45.23) float79 := QemuDiskBandwidthMBpsLimitBurst(79.23) float99 := QemuDiskBandwidthMBpsLimitBurst(99.2) + uint1 := uint(1) uint23 := QemuDiskBandwidthIopsLimitConcurrent(23) uint34 := QemuDiskBandwidthIopsLimitConcurrent(34) uint78 := QemuDiskBandwidthIopsLimitBurst(78) @@ -1275,14 +1276,16 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"ide3": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, }, {name: "Update Disk.Ide.Disk_X.Disk CHANGE LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ - AsyncIO: QemuDiskAsyncIO_IOuring, - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ AsyncIO: QemuDiskAsyncIO_Native, Format: QemuDiskFormat_Raw, @@ -1311,13 +1314,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"ide1": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, {name: "Update Disk.Ide.Disk_X.Disk MIGRATE LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{DiskId: 1, VmId: 100}, - Size: 10, - Storage: "test1", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test1", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Raw, Size: 10, @@ -1340,13 +1345,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"ide2": "test:9,backup=0,format=raw,replicate=0"}, }, {name: "Update Disk.Ide.Disk_X.Disk RESIZE DOWN LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Raw, Size: 9, @@ -1369,13 +1376,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{}, }, {name: "Update Disk.Ide.Disk_X.Disk RESIZE UP LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 110, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 110, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Raw, Size: 11, @@ -1407,13 +1416,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"ide1": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, }, {name: "Update Disk.Ide.Disk_X.Disk.Format CHANGE LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Qcow2, Size: 10, @@ -1537,14 +1548,16 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"sata3": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, }, {name: "Update Disk.Sata.Disk_X.Disk CHANGE LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ - AsyncIO: QemuDiskAsyncIO_IOuring, - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ AsyncIO: QemuDiskAsyncIO_Native, Format: QemuDiskFormat_Raw, @@ -1573,13 +1586,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"sata5": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, {name: "Update Disk.Sata.Disk_X.Disk MIGRATE LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{DiskId: 1, VmId: 100}, - Size: 10, - Storage: "test1", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test1", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Raw, Size: 10, @@ -1602,13 +1617,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"sata0": "test:9,backup=0,format=raw,replicate=0"}, }, {name: "Update Disk.Sata.Disk_X.Disk RESIZE DOWN LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Raw, Size: 9, @@ -1631,13 +1648,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{}, }, {name: "Update Disk.Sata.Disk_X.Disk RESIZE UP LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Raw, Size: 11, @@ -1669,13 +1688,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"sata3": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, }, {name: "Update Disk.Sata.Disk_X.Disk.Format CHANGE LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Qcow2, Size: 10, @@ -1799,14 +1820,16 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"scsi15": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, }, {name: "Update Disk.Scsi.Disk_X.Disk CHANGE LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ - AsyncIO: QemuDiskAsyncIO_IOuring, - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ AsyncIO: QemuDiskAsyncIO_Native, Format: QemuDiskFormat_Raw, @@ -1835,13 +1858,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"scsi17": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, {name: "Update Disk.Scsi.Disk_X.Disk MIGRATE Linked Clone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{DiskId: 1, VmId: 100}, - Size: 10, - Storage: "test1", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test1", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, Size: 10, @@ -1864,13 +1889,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"scsi18": "test:9,backup=0,format=raw,replicate=0"}, }, {name: "Update Disk.Scsi.Disk_X.Disk RESIZE DOWN LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, Size: 9, @@ -1893,13 +1920,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{}, }, {name: "Update Disk.Scsi.Disk_X.Disk RESIZE UP LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, Size: 11, @@ -1931,13 +1960,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"scsi21": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, }, {name: "Update Disk.Scsi.Disk_X.Disk.Format CHANGE LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Qcow2, Size: 10, @@ -2061,14 +2092,16 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"virtio15": "test:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, }, {name: "Update Disk.VirtIO.Disk_X.Disk CHANGE LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ - AsyncIO: QemuDiskAsyncIO_IOuring, - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ AsyncIO: QemuDiskAsyncIO_Native, Format: QemuDiskFormat_Raw, @@ -2097,13 +2130,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"virtio1": "test2:0/vm-0-disk-23.raw,backup=0,replicate=0"}, }, {name: "Update Disk.VirtIO.Disk_X.Disk MIGRATE LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{DiskId: 1, VmId: 100}, - Size: 10, - Storage: "test1", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test1", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Raw, Size: 10, @@ -2126,13 +2161,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"virtio2": "test:9,backup=0,format=raw,replicate=0"}, }, {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE DOWN LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Raw, Size: 9, @@ -2155,13 +2192,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{}, }, {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE UP LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Raw, Size: 11, @@ -2193,13 +2232,15 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"virtio5": "test:0/vm-0-disk-23.qcow2,backup=0,replicate=0"}, }, {name: "Update Disk.VirtIO.Disk_X.Disk.Format CHANGE LinkedClone", - currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ - Format: QemuDiskFormat_Raw, - Id: 23, - LinkedClone: &QemuDiskLinkedClone{VmId: 100, DiskId: 1}, - Size: 10, - Storage: "test", - }}}}}, + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Qcow2, Size: 10, @@ -2259,6 +2300,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { } func Test_ConfigQemu_mapToStruct(t *testing.T) { + uint1 := uint(1) uint2 := uint(2) uint31 := uint(31) uint47 := uint(47) @@ -2334,30 +2376,32 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }, {name: "Disks Ide Disk ALL LinkedClone", input: map[string]interface{}{"ide1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-53.qcow2,aio=io_uring,backup=0,cache=writethrough,discard=on,iops_rd=12,iops_rd_max=13,iops_rd_max_length=4,iops_wr=15,iops_wr_max=14,iops_wr_max_length=5,mbps_rd=1.46,mbps_rd_max=3.57,mbps_wr=2.68,mbps_wr_max=4.55,replicate=0,serial=disk-9763,size=1032G,ssd=1"}, - output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ - AsyncIO: QemuDiskAsyncIO_IOuring, - Backup: false, - Bandwidth: QemuDiskBandwidth{ - MBps: QemuDiskBandwidthMBps{ - ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.57, Concurrent: 1.46}, - WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.55, Concurrent: 2.68}, - }, - Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 4, Concurrent: 12}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 14, BurstDuration: 5, Concurrent: 15}, + output: &ConfigQemu{ + LinkedVmId: 110, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.57, Concurrent: 1.46}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.55, Concurrent: 2.68}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 4, Concurrent: 12}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 14, BurstDuration: 5, Concurrent: 15}, + }, }, - }, - Cache: QemuDiskCache_WriteThrough, - Discard: true, - EmulateSSD: true, - Format: QemuDiskFormat_Qcow2, - Id: uint53, - LinkedClone: &QemuDiskLinkedClone{VmId: 110, DiskId: 1}, - Replicate: false, - Serial: "disk-9763", - Size: 1032, - Storage: "test2", - }}}}}, + Cache: QemuDiskCache_WriteThrough, + Discard: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: uint53, + LinkedDiskId: &uint1, + Replicate: false, + Serial: "disk-9763", + Size: 1032, + Storage: "test2", + }}}}}, }, {name: "Disks Ide Disk aio", input: map[string]interface{}{"ide2": "test2:100/vm-100-disk-53.qcow2,aio=io_uring"}, @@ -2812,30 +2856,32 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }, {name: "Disks Sata Disk ALL LinkedClone", input: map[string]interface{}{"sata1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-47.qcow2,aio=native,backup=0,cache=none,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=4,iops_wr=11,iops_wr_max=13,iops_wr_max_length=5,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,serial=disk-9763,size=32G,ssd=1"}, - output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ - AsyncIO: QemuDiskAsyncIO_Native, - Backup: false, - Bandwidth: QemuDiskBandwidth{ - MBps: QemuDiskBandwidthMBps{ - ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, - }, - Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 5, Concurrent: 11}, + output: &ConfigQemu{ + LinkedVmId: 110, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 5, Concurrent: 11}, + }, }, - }, - Cache: QemuDiskCache_None, - Discard: true, - EmulateSSD: true, - Format: QemuDiskFormat_Qcow2, - Id: uint47, - LinkedClone: &QemuDiskLinkedClone{VmId: 110, DiskId: 1}, - Replicate: false, - Serial: "disk-9763", - Size: 32, - Storage: "test2", - }}}}}, + Cache: QemuDiskCache_None, + Discard: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: uint47, + LinkedDiskId: &uint1, + Replicate: false, + Serial: "disk-9763", + Size: 32, + Storage: "test2", + }}}}}, }, {name: "Disks Sata Disk aio", input: map[string]interface{}{"sata2": "test2:100/vm-100-disk-47.qcow2,aio=native"}, @@ -3296,32 +3342,34 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }, {name: "Disks Scsi Disk ALL LinkedClone", input: map[string]interface{}{"scsi1": "test:110/base-110-disk-1.qcow2/100/vm-100-disk-2.qcow2,aio=threads,backup=0,cache=writeback,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=4,iops_wr=11,iops_wr_max=13,iops_wr_max_length=5,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G,ssd=1"}, - output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Disk: &QemuScsiDisk{ - AsyncIO: QemuDiskAsyncIO_Threads, - Backup: false, - Bandwidth: QemuDiskBandwidth{ - MBps: QemuDiskBandwidthMBps{ - ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, - }, - Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 5, Concurrent: 11}, + output: &ConfigQemu{ + LinkedVmId: 110, + Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_1: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_Threads, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 4, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 5, Concurrent: 11}, + }, }, - }, - Cache: QemuDiskCache_WriteBack, - Discard: true, - EmulateSSD: true, - Format: QemuDiskFormat_Qcow2, - Id: uint2, - IOThread: true, - LinkedClone: &QemuDiskLinkedClone{VmId: 110, DiskId: 1}, - ReadOnly: true, - Replicate: false, - Serial: "disk-9763", - Size: 32, - Storage: "test", - }}}}}, + Cache: QemuDiskCache_WriteBack, + Discard: true, + EmulateSSD: true, + Format: QemuDiskFormat_Qcow2, + Id: uint2, + IOThread: true, + LinkedDiskId: &uint1, + ReadOnly: true, + Replicate: false, + Serial: "disk-9763", + Size: 32, + Storage: "test", + }}}}}, }, {name: "Disks Scsi Disk aio", input: map[string]interface{}{"scsi2": "test:100/vm-100-disk-2.qcow2,aio=threads"}, @@ -3819,31 +3867,33 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }, {name: "Disks VirtIO Disk ALL LinkedClone", input: map[string]interface{}{"virtio1": "test2:110/base-110-disk-1.qcow2/100/vm-100-disk-31.qcow2,aio=io_uring,backup=0,cache=directsync,discard=on,iops_rd=10,iops_rd_max=12,iops_rd_max_length=2,iops_wr=11,iops_wr_max=13,iops_wr_max_length=3,iothread=1,mbps_rd=1.51,mbps_rd_max=3.51,mbps_wr=2.51,mbps_wr_max=4.51,replicate=0,ro=1,serial=disk-9763,size=32G"}, - output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ - AsyncIO: QemuDiskAsyncIO_IOuring, - Backup: false, - Bandwidth: QemuDiskBandwidth{ - MBps: QemuDiskBandwidthMBps{ - ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, - WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, - }, - Iops: QemuDiskBandwidthIops{ - ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 2, Concurrent: 10}, - WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 3, Concurrent: 11}, + output: &ConfigQemu{ + LinkedVmId: 110, + Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Backup: false, + Bandwidth: QemuDiskBandwidth{ + MBps: QemuDiskBandwidthMBps{ + ReadLimit: QemuDiskBandwidthMBpsLimit{Burst: 3.51, Concurrent: 1.51}, + WriteLimit: QemuDiskBandwidthMBpsLimit{Burst: 4.51, Concurrent: 2.51}, + }, + Iops: QemuDiskBandwidthIops{ + ReadLimit: QemuDiskBandwidthIopsLimit{Burst: 12, BurstDuration: 2, Concurrent: 10}, + WriteLimit: QemuDiskBandwidthIopsLimit{Burst: 13, BurstDuration: 3, Concurrent: 11}, + }, }, - }, - Cache: QemuDiskCache_DirectSync, - Discard: true, - Format: QemuDiskFormat_Qcow2, - Id: uint31, - IOThread: true, - LinkedClone: &QemuDiskLinkedClone{VmId: 110, DiskId: 1}, - ReadOnly: true, - Replicate: false, - Serial: "disk-9763", - Size: 32, - Storage: "test2", - }}}}}, + Cache: QemuDiskCache_DirectSync, + Discard: true, + Format: QemuDiskFormat_Qcow2, + Id: uint31, + IOThread: true, + LinkedDiskId: &uint1, + ReadOnly: true, + Replicate: false, + Serial: "disk-9763", + Size: 32, + Storage: "test2", + }}}}}, }, {name: "Disks VirtIO Disk aio", input: map[string]interface{}{"virtio2": "test2:100/vm-100-disk-31.qcow2,aio=io_uring"}, From d941f39c77cafa6e9b4352e0121b638bd7e58fe7 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 4 Apr 2023 21:08:58 +0000 Subject: [PATCH 115/120] fix: API can return disk size in TerraBytes --- proxmox/config_qemu_disk.go | 12 +++++++-- proxmox/config_qemu_test.go | 52 ++++++++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index ce2fd9c6..7caa86d5 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -419,8 +419,16 @@ func (qemuDisk) mapToStruct(settings [][]string, linkedVmId *uint) *qemuDisk { continue } if e[0] == "size" { - diskSize, _ := strconv.Atoi(strings.TrimSuffix(e[1], "G")) - disk.Size = uint(diskSize) + if len(e[1]) > 1 { + test := e[1][0 : len(e[1])-1] + diskSize, _ := strconv.Atoi(test) + switch e[1][len(e[1])-1:] { + case "G": + disk.Size = uint(diskSize) + case "T": + disk.Size = uint(diskSize * 1024) + } + } continue } if e[0] == "ssd" { diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index 6d19150b..68f7a8f3 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -2577,7 +2577,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, - {name: "Disks Ide Disk size", + {name: "Disks Ide Disk size G", input: map[string]interface{}{"ide0": "test2:100/vm-100-disk-53.qcow2,size=1032G"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: true, @@ -2588,6 +2588,17 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Ide Disk size T", + input: map[string]interface{}{"ide0": "test2:100/vm-100-disk-53.qcow2,size=2T"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_0: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: uint53, + Replicate: true, + Size: 2048, + Storage: "test2", + }}}}}, + }, {name: "Disks Ide Disk ssd", input: map[string]interface{}{"ide1": "test2:100/vm-100-disk-53.qcow2,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -3061,7 +3072,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, - {name: "Disks Sata Disk size", + {name: "Disks Sata Disk size G", input: map[string]interface{}{"sata4": "test2:100/vm-100-disk-47.qcow2,size=32G"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: true, @@ -3072,6 +3083,17 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Sata Disk size T", + input: map[string]interface{}{"sata4": "test2:100/vm-100-disk-47.qcow2,size=3T"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_4: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: uint47, + Replicate: true, + Size: 3072, + Storage: "test2", + }}}}}, + }, {name: "Disks Sata Disk ssd", input: map[string]interface{}{"sata5": "test2:100/vm-100-disk-47.qcow2,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -3567,7 +3589,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test", }}}}}, }, - {name: "Disks Scsi Disk size", + {name: "Disks Scsi Disk size G", input: map[string]interface{}{"scsi18": "test:100/vm-100-disk-2.qcow2,size=32G"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, @@ -3578,6 +3600,17 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test", }}}}}, }, + {name: "Disks Scsi Disk size T", + input: map[string]interface{}{"scsi18": "test:100/vm-100-disk-2.qcow2,size=4T"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: uint2, + Replicate: true, + Size: 4096, + Storage: "test", + }}}}}, + }, {name: "Disks Scsi Disk ssd", input: map[string]interface{}{"scsi19": "test:100/vm-100-disk-2.qcow2,ssd=1"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -4095,7 +4128,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, - {name: "Disks VirtIO Disk size", + {name: "Disks VirtIO Disk size G", input: map[string]interface{}{"virtio2": "test2:100/vm-100-disk-31.qcow2,size=32G"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, @@ -4106,6 +4139,17 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks VirtIO Disk size T", + input: map[string]interface{}{"virtio2": "test2:100/vm-100-disk-31.qcow2,size=5T"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Format: QemuDiskFormat_Qcow2, + Id: uint31, + Replicate: true, + Size: 5120, + Storage: "test2", + }}}}}, + }, // Disks VirtIO Passthrough {name: "Disks VirtIO Passthrough", input: map[string]interface{}{"virtio0": "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi8"}, From c11acf162bb40a8bf67972465c535bca4a728252 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 5 Apr 2023 20:27:09 +0000 Subject: [PATCH 116/120] refactor: change custom type to uint --- proxmox/config_qemu_disk.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 7caa86d5..f1e06967 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -372,7 +372,7 @@ func (qemuDisk) mapToStruct(settings [][]string, linkedVmId *uint) *qemuDisk { } if e[0] == "iops_rd_max_length" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.ReadLimit.BurstDuration = QemuDiskBandwidthBurstDuration(tmp) + disk.Bandwidth.Iops.ReadLimit.BurstDuration = uint(tmp) } if e[0] == "iops_wr" { tmp, _ := strconv.Atoi(e[1]) @@ -384,7 +384,7 @@ func (qemuDisk) mapToStruct(settings [][]string, linkedVmId *uint) *qemuDisk { } if e[0] == "iops_wr_max_length" { tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.WriteLimit.BurstDuration = QemuDiskBandwidthBurstDuration(tmp) + disk.Bandwidth.Iops.WriteLimit.BurstDuration = uint(tmp) } if e[0] == "iothread" { disk.IOThread, _ = strconv.ParseBool(e[1]) @@ -507,9 +507,6 @@ func (bandwidth QemuDiskBandwidth) Validate() error { return bandwidth.Iops.Validate() } -// burst duration in seconds -type QemuDiskBandwidthBurstDuration uint - type QemuDiskBandwidthIops struct { ReadLimit QemuDiskBandwidthIopsLimit `json:"read,omitempty"` WriteLimit QemuDiskBandwidthIopsLimit `json:"write,omitempty"` @@ -524,9 +521,9 @@ func (iops QemuDiskBandwidthIops) Validate() error { } type QemuDiskBandwidthIopsLimit struct { - Burst QemuDiskBandwidthIopsLimitBurst `json:"burst,omitempty"` // 0 = unlimited - BurstDuration QemuDiskBandwidthBurstDuration `json:"burst_duration,omitempty"` - Concurrent QemuDiskBandwidthIopsLimitConcurrent `json:"concurrent,omitempty"` // 0 = unlimited + Burst QemuDiskBandwidthIopsLimitBurst `json:"burst,omitempty"` // 0 = unlimited + BurstDuration uint `json:"burst_duration,omitempty"` // burst duration in seconds + Concurrent QemuDiskBandwidthIopsLimitConcurrent `json:"concurrent,omitempty"` // 0 = unlimited } func (limit QemuDiskBandwidthIopsLimit) Validate() (err error) { From df891852765487d9e8cdfee5105433b51eba940f Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 6 Apr 2023 18:34:55 +0000 Subject: [PATCH 117/120] refactor: use map instad of 2D string array --- proxmox/config_qemu_disk.go | 213 +++++++++++++---------------- proxmox/config_qemu_disk_ide.go | 10 +- proxmox/config_qemu_disk_sata.go | 10 +- proxmox/config_qemu_disk_scsi.go | 10 +- proxmox/config_qemu_disk_test.go | 8 +- proxmox/config_qemu_disk_virtio.go | 10 +- proxmox/util.go | 15 +- proxmox/util_test.go | 14 +- 8 files changed, 147 insertions(+), 143 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index f1e06967..8b31db7f 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -87,41 +87,34 @@ type qemuCdRom struct { Size string } -func (qemuCdRom) mapToStruct(settings [][]string) *qemuCdRom { +func (qemuCdRom) mapToStruct(diskData string, settings map[string]interface{}) *qemuCdRom { var isCdRom bool - for _, e := range settings { - if e[0] == "media" { - if e[1] == "cdrom" { - isCdRom = true - break - } - } + if setting, isSet := settings["media"]; isSet { + isCdRom = setting.(string) == "cdrom" } if !isCdRom { return nil } - if settings[0][0] == "none" { + if _, isSet := settings["none"]; isSet { return &qemuCdRom{CdRom: true} } - if settings[0][0] == "cdrom" { + if _, isSet := settings["cdrom"]; isSet { return &qemuCdRom{CdRom: true, Passthrough: true} } - tmpStorage := strings.Split(settings[0][0], ":") + tmpStorage := strings.Split(diskData, ":") if len(tmpStorage) > 1 { - tmpFile := strings.Split(settings[0][0], "/") + tmpFile := strings.Split(diskData, "/") if len(tmpFile) == 2 { tmpFileType := strings.Split(tmpFile[1], ".") if len(tmpFileType) > 1 { fileType := QemuDiskFormat(tmpFileType[len(tmpFileType)-1]) if fileType == "iso" { - for _, e := range settings { - if e[0] == "size" { - return &qemuCdRom{ - CdRom: true, - Storage: tmpStorage[0], - File: tmpFile[1], - Size: e[1], - } + if setting, isSet := settings["size"]; isSet { + return &qemuCdRom{ + CdRom: true, + Storage: tmpStorage[0], + File: tmpFile[1], + Size: setting.(string), } } } else { @@ -300,18 +293,15 @@ func (disk qemuDisk) mapToApiValues(vmID, LinkedVmId uint, currentStorage string } // Maps all the disk related settings to our own data structure. -func (qemuDisk) mapToStruct(settings [][]string, linkedVmId *uint) *qemuDisk { - if len(settings) == 0 { - return nil - } +func (qemuDisk) mapToStruct(diskData string, settings map[string]interface{}, linkedVmId *uint) *qemuDisk { disk := qemuDisk{Backup: true} - if settings[0][0][0:1] == "/" { - disk.File = settings[0][0] + if diskData[0:1] == "/" { + disk.File = diskData } else { // storage:110/base-110-disk-1.qcow2/100/vm-100-disk-0.qcow2 // storage:100/vm-100-disk-0.qcow2 - diskAndPath := strings.Split(settings[0][0], ":") + diskAndPath := strings.Split(diskData, ":") disk.Storage = diskAndPath[0] if len(diskAndPath) == 2 { pathParts := strings.Split(diskAndPath[1], "/") @@ -340,101 +330,94 @@ func (qemuDisk) mapToStruct(settings [][]string, linkedVmId *uint) *qemuDisk { } } + if len(settings) == 0 { + return nil + } + // Replicate defaults to true disk.Replicate = true - for _, e := range settings { - if e[0] == "aio" { - disk.AsyncIO = QemuDiskAsyncIO(e[1]) - continue - } - if e[0] == "backup" { - disk.Backup, _ = strconv.ParseBool(e[1]) - continue - } - if e[0] == "cache" { - disk.Cache = QemuDiskCache(e[1]) - continue - } - if e[0] == "discard" { - if e[1] == "on" { - disk.Discard = true - } - continue - } - if e[0] == "iops_rd" { - tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.ReadLimit.Concurrent = QemuDiskBandwidthIopsLimitConcurrent(tmp) - } - if e[0] == "iops_rd_max" { - tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.ReadLimit.Burst = QemuDiskBandwidthIopsLimitBurst(tmp) - } - if e[0] == "iops_rd_max_length" { - tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.ReadLimit.BurstDuration = uint(tmp) - } - if e[0] == "iops_wr" { - tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.WriteLimit.Concurrent = QemuDiskBandwidthIopsLimitConcurrent(tmp) - } - if e[0] == "iops_wr_max" { - tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.WriteLimit.Burst = QemuDiskBandwidthIopsLimitBurst(tmp) - } - if e[0] == "iops_wr_max_length" { - tmp, _ := strconv.Atoi(e[1]) - disk.Bandwidth.Iops.WriteLimit.BurstDuration = uint(tmp) - } - if e[0] == "iothread" { - disk.IOThread, _ = strconv.ParseBool(e[1]) - continue - } - if e[0] == "mbps_rd" { - tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.MBps.ReadLimit.Concurrent = QemuDiskBandwidthMBpsLimitConcurrent(math.Round(tmp*100) / 100) - } - if e[0] == "mbps_rd_max" { - tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.MBps.ReadLimit.Burst = QemuDiskBandwidthMBpsLimitBurst(math.Round(tmp*100) / 100) - } - if e[0] == "mbps_wr" { - tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.MBps.WriteLimit.Concurrent = QemuDiskBandwidthMBpsLimitConcurrent(math.Round(tmp*100) / 100) - } - if e[0] == "mbps_wr_max" { - tmp, _ := strconv.ParseFloat(e[1], 32) - disk.Bandwidth.MBps.WriteLimit.Burst = QemuDiskBandwidthMBpsLimitBurst(math.Round(tmp*100) / 100) - } - if e[0] == "replicate" { - disk.Replicate, _ = strconv.ParseBool(e[1]) - continue - } - if e[0] == "ro" { - disk.ReadOnly, _ = strconv.ParseBool(e[1]) - continue - } - if e[0] == "serial" { - disk.Serial = QemuDiskSerial(e[1]) - continue + if value, isSet := settings["aio"]; isSet { + disk.AsyncIO = QemuDiskAsyncIO(value.(string)) + } + if value, isSet := settings["backup"]; isSet { + disk.Backup, _ = strconv.ParseBool(value.(string)) + } + if value, isSet := settings["cache"]; isSet { + disk.Cache = QemuDiskCache(value.(string)) + } + if value, isSet := settings["discard"]; isSet { + if value.(string) == "on" { + disk.Discard = true } - if e[0] == "size" { - if len(e[1]) > 1 { - test := e[1][0 : len(e[1])-1] - diskSize, _ := strconv.Atoi(test) - switch e[1][len(e[1])-1:] { - case "G": - disk.Size = uint(diskSize) - case "T": - disk.Size = uint(diskSize * 1024) - } + } + if value, isSet := settings["iops_rd"]; isSet { + tmp, _ := strconv.Atoi(value.(string)) + disk.Bandwidth.Iops.ReadLimit.Concurrent = QemuDiskBandwidthIopsLimitConcurrent(tmp) + } + if value, isSet := settings["iops_rd_max"]; isSet { + tmp, _ := strconv.Atoi(value.(string)) + disk.Bandwidth.Iops.ReadLimit.Burst = QemuDiskBandwidthIopsLimitBurst(tmp) + } + if value, isSet := settings["iops_rd_max_length"]; isSet { + tmp, _ := strconv.Atoi(value.(string)) + disk.Bandwidth.Iops.ReadLimit.BurstDuration = uint(tmp) + } + if value, isSet := settings["iops_wr"]; isSet { + tmp, _ := strconv.Atoi(value.(string)) + disk.Bandwidth.Iops.WriteLimit.Concurrent = QemuDiskBandwidthIopsLimitConcurrent(tmp) + } + if value, isSet := settings["iops_wr_max"]; isSet { + tmp, _ := strconv.Atoi(value.(string)) + disk.Bandwidth.Iops.WriteLimit.Burst = QemuDiskBandwidthIopsLimitBurst(tmp) + } + if value, isSet := settings["iops_wr_max_length"]; isSet { + tmp, _ := strconv.Atoi(value.(string)) + disk.Bandwidth.Iops.WriteLimit.BurstDuration = uint(tmp) + } + if value, isSet := settings["iothread"]; isSet { + disk.IOThread, _ = strconv.ParseBool(value.(string)) + } + if value, isSet := settings["mbps_rd"]; isSet { + tmp, _ := strconv.ParseFloat(value.(string), 32) + disk.Bandwidth.MBps.ReadLimit.Concurrent = QemuDiskBandwidthMBpsLimitConcurrent(math.Round(tmp*100) / 100) + } + if value, isSet := settings["mbps_rd_max"]; isSet { + tmp, _ := strconv.ParseFloat(value.(string), 32) + disk.Bandwidth.MBps.ReadLimit.Burst = QemuDiskBandwidthMBpsLimitBurst(math.Round(tmp*100) / 100) + } + if value, isSet := settings["mbps_wr"]; isSet { + tmp, _ := strconv.ParseFloat(value.(string), 32) + disk.Bandwidth.MBps.WriteLimit.Concurrent = QemuDiskBandwidthMBpsLimitConcurrent(math.Round(tmp*100) / 100) + } + if value, isSet := settings["mbps_wr_max"]; isSet { + tmp, _ := strconv.ParseFloat(value.(string), 32) + disk.Bandwidth.MBps.WriteLimit.Burst = QemuDiskBandwidthMBpsLimitBurst(math.Round(tmp*100) / 100) + } + if value, isSet := settings["replicate"]; isSet { + disk.Replicate, _ = strconv.ParseBool(value.(string)) + } + if value, isSet := settings["ro"]; isSet { + disk.ReadOnly, _ = strconv.ParseBool(value.(string)) + } + if value, isSet := settings["serial"]; isSet { + disk.Serial = QemuDiskSerial(value.(string)) + } + if value, isSet := settings["size"]; isSet { + sizeString := value.(string) + if len(sizeString) > 1 { + diskSize, _ := strconv.Atoi(sizeString[0 : len(sizeString)-1]) + switch sizeString[len(sizeString)-1:] { + case "G": + disk.Size = uint(diskSize) + case "T": + disk.Size = uint(diskSize * 1024) } - continue - } - if e[0] == "ssd" { - disk.EmulateSSD, _ = strconv.ParseBool(e[1]) } } + if value, isSet := settings["ssd"]; isSet { + disk.EmulateSSD, _ = strconv.ParseBool(value.(string)) + } return &disk } diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index d0746259..ed019ae3 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -1,6 +1,9 @@ package proxmox -import "strconv" +import ( + "strconv" + "strings" +) type QemuIdeDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` @@ -205,8 +208,9 @@ func (storage *QemuIdeStorage) convertDataStructureMark() *qemuDiskMark { } func (QemuIdeStorage) mapToStruct(param string, LinkedVmId *uint) *QemuIdeStorage { + diskData, _, _ := strings.Cut(param, ",") settings := splitStringOfSettings(param) - tmpCdRom := qemuCdRom{}.mapToStruct(settings) + tmpCdRom := qemuCdRom{}.mapToStruct(diskData, settings) if tmpCdRom != nil { if tmpCdRom.CdRom { return &QemuIdeStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} @@ -215,7 +219,7 @@ func (QemuIdeStorage) mapToStruct(param string, LinkedVmId *uint) *QemuIdeStorag } } - tmpDisk := qemuDisk{}.mapToStruct(settings, LinkedVmId) + tmpDisk := qemuDisk{}.mapToStruct(diskData, settings, LinkedVmId) if tmpDisk == nil { return nil } diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index 3e1cb7db..d1c4b584 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -1,6 +1,9 @@ package proxmox -import "strconv" +import ( + "strconv" + "strings" +) type QemuSataDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` @@ -217,8 +220,9 @@ func (storage *QemuSataStorage) convertDataStructureMark() *qemuDiskMark { } func (QemuSataStorage) mapToStruct(param string, LinkedVmId *uint) *QemuSataStorage { + diskData, _, _ := strings.Cut(param, ",") settings := splitStringOfSettings(param) - tmpCdRom := qemuCdRom{}.mapToStruct(settings) + tmpCdRom := qemuCdRom{}.mapToStruct(diskData, settings) if tmpCdRom != nil { if tmpCdRom.CdRom { return &QemuSataStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} @@ -227,7 +231,7 @@ func (QemuSataStorage) mapToStruct(param string, LinkedVmId *uint) *QemuSataStor } } - tmpDisk := qemuDisk{}.mapToStruct(settings, LinkedVmId) + tmpDisk := qemuDisk{}.mapToStruct(diskData, settings, LinkedVmId) if tmpDisk == nil { return nil } diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index 43b83be8..3ad5a1ea 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -1,6 +1,9 @@ package proxmox -import "strconv" +import ( + "strconv" + "strings" +) type QemuScsiDisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` @@ -375,8 +378,9 @@ func (storage *QemuScsiStorage) convertDataStructureMark() *qemuDiskMark { } func (QemuScsiStorage) mapToStruct(param string, LinkedVmId *uint) *QemuScsiStorage { + diskData, _, _ := strings.Cut(param, ",") settings := splitStringOfSettings(param) - tmpCdRom := qemuCdRom{}.mapToStruct(settings) + tmpCdRom := qemuCdRom{}.mapToStruct(diskData, settings) if tmpCdRom != nil { if tmpCdRom.CdRom { return &QemuScsiStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} @@ -385,7 +389,7 @@ func (QemuScsiStorage) mapToStruct(param string, LinkedVmId *uint) *QemuScsiStor } } - tmpDisk := qemuDisk{}.mapToStruct(settings, LinkedVmId) + tmpDisk := qemuDisk{}.mapToStruct(diskData, settings, LinkedVmId) if tmpDisk == nil { return nil } diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 167b8f07..2f5c23ac 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -90,24 +90,24 @@ func Test_QemuCloudInitDisk_Validate(t *testing.T) { func Test_qemuDisk_mapToStruct(t *testing.T) { tests := []struct { name string - input [][]string + input string linkedVmId uint output uint }{ {name: "Don't Update LinkedVmId", - input: [][]string{{"storage:100/vm-100-disk-0.qcow2"}}, + input: "storage:100/vm-100-disk-0.qcow2", linkedVmId: 110, output: 110, }, {name: "Update LinkedVmId", - input: [][]string{{"storage:110/base-110-disk-1.qcow2/100/vm-100-disk-0.qcow2"}}, + input: "storage:110/base-110-disk-1.qcow2/100/vm-100-disk-0.qcow2", output: 110, }, } for _, test := range tests { t.Run(test.name, func(*testing.T) { linkedVmId := uint(test.linkedVmId) - qemuDisk{}.mapToStruct(test.input, &linkedVmId) + qemuDisk{}.mapToStruct(test.input, nil, &linkedVmId) require.Equal(t, test.output, linkedVmId, test.name) }) } diff --git a/proxmox/config_qemu_disk_virtio.go b/proxmox/config_qemu_disk_virtio.go index 95485877..4962d5e2 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -1,6 +1,9 @@ package proxmox -import "strconv" +import ( + "strconv" + "strings" +) type QemuVirtIODisk struct { AsyncIO QemuDiskAsyncIO `json:"asyncio,omitempty"` @@ -281,8 +284,9 @@ func (storage *QemuVirtIOStorage) convertDataStructureMark() *qemuDiskMark { } func (QemuVirtIOStorage) mapToStruct(param string, LinkedVmId *uint) *QemuVirtIOStorage { + diskData, _, _ := strings.Cut(param, ",") settings := splitStringOfSettings(param) - tmpCdRom := qemuCdRom{}.mapToStruct(settings) + tmpCdRom := qemuCdRom{}.mapToStruct(diskData, settings) if tmpCdRom != nil { if tmpCdRom.CdRom { return &QemuVirtIOStorage{CdRom: QemuCdRom{}.mapToStruct(*tmpCdRom)} @@ -291,7 +295,7 @@ func (QemuVirtIOStorage) mapToStruct(param string, LinkedVmId *uint) *QemuVirtIO } } - tmpDisk := qemuDisk{}.mapToStruct(settings, LinkedVmId) + tmpDisk := qemuDisk{}.mapToStruct(diskData, settings, LinkedVmId) if tmpDisk == nil { return nil } diff --git a/proxmox/util.go b/proxmox/util.go index f1c4fcfe..400f91e6 100644 --- a/proxmox/util.go +++ b/proxmox/util.go @@ -216,11 +216,16 @@ func keyExists(array []interface{}, key string) (existence bool) { return false } -func splitStringOfSettings(settings string) (settingArray [][]string) { +func splitStringOfSettings(settings string) map[string]interface{} { settingValuePairs := strings.Split(settings, ",") - settingArray = make([][]string, len(settingValuePairs)) - for i, e := range settingValuePairs { - settingArray[i] = strings.SplitN(e, "=", 2) + settingMap := map[string]interface{}{} + for _, e := range settingValuePairs { + keyValuePair := strings.SplitN(e, "=", 2) + var value string + if len(keyValuePair) == 2 { + value = keyValuePair[1] + } + settingMap[keyValuePair[0]] = value } - return + return settingMap } diff --git a/proxmox/util_test.go b/proxmox/util_test.go index db842767..1ac4211c 100644 --- a/proxmox/util_test.go +++ b/proxmox/util_test.go @@ -55,16 +55,16 @@ func Test_keyExists(t *testing.T) { func Test_splitStringOfSettings(t *testing.T) { testData := []struct { Input string - Output [][]string + Output map[string]interface{} }{ { Input: "setting=a,thing=b,randomString,doubleTest=value=equals,object=test", - Output: [][]string{ - {"setting", "a"}, - {"thing", "b"}, - {"randomString"}, - {"doubleTest", "value=equals"}, - {"object", "test"}, + Output: map[string]interface{}{ + "setting": "a", + "thing": "b", + "randomString": "", + "doubleTest": "value=equals", + "object": "test", }, }, } From c8e3d98d40ed574a7386c2280077034216820e66 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 2 May 2023 18:41:22 +0000 Subject: [PATCH 118/120] Make func private --- proxmox/config_qemu.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index 14340834..c828d34b 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -91,7 +91,7 @@ type ConfigQemu struct { // Create - Tell Proxmox API to make the VM func (config ConfigQemu) Create(vmr *VmRef, client *Client) (err error) { - _, err = config.SetAdvanced(nil, false, vmr, client) + _, err = config.setAdvanced(nil, false, vmr, client) return } @@ -697,7 +697,7 @@ func (newConfig ConfigQemu) Update(rebootIfNeeded bool, vmr *VmRef, client *Clie if err != nil { return } - return newConfig.SetAdvanced(currentConfig, rebootIfNeeded, vmr, client) + return newConfig.setAdvanced(currentConfig, rebootIfNeeded, vmr, client) } func (config *ConfigQemu) setVmr(vmr *VmRef) (err error) { @@ -712,7 +712,7 @@ func (config *ConfigQemu) setVmr(vmr *VmRef) (err error) { return } -func (newConfig ConfigQemu) SetAdvanced(currentConfig *ConfigQemu, rebootIfNeeded bool, vmr *VmRef, client *Client) (rebootRequired bool, err error) { +func (newConfig ConfigQemu) setAdvanced(currentConfig *ConfigQemu, rebootIfNeeded bool, vmr *VmRef, client *Client) (rebootRequired bool, err error) { err = newConfig.setVmr(vmr) if err != nil { return From e1851266e38be9ecbb0d9d7d62257eba55a9bdf2 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 2 May 2023 19:12:41 +0000 Subject: [PATCH 119/120] Restore Deprecated functions --- proxmox/config_qemu.go | 106 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 8 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index c828d34b..e44fbb37 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -99,19 +99,110 @@ func (config ConfigQemu) Create(vmr *VmRef, client *Client) (err error) { // // CreateVm - Tell Proxmox API to make the VM func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) { - err = config.setVmr(vmr) - if err != nil { - return + if config.HasCloudInit() { + return fmt.Errorf("cloud-init parameters only supported on clones or updates") + } + vmr.SetVmType("qemu") + + params := map[string]interface{}{ + "vmid": vmr.vmId, + "name": config.Name, + "startup": config.Startup, + "agent": config.Agent, + "ostype": config.QemuOs, + "sockets": config.QemuSockets, + "cores": config.QemuCores, + "cpu": config.QemuCpu, + "hotplug": config.Hotplug, + "memory": config.Memory, + "boot": config.Boot, + "description": config.Description, + "tags": config.Tags, + "machine": config.Machine, + "args": config.Args, + } + + if config.QemuNuma != nil { + params["numa"] = *config.QemuNuma + } + + if config.QemuKVM != nil { + params["kvm"] = *config.QemuKVM + } + + if config.Tablet != nil { + params["tablet"] = *config.Tablet + } + + if config.Onboot != nil { + params["onboot"] = *config.Onboot + } + + if config.QemuIso != "" { + params["ide2"] = config.QemuIso + ",media=cdrom" + } + + if config.Bios != "" { + params["bios"] = config.Bios + } + + if config.Balloon >= 1 { + params["balloon"] = config.Balloon + } + + if config.QemuVcpus >= 1 { + params["vcpus"] = config.QemuVcpus + } + + if vmr.pool != "" { + params["pool"] = vmr.pool } - err = config.Validate() + if config.Boot != "" { + params["boot"] = config.Boot + } + if config.BootDisk != "" { + params["bootdisk"] = config.BootDisk + } + + if config.Scsihw != "" { + params["scsihw"] = config.Scsihw + } + + err = config.CreateQemuMachineParam(params) if err != nil { - return + log.Printf("[ERROR] %q", err) + } + + // Create disks config. + config.CreateQemuDisksParams(params, false) + + // Create EFI disk + config.CreateQemuEfiParams(params) + + // Create vga config. + vgaParam := QemuDeviceParam{} + vgaParam = vgaParam.createDeviceParam(config.QemuVga, nil) + if len(vgaParam) > 0 { + params["vga"] = strings.Join(vgaParam, ",") } - _, params, err := config.mapToApiValues(ConfigQemu{}) + + // Create networks config. + config.CreateQemuNetworksParams(params) + + // Create ipconfig. + err = config.CreateIpconfigParams(params) if err != nil { - return + log.Printf("[ERROR] %q", err) } + // Create serial interfaces + config.CreateQemuSerialsParams(params) + + config.CreateQemuPCIsParams(params) + + // Create usb interfaces + config.CreateQemuUsbsParams(params) + exitStatus, err := client.CreateQemuVm(vmr.node, params) if err != nil { return fmt.Errorf("error creating VM: %v, error status: %s (params: %v)", err, exitStatus, params) @@ -984,7 +1075,6 @@ func (config ConfigQemu) UpdateConfig(vmr *VmRef, client *Client) (err error) { configParamsDisk := map[string]interface{}{ "vmid": vmr.vmId, } - // TODO keep going if error= config.CreateQemuDisksParams(configParamsDisk, false) // TODO keep going if error= _, err = client.createVMDisks(vmr.node, configParamsDisk) From 9fa35651591aca9b66656126907e1edcec558460 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 2 May 2023 21:03:09 +0000 Subject: [PATCH 120/120] Remove unused variables --- proxmox/config_qemu.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index e44fbb37..2f3e8d5b 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -1164,16 +1164,12 @@ func NewConfigQemuFromJson(input []byte) (config *ConfigQemu, err error) { } var ( - rxIso = regexp.MustCompile(`(.*?),media`) rxDeviceID = regexp.MustCompile(`\d+`) - rxDiskName = regexp.MustCompile(`(virtio|scsi|ide|sata)\d+`) - rxDiskType = regexp.MustCompile(`\D+`) rxUnusedDiskName = regexp.MustCompile(`^(unused)\d+`) rxNicName = regexp.MustCompile(`net\d+`) rxMpName = regexp.MustCompile(`mp\d+`) rxSerialName = regexp.MustCompile(`serial\d+`) rxUsbName = regexp.MustCompile(`usb\d+`) - rxDiskPath = regexp.MustCompile(`^\/dev\/.*`) rxPCIName = regexp.MustCompile(`hostpci\d+`) rxIpconfigName = regexp.MustCompile(`ipconfig\d+`) )