From c2d53dff1f992c51cef831fa29bbae1a68826432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernardo=20De=20Marco=20Gon=C3=A7alves?= Date: Thu, 5 Jun 2025 09:59:50 -0300 Subject: [PATCH 1/2] CPU features for system VMs --- agent/conf/agent.properties | 10 ++++-- .../agent/properties/AgentProperties.java | 15 +++++++-- .../resource/LibvirtComputingResource.java | 31 +++++++++++++------ .../LibvirtComputingResourceTest.java | 16 ++++++++++ 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties index e70acee229df..d78cad8b183a 100644 --- a/agent/conf/agent.properties +++ b/agent/conf/agent.properties @@ -213,10 +213,16 @@ hypervisor.type=kvm # If null (default), defaults to the VM's OS architecture #guest.cpu.arch= -# This param will require CPU features on the CPU section. -# The features listed in this property must be separated by a blank space (e.g.: vmx vme) +# Specifies required CPU features for end-user VMs (non-system VMs). +# These features must be present on the host CPU for VM deployment. +# Multiple features should be separated by whitespace (e.g.: vmx vme). #guest.cpu.features= +# Specifies required CPU features for system VMs. +# These features must be present on the host CPU for VM deployment. +# Multiple features should be separated by whitespace (e.g.: vmx vme). +#systemvm.guest.cpu.features= + # Disables memory ballooning on VM guests for overcommit. # By default overcommit feature enables balloon and sets currentMemory to a minimum value. #vm.memballoon.disable=false diff --git a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java index 695376216732..4dddffc45fe9 100644 --- a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java +++ b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java @@ -390,14 +390,25 @@ public class AgentProperties{ public static final Property GUEST_CPU_ARCH = new Property<>("guest.cpu.arch", null, String.class); /** - * This param will require CPU features on the CPU section.
- * The features listed in this property must be separated by a blank space (see example below).
+ * Specifies required CPU features for end-user VMs (non-system VMs).
+ * These features must be present on the host CPU for VM deployment.
+ * Multiple features should be separated by whitespace (see example below).
* Possible values: vmx vme
* Data type: String.
* Default value: null */ public static final Property GUEST_CPU_FEATURES = new Property<>("guest.cpu.features", null, String.class); + /** + * Specifies required CPU features for system VMs.
+ * These features must be present on the host CPU for VM deployment.
+ * Multiple features should be separated by whitespace (see example below).
+ * Possible values: vmx vme
+ * Data type: String.
+ * Default value: null + */ + public static final Property SYSTEMVM_GUEST_CPU_FEATURES = new Property<>("systemvm.guest.cpu.features", null, String.class); + /** * Disables memory ballooning on VM guests for overcommit.
* By default overcommit feature enables balloon and sets currentMemory to a minimum value.
diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index a632fd5adfd2..2bedef07fb5b 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -843,6 +843,8 @@ protected String getDefaultScriptsDir() { protected List cpuFeatures; + protected List systemVmCpuFeatures; + protected enum BridgeType { NATIVE, OPENVSWITCH, TUNGSTEN } @@ -1283,15 +1285,8 @@ public boolean configure(final String name, final Map params) th params.put("guest.cpu.model", guestCpuModel); } - final String cpuFeatures = AgentPropertiesFileHandler.getPropertyValue(AgentProperties.GUEST_CPU_FEATURES); - if (cpuFeatures != null) { - this.cpuFeatures = new ArrayList(); - for (final String feature: cpuFeatures.split(" ")) { - if (!feature.isEmpty()) { - this.cpuFeatures.add(feature); - } - } - } + this.cpuFeatures = parseCpuFeatures(AgentPropertiesFileHandler.getPropertyValue(AgentProperties.GUEST_CPU_FEATURES)); + this.systemVmCpuFeatures = parseCpuFeatures(AgentPropertiesFileHandler.getPropertyValue(AgentProperties.SYSTEMVM_GUEST_CPU_FEATURES)); final String[] info = NetUtils.getNetworkParams(privateNic); @@ -1397,6 +1392,22 @@ public boolean configure(final String name, final Map params) th return true; } + /** + * Parses a string containing whitespace-separated CPU feature names and converts it into a list. + * + * @param features A string containing whitespace-separated CPU feature names to be parsed. + * @return A list of CPU feature strings. Returns an empty list if {@code features} is null. + */ + protected List parseCpuFeatures(String features) { + if (features == null) { + return new ArrayList<>(); + } + + return Arrays.stream(features.split(" ")) + .filter(feature -> !feature.isEmpty()) + .collect(Collectors.toList()); + } + /** * Gets the ID list of the VMs to set memory balloon stats period. * @param conn the Libvirt connection. @@ -2986,6 +2997,8 @@ private CpuModeDef createCpuModeDef(VirtualMachineTO vmTO, int vcpus) { cmd.setModel(cpuModel); if (VirtualMachine.Type.User.equals(vmTO.getType())) { cmd.setFeatures(cpuFeatures); + } else if (vmTO.getType().isUsedBySystem()) { + cmd.setFeatures(systemVmCpuFeatures); } int vCpusInDef = vmTO.getVcpuMaxLimit() == null ? vcpus : vmTO.getVcpuMaxLimit(); setCpuTopology(cmd, vCpusInDef, vmTO.getDetails()); diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 35c5a3bea930..0831c6d1259c 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -6620,4 +6620,20 @@ public void recreateCheckpointsOnVmTestVolumesHaveCheckpoints() { Mockito.verify(libvirtComputingResourceSpy, Mockito.times(1)).recreateCheckpointsOfDisk(Mockito.any(), Mockito.any(), Mockito.any()); Assert.assertTrue(result); } + + @Test + public void parseCpuFeaturesTestReturnEmptyListWhenFeaturesIsNull() { + List cpuFeatures = libvirtComputingResourceSpy.parseCpuFeatures(null); + Assert.assertEquals(0, cpuFeatures.size()); + } + + @Test + public void parseCpuFeaturesTestReturnListOfCpuFeaturesAndIgnoreMultipleWhitespacesAlongsideEachOther() { + List cpuFeatures = libvirtComputingResourceSpy.parseCpuFeatures(" -mca mce -mmx hle "); + Assert.assertEquals(4, cpuFeatures.size()); + Assert.assertEquals("-mca", cpuFeatures.get(0)); + Assert.assertEquals("mce", cpuFeatures.get(1)); + Assert.assertEquals("-mmx", cpuFeatures.get(2)); + Assert.assertEquals("hle", cpuFeatures.get(3)); + } } From 84148e63555233c0721a831b766ce258cc7142b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernardo=20De=20Marco=20Gon=C3=A7alves?= Date: Thu, 12 Jun 2025 15:10:41 -0300 Subject: [PATCH 2/2] apply guest.cpu.features for system VMs --- agent/conf/agent.properties | 7 +------ .../com/cloud/agent/properties/AgentProperties.java | 12 +----------- .../kvm/resource/LibvirtComputingResource.java | 9 +-------- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties index d78cad8b183a..988e812d9c6d 100644 --- a/agent/conf/agent.properties +++ b/agent/conf/agent.properties @@ -213,16 +213,11 @@ hypervisor.type=kvm # If null (default), defaults to the VM's OS architecture #guest.cpu.arch= -# Specifies required CPU features for end-user VMs (non-system VMs). +# Specifies required CPU features for end-user and system VMs. # These features must be present on the host CPU for VM deployment. # Multiple features should be separated by whitespace (e.g.: vmx vme). #guest.cpu.features= -# Specifies required CPU features for system VMs. -# These features must be present on the host CPU for VM deployment. -# Multiple features should be separated by whitespace (e.g.: vmx vme). -#systemvm.guest.cpu.features= - # Disables memory ballooning on VM guests for overcommit. # By default overcommit feature enables balloon and sets currentMemory to a minimum value. #vm.memballoon.disable=false diff --git a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java index 4dddffc45fe9..7392b54828e5 100644 --- a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java +++ b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java @@ -390,7 +390,7 @@ public class AgentProperties{ public static final Property GUEST_CPU_ARCH = new Property<>("guest.cpu.arch", null, String.class); /** - * Specifies required CPU features for end-user VMs (non-system VMs).
+ * Specifies required CPU features for end-user and system VMs.
* These features must be present on the host CPU for VM deployment.
* Multiple features should be separated by whitespace (see example below).
* Possible values: vmx vme
@@ -399,16 +399,6 @@ public class AgentProperties{ */ public static final Property GUEST_CPU_FEATURES = new Property<>("guest.cpu.features", null, String.class); - /** - * Specifies required CPU features for system VMs.
- * These features must be present on the host CPU for VM deployment.
- * Multiple features should be separated by whitespace (see example below).
- * Possible values: vmx vme
- * Data type: String.
- * Default value: null - */ - public static final Property SYSTEMVM_GUEST_CPU_FEATURES = new Property<>("systemvm.guest.cpu.features", null, String.class); - /** * Disables memory ballooning on VM guests for overcommit.
* By default overcommit feature enables balloon and sets currentMemory to a minimum value.
diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 2bedef07fb5b..90b1738b4e5c 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -843,8 +843,6 @@ protected String getDefaultScriptsDir() { protected List cpuFeatures; - protected List systemVmCpuFeatures; - protected enum BridgeType { NATIVE, OPENVSWITCH, TUNGSTEN } @@ -1286,7 +1284,6 @@ public boolean configure(final String name, final Map params) th } this.cpuFeatures = parseCpuFeatures(AgentPropertiesFileHandler.getPropertyValue(AgentProperties.GUEST_CPU_FEATURES)); - this.systemVmCpuFeatures = parseCpuFeatures(AgentPropertiesFileHandler.getPropertyValue(AgentProperties.SYSTEMVM_GUEST_CPU_FEATURES)); final String[] info = NetUtils.getNetworkParams(privateNic); @@ -2995,11 +2992,7 @@ private CpuModeDef createCpuModeDef(VirtualMachineTO vmTO, int vcpus) { String cpuModel = MapUtils.isNotEmpty(details) && details.get(VmDetailConstants.GUEST_CPU_MODEL) != null ? details.get(VmDetailConstants.GUEST_CPU_MODEL) : guestCpuModel; cmd.setMode(cpuMode); cmd.setModel(cpuModel); - if (VirtualMachine.Type.User.equals(vmTO.getType())) { - cmd.setFeatures(cpuFeatures); - } else if (vmTO.getType().isUsedBySystem()) { - cmd.setFeatures(systemVmCpuFeatures); - } + cmd.setFeatures(cpuFeatures); int vCpusInDef = vmTO.getVcpuMaxLimit() == null ? vcpus : vmTO.getVcpuMaxLimit(); setCpuTopology(cmd, vCpusInDef, vmTO.getDetails()); return cmd;