From 781ce8d39519318b5038b7ba9879514ecb4144d6 Mon Sep 17 00:00:00 2001 From: Cooper Tseng Date: Tue, 1 Oct 2024 17:53:17 +0800 Subject: [PATCH] Add isolate_emulator_thread option to vm resource Signed-off-by: Cooper Tseng --- .../resource_virtualmachine_constructor.go | 7 +++ .../virtualmachine/schema_virtualmachine.go | 6 +++ .../tests/resource_virtualmachine_test.go | 44 ++++++++++++++--- pkg/constants/constants_virtualmachine.go | 37 ++++++++------- .../resource_virtualmachine_importer.go | 47 ++++++++++--------- 5 files changed, 96 insertions(+), 45 deletions(-) diff --git a/internal/provider/virtualmachine/resource_virtualmachine_constructor.go b/internal/provider/virtualmachine/resource_virtualmachine_constructor.go index 4f230f56..93041cdc 100644 --- a/internal/provider/virtualmachine/resource_virtualmachine_constructor.go +++ b/internal/provider/virtualmachine/resource_virtualmachine_constructor.go @@ -314,6 +314,13 @@ func (c *Constructor) Setup() util.Processors { return nil }, }, + { + Field: constants.FieldVirtualMachineIsolateEmulatorThread, + Parser: func(i interface{}) error { + vmBuilder.VirtualMachine.Spec.Template.Spec.Domain.CPU.IsolateEmulatorThread = i.(bool) + return nil + }, + }, } return append(processors, customProcessors...) } diff --git a/internal/provider/virtualmachine/schema_virtualmachine.go b/internal/provider/virtualmachine/schema_virtualmachine.go index 51aa3cda..3f56d025 100644 --- a/internal/provider/virtualmachine/schema_virtualmachine.go +++ b/internal/provider/virtualmachine/schema_virtualmachine.go @@ -133,6 +133,12 @@ please use %s instead of this deprecated field: Optional: true, Default: false, }, + constants.FieldVirtualMachineIsolateEmulatorThread: { + Type: schema.TypeBool, + Description: "To enable isolate emulator thread, ensure that at least one node has the CPU manager enabled, also VM CPU pinning must be enabled. Note that enable option will allocate an additional dedicated CPU.", + Optional: true, + Default: false, + }, } util.NamespacedSchemaWrap(s, false) return s diff --git a/internal/tests/resource_virtualmachine_test.go b/internal/tests/resource_virtualmachine_test.go index 2711938f..cc956f71 100644 --- a/internal/tests/resource_virtualmachine_test.go +++ b/internal/tests/resource_virtualmachine_test.go @@ -35,6 +35,7 @@ const ( resource %s "%s" { %s = "%s" %s = "%s" + %s = "%s" cpu = 1 %s = "%s" @@ -59,12 +60,17 @@ resource %s "%s" { ` ) -func buildVirtualMachineConfig(name, description, memory string, cpuPinning bool) string { +func buildBasicVirtualMachineConfig(name, description, memory string) string { + return buildVirtualMachineConfig(name, description, memory, false, false) +} + +func buildVirtualMachineConfig(name, description, memory string, cpuPinning bool, isolateEmulatorThread bool) string { return fmt.Sprintf(testAccVirtualMachineConfigTemplate, constants.ResourceTypeVirtualMachine, name, constants.FieldCommonName, name, constants.FieldCommonDescription, description, constants.FieldVirtualMachineMemory, memory, - constants.FieldVirtualMachineCPUPinning, strconv.FormatBool(cpuPinning)) + constants.FieldVirtualMachineCPUPinning, strconv.FormatBool(cpuPinning), + constants.FieldVirtualMachineIsolateEmulatorThread, strconv.FormatBool(isolateEmulatorThread)) } func TestAccVirtualMachine_basic(t *testing.T) { @@ -78,23 +84,25 @@ func TestAccVirtualMachine_basic(t *testing.T) { CheckDestroy: testAccCheckVirtualMachineDestroy(ctx), Steps: []resource.TestStep{ { - Config: buildVirtualMachineConfig(testAccVirtualMachineName, testAccVirtualMachineDescription, testAccVirtualMachineMemory, false), + Config: buildBasicVirtualMachineConfig(testAccVirtualMachineName, testAccVirtualMachineDescription, testAccVirtualMachineMemory), Check: resource.ComposeTestCheckFunc( testAccVirtualMachineExists(ctx, testAccVirtualMachineResourceName, vm), resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldCommonName, testAccVirtualMachineName), resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldCommonDescription, testAccVirtualMachineDescription), resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineMemory, testAccVirtualMachineMemory), resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineCPUPinning, "false"), + resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineIsolateEmulatorThread, "false"), ), }, { - Config: buildVirtualMachineConfig(testAccVirtualMachineName, testAccVirtualMachineDescription, testAccVirtualMachineMemoryUpdate, false), + Config: buildBasicVirtualMachineConfig(testAccVirtualMachineName, testAccVirtualMachineDescription, testAccVirtualMachineMemoryUpdate), Check: resource.ComposeTestCheckFunc( testAccVirtualMachineExists(ctx, testAccVirtualMachineResourceName, vm), resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldCommonName, testAccVirtualMachineName), resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldCommonDescription, testAccVirtualMachineDescription), resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineMemory, testAccVirtualMachineMemoryUpdate), resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineCPUPinning, "false"), + resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineIsolateEmulatorThread, "false"), ), }, }, @@ -133,19 +141,43 @@ func TestAccVirtualMachine_cpu_pinning(t *testing.T) { }, Steps: []resource.TestStep{ { - Config: buildVirtualMachineConfig(testAccVirtualMachineName, testAccVirtualMachineDescription, testAccVirtualMachineMemory, true), + Config: buildVirtualMachineConfig(testAccVirtualMachineName, testAccVirtualMachineDescription, testAccVirtualMachineMemory, true, false), + Check: resource.ComposeTestCheckFunc( + testAccVirtualMachineExists(ctx, testAccVirtualMachineResourceName, vm), + func(s *terraform.State) error { + if vm.Spec.Template == nil || vm.Spec.Template.Spec.Domain.CPU == nil || !vm.Spec.Template.Spec.Domain.CPU.DedicatedCPUPlacement { + return errors.New("DedicatedCPUPlacement should be true") + } + if vm.Spec.Template == nil || vm.Spec.Template.Spec.Domain.CPU == nil || vm.Spec.Template.Spec.Domain.CPU.IsolateEmulatorThread { + return errors.New("IsolateEmulatorThread should be false") + } + return nil + }, + resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldCommonName, testAccVirtualMachineName), + resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldCommonDescription, testAccVirtualMachineDescription), + resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineMemory, testAccVirtualMachineMemory), + resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineCPUPinning, "true"), + resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineIsolateEmulatorThread, "false"), + ), + }, + { + Config: buildVirtualMachineConfig(testAccVirtualMachineName, testAccVirtualMachineDescription, testAccVirtualMachineMemory, true, true), Check: resource.ComposeTestCheckFunc( testAccVirtualMachineExists(ctx, testAccVirtualMachineResourceName, vm), func(s *terraform.State) error { if vm.Spec.Template == nil || vm.Spec.Template.Spec.Domain.CPU == nil || !vm.Spec.Template.Spec.Domain.CPU.DedicatedCPUPlacement { return errors.New("DedicatedCPUPlacement should be true") } + if vm.Spec.Template == nil || vm.Spec.Template.Spec.Domain.CPU == nil || !vm.Spec.Template.Spec.Domain.CPU.IsolateEmulatorThread { + return errors.New("IsolateEmulatorThread should be true") + } return nil }, resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldCommonName, testAccVirtualMachineName), resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldCommonDescription, testAccVirtualMachineDescription), resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineMemory, testAccVirtualMachineMemory), resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineCPUPinning, "true"), + resource.TestCheckResourceAttr(testAccVirtualMachineResourceName, constants.FieldVirtualMachineIsolateEmulatorThread, "true"), ), }, }, @@ -287,7 +319,7 @@ func waitForCPUMangerLabel(ctx context.Context, c *client.Client, nodeName strin return waitUntil(func() (bool, error) { node, err := c.KubeClient.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{}) if err != nil { - return false, fmt.Errorf("failed to get node: %v", err) + return false, nil } expectedValue := strconv.FormatBool(enableCPUManager) diff --git a/pkg/constants/constants_virtualmachine.go b/pkg/constants/constants_virtualmachine.go index f31ea7d8..9bad6bd1 100644 --- a/pkg/constants/constants_virtualmachine.go +++ b/pkg/constants/constants_virtualmachine.go @@ -3,24 +3,25 @@ package constants const ( ResourceTypeVirtualMachine = "harvester_virtualmachine" - FieldVirtualMachineMachineType = "machine_type" - FieldVirtualMachineHostname = "hostname" - FieldVirtualMachineReservedMemory = "reserved_memory" - FieldVirtualMachineRestartAfterUpdate = "restart_after_update" - FieldVirtualMachineStart = "start" - FieldVirtualMachineRunStrategy = "run_strategy" - FieldVirtualMachineCPU = "cpu" - FieldVirtualMachineMemory = "memory" - FieldVirtualMachineSSHKeys = "ssh_keys" - FieldVirtualMachineCloudInit = "cloudinit" - FieldVirtualMachineDisk = "disk" - FieldVirtualMachineNetworkInterface = "network_interface" - FieldVirtualMachineInput = "input" - FieldVirtualMachineTPM = "tpm" - FieldVirtualMachineInstanceNodeName = "node_name" - FieldVirtualMachineEFI = "efi" - FieldVirtualMachineSecureBoot = "secure_boot" - FieldVirtualMachineCPUPinning = "cpu_pinning" + FieldVirtualMachineMachineType = "machine_type" + FieldVirtualMachineHostname = "hostname" + FieldVirtualMachineReservedMemory = "reserved_memory" + FieldVirtualMachineRestartAfterUpdate = "restart_after_update" + FieldVirtualMachineStart = "start" + FieldVirtualMachineRunStrategy = "run_strategy" + FieldVirtualMachineCPU = "cpu" + FieldVirtualMachineMemory = "memory" + FieldVirtualMachineSSHKeys = "ssh_keys" + FieldVirtualMachineCloudInit = "cloudinit" + FieldVirtualMachineDisk = "disk" + FieldVirtualMachineNetworkInterface = "network_interface" + FieldVirtualMachineInput = "input" + FieldVirtualMachineTPM = "tpm" + FieldVirtualMachineInstanceNodeName = "node_name" + FieldVirtualMachineEFI = "efi" + FieldVirtualMachineSecureBoot = "secure_boot" + FieldVirtualMachineCPUPinning = "cpu_pinning" + FieldVirtualMachineIsolateEmulatorThread = "isolate_emulator_thread" StateVirtualMachineStarting = "Starting" StateVirtualMachineRunning = "Running" diff --git a/pkg/importer/resource_virtualmachine_importer.go b/pkg/importer/resource_virtualmachine_importer.go index 0f44e1e5..49b3886c 100644 --- a/pkg/importer/resource_virtualmachine_importer.go +++ b/pkg/importer/resource_virtualmachine_importer.go @@ -55,6 +55,10 @@ func (v *VMImporter) DedicatedCPUPlacement() bool { return bool(v.VirtualMachine.Spec.Template.Spec.Domain.CPU.DedicatedCPUPlacement) } +func (v *VMImporter) IsolateEmulatorThread() bool { + return bool(v.VirtualMachine.Spec.Template.Spec.Domain.CPU.IsolateEmulatorThread) +} + func (v *VMImporter) EFI() bool { firmware := v.VirtualMachine.Spec.Template.Spec.Domain.Firmware return firmware != nil && firmware.Bootloader != nil && firmware.Bootloader.EFI != nil @@ -365,27 +369,28 @@ func ResourceVirtualMachineStateGetter(vm *kubevirtv1.VirtualMachine, vmi *kubev Name: vm.Name, ResourceType: constants.ResourceTypeVirtualMachine, States: map[string]interface{}{ - constants.FieldCommonNamespace: vm.Namespace, - constants.FieldCommonName: vm.Name, - constants.FieldCommonDescription: GetDescriptions(vm.Annotations), - constants.FieldCommonTags: GetTags(vm.Labels), - constants.FieldCommonState: vmImporter.State(networkInterface, oldInstanceUID), - constants.FieldVirtualMachineCPU: vmImporter.CPU(), - constants.FieldVirtualMachineMemory: vmImporter.Memory(), - constants.FieldVirtualMachineHostname: vmImporter.HostName(), - constants.FieldVirtualMachineReservedMemory: vmImporter.ReservedMemory(), - constants.FieldVirtualMachineMachineType: vmImporter.MachineType(), - constants.FieldVirtualMachineRunStrategy: string(runStrategy), - constants.FieldVirtualMachineNetworkInterface: networkInterface, - constants.FieldVirtualMachineDisk: disk, - constants.FieldVirtualMachineInput: input, - constants.FieldVirtualMachineTPM: vmImporter.TPM(), - constants.FieldVirtualMachineCloudInit: cloudInit, - constants.FieldVirtualMachineSSHKeys: sshKeys, - constants.FieldVirtualMachineInstanceNodeName: vmImporter.NodeName(), - constants.FieldVirtualMachineEFI: vmImporter.EFI(), - constants.FieldVirtualMachineSecureBoot: vmImporter.SecureBoot(), - constants.FieldVirtualMachineCPUPinning: vmImporter.DedicatedCPUPlacement(), + constants.FieldCommonNamespace: vm.Namespace, + constants.FieldCommonName: vm.Name, + constants.FieldCommonDescription: GetDescriptions(vm.Annotations), + constants.FieldCommonTags: GetTags(vm.Labels), + constants.FieldCommonState: vmImporter.State(networkInterface, oldInstanceUID), + constants.FieldVirtualMachineCPU: vmImporter.CPU(), + constants.FieldVirtualMachineMemory: vmImporter.Memory(), + constants.FieldVirtualMachineHostname: vmImporter.HostName(), + constants.FieldVirtualMachineReservedMemory: vmImporter.ReservedMemory(), + constants.FieldVirtualMachineMachineType: vmImporter.MachineType(), + constants.FieldVirtualMachineRunStrategy: string(runStrategy), + constants.FieldVirtualMachineNetworkInterface: networkInterface, + constants.FieldVirtualMachineDisk: disk, + constants.FieldVirtualMachineInput: input, + constants.FieldVirtualMachineTPM: vmImporter.TPM(), + constants.FieldVirtualMachineCloudInit: cloudInit, + constants.FieldVirtualMachineSSHKeys: sshKeys, + constants.FieldVirtualMachineInstanceNodeName: vmImporter.NodeName(), + constants.FieldVirtualMachineEFI: vmImporter.EFI(), + constants.FieldVirtualMachineSecureBoot: vmImporter.SecureBoot(), + constants.FieldVirtualMachineCPUPinning: vmImporter.DedicatedCPUPlacement(), + constants.FieldVirtualMachineIsolateEmulatorThread: vmImporter.IsolateEmulatorThread(), }, }, nil }