From c9186a808e740640c782f49029c98d5266197404 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 11 Mar 2025 11:34:20 +0100 Subject: [PATCH 01/17] KVM: add Virtual TPM model and version --- .../java/com/cloud/vm/VmDetailConstants.java | 5 ++ .../resource/LibvirtComputingResource.java | 19 +++++ .../hypervisor/kvm/resource/LibvirtVMDef.java | 75 +++++++++++++++++++ .../kvm/resource/LibvirtVMDefTest.java | 7 ++ .../com/cloud/api/query/QueryManagerImpl.java | 3 + 5 files changed, 109 insertions(+) diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index 29803d5271b4..9fe9ff6b9096 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -101,4 +101,9 @@ public interface VmDetailConstants { String VMWARE_HOST_NAME = String.format("%s-host", VMWARE_TO_KVM_PREFIX); String VMWARE_DISK = String.format("%s-disk", VMWARE_TO_KVM_PREFIX); String VMWARE_MAC_ADDRESSES = String.format("%s-mac-addresses", VMWARE_TO_KVM_PREFIX); + + // TPM + String VIRTUAL_TPM_ENABLED = "virtual.tpm.enabled"; + String VIRTUAL_TPM_MODEL = "virtual.tpm.model"; + String VIRTUAL_TPM_VERSION = "virtual.tpm.version"; } 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 ce40dd4b6819..d28b24610fc2 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 @@ -166,6 +166,7 @@ import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SCSIDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TpmDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VideoDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef.WatchDogAction; @@ -2660,6 +2661,11 @@ protected DevicesDef createDevicesDef(VirtualMachineTO vmTO, GuestDef guest, int devices.addDevice(createGraphicDef(vmTO)); devices.addDevice(createTabletInputDef()); + TpmDef tpmDef = createTpmDef(vmTO); + if (tpmDef != null) { + devices.addDevice(tpmDef); + } + if (isGuestAarch64()) { createArm64UsbDef(devices); } @@ -2850,6 +2856,19 @@ private CpuModeDef createCpuModeDef(VirtualMachineTO vmTO, int vcpus) { return cmd; } + private TpmDef createTpmDef(VirtualMachineTO vmTO) { + Map details = vmTO.getDetails(); + if (MapUtils.isEmpty(details)) { + return null; + } + String tpmModel = details.get(VmDetailConstants.VIRTUAL_TPM_MODEL); + if (tpmModel == null) { + return null; + } + String tpmVersion = details.get(VmDetailConstants.VIRTUAL_TPM_VERSION); + return new TpmDef(tpmModel, tpmVersion); + } + private void configureGuestIfUefiEnabled(boolean isSecureBoot, String bootMode, GuestDef guest) { setGuestLoader(bootMode, SECURE, guest, GuestDef.GUEST_LOADER_SECURE); setGuestLoader(bootMode, LEGACY, guest, GuestDef.GUEST_LOADER_LEGACY); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java index c34c151aad28..0a63b8b63e1b 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java @@ -18,6 +18,7 @@ import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -2358,6 +2359,80 @@ public String toString() { } } + public static class TpmDef { + enum TpmModel { + TIS("tpm-tis"), // TPM Interface Specification (TIS) + CRB("tpm-crb"); // Command-Response Buffer (CRB) + + final String model; + + TpmModel(String model) { + this.model = model; + } + + @Override + public String toString() { + return model; + } + } + + enum TpmVersion { + V1_2("1.2"), // 1.2 + V2_0("2.0"); // 2.0. Default version. The CRB model is only supported with version 2.0. + + final String version; + + TpmVersion(String version) { + this.version = version; + } + + @Override + public String toString() { + return version; + } + } + + private TpmModel model; + private TpmVersion version = TpmVersion.V2_0; + + public TpmDef(TpmModel model, TpmVersion version) { + this.model = model; + if (version != null) { + this.version = version; + } + } + + public TpmDef(String model, String version) { + this.model = Arrays.stream(TpmModel.values()) + .filter(tpmModel -> tpmModel.toString().equals(model)) + .findFirst() + .orElse(null); + if (version != null) { + this.version = Arrays.stream(TpmVersion.values()) + .filter(tpmVersion -> tpmVersion.toString().equals(version)) + .findFirst() + .orElse(null);; + } + } + + public TpmModel getModel() { + return model; + } + + public TpmVersion getVersion() { + return version; + } + + @Override + public String toString() { + StringBuilder tpmBuidler = new StringBuilder(); + tpmBuidler.append("\n"); + tpmBuidler.append("\n"); + tpmBuidler.append("\n"); + return tpmBuidler.toString(); + } + } + public void setHvsType(String hvs) { _hvsType = hvs; } diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java index bcbf6a2238b8..d0901092eef5 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java @@ -571,4 +571,11 @@ public void testTopologyNoInfo() { cpuModeDef.setTopology(-1, -1, 4); assertEquals("", cpuModeDef.toString()); } + + @Test + public void testTpmModel() { + LibvirtVMDef.TpmDef tpmDef = new LibvirtVMDef.TpmDef("tpm-tis", "2.0"); + assertEquals(LibvirtVMDef.TpmDef.TpmModel.TIS, tpmDef.getModel()); + assertEquals(LibvirtVMDef.TpmDef.TpmVersion.V2_0, tpmDef.getVersion()); + } } diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index 26c5cd4e10f1..fa4a1841de3b 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -5062,6 +5062,8 @@ private void fillVMOrTemplateDetailOptions(final Map> optio options.put(VmDetailConstants.IOTHREADS, Arrays.asList("enabled")); options.put(VmDetailConstants.NIC_MULTIQUEUE_NUMBER, Collections.emptyList()); options.put(VmDetailConstants.NIC_PACKED_VIRTQUEUES_ENABLED, Arrays.asList("true", "false")); + options.put(VmDetailConstants.VIRTUAL_TPM_MODEL, Arrays.asList("tpm-tis", "tpm-crb")); + options.put(VmDetailConstants.VIRTUAL_TPM_VERSION, Arrays.asList("1.2", "2.0")); } if (HypervisorType.VMware.equals(hypervisorType)) { @@ -5071,6 +5073,7 @@ private void fillVMOrTemplateDetailOptions(final Map> optio options.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, Arrays.asList("true", "false")); options.put(VmDetailConstants.SVGA_VRAM_SIZE, Collections.emptyList()); options.put(VmDetailConstants.RAM_RESERVATION, Collections.emptyList()); + options.put(VmDetailConstants.VIRTUAL_TPM_ENABLED, Arrays.asList("true", "false")); } } From 5378192623149fa9b2496ee2bed2da1b2fa2bce8 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 11 Mar 2025 11:34:27 +0100 Subject: [PATCH 02/17] KVM: add admin-only VM setting GUEST.CPU.MODE and GUEST.CPU.MODEL --- api/src/main/java/com/cloud/vm/VmDetailConstants.java | 4 ++++ .../java/org/apache/cloudstack/query/QueryService.java | 4 ++++ .../hypervisor/kvm/resource/LibvirtComputingResource.java | 7 +++++-- .../main/java/com/cloud/api/query/QueryManagerImpl.java | 3 +++ server/src/main/java/com/cloud/vm/UserVmManagerImpl.java | 1 + 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index 9fe9ff6b9096..a6c9b6eba16b 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -106,4 +106,8 @@ public interface VmDetailConstants { String VIRTUAL_TPM_ENABLED = "virtual.tpm.enabled"; String VIRTUAL_TPM_MODEL = "virtual.tpm.model"; String VIRTUAL_TPM_VERSION = "virtual.tpm.version"; + + // CPU mode and model, ADMIN only + String GUEST_CPU_MODE = "guest.cpu.mode"; + String GUEST_CPU_MODEL = "guest.cpu.model"; } diff --git a/api/src/main/java/org/apache/cloudstack/query/QueryService.java b/api/src/main/java/org/apache/cloudstack/query/QueryService.java index 88081494320c..0a5721abdc1f 100644 --- a/api/src/main/java/org/apache/cloudstack/query/QueryService.java +++ b/api/src/main/java/org/apache/cloudstack/query/QueryService.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.query; +import java.util.Arrays; import java.util.List; import org.apache.cloudstack.affinity.AffinityGroupResponse; @@ -97,6 +98,7 @@ import org.apache.cloudstack.framework.config.ConfigKey; import com.cloud.exception.PermissionDeniedException; +import com.cloud.vm.VmDetailConstants; /** * Service used for list api query. @@ -104,6 +106,8 @@ */ public interface QueryService { + List RootAdminOnlyVmSettings = Arrays.asList(VmDetailConstants.GUEST_CPU_MODE, VmDetailConstants.GUEST_CPU_MODEL); + // Config keys ConfigKey AllowUserViewDestroyedVM = new ConfigKey<>("Advanced", Boolean.class, "allow.user.view.destroyed.vm", "false", "Determines whether users can view their destroyed or expunging vm ", true, ConfigKey.Scope.Account); 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 d28b24610fc2..94ae42d27a24 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 @@ -2846,8 +2846,11 @@ public int calculateCpuShares(VirtualMachineTO vmTO) { private CpuModeDef createCpuModeDef(VirtualMachineTO vmTO, int vcpus) { final CpuModeDef cmd = new CpuModeDef(); - cmd.setMode(guestCpuMode); - cmd.setModel(guestCpuModel); + Map details = vmTO.getDetails(); + String cpuMode = MapUtils.isNotEmpty(details) && details.get(VmDetailConstants.GUEST_CPU_MODE) != null ? details.get(VmDetailConstants.GUEST_CPU_MODE) : guestCpuMode; + 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); } diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index fa4a1841de3b..5cb24894d9ce 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -5012,6 +5012,7 @@ public DetailOptionsResponse listDetailOptions(final ListDetailOptionsCmd cmd) { final List userDenyListedSettings = Stream.of(QueryService.UserVMDeniedDetails.value().split(",")) .map(item -> (item).trim()) .collect(Collectors.toList()); + userDenyListedSettings.addAll(QueryService.RootAdminOnlyVmSettings); for (final String detail : userDenyListedSettings) { if (options.containsKey(detail)) { options.remove(detail); @@ -5064,6 +5065,8 @@ private void fillVMOrTemplateDetailOptions(final Map> optio options.put(VmDetailConstants.NIC_PACKED_VIRTQUEUES_ENABLED, Arrays.asList("true", "false")); options.put(VmDetailConstants.VIRTUAL_TPM_MODEL, Arrays.asList("tpm-tis", "tpm-crb")); options.put(VmDetailConstants.VIRTUAL_TPM_VERSION, Arrays.asList("1.2", "2.0")); + options.put(VmDetailConstants.GUEST_CPU_MODE, Arrays.asList("custom", "host-model", "host-passthrough")); + options.put(VmDetailConstants.GUEST_CPU_MODEL, Collections.emptyList()); } if (HypervisorType.VMware.equals(hypervisorType)) { diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 021c6ff62267..cfc88de6484f 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -2840,6 +2840,7 @@ public UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableEx final List userDenyListedSettings = Stream.of(QueryService.UserVMDeniedDetails.value().split(",")) .map(item -> (item).trim()) .collect(Collectors.toList()); + userDenyListedSettings.addAll(QueryService.RootAdminOnlyVmSettings); final List userReadOnlySettings = Stream.of(QueryService.UserVMReadOnlyDetails.value().split(",")) .map(item -> (item).trim()) .collect(Collectors.toList()); From 686b71475b99aacefcfb500815a2e2fb1bbcc9a3 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 11 Mar 2025 11:36:10 +0100 Subject: [PATCH 03/17] VMware: add vTPM --- .../vmware/resource/VmwareResource.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 08fa4b438f63..724f76ea8812 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -51,6 +51,7 @@ import com.cloud.capacity.CapacityManager; import com.cloud.hypervisor.vmware.mo.HostDatastoreBrowserMO; +import com.vmware.vim25.Description; import com.vmware.vim25.FileInfo; import com.vmware.vim25.FileQueryFlags; import com.vmware.vim25.FolderFileInfo; @@ -58,6 +59,7 @@ import com.vmware.vim25.HostDatastoreBrowserSearchSpec; import com.vmware.vim25.VirtualCdromIsoBackingInfo; import com.vmware.vim25.VirtualMachineConfigSummary; +import com.vmware.vim25.VirtualTPM; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.backup.PrepareForBackupRestorationCommand; import org.apache.cloudstack.storage.command.CopyCommand; @@ -2597,12 +2599,16 @@ protected StartAnswer execute(StartCommand cmd) { setBootOptions(vmSpec, bootMode, vmConfigSpec); + // Config vTPM + configureVirtualTPM(vmMo, vmSpec, vmConfigSpec, bootMode); + if (StringUtils.isNotEmpty(vmStoragePolicyId)) { vmConfigSpec.getVmProfile().add(vmProfileSpec); if (logger.isTraceEnabled()) { logger.trace(String.format("Configuring the VM %s with storage policy: %s", vmInternalCSName, vmStoragePolicyId)); } } + // // Configure VM // @@ -3203,6 +3209,51 @@ protected void configureSpecVideoCardNewVRamSize(VirtualMachineVideoCard videoCa vmConfigSpec.getDeviceChange().add(arrayVideoCardConfigSpecs); } + /** + * Add or Remove virtual TPM module + * + * @param vmMo virtual machine mo + * @param vmSpec virtual machine specs + * @param vmConfigSpec virtual machine config spec + * @throws Exception exception + */ + protected void configureVirtualTPM(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, VirtualMachineConfigSpec vmConfigSpec, String bootMode) throws Exception { + String bootType = vmSpec.getDetails().getOrDefault(ApiConstants.BootType.UEFI.toString(), null); + String virtualTPMEnabled = vmSpec.getDetails().getOrDefault(VmDetailConstants.VIRTUAL_TPM_ENABLED, null); + if (StringUtils.isNotBlank(bootMode) && !bootMode.equalsIgnoreCase("bios") + && "secure".equalsIgnoreCase(bootType) + && Boolean.parseBoolean(virtualTPMEnabled)) { + logger.debug("Adding Virtual TPM device"); + for (VirtualDevice device : vmMo.getAllDeviceList()) { + if (device instanceof VirtualTPM) { + return; + } + } + Description description = new Description(); + description.setSummary("Trusted Platform Module"); + description.setLabel("Trusted Platform Module"); + VirtualTPM virtualTPM = new VirtualTPM(); + virtualTPM.setDeviceInfo(description); + virtualTPM.setKey(-1); + VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec(); + deviceConfigSpec.setDevice(virtualTPM); + deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD); + vmConfigSpec.getDeviceChange().add(deviceConfigSpec); + } else { + logger.debug(String.format("Virtual TPM device is not enabled. It is only enabled when boot type is SECURE (actually %s) and vTPM is enabled (actually %s)", bootType, virtualTPMEnabled)); + for (VirtualDevice device : vmMo.getAllDeviceList()) { + if (device instanceof VirtualTPM) { + VirtualTPM virtualTPM = (VirtualTPM) device; + VirtualDeviceConfigSpec virtualDeviceConfigSpec = new VirtualDeviceConfigSpec(); + virtualDeviceConfigSpec.setDevice(virtualTPM); + virtualDeviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.REMOVE); + vmConfigSpec.getDeviceChange().add(virtualDeviceConfigSpec); + } + } + + } + } + private void tearDownVm(VirtualMachineMO vmMo) throws Exception { if (vmMo == null) From 771dfceadc7cce4f0ae630cf2b16d4e1d9697fed Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 11 Mar 2025 11:36:17 +0100 Subject: [PATCH 04/17] vTPM: do not set Key due to 'Cannot add multiple devices using the same device key..' --- .../com/cloud/hypervisor/vmware/resource/VmwareResource.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 724f76ea8812..e517a9132fc3 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -3234,7 +3234,6 @@ protected void configureVirtualTPM(VirtualMachineMO vmMo, VirtualMachineTO vmSpe description.setLabel("Trusted Platform Module"); VirtualTPM virtualTPM = new VirtualTPM(); virtualTPM.setDeviceInfo(description); - virtualTPM.setKey(-1); VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec(); deviceConfigSpec.setDevice(virtualTPM); deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD); From 7f0b82804148ef4fe23361960a23b9738adf8b1e Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Thu, 13 Mar 2025 08:57:04 +0100 Subject: [PATCH 05/17] vTPM: add unit test testTpmModel --- .../com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java index d0901092eef5..856dc0be9dcf 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java @@ -566,6 +566,7 @@ public void testTopology() { assertEquals("", cpuModeDef.toString()); } + @Test public void testTopologyNoInfo() { LibvirtVMDef.CpuModeDef cpuModeDef = new LibvirtVMDef.CpuModeDef(); cpuModeDef.setTopology(-1, -1, 4); @@ -577,5 +578,8 @@ public void testTpmModel() { LibvirtVMDef.TpmDef tpmDef = new LibvirtVMDef.TpmDef("tpm-tis", "2.0"); assertEquals(LibvirtVMDef.TpmDef.TpmModel.TIS, tpmDef.getModel()); assertEquals(LibvirtVMDef.TpmDef.TpmVersion.V2_0, tpmDef.getVersion()); + assertEquals("\n" + + "\n" + + "\n", tpmDef.toString()); } } From 5c90596fb9e082065414ba379b6b12a278d0ebe7 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Thu, 13 Mar 2025 09:52:48 +0100 Subject: [PATCH 06/17] engine/schema: remove user vm details for guest CPU mode/model --- .../src/main/resources/META-INF/db/schema-42000to42010.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql b/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql index bf13e5eee1ac..8e45e650ab04 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql @@ -19,6 +19,9 @@ -- Schema upgrade from 4.20.0.0 to 4.20.1.0 --; +-- Delete user vm details for guest CPU mode/model which are root admin only +DELETE FROM `cloud`.`user_vm_details` WHERE `name` IN ('guest.cpu.mode','guest.cpu.model'); + -- Add column api_key_access to user and account tables CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.user', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the user" AFTER `secret_key`'); CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.account', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the account" '); From aabee5eb9600046a1392a76ff61890839fef12d4 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Thu, 13 Mar 2025 16:34:29 +0100 Subject: [PATCH 07/17] vTPM: extra methods as Daan's requests --- .../vmware/resource/VmwareResource.java | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index e517a9132fc3..0b1af91ff585 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -3229,30 +3229,36 @@ protected void configureVirtualTPM(VirtualMachineMO vmMo, VirtualMachineTO vmSpe return; } } - Description description = new Description(); - description.setSummary("Trusted Platform Module"); - description.setLabel("Trusted Platform Module"); - VirtualTPM virtualTPM = new VirtualTPM(); - virtualTPM.setDeviceInfo(description); - VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec(); - deviceConfigSpec.setDevice(virtualTPM); - deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD); - vmConfigSpec.getDeviceChange().add(deviceConfigSpec); + addVirtualTPMDevice(vmConfigSpec); } else { logger.debug(String.format("Virtual TPM device is not enabled. It is only enabled when boot type is SECURE (actually %s) and vTPM is enabled (actually %s)", bootType, virtualTPMEnabled)); for (VirtualDevice device : vmMo.getAllDeviceList()) { if (device instanceof VirtualTPM) { - VirtualTPM virtualTPM = (VirtualTPM) device; - VirtualDeviceConfigSpec virtualDeviceConfigSpec = new VirtualDeviceConfigSpec(); - virtualDeviceConfigSpec.setDevice(virtualTPM); - virtualDeviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.REMOVE); - vmConfigSpec.getDeviceChange().add(virtualDeviceConfigSpec); + removeVirtualTPMDevice(vmConfigSpec, (VirtualTPM) device); } } - } } + private void addVirtualTPMDevice(VirtualMachineConfigSpec vmConfigSpec) { + Description description = new Description(); + description.setSummary("Trusted Platform Module"); + description.setLabel("Trusted Platform Module"); + VirtualTPM virtualTPM = new VirtualTPM(); + virtualTPM.setDeviceInfo(description); + VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec(); + deviceConfigSpec.setDevice(virtualTPM); + deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD); + vmConfigSpec.getDeviceChange().add(deviceConfigSpec); + } + + private void removeVirtualTPMDevice(VirtualMachineConfigSpec vmConfigSpec, VirtualTPM virtualTPM) { + VirtualDeviceConfigSpec virtualDeviceConfigSpec = new VirtualDeviceConfigSpec(); + virtualDeviceConfigSpec.setDevice(virtualTPM); + virtualDeviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.REMOVE); + vmConfigSpec.getDeviceChange().add(virtualDeviceConfigSpec); + } + private void tearDownVm(VirtualMachineMO vmMo) throws Exception { if (vmMo == null) From 3588be7a47f063de3d07711e1d4760df2400a011 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 14 Mar 2025 12:35:25 +0100 Subject: [PATCH 08/17] vTPM: add unit tests in VmwareResourceTest --- .../vmware/resource/VmwareResource.java | 4 +-- .../vmware/resource/VmwareResourceTest.java | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 0b1af91ff585..39bfd4675e2e 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -3240,7 +3240,7 @@ protected void configureVirtualTPM(VirtualMachineMO vmMo, VirtualMachineTO vmSpe } } - private void addVirtualTPMDevice(VirtualMachineConfigSpec vmConfigSpec) { + protected void addVirtualTPMDevice(VirtualMachineConfigSpec vmConfigSpec) { Description description = new Description(); description.setSummary("Trusted Platform Module"); description.setLabel("Trusted Platform Module"); @@ -3252,7 +3252,7 @@ private void addVirtualTPMDevice(VirtualMachineConfigSpec vmConfigSpec) { vmConfigSpec.getDeviceChange().add(deviceConfigSpec); } - private void removeVirtualTPMDevice(VirtualMachineConfigSpec vmConfigSpec, VirtualTPM virtualTPM) { + protected void removeVirtualTPMDevice(VirtualMachineConfigSpec vmConfigSpec, VirtualTPM virtualTPM) { VirtualDeviceConfigSpec virtualDeviceConfigSpec = new VirtualDeviceConfigSpec(); virtualDeviceConfigSpec.setDevice(virtualTPM); virtualDeviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.REMOVE); diff --git a/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java b/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java index 58d8e5ef254a..b43d32d03978 100644 --- a/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java +++ b/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java @@ -48,6 +48,8 @@ import com.vmware.vim25.FileInfo; import com.vmware.vim25.HostDatastoreBrowserSearchResults; import com.vmware.vim25.HostDatastoreBrowserSearchSpec; +import com.vmware.vim25.VirtualTPM; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsAnswer; import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsCommand; @@ -842,4 +844,37 @@ public void testExecuteWithEmptyPath() throws Exception { assertEquals(Collections.singletonList(1L), answer.getSizes()); assertEquals(Collections.singletonList(date.getTime()), answer.getLastModified()); } + + @Test + public void testAddVirtualTPMDevice() throws Exception { + VirtualMachineMO vmMo = Mockito.mock(VirtualMachineMO.class); + VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class); + VirtualMachineConfigSpec vmConfigSpec = Mockito.mock(VirtualMachineConfigSpec.class); + Map details = new HashMap<>(); + details.put(ApiConstants.BootType.UEFI.toString(), "SECURE"); + details.put(VmDetailConstants.VIRTUAL_TPM_ENABLED, "true"); + when(vmSpec.getDetails()).thenReturn(details); + when(vmMo.getAllDeviceList()).thenReturn(new ArrayList<>()); + Mockito.doNothing().when(vmwareResource).addVirtualTPMDevice(vmConfigSpec); + + vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec, "uefi"); + Mockito.verify(vmwareResource, Mockito.times(1)).addVirtualTPMDevice(vmConfigSpec); + } + + @Test + public void testRemoveVirtualTPMDevice() throws Exception { + VirtualMachineMO vmMo = Mockito.mock(VirtualMachineMO.class); + VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class); + VirtualMachineConfigSpec vmConfigSpec = Mockito.mock(VirtualMachineConfigSpec.class); + Map details = new HashMap<>(); + details.put(ApiConstants.BootType.UEFI.toString(), "SECURE"); + details.put(VmDetailConstants.VIRTUAL_TPM_ENABLED, "false"); + when(vmSpec.getDetails()).thenReturn(details); + VirtualTPM tpm = new VirtualTPM(); + when(vmMo.getAllDeviceList()).thenReturn(List.of(tpm)); + Mockito.doNothing().when(vmwareResource).removeVirtualTPMDevice(vmConfigSpec, tpm); + + vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec, "uefi"); + Mockito.verify(vmwareResource, Mockito.times(1)).removeVirtualTPMDevice(vmConfigSpec, tpm); + } } From 6a461b14b05138141902a56db6b54decb8d23139 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 14 Mar 2025 13:57:55 +0100 Subject: [PATCH 09/17] vTPM: update unit tests in VmwareResourceTest --- .../hypervisor/vmware/resource/VmwareResourceTest.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java b/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java index b43d32d03978..70f78ee9e193 100644 --- a/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java +++ b/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java @@ -855,10 +855,12 @@ public void testAddVirtualTPMDevice() throws Exception { details.put(VmDetailConstants.VIRTUAL_TPM_ENABLED, "true"); when(vmSpec.getDetails()).thenReturn(details); when(vmMo.getAllDeviceList()).thenReturn(new ArrayList<>()); - Mockito.doNothing().when(vmwareResource).addVirtualTPMDevice(vmConfigSpec); + List deviceChanges = Mockito.mock(List.class); + when(vmConfigSpec.getDeviceChange()).thenReturn(deviceChanges); vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec, "uefi"); Mockito.verify(vmwareResource, Mockito.times(1)).addVirtualTPMDevice(vmConfigSpec); + Mockito.verify(deviceChanges, Mockito.times(1)).add(any(VirtualDeviceConfigSpec.class)); } @Test @@ -872,9 +874,11 @@ public void testRemoveVirtualTPMDevice() throws Exception { when(vmSpec.getDetails()).thenReturn(details); VirtualTPM tpm = new VirtualTPM(); when(vmMo.getAllDeviceList()).thenReturn(List.of(tpm)); - Mockito.doNothing().when(vmwareResource).removeVirtualTPMDevice(vmConfigSpec, tpm); + List deviceChanges = Mockito.mock(List.class); + when(vmConfigSpec.getDeviceChange()).thenReturn(deviceChanges); vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec, "uefi"); Mockito.verify(vmwareResource, Mockito.times(1)).removeVirtualTPMDevice(vmConfigSpec, tpm); + Mockito.verify(deviceChanges, Mockito.times(1)).add(any(VirtualDeviceConfigSpec.class)); } } From 580b1cb2ea2734ae4e326d434661d783f779be1d Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 14 Mar 2025 14:03:46 +0100 Subject: [PATCH 10/17] vTPM: add unit test in LibvirtComputingResourceTest --- .../kvm/resource/LibvirtComputingResource.java | 2 +- .../kvm/resource/LibvirtComputingResourceTest.java | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) 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 94ae42d27a24..13518de5cb3c 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 @@ -2859,7 +2859,7 @@ private CpuModeDef createCpuModeDef(VirtualMachineTO vmTO, int vcpus) { return cmd; } - private TpmDef createTpmDef(VirtualMachineTO vmTO) { + protected TpmDef createTpmDef(VirtualMachineTO vmTO) { Map details = vmTO.getDetails(); if (MapUtils.isEmpty(details)) { return null; 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 753bce31c258..0e3da84c613f 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 @@ -6541,4 +6541,16 @@ public void testGetDiskModelFromVMDetailVirtioBlk() { DiskDef.DiskBus diskBus = libvirtComputingResourceSpy.getDiskModelFromVMDetail(virtualMachineTO); assertEquals(DiskDef.DiskBus.VIRTIOBLK, diskBus); } + + @Test + public void testCreateTpmDef() { + VirtualMachineTO virtualMachineTO = Mockito.mock(VirtualMachineTO.class); + Map details = new HashMap<>(); + details.put(VmDetailConstants.VIRTUAL_TPM_MODEL, "tpm-tis"); + details.put(VmDetailConstants.VIRTUAL_TPM_VERSION, "2.0"); + Mockito.when(virtualMachineTO.getDetails()).thenReturn(details); + LibvirtVMDef.TpmDef tpmDef = libvirtComputingResourceSpy.createTpmDef(virtualMachineTO); + assertEquals(LibvirtVMDef.TpmDef.TpmModel.TIS, tpmDef.getModel()); + assertEquals(LibvirtVMDef.TpmDef.TpmVersion.V2_0, tpmDef.getVersion()); + } } From c74f339a64e1fee3fff3c0b311702deae32cfb77 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 14 Mar 2025 19:49:21 +0100 Subject: [PATCH 11/17] vTPM: use the default TPM version if an invalid version is passed --- .../cloud/hypervisor/kvm/resource/LibvirtVMDef.java | 10 ++++++---- .../kvm/resource/LibvirtComputingResourceTest.java | 12 ++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java index 0a63b8b63e1b..93ad084b4379 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java @@ -2411,7 +2411,7 @@ public TpmDef(String model, String version) { this.version = Arrays.stream(TpmVersion.values()) .filter(tpmVersion -> tpmVersion.toString().equals(version)) .findFirst() - .orElse(null);; + .orElse(this.version);; } } @@ -2426,9 +2426,11 @@ public TpmVersion getVersion() { @Override public String toString() { StringBuilder tpmBuidler = new StringBuilder(); - tpmBuidler.append("\n"); - tpmBuidler.append("\n"); - tpmBuidler.append("\n"); + if (model != null) { + tpmBuidler.append("\n"); + tpmBuidler.append("\n"); + tpmBuidler.append("\n"); + } return tpmBuidler.toString(); } } 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 0e3da84c613f..88e0983b63e6 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 @@ -6553,4 +6553,16 @@ public void testCreateTpmDef() { assertEquals(LibvirtVMDef.TpmDef.TpmModel.TIS, tpmDef.getModel()); assertEquals(LibvirtVMDef.TpmDef.TpmVersion.V2_0, tpmDef.getVersion()); } + + @Test + public void testCreateTpmDefWithInvalidVersion() { + VirtualMachineTO virtualMachineTO = Mockito.mock(VirtualMachineTO.class); + Map details = new HashMap<>(); + details.put(VmDetailConstants.VIRTUAL_TPM_MODEL, "tpm-crb"); + details.put(VmDetailConstants.VIRTUAL_TPM_VERSION, "3.0"); + Mockito.when(virtualMachineTO.getDetails()).thenReturn(details); + LibvirtVMDef.TpmDef tpmDef = libvirtComputingResourceSpy.createTpmDef(virtualMachineTO); + assertEquals(LibvirtVMDef.TpmDef.TpmModel.CRB, tpmDef.getModel()); + assertEquals(LibvirtVMDef.TpmDef.TpmVersion.V2_0, tpmDef.getVersion()); + } } From 81e26abc83d39d70fb8c8a3f9cc6741d58f4828a Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Mon, 17 Mar 2025 13:29:32 +0100 Subject: [PATCH 12/17] vTPM: requires UEFI on vmware and do nothing if it is not enabled/disabled --- .../vmware/resource/VmwareResource.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 39bfd4675e2e..1075783723fa 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -3218,22 +3218,26 @@ protected void configureSpecVideoCardNewVRamSize(VirtualMachineVideoCard videoCa * @throws Exception exception */ protected void configureVirtualTPM(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, VirtualMachineConfigSpec vmConfigSpec, String bootMode) throws Exception { - String bootType = vmSpec.getDetails().getOrDefault(ApiConstants.BootType.UEFI.toString(), null); String virtualTPMEnabled = vmSpec.getDetails().getOrDefault(VmDetailConstants.VIRTUAL_TPM_ENABLED, null); - if (StringUtils.isNotBlank(bootMode) && !bootMode.equalsIgnoreCase("bios") - && "secure".equalsIgnoreCase(bootType) - && Boolean.parseBoolean(virtualTPMEnabled)) { - logger.debug("Adding Virtual TPM device"); + if (Boolean.parseBoolean(virtualTPMEnabled)) { + if (StringUtils.isBlank(bootMode) || !bootMode.equalsIgnoreCase("uefi")) { + throw new Exception("VM instance with Virtual TPM must use UEFI boot mode"); + } for (VirtualDevice device : vmMo.getAllDeviceList()) { if (device instanceof VirtualTPM) { + logger.debug("Virtual TPM device has already been added, returning"); return; } } + logger.debug("Adding Virtual TPM device"); addVirtualTPMDevice(vmConfigSpec); + } else if (virtualTPMEnabled == null) { + logger.debug("Virtual TPM device is neither enabled nor disabled, skipping"); } else { - logger.debug(String.format("Virtual TPM device is not enabled. It is only enabled when boot type is SECURE (actually %s) and vTPM is enabled (actually %s)", bootType, virtualTPMEnabled)); + logger.debug(String.format("Virtual TPM device is disabled. It is enabled when boot mode is UEFI (actually %s) and vTPM is enabled (actually %s)", bootMode, virtualTPMEnabled)); for (VirtualDevice device : vmMo.getAllDeviceList()) { if (device instanceof VirtualTPM) { + logger.debug("Removing Virtual TPM device as it is disabled"); removeVirtualTPMDevice(vmConfigSpec, (VirtualTPM) device); } } From 8c99e651752dee5a47dc4ed5e8ac7ca9384b6629 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Mon, 17 Mar 2025 16:38:38 +0100 Subject: [PATCH 13/17] vTPM: let uses to add UEFI on vmware --- .../vmware/resource/VmwareResource.java | 15 ++++++--------- .../vmware/resource/VmwareResourceTest.java | 4 ++-- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 1075783723fa..6bdc3cf13fdb 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -2600,7 +2600,7 @@ protected StartAnswer execute(StartCommand cmd) { setBootOptions(vmSpec, bootMode, vmConfigSpec); // Config vTPM - configureVirtualTPM(vmMo, vmSpec, vmConfigSpec, bootMode); + configureVirtualTPM(vmMo, vmSpec, vmConfigSpec); if (StringUtils.isNotEmpty(vmStoragePolicyId)) { vmConfigSpec.getVmProfile().add(vmProfileSpec); @@ -3217,27 +3217,24 @@ protected void configureSpecVideoCardNewVRamSize(VirtualMachineVideoCard videoCa * @param vmConfigSpec virtual machine config spec * @throws Exception exception */ - protected void configureVirtualTPM(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, VirtualMachineConfigSpec vmConfigSpec, String bootMode) throws Exception { + protected void configureVirtualTPM(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, VirtualMachineConfigSpec vmConfigSpec) throws Exception { String virtualTPMEnabled = vmSpec.getDetails().getOrDefault(VmDetailConstants.VIRTUAL_TPM_ENABLED, null); if (Boolean.parseBoolean(virtualTPMEnabled)) { - if (StringUtils.isBlank(bootMode) || !bootMode.equalsIgnoreCase("uefi")) { - throw new Exception("VM instance with Virtual TPM must use UEFI boot mode"); - } for (VirtualDevice device : vmMo.getAllDeviceList()) { if (device instanceof VirtualTPM) { - logger.debug("Virtual TPM device has already been added, returning"); + logger.debug(String.format("Virtual TPM device has already been added to VM , returning", vmMo.getVmName())); return; } } logger.debug("Adding Virtual TPM device"); addVirtualTPMDevice(vmConfigSpec); } else if (virtualTPMEnabled == null) { - logger.debug("Virtual TPM device is neither enabled nor disabled, skipping"); + logger.debug(String.format("Virtual TPM device is neither enabled nor disabled for VM %s, skipping", vmMo.getVmName())); } else { - logger.debug(String.format("Virtual TPM device is disabled. It is enabled when boot mode is UEFI (actually %s) and vTPM is enabled (actually %s)", bootMode, virtualTPMEnabled)); + logger.debug(String.format("Virtual TPM device is disabled for VM %s", vmMo.getVmName())); for (VirtualDevice device : vmMo.getAllDeviceList()) { if (device instanceof VirtualTPM) { - logger.debug("Removing Virtual TPM device as it is disabled"); + logger.debug(String.format("Removing Virtual TPM device from VM %s as it is disabled", vmMo.getVmName())); removeVirtualTPMDevice(vmConfigSpec, (VirtualTPM) device); } } diff --git a/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java b/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java index 70f78ee9e193..45457756e55a 100644 --- a/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java +++ b/plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java @@ -858,7 +858,7 @@ public void testAddVirtualTPMDevice() throws Exception { List deviceChanges = Mockito.mock(List.class); when(vmConfigSpec.getDeviceChange()).thenReturn(deviceChanges); - vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec, "uefi"); + vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec); Mockito.verify(vmwareResource, Mockito.times(1)).addVirtualTPMDevice(vmConfigSpec); Mockito.verify(deviceChanges, Mockito.times(1)).add(any(VirtualDeviceConfigSpec.class)); } @@ -877,7 +877,7 @@ public void testRemoveVirtualTPMDevice() throws Exception { List deviceChanges = Mockito.mock(List.class); when(vmConfigSpec.getDeviceChange()).thenReturn(deviceChanges); - vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec, "uefi"); + vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec); Mockito.verify(vmwareResource, Mockito.times(1)).removeVirtualTPMDevice(vmConfigSpec, tpm); Mockito.verify(deviceChanges, Mockito.times(1)).add(any(VirtualDeviceConfigSpec.class)); } From 1c330153485638632f1065b0cbfd269e8c781f74 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Wed, 19 Mar 2025 20:42:18 +0100 Subject: [PATCH 14/17] Update plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java Co-authored-by: Suresh Kumar Anaparti --- .../com/cloud/hypervisor/vmware/resource/VmwareResource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 6bdc3cf13fdb..8b55d025c5a2 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -3222,7 +3222,7 @@ protected void configureVirtualTPM(VirtualMachineMO vmMo, VirtualMachineTO vmSpe if (Boolean.parseBoolean(virtualTPMEnabled)) { for (VirtualDevice device : vmMo.getAllDeviceList()) { if (device instanceof VirtualTPM) { - logger.debug(String.format("Virtual TPM device has already been added to VM , returning", vmMo.getVmName())); + logger.debug(String.format("Virtual TPM device has already been added to VM %s, returning", vmMo.getVmName())); return; } } From 310bf899e2fbded11ab042dea514d5a5bb352f56 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Wed, 19 Mar 2025 20:42:29 +0100 Subject: [PATCH 15/17] Update plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java Co-authored-by: Suresh Kumar Anaparti --- .../com/cloud/hypervisor/vmware/resource/VmwareResource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 8b55d025c5a2..24dda4f3ae47 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -3226,7 +3226,7 @@ protected void configureVirtualTPM(VirtualMachineMO vmMo, VirtualMachineTO vmSpe return; } } - logger.debug("Adding Virtual TPM device"); + logger.debug(String.format("Adding Virtual TPM device to the VM %s", vmMo.getVmName())); addVirtualTPMDevice(vmConfigSpec); } else if (virtualTPMEnabled == null) { logger.debug(String.format("Virtual TPM device is neither enabled nor disabled for VM %s, skipping", vmMo.getVmName())); From e1a4ed2e04e6ffc9803e7bd547f88fba83842cad Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 28 Mar 2025 09:40:39 +0100 Subject: [PATCH 16/17] vTPM: remove template details for guest CPU mode/model --- .../src/main/resources/META-INF/db/schema-42000to42010.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql b/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql index 8e45e650ab04..9c1b1eac6384 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql @@ -22,6 +22,9 @@ -- Delete user vm details for guest CPU mode/model which are root admin only DELETE FROM `cloud`.`user_vm_details` WHERE `name` IN ('guest.cpu.mode','guest.cpu.model'); +-- Delete template details for guest CPU mode/model which are root admin only +DELETE FROM `cloud`.`vm_template_details` WHERE `name` IN ('guest.cpu.mode','guest.cpu.model'); + -- Add column api_key_access to user and account tables CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.user', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the user" AFTER `secret_key`'); CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.account', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the account" '); From 8bfd8f88924b513e3150788226a0ba5858cd4bd5 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Thu, 17 Apr 2025 10:46:56 +0200 Subject: [PATCH 17/17] UI: boot vm from ISO into UEFI/SECURE mode --- ui/src/views/compute/DeployVM.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/views/compute/DeployVM.vue b/ui/src/views/compute/DeployVM.vue index 57dbe8eeabcf..eb5e4a6a9a09 100644 --- a/ui/src/views/compute/DeployVM.vue +++ b/ui/src/views/compute/DeployVM.vue @@ -559,7 +559,7 @@
+ v-if="['KVM', 'VMware', 'XenServer'].includes(hypervisor) && ((vm.templateid && !template.deployasis) || vm.isoid)">