mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-07-09 15:25:01 +00:00
* 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:
parent
9fee8c1e2e
commit
83a5971cf6
@ -231,11 +231,15 @@ output "ubuntu_vm_public_key" {
|
|||||||
- `custom-<model>` - Custom CPU model. All `custom-<model>` values
|
- `custom-<model>` - Custom CPU model. All `custom-<model>` values
|
||||||
should be defined in `/etc/pve/virtual-guest/cpu-models.conf` file.
|
should be defined in `/etc/pve/virtual-guest/cpu-models.conf` file.
|
||||||
- `units` - (Optional) The CPU units (defaults to `1024`).
|
- `units` - (Optional) The CPU units (defaults to `1024`).
|
||||||
|
- `affinity` - (Optional) The CPU cores that are used to run the VM’s 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 VM’s vCPUs are run on the first four
|
||||||
|
CPU cores. Setting `affinity` is only allowed for `root@pam` authenticated user.
|
||||||
- `description` - (Optional) The description.
|
- `description` - (Optional) The description.
|
||||||
- `disk` - (Optional) A disk (multiple blocks supported).
|
- `disk` - (Optional) A disk (multiple blocks supported).
|
||||||
- `aio` - (Optional) The disk AIO mode (defaults to `io_uring`).
|
- `aio` - (Optional) The disk AIO mode (defaults to `io_uring`).
|
||||||
- `io_uring` - Use 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.
|
with the disk `cache` must be set to `none`. Raw block storage types include iSCSI, CEPH/RBD, and NVMe.
|
||||||
- `threads` - Use thread-based AIO.
|
- `threads` - Use thread-based AIO.
|
||||||
- `backup` - (Optional) Whether the drive should be included when making backups (defaults to `true`).
|
- `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).
|
- `queues` - (Optional) The number of queues for VirtIO (1..64).
|
||||||
- `rate_limit` - (Optional) The rate limit in megabytes per second.
|
- `rate_limit` - (Optional) The rate limit in megabytes per second.
|
||||||
- `vlan_id` - (Optional) The VLAN identifier.
|
- `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
|
("10;20;30"). Note that the VLAN-aware feature need to be enabled on the PVE
|
||||||
Linux Bridge to use trunks.
|
Linux Bridge to use trunks.
|
||||||
- `node_name` - (Required) The name of the node to assign the virtual machine
|
- `node_name` - (Required) The name of the node to assign the virtual machine
|
||||||
|
@ -14,6 +14,7 @@ resource "proxmox_virtual_environment_vm" "example_template" {
|
|||||||
cores = 2
|
cores = 2
|
||||||
numa = true
|
numa = true
|
||||||
limit = 64
|
limit = 64
|
||||||
|
# affinity = "0-1"
|
||||||
}
|
}
|
||||||
|
|
||||||
smbios {
|
smbios {
|
||||||
@ -75,7 +76,7 @@ resource "proxmox_virtual_environment_vm" "example_template" {
|
|||||||
address = "dhcp"
|
address = "dhcp"
|
||||||
}
|
}
|
||||||
# ipv6 {
|
# ipv6 {
|
||||||
# address = "dhcp"
|
# address = "dhcp"
|
||||||
#}
|
#}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,6 +236,7 @@ type CreateRequestBody struct {
|
|||||||
CPULimit *int `json:"cpulimit,omitempty" url:"cpulimit,omitempty"`
|
CPULimit *int `json:"cpulimit,omitempty" url:"cpulimit,omitempty"`
|
||||||
CPUSockets *int `json:"sockets,omitempty" url:"sockets,omitempty"`
|
CPUSockets *int `json:"sockets,omitempty" url:"sockets,omitempty"`
|
||||||
CPUUnits *int `json:"cpuunits,omitempty" url:"cpuunits,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"`
|
DedicatedMemory *int `json:"memory,omitempty" url:"memory,omitempty"`
|
||||||
Delete []string `json:"delete,omitempty" url:"delete,omitempty,comma"`
|
Delete []string `json:"delete,omitempty" url:"delete,omitempty,comma"`
|
||||||
DeletionProtection *types.CustomBool `json:"protection,omitempty" url:"protection,omitempty,int"`
|
DeletionProtection *types.CustomBool `json:"protection,omitempty" url:"protection,omitempty,int"`
|
||||||
@ -364,6 +365,7 @@ type GetResponseData struct {
|
|||||||
CPULimit *types.CustomInt `json:"cpulimit,omitempty"`
|
CPULimit *types.CustomInt `json:"cpulimit,omitempty"`
|
||||||
CPUSockets *int `json:"sockets,omitempty"`
|
CPUSockets *int `json:"sockets,omitempty"`
|
||||||
CPUUnits *int `json:"cpuunits,omitempty"`
|
CPUUnits *int `json:"cpuunits,omitempty"`
|
||||||
|
CPUAffinity *string `json:"affinity,omitempty"`
|
||||||
DedicatedMemory *types.CustomInt64 `json:"memory,omitempty"`
|
DedicatedMemory *types.CustomInt64 `json:"memory,omitempty"`
|
||||||
DeletionProtection *types.CustomBool `json:"protection,omitempty"`
|
DeletionProtection *types.CustomBool `json:"protection,omitempty"`
|
||||||
Description *string `json:"description,omitempty"`
|
Description *string `json:"description,omitempty"`
|
||||||
|
@ -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.
|
// QEMUAgentTypeValidator is a schema validation function for QEMU agent types.
|
||||||
func QEMUAgentTypeValidator() schema.SchemaValidateDiagFunc {
|
func QEMUAgentTypeValidator() schema.SchemaValidateDiagFunc {
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{"isa", "virtio"}, false))
|
return validation.ToDiagFunc(validation.StringInSlice([]string{"isa", "virtio"}, false))
|
||||||
|
@ -64,6 +64,7 @@ const (
|
|||||||
dvCPUSockets = 1
|
dvCPUSockets = 1
|
||||||
dvCPUType = "qemu64"
|
dvCPUType = "qemu64"
|
||||||
dvCPUUnits = 1024
|
dvCPUUnits = 1024
|
||||||
|
dvCPUAffinity = ""
|
||||||
dvDescription = ""
|
dvDescription = ""
|
||||||
|
|
||||||
dvEFIDiskDatastoreID = "local-lvm"
|
dvEFIDiskDatastoreID = "local-lvm"
|
||||||
@ -165,6 +166,7 @@ const (
|
|||||||
mkCPUSockets = "sockets"
|
mkCPUSockets = "sockets"
|
||||||
mkCPUType = "type"
|
mkCPUType = "type"
|
||||||
mkCPUUnits = "units"
|
mkCPUUnits = "units"
|
||||||
|
mkCPUAffinity = "affinity"
|
||||||
mkDescription = "description"
|
mkDescription = "description"
|
||||||
|
|
||||||
mkEFIDisk = "efi_disk"
|
mkEFIDisk = "efi_disk"
|
||||||
@ -491,6 +493,7 @@ func VM() *schema.Resource {
|
|||||||
mkCPUSockets: dvCPUSockets,
|
mkCPUSockets: dvCPUSockets,
|
||||||
mkCPUType: dvCPUType,
|
mkCPUType: dvCPUType,
|
||||||
mkCPUUnits: dvCPUUnits,
|
mkCPUUnits: dvCPUUnits,
|
||||||
|
mkCPUAffinity: dvCPUAffinity,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
@ -564,6 +567,13 @@ func VM() *schema.Resource {
|
|||||||
validation.IntBetween(2, 262144),
|
validation.IntBetween(2, 262144),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
mkCPUAffinity: {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Description: "The CPU affinity",
|
||||||
|
Optional: true,
|
||||||
|
Default: dvCPUAffinity,
|
||||||
|
ValidateDiagFunc: CPUAffinityValidator(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MaxItems: 1,
|
MaxItems: 1,
|
||||||
@ -1776,6 +1786,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
|||||||
cpuSockets := cpuBlock[mkCPUSockets].(int)
|
cpuSockets := cpuBlock[mkCPUSockets].(int)
|
||||||
cpuType := cpuBlock[mkCPUType].(string)
|
cpuType := cpuBlock[mkCPUType].(string)
|
||||||
cpuUnits := cpuBlock[mkCPUUnits].(int)
|
cpuUnits := cpuBlock[mkCPUUnits].(int)
|
||||||
|
cpuAffinity := cpuBlock[mkCPUAffinity].(string)
|
||||||
|
|
||||||
cpuFlagsConverted := make([]string, len(cpuFlags))
|
cpuFlagsConverted := make([]string, len(cpuFlags))
|
||||||
|
|
||||||
@ -1798,6 +1809,10 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
|||||||
updateBody.CPUSockets = &cpuSockets
|
updateBody.CPUSockets = &cpuSockets
|
||||||
updateBody.CPUUnits = &cpuUnits
|
updateBody.CPUUnits = &cpuUnits
|
||||||
|
|
||||||
|
if cpuAffinity != "" {
|
||||||
|
updateBody.CPUAffinity = &cpuAffinity
|
||||||
|
}
|
||||||
|
|
||||||
if cpuHotplugged > 0 {
|
if cpuHotplugged > 0 {
|
||||||
updateBody.VirtualCPUCount = &cpuHotplugged
|
updateBody.VirtualCPUCount = &cpuHotplugged
|
||||||
}
|
}
|
||||||
@ -2183,6 +2198,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
cpuNUMA := types.CustomBool(cpuBlock[mkCPUNUMA].(bool))
|
cpuNUMA := types.CustomBool(cpuBlock[mkCPUNUMA].(bool))
|
||||||
cpuType := cpuBlock[mkCPUType].(string)
|
cpuType := cpuBlock[mkCPUType].(string)
|
||||||
cpuUnits := cpuBlock[mkCPUUnits].(int)
|
cpuUnits := cpuBlock[mkCPUUnits].(int)
|
||||||
|
cpuAffinity := cpuBlock[mkCPUAffinity].(string)
|
||||||
|
|
||||||
description := d.Get(mkDescription).(string)
|
description := d.Get(mkDescription).(string)
|
||||||
|
|
||||||
@ -2465,6 +2481,10 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
createBody.CPULimit = &cpuLimit
|
createBody.CPULimit = &cpuLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cpuAffinity != "" {
|
||||||
|
createBody.CPUAffinity = &cpuAffinity
|
||||||
|
}
|
||||||
|
|
||||||
if description != "" {
|
if description != "" {
|
||||||
createBody.Description = &description
|
createBody.Description = &description
|
||||||
}
|
}
|
||||||
@ -3379,6 +3399,12 @@ func vmReadCustom(
|
|||||||
cpu[mkCPUUnits] = 1024
|
cpu[mkCPUUnits] = 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if vmConfig.CPUAffinity != nil {
|
||||||
|
cpu[mkCPUAffinity] = *vmConfig.CPUAffinity
|
||||||
|
} else {
|
||||||
|
cpu[mkCPUAffinity] = ""
|
||||||
|
}
|
||||||
|
|
||||||
currentCPU := d.Get(mkCPU).([]interface{})
|
currentCPU := d.Get(mkCPU).([]interface{})
|
||||||
|
|
||||||
if len(clone) > 0 {
|
if len(clone) > 0 {
|
||||||
@ -4643,6 +4669,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
cpuSockets := cpuBlock[mkCPUSockets].(int)
|
cpuSockets := cpuBlock[mkCPUSockets].(int)
|
||||||
cpuType := cpuBlock[mkCPUType].(string)
|
cpuType := cpuBlock[mkCPUType].(string)
|
||||||
cpuUnits := cpuBlock[mkCPUUnits].(int)
|
cpuUnits := cpuBlock[mkCPUUnits].(int)
|
||||||
|
cpuAffinity := cpuBlock[mkCPUAffinity].(string)
|
||||||
|
|
||||||
// Only the root account is allowed to change the CPU architecture, which makes this check necessary.
|
// Only the root account is allowed to change the CPU architecture, which makes this check necessary.
|
||||||
if api.API().IsRootTicket() ||
|
if api.API().IsRootTicket() ||
|
||||||
@ -4653,8 +4680,15 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
updateBody.CPUCores = &cpuCores
|
updateBody.CPUCores = &cpuCores
|
||||||
updateBody.CPUSockets = &cpuSockets
|
updateBody.CPUSockets = &cpuSockets
|
||||||
updateBody.CPUUnits = &cpuUnits
|
updateBody.CPUUnits = &cpuUnits
|
||||||
|
updateBody.CPUAffinity = &cpuAffinity
|
||||||
updateBody.NUMAEnabled = &cpuNUMA
|
updateBody.NUMAEnabled = &cpuNUMA
|
||||||
|
|
||||||
|
if cpuAffinity != "" {
|
||||||
|
updateBody.CPUAffinity = &cpuAffinity
|
||||||
|
} else {
|
||||||
|
del = append(del, "affinity")
|
||||||
|
}
|
||||||
|
|
||||||
if cpuHotplugged > 0 {
|
if cpuHotplugged > 0 {
|
||||||
updateBody.VirtualCPUCount = &cpuHotplugged
|
updateBody.VirtualCPUCount = &cpuHotplugged
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user