0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-06-30 02:31:10 +00:00

feat(vm): add support for cpu affinity attribute (#1148) (#1153)

* feat(vm): add support for cpu `affinity` attribute (#1148)

It helps to pin VMs to the special cpu.

Signed-off-by: Serge Logvinov <serge.logvinov@sinextra.dev>

* add clarification about the format and permission requirements for `affinity`
* do not add `affinity` property to the API call if is not set

Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>

---------

Signed-off-by: Serge Logvinov <serge.logvinov@sinextra.dev>
Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
Co-authored-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
Serge 2024-03-24 03:34:59 +02:00 committed by GitHub
parent 9fee8c1e2e
commit 83a5971cf6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 51 additions and 3 deletions

View File

@ -231,11 +231,15 @@ output "ubuntu_vm_public_key" {
- `custom-<model>` - Custom CPU model. All `custom-<model>` values
should be defined in `/etc/pve/virtual-guest/cpu-models.conf` file.
- `units` - (Optional) The CPU units (defaults to `1024`).
- `affinity` - (Optional) The CPU cores that are used to run the VMs vCPU. The
value is a list of CPU IDs, separated by commas. The CPU IDs are zero-based.
For example, `0,1,2,3` (which also can be shortened to `0-3`) means that the VMs vCPUs are run on the first four
CPU cores. Setting `affinity` is only allowed for `root@pam` authenticated user.
- `description` - (Optional) The description.
- `disk` - (Optional) A disk (multiple blocks supported).
- `aio` - (Optional) The disk AIO mode (defaults to `io_uring`).
- `io_uring` - Use io_uring.
- `native` - Use native AIO. Should be used with to unbuffered, O_DIRECT, raw block storage only,
- `native` - Use native AIO. Should be used with to unbuffered, O_DIRECT, raw block storage only,
with the disk `cache` must be set to `none`. Raw block storage types include iSCSI, CEPH/RBD, and NVMe.
- `threads` - Use thread-based AIO.
- `backup` - (Optional) Whether the drive should be included when making backups (defaults to `true`).
@ -422,7 +426,7 @@ output "ubuntu_vm_public_key" {
- `queues` - (Optional) The number of queues for VirtIO (1..64).
- `rate_limit` - (Optional) The rate limit in megabytes per second.
- `vlan_id` - (Optional) The VLAN identifier.
- `trunks` - (Optional) String containing a `;` separated list of VLAN trunks
- `trunks` - (Optional) String containing a `;` separated list of VLAN trunks
("10;20;30"). Note that the VLAN-aware feature need to be enabled on the PVE
Linux Bridge to use trunks.
- `node_name` - (Required) The name of the node to assign the virtual machine

View File

@ -14,6 +14,7 @@ resource "proxmox_virtual_environment_vm" "example_template" {
cores = 2
numa = true
limit = 64
# affinity = "0-1"
}
smbios {
@ -75,7 +76,7 @@ resource "proxmox_virtual_environment_vm" "example_template" {
address = "dhcp"
}
# ipv6 {
# address = "dhcp"
# address = "dhcp"
#}
}

View File

@ -236,6 +236,7 @@ type CreateRequestBody struct {
CPULimit *int `json:"cpulimit,omitempty" url:"cpulimit,omitempty"`
CPUSockets *int `json:"sockets,omitempty" url:"sockets,omitempty"`
CPUUnits *int `json:"cpuunits,omitempty" url:"cpuunits,omitempty"`
CPUAffinity *string `json:"affinity,omitempty" url:"affinity,omitempty"`
DedicatedMemory *int `json:"memory,omitempty" url:"memory,omitempty"`
Delete []string `json:"delete,omitempty" url:"delete,omitempty,comma"`
DeletionProtection *types.CustomBool `json:"protection,omitempty" url:"protection,omitempty,int"`
@ -364,6 +365,7 @@ type GetResponseData struct {
CPULimit *types.CustomInt `json:"cpulimit,omitempty"`
CPUSockets *int `json:"sockets,omitempty"`
CPUUnits *int `json:"cpuunits,omitempty"`
CPUAffinity *string `json:"affinity,omitempty"`
DedicatedMemory *types.CustomInt64 `json:"memory,omitempty"`
DeletionProtection *types.CustomBool `json:"protection,omitempty"`
Description *string `json:"description,omitempty"`

View File

@ -144,6 +144,13 @@ func CPUTypeValidator() schema.SchemaValidateDiagFunc {
))
}
// CPUAffinityValidator returns a schema validation function for a CPU affinity.
func CPUAffinityValidator() schema.SchemaValidateDiagFunc {
return validation.ToDiagFunc(
validation.StringMatch(regexp.MustCompile(`^\d+[\d-,]*$`), "must contain numbers but also number ranges"),
)
}
// QEMUAgentTypeValidator is a schema validation function for QEMU agent types.
func QEMUAgentTypeValidator() schema.SchemaValidateDiagFunc {
return validation.ToDiagFunc(validation.StringInSlice([]string{"isa", "virtio"}, false))

View File

@ -64,6 +64,7 @@ const (
dvCPUSockets = 1
dvCPUType = "qemu64"
dvCPUUnits = 1024
dvCPUAffinity = ""
dvDescription = ""
dvEFIDiskDatastoreID = "local-lvm"
@ -165,6 +166,7 @@ const (
mkCPUSockets = "sockets"
mkCPUType = "type"
mkCPUUnits = "units"
mkCPUAffinity = "affinity"
mkDescription = "description"
mkEFIDisk = "efi_disk"
@ -491,6 +493,7 @@ func VM() *schema.Resource {
mkCPUSockets: dvCPUSockets,
mkCPUType: dvCPUType,
mkCPUUnits: dvCPUUnits,
mkCPUAffinity: dvCPUAffinity,
},
}, nil
},
@ -564,6 +567,13 @@ func VM() *schema.Resource {
validation.IntBetween(2, 262144),
),
},
mkCPUAffinity: {
Type: schema.TypeString,
Description: "The CPU affinity",
Optional: true,
Default: dvCPUAffinity,
ValidateDiagFunc: CPUAffinityValidator(),
},
},
},
MaxItems: 1,
@ -1776,6 +1786,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
cpuSockets := cpuBlock[mkCPUSockets].(int)
cpuType := cpuBlock[mkCPUType].(string)
cpuUnits := cpuBlock[mkCPUUnits].(int)
cpuAffinity := cpuBlock[mkCPUAffinity].(string)
cpuFlagsConverted := make([]string, len(cpuFlags))
@ -1798,6 +1809,10 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
updateBody.CPUSockets = &cpuSockets
updateBody.CPUUnits = &cpuUnits
if cpuAffinity != "" {
updateBody.CPUAffinity = &cpuAffinity
}
if cpuHotplugged > 0 {
updateBody.VirtualCPUCount = &cpuHotplugged
}
@ -2183,6 +2198,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
cpuNUMA := types.CustomBool(cpuBlock[mkCPUNUMA].(bool))
cpuType := cpuBlock[mkCPUType].(string)
cpuUnits := cpuBlock[mkCPUUnits].(int)
cpuAffinity := cpuBlock[mkCPUAffinity].(string)
description := d.Get(mkDescription).(string)
@ -2465,6 +2481,10 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
createBody.CPULimit = &cpuLimit
}
if cpuAffinity != "" {
createBody.CPUAffinity = &cpuAffinity
}
if description != "" {
createBody.Description = &description
}
@ -3379,6 +3399,12 @@ func vmReadCustom(
cpu[mkCPUUnits] = 1024
}
if vmConfig.CPUAffinity != nil {
cpu[mkCPUAffinity] = *vmConfig.CPUAffinity
} else {
cpu[mkCPUAffinity] = ""
}
currentCPU := d.Get(mkCPU).([]interface{})
if len(clone) > 0 {
@ -4643,6 +4669,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
cpuSockets := cpuBlock[mkCPUSockets].(int)
cpuType := cpuBlock[mkCPUType].(string)
cpuUnits := cpuBlock[mkCPUUnits].(int)
cpuAffinity := cpuBlock[mkCPUAffinity].(string)
// Only the root account is allowed to change the CPU architecture, which makes this check necessary.
if api.API().IsRootTicket() ||
@ -4653,8 +4680,15 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
updateBody.CPUCores = &cpuCores
updateBody.CPUSockets = &cpuSockets
updateBody.CPUUnits = &cpuUnits
updateBody.CPUAffinity = &cpuAffinity
updateBody.NUMAEnabled = &cpuNUMA
if cpuAffinity != "" {
updateBody.CPUAffinity = &cpuAffinity
} else {
del = append(del, "affinity")
}
if cpuHotplugged > 0 {
updateBody.VirtualCPUCount = &cpuHotplugged
} else {