From 953450a906b408cc3dbcf196a3c5bf499ed61dd5 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 3 Jan 2024 16:33:06 +0000 Subject: [PATCH 1/4] fix: disk format can be optional --- proxmox/config_qemu_disk.go | 9 ++++- proxmox/config_qemu_test.go | 80 +++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 8539e1c5..62d2464c 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -321,13 +321,18 @@ func (qemuDisk) mapToStruct(diskData string, settings map[string]interface{}, li } if len(pathParts) > 1 { diskNameAndFormat := strings.Split(pathParts[len(pathParts)-1], ".") - if len(diskNameAndFormat) == 2 { - disk.Format = QemuDiskFormat(diskNameAndFormat[1]) + if len(diskNameAndFormat) > 0 { tmp := strings.Split(diskNameAndFormat[0], "-") if len(tmp) > 1 { tmpDiskId, _ := strconv.Atoi(tmp[len(tmp)-1]) disk.Id = uint(tmpDiskId) } + // set disk format, default to raw + if len(diskNameAndFormat) == 2 { + disk.Format = QemuDiskFormat(diskNameAndFormat[1]) + } else { + disk.Format = QemuDiskFormat_Raw + } } } } diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index f143725d..e161b8cf 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -2489,6 +2489,26 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Ide Disk Format default", + input: map[string]interface{}{"ide2": "test:100/vm-100-disk-2"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Ide Disk Format raw", + input: map[string]interface{}{"ide3": "test:100/vm-100-disk-2.raw"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, {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{ @@ -3003,6 +3023,26 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Sata Disk Format default", + input: map[string]interface{}{"sata0": "test:100/vm-100-disk-2"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Sata Disk Format raw", + input: map[string]interface{}{"sata1": "test:100/vm-100-disk-2.raw"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, {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{ @@ -3525,6 +3565,26 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test", }}}}}, }, + {name: "Disks Scsi Disk Format default", + input: map[string]interface{}{"scsi6": "test:100/vm-100-disk-2"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks Scsi Disk Format raw", + input: map[string]interface{}{"scsi7": "test:100/vm-100-disk-2.raw"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + 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{ @@ -4083,6 +4143,26 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks VirtIO Disk Format default", + input: map[string]interface{}{"virtio7": "test:100/vm-100-disk-2"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, + {name: "Disks VirtIO Disk Format raw", + input: map[string]interface{}{"virtio8": "test:100/vm-100-disk-2.raw"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + Replicate: true, + Storage: "test", + }}}}}, + }, {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{ From 02f34049005252e384b6ba82d641d91bce07a397 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Wed, 3 Jan 2024 20:42:42 +0000 Subject: [PATCH 2/4] fix: add missing support for disk syntax --- proxmox/config_qemu_disk.go | 27 +++++++++++++-------------- proxmox/config_qemu_test.go | 16 ++++++++-------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index 62d2464c..fc5fa684 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -304,6 +304,7 @@ func (qemuDisk) mapToStruct(diskData string, settings map[string]interface{}, li } else { // storage:110/base-110-disk-1.qcow2/100/vm-100-disk-0.qcow2 // storage:100/vm-100-disk-0.qcow2 + // storage:vm-100-disk-0 diskAndPath := strings.Split(diskData, ":") disk.Storage = diskAndPath[0] if len(diskAndPath) == 2 { @@ -319,20 +320,18 @@ func (qemuDisk) mapToStruct(diskData string, settings map[string]interface{}, li disk.LinkedDiskId = &tmpDiskIdPointer } } - if len(pathParts) > 1 { - diskNameAndFormat := strings.Split(pathParts[len(pathParts)-1], ".") - if len(diskNameAndFormat) > 0 { - tmp := strings.Split(diskNameAndFormat[0], "-") - if len(tmp) > 1 { - tmpDiskId, _ := strconv.Atoi(tmp[len(tmp)-1]) - disk.Id = uint(tmpDiskId) - } - // set disk format, default to raw - if len(diskNameAndFormat) == 2 { - disk.Format = QemuDiskFormat(diskNameAndFormat[1]) - } else { - disk.Format = QemuDiskFormat_Raw - } + diskNameAndFormat := strings.Split(pathParts[len(pathParts)-1], ".") + if len(diskNameAndFormat) > 0 { + tmp := strings.Split(diskNameAndFormat[0], "-") + if len(tmp) > 1 { + tmpDiskId, _ := strconv.Atoi(tmp[len(tmp)-1]) + disk.Id = uint(tmpDiskId) + } + // set disk format, default to raw + if len(diskNameAndFormat) == 2 { + disk.Format = QemuDiskFormat(diskNameAndFormat[1]) + } else { + disk.Format = QemuDiskFormat_Raw } } } diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index e161b8cf..da5e2f5f 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -2490,7 +2490,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Ide Disk Format default", - input: map[string]interface{}{"ide2": "test:100/vm-100-disk-2"}, + input: map[string]interface{}{"ide2": "test:vm-100-disk-2"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: true, Format: QemuDiskFormat_Raw, @@ -2500,7 +2500,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Ide Disk Format raw", - input: map[string]interface{}{"ide3": "test:100/vm-100-disk-2.raw"}, + input: map[string]interface{}{"ide3": "test:vm-100-disk-2.raw"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ Backup: true, Format: QemuDiskFormat_Raw, @@ -3024,7 +3024,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Sata Disk Format default", - input: map[string]interface{}{"sata0": "test:100/vm-100-disk-2"}, + input: map[string]interface{}{"sata0": "test:vm-100-disk-2"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: true, Format: QemuDiskFormat_Raw, @@ -3034,7 +3034,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Sata Disk Format raw", - input: map[string]interface{}{"sata1": "test:100/vm-100-disk-2.raw"}, + input: map[string]interface{}{"sata1": "test:vm-100-disk-2.raw"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ Backup: true, Format: QemuDiskFormat_Raw, @@ -3566,7 +3566,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Scsi Disk Format default", - input: map[string]interface{}{"scsi6": "test:100/vm-100-disk-2"}, + input: map[string]interface{}{"scsi6": "test:vm-100-disk-2"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, Format: QemuDiskFormat_Raw, @@ -3576,7 +3576,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks Scsi Disk Format raw", - input: map[string]interface{}{"scsi7": "test:100/vm-100-disk-2.raw"}, + input: map[string]interface{}{"scsi7": "test:vm-100-disk-2.raw"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{ Backup: true, Format: QemuDiskFormat_Raw, @@ -4144,7 +4144,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks VirtIO Disk Format default", - input: map[string]interface{}{"virtio7": "test:100/vm-100-disk-2"}, + input: map[string]interface{}{"virtio7": "test:vm-100-disk-2"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, Format: QemuDiskFormat_Raw, @@ -4154,7 +4154,7 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { }}}}}, }, {name: "Disks VirtIO Disk Format raw", - input: map[string]interface{}{"virtio8": "test:100/vm-100-disk-2.raw"}, + input: map[string]interface{}{"virtio8": "test:vm-100-disk-2.raw"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Backup: true, Format: QemuDiskFormat_Raw, From ccd9e2c9d5357de8bb615e10d169e935ce8e4c6e Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 4 Jan 2024 18:31:44 +0000 Subject: [PATCH 3/4] fix: disk incorrectly formatted for lvm storage --- proxmox/config_qemu_disk.go | 170 ++++-- 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_test.go | 153 ++++- proxmox/config_qemu_disk_virtio.go | 3 + proxmox/config_qemu_test.go | 896 +++++++++++++++++++++++++---- 7 files changed, 1052 insertions(+), 179 deletions(-) diff --git a/proxmox/config_qemu_disk.go b/proxmox/config_qemu_disk.go index fc5fa684..8985617f 100644 --- a/proxmox/config_qemu_disk.go +++ b/proxmox/config_qemu_disk.go @@ -9,6 +9,13 @@ import ( "strings" ) +type diskSyntaxEnum bool + +const ( + diskSyntaxFile diskSyntaxEnum = false + diskSyntaxVolume diskSyntaxEnum = true +) + type IsoFile struct { File string `json:"file"` Storage string `json:"storage"` @@ -178,6 +185,7 @@ type qemuDisk struct { EmulateSSD bool // Only set for ide,sata,scsi // TODO custom type File string // Only set for Passthrough. + fileSyntax diskSyntaxEnum // private enum to determine the syntax of the file path, as this changes depending on the type of backing storage. ie nfs, lvm, local, etc. Format QemuDiskFormat // Only set for Disk Id uint // Only set for Disk IOThread bool // Only set for scsi,virtio @@ -199,21 +207,48 @@ const ( Error_QemuDisk_Storage string = "storage may not be empty" ) +// create the disk string for the api +func (disk qemuDisk) formatDisk(vmID, LinkedVmId uint, currentStorage string, currentFormat QemuDiskFormat, syntax diskSyntaxEnum) (settings string) { + tmpId := strconv.Itoa(int(vmID)) + // vm-100-disk-0 + settings = "vm-" + tmpId + "-disk-" + strconv.Itoa(int(disk.Id)) + switch syntax { + case diskSyntaxFile: + // format is ignored when syntax is diskSyntaxVolume + // normal disk syntax + // 100/vm-100-disk-0.raw + settings = tmpId + "/" + settings + "." + string(disk.Format) + if disk.LinkedDiskId != nil && disk.Storage == currentStorage && disk.Format == currentFormat { + // linked clone disk syntax + // 110/base-110-disk-1.raw/100/vm-100-disk-0.raw + tmpId = strconv.Itoa(int(LinkedVmId)) + settings = tmpId + "/base-" + tmpId + "-disk-" + strconv.Itoa(int(*disk.LinkedDiskId)) + "." + string(disk.Format) + "/" + settings + } + case diskSyntaxVolume: + // normal disk syntax + // vm-100-disk-0 + if disk.LinkedDiskId != nil && disk.Storage == currentStorage { + // linked clone disk syntax + // base-110-disk-1/vm-100-disk-0 + tmpId = strconv.Itoa(int(LinkedVmId)) + settings = "base-" + tmpId + "-disk-" + strconv.Itoa(int(*disk.LinkedDiskId)) + "/" + settings + } + } + // storage:100/vm-100-disk-0.raw + // storage:110/base-110-disk-1.raw/100/vm-100-disk-0.raw + // storage:vm-100-disk-0 + // storage:base-110-disk-1/vm-100-disk-0 + settings = disk.Storage + ":" + settings + return +} + // Maps all the disk related settings to api values proxmox understands. -func (disk qemuDisk) mapToApiValues(vmID, LinkedVmId uint, currentStorage string, currentFormat QemuDiskFormat, create bool) (settings string) { +func (disk qemuDisk) mapToApiValues(vmID, LinkedVmId uint, currentStorage string, currentFormat QemuDiskFormat, syntax diskSyntaxEnum, create bool) (settings string) { if disk.Storage != "" { if create { settings = disk.Storage + ":" + strconv.Itoa(int(disk.Size)) } else { - 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.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(LinkedVmId)) - settings = tmpId + "/base-" + tmpId + "-disk-" + strconv.Itoa(int(*disk.LinkedDiskId)) + "." + string(disk.Format) + "/" + settings - } - settings = disk.Storage + ":" + settings + settings = disk.formatDisk(vmID, LinkedVmId, currentStorage, currentFormat, syntax) } } @@ -302,39 +337,7 @@ func (qemuDisk) mapToStruct(diskData string, settings map[string]interface{}, li 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 - // storage:vm-100-disk-0 - diskAndPath := strings.Split(diskData, ":") - 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]) - *linkedVmId = uint(tmpVmId) - tmp := strings.Split(strings.Split(pathParts[1], ".")[0], "-") - if len(tmp) > 1 { - tmpDiskId, _ = strconv.Atoi(tmp[len(tmp)-1]) - tmpDiskIdPointer := uint(tmpDiskId) - disk.LinkedDiskId = &tmpDiskIdPointer - } - } - diskNameAndFormat := strings.Split(pathParts[len(pathParts)-1], ".") - if len(diskNameAndFormat) > 0 { - tmp := strings.Split(diskNameAndFormat[0], "-") - if len(tmp) > 1 { - tmpDiskId, _ := strconv.Atoi(tmp[len(tmp)-1]) - disk.Id = uint(tmpDiskId) - } - // set disk format, default to raw - if len(diskNameAndFormat) == 2 { - disk.Format = QemuDiskFormat(diskNameAndFormat[1]) - } else { - disk.Format = QemuDiskFormat_Raw - } - } - } + disk.Id, disk.Storage, disk.Format, disk.LinkedDiskId, disk.fileSyntax = qemuDisk{}.parseDisk(diskData, linkedVmId) } if len(settings) == 0 { @@ -431,6 +434,73 @@ func (qemuDisk) mapToStruct(diskData string, settings map[string]interface{}, li return &disk } +// parse and extract the values from the disk data +// storage:110/base-110-disk-1.qcow2/100/vm-100-disk-0.qcow2 +// storage:100/vm-100-disk-0.qcow2 +// storage:base-110-disk-1/vm-100-disk-0 +// storage:vm-100-disk-0 +func (qemuDisk) parseDisk(diskData string, linkedVmId *uint) (diskId uint, storage string, format QemuDiskFormat, linkedDiskId *uint, syntax diskSyntaxEnum) { + parts := strings.Split(diskData, ":") + storage = parts[0] + + if len(parts) != 2 { + return + } + + pathParts := strings.Split(parts[1], "/") + switch len(pathParts) { + case 1: + syntax = diskSyntaxVolume + case 2: + if _, err := strconv.Atoi(pathParts[0]); err != nil { // linked clone + tmp := strings.Split(strings.Split(pathParts[0], ".")[0], "-") + if len(tmp) > 1 { + if tmpVmId, err := strconv.Atoi(tmp[1]); err == nil { + *linkedVmId = uint(tmpVmId) + } + if tmpDiskId, err := strconv.Atoi(tmp[len(tmp)-1]); err == nil { + tmpDiskIdPointer := uint(tmpDiskId) + linkedDiskId = &tmpDiskIdPointer + } + syntax = diskSyntaxVolume + } + } else { + syntax = diskSyntaxFile + } + case 4: // Linked Clone + if tmpVmId, err := strconv.Atoi(pathParts[0]); err == nil { + *linkedVmId = uint(tmpVmId) + } + tmp := strings.Split(strings.Split(pathParts[1], ".")[0], "-") + if len(tmp) > 1 { + if tmpDiskId, err := strconv.Atoi(tmp[len(tmp)-1]); err == nil { + tmpDiskIdPointer := uint(tmpDiskId) + linkedDiskId = &tmpDiskIdPointer + } + } + syntax = diskSyntaxFile + } + + diskNameAndFormat := strings.Split(pathParts[len(pathParts)-1], ".") + if len(diskNameAndFormat) > 0 { + tmp := strings.Split(diskNameAndFormat[0], "-") + if len(tmp) > 1 { + if tmpDiskId, err := strconv.Atoi(tmp[len(tmp)-1]); err == nil { + diskId = uint(tmpDiskId) + } + } + + // set disk format, default to raw + if len(diskNameAndFormat) == 2 { + format = QemuDiskFormat(diskNameAndFormat[1]) + } else { + format = QemuDiskFormat_Raw + } + } + + return +} + func (disk *qemuDisk) validate() (err error) { if disk == nil { return @@ -873,20 +943,20 @@ func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID, li if storage.Disk != nil { if currentStorage == nil || currentStorage.Disk == nil { // Create - params[string(id)] = storage.Disk.mapToApiValues(vmID, 0, "", "", true) + params[string(id)] = storage.Disk.mapToApiValues(vmID, 0, "", "", false, true) } else { if storage.Disk.Size >= currentStorage.Disk.Size { // Update storage.Disk.Id = currentStorage.Disk.Id 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) { + disk := storage.Disk.mapToApiValues(vmID, linkedVmId, currentStorage.Disk.Storage, currentStorage.Disk.Format, currentStorage.Disk.fileSyntax, false) + if disk != currentStorage.Disk.mapToApiValues(vmID, linkedVmId, currentStorage.Disk.Storage, currentStorage.Disk.Format, currentStorage.Disk.fileSyntax, 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, 0, "", "", true) + params[string(id)] = storage.Disk.mapToApiValues(vmID, 0, "", "", false, true) } } return delete @@ -898,11 +968,11 @@ func (storage *qemuStorage) mapToApiValues(currentStorage *qemuStorage, vmID, li if storage.Passthrough != nil { if currentStorage == nil || currentStorage.Passthrough == nil { // Create - params[string(id)] = storage.Passthrough.mapToApiValues(0, 0, "", "", false) + params[string(id)] = storage.Passthrough.mapToApiValues(0, 0, "", "", false, false) } else { // Update - passthrough := storage.Passthrough.mapToApiValues(0, 0, "", "", false) - if passthrough != currentStorage.Passthrough.mapToApiValues(0, 0, "", "", false) { + passthrough := storage.Passthrough.mapToApiValues(0, 0, "", "", false, false) + if passthrough != currentStorage.Passthrough.mapToApiValues(0, 0, "", "", false, false) { params[string(id)] = passthrough } } diff --git a/proxmox/config_qemu_disk_ide.go b/proxmox/config_qemu_disk_ide.go index 52b495f5..2a02b6f9 100644 --- a/proxmox/config_qemu_disk_ide.go +++ b/proxmox/config_qemu_disk_ide.go @@ -19,6 +19,7 @@ type QemuIdeDisk struct { Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size"` Storage string `json:"storage"` + syntax diskSyntaxEnum WorldWideName QemuWorldWideName `json:"wwn"` } @@ -31,6 +32,7 @@ func (disk *QemuIdeDisk) convertDataStructure() *qemuDisk { Discard: disk.Discard, Disk: true, EmulateSSD: disk.EmulateSSD, + fileSyntax: disk.syntax, Format: disk.Format, Id: disk.Id, LinkedDiskId: disk.LinkedDiskId, @@ -242,6 +244,7 @@ func (QemuIdeStorage) mapToStruct(param string, LinkedVmId *uint) *QemuIdeStorag Serial: tmpDisk.Serial, Size: tmpDisk.Size, Storage: tmpDisk.Storage, + syntax: tmpDisk.fileSyntax, WorldWideName: tmpDisk.WorldWideName, }} } diff --git a/proxmox/config_qemu_disk_sata.go b/proxmox/config_qemu_disk_sata.go index e4e89c42..f5e364b4 100644 --- a/proxmox/config_qemu_disk_sata.go +++ b/proxmox/config_qemu_disk_sata.go @@ -19,6 +19,7 @@ type QemuSataDisk struct { Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size"` Storage string `json:"storage"` + syntax diskSyntaxEnum WorldWideName QemuWorldWideName `json:"wwn"` } @@ -31,6 +32,7 @@ func (disk *QemuSataDisk) convertDataStructure() *qemuDisk { Discard: disk.Discard, Disk: true, EmulateSSD: disk.EmulateSSD, + fileSyntax: disk.syntax, Format: disk.Format, Id: disk.Id, LinkedDiskId: disk.LinkedDiskId, @@ -254,6 +256,7 @@ func (QemuSataStorage) mapToStruct(param string, LinkedVmId *uint) *QemuSataStor Serial: tmpDisk.Serial, Size: tmpDisk.Size, Storage: tmpDisk.Storage, + syntax: tmpDisk.fileSyntax, WorldWideName: tmpDisk.WorldWideName, }} } diff --git a/proxmox/config_qemu_disk_scsi.go b/proxmox/config_qemu_disk_scsi.go index e68ee370..41842fa7 100644 --- a/proxmox/config_qemu_disk_scsi.go +++ b/proxmox/config_qemu_disk_scsi.go @@ -21,6 +21,7 @@ type QemuScsiDisk struct { Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size"` Storage string `json:"storage"` + syntax diskSyntaxEnum WorldWideName QemuWorldWideName `json:"wwn"` } @@ -42,6 +43,7 @@ func (disk *QemuScsiDisk) convertDataStructure() *qemuDisk { Serial: disk.Serial, Size: disk.Size, Storage: disk.Storage, + fileSyntax: disk.syntax, Type: scsi, WorldWideName: disk.WorldWideName, } @@ -414,6 +416,7 @@ func (QemuScsiStorage) mapToStruct(param string, LinkedVmId *uint) *QemuScsiStor Serial: tmpDisk.Serial, Size: tmpDisk.Size, Storage: tmpDisk.Storage, + syntax: tmpDisk.fileSyntax, WorldWideName: tmpDisk.WorldWideName, }} } diff --git a/proxmox/config_qemu_disk_test.go b/proxmox/config_qemu_disk_test.go index 4080e082..4864d661 100644 --- a/proxmox/config_qemu_disk_test.go +++ b/proxmox/config_qemu_disk_test.go @@ -87,6 +87,90 @@ func Test_QemuCloudInitDisk_Validate(t *testing.T) { } } +func Test_qemuDisk_formatDisk(t *testing.T) { + uintPtr := func(i uint) *uint { return &i } + type localInput struct { + vmID uint + linkedVmId uint + currentStorage string + currentFormat QemuDiskFormat + syntax diskSyntaxEnum + disk qemuDisk + } + tests := []struct { + name string + input localInput + output string + }{ + {name: "linked file", + input: localInput{ + vmID: 100, + linkedVmId: 110, + currentStorage: "storage", + currentFormat: QemuDiskFormat_Qcow2, + syntax: diskSyntaxFile, + disk: qemuDisk{ + Id: 6, + Storage: "storage", + Format: QemuDiskFormat_Qcow2, + LinkedDiskId: uintPtr(1), + }, + }, + output: "storage:110/base-110-disk-1.qcow2/100/vm-100-disk-6.qcow2", + }, + {name: "linked volume", + input: localInput{ + vmID: 100, + linkedVmId: 110, + currentStorage: "storage", + currentFormat: QemuDiskFormat_Raw, + syntax: diskSyntaxVolume, + disk: qemuDisk{ + Id: 12, + Storage: "storage", + Format: QemuDiskFormat_Qcow, + LinkedDiskId: uintPtr(8), + }, + }, + output: "storage:base-110-disk-8/vm-100-disk-12", + }, + {name: "normal file", + input: localInput{ + vmID: 100, + currentStorage: "storage", + currentFormat: QemuDiskFormat_Qcow2, + syntax: diskSyntaxFile, + disk: qemuDisk{ + Id: 9, + Storage: "storage", + Format: QemuDiskFormat_Qcow2, + }, + }, + output: "storage:100/vm-100-disk-9.qcow2", + }, + {name: "normal volume", + input: localInput{ + vmID: 100, + currentStorage: "storage", + currentFormat: QemuDiskFormat_Qcow2, + syntax: diskSyntaxVolume, + disk: qemuDisk{ + Id: 45, + Storage: "storage", + Format: QemuDiskFormat_Qed, + }, + }, + output: "storage:vm-100-disk-45", + }, + } + for _, test := range tests { + t.Run(test.name, func(*testing.T) { + result := test.input.disk.formatDisk(test.input.vmID, test.input.linkedVmId, test.input.currentStorage, test.input.currentFormat, test.input.syntax) + require.Equal(t, test.output, result, test.name) + }) + } +} + func Test_qemuDisk_mapToStruct(t *testing.T) { tests := []struct { name string @@ -94,15 +178,24 @@ func Test_qemuDisk_mapToStruct(t *testing.T) { linkedVmId uint output uint }{ - {name: "Don't Update LinkedVmId", + {name: "Don't Update LinkedVmId file", input: "storage:100/vm-100-disk-0.qcow2", linkedVmId: 110, output: 110, }, - {name: "Update LinkedVmId", + {name: "Don't Update LinkedVmId volume", + input: "storage:vm-100-disk-45", + linkedVmId: 110, + output: 110, + }, + {name: "Update LinkedVmId file", input: "storage:110/base-110-disk-1.qcow2/100/vm-100-disk-0.qcow2", output: 110, }, + {name: "Update LinkedVmId volume", + input: "storage:base-110-disk-8/vm-100-disk-12", + output: 110, + }, } for _, test := range tests { t.Run(test.name, func(*testing.T) { @@ -113,6 +206,62 @@ func Test_qemuDisk_mapToStruct(t *testing.T) { } } +func Test_qemuDisk_parseDisk(t *testing.T) { + uintPtr := func(i uint) *uint { return &i } + tests := []struct { + name string + input string + output qemuDisk + }{ + {name: "linked file", + input: "storage:110/base-110-disk-1.qcow2/100/vm-100-disk-6.qcow2", + output: qemuDisk{ + Id: 6, + Storage: "storage", + Format: QemuDiskFormat_Qcow2, + LinkedDiskId: uintPtr(1), + fileSyntax: diskSyntaxFile, + }, + }, + {name: "linked volume", + input: "storage:base-110-disk-8/vm-100-disk-12", + output: qemuDisk{ + Id: 12, + Storage: "storage", + Format: QemuDiskFormat_Raw, + LinkedDiskId: uintPtr(8), + fileSyntax: diskSyntaxVolume, + }, + }, + {name: "normal file", + input: "storage:100/vm-100-disk-9.qcow2", + output: qemuDisk{ + Id: 9, + Storage: "storage", + Format: QemuDiskFormat_Qcow2, + fileSyntax: diskSyntaxFile, + }, + }, + {name: "normal volume", + input: "storage:vm-100-disk-45", + output: qemuDisk{ + Id: 45, + Storage: "storage", + Format: QemuDiskFormat_Raw, + fileSyntax: diskSyntaxVolume, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(*testing.T) { + linkedVmId := uint(0) + disk := qemuDisk{} + disk.Id, disk.Storage, disk.Format, disk.LinkedDiskId, disk.fileSyntax = qemuDisk{}.parseDisk(test.input, &linkedVmId) + require.Equal(t, test.output, disk, 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 40973ca7..27acb900 100644 --- a/proxmox/config_qemu_disk_virtio.go +++ b/proxmox/config_qemu_disk_virtio.go @@ -20,6 +20,7 @@ type QemuVirtIODisk struct { Serial QemuDiskSerial `json:"serial,omitempty"` Size uint `json:"size"` Storage string `json:"storage"` + syntax diskSyntaxEnum WorldWideName QemuWorldWideName `json:"wwn"` } @@ -31,6 +32,7 @@ func (disk *QemuVirtIODisk) convertDataStructure() *qemuDisk { Cache: disk.Cache, Discard: disk.Discard, Disk: true, + fileSyntax: disk.syntax, Format: disk.Format, Id: disk.Id, IOThread: disk.IOThread, @@ -319,6 +321,7 @@ func (QemuVirtIOStorage) mapToStruct(param string, LinkedVmId *uint) *QemuVirtIO Serial: tmpDisk.Serial, Size: tmpDisk.Size, Storage: tmpDisk.Storage, + syntax: tmpDisk.fileSyntax, WorldWideName: tmpDisk.WorldWideName, }} } diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index da5e2f5f..339c747e 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -1299,7 +1299,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"ide2": "NewStorage:cloudinit,format=raw"}, }, // Update Disk.Ide.Disk_X.Disk - {name: "Update Disk.Ide.Disk_X.Disk CHANGE", + {name: "Update Disk.Ide.Disk_X.Disk CHANGE File", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ AsyncIO: QemuDiskAsyncIO_IOuring, Format: QemuDiskFormat_Raw, @@ -1315,7 +1315,7 @@ 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", + {name: "Update Disk.Ide.Disk_X.Disk CHANGE File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -1334,12 +1334,45 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, 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 CHANGE Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"ide3": "test:vm-0-disk-23,aio=native,backup=0,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk CHANGE Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + syntax: diskSyntaxVolume, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"ide3": "test:base-100-disk-1/vm-0-disk-23,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", + {name: "Update Disk.Ide.Disk_X.Disk MIGRATE File", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -1353,7 +1386,7 @@ 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", + {name: "Update Disk.Ide.Disk_X.Disk MIGRATE File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -1370,7 +1403,36 @@ 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 RESIZE DOWN", + {name: "Update Disk.Ide.Disk_X.Disk MIGRATE Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Id: 23, + Size: 10, + Storage: "test1", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"ide1": "test2:vm-0-disk-23,backup=0,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk MIGRATE Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test1", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"ide1": "test2:vm-0-disk-23,backup=0,replicate=0"}, + }, + {name: "Update Disk.Ide.Disk_X.Disk RESIZE DOWN File", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -1384,7 +1446,7 @@ 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", + {name: "Update Disk.Ide.Disk_X.Disk RESIZE DOWN File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -1401,7 +1463,38 @@ 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 UP", + {name: "Update Disk.Ide.Disk_X.Disk RESIZE DOWN Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + 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 Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + 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 File", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -1415,7 +1508,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{}, }, - {name: "Update Disk.Ide.Disk_X.Disk RESIZE UP LinkedClone", + {name: "Update Disk.Ide.Disk_X.Disk RESIZE UP File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 110, Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -1432,6 +1525,35 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{}, }, + {name: "Update Disk.Ide.Disk_X.Disk RESIZE UP Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, + {name: "Update Disk.Ide.Disk_X.Disk RESIZE UP Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 110, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, {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: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -1441,7 +1563,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{}, }, - {name: "Update Disk.Ide.Disk_X.Disk.Format CHANGE", + {name: "Update Disk.Ide.Disk_X.Disk.Format CHANGE File", currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -1455,7 +1577,7 @@ 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", + {name: "Update Disk.Ide.Disk_X.Disk.Format CHANGE File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -1472,6 +1594,39 @@ 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 Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Qcow2, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, + {name: "Update Disk.Ide.Disk_X.Disk.Format CHANGE Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Format: QemuDiskFormat_Qcow2, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, // 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{ @@ -1571,7 +1726,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"sata2": "NewStorage:cloudinit,format=raw"}, }, // Update Disk.Sata.Disk_X.Disk - {name: "Update Disk.Sata.Disk_X.Disk CHANGE", + {name: "Update Disk.Sata.Disk_X.Disk CHANGE File", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ AsyncIO: QemuDiskAsyncIO_IOuring, Format: QemuDiskFormat_Raw, @@ -1587,7 +1742,7 @@ 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", + {name: "Update Disk.Sata.Disk_X.Disk CHANGE File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -1606,12 +1761,45 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, 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 CHANGE Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata3": "test:vm-0-disk-23,aio=native,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk CHANGE Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata3": "test:base-100-disk-1/vm-0-disk-23,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", + {name: "Update Disk.Sata.Disk_X.Disk MIGRATE File", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -1625,7 +1813,7 @@ 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", + {name: "Update Disk.Sata.Disk_X.Disk MIGRATE File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -1642,7 +1830,38 @@ 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 RESIZE DOWN", + {name: "Update Disk.Sata.Disk_X.Disk MIGRATE Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test1", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"sata5": "test2:vm-0-disk-23,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk MIGRATE File LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test1", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"sata5": "test2:vm-0-disk-23,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk RESIZE DOWN File", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -1656,7 +1875,7 @@ 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", + {name: "Update Disk.Sata.Disk_X.Disk RESIZE DOWN File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -1673,7 +1892,36 @@ 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 UP", + {name: "Update Disk.Sata.Disk_X.Disk RESIZE DOWN Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Size: 9, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata0": "test:9,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk RESIZE DOWN Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Size: 9, + Storage: "test", + }}}}}, + output: map[string]interface{}{"sata0": "test:9,backup=0,replicate=0"}, + }, + {name: "Update Disk.Sata.Disk_X.Disk RESIZE UP File", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -1687,7 +1935,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{}, }, - {name: "Update Disk.Sata.Disk_X.Disk RESIZE UP LinkedClone", + {name: "Update Disk.Sata.Disk_X.Disk RESIZE UP File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -1704,6 +1952,33 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{}, }, + {name: "Update Disk.Sata.Disk_X.Disk RESIZE UP Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Id: 23, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, + {name: "Update Disk.Sata.Disk_X.Disk RESIZE UP Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, {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: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -1713,7 +1988,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{}, }, - {name: "Update Disk.Sata.Disk_X.Disk.Format CHANGE", + {name: "Update Disk.Sata.Disk_X.Disk.Format CHANGE File", currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -1727,7 +2002,7 @@ 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", + {name: "Update Disk.Sata.Disk_X.Disk.Format CHANGE File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -1744,6 +2019,39 @@ 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 Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Qcow2, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, + {name: "Update Disk.Sata.Disk_X.Disk.Format CHANGE Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_3: &QemuSataStorage{Disk: &QemuSataDisk{ + Format: QemuDiskFormat_Qcow2, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, // 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{ @@ -1843,7 +2151,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { output: map[string]interface{}{"scsi14": "NewStorage:cloudinit,format=raw"}, }, // Update Disk.Scsi.Disk_X.Disk - {name: "Update Disk.Scsi.Disk_X.Disk CHANGE", + {name: "Update Disk.Scsi.Disk_X.Disk CHANGE File", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ AsyncIO: QemuDiskAsyncIO_IOuring, Format: QemuDiskFormat_Raw, @@ -1859,7 +2167,7 @@ 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", + {name: "Update Disk.Scsi.Disk_X.Disk CHANGE File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -1878,12 +2186,45 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, 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 CHANGE Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"scsi15": "test:vm-0-disk-23,aio=native,backup=0,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk CHANGE Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_IOuring, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_15: &QemuScsiStorage{Disk: &QemuScsiDisk{ + AsyncIO: QemuDiskAsyncIO_Native, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{"scsi15": "test:base-100-disk-1/vm-0-disk-23,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", + {name: "Update Disk.Scsi.Disk_X.Disk MIGRATE File", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -1897,7 +2238,7 @@ 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", + {name: "Update Disk.Scsi.Disk_X.Disk MIGRATE File Linked Clone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -1914,7 +2255,36 @@ 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 RESIZE DOWN", + {name: "Update Disk.Scsi.Disk_X.Disk MIGRATE Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Id: 23, + Size: 10, + Storage: "test1", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"scsi17": "test2:vm-0-disk-23,backup=0,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk MIGRATE Volume Linked Clone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test1", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_17: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"scsi17": "test2:vm-0-disk-23,backup=0,replicate=0"}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk RESIZE DOWN File", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -1928,7 +2298,7 @@ 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", + {name: "Update Disk.Scsi.Disk_X.Disk RESIZE DOWN File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -1945,12 +2315,75 @@ 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 UP", + {name: "Update Disk.Scsi.Disk_X.Disk RESIZE DOWN Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + 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 Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_18: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + 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 File", + 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, + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk RESIZE UP File LinkedClone", + 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, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk RESIZE UP Volume", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, Id: 23, Size: 10, Storage: "test", + syntax: diskSyntaxVolume, }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, @@ -1959,7 +2392,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{}, }, - {name: "Update Disk.Scsi.Disk_X.Disk RESIZE UP LinkedClone", + {name: "Update Disk.Scsi.Disk_X.Disk RESIZE UP Volume LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -1968,6 +2401,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { LinkedDiskId: &uint1, Size: 10, Storage: "test", + syntax: diskSyntaxVolume, }}}}}, config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, @@ -1985,7 +2419,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{}, }, - {name: "Update Disk.Scsi.Disk_X.Disk.Format CHANGE", + {name: "Update Disk.Scsi.Disk_X.Disk.Format CHANGE File", currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -1999,7 +2433,7 @@ 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", + {name: "Update Disk.Scsi.Disk_X.Disk.Format CHANGE File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -2016,6 +2450,39 @@ 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 Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Qcow2, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, + {name: "Update Disk.Scsi.Disk_X.Disk.Format CHANGE Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_21: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Format: QemuDiskFormat_Qcow2, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, // 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{ @@ -2114,48 +2581,81 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { 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", + // Update Disk.VirtIO.Disk_X.Disk + {name: "Update Disk.VirtIO.Disk_X.Disk CHANGE File", + 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, + 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 File LinkedClone", + 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, + 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 CHANGE Volume", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_15: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ AsyncIO: QemuDiskAsyncIO_IOuring, - Format: QemuDiskFormat_Raw, Id: 23, Size: 10, Storage: "test", + syntax: diskSyntaxVolume, }}}}}, 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:0/vm-0-disk-23.raw,aio=native,backup=0,replicate=0"}, + output: map[string]interface{}{"virtio15": "test:vm-0-disk-23,aio=native,backup=0,replicate=0"}, }, - {name: "Update Disk.VirtIO.Disk_X.Disk CHANGE LinkedClone", + {name: "Update Disk.VirtIO.Disk_X.Disk CHANGE Volume LinkedClone", 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", + syntax: diskSyntaxVolume, }}}}}, 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"}, + output: map[string]interface{}{"virtio15": "test:base-100-disk-1/vm-0-disk-23,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", + {name: "Update Disk.VirtIO.Disk_X.Disk MIGRATE File", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -2169,7 +2669,7 @@ 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", + {name: "Update Disk.VirtIO.Disk_X.Disk MIGRATE File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ @@ -2186,7 +2686,36 @@ 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 RESIZE DOWN", + {name: "Update Disk.VirtIO.Disk_X.Disk MIGRATE Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Id: 23, + Size: 10, + Storage: "test1", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"virtio1": "test2:vm-0-disk-23,backup=0,replicate=0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk MIGRATE Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test1", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_1: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Size: 10, + Storage: "test2", + }}}}}, + output: map[string]interface{}{"virtio1": "test2:vm-0-disk-23,backup=0,replicate=0"}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE DOWN File", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -2200,7 +2729,7 @@ 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", + {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE DOWN File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ @@ -2217,7 +2746,38 @@ 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 UP", + {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE DOWN Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + 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 Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + 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 File", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -2231,7 +2791,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{}, }, - {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE UP LinkedClone", + {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE UP File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ @@ -2248,6 +2808,35 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{}, }, + {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE UP Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk RESIZE UP Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_3: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Size: 11, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, {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: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ @@ -2257,7 +2846,7 @@ func Test_ConfigQemu_mapToApiValues(t *testing.T) { }}}}}, output: map[string]interface{}{}, }, - {name: "Update Disk.VirtIO.Disk_X.Disk.Format CHANGE", + {name: "Update Disk.VirtIO.Disk_X.Disk.Format CHANGE File", currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ Format: QemuDiskFormat_Raw, Id: 23, @@ -2271,7 +2860,7 @@ 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", + {name: "Update Disk.VirtIO.Disk_X.Disk.Format CHANGE File LinkedClone", currentConfig: ConfigQemu{ LinkedVmId: 100, Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ @@ -2288,6 +2877,39 @@ 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 Volume", + currentConfig: ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Qcow2, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, + {name: "Update Disk.VirtIO.Disk_X.Disk.Format CHANGE Volume LinkedClone", + currentConfig: ConfigQemu{ + LinkedVmId: 100, + Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Raw, + Id: 23, + LinkedDiskId: &uint1, + Size: 10, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + config: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_5: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Format: QemuDiskFormat_Qcow2, + Size: 10, + Storage: "test", + }}}}}, + output: map[string]interface{}{}, + }, // 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{ @@ -2489,26 +3111,6 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, - {name: "Disks Ide Disk Format default", - input: map[string]interface{}{"ide2": "test:vm-100-disk-2"}, - output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ - Backup: true, - Format: QemuDiskFormat_Raw, - Id: uint2, - Replicate: true, - Storage: "test", - }}}}}, - }, - {name: "Disks Ide Disk Format raw", - input: map[string]interface{}{"ide3": "test:vm-100-disk-2.raw"}, - output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ - Backup: true, - Format: QemuDiskFormat_Raw, - Id: uint2, - Replicate: true, - Storage: "test", - }}}}}, - }, {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{ @@ -2673,6 +3275,31 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Ide Disk syntax fileSyntaxVolume", + input: map[string]interface{}{"ide2": "test:vm-100-disk-2"}, + output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_2: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + Replicate: true, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + }, + {name: "Disks Ide Disk syntax fileSyntaxVolume LinkedClone", + input: map[string]interface{}{"ide3": "test:base-110-disk-1/vm-100-disk-2"}, + output: &ConfigQemu{ + LinkedVmId: 110, + Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_3: &QemuIdeStorage{Disk: &QemuIdeDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + LinkedDiskId: &uint1, + Replicate: true, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + }, {name: "Disks Ide Disk wwn", input: map[string]interface{}{"ide1": "test2:100/vm-100-disk-53.qcow2,wwn=0x500DB82100C6FA59"}, output: &ConfigQemu{Disks: &QemuStorages{Ide: &QemuIdeDisks{Disk_1: &QemuIdeStorage{Disk: &QemuIdeDisk{ @@ -3023,26 +3650,6 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, - {name: "Disks Sata Disk Format default", - input: map[string]interface{}{"sata0": "test:vm-100-disk-2"}, - output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ - Backup: true, - Format: QemuDiskFormat_Raw, - Id: uint2, - Replicate: true, - Storage: "test", - }}}}}, - }, - {name: "Disks Sata Disk Format raw", - input: map[string]interface{}{"sata1": "test:vm-100-disk-2.raw"}, - output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ - Backup: true, - Format: QemuDiskFormat_Raw, - Id: uint2, - Replicate: true, - Storage: "test", - }}}}}, - }, {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{ @@ -3211,6 +3818,31 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks Sata Disk syntax fileSyntaxVolume", + input: map[string]interface{}{"sata0": "test:vm-100-disk-2"}, + output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_0: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + Replicate: true, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + }, + {name: "Disks Sata Disk syntax fileSyntaxVolume LinkedClone", + input: map[string]interface{}{"sata1": "test:base-110-disk-1/vm-100-disk-2"}, + output: &ConfigQemu{ + LinkedVmId: 110, + Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_1: &QemuSataStorage{Disk: &QemuSataDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + LinkedDiskId: &uint1, + Replicate: true, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + }, {name: "Disks Sata Disk wwn", input: map[string]interface{}{"sata5": "test2:100/vm-100-disk-47.qcow2,wwn=0x5001E48A00D567C9"}, output: &ConfigQemu{Disks: &QemuStorages{Sata: &QemuSataDisks{Disk_5: &QemuSataStorage{Disk: &QemuSataDisk{ @@ -3565,26 +4197,6 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test", }}}}}, }, - {name: "Disks Scsi Disk Format default", - input: map[string]interface{}{"scsi6": "test:vm-100-disk-2"}, - output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{ - Backup: true, - Format: QemuDiskFormat_Raw, - Id: uint2, - Replicate: true, - Storage: "test", - }}}}}, - }, - {name: "Disks Scsi Disk Format raw", - input: map[string]interface{}{"scsi7": "test:vm-100-disk-2.raw"}, - output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{ - Backup: true, - Format: QemuDiskFormat_Raw, - 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{ @@ -3771,6 +4383,31 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test", }}}}}, }, + {name: "Disks Scsi Disk syntax fileSyntaxVolume", + input: map[string]interface{}{"scsi6": "test:vm-100-disk-2"}, + output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_6: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + Replicate: true, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + }, + {name: "Disks Scsi Disk syntax fileSyntaxVolume LinkedClone", + input: map[string]interface{}{"scsi7": "test:base-110-disk-1/vm-100-disk-2"}, + output: &ConfigQemu{ + LinkedVmId: 110, + Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_7: &QemuScsiStorage{Disk: &QemuScsiDisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + LinkedDiskId: &uint1, + Replicate: true, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + }, {name: "Disks Scsi Disk wwn", input: map[string]interface{}{"scsi19": "test:100/vm-100-disk-2.qcow2,wwn=0x500E265400A1F3D7"}, output: &ConfigQemu{Disks: &QemuStorages{Scsi: &QemuScsiDisks{Disk_19: &QemuScsiStorage{Disk: &QemuScsiDisk{ @@ -4143,26 +4780,6 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, - {name: "Disks VirtIO Disk Format default", - input: map[string]interface{}{"virtio7": "test:vm-100-disk-2"}, - output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ - Backup: true, - Format: QemuDiskFormat_Raw, - Id: uint2, - Replicate: true, - Storage: "test", - }}}}}, - }, - {name: "Disks VirtIO Disk Format raw", - input: map[string]interface{}{"virtio8": "test:vm-100-disk-2.raw"}, - output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ - Backup: true, - Format: QemuDiskFormat_Raw, - Id: uint2, - Replicate: true, - Storage: "test", - }}}}}, - }, {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{ @@ -4342,6 +4959,31 @@ func Test_ConfigQemu_mapToStruct(t *testing.T) { Storage: "test2", }}}}}, }, + {name: "Disks VirtIO Disk syntax fileSyntaxVolume", + input: map[string]interface{}{"virtio7": "test:vm-100-disk-2"}, + output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_7: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + Replicate: true, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + }, + {name: "Disks VirtIO Disk syntax fileSyntaxVolume LinkedClone", + input: map[string]interface{}{"virtio8": "test:base-110-disk-1/vm-100-disk-2"}, + output: &ConfigQemu{ + LinkedVmId: 110, + Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_8: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ + Backup: true, + Format: QemuDiskFormat_Raw, + Id: uint2, + LinkedDiskId: &uint1, + Replicate: true, + Storage: "test", + syntax: diskSyntaxVolume, + }}}}}, + }, {name: "Disks VirtIO Disk wwn", input: map[string]interface{}{"virtio2": "test2:100/vm-100-disk-31.qcow2,wwn=0x500D3FAB00B4E672"}, output: &ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_2: &QemuVirtIOStorage{Disk: &QemuVirtIODisk{ From af11eb2f59353382a606d0353be0c1afca06dbf7 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:54:46 +0000 Subject: [PATCH 4/4] fix: node not set causes disk migration --- proxmox/config_qemu.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proxmox/config_qemu.go b/proxmox/config_qemu.go index eaf1dfad..1a7e6985 100644 --- a/proxmox/config_qemu.go +++ b/proxmox/config_qemu.go @@ -60,7 +60,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"` + Node string `json:"node,omitempty"` // Only returned setting it has no effect, set node in the VmRef instead 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 @@ -834,6 +834,7 @@ func (config *ConfigQemu) setVmr(vmr *VmRef) (err error) { } vmr.SetVmType("qemu") config.VmID = vmr.vmId + config.Node = vmr.node return }