mirror of https://github.com/apache/cloudstack.git
UEFI Implementation: Enabled UEFI Support for Guest VM's on Hypervisor KVM,VMware. enabled boot modes [Legacy,Secure] support for UEFI boot with known caveats. (#3638)
Co-authored-by: Pavan Kumar Aravapalli <pavan_aravapalli@accelerite.com> Co-authored-by: dahn <daan.hoogland@shapeblue.com>
This commit is contained in:
parent
b9492807fd
commit
d4b537efa7
|
|
@ -63,6 +63,8 @@ public class VirtualMachineTO {
|
|||
String vncAddr;
|
||||
Map<String, String> params;
|
||||
String uuid;
|
||||
String bootType;
|
||||
String bootMode;
|
||||
|
||||
DiskTO[] disks;
|
||||
NicTO[] nics;
|
||||
|
|
@ -380,4 +382,15 @@ public class VirtualMachineTO {
|
|||
public void setOvfProperties(Pair<String, List<OVFPropertyTO>> ovfProperties) {
|
||||
this.ovfProperties = ovfProperties;
|
||||
}
|
||||
public String getBootType() {
|
||||
return bootType;
|
||||
}
|
||||
|
||||
public void setBootType(String bootType) {
|
||||
this.bootType = bootType;
|
||||
}
|
||||
|
||||
public String getBootMode() { return bootMode; }
|
||||
|
||||
public void setBootMode(String bootMode) { this.bootMode = bootMode; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ public interface Host extends StateObject<Status>, Identity, Partition, HAResour
|
|||
return strs;
|
||||
}
|
||||
}
|
||||
public static final String HOST_UEFI_ENABLE = "host.uefi.enable";
|
||||
|
||||
/**
|
||||
* @return name of the machine.
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ public interface VirtualMachineProfile {
|
|||
public static final Param PxeSeverType = new Param("PxeSeverType");
|
||||
public static final Param HaTag = new Param("HaTag");
|
||||
public static final Param HaOperation = new Param("HaOperation");
|
||||
public static final Param UefiFlag = new Param("UefiFlag");
|
||||
public static final Param BootMode = new Param("BootMode");
|
||||
public static final Param BootType = new Param("BootType");
|
||||
|
||||
private String name;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ public interface VmDetailConstants {
|
|||
String KEYBOARD = "keyboard";
|
||||
String CPU_CORE_PER_SOCKET = "cpu.corespersocket";
|
||||
String ROOT_DISK_SIZE = "rootdisksize";
|
||||
String BOOT_MODE = "boot.mode";
|
||||
|
||||
// VMware specific
|
||||
String NIC_ADAPTER = "nicAdapter";
|
||||
|
|
|
|||
|
|
@ -804,6 +804,27 @@ public class ApiConstants {
|
|||
public static final String NODE_ROOT_DISK_SIZE = "noderootdisksize";
|
||||
public static final String SUPPORTS_HA = "supportsha";
|
||||
|
||||
public static final String BOOT_TYPE ="boottype";
|
||||
public static final String BOOT_MODE ="bootmode";
|
||||
|
||||
public enum BootType {
|
||||
UEFI, BIOS;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name();
|
||||
}
|
||||
}
|
||||
|
||||
public enum BootMode {
|
||||
LEGACY, SECURE;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name();
|
||||
}
|
||||
}
|
||||
|
||||
public enum HostDetails {
|
||||
all, capacity, events, stats, min;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.apache.cloudstack.api.command.user.vm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
|
@ -26,6 +27,8 @@ import java.util.Map;
|
|||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.cloud.utils.StringUtils;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
|
|
@ -110,6 +113,12 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
|
|||
@Parameter(name = ApiConstants.NETWORK_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = NetworkResponse.class, description = "list of network ids used by virtual machine. Can't be specified with ipToNetworkList parameter")
|
||||
private List<Long> networkIds;
|
||||
|
||||
@Parameter(name = ApiConstants.BOOT_TYPE, type = CommandType.STRING, required = false, description = "Guest VM Boot option either custom[UEFI] or default boot [BIOS]")
|
||||
private String bootType;
|
||||
|
||||
@Parameter(name = ApiConstants.BOOT_MODE, type = CommandType.STRING, required = false, description = "Boot Mode [Legacy] or [Secure] Applicable when Boot Type Selected is UEFI, otherwise Legacy By default for BIOS")
|
||||
private String bootMode;
|
||||
|
||||
//DataDisk information
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.DISK_OFFERING_ID, type = CommandType.UUID, entityType = DiskOfferingResponse.class, description = "the ID of the disk offering for the virtual machine. If the template is of ISO format,"
|
||||
|
|
@ -244,6 +253,22 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
|
|||
return domainId;
|
||||
}
|
||||
|
||||
private ApiConstants.BootType getBootType() {
|
||||
|
||||
if (StringUtils.isNotBlank(bootType)) {
|
||||
try {
|
||||
String type = bootType.trim().toUpperCase();
|
||||
return ApiConstants.BootType.valueOf(type);
|
||||
} catch (IllegalArgumentException e) {
|
||||
String errMesg = "Invalid bootType " + bootType + "Specified for vm " + getName()
|
||||
+ " Valid values are: " + Arrays.toString(ApiConstants.BootType.values());
|
||||
s_logger.warn(errMesg);
|
||||
throw new InvalidParameterValueException(errMesg);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, String> getDetails() {
|
||||
Map<String, String> customparameterMap = new HashMap<String, String>();
|
||||
if (details != null && details.size() != 0) {
|
||||
|
|
@ -256,12 +281,35 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
|
|||
}
|
||||
}
|
||||
}
|
||||
if(getBootType() != null){ // export to get
|
||||
if(getBootType() == ApiConstants.BootType.UEFI) {
|
||||
customparameterMap.put(getBootType().toString(), getBootMode().toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (rootdisksize != null && !customparameterMap.containsKey("rootdisksize")) {
|
||||
customparameterMap.put("rootdisksize", rootdisksize.toString());
|
||||
}
|
||||
return customparameterMap;
|
||||
}
|
||||
|
||||
|
||||
public ApiConstants.BootMode getBootMode() {
|
||||
if (StringUtils.isNotBlank(bootMode)) {
|
||||
try {
|
||||
String mode = bootMode.trim().toUpperCase();
|
||||
return ApiConstants.BootMode.valueOf(mode);
|
||||
} catch (IllegalArgumentException e) {
|
||||
String errMesg = "Invalid bootMode " + bootMode + "Specified for vm " + getName()
|
||||
+ " Valid values are: "+ Arrays.toString(ApiConstants.BootMode.values());
|
||||
s_logger.warn(errMesg);
|
||||
throw new InvalidParameterValueException(errMesg);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, String> getVmOVFProperties() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
if (MapUtils.isNotEmpty(vmOvfProperties)) {
|
||||
|
|
|
|||
|
|
@ -244,6 +244,10 @@ public class HostResponse extends BaseResponse {
|
|||
@Param(description = "the admin that annotated this host", since = "4.11")
|
||||
private String username;
|
||||
|
||||
@SerializedName("ueficapability")
|
||||
@Param(description = "true if the host has capability to support UEFI boot")
|
||||
private Boolean uefiCapabilty;
|
||||
|
||||
@Override
|
||||
public String getObjectId() {
|
||||
return this.getId();
|
||||
|
|
@ -499,6 +503,14 @@ public class HostResponse extends BaseResponse {
|
|||
detailsCopy.remove("username");
|
||||
detailsCopy.remove("password");
|
||||
|
||||
if(detailsCopy.containsKey(Host.HOST_UEFI_ENABLE)) {
|
||||
this.setUefiCapabilty(Boolean.parseBoolean((String) detailsCopy.get(Host.HOST_UEFI_ENABLE)));
|
||||
detailsCopy.remove(Host.HOST_UEFI_ENABLE);
|
||||
} else {
|
||||
this.setUefiCapabilty(new Boolean(false)); // in case of existing host which is not scanned for UEFI capability
|
||||
}
|
||||
|
||||
|
||||
this.details = detailsCopy;
|
||||
}
|
||||
|
||||
|
|
@ -668,4 +680,8 @@ public class HostResponse extends BaseResponse {
|
|||
public Boolean getHaHost() {
|
||||
return haHost;
|
||||
}
|
||||
|
||||
public void setUefiCapabilty(Boolean hostCapability) {
|
||||
this.uefiCapabilty = hostCapability;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -298,6 +298,14 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
|
|||
@Param(description = "OS type id of the vm", since = "4.4")
|
||||
private String osTypeId;
|
||||
|
||||
@SerializedName(ApiConstants.BOOT_MODE)
|
||||
@Param(description = "Guest vm Boot Mode")
|
||||
private String bootMode;
|
||||
|
||||
@SerializedName(ApiConstants.BOOT_TYPE)
|
||||
@Param(description = "Guest vm Boot Type")
|
||||
private String bootType;
|
||||
|
||||
public UserVmResponse() {
|
||||
securityGroupList = new LinkedHashSet<SecurityGroupResponse>();
|
||||
nics = new LinkedHashSet<NicResponse>();
|
||||
|
|
@ -873,4 +881,13 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
|
|||
public String getOsTypeId() {
|
||||
return osTypeId;
|
||||
}
|
||||
|
||||
public String getBootType() { return bootType; }
|
||||
|
||||
public void setBootType(String bootType) { this.bootType = bootType; }
|
||||
|
||||
public String getBootMode() { return bootMode; }
|
||||
|
||||
public void setBootMode(String bootMode) { this.bootMode = bootMode; }
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,4 +171,10 @@ public interface VirtualMachineEntity extends CloudStackEntity {
|
|||
* @param netowrk network to disconnect from
|
||||
*/
|
||||
void disconnectFrom(NetworkEntity netowrk, short nicId);
|
||||
|
||||
/**
|
||||
* passing additional params of deployment associated with the virtual machine
|
||||
*/
|
||||
void setParamsToEntity(Map<VirtualMachineProfile.Param, Object> params);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1064,6 +1064,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
}
|
||||
|
||||
final VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, offering, owner, params);
|
||||
s_logger.info(" Uefi params " + "UefiFlag: " + params.get(VirtualMachineProfile.Param.UefiFlag)
|
||||
+ " Boot Type: " + params.get(VirtualMachineProfile.Param.BootType)
|
||||
+ " Boot Mode: " + params.get(VirtualMachineProfile.Param.BootMode)
|
||||
);
|
||||
DeployDestination dest = null;
|
||||
try {
|
||||
dest = _dpMgr.planDeployment(vmProfile, plan, avoids, planner);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMEntityDao;
|
|||
import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMReservationDao;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
|
@ -148,6 +149,15 @@ public class VMEntityManagerImpl implements VMEntityManager {
|
|||
VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid());
|
||||
VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm);
|
||||
vmProfile.setServiceOffering(_serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()));
|
||||
if (MapUtils.isNotEmpty(vmEntityVO.getDetails()) &&
|
||||
vmEntityVO.getDetails().containsKey(VirtualMachineProfile.Param.UefiFlag.getName()) &&
|
||||
"yes".equalsIgnoreCase(vmEntityVO.getDetails().get(VirtualMachineProfile.Param.UefiFlag.getName())))
|
||||
{
|
||||
Map<String, String> details = vmEntityVO.getDetails();
|
||||
vmProfile.getParameters().put(VirtualMachineProfile.Param.BootType, details.get(VirtualMachineProfile.Param.BootType.getName()));
|
||||
vmProfile.getParameters().put(VirtualMachineProfile.Param.BootMode, details.get(VirtualMachineProfile.Param.BootMode.getName()));
|
||||
vmProfile.getParameters().put(VirtualMachineProfile.Param.UefiFlag, details.get(VirtualMachineProfile.Param.UefiFlag.getName()));
|
||||
}
|
||||
DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vm.getPodIdToDeployIn(), null, null, null, null);
|
||||
if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) {
|
||||
plan =
|
||||
|
|
|
|||
|
|
@ -20,9 +20,11 @@ import java.lang.reflect.Method;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.apache.cloudstack.engine.cloud.entity.api.db.VMEntityVO;
|
||||
|
||||
|
|
@ -269,4 +271,22 @@ public class VirtualMachineEntityImpl implements VirtualMachineEntity {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParamsToEntity(Map<VirtualMachineProfile.Param, Object> map) {
|
||||
if (MapUtils.isNotEmpty(map)) {
|
||||
if (this.vmEntityVO != null) {
|
||||
Map<String, String> details = this.vmEntityVO.getDetails();
|
||||
if (details == null) {
|
||||
details = new HashMap<String, String>();
|
||||
}
|
||||
for (Map.Entry<VirtualMachineProfile.Param, Object> entry : map.entrySet()) {
|
||||
if (null != entry && null != entry.getValue() && null != entry.getKey()) {
|
||||
details.put(entry.getKey().getName(), entry.getValue().toString());
|
||||
}
|
||||
}
|
||||
this.vmEntityVO.setDetails(details);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,5 +112,7 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
|
|||
|
||||
List<HostVO> listAllHostsUpByZoneAndHypervisor(long zoneId, HypervisorType hypervisorType);
|
||||
|
||||
List<HostVO> listByHostCapability(Host.Type type, Long clusterId, Long podId, long dcId, String hostCapabilty);
|
||||
|
||||
List<HostVO> listByClusterAndHypervisorType(long clusterId, HypervisorType hypervisorType);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ import com.cloud.dc.dao.ClusterDao;
|
|||
import com.cloud.gpu.dao.HostGpuGroupsDao;
|
||||
import com.cloud.gpu.dao.VGPUTypesDao;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.DetailVO;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.host.HostTagVO;
|
||||
import com.cloud.host.HostVO;
|
||||
|
|
@ -1222,6 +1223,39 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<HostVO> listByHostCapability(Type type, Long clusterId, Long podId, long dcId, String hostCapabilty) {
|
||||
SearchBuilder<DetailVO> hostCapabilitySearch = _detailsDao.createSearchBuilder();
|
||||
DetailVO tagEntity = hostCapabilitySearch.entity();
|
||||
hostCapabilitySearch.and("capability", tagEntity.getName(), SearchCriteria.Op.EQ);
|
||||
hostCapabilitySearch.and("value", tagEntity.getValue(), SearchCriteria.Op.EQ);
|
||||
|
||||
SearchBuilder<HostVO> hostSearch = createSearchBuilder();
|
||||
HostVO entity = hostSearch.entity();
|
||||
hostSearch.and("type", entity.getType(), SearchCriteria.Op.EQ);
|
||||
hostSearch.and("pod", entity.getPodId(), SearchCriteria.Op.EQ);
|
||||
hostSearch.and("dc", entity.getDataCenterId(), SearchCriteria.Op.EQ);
|
||||
hostSearch.and("cluster", entity.getClusterId(), SearchCriteria.Op.EQ);
|
||||
hostSearch.and("status", entity.getStatus(), SearchCriteria.Op.EQ);
|
||||
hostSearch.and("resourceState", entity.getResourceState(), SearchCriteria.Op.EQ);
|
||||
hostSearch.join("hostCapabilitySearch", hostCapabilitySearch, entity.getId(), tagEntity.getHostId(), JoinBuilder.JoinType.INNER);
|
||||
|
||||
SearchCriteria<HostVO> sc = hostSearch.create();
|
||||
sc.setJoinParameters("hostCapabilitySearch", "value", Boolean.toString(true));
|
||||
sc.setJoinParameters("hostCapabilitySearch", "capability", hostCapabilty);
|
||||
sc.setParameters("type", type.toString());
|
||||
if (podId != null) {
|
||||
sc.setParameters("pod", podId);
|
||||
}
|
||||
if (clusterId != null) {
|
||||
sc.setParameters("cluster", clusterId);
|
||||
}
|
||||
sc.setParameters("dc", dcId);
|
||||
sc.setParameters("status", Status.Up.toString());
|
||||
sc.setParameters("resourceState", ResourceState.Enabled.toString());
|
||||
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
public List<HostVO> listByClusterAndHypervisorType(long clusterId, HypervisorType hypervisorType) {
|
||||
SearchCriteria<HostVO> sc = ClusterHypervisorSearch.create();
|
||||
sc.setParameters("clusterId", clusterId);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ import com.cloud.exception.InsufficientServerCapacityException;
|
|||
import com.cloud.gpu.dao.HostGpuGroupsDao;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.host.dao.HostDetailsDao;
|
||||
import com.cloud.host.dao.HostTagsDao;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
|
|
@ -573,6 +574,10 @@ public class ImplicitPlannerTest {
|
|||
return Mockito.mock(DataStoreManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HostDetailsDao hostDetailsDao() { return Mockito.mock(HostDetailsDao.class); }
|
||||
|
||||
|
||||
@Bean
|
||||
public ClusterDetailsDao clusterDetailsDao() {
|
||||
return Mockito.mock(ClusterDetailsDao.class);
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
private String _dcId;
|
||||
private String _pod;
|
||||
private String _clusterId;
|
||||
private final Properties _uefiProperties = new Properties();
|
||||
|
||||
private long _hvVersion;
|
||||
private Duration _timeout;
|
||||
|
|
@ -497,7 +498,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
public StorageSubsystemCommandHandler getStorageHandler() {
|
||||
return storageHandler;
|
||||
}
|
||||
|
||||
private static final class KeyValueInterpreter extends OutputInterpreter {
|
||||
private final Map<String, String> map = new HashMap<String, String>();
|
||||
|
||||
|
|
@ -628,6 +628,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
loadUefiProperties();
|
||||
} catch (FileNotFoundException e) {
|
||||
s_logger.error("uefi properties file not found due to: " + e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
_storage = new JavaStorageLayer();
|
||||
_storage.configure("StorageLayer", params);
|
||||
|
|
@ -1150,6 +1155,31 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
return true;
|
||||
}
|
||||
|
||||
private void loadUefiProperties() throws FileNotFoundException {
|
||||
|
||||
if (_uefiProperties != null && _uefiProperties.getProperty("guest.loader.legacy") != null) {
|
||||
return;
|
||||
}
|
||||
final File file = PropertiesUtil.findConfigFile("uefi.properties");
|
||||
if (file == null) {
|
||||
throw new FileNotFoundException("Unable to find file uefi.properties.");
|
||||
}
|
||||
|
||||
s_logger.info("uefi.properties file found at " + file.getAbsolutePath());
|
||||
try {
|
||||
PropertiesUtil.loadFromFile(_uefiProperties, file);
|
||||
s_logger.info("guest.nvram.template.legacy = " + _uefiProperties.getProperty("guest.nvram.template.legacy"));
|
||||
s_logger.info("guest.loader.legacy = " + _uefiProperties.getProperty("guest.loader.legacy"));
|
||||
s_logger.info("guest.nvram.template.secure = " + _uefiProperties.getProperty("guest.nvram.template.secure"));
|
||||
s_logger.info("guest.loader.secure =" + _uefiProperties.getProperty("guest.loader.secure"));
|
||||
s_logger.info("guest.nvram.path = " + _uefiProperties.getProperty("guest.nvram.path"));
|
||||
} catch (final FileNotFoundException ex) {
|
||||
throw new CloudRuntimeException("Cannot find the file: " + file.getAbsolutePath(), ex);
|
||||
} catch (final IOException ex) {
|
||||
throw new CloudRuntimeException("IOException in reading " + file.getAbsolutePath(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected void configureDiskActivityChecks(final Map<String, Object> params) {
|
||||
_diskActivityCheckEnabled = Boolean.parseBoolean((String)params.get("vm.diskactivity.checkenabled"));
|
||||
if (_diskActivityCheckEnabled) {
|
||||
|
|
@ -2106,6 +2136,18 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
vm.setDomDescription(vmTO.getOs());
|
||||
vm.setPlatformEmulator(vmTO.getPlatformEmulator());
|
||||
|
||||
Map<String, String> customParams = vmTO.getDetails();
|
||||
boolean isUefiEnabled = false;
|
||||
boolean isSecureBoot = false;
|
||||
String bootMode =null;
|
||||
if (MapUtils.isNotEmpty(customParams) && customParams.containsKey(GuestDef.BootType.UEFI.toString())) {
|
||||
isUefiEnabled = true;
|
||||
bootMode = customParams.get(GuestDef.BootType.UEFI.toString());
|
||||
if (StringUtils.isNotBlank(bootMode) && "secure".equalsIgnoreCase(bootMode)) {
|
||||
isSecureBoot = true;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String> extraConfig = vmTO.getExtraConfig();
|
||||
if (dpdkSupport && (!extraConfig.containsKey(DpdkHelper.DPDK_NUMA) || !extraConfig.containsKey(DpdkHelper.DPDK_HUGE_PAGES))) {
|
||||
s_logger.info("DPDK is enabled but it needs extra configurations for CPU NUMA and Huge Pages for VM deployment");
|
||||
|
|
@ -2125,11 +2167,44 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
}
|
||||
guest.setGuestArch(_guestCpuArch != null ? _guestCpuArch : vmTO.getArch());
|
||||
guest.setMachineType(_guestCpuArch != null && _guestCpuArch.equals("aarch64") ? "virt" : "pc");
|
||||
guest.setBootType(GuestDef.BootType.BIOS);
|
||||
if (MapUtils.isNotEmpty(customParams) && customParams.containsKey(GuestDef.BootType.UEFI.toString())) {
|
||||
guest.setBootType(GuestDef.BootType.UEFI);
|
||||
guest.setBootMode(GuestDef.BootMode.LEGACY);
|
||||
if (StringUtils.isNotBlank(customParams.get(GuestDef.BootType.UEFI.toString())) && "secure".equalsIgnoreCase(customParams.get(GuestDef.BootType.UEFI.toString()))) {
|
||||
guest.setMachineType("q35");
|
||||
guest.setBootMode(GuestDef.BootMode.SECURE); // setting to secure mode
|
||||
}
|
||||
}
|
||||
guest.setUuid(uuid);
|
||||
guest.setBootOrder(GuestDef.BootOrder.CDROM);
|
||||
guest.setBootOrder(GuestDef.BootOrder.HARDISK);
|
||||
|
||||
vm.addComp(guest);
|
||||
if (isUefiEnabled) {
|
||||
if (_uefiProperties.getProperty(GuestDef.GUEST_LOADER_SECURE) != null && "secure".equalsIgnoreCase(bootMode)) {
|
||||
guest.setLoader(_uefiProperties.getProperty(GuestDef.GUEST_LOADER_SECURE));
|
||||
}
|
||||
|
||||
if (_uefiProperties.getProperty(GuestDef.GUEST_LOADER_LEGACY) != null && "legacy".equalsIgnoreCase(bootMode)) {
|
||||
guest.setLoader(_uefiProperties.getProperty(GuestDef.GUEST_LOADER_LEGACY));
|
||||
}
|
||||
|
||||
if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_PATH) != null) {
|
||||
guest.setNvram(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_PATH));
|
||||
}
|
||||
|
||||
if (isSecureBoot) {
|
||||
if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE) != null && "secure".equalsIgnoreCase(bootMode)) {
|
||||
guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE));
|
||||
}
|
||||
} else {
|
||||
if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY) != null) {
|
||||
guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vm.addComp(guest);
|
||||
|
||||
final GuestResourceDef grd = new GuestResourceDef();
|
||||
|
||||
|
|
@ -2189,6 +2264,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
features.addFeatures("pae");
|
||||
features.addFeatures("apic");
|
||||
features.addFeatures("acpi");
|
||||
if (isUefiEnabled && isSecureMode(customParams.get(GuestDef.BootType.UEFI.toString()))) {
|
||||
features.addFeatures("smm");
|
||||
}
|
||||
|
||||
//KVM hyperv enlightenment features based on OS Type
|
||||
enlightenWindowsVm(vmTO, features);
|
||||
|
|
@ -2329,7 +2407,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
}
|
||||
|
||||
public void createVbd(final Connect conn, final VirtualMachineTO vmSpec, final String vmName, final LibvirtVMDef vm) throws InternalErrorException, LibvirtException, URISyntaxException {
|
||||
final Map<String, String> details = vmSpec.getDetails();
|
||||
final List<DiskTO> disks = Arrays.asList(vmSpec.getDisks());
|
||||
boolean isSecureBoot = false;
|
||||
boolean isWindowsTemplate = false;
|
||||
Collections.sort(disks, new Comparator<DiskTO>() {
|
||||
@Override
|
||||
public int compare(final DiskTO arg0, final DiskTO arg1) {
|
||||
|
|
@ -2337,6 +2418,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
}
|
||||
});
|
||||
|
||||
if (MapUtils.isNotEmpty(details) && details.containsKey(GuestDef.BootType.UEFI.toString())) {
|
||||
isSecureBoot = isSecureMode(details.get(GuestDef.BootType.UEFI.toString()));
|
||||
}
|
||||
if (vmSpec.getOs().toLowerCase().contains("window")) {
|
||||
isWindowsTemplate =true;
|
||||
}
|
||||
for (final DiskTO volume : disks) {
|
||||
KVMPhysicalDisk physicalDisk = null;
|
||||
KVMStoragePool pool = null;
|
||||
|
|
@ -2397,8 +2484,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
int devId = volume.getDiskSeq().intValue();
|
||||
if (volume.getType() == Volume.Type.ISO) {
|
||||
if (volPath == null) {
|
||||
/* Add iso as placeholder */
|
||||
disk.defISODisk(null, devId);
|
||||
if (isSecureBoot) {
|
||||
disk.defISODisk(null, devId,isSecureBoot,isWindowsTemplate);
|
||||
} else {
|
||||
/* Add iso as placeholder */
|
||||
disk.defISODisk(null, devId);
|
||||
}
|
||||
} else {
|
||||
disk.defISODisk(volPath, devId);
|
||||
}
|
||||
|
|
@ -2436,7 +2527,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
if (volume.getType() == Volume.Type.DATADISK) {
|
||||
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData, DiskDef.DiskFmtType.QCOW2);
|
||||
} else {
|
||||
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.DiskFmtType.QCOW2);
|
||||
if (isSecureBoot) {
|
||||
disk.defFileBasedDisk(physicalDisk.getPath(), devId, DiskDef.DiskFmtType.QCOW2, isWindowsTemplate);
|
||||
} else {
|
||||
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.DiskFmtType.QCOW2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4052,4 +4147,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isSecureMode(String bootMode) {
|
||||
if (StringUtils.isNotBlank(bootMode) && "secure".equalsIgnoreCase(bootMode)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,39 @@ public class LibvirtVMDef {
|
|||
}
|
||||
}
|
||||
|
||||
enum BootType {
|
||||
UEFI("UEFI"), BIOS("BIOS");
|
||||
|
||||
String _type;
|
||||
|
||||
BootType(String type) {
|
||||
_type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return _type;
|
||||
}
|
||||
}
|
||||
|
||||
enum BootMode {
|
||||
LEGACY("LEGACY"), SECURE("SECURE");
|
||||
|
||||
String _mode;
|
||||
|
||||
BootMode(String mode) {
|
||||
_mode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return _mode;
|
||||
}
|
||||
}
|
||||
|
||||
private GuestType _type;
|
||||
private BootType _boottype;
|
||||
private BootMode _bootmode;
|
||||
private String _arch;
|
||||
private String _loader;
|
||||
private String _kernel;
|
||||
|
|
@ -67,6 +99,14 @@ public class LibvirtVMDef {
|
|||
private String _uuid;
|
||||
private final List<BootOrder> _bootdevs = new ArrayList<BootOrder>();
|
||||
private String _machine;
|
||||
private String _nvram;
|
||||
private String _nvramTemplate;
|
||||
|
||||
public static final String GUEST_LOADER_SECURE = "guest.loader.secure";
|
||||
public static final String GUEST_LOADER_LEGACY = "guest.loader.legacy";
|
||||
public static final String GUEST_NVRAM_PATH = "guest.nvram.path";
|
||||
public static final String GUEST_NVRAM_TEMPLATE_SECURE = "guest.nvram.template.secure";
|
||||
public static final String GUEST_NVRAM_TEMPLATE_LEGACY = "guest.nvram.template.legacy";
|
||||
|
||||
public void setGuestType(GuestType type) {
|
||||
_type = type;
|
||||
|
|
@ -76,6 +116,10 @@ public class LibvirtVMDef {
|
|||
return _type;
|
||||
}
|
||||
|
||||
public void setNvram(String nvram) { _nvram = nvram; }
|
||||
|
||||
public void setNvramTemplate(String nvramTemplate) { _nvramTemplate = nvramTemplate; }
|
||||
|
||||
public void setGuestArch(String arch) {
|
||||
_arch = arch;
|
||||
}
|
||||
|
|
@ -103,6 +147,22 @@ public class LibvirtVMDef {
|
|||
_uuid = uuid;
|
||||
}
|
||||
|
||||
public BootType getBootType() {
|
||||
return _boottype;
|
||||
}
|
||||
|
||||
public void setBootType(BootType boottype) {
|
||||
this._boottype = boottype;
|
||||
}
|
||||
|
||||
public BootMode getBootMode() {
|
||||
return _bootmode;
|
||||
}
|
||||
|
||||
public void setBootMode(BootMode bootmode) {
|
||||
this._bootmode = bootmode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (_type == GuestType.KVM) {
|
||||
|
|
@ -128,6 +188,24 @@ public class LibvirtVMDef {
|
|||
if (_arch != null && _arch.equals("aarch64")) {
|
||||
guestDef.append("<loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>\n");
|
||||
}
|
||||
if (_loader != null) {
|
||||
if (_bootmode == BootMode.LEGACY) {
|
||||
guestDef.append("<loader readonly='yes' secure='no' type='pflash'>" + _loader + "</loader>\n");
|
||||
} else if (_bootmode == BootMode.SECURE) {
|
||||
guestDef.append("<loader readonly='yes' secure='yes' type='pflash'>" + _loader + "</loader>\n");
|
||||
}
|
||||
}
|
||||
if (_nvram != null) {
|
||||
guestDef.append("<nvram ");
|
||||
if (_nvramTemplate != null) {
|
||||
guestDef.append("template='" + _nvramTemplate + "'>");
|
||||
} else {
|
||||
guestDef.append(">");
|
||||
}
|
||||
|
||||
guestDef.append(_nvram);
|
||||
guestDef.append(_uuid + ".fd</nvram>");
|
||||
}
|
||||
if (!_bootdevs.isEmpty()) {
|
||||
for (BootOrder bo : _bootdevs) {
|
||||
guestDef.append("<boot dev='" + bo + "'/>\n");
|
||||
|
|
@ -276,7 +354,11 @@ public class LibvirtVMDef {
|
|||
StringBuilder feaBuilder = new StringBuilder();
|
||||
feaBuilder.append("<features>\n");
|
||||
for (String feature : _features) {
|
||||
feaBuilder.append("<" + feature + "/>\n");
|
||||
if (feature.equalsIgnoreCase("smm")) {
|
||||
feaBuilder.append("<" + feature + " state=\'on\' " + "/>\n");
|
||||
} else {
|
||||
feaBuilder.append("<" + feature + "/>\n");
|
||||
}
|
||||
}
|
||||
if (hyperVEnlightenmentFeatureDef != null) {
|
||||
String hpervF = hyperVEnlightenmentFeatureDef.toString();
|
||||
|
|
@ -508,7 +590,7 @@ public class LibvirtVMDef {
|
|||
}
|
||||
|
||||
public enum DiskBus {
|
||||
IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML("uml"), FDC("fdc");
|
||||
IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML("uml"), FDC("fdc"), SATA("sata");
|
||||
String _bus;
|
||||
|
||||
DiskBus(String bus) {
|
||||
|
|
@ -633,13 +715,17 @@ public class LibvirtVMDef {
|
|||
return "sd" + getDevLabelSuffix(devId);
|
||||
} else if (bus == DiskBus.VIRTIO) {
|
||||
return "vd" + getDevLabelSuffix(devId);
|
||||
} else if (bus == DiskBus.SATA){
|
||||
if (!forIso) {
|
||||
return "sda";
|
||||
}
|
||||
}
|
||||
if (forIso) {
|
||||
devId --;
|
||||
} else if(devId >= 2) {
|
||||
devId += 2;
|
||||
}
|
||||
return "hd" + getDevLabelSuffix(devId);
|
||||
return (DiskBus.SATA == bus) ? "sdb" : "hd" + getDevLabelSuffix(devId);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -671,6 +757,23 @@ public class LibvirtVMDef {
|
|||
|
||||
}
|
||||
|
||||
public void defFileBasedDisk(String filePath, int devId, DiskFmtType diskFmtType,boolean isWindowsOS) {
|
||||
|
||||
_diskType = DiskType.FILE;
|
||||
_deviceType = DeviceType.DISK;
|
||||
_diskCacheMode = DiskCacheMode.NONE;
|
||||
_sourcePath = filePath;
|
||||
_diskFmtType = diskFmtType;
|
||||
|
||||
if (isWindowsOS) {
|
||||
_diskLabel = getDevLabel(devId, DiskBus.SATA, false); // Windows Secure VM
|
||||
_bus = DiskBus.SATA;
|
||||
} else {
|
||||
_diskLabel = getDevLabel(devId, DiskBus.VIRTIO, false); // Linux Secure VM
|
||||
_bus = DiskBus.VIRTIO;
|
||||
}
|
||||
}
|
||||
|
||||
public void defISODisk(String volPath) {
|
||||
_diskType = DiskType.FILE;
|
||||
_deviceType = DeviceType.CDROM;
|
||||
|
|
@ -695,6 +798,26 @@ public class LibvirtVMDef {
|
|||
}
|
||||
}
|
||||
|
||||
public void defISODisk(String volPath, Integer devId,boolean isSecure, boolean isWindowOs) {
|
||||
if (!isSecure) {
|
||||
defISODisk(volPath, devId);
|
||||
} else {
|
||||
_diskType = DiskType.FILE;
|
||||
_deviceType = DeviceType.CDROM;
|
||||
_sourcePath = volPath;
|
||||
if (isWindowOs) {
|
||||
_diskLabel = getDevLabel(devId, DiskBus.SATA, true);
|
||||
_bus = DiskBus.SATA;
|
||||
} else {
|
||||
_diskLabel = getDevLabel(devId, DiskBus.SCSI, true);
|
||||
_bus = DiskBus.SCSI;
|
||||
}
|
||||
_diskFmtType = DiskFmtType.RAW;
|
||||
_diskCacheMode = DiskCacheMode.NONE;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void defBlockBasedDisk(String diskName, int devId, DiskBus bus) {
|
||||
_diskType = DiskType.BLOCK;
|
||||
_deviceType = DeviceType.DISK;
|
||||
|
|
|
|||
|
|
@ -294,6 +294,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
|
|||
}
|
||||
}
|
||||
|
||||
details.put(VmDetailConstants.BOOT_MODE, to.getBootType());
|
||||
String diskDeviceType = details.get(VmDetailConstants.ROOT_DISK_CONTROLLER);
|
||||
if (userVm) {
|
||||
if (diskDeviceType == null) {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import com.cloud.exception.DiscoveredWithErrorException;
|
|||
import com.cloud.exception.DiscoveryException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceInUseException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
|
|
@ -367,6 +368,10 @@ public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer
|
|||
details.put("url", hostMo.getHostName());
|
||||
details.put("username", username);
|
||||
details.put("password", password);
|
||||
boolean uefiLegacySupported = hostMo.isUefiLegacySupported();
|
||||
if (uefiLegacySupported) {
|
||||
details.put(Host.HOST_UEFI_ENABLE, "true");
|
||||
}
|
||||
String guid = morHost.getType() + ":" + morHost.getValue() + "@" + url.getHost();
|
||||
details.put("guid", guid);
|
||||
|
||||
|
|
|
|||
|
|
@ -318,6 +318,7 @@ import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
|
|||
import com.vmware.vim25.VirtualEthernetCardOpaqueNetworkBackingInfo;
|
||||
import com.vmware.vim25.VirtualIDEController;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualMachineBootOptions;
|
||||
import com.vmware.vim25.VirtualMachineFileInfo;
|
||||
import com.vmware.vim25.VirtualMachineFileLayoutEx;
|
||||
import com.vmware.vim25.VirtualMachineFileLayoutExFileInfo;
|
||||
|
|
@ -1723,6 +1724,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
String dataDiskController = vmSpec.getDetails().get(VmDetailConstants.DATA_DISK_CONTROLLER);
|
||||
String rootDiskController = vmSpec.getDetails().get(VmDetailConstants.ROOT_DISK_CONTROLLER);
|
||||
DiskTO rootDiskTO = null;
|
||||
String bootMode = ApiConstants.BootType.BIOS.toString();
|
||||
if (vmSpec.getDetails().containsKey(VmDetailConstants.BOOT_MODE)) {
|
||||
bootMode = vmSpec.getDetails().get(VmDetailConstants.BOOT_MODE);
|
||||
}
|
||||
|
||||
// If root disk controller is scsi, then data disk controller would also be scsi instead of using 'osdefault'
|
||||
// This helps avoid mix of different scsi subtype controllers in instance.
|
||||
if (DiskControllerType.osdefault == DiskControllerType.getType(dataDiskController) && DiskControllerType.lsilogic == DiskControllerType.getType(rootDiskController)) {
|
||||
|
|
@ -2280,6 +2286,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
}
|
||||
}
|
||||
|
||||
if (!bootMode.equalsIgnoreCase(ApiConstants.BootType.BIOS.toString())) {
|
||||
vmConfigSpec.setFirmware("efi");
|
||||
if (vmSpec.getDetails().containsKey(ApiConstants.BootType.UEFI.toString()) && "secure".equalsIgnoreCase(vmSpec.getDetails().get(ApiConstants.BootType.UEFI.toString()))) {
|
||||
VirtualMachineBootOptions bootOptions = new VirtualMachineBootOptions();
|
||||
bootOptions.setEfiSecureBootEnabled(true);
|
||||
vmConfigSpec.setBootOptions(bootOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Configure VM
|
||||
//
|
||||
|
|
@ -2772,6 +2788,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
private static void configCustomExtraOption(List<OptionValue> extraOptions, VirtualMachineTO vmSpec) {
|
||||
// we no longer to validation anymore
|
||||
for (Map.Entry<String, String> entry : vmSpec.getDetails().entrySet()) {
|
||||
if (entry.getKey().equalsIgnoreCase(VmDetailConstants.BOOT_MODE)) {
|
||||
continue;
|
||||
}
|
||||
OptionValue newVal = new OptionValue();
|
||||
newVal.setKey(entry.getKey());
|
||||
newVal.setValue(entry.getValue());
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ import com.cloud.utils.component.AdapterBase;
|
|||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.vm.UserVmDetailVO;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
|
||||
|
||||
/**
|
||||
* An allocator that tries to find a fit on a computing host. This allocator does not care whether or not the host supports routing.
|
||||
|
|
@ -92,6 +95,8 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
|||
CapacityManager _capacityMgr;
|
||||
@Inject
|
||||
CapacityDao _capacityDao;
|
||||
@Inject
|
||||
UserVmDetailsDao _userVmDetailsDao;
|
||||
|
||||
boolean _checkHvm = true;
|
||||
protected String _allocationAlgorithm = "random";
|
||||
|
|
@ -112,6 +117,16 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
|||
VMTemplateVO template = (VMTemplateVO)vmProfile.getTemplate();
|
||||
Account account = vmProfile.getOwner();
|
||||
|
||||
boolean isVMDeployedWithUefi = false;
|
||||
UserVmDetailVO userVmDetailVO = _userVmDetailsDao.findDetail(vmProfile.getId(), "UEFI");
|
||||
if(userVmDetailVO != null){
|
||||
if ("secure".equalsIgnoreCase(userVmDetailVO.getValue()) || "legacy".equalsIgnoreCase(userVmDetailVO.getValue())) {
|
||||
isVMDeployedWithUefi = true;
|
||||
}
|
||||
}
|
||||
s_logger.info(" Guest VM is requested with Cusotm[UEFI] Boot Type "+ isVMDeployedWithUefi);
|
||||
|
||||
|
||||
if (type == Host.Type.Storage) {
|
||||
// FirstFitAllocator should be used for user VMs only since it won't care whether the host is capable of routing or not
|
||||
return new ArrayList<Host>();
|
||||
|
|
@ -123,11 +138,20 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
|||
|
||||
String hostTagOnOffering = offering.getHostTag();
|
||||
String hostTagOnTemplate = template.getTemplateTag();
|
||||
String hostTagUefi = "UEFI";
|
||||
|
||||
boolean hasSvcOfferingTag = hostTagOnOffering != null ? true : false;
|
||||
boolean hasTemplateTag = hostTagOnTemplate != null ? true : false;
|
||||
|
||||
List<HostVO> clusterHosts = new ArrayList<HostVO>();
|
||||
List<HostVO> hostsMatchingUefiTag = new ArrayList<HostVO>();
|
||||
if(isVMDeployedWithUefi){
|
||||
hostsMatchingUefiTag = _hostDao.listByHostCapability(type, clusterId, podId, dcId, Host.HOST_UEFI_ENABLE);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Hosts with tag '" + hostTagUefi + "' are:" + hostsMatchingUefiTag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
|
||||
if (haVmTag != null) {
|
||||
|
|
@ -175,6 +199,10 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
|||
}
|
||||
}
|
||||
|
||||
if (isVMDeployedWithUefi) {
|
||||
clusterHosts.retainAll(hostsMatchingUefiTag);
|
||||
}
|
||||
|
||||
// add all hosts that we are not considering to the avoid list
|
||||
List<HostVO> allhostsInCluster = _hostDao.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId, null);
|
||||
allhostsInCluster.removeAll(clusterHosts);
|
||||
|
|
|
|||
|
|
@ -321,6 +321,15 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
(UserVmManager.DisplayVMOVFProperties.value() && userVmDetailVO.getName().startsWith(ApiConstants.OVF_PROPERTIES))) {
|
||||
resourceDetails.put(userVmDetailVO.getName(), userVmDetailVO.getValue());
|
||||
}
|
||||
if ((ApiConstants.BootType.UEFI.toString()).equalsIgnoreCase(userVmDetailVO.getName())) {
|
||||
userVmResponse.setBootType("Uefi");
|
||||
userVmResponse.setBootMode(userVmDetailVO.getValue().toLowerCase());
|
||||
|
||||
}
|
||||
}
|
||||
if (vmDetails.size() == 0) {
|
||||
userVmResponse.setBootType("Bios");
|
||||
userVmResponse.setBootMode("legacy");
|
||||
}
|
||||
// Remove blacklisted settings if user is not admin
|
||||
if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
|
||||
|
|
|
|||
|
|
@ -30,10 +30,12 @@ import java.util.TreeSet;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.fsm.StateMachine2;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupService;
|
||||
|
|
@ -271,6 +273,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
|
|||
}
|
||||
|
||||
String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
|
||||
String uefiFlag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.UefiFlag);
|
||||
|
||||
if (plan.getHostId() != null && haVmTag == null) {
|
||||
Long hostIdSpecified = plan.getHostId();
|
||||
|
|
@ -278,6 +281,14 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
|
|||
s_logger.debug("DeploymentPlan has host_id specified, choosing this host and making no checks on this host: " + hostIdSpecified);
|
||||
}
|
||||
HostVO host = _hostDao.findById(hostIdSpecified);
|
||||
if (host != null && StringUtils.isNotBlank(uefiFlag) && "yes".equalsIgnoreCase(uefiFlag)) {
|
||||
_hostDao.loadDetails(host);
|
||||
if (MapUtils.isNotEmpty(host.getDetails()) && host.getDetails().containsKey(Host.HOST_UEFI_ENABLE) && "false".equalsIgnoreCase(host.getDetails().get(Host.HOST_UEFI_ENABLE))) {
|
||||
s_logger.debug("Cannot deploy to specified host as host does n't support uefi vm deployment, returning.");
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
if (host == null) {
|
||||
s_logger.debug("The specified host cannot be found");
|
||||
} else if (avoids.shouldAvoid(host)) {
|
||||
|
|
|
|||
|
|
@ -68,12 +68,15 @@ import com.cloud.vm.VirtualMachineProfile;
|
|||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.host.dao.HostDetailsDao;
|
||||
|
||||
public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPlanner, Configurable, DeploymentPlanner {
|
||||
private static final Logger s_logger = Logger.getLogger(FirstFitPlanner.class);
|
||||
@Inject
|
||||
protected HostDao hostDao;
|
||||
@Inject
|
||||
protected HostDetailsDao hostDetailsDao;
|
||||
@Inject
|
||||
protected DataCenterDao dcDao;
|
||||
@Inject
|
||||
protected HostPodDao podDao;
|
||||
|
|
@ -187,8 +190,16 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla
|
|||
|
||||
if (clusterList != null && !clusterList.isEmpty()) {
|
||||
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||
boolean nonUefiVMDeploy =false;
|
||||
if (vmProfile.getParameters().containsKey(VirtualMachineProfile.Param.BootType)) {
|
||||
if (vmProfile.getParameters().get(VirtualMachineProfile.Param.BootType).toString().equalsIgnoreCase("BIOS")) {
|
||||
nonUefiVMDeploy = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// In case of non-GPU VMs, protect GPU enabled Hosts and prefer VM deployment on non-GPU Hosts.
|
||||
if ((serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString()) == null) && !(hostGpuGroupsDao.listHostIds().isEmpty())) {
|
||||
if (((serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString()) == null) && !(hostGpuGroupsDao.listHostIds().isEmpty())) || nonUefiVMDeploy) {
|
||||
int requiredCpu = offering.getCpu() * offering.getSpeed();
|
||||
long requiredRam = offering.getRamSize() * 1024L * 1024L;
|
||||
reorderClustersBasedOnImplicitTags(clusterList, requiredCpu, requiredRam);
|
||||
|
|
@ -205,7 +216,8 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla
|
|||
List<Long> hostList = capacityDao.listHostsWithEnoughCapacity(requiredCpu, requiredRam, clusterId, Host.Type.Routing.toString());
|
||||
if (!hostList.isEmpty() && implicitHostTags.length > 0) {
|
||||
uniqueTags = new Long(hostTagsDao.getDistinctImplicitHostTags(hostList, implicitHostTags).size());
|
||||
}
|
||||
uniqueTags = uniqueTags + getHostsByCapability(hostList, Host.HOST_UEFI_ENABLE);
|
||||
}
|
||||
UniqueTagsInClusterMap.put(clusterId, uniqueTags);
|
||||
}
|
||||
Collections.sort(clusterList, new Comparator<Long>() {
|
||||
|
|
@ -218,6 +230,19 @@ public class FirstFitPlanner extends AdapterBase implements DeploymentClusterPla
|
|||
});
|
||||
}
|
||||
|
||||
private Long getHostsByCapability(List<Long> hostList, String hostCapability) {
|
||||
for (Long host : hostList) { //TODO: Fix this in single query instead of polling request for each Host
|
||||
Map<String, String> details = hostDetailsDao.findDetails(host);
|
||||
if (details.containsKey(Host.HOST_UEFI_ENABLE)) {
|
||||
if (details.get(Host.HOST_UEFI_ENABLE).equalsIgnoreCase("Yes")) {
|
||||
return new Long(1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return new Long(0);
|
||||
}
|
||||
|
||||
private List<Long> scanPodsForDestination(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) {
|
||||
|
||||
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ import java.util.UUID;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.network.dao.NetworkDetailVO;
|
||||
import com.cloud.network.dao.NetworkDetailsDao;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.backup.Backup;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
|
|
@ -37,6 +35,8 @@ import com.cloud.agent.api.to.VirtualMachineTO;
|
|||
import com.cloud.gpu.GPU;
|
||||
import com.cloud.network.Networks.BroadcastDomainType;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.dao.NetworkDetailVO;
|
||||
import com.cloud.network.dao.NetworkDetailsDao;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
|
|
@ -47,6 +47,7 @@ import com.cloud.service.dao.ServiceOfferingDao;
|
|||
import com.cloud.service.dao.ServiceOfferingDetailsDao;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.component.AdapterBase;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.NicVO;
|
||||
|
|
@ -171,6 +172,11 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
|
|||
offering.getRamSize() * 1024l * 1024l, null, null, vm.isHaEnabled(), vm.limitCpuUse(), vm.getVncPassword());
|
||||
to.setBootArgs(vmProfile.getBootArgs());
|
||||
|
||||
String bootType = (String)vmProfile.getParameter(new VirtualMachineProfile.Param("BootType"));
|
||||
if (StringUtils.isNotBlank(bootType)) {
|
||||
to.setBootType(bootType);
|
||||
}
|
||||
|
||||
List<NicProfile> nicProfiles = vmProfile.getNics();
|
||||
NicTO[] nics = new NicTO[nicProfiles.size()];
|
||||
int i = 0;
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements
|
|||
@Override
|
||||
public Map<? extends ServerResource, Map<String, String>>
|
||||
find(long dcId, Long podId, Long clusterId, URI uri, String username, String password, List<String> hostTags) throws DiscoveryException {
|
||||
boolean isUefiSupported = false;
|
||||
|
||||
ClusterVO cluster = _clusterDao.findById(clusterId);
|
||||
if (cluster == null || cluster.getHypervisorType() != getHypervisorType()) {
|
||||
|
|
@ -256,6 +257,11 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements
|
|||
return null;
|
||||
}
|
||||
|
||||
if (SSHCmdHelper.sshExecuteCmd(sshConnection, "rpm -qa | grep -i ovmf", 3)) {
|
||||
s_logger.debug("It's UEFI enabled KVM machine");
|
||||
isUefiSupported = true;
|
||||
}
|
||||
|
||||
List<PhysicalNetworkSetupInfo> netInfos = _networkMgr.getPhysicalNetworkInfo(dcId, getHypervisorType());
|
||||
String kvmPrivateNic = null;
|
||||
String kvmPublicNic = null;
|
||||
|
|
@ -338,6 +344,7 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements
|
|||
Map<String, String> hostDetails = connectedHost.getDetails();
|
||||
hostDetails.put("password", password);
|
||||
hostDetails.put("username", username);
|
||||
hostDetails.put(Host.HOST_UEFI_ENABLE, isUefiSupported == true ? Boolean.toString(true) : Boolean.toString(false));
|
||||
_hostDao.saveDetails(connectedHost);
|
||||
return resources;
|
||||
} catch (DiscoveredWithErrorException e) {
|
||||
|
|
|
|||
|
|
@ -709,6 +709,8 @@ import com.cloud.vm.dao.InstanceGroupDao;
|
|||
import com.cloud.vm.dao.SecondaryStorageVmDao;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.vm.UserVmDetailVO;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
|
||||
public class ManagementServerImpl extends ManagerBase implements ManagementServer, Configurable {
|
||||
public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName());
|
||||
|
|
@ -728,6 +730,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||
@Inject
|
||||
private ClusterDao _clusterDao;
|
||||
@Inject
|
||||
private UserVmDetailsDao _UserVmDetailsDao;
|
||||
@Inject
|
||||
private SecondaryStorageVmDao _secStorageVmDao;
|
||||
@Inject
|
||||
public EventDao _eventDao;
|
||||
|
|
@ -1191,6 +1195,16 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||
throw ex;
|
||||
}
|
||||
|
||||
UserVmDetailVO userVmDetailVO = _UserVmDetailsDao.findDetail(vm.getId(), ApiConstants.BootType.UEFI.toString());
|
||||
if (userVmDetailVO != null) {
|
||||
s_logger.info(" Live Migration of UEFI enabled VM : " + vm.getInstanceName() + " is not supported");
|
||||
if ("legacy".equalsIgnoreCase(userVmDetailVO.getValue()) || "secure".equalsIgnoreCase(userVmDetailVO.getValue())) {
|
||||
// Return empty list.
|
||||
return new Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Host, Boolean>>(new Pair<List<? extends Host>,
|
||||
Integer>(new ArrayList<HostVO>(), new Integer(0)), new ArrayList<Host>(), new HashMap<Host, Boolean>());
|
||||
}
|
||||
}
|
||||
|
||||
if (_serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
|
||||
s_logger.info(" Live Migration of GPU enabled VM : " + vm.getInstanceName() + " is not supported");
|
||||
// Return empty list.
|
||||
|
|
|
|||
|
|
@ -3963,6 +3963,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
} else {
|
||||
vm.setDetail(key, customParameters.get(key));
|
||||
}
|
||||
|
||||
if (key.equalsIgnoreCase(ApiConstants.BootType.UEFI.toString())) {
|
||||
vm.setDetail(key, customParameters.get(key));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
vm.setDetail(VmDetailConstants.DEPLOY_VM, "true");
|
||||
|
||||
|
|
@ -4282,13 +4287,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
Long podId = null;
|
||||
Long clusterId = null;
|
||||
Long hostId = cmd.getHostId();
|
||||
Map<VirtualMachineProfile.Param, Object> additonalParams = null;
|
||||
Map<Long, DiskOffering> diskOfferingMap = cmd.getDataDiskTemplateToDiskOfferingMap();
|
||||
if (cmd instanceof DeployVMCmdByAdmin) {
|
||||
DeployVMCmdByAdmin adminCmd = (DeployVMCmdByAdmin)cmd;
|
||||
podId = adminCmd.getPodId();
|
||||
clusterId = adminCmd.getClusterId();
|
||||
}
|
||||
return startVirtualMachine(vmId, podId, clusterId, hostId, diskOfferingMap, null, cmd.getDeploymentPlanner());
|
||||
if (MapUtils.isNotEmpty(cmd.getDetails()) && cmd.getDetails().containsKey(ApiConstants.BootType.UEFI.toString())) {
|
||||
additonalParams = new HashMap<VirtualMachineProfile.Param, Object>();
|
||||
Map<String, String> map = cmd.getDetails();
|
||||
additonalParams.put(VirtualMachineProfile.Param.UefiFlag, "Yes");
|
||||
additonalParams.put(VirtualMachineProfile.Param.BootType, ApiConstants.BootType.UEFI.toString());
|
||||
additonalParams.put(VirtualMachineProfile.Param.BootMode, map.get(ApiConstants.BootType.UEFI.toString()));
|
||||
}
|
||||
return startVirtualMachine(vmId, podId, clusterId, hostId, diskOfferingMap, additonalParams, cmd.getDeploymentPlanner());
|
||||
}
|
||||
|
||||
private UserVm startVirtualMachine(long vmId, Long podId, Long clusterId, Long hostId, Map<Long, DiskOffering> diskOfferingMap, Map<VirtualMachineProfile.Param, Object> additonalParams, String deploymentPlannerToUse)
|
||||
|
|
@ -4747,6 +4760,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
throw new InvalidParameterValueException("Can't find a planner by name " + deploymentPlannerToUse);
|
||||
}
|
||||
}
|
||||
vmEntity.setParamsToEntity(additionalParams);
|
||||
|
||||
String reservationId = vmEntity.reserve(planner, plan, new ExcludeList(), Long.toString(callerUser.getId()));
|
||||
vmEntity.deploy(reservationId, Long.toString(callerUser.getId()), params, deployOnGivenHost);
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ import com.cloud.utils.component.ComponentContext;
|
|||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.host.dao.HostDetailsDao;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
||||
|
|
@ -284,6 +285,12 @@ public class DeploymentPlanningManagerImplTest {
|
|||
return Mockito.mock(HostTagsDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HostDetailsDao hostDetailsDao() {
|
||||
return Mockito.mock(HostDetailsDao.class);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public ClusterDetailsDao clusterDetailsDao() {
|
||||
return Mockito.mock(ClusterDetailsDao.class);
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ import com.cloud.utils.component.ComponentContext;
|
|||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.host.dao.HostDetailsDao;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
||||
|
|
@ -109,6 +110,8 @@ public class FirstFitPlannerTest {
|
|||
@Inject
|
||||
UserVmDao vmDao;
|
||||
@Inject
|
||||
HostDetailsDao hostDetailsDao;
|
||||
@Inject
|
||||
UserVmDetailsDao vmDetailsDao;
|
||||
@Inject
|
||||
ConfigurationDao configDao;
|
||||
|
|
@ -355,6 +358,9 @@ public class FirstFitPlannerTest {
|
|||
return Mockito.mock(HostTagsDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HostDetailsDao hostDetailsDao() { return Mockito.mock(HostDetailsDao.class); }
|
||||
|
||||
@Bean
|
||||
public HostGpuGroupsDao hostGpuGroupsDao() {
|
||||
return Mockito.mock(HostGpuGroupsDao.class);
|
||||
|
|
|
|||
|
|
@ -480,6 +480,31 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UEFI Boot -->
|
||||
<div class="select" odd>
|
||||
<div class="name">
|
||||
<span><translate key="label.vm.boottype" /></span>
|
||||
</div>
|
||||
<div class="value">
|
||||
<select name="customboot" id="customboot">
|
||||
<option value="BIOS">BIOS</option>
|
||||
<option value="UEFI">UEFI</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="select field hide-if-unselected">
|
||||
<div class="name">
|
||||
<span><translate key="label.vm.bootmode" /></span>
|
||||
</div>
|
||||
<div class="value">
|
||||
<select name="bootmode" id="bootmode">
|
||||
<option value="LEGACY">LEGACY</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Zone -->
|
||||
<div class="select">
|
||||
<div class="name">
|
||||
|
|
|
|||
|
|
@ -893,6 +893,7 @@ var dictionary = {
|
|||
"label.host.name":"Host Name",
|
||||
"label.host.tag":"Host Tag",
|
||||
"label.host.tags":"Host Tags",
|
||||
"label.host.ueficapability":"UEFI Supported",
|
||||
"label.hosts":"Hosts",
|
||||
"label.hourly":"Hourly",
|
||||
"label.hvm":"HVM",
|
||||
|
|
@ -990,6 +991,8 @@ var dictionary = {
|
|||
"label.keep.colon":"Keep:",
|
||||
"label.key":"Key",
|
||||
"label.keyboard.language":"Keyboard language",
|
||||
"label.vm.boottype":"Boot Type",
|
||||
"label.vm.bootmode":"Boot Mode",
|
||||
"label.keyboard.type":"Keyboard type",
|
||||
"label.kubernetes.cluster":"Kubernetes cluster",
|
||||
"label.kubernetes.cluster.details":"Kubernetes cluster details",
|
||||
|
|
|
|||
|
|
@ -1399,6 +1399,18 @@
|
|||
keyboard : keyboard
|
||||
});
|
||||
}
|
||||
var boottype = args.data.customboot;
|
||||
if (boottype != null && boottype.length > 0) {
|
||||
$.extend(deployVmData, {
|
||||
boottype : boottype
|
||||
});
|
||||
}
|
||||
var bootmode = args.data.bootmode;
|
||||
if (bootmode != null && bootmode.length > 0) {
|
||||
$.extend(deployVmData, {
|
||||
bootmode : bootmode
|
||||
});
|
||||
}
|
||||
|
||||
if (g_hostid != null) {
|
||||
$.extend(deployVmData, {
|
||||
|
|
|
|||
|
|
@ -3322,6 +3322,12 @@
|
|||
},
|
||||
id: {
|
||||
label: 'label.id'
|
||||
},
|
||||
boottype: {
|
||||
label: 'label.vm.boottype'
|
||||
},
|
||||
bootmode: {
|
||||
label: 'label.vm.bootmode'
|
||||
}
|
||||
}],
|
||||
|
||||
|
|
|
|||
|
|
@ -18024,6 +18024,10 @@
|
|||
});
|
||||
}
|
||||
},
|
||||
ueficapability: {
|
||||
label:'label.host.ueficapability',
|
||||
converter: cloudStack.converters.toBooleanText
|
||||
},
|
||||
hahost: {
|
||||
label: 'label.ha.enabled',
|
||||
converter: cloudStack.converters.toBooleanText
|
||||
|
|
|
|||
|
|
@ -1392,6 +1392,50 @@
|
|||
$(this).closest('div.select').hide();
|
||||
}
|
||||
}
|
||||
|
||||
var uefi = function(bootType){
|
||||
var $bootmode = $step.find('select[name=bootmode]');
|
||||
|
||||
if(bootType.toLowerCase() == 'uefi' ){
|
||||
$bootmode.html('');
|
||||
var $option = $('<option>');
|
||||
var id = 'LEGACY';
|
||||
var description = 'LEGACY';
|
||||
|
||||
$option.attr('value', id);
|
||||
$option.html(description);
|
||||
$option.appendTo($bootmode);
|
||||
|
||||
var $option2 = $('<option>');
|
||||
var id2 = 'SECURE';
|
||||
var description2 = 'SECURE';
|
||||
|
||||
$option2.attr('value', id2);
|
||||
$option2.html(description2);
|
||||
$option2.appendTo($bootmode);
|
||||
|
||||
}
|
||||
|
||||
if(bootType.toLowerCase() == 'bios' ){
|
||||
$bootmode.html('');
|
||||
|
||||
var $option = $('<option>');
|
||||
var id = 'LEGACY';
|
||||
var description = 'LEGACY';
|
||||
|
||||
$option.attr('value', id);
|
||||
$option.html(description);
|
||||
$option.appendTo($bootmode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var $uefiselect = $step.find('select[name=customboot]');
|
||||
$uefiselect.unbind('change');
|
||||
$uefiselect.change(function(){
|
||||
uefi($uefiselect.val());
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1196,4 +1196,17 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
|||
}
|
||||
return morNetwork;
|
||||
}
|
||||
|
||||
public String getProductVersion() throws Exception {
|
||||
return getHostAboutInfo().getVersion();
|
||||
}
|
||||
|
||||
public boolean isUefiLegacySupported() throws Exception {
|
||||
String hostVersion = getProductVersion();
|
||||
if (hostVersion.compareTo(VmwareHelper.MIN_VERSION_UEFI_LEGACY) >= 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ public class VmwareHelper {
|
|||
public static final int MAX_IDE_CONTROLLER_COUNT = 2;
|
||||
public static final int MAX_ALLOWED_DEVICES_IDE_CONTROLLER = 2;
|
||||
public static final int MAX_ALLOWED_DEVICES_SCSI_CONTROLLER = 15;
|
||||
public static final String MIN_VERSION_UEFI_LEGACY = "5.5";
|
||||
|
||||
public static boolean isReservedScsiDeviceNumber(int deviceNumber) {
|
||||
return deviceNumber == 7;
|
||||
|
|
|
|||
Loading…
Reference in New Issue