From e84841ac4b48d03b765eba5b58839f0b22d6ec61 Mon Sep 17 00:00:00 2001 From: Vasil Atanasov Date: Thu, 14 Dec 2023 16:40:18 +0200 Subject: [PATCH] [feat sr-iov] Adding memory_reservation_locked_to_max property to vsphere_virtual_macine schema Fixes #2091 The memory_reservation_locked_to_max property was missing from vsphere_virtual_macine schema (both data and resource). The property of the VM was automaticaly set to false if memory and memory_reservation properties have different values. With this commit the property can be set to true explicitly and it will be applied only if memory and memory_reservation properties have same values. If the memory_reservation_locked_to_max is not explicitly set to true the original behavior is preserved. Signed-off-by: Vasil Atanasov --- ...ata_source_vsphere_virtual_machine_test.go | 1 + .../resource_vsphere_virtual_machine_test.go | 54 +++++++++++++++++++ vsphere/virtual_machine_config_structure.go | 24 ++++++++- 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/vsphere/data_source_vsphere_virtual_machine_test.go b/vsphere/data_source_vsphere_virtual_machine_test.go index cc9613a6d..4915c14c8 100644 --- a/vsphere/data_source_vsphere_virtual_machine_test.go +++ b/vsphere/data_source_vsphere_virtual_machine_test.go @@ -33,6 +33,7 @@ func TestAccDataSourceVSphereVirtualMachine_basic(t *testing.T) { resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "guest_id"), resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "scsi_type"), resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "memory"), + resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "memory_reservation_locked_to_max"), resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "num_cpus"), resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "num_cores_per_socket"), resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "firmware"), diff --git a/vsphere/resource_vsphere_virtual_machine_test.go b/vsphere/resource_vsphere_virtual_machine_test.go index c278016df..a56668874 100644 --- a/vsphere/resource_vsphere_virtual_machine_test.go +++ b/vsphere/resource_vsphere_virtual_machine_test.go @@ -2559,6 +2559,27 @@ func TestAccResourceVSphereVirtualMachine_SRIOV(t *testing.T) { }) } +func TestAccResourceVSphereVirtualMachine_createMemoryReservationLockedToMax(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + RunSweepers() + testAccPreCheck(t) + testAccResourceVSphereVirtualMachinePreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccResourceVSphereVirtualMachineCheckExists(false), + Steps: []resource.TestStep{ + { + Config: testAccResourceVSphereVirtualMachineCreateMemoryLockToMax(), + Check: resource.ComposeTestCheckFunc( + testAccResourceVSphereVirtualMachineCheckExists(true), + resource.TestCheckResourceAttr("vsphere_virtual_machine.vm", "memory_reservation_locked_to_max", "true"), + ), + }, + }, + }) +} + func testAccResourceVSphereVirtualMachinePreCheck(t *testing.T) { // Note that TF_VAR_VSPHERE_USE_LINKED_CLONE is also a variable and its presence // speeds up tests greatly, but it's not a necessary variable, so we don't @@ -7383,6 +7404,39 @@ resource "vsphere_virtual_machine" "vm" { ) } +func testAccResourceVSphereVirtualMachineCreateMemoryLockToMax() string { + return fmt.Sprintf(` + + +%s // Mix and match config + +resource "vsphere_virtual_machine" "vm" { + name = "testacc-test" + resource_pool_id = data.vsphere_host.roothost1.resource_pool_id + datastore_id = data.vsphere_datastore.rootds1.id + host_system_id = data.vsphere_host.roothost1.id + + num_cpus = 2 + memory = 2048 + memory_reservation = 2048 + memory_reservation_locked_to_max = true + guest_id = "other3xLinuxGuest" + wait_for_guest_net_timeout = 0 + network_interface { + network_id = "${data.vsphere_network.network1.id}" + } + + disk { + label = "disk0" + size = 20 + } +} +`, + + testAccResourceVSphereVirtualMachineConfigBase(), + ) +} + // Tests to skip until new features are developed. // Needs storage policy resource diff --git a/vsphere/virtual_machine_config_structure.go b/vsphere/virtual_machine_config_structure.go index a478e5f37..623d7ce8f 100644 --- a/vsphere/virtual_machine_config_structure.go +++ b/vsphere/virtual_machine_config_structure.go @@ -249,6 +249,13 @@ func schemaVirtualMachineConfigSpec() map[string]*schema.Schema { Default: 1024, Description: "The size of the virtual machine's memory, in MB.", }, + "memory_reservation_locked_to_max": { + Type: schema.TypeBool, + Optional: true, + Description: "If set true, memory resource reservation for this virtual machine will always be equal to the virtual machine's memory size;" + + "increases in memory size will be rejected when a corresponding reservation increase is not possible." + + " This feature may only be enabled if it is currently possible to reserve all of the virtual machine's memory.", + }, "memory_hot_add_enabled": { Type: schema.TypeBool, Optional: true, @@ -957,6 +964,12 @@ func flattenVirtualMachineConfigInfo(d *schema.ResourceData, obj *types.VirtualM _ = d.Set("num_cores_per_socket", obj.Hardware.NumCoresPerSocket) _ = d.Set("memory", obj.Hardware.MemoryMB) _ = d.Set("memory_hot_add_enabled", obj.MemoryHotAddEnabled) + + memoryReservationLockedToMax := false + if obj.MemoryReservationLockedToMax != nil { + memoryReservationLockedToMax = *obj.MemoryReservationLockedToMax + } + _ = d.Set("memory_reservation_locked_to_max", memoryReservationLockedToMax) _ = d.Set("cpu_hot_add_enabled", obj.CpuHotAddEnabled) _ = d.Set("cpu_hot_remove_enabled", obj.CpuHotRemoveEnabled) _ = d.Set("swap_placement_policy", obj.SwapPlacement) @@ -1044,8 +1057,17 @@ func expandVirtualMachineConfigSpecChanged(d *schema.ResourceData, client *govmo // cloning from a template that has it enabled. The solution is to set it to // false when needed, but leave it alone when the change is not necessary. func getMemoryReservationLockedToMax(d *schema.ResourceData) *bool { - if d.Get("memory_reservation").(int) != d.Get("memory").(int) { + memory := d.Get("memory").(int) + memoryReservation := d.Get("memory_reservation").(int) + memoryLockMax := d.Get("memory_reservation_locked_to_max").(bool) + + if memory != memoryReservation { return structure.BoolPtr(false) } + + if memory == memoryReservation && memoryLockMax == true { + return structure.BoolPtr(true) + } + return nil }