diff --git a/proxmox/config_qemu_memory.go b/proxmox/config_qemu_memory.go index 3aba548b..e85c0be2 100644 --- a/proxmox/config_qemu_memory.go +++ b/proxmox/config_qemu_memory.go @@ -1,6 +1,8 @@ package proxmox import ( + "fmt" + "github.com/Telmate/proxmox-api-go/internal/parse" ) @@ -10,6 +12,12 @@ type QemuMemory struct { Shares *QemuMemoryShares `json:"shares,omitempty"` // 0 to clear, max 50000 } +const ( + QemuMemory_Error_MinimumCapacityMiB_GreaterThan_CapacityMiB string = "minimum capacity MiB cannot be greater than capacity MiB" + QemuMemory_Error_NoMemoryCapacity string = "no memory capacity specified" + QemuMemory_Error_SharesHasNoEffectWithoutBallooning string = "shares has no effect when capacity equals minimum capacity" +) + func (config QemuMemory) mapToAPI(current *QemuMemory, params map[string]interface{}) string { if current == nil { // create if config.CapacityMiB != nil { @@ -71,8 +79,87 @@ func (QemuMemory) mapToSDK(params map[string]interface{}) *QemuMemory { return &config } +func (config QemuMemory) Validate(current *QemuMemory) error { + var eventualCapacityMiB QemuMemoryCapacity + var eventualMinimumCapacityMiB QemuMemoryBalloonCapacity + if config.MinimumCapacityMiB != nil { + if err := config.MinimumCapacityMiB.Validate(); err != nil { + return err + } + if config.CapacityMiB != nil && QemuMemoryCapacity(*config.MinimumCapacityMiB) > *config.CapacityMiB { + return fmt.Errorf(QemuMemory_Error_MinimumCapacityMiB_GreaterThan_CapacityMiB) + } + eventualMinimumCapacityMiB = *config.MinimumCapacityMiB + eventualCapacityMiB = QemuMemoryCapacity(eventualMinimumCapacityMiB) + } else if current != nil && current.MinimumCapacityMiB != nil { + eventualMinimumCapacityMiB = *current.MinimumCapacityMiB + } + if config.CapacityMiB != nil { + if err := config.CapacityMiB.Validate(); err != nil { + return err + } + eventualCapacityMiB = *config.CapacityMiB + } else if current != nil && current.CapacityMiB != nil { + eventualCapacityMiB = *current.CapacityMiB + } + if eventualCapacityMiB == 0 { + return fmt.Errorf(QemuMemory_Error_NoMemoryCapacity) + } + if config.Shares != nil { + if err := config.Shares.Validate(); err != nil { + return err + } + if *config.Shares > 0 { + if eventualCapacityMiB == QemuMemoryCapacity(eventualMinimumCapacityMiB) { + return fmt.Errorf(QemuMemory_Error_SharesHasNoEffectWithoutBallooning) + } + } + } + return nil +} + type QemuMemoryBalloonCapacity uint32 // max 4178944 +const ( + QemuMemoryBalloonCapacity_Error_Invalid string = "memory balloon capacity has a maximum of 4178944" + qemuMemoryBalloonCapacity_Max QemuMemoryBalloonCapacity = 4178944 +) + +func (m QemuMemoryBalloonCapacity) Validate() error { + if m > qemuMemoryBalloonCapacity_Max { + return fmt.Errorf(QemuMemoryBalloonCapacity_Error_Invalid) + } + return nil +} + type QemuMemoryCapacity uint32 // max 4178944 +const ( + QemuMemoryCapacity_Error_Maximum string = "memory capacity has a maximum of 4178944" + QemuMemoryCapacity_Error_Minimum string = "memory capacity has a minimum of 1" + qemuMemoryCapacity_Max QemuMemoryCapacity = 4178944 +) + +func (m QemuMemoryCapacity) Validate() error { + if m == 0 { + return fmt.Errorf(QemuMemoryCapacity_Error_Minimum) + } + if m > qemuMemoryCapacity_Max { + return fmt.Errorf(QemuMemoryCapacity_Error_Maximum) + } + return nil +} + type QemuMemoryShares uint16 // max 50000 + +const ( + QemuMemoryShares_Error_Invalid string = "memory shares has a maximum of 50000" + qemuMemoryShares_Max QemuMemoryShares = 50000 +) + +func (m QemuMemoryShares) Validate() error { + if m > qemuMemoryShares_Max { + return fmt.Errorf(QemuMemoryShares_Error_Invalid) + } + return nil +} diff --git a/proxmox/config_qemu_memory_test.go b/proxmox/config_qemu_memory_test.go new file mode 100644 index 00000000..98da584c --- /dev/null +++ b/proxmox/config_qemu_memory_test.go @@ -0,0 +1,221 @@ +package proxmox + +import ( + "errors" + "testing" + + "github.com/Telmate/proxmox-api-go/internal/util" + "github.com/stretchr/testify/require" +) + +func Test_QemuMemory_Validate(t *testing.T) { + type testInput struct { + new QemuMemory + current *QemuMemory + } + tests := []struct { + name string + input testInput + output error + }{ + // there could still be some edge cases that are not covered + {name: `Valid Create new.CapacityMiB`, + input: testInput{new: QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(qemuMemoryCapacity_Max))}}}, + {name: `Valid Update new.CapacityMiB smaller then current.MinimumCapacityMiB`, + input: testInput{ + new: QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1000))}, + current: &QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(2000))}}}, + {name: `Valid Update new.CapacityMiB smaller then current.MinimumCapacityMiB and MinimumCapacityMiB lowered`, + input: testInput{ + new: QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1000)), MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000))}, + current: &QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(2000))}}}, + {name: `Valid Create new.MinimumCapacityMiB`, + input: testInput{new: QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000))}}}, + {name: `Valid Update new.CapacityMiB == new.MinimumCapacityMiB && new.CapacityMiB > current.CapacityMiB`, + input: testInput{ + new: QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1500)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1500))}, + current: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1000))}}}, + {name: `Valid Update new.MinimumCapacityMiB > current.MinimumCapacityMiB && new.MinimumCapacityMiB < new.CapacityMiB`, + input: testInput{ + new: QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(3000)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(2000))}, + current: &QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1500))}}}, + {name: `Valid Create new.Shares(qemuMemoryShares_Max) new.CapacityMiB & new.MinimumCapacityMiB`, + input: testInput{ + new: QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1001)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000)), + Shares: util.Pointer(QemuMemoryShares(qemuMemoryShares_Max))}}}, + {name: `Valid Create new.Shares new.MinimumCapacityMiB`, + input: testInput{ + new: QemuMemory{ + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000)), + Shares: util.Pointer(QemuMemoryShares(0))}}}, + {name: `Valid Create new.Shares(0) new.CapacityMiB & new.MinimumCapacityMiB`, + input: testInput{ + new: QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1001)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000)), + Shares: util.Pointer(QemuMemoryShares(0))}}}, + {name: `Valid Update new.Shares(0) current.CapacityMiB == current.MinimumCapacityMiB`, + input: testInput{ + new: QemuMemory{Shares: util.Pointer(QemuMemoryShares(0))}, + current: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1000)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000))}}}, + {name: `Invalid Create new.CapacityMiB(0)`, + input: testInput{new: QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(0))}}, + output: errors.New(QemuMemoryCapacity_Error_Minimum)}, + {name: `Invalid Update new.CapacityMiB(0)`, + input: testInput{ + new: QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(0))}, + current: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1000))}}, + output: errors.New(QemuMemoryCapacity_Error_Minimum)}, + {name: `Invalid Create new.CapacityMiB > qemuMemoryCapacity_Max`, + input: testInput{new: QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(qemuMemoryCapacity_Max + 1))}}, + output: errors.New(QemuMemoryCapacity_Error_Maximum)}, + {name: `Invalid Update new.CapacityMiB > qemuMemoryCapacity_Max`, + input: testInput{ + new: QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(qemuMemoryCapacity_Max + 1))}, + current: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(qemuMemoryCapacity_Max))}}, + output: errors.New(QemuMemoryCapacity_Error_Maximum)}, + {name: `Invalid Update new.CapacityMiB(0)`, + input: testInput{ + new: QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(0))}, + current: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1000))}}, + output: errors.New(QemuMemoryCapacity_Error_Minimum)}, + {name: `Invalid Create new.MinimumCapacityMiB to big`, + input: testInput{new: QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(qemuMemoryBalloonCapacity_Max + 1))}}, + output: errors.New(QemuMemoryBalloonCapacity_Error_Invalid)}, + {name: `Invalid Update new.MinimumCapacityMiB to big`, + input: testInput{ + new: QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(qemuMemoryBalloonCapacity_Max + 1))}, + current: &QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000))}}, + output: errors.New(QemuMemoryBalloonCapacity_Error_Invalid)}, + {name: `Invalid Create new.MinimumCapacityMiB > new.CapacityMiB`, + input: testInput{ + new: QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1000)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(2000))}}, + output: errors.New(QemuMemory_Error_MinimumCapacityMiB_GreaterThan_CapacityMiB)}, + {name: `Invalid Create new.Shares(1)`, + input: testInput{new: QemuMemory{Shares: util.Pointer(QemuMemoryShares(1))}}, + output: errors.New(QemuMemory_Error_NoMemoryCapacity)}, + {name: `Invalid Create new.Shares() too big and new.CapacityMiB & new.MinimumCapacityMiB`, + input: testInput{ + new: QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1001)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000)), + Shares: util.Pointer(QemuMemoryShares(qemuMemoryShares_Max + 1))}}, + output: errors.New(QemuMemoryShares_Error_Invalid)}, + {name: `Invalid Update new.Shares() too big and new.CapacityMiB & new.MinimumCapacityMiB`, + input: testInput{ + new: QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1001)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000)), + Shares: util.Pointer(QemuMemoryShares(qemuMemoryShares_Max + 1))}, + current: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(512)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(256)), + Shares: util.Pointer(QemuMemoryShares(1))}}, + output: errors.New(QemuMemoryShares_Error_Invalid)}, + {name: `Invalid Create new.Shares(1) when new.CapacityMiB == new.MinimumCapacityMiB`, + input: testInput{new: QemuMemory{Shares: util.Pointer(QemuMemoryShares(1))}}, + output: errors.New(QemuMemory_Error_NoMemoryCapacity)}, + {name: `Invalid Update new.Shares(1) when current.CapacityMiB == current.MinimumCapacityMiB`, + input: testInput{ + new: QemuMemory{Shares: util.Pointer(QemuMemoryShares(1))}, + current: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1000)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000))}}, + output: errors.New(QemuMemory_Error_SharesHasNoEffectWithoutBallooning)}, + {name: `Invalid Update new.Shares(1) new.CapacityMiB == current.MinimumCapacityMiB & MinimumCapacityMiB not updated`, + input: testInput{ + new: QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1024)), + Shares: util.Pointer(QemuMemoryShares(1))}, + current: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(2048)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1024))}}, + output: errors.New(QemuMemory_Error_SharesHasNoEffectWithoutBallooning)}, + {name: `Invalid Update new.Shares(1) new.MinimumCapacityMiB == current.CapacityMiB & CapacityMiB not updated`, + input: testInput{ + new: QemuMemory{ + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(2048)), + Shares: util.Pointer(QemuMemoryShares(1))}, + current: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(2048)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1024))}}, + output: errors.New(QemuMemory_Error_SharesHasNoEffectWithoutBallooning)}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require.Equal(t, test.output, test.input.new.Validate(test.input.current)) + }) + } +} + +func Test_QemuMemoryBalloonCapacity_Validate(t *testing.T) { + tests := []struct { + name string + input QemuMemoryBalloonCapacity + output error + }{ + {name: `Valid`, + input: qemuMemoryBalloonCapacity_Max}, + {name: `Invalid Max`, + input: qemuMemoryBalloonCapacity_Max + 1, + output: errors.New(QemuMemoryBalloonCapacity_Error_Invalid)}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require.Equal(t, test.output, test.input.Validate()) + }) + } +} + +func Test_QemuMemoryCapacity_Validate(t *testing.T) { + tests := []struct { + name string + input QemuMemoryCapacity + output error + }{ + {name: `Valid`, + input: qemuMemoryCapacity_Max}, + {name: `Invalid Max`, + input: qemuMemoryCapacity_Max + 1, + output: errors.New(QemuMemoryCapacity_Error_Maximum)}, + {name: `Invalid Min`, + input: 0, + output: errors.New(QemuMemoryCapacity_Error_Minimum)}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require.Equal(t, test.output, test.input.Validate()) + }) + } +} + +func Test_QemuMemoryShares_Validate(t *testing.T) { + tests := []struct { + name string + input QemuMemoryShares + output error + }{ + {name: `Valid`, + input: qemuMemoryShares_Max, + }, + {name: `Invalid`, + input: qemuMemoryShares_Max + 1, + output: errors.New(QemuMemoryShares_Error_Invalid), + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require.Equal(t, test.output, test.input.Validate()) + }) + } +} diff --git a/proxmox/config_qemu_test.go b/proxmox/config_qemu_test.go index e41e0822..30a48aa3 100644 --- a/proxmox/config_qemu_test.go +++ b/proxmox/config_qemu_test.go @@ -5614,6 +5614,9 @@ func Test_ConfigQemu_Validate(t *testing.T) { Concurrent: 10}}} } baseConfig := func(config ConfigQemu) ConfigQemu { + if config.Memory == nil { + config.Memory = &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1024))} + } return config } validCloudInit := QemuCloudInitDisk{Format: QemuDiskFormat_Raw, Storage: "Test"} @@ -6704,6 +6707,122 @@ func Test_ConfigQemu_Validate(t *testing.T) { {name: `VirtIO errors.New(Error_QemuWorldWideName_Invalid)`, input: baseConfig(ConfigQemu{Disks: &QemuStorages{VirtIO: &QemuVirtIODisks{Disk_13: &QemuVirtIOStorage{Passthrough: &QemuVirtIOPassthrough{File: "/dev/disk/by-id/scsi1", WorldWideName: "0x5004A3B2C1D0E0F1#"}}}}}), err: errors.New(Error_QemuWorldWideName_Invalid)}}}, + {category: `Memory`, + valid: []test{ + {name: `Create CapacityMiB only`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1024))}})}, + {name: `Update new.CapacityMiB smaller then current.MinimumCapacityMiB`, + input: ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1000))}}, + current: &ConfigQemu{Memory: &QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(2000))}}}, + {name: `Update new.CapacityMiB smaller then current.MinimumCapacityMiB and MinimumCapacityMiB lowered`, + input: ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1000)), MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000))}}, + current: &ConfigQemu{Memory: &QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(2000))}}}, + {name: `Create new.MinimumCapacityMiB`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000))}})}, + {name: `Update new.CapacityMiB == new.MinimumCapacityMiB && new.CapacityMiB > current.CapacityMiB`, + input: ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1500)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1500))}}, + current: &ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1000))}}}, + {name: `Update new.MinimumCapacityMiB > current.MinimumCapacityMiB && new.MinimumCapacityMiB < new.CapacityMiB`, + input: ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(3000)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(2000))}}, + current: &ConfigQemu{Memory: &QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1500))}}}, + {name: `Create new.Shares(qemuMemoryShares_Max) new.CapacityMiB & new.MinimumCapacityMiB`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1001)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000)), + Shares: util.Pointer(QemuMemoryShares(qemuMemoryShares_Max))}})}, + {name: `Create new.Shares new.MinimumCapacityMiB`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{ + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000)), + Shares: util.Pointer(QemuMemoryShares(0))}})}, + {name: `Create new.Shares(0) new.CapacityMiB & new.MinimumCapacityMiB`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1001)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000)), + Shares: util.Pointer(QemuMemoryShares(0))}})}, + {name: `Update new.Shares(0) current.CapacityMiB == current.MinimumCapacityMiB`, + input: ConfigQemu{Memory: &QemuMemory{Shares: util.Pointer(QemuMemoryShares(0))}}, + current: &ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1000)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000))}}}}, + invalid: []test{ + {name: `Create new.CapacityMiB(0)`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(0))}}), + err: errors.New(QemuMemoryCapacity_Error_Minimum)}, + {name: `Update new.CapacityMiB(0)`, + input: ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(0))}}, + current: &ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1000))}}, + err: errors.New(QemuMemoryCapacity_Error_Minimum)}, + {name: `Create new.CapacityMiB > qemuMemoryCapacity_Max`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(qemuMemoryCapacity_Max + 1))}}), + err: errors.New(QemuMemoryCapacity_Error_Maximum)}, + {name: `Update new.CapacityMiB > qemuMemoryCapacity_Max`, + input: ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(qemuMemoryCapacity_Max + 1))}}, + current: &ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(qemuMemoryCapacity_Max))}}, + err: errors.New(QemuMemoryCapacity_Error_Maximum)}, + {name: `Update new.CapacityMiB(0)`, + input: ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(0))}}, + current: &ConfigQemu{Memory: &QemuMemory{CapacityMiB: util.Pointer(QemuMemoryCapacity(1000))}}, + err: errors.New(QemuMemoryCapacity_Error_Minimum)}, + {name: `Create new.MinimumCapacityMiB to big`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(qemuMemoryBalloonCapacity_Max + 1))}}), + err: errors.New(QemuMemoryBalloonCapacity_Error_Invalid)}, + {name: `Update new.MinimumCapacityMiB to big`, + input: ConfigQemu{Memory: &QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(qemuMemoryBalloonCapacity_Max + 1))}}, + current: &ConfigQemu{Memory: &QemuMemory{MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000))}}, + err: errors.New(QemuMemoryBalloonCapacity_Error_Invalid)}, + {name: `Create new.MinimumCapacityMiB > new.CapacityMiB`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1000)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(2000))}}), + err: errors.New(QemuMemory_Error_MinimumCapacityMiB_GreaterThan_CapacityMiB)}, + {name: `Create new.Shares(1)`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{Shares: util.Pointer(QemuMemoryShares(1))}}), + err: errors.New(QemuMemory_Error_NoMemoryCapacity)}, + {name: `Create new.Shares() too big and new.CapacityMiB & new.MinimumCapacityMiB`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1001)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000)), + Shares: util.Pointer(QemuMemoryShares(qemuMemoryShares_Max + 1))}}), + err: errors.New(QemuMemoryShares_Error_Invalid)}, + {name: `Update new.Shares() too big and new.CapacityMiB & new.MinimumCapacityMiB`, + input: ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1001)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000)), + Shares: util.Pointer(QemuMemoryShares(qemuMemoryShares_Max + 1))}}, + current: &ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(512)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(256)), + Shares: util.Pointer(QemuMemoryShares(1))}}, + err: errors.New(QemuMemoryShares_Error_Invalid)}, + {name: `Create new.Shares(1) when new.CapacityMiB == new.MinimumCapacityMiB`, + input: baseConfig(ConfigQemu{Memory: &QemuMemory{Shares: util.Pointer(QemuMemoryShares(1))}}), + err: errors.New(QemuMemory_Error_NoMemoryCapacity)}, + {name: `Update new.Shares(1) when current.CapacityMiB == current.MinimumCapacityMiB`, + input: ConfigQemu{Memory: &QemuMemory{Shares: util.Pointer(QemuMemoryShares(1))}}, + current: &ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1000)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1000))}}, + err: errors.New(QemuMemory_Error_SharesHasNoEffectWithoutBallooning)}, + {name: `Update new.Shares(1) new.CapacityMiB == current.MinimumCapacityMiB & MinimumCapacityMiB not updated`, + input: ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(1024)), + Shares: util.Pointer(QemuMemoryShares(1))}}, + current: &ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(2048)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1024))}}, + err: errors.New(QemuMemory_Error_SharesHasNoEffectWithoutBallooning)}, + {name: `Update new.Shares(1) new.MinimumCapacityMiB == current.CapacityMiB & CapacityMiB not updated`, + input: ConfigQemu{Memory: &QemuMemory{ + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(2048)), + Shares: util.Pointer(QemuMemoryShares(1))}}, + current: &ConfigQemu{Memory: &QemuMemory{ + CapacityMiB: util.Pointer(QemuMemoryCapacity(2048)), + MinimumCapacityMiB: util.Pointer(QemuMemoryBalloonCapacity(1024))}}, + err: errors.New(QemuMemory_Error_SharesHasNoEffectWithoutBallooning)}}}, {category: `PoolName`, valid: []test{ {name: ``, diff --git a/test/api/CloudInit/shared_test.go b/test/api/CloudInit/shared_test.go index f7473335..f81582b0 100644 --- a/test/api/CloudInit/shared_test.go +++ b/test/api/CloudInit/shared_test.go @@ -30,7 +30,7 @@ func _create_vm_spec(network bool) pxapi.ConfigQemu { Name: "test-qemu01", Bios: "seabios", Tablet: util.Pointer(true), - Memory: 2048, + Memory: &pxapi.QemuMemory{CapacityMiB: util.Pointer(pxapi.QemuMemoryCapacity(2048))}, QemuOs: "l26", QemuCores: 1, QemuSockets: 1, diff --git a/test/api/Qemu/shared_test.go b/test/api/Qemu/shared_test.go index 41924f14..712dceaf 100644 --- a/test/api/Qemu/shared_test.go +++ b/test/api/Qemu/shared_test.go @@ -34,7 +34,7 @@ func _create_vm_spec(network bool) pxapi.ConfigQemu { Name: "test-qemu01", Bios: "seabios", Tablet: util.Pointer(true), - Memory: 128, + Memory: &pxapi.QemuMemory{CapacityMiB: util.Pointer(pxapi.QemuMemoryCapacity(128))}, QemuOs: "l26", QemuCores: 1, QemuSockets: 1,