From e2f539282876b5e80fa92ea752c2f569c252581a Mon Sep 17 00:00:00 2001 From: Sivaanand Murugesan Date: Wed, 5 Apr 2023 21:15:16 +0530 Subject: [PATCH] PLT-414: Added limits & CPU support with cores, sockets and thread (#247) * PLT-414: Added limits & CPU suport with cores, sockets and thread * PLT-414: Renew sdk dependency after merge and fix unit test. --------- Co-authored-by: nikolay-spectro --- docs/resources/virtual_machine.md | 16 +++- .../resource-vm-all-type-config.tf | 29 +++++--- go.mod | 2 +- go.sum | 2 + .../virtualmachineinstance/domain_spec.go | 73 ++++++++++++++++++- 5 files changed, 109 insertions(+), 13 deletions(-) diff --git a/docs/resources/virtual_machine.md b/docs/resources/virtual_machine.md index c11acfeb..45839924 100644 --- a/docs/resources/virtual_machine.md +++ b/docs/resources/virtual_machine.md @@ -539,6 +539,10 @@ Required: - `devices` (Block List, Min: 1, Max: 1) Devices allows adding disks, network interfaces, ... (see [below for nested schema](#nestedblock--spec--template--spec--domain--devices)) - `resources` (Block List, Min: 1, Max: 1) Resources describes the Compute Resources required by this vmi. (see [below for nested schema](#nestedblock--spec--template--spec--domain--resources)) +Optional: + +- `cpu` (Block List, Max: 1) CPU allows to specifying the CPU topology. Valid resource keys are "cores" , "sockets" and "threads" (see [below for nested schema](#nestedblock--spec--template--spec--domain--cpu)) + ### Nested Schema for `spec.template.spec.domain.devices` @@ -603,11 +607,21 @@ Optional: Optional: -- `limits` (Map of String) Requests is a description of the initial vmi resources. +- `limits` (Map of String) Requests is the maximum amount of compute resources allowed. Valid resource keys are "memory" and "cpu" - `over_commit_guest_overhead` (Boolean) Don't ask the scheduler to take the guest-management overhead into account. Instead put the overhead only into the container's memory limit. This can lead to crashes if all memory is in use on a node. Defaults to false. - `requests` (Map of String) Requests is a description of the initial vmi resources. + +### Nested Schema for `spec.template.spec.domain.cpu` + +Optional: + +- `cores` (Number) Cores is the number of cores inside the vmi. Must be a value greater or equal 1 +- `sockets` (Number) Sockets is the number of sockets inside the vmi. Must be a value greater or equal 1. +- `threads` (Number) Threads is the number of threads inside the vmi. Must be a value greater or equal 1. + + ### Nested Schema for `spec.template.spec.liveness_probe` diff --git a/examples/resources/spectrocloud_virtual_machine2/resource-vm-all-type-config.tf b/examples/resources/spectrocloud_virtual_machine2/resource-vm-all-type-config.tf index 9ad4f6e0..dcf3f6dc 100644 --- a/examples/resources/spectrocloud_virtual_machine2/resource-vm-all-type-config.tf +++ b/examples/resources/spectrocloud_virtual_machine2/resource-vm-all-type-config.tf @@ -1,4 +1,4 @@ -data spectrocloud_cluster "vm_enabled_base_cluster" { +data "spectrocloud_cluster" "vm_enabled_base_cluster" { name = "shruthi-aws-ugadi" } locals { @@ -8,7 +8,7 @@ locals { // Creating VM with Data Volume Templates resource "spectrocloud_virtual_machine" "tf-test-vm-data-volume-template" { - cluster_uid = data.spectrocloud_cluster.vm_enabled_base_cluster.id + cluster_uid = data.spectrocloud_cluster.vm_enabled_base_cluster.id run_on_launch = false # vm_action = "start" //["start", "stop", "pause", "resume", "migrate", "restart"] metadata { @@ -59,11 +59,20 @@ resource "spectrocloud_virtual_machine" "tf-test-vm-data-volume-template" { } } domain { + cpu { + cores = 2 + sockets = 2 + threads = 50 + } resources { requests = { memory = "8G" cpu = 2 } + limits = { + cpu = 4 + memory = "20G" + } } devices { disk { @@ -196,7 +205,7 @@ resource "spectrocloud_virtual_machine" "tf-test-vm-default" { // Creating VM by cloning existing VM resource "spectrocloud_virtual_machine" "tf-test-vm-clone-default" { - cluster_uid = data.spectrocloud_cluster.vm_enabled_base_cluster.id + cluster_uid = data.spectrocloud_cluster.vm_enabled_base_cluster.id base_vm_name = spectrocloud_virtual_machine.tf-test-vm-default.metadata.0.name metadata { name = "tf-test-vm-clone-default" @@ -332,12 +341,12 @@ resource "spectrocloud_virtual_machine" "tf-test-vm-multinetwork" { interface { name = "main" interface_binding_method = "InterfaceMasquerade" - model = "virtio" + model = "virtio" } interface { name = "additional" interface_binding_method = "InterfaceBridge" - model = "e1000e" + model = "e1000e" } } } @@ -348,7 +357,7 @@ resource "spectrocloud_virtual_machine" "tf-test-vm-multinetwork" { } } network { - name = "additional" + name = "additional" network_source { multus { network_name = "macvlan-conf" @@ -466,7 +475,7 @@ resource "spectrocloud_virtual_machine" "tf-test-vm-all-option-template-spec" { name = "cloudintdisk" disk_device { disk { - bus = "virtio" + bus = "virtio" read_only = false # pci_address = "0000:03:07.0" } @@ -476,12 +485,12 @@ resource "spectrocloud_virtual_machine" "tf-test-vm-all-option-template-spec" { interface { name = "main" interface_binding_method = "InterfaceMasquerade" //["InterfaceBridge", "InterfaceSlirp", "InterfaceMasquerade","InterfaceSRIOV",] - model = "virtio" + model = "virtio" } interface { name = "additional" interface_binding_method = "InterfaceBridge" - model = "e1000e" // ["", "e1000", "e1000e", "ne2k_pci", "pcnet", "rtl8139", "virtio"] + model = "e1000e" // ["", "e1000", "e1000e", "ne2k_pci", "pcnet", "rtl8139", "virtio"] } } } @@ -492,7 +501,7 @@ resource "spectrocloud_virtual_machine" "tf-test-vm-all-option-template-spec" { } } network { - name = "additional" + name = "additional" network_source { multus { network_name = "macvlan-conf" diff --git a/go.mod b/go.mod index 6dbf8b63..6bda265c 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1 github.com/robfig/cron v1.2.0 github.com/spectrocloud/hapi v1.14.1-0.20230315115513-301628ae2f5e - github.com/spectrocloud/palette-sdk-go v0.0.0-20230404004301-0e4bcff8f3e7 + github.com/spectrocloud/palette-sdk-go v0.0.0-20230405142217-be3e411364a1 github.com/stretchr/testify v1.8.0 gotest.tools v2.2.0+incompatible k8s.io/api v0.23.5 diff --git a/go.sum b/go.sum index 02bd5013..dafbf4f7 100644 --- a/go.sum +++ b/go.sum @@ -719,6 +719,8 @@ github.com/spectrocloud/hapi v1.14.1-0.20230315115513-301628ae2f5e h1:xPfQZPpsZI github.com/spectrocloud/hapi v1.14.1-0.20230315115513-301628ae2f5e/go.mod h1:2eQvv8EJZnMfIFC67ONLsOaEFHsoUcRCYoU/+gV1h2M= github.com/spectrocloud/palette-sdk-go v0.0.0-20230404004301-0e4bcff8f3e7 h1:GRGOUXoOoODWUMLSDVFKoHQu4HYGmbQBepRgT+UwNdQ= github.com/spectrocloud/palette-sdk-go v0.0.0-20230404004301-0e4bcff8f3e7/go.mod h1:8zLdz1aTZpfDOxxZGqT6ng+jZiKtV3iqiy1b6cD97Pg= +github.com/spectrocloud/palette-sdk-go v0.0.0-20230405142217-be3e411364a1 h1:qglK37ktellPYq3hRMQwxZwfmcYaavZdnugffHW+H/I= +github.com/spectrocloud/palette-sdk-go v0.0.0-20230405142217-be3e411364a1/go.mod h1:8zLdz1aTZpfDOxxZGqT6ng+jZiKtV3iqiy1b6cD97Pg= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= diff --git a/spectrocloud/kubevirt/schema/virtualmachineinstance/domain_spec.go b/spectrocloud/kubevirt/schema/virtualmachineinstance/domain_spec.go index 9aa4189a..4457504d 100644 --- a/spectrocloud/kubevirt/schema/virtualmachineinstance/domain_spec.go +++ b/spectrocloud/kubevirt/schema/virtualmachineinstance/domain_spec.go @@ -24,7 +24,7 @@ func domainSpecFields() map[string]*schema.Schema { }, "limits": { Type: schema.TypeMap, - Description: "Requests is a description of the initial vmi resources.", + Description: "Requests is the maximum amount of compute resources allowed. Valid resource keys are \"memory\" and \"cpu\"", Optional: true, }, "over_commit_guest_overhead": { @@ -35,6 +35,31 @@ func domainSpecFields() map[string]*schema.Schema { }, }, }, + "cpu": { + Type: schema.TypeList, + Description: "CPU allows to specifying the CPU topology. Valid resource keys are \"cores\" , \"sockets\" and \"threads\"", + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cores": { + Type: schema.TypeInt, + Description: "Cores is the number of cores inside the vmi. Must be a value greater or equal 1", + Optional: true, + }, + "sockets": { + Type: schema.TypeInt, + Description: "Sockets is the number of sockets inside the vmi. Must be a value greater or equal 1.", + Optional: true, + }, + "threads": { + Type: schema.TypeInt, + Description: "Threads is the number of threads inside the vmi. Must be a value greater or equal 1.", + Optional: true, + }, + }, + }, + }, "devices": { Type: schema.TypeList, Description: "Devices allows adding disks, network interfaces, ...", @@ -178,6 +203,13 @@ func expandDomainSpec(domainSpec []interface{}) (kubevirtapiv1.DomainSpec, error } result.Devices = devices } + if v, ok := in["cpu"].([]interface{}); ok { + cpu, err := expandCPU(v) + if err != nil { + return result, err + } + result.CPU = &cpu + } return result, nil } @@ -230,6 +262,27 @@ func expandDevices(devices []interface{}) (kubevirtapiv1.Devices, error) { return result, nil } +func expandCPU(cpu []interface{}) (kubevirtapiv1.CPU, error) { + result := kubevirtapiv1.CPU{} + + if len(cpu) == 0 || cpu[0] == nil { + return result, nil + } + + in := cpu[0].(map[string]interface{}) + + if v, ok := in["cores"].(int); ok { + result.Cores = uint32(v) + } + if v, ok := in["sockets"].(int); ok { + result.Sockets = uint32(v) + } + if v, ok := in["threads"].(int); ok { + result.Threads = uint32(v) + } + + return result, nil +} func expandDisks(disks []interface{}) []kubevirtapiv1.Disk { result := make([]kubevirtapiv1.Disk, len(disks)) @@ -338,11 +391,29 @@ func flattenDomainSpec(in kubevirtapiv1.DomainSpec) []interface{} { att := make(map[string]interface{}) att["resources"] = flattenResources(in.Resources) + if in.CPU != nil { + att["cpu"] = flattenCPU(in.CPU) + } att["devices"] = flattenDevices(in.Devices) return []interface{}{att} } +func flattenCPU(in *kubevirtapiv1.CPU) []interface{} { + att := make(map[string]interface{}) + + if in.Cores != 0 { + att["cores"] = in.Cores + } + if in.Sockets != 0 { + att["sockets"] = in.Sockets + } + if in.Threads != 0 { + att["threads"] = in.Threads + } + return []interface{}{att} +} + func flattenResources(in kubevirtapiv1.ResourceRequirements) []interface{} { att := make(map[string]interface{})