mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
vTPM: support KVM and VMware (#10543)
* KVM: add Virtual TPM model and version * KVM: add admin-only VM setting GUEST.CPU.MODE and GUEST.CPU.MODEL * VMware: add vTPM * vTPM: do not set Key due to 'Cannot add multiple devices using the same device key..' * vTPM: add unit test testTpmModel * engine/schema: remove user vm details for guest CPU mode/model * vTPM: extra methods as Daan's requests * vTPM: add unit tests in VmwareResourceTest * vTPM: update unit tests in VmwareResourceTest * vTPM: add unit test in LibvirtComputingResourceTest * vTPM: use the default TPM version if an invalid version is passed * vTPM: requires UEFI on vmware and do nothing if it is not enabled/disabled * vTPM: let uses to add UEFI on vmware * Update plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java Co-authored-by: Suresh Kumar Anaparti <sureshkumar.anaparti@gmail.com> * Update plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java Co-authored-by: Suresh Kumar Anaparti <sureshkumar.anaparti@gmail.com> * vTPM: remove template details for guest CPU mode/model * UI: boot vm from ISO into UEFI/SECURE mode --------- Co-authored-by: Suresh Kumar Anaparti <sureshkumar.anaparti@gmail.com>
This commit is contained in:
parent
12c077d704
commit
5d28e66b52
@ -101,4 +101,13 @@ public interface VmDetailConstants {
|
|||||||
String VMWARE_HOST_NAME = String.format("%s-host", VMWARE_TO_KVM_PREFIX);
|
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_DISK = String.format("%s-disk", VMWARE_TO_KVM_PREFIX);
|
||||||
String VMWARE_MAC_ADDRESSES = String.format("%s-mac-addresses", 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";
|
||||||
|
|
||||||
|
// CPU mode and model, ADMIN only
|
||||||
|
String GUEST_CPU_MODE = "guest.cpu.mode";
|
||||||
|
String GUEST_CPU_MODEL = "guest.cpu.model";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package org.apache.cloudstack.query;
|
package org.apache.cloudstack.query;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||||
@ -97,6 +98,7 @@ import org.apache.cloudstack.api.response.ZoneResponse;
|
|||||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||||
|
|
||||||
import com.cloud.exception.PermissionDeniedException;
|
import com.cloud.exception.PermissionDeniedException;
|
||||||
|
import com.cloud.vm.VmDetailConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service used for list api query.
|
* Service used for list api query.
|
||||||
@ -104,6 +106,8 @@ import com.cloud.exception.PermissionDeniedException;
|
|||||||
*/
|
*/
|
||||||
public interface QueryService {
|
public interface QueryService {
|
||||||
|
|
||||||
|
List<String> RootAdminOnlyVmSettings = Arrays.asList(VmDetailConstants.GUEST_CPU_MODE, VmDetailConstants.GUEST_CPU_MODEL);
|
||||||
|
|
||||||
// Config keys
|
// Config keys
|
||||||
ConfigKey<Boolean> AllowUserViewDestroyedVM = new ConfigKey<>("Advanced", Boolean.class, "allow.user.view.destroyed.vm", "false",
|
ConfigKey<Boolean> 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);
|
"Determines whether users can view their destroyed or expunging vm ", true, ConfigKey.Scope.Account);
|
||||||
|
|||||||
@ -19,6 +19,12 @@
|
|||||||
-- Schema upgrade from 4.20.0.0 to 4.20.1.0
|
-- 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');
|
||||||
|
|
||||||
|
-- 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
|
-- 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.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" ');
|
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.account', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the account" ');
|
||||||
|
|||||||
@ -166,6 +166,7 @@ import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef.RngBackendModel;
|
|||||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SCSIDef;
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SCSIDef;
|
||||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef;
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef;
|
||||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy;
|
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.VideoDef;
|
||||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef;
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef;
|
||||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef.WatchDogAction;
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef.WatchDogAction;
|
||||||
@ -2660,6 +2661,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
devices.addDevice(createGraphicDef(vmTO));
|
devices.addDevice(createGraphicDef(vmTO));
|
||||||
devices.addDevice(createTabletInputDef());
|
devices.addDevice(createTabletInputDef());
|
||||||
|
|
||||||
|
TpmDef tpmDef = createTpmDef(vmTO);
|
||||||
|
if (tpmDef != null) {
|
||||||
|
devices.addDevice(tpmDef);
|
||||||
|
}
|
||||||
|
|
||||||
if (isGuestAarch64()) {
|
if (isGuestAarch64()) {
|
||||||
createArm64UsbDef(devices);
|
createArm64UsbDef(devices);
|
||||||
}
|
}
|
||||||
@ -2840,8 +2846,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
|
|
||||||
private CpuModeDef createCpuModeDef(VirtualMachineTO vmTO, int vcpus) {
|
private CpuModeDef createCpuModeDef(VirtualMachineTO vmTO, int vcpus) {
|
||||||
final CpuModeDef cmd = new CpuModeDef();
|
final CpuModeDef cmd = new CpuModeDef();
|
||||||
cmd.setMode(guestCpuMode);
|
Map<String, String> details = vmTO.getDetails();
|
||||||
cmd.setModel(guestCpuModel);
|
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())) {
|
if (VirtualMachine.Type.User.equals(vmTO.getType())) {
|
||||||
cmd.setFeatures(cpuFeatures);
|
cmd.setFeatures(cpuFeatures);
|
||||||
}
|
}
|
||||||
@ -2850,6 +2859,19 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected TpmDef createTpmDef(VirtualMachineTO vmTO) {
|
||||||
|
Map<String, String> 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) {
|
private void configureGuestIfUefiEnabled(boolean isSecureBoot, String bootMode, GuestDef guest) {
|
||||||
setGuestLoader(bootMode, SECURE, guest, GuestDef.GUEST_LOADER_SECURE);
|
setGuestLoader(bootMode, SECURE, guest, GuestDef.GUEST_LOADER_SECURE);
|
||||||
setGuestLoader(bootMode, LEGACY, guest, GuestDef.GUEST_LOADER_LEGACY);
|
setGuestLoader(bootMode, LEGACY, guest, GuestDef.GUEST_LOADER_LEGACY);
|
||||||
|
|||||||
@ -18,6 +18,7 @@ package com.cloud.hypervisor.kvm.resource;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -2358,6 +2359,82 @@ public class LibvirtVMDef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(this.version);;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TpmModel getModel() {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TpmVersion getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder tpmBuidler = new StringBuilder();
|
||||||
|
if (model != null) {
|
||||||
|
tpmBuidler.append("<tpm model='").append(model).append("'>\n");
|
||||||
|
tpmBuidler.append("<backend type='emulator' version='").append(version).append("'/>\n");
|
||||||
|
tpmBuidler.append("</tpm>\n");
|
||||||
|
}
|
||||||
|
return tpmBuidler.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setHvsType(String hvs) {
|
public void setHvsType(String hvs) {
|
||||||
_hvsType = hvs;
|
_hvsType = hvs;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6541,4 +6541,28 @@ public class LibvirtComputingResourceTest {
|
|||||||
DiskDef.DiskBus diskBus = libvirtComputingResourceSpy.getDiskModelFromVMDetail(virtualMachineTO);
|
DiskDef.DiskBus diskBus = libvirtComputingResourceSpy.getDiskModelFromVMDetail(virtualMachineTO);
|
||||||
assertEquals(DiskDef.DiskBus.VIRTIOBLK, diskBus);
|
assertEquals(DiskDef.DiskBus.VIRTIOBLK, diskBus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateTpmDef() {
|
||||||
|
VirtualMachineTO virtualMachineTO = Mockito.mock(VirtualMachineTO.class);
|
||||||
|
Map<String, String> 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateTpmDefWithInvalidVersion() {
|
||||||
|
VirtualMachineTO virtualMachineTO = Mockito.mock(VirtualMachineTO.class);
|
||||||
|
Map<String, String> 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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -566,9 +566,20 @@ public class LibvirtVMDefTest extends TestCase {
|
|||||||
assertEquals("<cpu><topology sockets='4' cores='2' threads='1' /></cpu>", cpuModeDef.toString());
|
assertEquals("<cpu><topology sockets='4' cores='2' threads='1' /></cpu>", cpuModeDef.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testTopologyNoInfo() {
|
public void testTopologyNoInfo() {
|
||||||
LibvirtVMDef.CpuModeDef cpuModeDef = new LibvirtVMDef.CpuModeDef();
|
LibvirtVMDef.CpuModeDef cpuModeDef = new LibvirtVMDef.CpuModeDef();
|
||||||
cpuModeDef.setTopology(-1, -1, 4);
|
cpuModeDef.setTopology(-1, -1, 4);
|
||||||
assertEquals("<cpu></cpu>", cpuModeDef.toString());
|
assertEquals("<cpu></cpu>", 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());
|
||||||
|
assertEquals("<tpm model='tpm-tis'>\n" +
|
||||||
|
"<backend type='emulator' version='2.0'/>\n" +
|
||||||
|
"</tpm>\n", tpmDef.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,6 +51,7 @@ import javax.xml.datatype.XMLGregorianCalendar;
|
|||||||
|
|
||||||
import com.cloud.capacity.CapacityManager;
|
import com.cloud.capacity.CapacityManager;
|
||||||
import com.cloud.hypervisor.vmware.mo.HostDatastoreBrowserMO;
|
import com.cloud.hypervisor.vmware.mo.HostDatastoreBrowserMO;
|
||||||
|
import com.vmware.vim25.Description;
|
||||||
import com.vmware.vim25.FileInfo;
|
import com.vmware.vim25.FileInfo;
|
||||||
import com.vmware.vim25.FileQueryFlags;
|
import com.vmware.vim25.FileQueryFlags;
|
||||||
import com.vmware.vim25.FolderFileInfo;
|
import com.vmware.vim25.FolderFileInfo;
|
||||||
@ -58,6 +59,7 @@ import com.vmware.vim25.HostDatastoreBrowserSearchResults;
|
|||||||
import com.vmware.vim25.HostDatastoreBrowserSearchSpec;
|
import com.vmware.vim25.HostDatastoreBrowserSearchSpec;
|
||||||
import com.vmware.vim25.VirtualCdromIsoBackingInfo;
|
import com.vmware.vim25.VirtualCdromIsoBackingInfo;
|
||||||
import com.vmware.vim25.VirtualMachineConfigSummary;
|
import com.vmware.vim25.VirtualMachineConfigSummary;
|
||||||
|
import com.vmware.vim25.VirtualTPM;
|
||||||
import org.apache.cloudstack.api.ApiConstants;
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
import org.apache.cloudstack.backup.PrepareForBackupRestorationCommand;
|
import org.apache.cloudstack.backup.PrepareForBackupRestorationCommand;
|
||||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||||
@ -2597,12 +2599,16 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||||||
|
|
||||||
setBootOptions(vmSpec, bootMode, vmConfigSpec);
|
setBootOptions(vmSpec, bootMode, vmConfigSpec);
|
||||||
|
|
||||||
|
// Config vTPM
|
||||||
|
configureVirtualTPM(vmMo, vmSpec, vmConfigSpec);
|
||||||
|
|
||||||
if (StringUtils.isNotEmpty(vmStoragePolicyId)) {
|
if (StringUtils.isNotEmpty(vmStoragePolicyId)) {
|
||||||
vmConfigSpec.getVmProfile().add(vmProfileSpec);
|
vmConfigSpec.getVmProfile().add(vmProfileSpec);
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace(String.format("Configuring the VM %s with storage policy: %s", vmInternalCSName, vmStoragePolicyId));
|
logger.trace(String.format("Configuring the VM %s with storage policy: %s", vmInternalCSName, vmStoragePolicyId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Configure VM
|
// Configure VM
|
||||||
//
|
//
|
||||||
@ -3203,6 +3209,57 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||||||
vmConfigSpec.getDeviceChange().add(arrayVideoCardConfigSpecs);
|
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) throws Exception {
|
||||||
|
String virtualTPMEnabled = vmSpec.getDetails().getOrDefault(VmDetailConstants.VIRTUAL_TPM_ENABLED, null);
|
||||||
|
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 %s, returning", vmMo.getVmName()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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()));
|
||||||
|
} else {
|
||||||
|
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(String.format("Removing Virtual TPM device from VM %s as it is disabled", vmMo.getVmName()));
|
||||||
|
removeVirtualTPMDevice(vmConfigSpec, (VirtualTPM) device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected 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 {
|
private void tearDownVm(VirtualMachineMO vmMo) throws Exception {
|
||||||
|
|
||||||
if (vmMo == null)
|
if (vmMo == null)
|
||||||
|
|||||||
@ -48,6 +48,8 @@ import com.cloud.hypervisor.vmware.util.VmwareHelper;
|
|||||||
import com.vmware.vim25.FileInfo;
|
import com.vmware.vim25.FileInfo;
|
||||||
import com.vmware.vim25.HostDatastoreBrowserSearchResults;
|
import com.vmware.vim25.HostDatastoreBrowserSearchResults;
|
||||||
import com.vmware.vim25.HostDatastoreBrowserSearchSpec;
|
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.CopyCommand;
|
||||||
import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsAnswer;
|
import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsAnswer;
|
||||||
import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsCommand;
|
import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsCommand;
|
||||||
@ -842,4 +844,41 @@ public class VmwareResourceTest {
|
|||||||
assertEquals(Collections.singletonList(1L), answer.getSizes());
|
assertEquals(Collections.singletonList(1L), answer.getSizes());
|
||||||
assertEquals(Collections.singletonList(date.getTime()), answer.getLastModified());
|
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<String, String> 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<>());
|
||||||
|
List<VirtualDeviceConfigSpec> deviceChanges = Mockito.mock(List.class);
|
||||||
|
when(vmConfigSpec.getDeviceChange()).thenReturn(deviceChanges);
|
||||||
|
|
||||||
|
vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec);
|
||||||
|
Mockito.verify(vmwareResource, Mockito.times(1)).addVirtualTPMDevice(vmConfigSpec);
|
||||||
|
Mockito.verify(deviceChanges, Mockito.times(1)).add(any(VirtualDeviceConfigSpec.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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<String, String> 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));
|
||||||
|
List<VirtualDeviceConfigSpec> deviceChanges = Mockito.mock(List.class);
|
||||||
|
when(vmConfigSpec.getDeviceChange()).thenReturn(deviceChanges);
|
||||||
|
|
||||||
|
vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec);
|
||||||
|
Mockito.verify(vmwareResource, Mockito.times(1)).removeVirtualTPMDevice(vmConfigSpec, tpm);
|
||||||
|
Mockito.verify(deviceChanges, Mockito.times(1)).add(any(VirtualDeviceConfigSpec.class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5033,6 +5033,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||||||
final List<String> userDenyListedSettings = Stream.of(QueryService.UserVMDeniedDetails.value().split(","))
|
final List<String> userDenyListedSettings = Stream.of(QueryService.UserVMDeniedDetails.value().split(","))
|
||||||
.map(item -> (item).trim())
|
.map(item -> (item).trim())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
userDenyListedSettings.addAll(QueryService.RootAdminOnlyVmSettings);
|
||||||
for (final String detail : userDenyListedSettings) {
|
for (final String detail : userDenyListedSettings) {
|
||||||
if (options.containsKey(detail)) {
|
if (options.containsKey(detail)) {
|
||||||
options.remove(detail);
|
options.remove(detail);
|
||||||
@ -5083,6 +5084,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||||||
options.put(VmDetailConstants.IOTHREADS, Arrays.asList("enabled"));
|
options.put(VmDetailConstants.IOTHREADS, Arrays.asList("enabled"));
|
||||||
options.put(VmDetailConstants.NIC_MULTIQUEUE_NUMBER, Collections.emptyList());
|
options.put(VmDetailConstants.NIC_MULTIQUEUE_NUMBER, Collections.emptyList());
|
||||||
options.put(VmDetailConstants.NIC_PACKED_VIRTQUEUES_ENABLED, Arrays.asList("true", "false"));
|
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)) {
|
if (HypervisorType.VMware.equals(hypervisorType)) {
|
||||||
@ -5092,6 +5097,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||||||
options.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, Arrays.asList("true", "false"));
|
options.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, Arrays.asList("true", "false"));
|
||||||
options.put(VmDetailConstants.SVGA_VRAM_SIZE, Collections.emptyList());
|
options.put(VmDetailConstants.SVGA_VRAM_SIZE, Collections.emptyList());
|
||||||
options.put(VmDetailConstants.RAM_RESERVATION, Collections.emptyList());
|
options.put(VmDetailConstants.RAM_RESERVATION, Collections.emptyList());
|
||||||
|
options.put(VmDetailConstants.VIRTUAL_TPM_ENABLED, Arrays.asList("true", "false"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2839,6 +2839,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
final List<String> userDenyListedSettings = Stream.of(QueryService.UserVMDeniedDetails.value().split(","))
|
final List<String> userDenyListedSettings = Stream.of(QueryService.UserVMDeniedDetails.value().split(","))
|
||||||
.map(item -> (item).trim())
|
.map(item -> (item).trim())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
userDenyListedSettings.addAll(QueryService.RootAdminOnlyVmSettings);
|
||||||
final List<String> userReadOnlySettings = Stream.of(QueryService.UserVMReadOnlyDetails.value().split(","))
|
final List<String> userReadOnlySettings = Stream.of(QueryService.UserVMReadOnlyDetails.value().split(","))
|
||||||
.map(item -> (item).trim())
|
.map(item -> (item).trim())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|||||||
@ -559,7 +559,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<div style="margin-top: 15px" v-if="showDetails">
|
<div style="margin-top: 15px" v-if="showDetails">
|
||||||
<div
|
<div
|
||||||
v-if="vm.templateid && ['KVM', 'VMware', 'XenServer'].includes(hypervisor) && !template.deployasis">
|
v-if="['KVM', 'VMware', 'XenServer'].includes(hypervisor) && ((vm.templateid && !template.deployasis) || vm.isoid)">
|
||||||
<a-form-item :label="$t('label.boottype')" name="boottype" ref="boottype">
|
<a-form-item :label="$t('label.boottype')" name="boottype" ref="boottype">
|
||||||
<a-select
|
<a-select
|
||||||
v-model:value="form.boottype"
|
v-model:value="form.boottype"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user