diff --git a/docs/resources/virtual_environment_vm.md b/docs/resources/virtual_environment_vm.md index 96938188..16c30d73 100644 --- a/docs/resources/virtual_environment_vm.md +++ b/docs/resources/virtual_environment_vm.md @@ -182,6 +182,7 @@ output "ubuntu_vm_public_key" { protection for AMD models. - `hotplugged` - (Optional) The number of hotplugged vCPUs (defaults to `0`). + - `limit` - (Optional) Limit of CPU usage, `0...128`. (defaults to `0` -- no limit). - `numa` - (Boolean) Enable/disable NUMA. (default to `false`) - `sockets` - (Optional) The number of CPU sockets (defaults to `1`). - `type` - (Optional) The emulated CPU type, it's recommended to diff --git a/example/resource_virtual_environment_vm.tf b/example/resource_virtual_environment_vm.tf index 0e25ef3f..3537e8d3 100644 --- a/example/resource_virtual_environment_vm.tf +++ b/example/resource_virtual_environment_vm.tf @@ -13,6 +13,7 @@ resource "proxmox_virtual_environment_vm" "example_template" { cpu { cores = 2 numa = true + limit = 64 } smbios { diff --git a/proxmoxtf/resource/vm.go b/proxmoxtf/resource/vm.go index 0d265cd0..d599732b 100644 --- a/proxmoxtf/resource/vm.go +++ b/proxmoxtf/resource/vm.go @@ -56,6 +56,7 @@ const ( dvResourceVirtualEnvironmentVMCPUArchitecture = "x86_64" dvResourceVirtualEnvironmentVMCPUCores = 1 dvResourceVirtualEnvironmentVMCPUHotplugged = 0 + dvResourceVirtualEnvironmentVMCPULimit = 0 dvResourceVirtualEnvironmentVMCPUNUMA = false dvResourceVirtualEnvironmentVMCPUSockets = 1 dvResourceVirtualEnvironmentVMCPUType = "qemu64" @@ -175,6 +176,7 @@ const ( mkResourceVirtualEnvironmentVMCPUCores = "cores" mkResourceVirtualEnvironmentVMCPUFlags = "flags" mkResourceVirtualEnvironmentVMCPUHotplugged = "hotplugged" + mkResourceVirtualEnvironmentVMCPULimit = "limit" mkResourceVirtualEnvironmentVMCPUNUMA = "numa" mkResourceVirtualEnvironmentVMCPUSockets = "sockets" mkResourceVirtualEnvironmentVMCPUType = "type" @@ -526,8 +528,9 @@ func VM() *schema.Resource { mkResourceVirtualEnvironmentVMCPUArchitecture: dvResourceVirtualEnvironmentVMCPUArchitecture, mkResourceVirtualEnvironmentVMCPUCores: dvResourceVirtualEnvironmentVMCPUCores, mkResourceVirtualEnvironmentVMCPUFlags: []interface{}{}, - mkResourceVirtualEnvironmentVMCPUNUMA: dvResourceVirtualEnvironmentVMCPUNUMA, mkResourceVirtualEnvironmentVMCPUHotplugged: dvResourceVirtualEnvironmentVMCPUHotplugged, + mkResourceVirtualEnvironmentVMCPULimit: dvResourceVirtualEnvironmentVMCPULimit, + mkResourceVirtualEnvironmentVMCPUNUMA: dvResourceVirtualEnvironmentVMCPUNUMA, mkResourceVirtualEnvironmentVMCPUSockets: dvResourceVirtualEnvironmentVMCPUSockets, mkResourceVirtualEnvironmentVMCPUType: dvResourceVirtualEnvironmentVMCPUType, mkResourceVirtualEnvironmentVMCPUUnits: dvResourceVirtualEnvironmentVMCPUUnits, @@ -566,6 +569,15 @@ func VM() *schema.Resource { Default: dvResourceVirtualEnvironmentVMCPUHotplugged, ValidateDiagFunc: validation.ToDiagFunc(validation.IntBetween(0, 2304)), }, + mkResourceVirtualEnvironmentVMCPULimit: { + Type: schema.TypeInt, + Description: "Limit of CPU usage", + Optional: true, + Default: dvResourceVirtualEnvironmentVMCPULimit, + ValidateDiagFunc: validation.ToDiagFunc( + validation.IntBetween(0, 128), + ), + }, mkResourceVirtualEnvironmentVMCPUNUMA: { Type: schema.TypeBool, Description: "Enable/disable NUMA.", @@ -2028,6 +2040,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d cpuCores := cpuBlock[mkResourceVirtualEnvironmentVMCPUCores].(int) cpuFlags := cpuBlock[mkResourceVirtualEnvironmentVMCPUFlags].([]interface{}) cpuHotplugged := cpuBlock[mkResourceVirtualEnvironmentVMCPUHotplugged].(int) + cpuLimit := cpuBlock[mkResourceVirtualEnvironmentVMCPULimit].(int) cpuNUMA := types.CustomBool(cpuBlock[mkResourceVirtualEnvironmentVMCPUNUMA].(bool)) cpuSockets := cpuBlock[mkResourceVirtualEnvironmentVMCPUSockets].(int) cpuType := cpuBlock[mkResourceVirtualEnvironmentVMCPUType].(string) @@ -2057,6 +2070,10 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d if cpuHotplugged > 0 { updateBody.VirtualCPUCount = &cpuHotplugged } + + if cpuLimit > 0 { + updateBody.CPULimit = &cpuLimit + } } vmConfig, err := vmAPI.GetVM(ctx) @@ -2504,6 +2521,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{}) cpuCores := cpuBlock[mkResourceVirtualEnvironmentVMCPUCores].(int) cpuFlags := cpuBlock[mkResourceVirtualEnvironmentVMCPUFlags].([]interface{}) cpuHotplugged := cpuBlock[mkResourceVirtualEnvironmentVMCPUHotplugged].(int) + cpuLimit := cpuBlock[mkResourceVirtualEnvironmentVMCPULimit].(int) cpuSockets := cpuBlock[mkResourceVirtualEnvironmentVMCPUSockets].(int) cpuNUMA := types.CustomBool(cpuBlock[mkResourceVirtualEnvironmentVMCPUNUMA].(bool)) cpuType := cpuBlock[mkResourceVirtualEnvironmentVMCPUType].(string) @@ -2779,6 +2797,10 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{}) createBody.VirtualCPUCount = &cpuHotplugged } + if cpuLimit > 0 { + createBody.CPULimit = &cpuLimit + } + if description != "" { createBody.Description = &description } @@ -4041,6 +4063,13 @@ func vmReadCustom( cpu[mkResourceVirtualEnvironmentVMCPUHotplugged] = 0 } + if vmConfig.CPULimit != nil { + cpu[mkResourceVirtualEnvironmentVMCPULimit] = *vmConfig.CPULimit + } else { + // Default value of "cpulimit" is "0" according to the API documentation. + cpu[mkResourceVirtualEnvironmentVMCPULimit] = 0 + } + if vmConfig.NUMAEnabled != nil { cpu[mkResourceVirtualEnvironmentVMCPUNUMA] = *vmConfig.NUMAEnabled } else { @@ -4094,6 +4123,7 @@ func vmReadCustom( cpu[mkResourceVirtualEnvironmentVMCPUCores] != dvResourceVirtualEnvironmentVMCPUCores || len(cpu[mkResourceVirtualEnvironmentVMCPUFlags].([]interface{})) > 0 || cpu[mkResourceVirtualEnvironmentVMCPUHotplugged] != dvResourceVirtualEnvironmentVMCPUHotplugged || + cpu[mkResourceVirtualEnvironmentVMCPULimit] != dvResourceVirtualEnvironmentVMCPULimit || cpu[mkResourceVirtualEnvironmentVMCPUSockets] != dvResourceVirtualEnvironmentVMCPUSockets || cpu[mkResourceVirtualEnvironmentVMCPUType] != dvResourceVirtualEnvironmentVMCPUType || cpu[mkResourceVirtualEnvironmentVMCPUUnits] != dvResourceVirtualEnvironmentVMCPUUnits { @@ -5559,6 +5589,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D cpuCores := cpuBlock[mkResourceVirtualEnvironmentVMCPUCores].(int) cpuFlags := cpuBlock[mkResourceVirtualEnvironmentVMCPUFlags].([]interface{}) cpuHotplugged := cpuBlock[mkResourceVirtualEnvironmentVMCPUHotplugged].(int) + cpuLimit := cpuBlock[mkResourceVirtualEnvironmentVMCPULimit].(int) cpuNUMA := types.CustomBool(cpuBlock[mkResourceVirtualEnvironmentVMCPUNUMA].(bool)) cpuSockets := cpuBlock[mkResourceVirtualEnvironmentVMCPUSockets].(int) cpuType := cpuBlock[mkResourceVirtualEnvironmentVMCPUType].(string) @@ -5581,6 +5612,12 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D del = append(del, "vcpus") } + if cpuLimit > 0 { + updateBody.CPULimit = &cpuLimit + } else { + del = append(del, "cpulimit") + } + cpuFlagsConverted := make([]string, len(cpuFlags)) for fi, flag := range cpuFlags {