Boot into hardware setup menu on Vmware (#4021)

This commit is contained in:
dahn 2020-06-11 13:47:20 +02:00 committed by GitHub
parent fbfab5b5eb
commit 0795cd430b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 888 additions and 559 deletions

View File

@ -65,6 +65,7 @@ public class VirtualMachineTO {
String uuid;
String bootType;
String bootMode;
boolean enterHardwareSetup;
DiskTO[] disks;
NicTO[] nics;
@ -393,4 +394,12 @@ public class VirtualMachineTO {
public String getBootMode() { return bootMode; }
public void setBootMode(String bootMode) { this.bootMode = bootMode; }
public boolean isEnterHardwareSetup() {
return enterHardwareSetup;
}
public void setEnterHardwareSetup(boolean enterHardwareSetup) {
this.enterHardwareSetup = enterHardwareSetup;
}
}

View File

@ -63,6 +63,7 @@ public interface VirtualMachineProfile {
public static final Param UefiFlag = new Param("UefiFlag");
public static final Param BootMode = new Param("BootMode");
public static final Param BootType = new Param("BootType");
public static final Param BootIntoSetup = new Param("enterHardwareSetup");
private String name;

View File

@ -805,8 +805,9 @@ 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 static final String BOOT_TYPE = "boottype";
public static final String BOOT_MODE = "bootmode";
public static final String BOOT_INTO_SETUP = "bootintosetup";
public enum BootType {
UEFI, BIOS;

View File

@ -113,12 +113,15 @@ 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]")
@Parameter(name = ApiConstants.BOOT_TYPE, type = CommandType.STRING, required = false, description = "Guest VM Boot option either custom[UEFI] or default boot [BIOS]", since = "4.14.0.0")
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")
@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", since = "4.14.0.0")
private String bootMode;
@Parameter(name = ApiConstants.BOOT_INTO_SETUP, type = CommandType.BOOLEAN, required = false, description = "Boot into hardware setup or not (ignored if startVm = false, only valid for vmware)", since = "4.15.0.0")
private Boolean bootIntoSetup;
//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,"
@ -281,15 +284,14 @@ 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 (ApiConstants.BootType.UEFI.equals(getBootType())) {
customparameterMap.put(getBootType().toString(), getBootMode().toString());
}
if (rootdisksize != null && !customparameterMap.containsKey("rootdisksize")) {
customparameterMap.put("rootdisksize", rootdisksize.toString());
}
return customparameterMap;
}
@ -577,6 +579,10 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
return copyImageTags == null ? false : copyImageTags;
}
public Boolean getBootIntoSetup() {
return bootIntoSetup;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -53,6 +53,9 @@ public class RebootVMCmd extends BaseAsyncCmd implements UserCmd {
required=true, description="The ID of the virtual machine")
private Long id;
@Parameter(name = ApiConstants.BOOT_INTO_SETUP, type = CommandType.BOOLEAN, required = false, description = "Boot into hardware setup menu or not", since = "4.15.0.0")
private Boolean bootIntoSetup;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -61,6 +64,10 @@ public class RebootVMCmd extends BaseAsyncCmd implements UserCmd {
return id;
}
public Boolean getBootIntoSetup() {
return bootIntoSetup;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -85,6 +85,9 @@ public class StartVMCmd extends BaseAsyncCmd implements UserCmd {
@Parameter(name = ApiConstants.DEPLOYMENT_PLANNER, type = CommandType.STRING, description = "Deployment planner to use for vm allocation. Available to ROOT admin only", since = "4.4", authorized = { RoleType.Admin })
private String deploymentPlanner;
@Parameter(name = ApiConstants.BOOT_INTO_SETUP, type = CommandType.BOOLEAN, required = false, description = "Boot into hardware setup menu or not", since = "4.15.0.0")
private Boolean bootIntoSetup;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
@ -105,6 +108,10 @@ public class StartVMCmd extends BaseAsyncCmd implements UserCmd {
return clusterId;
}
public Boolean getBootIntoSetup() {
return bootIntoSetup;
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////

View File

@ -503,14 +503,13 @@ public class HostResponse extends BaseResponse {
detailsCopy.remove("username");
detailsCopy.remove("password");
if(detailsCopy.containsKey(Host.HOST_UEFI_ENABLE)) {
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;
}

View File

@ -889,6 +889,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
if ( jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("start parameter value of %s == %s during dispatching",
VirtualMachineProfile.Param.BootIntoSetup.getName(),
(params == null?"<very null>":params.get(VirtualMachineProfile.Param.BootIntoSetup))));
}
// avoid re-entrance
VmWorkJobVO placeHolder = null;
final VirtualMachine vm = _vmDao.findByUuid(vmUuid);
@ -901,6 +906,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
}
} else {
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("start parameter value of %s == %s during processing of queued job",
VirtualMachineProfile.Param.BootIntoSetup.getName(),
(params == null?"<very null>":params.get(VirtualMachineProfile.Param.BootIntoSetup))));
}
final Outcome<VirtualMachine> outcome = startVmThroughJobQueue(vmUuid, params, planToDeploy, planner);
try {
@ -1064,10 +1074,7 @@ 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)
);
logBootModeParameters(params);
DeployDestination dest = null;
try {
dest = _dpMgr.planDeployment(vmProfile, plan, avoids, planner);
@ -1137,6 +1144,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
final VirtualMachineTO vmTO = hvGuru.implement(vmProfile);
checkAndSetEnterSetupMode(vmTO, params);
handlePath(vmTO.getDisks(), vm.getHypervisorType());
cmds = new Commands(Command.OnError.Stop);
@ -1315,6 +1324,30 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
}
private void logBootModeParameters(Map<VirtualMachineProfile.Param, Object> params) {
StringBuffer msgBuf = new StringBuffer("Uefi params ");
boolean log = false;
if (params.get(VirtualMachineProfile.Param.UefiFlag) != null) {
msgBuf.append(String.format("UefiFlag: %s ", params.get(VirtualMachineProfile.Param.UefiFlag)));
log = true;
}
if (params.get(VirtualMachineProfile.Param.BootType) != null) {
msgBuf.append(String.format("Boot Type: %s ", params.get(VirtualMachineProfile.Param.BootType)));
log = true;
}
if (params.get(VirtualMachineProfile.Param.BootMode) != null) {
msgBuf.append(String.format("Boot Mode: %s ", params.get(VirtualMachineProfile.Param.BootMode)));
log = true;
}
if (params.get(VirtualMachineProfile.Param.BootIntoSetup) != null) {
msgBuf.append(String.format("Boot into Setup: %s ", params.get(VirtualMachineProfile.Param.BootIntoSetup)));
log = true;
}
if (log) {
s_logger.info(msgBuf.toString());
}
}
// Add extra config data to the vmTO as a Map
private void addExtraConfig(VirtualMachineTO vmTO) {
Map<String, String> details = vmTO.getDetails();
@ -3094,6 +3127,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
final VirtualMachine vm = _vmDao.findByUuid(vmUuid);
placeHolder = createPlaceHolderWork(vm.getId());
try {
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("reboot parameter value of %s == %s at orchestration", VirtualMachineProfile.Param.BootIntoSetup.getName(),
(params == null? "<very null>":params.get(VirtualMachineProfile.Param.BootIntoSetup))));
}
orchestrateReboot(vmUuid, params);
} finally {
if (placeHolder != null) {
@ -3101,6 +3138,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
}
} else {
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("reboot parameter value of %s == %s through job-queue", VirtualMachineProfile.Param.BootIntoSetup.getName(),
(params == null? "<very null>":params.get(VirtualMachineProfile.Param.BootIntoSetup))));
}
final Outcome<VirtualMachine> outcome = rebootVmThroughJobQueue(vmUuid, params);
try {
@ -3150,7 +3191,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
final Commands cmds = new Commands(Command.OnError.Stop);
RebootCommand rebootCmd = new RebootCommand(vm.getInstanceName(), getExecuteInSequence(vm.getHypervisorType()));
rebootCmd.setVirtualMachine(getVmTO(vm.getId()));
VirtualMachineTO vmTo = getVmTO(vm.getId());
checkAndSetEnterSetupMode(vmTo, params);
rebootCmd.setVirtualMachine(vmTo);
cmds.addCommand(rebootCmd);
_agentMgr.send(host.getId(), cmds);
@ -3170,6 +3213,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
}
private void checkAndSetEnterSetupMode(VirtualMachineTO vmTo, Map<VirtualMachineProfile.Param, Object> params) {
Boolean enterSetup = (Boolean)params.get(VirtualMachineProfile.Param.BootIntoSetup);
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("orchestrating VM reboot for '%s' %s set to %s", vmTo.getName(), VirtualMachineProfile.Param.BootIntoSetup, enterSetup));
}
vmTo.setEnterHardwareSetup(enterSetup == null ? false : enterSetup);
}
protected VirtualMachineTO getVmTO(Long vmId) {
final VMInstanceVO vm = _vmDao.findById(vmId);
final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
@ -5223,6 +5274,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
assert vm != null;
Boolean enterSetup = (Boolean)work.getParams().get(VirtualMachineProfile.Param.BootIntoSetup);
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("orchestrating VM start for '%s' %s set to %s", vm.getInstanceName(), VirtualMachineProfile.Param.BootIntoSetup, enterSetup));
}
try{
orchestrateStart(vm.getUuid(), work.getParams(), work.getPlan(), _dpMgr.getDeploymentPlannerByName(work.getDeploymentPlanner()));
}

View File

@ -17,19 +17,15 @@
package com.cloud.hypervisor.guru;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.backup.Backup;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
@ -61,13 +57,11 @@ import com.cloud.agent.api.UnregisterVMCommand;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand;
import com.cloud.agent.api.storage.CreateVolumeOVACommand;
import com.cloud.agent.api.storage.OVFPropertyTO;
import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.cluster.ClusterManager;
@ -75,7 +69,6 @@ import com.cloud.configuration.Resource;
import com.cloud.dc.ClusterDetailsDao;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventUtils;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
@ -90,18 +83,13 @@ import com.cloud.hypervisor.vmware.dao.VmwareDatacenterDao;
import com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDao;
import com.cloud.hypervisor.vmware.manager.VmwareManager;
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
import com.cloud.hypervisor.vmware.mo.DiskControllerType;
import com.cloud.hypervisor.vmware.mo.NetworkMO;
import com.cloud.hypervisor.vmware.mo.VirtualDiskManagerMO;
import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
import com.cloud.hypervisor.vmware.mo.VirtualMachineDiskInfoBuilder;
import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
import com.cloud.hypervisor.vmware.resource.VmwareContextFactory;
import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.cloud.network.Network;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkModel;
import com.cloud.network.Networks;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.TrafficType;
@ -117,11 +105,9 @@ import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.GuestOSHypervisorVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.Storage;
import com.cloud.storage.StoragePool;
import com.cloud.storage.TemplateOVFPropertyVO;
import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateVO;
@ -129,20 +115,16 @@ import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.GuestOSHypervisorDao;
import com.cloud.storage.dao.TemplateOVFPropertiesDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.user.ResourceLimitService;
import com.cloud.utils.Pair;
import com.cloud.utils.UuidUtils;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.SecondaryStorageVmVO;
@ -152,8 +134,6 @@ import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
@ -172,373 +152,62 @@ import com.vmware.vim25.VirtualMachineRuntimeInfo;
public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Configurable {
private static final Logger s_logger = Logger.getLogger(VMwareGuru.class);
@Inject
private NetworkDao _networkDao;
@Inject
private GuestOSDao _guestOsDao;
@Inject
private GuestOSHypervisorDao _guestOsHypervisorDao;
@Inject
private HostDao _hostDao;
@Inject
private HostDetailsDao _hostDetailsDao;
@Inject
private ClusterDetailsDao _clusterDetailsDao;
@Inject
private CommandExecLogDao _cmdExecLogDao;
@Inject
private VmwareManager _vmwareMgr;
@Inject
private SecondaryStorageVmManager _secStorageMgr;
@Inject
private NetworkModel _networkMgr;
@Inject
private NicDao _nicDao;
@Inject
private DomainRouterDao _domainRouterDao;
@Inject
private PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao;
@Inject
private VMInstanceDao _vmDao;
@Inject
private VirtualMachineManager vmManager;
@Inject
private ClusterManager _clusterMgr;
@Inject
VolumeDao _volumeDao;
@Inject
ResourceLimitService _resourceLimitService;
@Inject
PrimaryDataStoreDao _storagePoolDao;
@Inject
VolumeDataFactory _volFactory;
@Inject
private VmwareDatacenterDao vmwareDatacenterDao;
@Inject
private VmwareDatacenterZoneMapDao vmwareDatacenterZoneMapDao;
@Inject
private ServiceOfferingDao serviceOfferingDao;
@Inject
private VMTemplatePoolDao templateStoragePoolDao;
@Inject
private VMTemplateDao vmTemplateDao;
@Inject
private UserVmDao userVmDao;
@Inject
private DiskOfferingDao diskOfferingDao;
@Inject
private PhysicalNetworkDao physicalNetworkDao;
@Inject
private TemplateOVFPropertiesDao templateOVFPropertiesDao;
@Inject VmwareVmImplementer vmwareVmImplementer;
@Inject NetworkDao _networkDao;
@Inject GuestOSDao _guestOsDao;
@Inject HostDao _hostDao;
@Inject HostDetailsDao _hostDetailsDao;
@Inject ClusterDetailsDao _clusterDetailsDao;
@Inject CommandExecLogDao _cmdExecLogDao;
@Inject VmwareManager _vmwareMgr;
@Inject SecondaryStorageVmManager _secStorageMgr;
@Inject NicDao _nicDao;
@Inject PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao;
@Inject VMInstanceDao _vmDao;
@Inject VirtualMachineManager vmManager;
@Inject ClusterManager _clusterMgr;
@Inject VolumeDao _volumeDao;
@Inject ResourceLimitService _resourceLimitService;
@Inject PrimaryDataStoreDao _storagePoolDao;
@Inject VolumeDataFactory _volFactory;
@Inject VmwareDatacenterDao vmwareDatacenterDao;
@Inject VmwareDatacenterZoneMapDao vmwareDatacenterZoneMapDao;
@Inject ServiceOfferingDao serviceOfferingDao;
@Inject VMTemplatePoolDao templateStoragePoolDao;
@Inject VMTemplateDao vmTemplateDao;
@Inject UserVmDao userVmDao;
@Inject DiskOfferingDao diskOfferingDao;
@Inject PhysicalNetworkDao physicalNetworkDao;
protected VMwareGuru() {
super();
}
public static final ConfigKey<Boolean> VmwareReserveCpu = new ConfigKey<Boolean>(Boolean.class, "vmware.reserve.cpu", "Advanced", "false",
"Specify whether or not to reserve CPU when deploying an instance.", true, ConfigKey.Scope.Cluster,
null);
"Specify whether or not to reserve CPU when deploying an instance.", true, ConfigKey.Scope.Cluster, null);
public static final ConfigKey<Boolean> VmwareReserveMemory = new ConfigKey<Boolean>(Boolean.class, "vmware.reserve.mem", "Advanced", "false",
"Specify whether or not to reserve memory when deploying an instance.", true,
ConfigKey.Scope.Cluster, null);
"Specify whether or not to reserve memory when deploying an instance.", true, ConfigKey.Scope.Cluster, null);
protected ConfigKey<Boolean> VmwareEnableNestedVirtualization = new ConfigKey<Boolean>(Boolean.class, "vmware.nested.virtualization", "Advanced", "false",
public static final ConfigKey<Boolean> VmwareEnableNestedVirtualization = new ConfigKey<Boolean>(Boolean.class, "vmware.nested.virtualization", "Advanced", "false",
"When set to true this will enable nested virtualization when this is supported by the hypervisor", true, ConfigKey.Scope.Global, null);
protected ConfigKey<Boolean> VmwareEnableNestedVirtualizationPerVM = new ConfigKey<Boolean>(Boolean.class, "vmware.nested.virtualization.perVM", "Advanced", "false",
public static final ConfigKey<Boolean> VmwareEnableNestedVirtualizationPerVM = new ConfigKey<Boolean>(Boolean.class, "vmware.nested.virtualization.perVM", "Advanced", "false",
"When set to true this will enable nested virtualization per vm", true, ConfigKey.Scope.Global, null);
@Override
public HypervisorType getHypervisorType() {
@Override public HypervisorType getHypervisorType() {
return HypervisorType.VMware;
}
@Override
public VirtualMachineTO implement(VirtualMachineProfile vm) {
VirtualMachineTO to = toVirtualMachineTO(vm);
to.setBootloader(BootloaderType.HVM);
Map<String, String> details = to.getDetails();
if (details == null)
details = new HashMap<String, String>();
Type vmType = vm.getType();
boolean userVm = !(vmType.equals(VirtualMachine.Type.DomainRouter) || vmType.equals(VirtualMachine.Type.ConsoleProxy)
|| vmType.equals(VirtualMachine.Type.SecondaryStorageVm));
String nicDeviceType = details.get(VmDetailConstants.NIC_ADAPTER);
if (!userVm) {
if (nicDeviceType == null) {
details.put(VmDetailConstants.NIC_ADAPTER, _vmwareMgr.getSystemVMDefaultNicAdapterType());
} else {
try {
VirtualEthernetCardType.valueOf(nicDeviceType);
} catch (Exception e) {
s_logger.warn("Invalid NIC device type " + nicDeviceType + " is specified in VM details, switch to default E1000");
details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString());
}
}
} else {
// for user-VM, use E1000 as default
if (nicDeviceType == null) {
details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString());
} else {
try {
VirtualEthernetCardType.valueOf(nicDeviceType);
} catch (Exception e) {
s_logger.warn("Invalid NIC device type " + nicDeviceType + " is specified in VM details, switch to default E1000");
details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString());
}
}
}
details.put(VmDetailConstants.BOOT_MODE, to.getBootMode());
String diskDeviceType = details.get(VmDetailConstants.ROOT_DISK_CONTROLLER);
if (userVm) {
if (diskDeviceType == null) {
details.put(VmDetailConstants.ROOT_DISK_CONTROLLER, _vmwareMgr.getRootDiskController());
}
}
String diskController = details.get(VmDetailConstants.DATA_DISK_CONTROLLER);
if (userVm) {
if (diskController == null) {
details.put(VmDetailConstants.DATA_DISK_CONTROLLER, DiskControllerType.lsilogic.toString());
}
}
if (vm.getType() == VirtualMachine.Type.NetScalerVm) {
details.put(VmDetailConstants.ROOT_DISK_CONTROLLER, "scsi");
}
List<NicProfile> nicProfiles = vm.getNics();
for (NicProfile nicProfile : nicProfiles) {
if (nicProfile.getTrafficType() == TrafficType.Guest) {
if (_networkMgr.isProviderSupportServiceInNetwork(nicProfile.getNetworkId(), Service.Firewall, Provider.CiscoVnmc)) {
details.put("ConfigureVServiceInNexus", Boolean.TRUE.toString());
}
break;
}
}
long clusterId = getClusterId(vm.getId());
details.put(VmwareReserveCpu.key(), VmwareReserveCpu.valueIn(clusterId).toString());
details.put(VmwareReserveMemory.key(), VmwareReserveMemory.valueIn(clusterId).toString());
to.setDetails(details);
if (vmType.equals(VirtualMachine.Type.DomainRouter)) {
NicProfile publicNicProfile = null;
for (NicProfile nicProfile : nicProfiles) {
if (nicProfile.getTrafficType() == TrafficType.Public) {
publicNicProfile = nicProfile;
break;
}
}
if (publicNicProfile != null) {
NicTO[] nics = to.getNics();
// reserve extra NICs
NicTO[] expandedNics = new NicTO[nics.length + _vmwareMgr.getRouterExtraPublicNics()];
int i = 0;
int deviceId = -1;
for (i = 0; i < nics.length; i++) {
expandedNics[i] = nics[i];
if (nics[i].getDeviceId() > deviceId)
deviceId = nics[i].getDeviceId();
}
deviceId++;
long networkId = publicNicProfile.getNetworkId();
NetworkVO network = _networkDao.findById(networkId);
for (; i < nics.length + _vmwareMgr.getRouterExtraPublicNics(); i++) {
NicTO nicTo = new NicTO();
nicTo.setDeviceId(deviceId++);
nicTo.setBroadcastType(publicNicProfile.getBroadcastType());
nicTo.setType(publicNicProfile.getTrafficType());
nicTo.setIp("0.0.0.0");
nicTo.setNetmask("255.255.255.255");
try {
String mac = _networkMgr.getNextAvailableMacAddressInNetwork(networkId);
nicTo.setMac(mac);
} catch (InsufficientAddressCapacityException e) {
throw new CloudRuntimeException("unable to allocate mac address on network: " + networkId);
}
nicTo.setDns1(publicNicProfile.getIPv4Dns1());
nicTo.setDns2(publicNicProfile.getIPv4Dns2());
if (publicNicProfile.getIPv4Gateway() != null) {
nicTo.setGateway(publicNicProfile.getIPv4Gateway());
} else {
nicTo.setGateway(network.getGateway());
}
nicTo.setDefaultNic(false);
nicTo.setBroadcastUri(publicNicProfile.getBroadCastUri());
nicTo.setIsolationuri(publicNicProfile.getIsolationUri());
Integer networkRate = _networkMgr.getNetworkRate(network.getId(), null);
nicTo.setNetworkRateMbps(networkRate);
expandedNics[i] = nicTo;
}
to.setNics(expandedNics);
VirtualMachine router = vm.getVirtualMachine();
DomainRouterVO routerVO = _domainRouterDao.findById(router.getId());
if (routerVO != null && routerVO.getIsRedundantRouter()) {
Long peerRouterId = _nicDao.getPeerRouterId(publicNicProfile.getMacAddress(), router.getId());
DomainRouterVO peerRouterVO = null;
if (peerRouterId != null) {
peerRouterVO = _domainRouterDao.findById(peerRouterId);
if (peerRouterVO != null) {
details.put("PeerRouterInstanceName", peerRouterVO.getInstanceName());
}
}
}
}
StringBuffer sbMacSequence = new StringBuffer();
for (NicTO nicTo : sortNicsByDeviceId(to.getNics())) {
sbMacSequence.append(nicTo.getMac()).append("|");
}
if (!sbMacSequence.toString().isEmpty()) {
sbMacSequence.deleteCharAt(sbMacSequence.length() - 1);
String bootArgs = to.getBootArgs();
to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString());
}
}
// Don't do this if the virtual machine is one of the special types
// Should only be done on user machines
if (userVm) {
configureNestedVirtualization(details, to);
}
// Determine the VM's OS description
GuestOSVO guestOS = _guestOsDao.findByIdIncludingRemoved(vm.getVirtualMachine().getGuestOSId());
to.setOs(guestOS.getDisplayName());
to.setHostName(vm.getHostName());
HostVO host = _hostDao.findById(vm.getVirtualMachine().getHostId());
GuestOSHypervisorVO guestOsMapping = null;
if (host != null) {
guestOsMapping = _guestOsHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), getHypervisorType().toString(), host.getHypervisorVersion());
}
if (guestOsMapping == null || host == null) {
to.setPlatformEmulator(null);
} else {
to.setPlatformEmulator(guestOsMapping.getGuestOsName());
}
List<OVFPropertyTO> ovfProperties = new ArrayList<>();
for (String detailKey : details.keySet()) {
if (detailKey.startsWith(ApiConstants.OVF_PROPERTIES)) {
String ovfPropKey = detailKey.replace(ApiConstants.OVF_PROPERTIES + "-", "");
TemplateOVFPropertyVO templateOVFPropertyVO = templateOVFPropertiesDao.findByTemplateAndKey(vm.getTemplateId(), ovfPropKey);
if (templateOVFPropertyVO == null) {
s_logger.warn(String.format("OVF property %s not found on template, discarding", ovfPropKey));
continue;
}
String ovfValue = details.get(detailKey);
boolean isPassword = templateOVFPropertyVO.isPassword();
OVFPropertyTO propertyTO = new OVFPropertyTO(ovfPropKey, ovfValue, isPassword);
ovfProperties.add(propertyTO);
}
}
if (CollectionUtils.isNotEmpty(ovfProperties)) {
removeOvfPropertiesFromDetails(ovfProperties, details);
String templateInstallPath = null;
List<DiskTO> rootDiskList = vm.getDisks().stream().filter(x -> x.getType() == Volume.Type.ROOT).collect(Collectors.toList());
if (rootDiskList.size() != 1) {
throw new CloudRuntimeException("Did not find only one root disk for VM " + vm.getHostName());
}
DiskTO rootDiskTO = rootDiskList.get(0);
DataStoreTO dataStore = rootDiskTO.getData().getDataStore();
StoragePoolVO storagePoolVO = _storagePoolDao.findByUuid(dataStore.getUuid());
long dataCenterId = storagePoolVO.getDataCenterId();
List<StoragePoolVO> pools = _storagePoolDao.listByDataCenterId(dataCenterId);
for (StoragePoolVO pool : pools) {
VMTemplateStoragePoolVO ref = templateStoragePoolDao.findByPoolTemplate(pool.getId(), vm.getTemplateId());
if (ref != null && ref.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
templateInstallPath = ref.getInstallPath();
break;
}
}
if (templateInstallPath == null) {
throw new CloudRuntimeException("Did not find the template install path for template " +
vm.getTemplateId() + " on zone " + dataCenterId);
}
Pair<String, List<OVFPropertyTO>> pair = new Pair<>(templateInstallPath, ovfProperties);
to.setOvfProperties(pair);
}
return to;
@Override public VirtualMachineTO implement(VirtualMachineProfile vm) {
vmwareVmImplementer.setGlobalNestedVirtualisationEnabled(VmwareEnableNestedVirtualization.value());
vmwareVmImplementer.setGlobalNestedVPerVMEnabled(VmwareEnableNestedVirtualizationPerVM.value());
return vmwareVmImplementer.implement(vm, toVirtualMachineTO(vm), getClusterId(vm.getId()));
}
/*
Remove OVF properties from details to be sent to hypervisor (avoid duplicate data)
*/
private void removeOvfPropertiesFromDetails(List<OVFPropertyTO> ovfProperties, Map<String, String> details) {
for (OVFPropertyTO propertyTO : ovfProperties) {
String key = propertyTO.getKey();
details.remove(ApiConstants.OVF_PROPERTIES + "-" + key);
}
}
/**
* Decide in which cases nested virtualization should be enabled based on (1){@code globalNestedV}, (2){@code globalNestedVPerVM}, (3){@code localNestedV}<br/>
* Nested virtualization should be enabled when one of this cases:
* <ul>
* <li>(1)=TRUE, (2)=TRUE, (3) is NULL (missing)</li>
* <li>(1)=TRUE, (2)=TRUE, (3)=TRUE</li>
* <li>(1)=TRUE, (2)=FALSE</li>
* <li>(1)=FALSE, (2)=TRUE, (3)=TRUE</li>
* </ul>
* In any other case, it shouldn't be enabled
* @param globalNestedV value of {@code 'vmware.nested.virtualization'} global config
* @param globalNestedVPerVM value of {@code 'vmware.nested.virtualization.perVM'} global config
* @param localNestedV value of {@code 'nestedVirtualizationFlag'} key in vm details if present, null if not present
* @return "true" for cases in which nested virtualization is enabled, "false" if not
*/
protected Boolean shouldEnableNestedVirtualization(Boolean globalNestedV, Boolean globalNestedVPerVM, String localNestedV){
if (globalNestedV == null || globalNestedVPerVM == null) {
return false;
}
boolean globalNV = globalNestedV.booleanValue();
boolean globalNVPVM = globalNestedVPerVM.booleanValue();
if (globalNVPVM){
return (localNestedV == null && globalNV) || BooleanUtils.toBoolean(localNestedV);
}
return globalNV;
}
/**
* Adds {@code 'nestedVirtualizationFlag'} value to {@code details} due to if it should be enabled or not
* @param details vm details
* @param to vm to
*/
protected void configureNestedVirtualization(Map<String, String> details, VirtualMachineTO to) {
Boolean globalNestedV = VmwareEnableNestedVirtualization.value();
Boolean globalNestedVPerVM = VmwareEnableNestedVirtualizationPerVM.value();
String localNestedV = details.get(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG);
Boolean shouldEnableNestedVirtualization = shouldEnableNestedVirtualization(globalNestedV, globalNestedVPerVM, localNestedV);
s_logger.debug("Nested virtualization requested, adding flag to vm configuration");
details.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, Boolean.toString(shouldEnableNestedVirtualization));
to.setDetails(details);
}
private long getClusterId(long vmId) {
long getClusterId(long vmId) {
long clusterId;
Long hostId;
@ -552,32 +221,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
return clusterId;
}
private NicTO[] sortNicsByDeviceId(NicTO[] nics) {
List<NicTO> listForSort = new ArrayList<NicTO>();
for (NicTO nic : nics) {
listForSort.add(nic);
}
Collections.sort(listForSort, new Comparator<NicTO>() {
@Override
public int compare(NicTO arg0, NicTO arg1) {
if (arg0.getDeviceId() < arg1.getDeviceId()) {
return -1;
} else if (arg0.getDeviceId() == arg1.getDeviceId()) {
return 0;
}
return 1;
}
});
return listForSort.toArray(new NicTO[0]);
}
@Override
@DB
public Pair<Boolean, Long> getCommandHostDelegation(long hostId, Command cmd) {
@Override @DB public Pair<Boolean, Long> getCommandHostDelegation(long hostId, Command cmd) {
boolean needDelegation = false;
if (cmd instanceof StorageSubSystemCommand) {
Boolean fullCloneEnabled = VmwareFullClone.value();
@ -585,12 +229,12 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
c.setExecuteInSequence(fullCloneEnabled);
}
if (cmd instanceof DownloadCommand) {
cmd.setContextParam(VmwareManager.s_vmwareOVAPackageTimeout.key(), String.valueOf(VmwareManager.s_vmwareOVAPackageTimeout.value()));
cmd.setContextParam(VmwareManager.s_vmwareOVAPackageTimeout.key(), String.valueOf(VmwareManager.s_vmwareOVAPackageTimeout.value()));
}
//NOTE: the hostid can be a hypervisor host, or a ssvm agent. For copycommand, if it's for volume upload, the hypervisor
//type is empty, so we need to check the format of volume at first.
if (cmd instanceof CopyCommand) {
CopyCommand cpyCommand = (CopyCommand) cmd;
CopyCommand cpyCommand = (CopyCommand)cmd;
DataTO srcData = cpyCommand.getSrcTO();
DataStoreTO srcStoreTO = srcData.getDataStore();
DataTO destData = cpyCommand.getDestTO();
@ -617,8 +261,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
return new Pair<Boolean, Long>(Boolean.FALSE, new Long(hostId));
}
if (destData.getObjectType() == DataObjectType.VOLUME && destStoreTO.getRole() == DataStoreRole.Primary &&
srcData.getObjectType() == DataObjectType.TEMPLATE && srcStoreTO.getRole() == DataStoreRole.Primary) {
if (destData.getObjectType() == DataObjectType.VOLUME && destStoreTO.getRole() == DataStoreRole.Primary && srcData.getObjectType() == DataObjectType.TEMPLATE
&& srcStoreTO.getRole() == DataStoreRole.Primary) {
needDelegation = false;
} else {
needDelegation = true;
@ -662,9 +306,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
cmd.setContextParam("vCenterSessionTimeout", String.valueOf(_vmwareMgr.getVcenterSessionTimeout()));
cmd.setContextParam(VmwareManager.s_vmwareOVAPackageTimeout.key(), String.valueOf(VmwareManager.s_vmwareOVAPackageTimeout.value()));
if (cmd instanceof BackupSnapshotCommand || cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
cmd instanceof CreatePrivateTemplateFromSnapshotCommand || cmd instanceof CopyVolumeCommand || cmd instanceof CopyCommand ||
cmd instanceof CreateVolumeOVACommand || cmd instanceof PrepareOVAPackingCommand || cmd instanceof CreateVolumeFromSnapshotCommand) {
if (cmd instanceof BackupSnapshotCommand || cmd instanceof CreatePrivateTemplateFromVolumeCommand || cmd instanceof CreatePrivateTemplateFromSnapshotCommand || cmd instanceof CopyVolumeCommand || cmd instanceof CopyCommand || cmd instanceof CreateVolumeOVACommand || cmd instanceof PrepareOVAPackingCommand
|| cmd instanceof CreateVolumeFromSnapshotCommand) {
String workerName = _vmwareMgr.composeWorkerName();
long checkPointId = 1;
// FIXME: Fix long checkPointId = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName));
@ -707,8 +350,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
return tokens[0] + "@" + vCenterIp;
}
@Override
public List<Command> finalizeExpungeNics(VirtualMachine vm, List<NicProfile> nics) {
@Override public List<Command> finalizeExpungeNics(VirtualMachine vm, List<NicProfile> nics) {
List<Command> commands = new ArrayList<Command>();
List<NicVO> nicVOs = _nicDao.listByVmId(vm.getId());
for (NicVO nic : nicVOs) {
@ -719,26 +361,22 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
// We need the traffic label to figure out which vSwitch has the
// portgroup
PhysicalNetworkTrafficTypeVO trafficTypeVO = _physicalNetworkTrafficTypeDao.findBy(networkVO.getPhysicalNetworkId(), networkVO.getTrafficType());
UnregisterNicCommand unregisterNicCommand =
new UnregisterNicCommand(vm.getInstanceName(), trafficTypeVO.getVmwareNetworkLabel(), UUID.fromString(nic.getUuid()));
UnregisterNicCommand unregisterNicCommand = new UnregisterNicCommand(vm.getInstanceName(), trafficTypeVO.getVmwareNetworkLabel(), UUID.fromString(nic.getUuid()));
commands.add(unregisterNicCommand);
}
}
return commands;
}
@Override
public String getConfigComponentName() {
@Override public String getConfigComponentName() {
return VMwareGuru.class.getSimpleName();
}
@Override
public ConfigKey<?>[] getConfigKeys() {
@Override public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {VmwareReserveCpu, VmwareReserveMemory, VmwareEnableNestedVirtualization, VmwareEnableNestedVirtualizationPerVM};
}
@Override
public List<Command> finalizeExpungeVolumes(VirtualMachine vm) {
@Override public List<Command> finalizeExpungeVolumes(VirtualMachine vm) {
List<Command> commands = new ArrayList<Command>();
List<VolumeVO> volumes = _volumeDao.findByInstance(vm.getId());
@ -776,8 +414,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
return commands;
}
@Override
public Map<String, String> getClusterSettings(long vmId) {
@Override public Map<String, String> getClusterSettings(long vmId) {
Map<String, String> details = new HashMap<String, String>();
long clusterId = getClusterId(vmId);
details.put(VmwareReserveCpu.key(), VmwareReserveCpu.valueIn(clusterId).toString());
@ -799,8 +436,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
*/
private DatacenterMO getDatacenterMO(long zoneId) throws Exception {
VmwareDatacenterVO vmwareDatacenter = getVmwareDatacenter(zoneId);
VmwareContext context = VmwareContextFactory.getContext(vmwareDatacenter.getVcenterHost(),
vmwareDatacenter.getUser(), vmwareDatacenter.getPassword());
VmwareContext context = VmwareContextFactory.getContext(vmwareDatacenter.getVcenterHost(), vmwareDatacenter.getUser(), vmwareDatacenter.getPassword());
DatacenterMO dcMo = new DatacenterMO(context, vmwareDatacenter.getVmwareDatacenterName());
ManagedObjectReference dcMor = dcMo.getMor();
if (dcMor == null) {
@ -826,9 +462,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
*/
private ServiceOfferingVO createServiceOfferingForVMImporting(Integer cpus, Integer memory, Integer maxCpuUsage) {
String name = "Imported-" + cpus + "-" + memory;
ServiceOfferingVO vo = new ServiceOfferingVO(name, cpus, memory, maxCpuUsage, null, null,
false, name, Storage.ProvisioningType.THIN, false, false,
null, false, Type.User, false);
ServiceOfferingVO vo = new ServiceOfferingVO(name, cpus, memory, maxCpuUsage, null, null, false, name, Storage.ProvisioningType.THIN, false, false, null, false, Type.User,
false);
return serviceOfferingDao.persist(vo);
}
@ -836,15 +471,12 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
* Get service offering ID for VM being imported.
* If it cannot be found it creates one and returns its ID
*/
private Long getImportingVMServiceOffering(VirtualMachineConfigSummary configSummary,
VirtualMachineRuntimeInfo runtimeInfo) {
private Long getImportingVMServiceOffering(VirtualMachineConfigSummary configSummary, VirtualMachineRuntimeInfo runtimeInfo) {
Integer numCpu = configSummary.getNumCpu();
Integer memorySizeMB = configSummary.getMemorySizeMB();
Integer maxCpuUsage = runtimeInfo.getMaxCpuUsage();
List<ServiceOfferingVO> offerings = serviceOfferingDao.listPublicByCpuAndMemory(numCpu, memorySizeMB);
return CollectionUtils.isEmpty(offerings) ?
createServiceOfferingForVMImporting(numCpu, memorySizeMB, maxCpuUsage).getId() :
offerings.get(0).getId();
return CollectionUtils.isEmpty(offerings) ? createServiceOfferingForVMImporting(numCpu, memorySizeMB, maxCpuUsage).getId() : offerings.get(0).getId();
}
/**
@ -876,7 +508,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
* Check backing info
*/
private void checkBackingInfo(VirtualDeviceBackingInfo backingInfo) {
if (! (backingInfo instanceof VirtualDiskFlatVer2BackingInfo)) {
if (!(backingInfo instanceof VirtualDiskFlatVer2BackingInfo)) {
throw new CloudRuntimeException("Unsopported backing, expected " + VirtualDiskFlatVer2BackingInfo.class.getSimpleName());
}
}
@ -899,7 +531,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
private Long getPoolId(VirtualDisk disk) {
VirtualDeviceBackingInfo backing = disk.getBacking();
checkBackingInfo(backing);
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo) backing;
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo)backing;
String[] fileNameParts = info.getFileName().split(" ");
String datastoreUuid = StringUtils.substringBetween(fileNameParts[0], "[", "]");
return getPoolIdFromDatastoreUuid(datastoreUuid);
@ -920,7 +552,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
private String getRootDiskTemplatePath(VirtualDisk rootDisk) {
VirtualDeviceBackingInfo backing = rootDisk.getBacking();
checkBackingInfo(backing);
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo) backing;
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo)backing;
VirtualDiskFlatVer2BackingInfo parent = info.getParent();
return (parent != null) ? getVolumeNameFromFileName(parent.getFileName()) : getVolumeNameFromFileName(info.getFileName());
}
@ -950,8 +582,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
/**
* Get template size
*/
private Long getTemplateSize(VirtualMachineMO template, String vmInternalName,
Map<VirtualDisk, VolumeVO> disksMapping, Backup backup) throws Exception {
private Long getTemplateSize(VirtualMachineMO template, String vmInternalName, Map<VirtualDisk, VolumeVO> disksMapping, Backup backup) throws Exception {
List<VirtualDisk> disks = template.getVirtualDisks();
if (CollectionUtils.isEmpty(disks)) {
throw new CloudRuntimeException("Couldn't find VM template size");
@ -964,11 +595,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
*/
private VMTemplateVO createVMTemplateRecord(String vmInternalName, long guestOsId, long accountId) {
Long nextTemplateId = vmTemplateDao.getNextInSequence(Long.class, "id");
VMTemplateVO templateVO = new VMTemplateVO(nextTemplateId, "Imported-from-" + vmInternalName,
Storage.ImageFormat.OVA,false, false, false, Storage.TemplateType.USER,
null, false, 64, accountId, null, "Template imported from VM " + vmInternalName,
false, guestOsId, false, HypervisorType.VMware, null, null,
false, false, false);
VMTemplateVO templateVO = new VMTemplateVO(nextTemplateId, "Imported-from-" + vmInternalName, Storage.ImageFormat.OVA, false, false, false, Storage.TemplateType.USER, null,
false, 64, accountId, null, "Template imported from VM " + vmInternalName, false, guestOsId, false, HypervisorType.VMware, null, null, false, false, false);
return vmTemplateDao.persist(templateVO);
}
@ -979,9 +607,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
*/
private long getTemplateId(String templatePath, String vmInternalName, Long guestOsId, long accountId) {
List<VMTemplateStoragePoolVO> poolRefs = templateStoragePoolDao.listByTemplatePath(templatePath);
return CollectionUtils.isNotEmpty(poolRefs) ?
poolRefs.get(0).getTemplateId() :
createVMTemplateRecord(vmInternalName, guestOsId, accountId).getId();
return CollectionUtils.isNotEmpty(poolRefs) ? poolRefs.get(0).getTemplateId() : createVMTemplateRecord(vmInternalName, guestOsId, accountId).getId();
}
/**
@ -990,9 +616,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
private void updateTemplateRef(long templateId, Long poolId, String templatePath, Long templateSize) {
VMTemplateStoragePoolVO templateRef = templateStoragePoolDao.findByPoolPath(poolId, templatePath);
if (templateRef == null) {
templateRef = new VMTemplateStoragePoolVO(poolId, templateId, null, 100,
VMTemplateStorageResourceAssoc.Status.DOWNLOADED, templatePath, null,
null, templatePath, templateSize);
templateRef = new VMTemplateStoragePoolVO(poolId, templateId, null, 100, VMTemplateStorageResourceAssoc.Status.DOWNLOADED, templatePath, null, null, templatePath,
templateSize);
templateRef.setState(ObjectInDataStoreStateMachine.State.Ready);
templateStoragePoolDao.persist(templateRef);
}
@ -1001,8 +626,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
/**
* Get template ID for VM being imported. If it is not found, it is created
*/
private Long getImportingVMTemplate(List<VirtualDisk> virtualDisks, DatacenterMO dcMo, String vmInternalName,
Long guestOsId, long accountId, Map<VirtualDisk, VolumeVO> disksMapping, Backup backup) throws Exception {
private Long getImportingVMTemplate(List<VirtualDisk> virtualDisks, DatacenterMO dcMo, String vmInternalName, Long guestOsId, long accountId, Map<VirtualDisk, VolumeVO> disksMapping, Backup backup) throws Exception {
for (VirtualDisk disk : virtualDisks) {
if (isRootDisk(disk, disksMapping, backup)) {
VolumeVO volumeVO = disksMapping.get(disk);
@ -1026,9 +650,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
* If VM does not exist: create and persist VM
* If VM exists: update VM
*/
private VMInstanceVO getVM(String vmInternalName, long templateId, long guestOsId,
long serviceOfferingId, long zoneId, long accountId, long userId,
long domainId) {
private VMInstanceVO getVM(String vmInternalName, long templateId, long guestOsId, long serviceOfferingId, long zoneId, long accountId, long userId, long domainId) {
VMInstanceVO vm = _vmDao.findVMByInstanceNameIncludingRemoved(vmInternalName);
if (vm != null) {
vm.setState(VirtualMachine.State.Stopped);
@ -1036,16 +658,14 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
_vmDao.update(vm.getId(), vm);
if (vm.getRemoved() != null) {
_vmDao.unremove(vm.getId());
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, vm.getDataCenterId(), vm.getId(),
vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(),
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, vm.getDataCenterId(), vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(),
vm.getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm());
}
return _vmDao.findById(vm.getId());
} else {
long id = userVmDao.getNextInSequence(Long.class, "id");
UserVmVO vmInstanceVO = new UserVmVO(id, vmInternalName, vmInternalName, templateId, HypervisorType.VMware,
guestOsId, false, false, domainId, accountId, userId, serviceOfferingId,
null, vmInternalName, null);
UserVmVO vmInstanceVO = new UserVmVO(id, vmInternalName, vmInternalName, templateId, HypervisorType.VMware, guestOsId, false, false, domainId, accountId, userId,
serviceOfferingId, null, vmInternalName, null);
vmInstanceVO.setDataCenterId(zoneId);
return userVmDao.persist(vmInstanceVO);
}
@ -1054,11 +674,9 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
/**
* Create and persist volume
*/
private VolumeVO createVolumeRecord(Volume.Type type, String volumeName, long zoneId, long domainId,
long accountId, long diskOfferingId, Storage.ProvisioningType provisioningType,
Long size, long instanceId, Long poolId, long templateId, Integer unitNumber, VirtualMachineDiskInfo diskInfo) {
VolumeVO volumeVO = new VolumeVO(type, volumeName, zoneId, domainId, accountId, diskOfferingId,
provisioningType, size, null, null, null);
private VolumeVO createVolumeRecord(Volume.Type type, String volumeName, long zoneId, long domainId, long accountId, long diskOfferingId, Storage.ProvisioningType provisioningType,
Long size, long instanceId, Long poolId, long templateId, Integer unitNumber, VirtualMachineDiskInfo diskInfo) {
VolumeVO volumeVO = new VolumeVO(type, volumeName, zoneId, domainId, accountId, diskOfferingId, provisioningType, size, null, null, null);
volumeVO.setFormat(Storage.ImageFormat.OVA);
volumeVO.setPath(volumeName);
volumeVO.setState(Volume.State.Ready);
@ -1097,9 +715,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
*/
private long getDiskOfferingId(long size, Storage.ProvisioningType provisioningType) {
List<DiskOfferingVO> offerings = diskOfferingDao.listAllBySizeAndProvisioningType(size, provisioningType);
return CollectionUtils.isNotEmpty(offerings) ?
offerings.get(0).getId() :
diskOfferingDao.findByUniqueName("Cloud.Com-Custom").getId();
return CollectionUtils.isNotEmpty(offerings) ? offerings.get(0).getId() : diskOfferingDao.findByUniqueName("Cloud.Com-Custom").getId();
}
protected VolumeVO updateVolume(VirtualDisk disk, Map<VirtualDisk, VolumeVO> disksMapping, VirtualMachineMO vmToImport, Long poolId, VirtualMachine vm) throws Exception {
@ -1116,8 +732,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
if (volume.getRemoved() != null) {
_volumeDao.unremove(volume.getId());
if (vm.getType() == Type.User) {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(),
volume.getId(), volume.getName(), volume.getDiskOfferingId(), null, volume.getSize(),
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(), null, volume.getSize(),
Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume());
_resourceLimitService.incrementResourceCount(vm.getAccountId(), Resource.ResourceType.volume, volume.isDisplayVolume());
_resourceLimitService.incrementResourceCount(vm.getAccountId(), Resource.ResourceType.primary_storage, volume.isDisplayVolume(), volume.getSize());
@ -1129,8 +744,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
/**
* Get volumes for VM being imported
*/
private void syncVMVolumes(VMInstanceVO vmInstanceVO, List<VirtualDisk> virtualDisks,
Map<VirtualDisk, VolumeVO> disksMapping, VirtualMachineMO vmToImport, Backup backup) throws Exception {
private void syncVMVolumes(VMInstanceVO vmInstanceVO, List<VirtualDisk> virtualDisks, Map<VirtualDisk, VolumeVO> disksMapping, VirtualMachineMO vmToImport, Backup backup)
throws Exception {
long zoneId = vmInstanceVO.getDataCenterId();
long accountId = vmInstanceVO.getAccountId();
long domainId = vmInstanceVO.getDomainId();
@ -1155,8 +770,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
return diskInfoBuilder.getDiskInfoByBackingFileBaseName(volumeName, poolName);
}
private VolumeVO createVolume(VirtualDisk disk, VirtualMachineMO vmToImport, long domainId, long zoneId,
long accountId, long instanceId, Long poolId, long templateId, Backup backup, boolean isImport) throws Exception {
private VolumeVO createVolume(VirtualDisk disk, VirtualMachineMO vmToImport, long domainId, long zoneId, long accountId, long instanceId, Long poolId, long templateId, Backup backup, boolean isImport) throws Exception {
VMInstanceVO vm = _vmDao.findByIdIncludingRemoved(backup.getVmId());
if (vm == null) {
throw new CloudRuntimeException("Failed to find the backup volume information from the VM backup");
@ -1173,14 +787,13 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
}
VirtualDeviceBackingInfo backing = disk.getBacking();
checkBackingInfo(backing);
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo) backing;
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo)backing;
String volumeName = getVolumeName(disk, vmToImport);
Storage.ProvisioningType provisioningType = getProvisioningType(info);
long diskOfferingId = getDiskOfferingId(size, provisioningType);
Integer unitNumber = disk.getUnitNumber();
VirtualMachineDiskInfo diskInfo = getDiskInfo(vmToImport, poolId, volumeName);
return createVolumeRecord(type, volumeName, zoneId, domainId, accountId, diskOfferingId,
provisioningType, size, instanceId, poolId, templateId, unitNumber, diskInfo);
return createVolumeRecord(type, volumeName, zoneId, domainId, accountId, diskOfferingId, provisioningType, size, instanceId, poolId, templateId, unitNumber, diskInfo);
}
/**
@ -1208,9 +821,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
private NetworkVO createNetworkRecord(Long zoneId, String tag, String vlan, long accountId, long domainId) {
Long physicalNetworkId = getPhysicalNetworkId(zoneId, tag);
final long id = _networkDao.getNextInSequence(Long.class, "id");
NetworkVO networkVO = new NetworkVO(id, TrafficType.Guest, Networks.Mode.Dhcp, BroadcastDomainType.Vlan, 9L,
domainId, accountId, id, "Imported-network-" + id, "Imported-network-" + id, null, Network.GuestType.Isolated,
zoneId, physicalNetworkId, ControlledEntity.ACLType.Account, false, null, false);
NetworkVO networkVO = new NetworkVO(id, TrafficType.Guest, Networks.Mode.Dhcp, BroadcastDomainType.Vlan, 9L, domainId, accountId, id, "Imported-network-" + id,
"Imported-network-" + id, null, Network.GuestType.Isolated, zoneId, physicalNetworkId, ControlledEntity.ACLType.Account, false, null, false);
networkVO.setBroadcastUri(BroadcastDomainType.Vlan.toUri(vlan));
networkVO.setGuruName("ExternalGuestNetworkGuru");
networkVO.setState(Network.State.Implemented);
@ -1252,7 +864,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
*/
private NetworkMO getNetworkMO(VirtualE1000 nic, VmwareContext context) {
VirtualDeviceConnectInfo connectable = nic.getConnectable();
VirtualEthernetCardNetworkBackingInfo info = (VirtualEthernetCardNetworkBackingInfo) nic.getBacking();
VirtualEthernetCardNetworkBackingInfo info = (VirtualEthernetCardNetworkBackingInfo)nic.getBacking();
ManagedObjectReference networkMor = info.getNetwork();
if (networkMor == null) {
throw new CloudRuntimeException("Could not find network for NIC on: " + nic.getMacAddress());
@ -1261,15 +873,14 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
}
private Pair<String, String> getNicMacAddressAndNetworkName(VirtualDevice nicDevice, VmwareContext context) throws Exception {
VirtualE1000 nic = (VirtualE1000) nicDevice;
VirtualE1000 nic = (VirtualE1000)nicDevice;
String macAddress = nic.getMacAddress();
NetworkMO networkMO = getNetworkMO(nic, context);
String networkName = networkMO.getName();
return new Pair<>(macAddress, networkName);
}
private void syncVMNics(VirtualDevice[] nicDevices, DatacenterMO dcMo, Map<String, NetworkVO> networksMapping,
VMInstanceVO vm) throws Exception {
private void syncVMNics(VirtualDevice[] nicDevices, DatacenterMO dcMo, Map<String, NetworkVO> networksMapping, VMInstanceVO vm) throws Exception {
VmwareContext context = dcMo.getContext();
List<NicVO> allNics = _nicDao.listByVmId(vm.getId());
for (VirtualDevice nicDevice : nicDevices) {
@ -1298,14 +909,12 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
for (Backup.VolumeInfo backedUpVol : backedUpVolumes) {
for (VirtualDisk disk : virtualDisks) {
if (!map.containsKey(disk) && backedUpVol.getSize().equals(disk.getCapacityInBytes())
&& !usedVols.containsKey(backedUpVol.getUuid())) {
if (!map.containsKey(disk) && backedUpVol.getSize().equals(disk.getCapacityInBytes()) && !usedVols.containsKey(backedUpVol.getUuid())) {
String volId = backedUpVol.getUuid();
VolumeVO vol = _volumeDao.findByUuidIncludingRemoved(volId);
usedVols.put(backedUpVol.getUuid(), true);
map.put(disk, vol);
s_logger.debug("VM restore mapping for disk " + disk.getBacking() +
" (capacity: " + disk.getCapacityInBytes() + ") with volume ID" + vol.getId());
s_logger.debug("VM restore mapping for disk " + disk.getBacking() + " (capacity: " + disk.getCapacityInBytes() + ") with volume ID" + vol.getId());
}
}
}
@ -1328,7 +937,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
*/
private VirtualDisk findRestoredVolume(Backup.VolumeInfo volumeInfo, VirtualMachineMO vm) throws Exception {
List<VirtualDisk> virtualDisks = vm.getVirtualDisks();
for (VirtualDisk disk: virtualDisks) {
for (VirtualDisk disk : virtualDisks) {
if (disk.getCapacityInBytes().equals(volumeInfo.getSize())) {
return disk;
}
@ -1342,15 +951,14 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
private String getVolumeFullPath(VirtualDisk disk) {
VirtualDeviceBackingInfo backing = disk.getBacking();
checkBackingInfo(backing);
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo) backing;
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo)backing;
return info.getFileName();
}
/**
* Get dest volume full path
*/
private String getDestVolumeFullPath(VirtualDisk restoredDisk, VirtualMachineMO restoredVm,
VirtualMachineMO vmMo) throws Exception {
private String getDestVolumeFullPath(VirtualDisk restoredDisk, VirtualMachineMO restoredVm, VirtualMachineMO vmMo) throws Exception {
VirtualDisk vmDisk = vmMo.getVirtualDisks().get(0);
String vmDiskPath = vmMo.getVmdkFileBaseName(vmDisk);
String vmDiskFullPath = getVolumeFullPath(vmMo.getVirtualDisks().get(0));
@ -1365,13 +973,11 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
VirtualDisk vmDisk = vmMo.getVirtualDisks().get(0);
VirtualDeviceBackingInfo backing = vmDisk.getBacking();
checkBackingInfo(backing);
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo) backing;
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo)backing;
return info.getDatastore();
}
@Override
public VirtualMachine importVirtualMachineFromBackup(long zoneId, long domainId, long accountId, long userId,
String vmInternalName, Backup backup) throws Exception {
@Override public VirtualMachine importVirtualMachineFromBackup(long zoneId, long domainId, long accountId, long userId, String vmInternalName, Backup backup) throws Exception {
DatacenterMO dcMo = getDatacenterMO(zoneId);
VirtualMachineMO vmToImport = dcMo.findVm(vmInternalName);
if (vmToImport == null) {
@ -1397,9 +1003,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
return vm;
}
@Override
public boolean attachRestoredVolumeToVirtualMachine(long zoneId, String location, Backup.VolumeInfo volumeInfo,
VirtualMachine vm, long poolId, Backup backup) throws Exception {
@Override public boolean attachRestoredVolumeToVirtualMachine(long zoneId, String location, Backup.VolumeInfo volumeInfo, VirtualMachine vm, long poolId, Backup backup)
throws Exception {
DatacenterMO dcMo = getDatacenterMO(zoneId);
VirtualMachineMO vmRestored = findVM(dcMo, location);
VirtualMachineMO vmMo = findVM(dcMo, vm.getInstanceName());
@ -1435,8 +1040,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
s_logger.error("Failed to get the attached the (restored) volume " + diskPath);
return false;
}
createVolume(attachedDisk, vmMo, vm.getDomainId(), vm.getDataCenterId(), vm.getAccountId(), vm.getId(),
poolId, vm.getTemplateId(), backup, false);
createVolume(attachedDisk, vmMo, vm.getDomainId(), vm.getDataCenterId(), vm.getAccountId(), vm.getId(), poolId, vm.getTemplateId(), backup, false);
return true;
}
@ -1450,15 +1054,14 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
return null;
}
@Override
public List<Command> finalizeMigrate(VirtualMachine vm, StoragePool destination) {
@Override public List<Command> finalizeMigrate(VirtualMachine vm, StoragePool destination) {
List<Command> commands = new ArrayList<Command>();
// OfflineVmwareMigration: specialised migration command
List<VolumeVO> volumes = _volumeDao.findByInstance(vm.getId());
List<VolumeTO> vols = new ArrayList<>();
for (Volume volume : volumes) {
VolumeTO vol = new VolumeTO(volume,destination);
VolumeTO vol = new VolumeTO(volume, destination);
vols.add(vol);
}
MigrateVmToPoolCommand migrateVmToPoolCommand = new MigrateVmToPoolCommand(vm.getInstanceName(), vols, destination.getUuid(), true);
@ -1468,7 +1071,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
final Long destClusterId = destination.getClusterId();
final Long srcClusterId = getClusterId(vm.getId());
if (srcClusterId != null && destClusterId != null && ! srcClusterId.equals(destClusterId)) {
if (srcClusterId != null && destClusterId != null && !srcClusterId.equals(destClusterId)) {
final String srcDcName = _clusterDetailsDao.getVmwareDcName(srcClusterId);
final String destDcName = _clusterDetailsDao.getVmwareDcName(destClusterId);
if (srcDcName != null && destDcName != null && !srcDcName.equals(destDcName)) {
@ -1480,4 +1083,9 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
}
return commands;
}
@Override
protected VirtualMachineTO toVirtualMachineTO(VirtualMachineProfile vmProfile) {
return super.toVirtualMachineTO(vmProfile);
}
}

View File

@ -0,0 +1,468 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.hypervisor.guru;
import com.cloud.agent.api.storage.OVFPropertyTO;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.vmware.manager.VmwareManager;
import com.cloud.hypervisor.vmware.mo.DiskControllerType;
import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.Networks;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.storage.GuestOSHypervisorVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.TemplateOVFPropertyVO;
import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.Volume;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.GuestOSHypervisorDao;
import com.cloud.storage.dao.TemplateOVFPropertiesDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.log4j.Logger;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class VmwareVmImplementer {
private static final Logger LOG = Logger.getLogger(VmwareVmImplementer.class);
@Inject
DomainRouterDao domainRouterDao;
@Inject
GuestOSDao guestOsDao;
@Inject
GuestOSHypervisorDao guestOsHypervisorDao;
@Inject
HostDao hostDao;
@Inject
NetworkDao networkDao;
@Inject
NetworkModel networkMgr;
@Inject
NicDao nicDao;
@Inject
PrimaryDataStoreDao storagePoolDao;
@Inject
TemplateOVFPropertiesDao templateOVFPropertiesDao;
@Inject
VMTemplatePoolDao templateStoragePoolDao;
@Inject
VmwareManager vmwareMgr;
private Boolean globalNestedVirtualisationEnabled;
private Boolean globalNestedVPerVMEnabled;
Boolean getGlobalNestedVirtualisationEnabled() {
return globalNestedVirtualisationEnabled != null ? globalNestedVirtualisationEnabled : false;
}
void setGlobalNestedVirtualisationEnabled(Boolean globalNestedVirtualisationEnabled) {
this.globalNestedVirtualisationEnabled = globalNestedVirtualisationEnabled;
}
Boolean getGlobalNestedVPerVMEnabled() {
return globalNestedVPerVMEnabled != null ? globalNestedVPerVMEnabled : false;
}
void setGlobalNestedVPerVMEnabled(Boolean globalNestedVPerVMEnabled) {
this.globalNestedVPerVMEnabled = globalNestedVPerVMEnabled;
}
VirtualMachineTO implement(VirtualMachineProfile vm, VirtualMachineTO to, long clusterId) {
to.setBootloader(VirtualMachineTemplate.BootloaderType.HVM);
Map<String, String> details = to.getDetails();
if (details == null)
details = new HashMap<String, String>();
VirtualMachine.Type vmType = vm.getType();
boolean userVm = !(vmType.equals(VirtualMachine.Type.DomainRouter) || vmType.equals(VirtualMachine.Type.ConsoleProxy) || vmType.equals(VirtualMachine.Type.SecondaryStorageVm));
String nicDeviceType = details.get(VmDetailConstants.NIC_ADAPTER);
if (!userVm) {
if (nicDeviceType == null) {
details.put(VmDetailConstants.NIC_ADAPTER, vmwareMgr.getSystemVMDefaultNicAdapterType());
} else {
try {
VirtualEthernetCardType.valueOf(nicDeviceType);
} catch (Exception e) {
LOG.warn("Invalid NIC device type " + nicDeviceType + " is specified in VM details, switch to default E1000");
details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString());
}
}
} else {
// for user-VM, use E1000 as default
if (nicDeviceType == null) {
details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString());
} else {
try {
VirtualEthernetCardType.valueOf(nicDeviceType);
} catch (Exception e) {
LOG.warn("Invalid NIC device type " + nicDeviceType + " is specified in VM details, switch to default E1000");
details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString());
}
}
}
setBootParameters(vm, to, details);
setDiskControllers(vm, details, userVm);
List<NicProfile> nicProfiles = getNicProfiles(vm, details);
addReservationDetails(clusterId, details);
if (vmType.equals(VirtualMachine.Type.DomainRouter)) {
configureDomainRouterNicsAndDetails(vm, to, details, nicProfiles);
}
// Don't do this if the virtual machine is one of the special types
// Should only be done on user machines
if (userVm) {
configureNestedVirtualization(details, to);
}
// Determine the VM's OS description
GuestOSVO guestOS = guestOsDao.findByIdIncludingRemoved(vm.getVirtualMachine().getGuestOSId());
to.setOs(guestOS.getDisplayName());
to.setHostName(vm.getHostName());
HostVO host = hostDao.findById(vm.getVirtualMachine().getHostId());
GuestOSHypervisorVO guestOsMapping = null;
if (host != null) {
guestOsMapping = guestOsHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), Hypervisor.HypervisorType.VMware.toString(), host.getHypervisorVersion());
}
if (guestOsMapping == null || host == null) {
to.setPlatformEmulator(null);
} else {
to.setPlatformEmulator(guestOsMapping.getGuestOsName());
}
List<OVFPropertyTO> ovfProperties = getOvfPropertyList(vm, details);
handleOvfProperties(vm, to, details, ovfProperties);
setDetails(to, details);
return to;
}
private void setDetails(VirtualMachineTO to, Map<String, String> details) {
if (LOG.isTraceEnabled()) {
for (String key: details.keySet()) {
LOG.trace(String.format("Detail for VM %s: %s => %s",to.getName(), key, details.get(key)));
}
}
to.setDetails(details);
}
private void configureDomainRouterNicsAndDetails(VirtualMachineProfile vm, VirtualMachineTO to, Map<String, String> details, List<NicProfile> nicProfiles) {
NicProfile publicNicProfile = null;
for (NicProfile nicProfile : nicProfiles) {
if (nicProfile.getTrafficType() == Networks.TrafficType.Public) {
publicNicProfile = nicProfile;
break;
}
}
if (publicNicProfile != null) {
NicTO[] nics = to.getNics();
// reserve extra NICs
NicTO[] expandedNics = new NicTO[nics.length + vmwareMgr.getRouterExtraPublicNics()];
int i = 0;
int deviceId = -1;
for (i = 0; i < nics.length; i++) {
expandedNics[i] = nics[i];
if (nics[i].getDeviceId() > deviceId)
deviceId = nics[i].getDeviceId();
}
deviceId++;
long networkId = publicNicProfile.getNetworkId();
NetworkVO network = networkDao.findById(networkId);
for (; i < nics.length + vmwareMgr.getRouterExtraPublicNics(); i++) {
NicTO nicTo = new NicTO();
nicTo.setDeviceId(deviceId++);
nicTo.setBroadcastType(publicNicProfile.getBroadcastType());
nicTo.setType(publicNicProfile.getTrafficType());
nicTo.setIp("0.0.0.0");
nicTo.setNetmask("255.255.255.255");
try {
String mac = networkMgr.getNextAvailableMacAddressInNetwork(networkId);
nicTo.setMac(mac);
} catch (InsufficientAddressCapacityException e) {
throw new CloudRuntimeException("unable to allocate mac address on network: " + networkId);
}
nicTo.setDns1(publicNicProfile.getIPv4Dns1());
nicTo.setDns2(publicNicProfile.getIPv4Dns2());
if (publicNicProfile.getIPv4Gateway() != null) {
nicTo.setGateway(publicNicProfile.getIPv4Gateway());
} else {
nicTo.setGateway(network.getGateway());
}
nicTo.setDefaultNic(false);
nicTo.setBroadcastUri(publicNicProfile.getBroadCastUri());
nicTo.setIsolationuri(publicNicProfile.getIsolationUri());
Integer networkRate = networkMgr.getNetworkRate(network.getId(), null);
nicTo.setNetworkRateMbps(networkRate);
expandedNics[i] = nicTo;
}
to.setNics(expandedNics);
VirtualMachine router = vm.getVirtualMachine();
DomainRouterVO routerVO = domainRouterDao.findById(router.getId());
if (routerVO != null && routerVO.getIsRedundantRouter()) {
Long peerRouterId = nicDao.getPeerRouterId(publicNicProfile.getMacAddress(), router.getId());
DomainRouterVO peerRouterVO = null;
if (peerRouterId != null) {
peerRouterVO = domainRouterDao.findById(peerRouterId);
if (peerRouterVO != null) {
details.put("PeerRouterInstanceName", peerRouterVO.getInstanceName());
}
}
}
}
StringBuffer sbMacSequence = new StringBuffer();
for (NicTO nicTo : sortNicsByDeviceId(to.getNics())) {
sbMacSequence.append(nicTo.getMac()).append("|");
}
if (!sbMacSequence.toString().isEmpty()) {
sbMacSequence.deleteCharAt(sbMacSequence.length() - 1);
String bootArgs = to.getBootArgs();
to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString());
}
}
private void handleOvfProperties(VirtualMachineProfile vm, VirtualMachineTO to, Map<String, String> details, List<OVFPropertyTO> ovfProperties) {
if (CollectionUtils.isNotEmpty(ovfProperties)) {
removeOvfPropertiesFromDetails(ovfProperties, details);
String templateInstallPath = null;
List<DiskTO> rootDiskList = vm.getDisks().stream().filter(x -> x.getType() == Volume.Type.ROOT).collect(Collectors.toList());
if (rootDiskList.size() != 1) {
throw new CloudRuntimeException("Did not find only one root disk for VM " + vm.getHostName());
}
DiskTO rootDiskTO = rootDiskList.get(0);
DataStoreTO dataStore = rootDiskTO.getData().getDataStore();
StoragePoolVO storagePoolVO = storagePoolDao.findByUuid(dataStore.getUuid());
long dataCenterId = storagePoolVO.getDataCenterId();
List<StoragePoolVO> pools = storagePoolDao.listByDataCenterId(dataCenterId);
for (StoragePoolVO pool : pools) {
VMTemplateStoragePoolVO ref = templateStoragePoolDao.findByPoolTemplate(pool.getId(), vm.getTemplateId());
if (ref != null && ref.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
templateInstallPath = ref.getInstallPath();
break;
}
}
if (templateInstallPath == null) {
throw new CloudRuntimeException("Did not find the template install path for template " + vm.getTemplateId() + " on zone " + dataCenterId);
}
Pair<String, List<OVFPropertyTO>> pair = new Pair<String, List<OVFPropertyTO>>(templateInstallPath, ovfProperties);
to.setOvfProperties(pair);
}
}
private List<OVFPropertyTO> getOvfPropertyList(VirtualMachineProfile vm, Map<String, String> details) {
List<OVFPropertyTO> ovfProperties = new ArrayList<OVFPropertyTO>();
for (String detailKey : details.keySet()) {
if (detailKey.startsWith(ApiConstants.OVF_PROPERTIES)) {
String ovfPropKey = detailKey.replace(ApiConstants.OVF_PROPERTIES + "-", "");
TemplateOVFPropertyVO templateOVFPropertyVO = templateOVFPropertiesDao.findByTemplateAndKey(vm.getTemplateId(), ovfPropKey);
if (templateOVFPropertyVO == null) {
LOG.warn(String.format("OVF property %s not found on template, discarding", ovfPropKey));
continue;
}
String ovfValue = details.get(detailKey);
boolean isPassword = templateOVFPropertyVO.isPassword();
OVFPropertyTO propertyTO = new OVFPropertyTO(ovfPropKey, ovfValue, isPassword);
ovfProperties.add(propertyTO);
}
}
return ovfProperties;
}
private void addReservationDetails(long clusterId, Map<String, String> details) {
details.put(VMwareGuru.VmwareReserveCpu.key(), VMwareGuru.VmwareReserveCpu.valueIn(clusterId).toString());
details.put(VMwareGuru.VmwareReserveMemory.key(), VMwareGuru.VmwareReserveMemory.valueIn(clusterId).toString());
}
private List<NicProfile> getNicProfiles(VirtualMachineProfile vm, Map<String, String> details) {
List<NicProfile> nicProfiles = vm.getNics();
for (NicProfile nicProfile : nicProfiles) {
if (nicProfile.getTrafficType() == Networks.TrafficType.Guest) {
if (networkMgr.isProviderSupportServiceInNetwork(nicProfile.getNetworkId(), Network.Service.Firewall, Network.Provider.CiscoVnmc)) {
details.put("ConfigureVServiceInNexus", Boolean.TRUE.toString());
}
break;
}
}
return nicProfiles;
}
private void setDiskControllers(VirtualMachineProfile vm, Map<String, String> details, boolean userVm) {
String diskDeviceType = details.get(VmDetailConstants.ROOT_DISK_CONTROLLER);
if (userVm) {
if (diskDeviceType == null) {
details.put(VmDetailConstants.ROOT_DISK_CONTROLLER,vmwareMgr.getRootDiskController());
}
}
String diskController = details.get(VmDetailConstants.DATA_DISK_CONTROLLER);
if (userVm) {
if (diskController == null) {
details.put(VmDetailConstants.DATA_DISK_CONTROLLER, DiskControllerType.lsilogic.toString());
}
}
if (vm.getType() == VirtualMachine.Type.NetScalerVm) {
details.put(VmDetailConstants.ROOT_DISK_CONTROLLER, "scsi");
}
}
private void setBootParameters(VirtualMachineProfile vm, VirtualMachineTO to, Map<String, String> details) {
details.put(VmDetailConstants.BOOT_MODE, to.getBootMode());
if (vm.getParameter(VirtualMachineProfile.Param.BootIntoSetup) != null && (Boolean)vm.getParameter(VirtualMachineProfile.Param.BootIntoSetup) == true) {
to.setEnterHardwareSetup(true);
}
// there should also be
// details.put(VmDetailConstants.BOOT_TYPE, to.getBootType());
}
/*
Remove OVF properties from details to be sent to hypervisor (avoid duplicate data)
*/
private void removeOvfPropertiesFromDetails(List<OVFPropertyTO> ovfProperties, Map<String, String> details) {
for (OVFPropertyTO propertyTO : ovfProperties) {
String key = propertyTO.getKey();
details.remove(ApiConstants.OVF_PROPERTIES + "-" + key);
}
}
/**
* Adds {@code 'nestedVirtualizationFlag'} value to {@code details} due to if it should be enabled or not
* @param details vm details should not be null
* @param to vm to
*/
protected void configureNestedVirtualization(Map<String, String> details, VirtualMachineTO to) {
String localNestedV = details.get(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG);
Boolean globalNestedVirtualisationEnabled = getGlobalNestedVirtualisationEnabled();
Boolean globalNestedVPerVMEnabled = getGlobalNestedVPerVMEnabled();
Boolean shouldEnableNestedVirtualization = shouldEnableNestedVirtualization(globalNestedVirtualisationEnabled, globalNestedVPerVMEnabled, localNestedV);
if(LOG.isDebugEnabled()) {
LOG.debug(String.format(
"Due to '%B'(globalNestedVirtualisationEnabled) and '%B'(globalNestedVPerVMEnabled) I'm adding a flag with value %B to the vm configuration for Nested Virtualisation.",
globalNestedVirtualisationEnabled,
globalNestedVPerVMEnabled,
shouldEnableNestedVirtualization)
);
}
details.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, Boolean.toString(shouldEnableNestedVirtualization));
}
/**
* Decide in which cases nested virtualization should be enabled based on (1){@code globalNestedV}, (2){@code globalNestedVPerVM}, (3){@code localNestedV}<br/>
* Nested virtualization should be enabled when one of this cases:
* <ul>
* <li>(1)=TRUE, (2)=TRUE, (3) is NULL (missing)</li>
* <li>(1)=TRUE, (2)=TRUE, (3)=TRUE</li>
* <li>(1)=TRUE, (2)=FALSE</li>
* <li>(1)=FALSE, (2)=TRUE, (3)=TRUE</li>
* </ul>
* In any other case, it shouldn't be enabled
* @param globalNestedV value of {@code 'vmware.nested.virtualization'} global config
* @param globalNestedVPerVM value of {@code 'vmware.nested.virtualization.perVM'} global config
* @param localNestedV value of {@code 'nestedVirtualizationFlag'} key in vm details if present, null if not present
* @return "true" for cases in which nested virtualization is enabled, "false" if not
*/
Boolean shouldEnableNestedVirtualization(Boolean globalNestedV, Boolean globalNestedVPerVM, String localNestedV) {
if (globalNestedV == null || globalNestedVPerVM == null) {
return false;
}
boolean globalNV = globalNestedV.booleanValue();
boolean globalNVPVM = globalNestedVPerVM.booleanValue();
if (globalNVPVM) {
return (localNestedV == null && globalNV) || BooleanUtils.toBoolean(localNestedV);
}
return globalNV;
}
private NicTO[] sortNicsByDeviceId(NicTO[] nics) {
List<NicTO> listForSort = new ArrayList<NicTO>();
for (NicTO nic : nics) {
listForSort.add(nic);
}
Collections.sort(listForSort, new Comparator<NicTO>() {
@Override public int compare(NicTO arg0, NicTO arg1) {
if (arg0.getDeviceId() < arg1.getDeviceId()) {
return -1;
} else if (arg0.getDeviceId() == arg1.getDeviceId()) {
return 0;
}
return 1;
}
});
return listForSort.toArray(new NicTO[0]);
}
}

View File

@ -1723,10 +1723,13 @@ 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 = "bios";
String bootMode = null;
if (vmSpec.getDetails().containsKey(VmDetailConstants.BOOT_MODE)) {
bootMode = vmSpec.getDetails().get(VmDetailConstants.BOOT_MODE);
}
if (null == bootMode) {
bootMode = ApiConstants.BootType.BIOS.toString();
}
// 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.
@ -2285,15 +2288,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
if (StringUtils.isNotBlank(bootMode) && !bootMode.equalsIgnoreCase("bios")) {
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);
}
}
setBootOptions(vmSpec, bootMode, vmConfigSpec);
//
// Configure VM
@ -2382,6 +2377,30 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
private void setBootOptions(VirtualMachineTO vmSpec, String bootMode, VirtualMachineConfigSpec vmConfigSpec) {
VirtualMachineBootOptions bootOptions = null;
if (StringUtils.isNotBlank(bootMode) && !bootMode.equalsIgnoreCase("bios")) {
vmConfigSpec.setFirmware("efi");
if (vmSpec.getDetails().containsKey(ApiConstants.BootType.UEFI.toString()) && "secure".equalsIgnoreCase(vmSpec.getDetails().get(ApiConstants.BootType.UEFI.toString()))) {
if (bootOptions == null) {
bootOptions = new VirtualMachineBootOptions();
}
bootOptions.setEfiSecureBootEnabled(true);
}
}
if (vmSpec.isEnterHardwareSetup()) {
if (bootOptions == null) {
bootOptions = new VirtualMachineBootOptions();
}
if (s_logger.isDebugEnabled()) {
s_logger.debug(String.format("configuring VM '%s' to enter hardware setup",vmSpec.getName()));
}
bootOptions.setEnterBIOSSetup(vmSpec.isEnterHardwareSetup());
}
if (bootOptions != null) {
vmConfigSpec.setBootOptions(bootOptions);
}
}
/**
* Set the ovf section spec from existing vApp configuration
@ -3908,8 +3927,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
s_logger.trace("Detected mounted vmware tools installer for :[" + cmd.getVmName() + "]");
}
try {
vmMo.rebootGuest();
return new RebootAnswer(cmd, "reboot succeeded", true);
if (canSetEnableSetupConfig(vmMo,cmd.getVirtualMachine())) {
vmMo.rebootGuest();
return new RebootAnswer(cmd, "reboot succeeded", true);
} else {
return new RebootAnswer(cmd, "Failed to configure VM to boot into hardware setup menu: " + vmMo.getName(), false);
}
} catch (ToolsUnavailableFaultMsg e) {
s_logger.warn("VMware tools is not installed at guest OS, we will perform hard reset for reboot");
} catch (Exception e) {
@ -3950,6 +3973,33 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
/**
* set the boot into setup option if possible
* @param vmMo vmware view on the vm
* @param virtualMachine orchestration spec for the vm
* @return true unless reboot into setup is requested and vmware is unable to comply
*/
private boolean canSetEnableSetupConfig(VirtualMachineMO vmMo, VirtualMachineTO virtualMachine) {
if (virtualMachine.isEnterHardwareSetup()) {
VirtualMachineBootOptions bootOptions = new VirtualMachineBootOptions();
VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
if (s_logger.isDebugEnabled()) {
s_logger.debug(String.format("configuring VM '%s' to reboot into hardware setup menu.",virtualMachine.getName()));
}
bootOptions.setEnterBIOSSetup(virtualMachine.isEnterHardwareSetup());
vmConfigSpec.setBootOptions(bootOptions);
try {
if (!vmMo.configureVm(vmConfigSpec)) {
return false;
}
} catch (Exception e) {
s_logger.error(String.format("failed to reconfigure VM '%s' to boot into hardware setup menu",virtualMachine.getName()),e);
return false;
}
}
return true;
}
protected Answer execute(CheckVirtualMachineCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource CheckVirtualMachineCommand: " + _gson.toJson(cmd));

View File

@ -35,6 +35,8 @@
<property name="name" value="VMwareGuru" />
</bean>
<bean id="VmwareVmImplementer" class="com.cloud.hypervisor.guru.VmwareVmImplementer"/>
<bean id="VmwareInvestigator" class="com.cloud.ha.VmwareInvestigator">
<property name="name" value="VMwareInvestigator" />
</bean>

View File

@ -16,11 +16,9 @@
// under the License.
package com.cloud.hypervisor.guru;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.inOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.verify;
import java.util.HashMap;
import java.util.Map;
@ -29,9 +27,9 @@ import org.apache.cloudstack.framework.config.ConfigKey;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.powermock.core.classloader.annotations.PrepareForTest;
@ -43,19 +41,13 @@ import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.vm.VmDetailConstants;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ConfigKey.class, VMwareGuru.class})
@PrepareForTest({ConfigKey.class, VmwareVmImplementer.class})
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class VMwareGuruTest {
@Mock(name="VmwareEnableNestedVirtualization")
private ConfigKey<Boolean> vmwareNestedVirtualizationConfig;
@Mock(name="VmwareEnableNestedVirtualizationPerVM")
private ConfigKey<Boolean> vmwareNestedVirtualizationPerVmConfig;
public class VmwareVmImplementerTest {
@Spy
@InjectMocks
private VMwareGuru _guru = new VMwareGuru();
private VmwareVmImplementer implementer = new VmwareVmImplementer();
@Mock
VirtualMachineTO vmTO;
@ -68,26 +60,25 @@ public class VMwareGuruTest {
}
private void setConfigValues(Boolean globalNV, Boolean globalNVPVM, String localNV){
when(vmwareNestedVirtualizationConfig.value()).thenReturn(globalNV);
when(vmwareNestedVirtualizationPerVmConfig.value()).thenReturn(globalNVPVM);
implementer.setGlobalNestedVirtualisationEnabled(globalNV.booleanValue());
implementer.setGlobalNestedVPerVMEnabled(globalNVPVM.booleanValue());
if (localNV != null) {
vmDetails.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, localNV);
}
}
private void executeAndVerifyTest(Boolean globalNV, Boolean globalNVPVM, String localNV, Boolean expectedResult){
Boolean result = _guru.shouldEnableNestedVirtualization(globalNV, globalNVPVM, localNV);
Boolean result = implementer.shouldEnableNestedVirtualization(globalNV, globalNVPVM, localNV);
assertEquals(expectedResult, result);
}
@Test
public void testConfigureNestedVirtualization(){
setConfigValues(true, true, null);
_guru.configureNestedVirtualization(vmDetails, vmTO);
implementer.configureNestedVirtualization(vmDetails, vmTO);
Map<String,String> spyDetails = Mockito.spy(vmDetails);
InOrder inOrder = inOrder(_guru, vmTO);
inOrder.verify(_guru).shouldEnableNestedVirtualization(true, true, null);
inOrder.verify(vmTO).setDetails(vmDetails);
verify(implementer).shouldEnableNestedVirtualization(true, true, null);
assertTrue(vmDetails.containsKey(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG));
assertEquals(Boolean.toString(true), vmDetails.get(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG));

View File

@ -786,7 +786,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
return true;
}
if (rebootVirtualMachine(userId, vmId) == null) {
if (rebootVirtualMachine(userId, vmId, false) == null) {
s_logger.warn("Failed to reboot the vm " + vmInstance);
return false;
} else {
@ -897,7 +897,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
s_logger.debug("Vm " + vmInstance + " is stopped, not rebooting it as a part of SSH Key reset");
return true;
}
if (rebootVirtualMachine(userId, vmId) == null) {
if (rebootVirtualMachine(userId, vmId, false) == null) {
s_logger.warn("Failed to reboot the vm " + vmInstance);
return false;
} else {
@ -934,9 +934,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
return status;
}
private UserVm rebootVirtualMachine(long userId, long vmId) throws InsufficientCapacityException, ResourceUnavailableException {
private UserVm rebootVirtualMachine(long userId, long vmId, boolean enterSetup) throws InsufficientCapacityException, ResourceUnavailableException {
UserVmVO vm = _vmDao.findById(vmId);
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("reboot %s with enterSetup set to %s", vm.getInstanceName(), Boolean.toString(enterSetup)));
}
if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging || vm.getRemoved() != null) {
s_logger.warn("Vm id=" + vmId + " doesn't exist");
return null;
@ -969,8 +973,18 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} catch (Exception ex){
throw new CloudRuntimeException("Router start failed due to" + ex);
}finally {
s_logger.info("Rebooting vm " + vm.getInstanceName());
_itMgr.reboot(vm.getUuid(), null);
if (s_logger.isInfoEnabled()) {
s_logger.info(String.format("Rebooting vm %s%s.", vm.getInstanceName(), enterSetup? " entering hardware setup menu" : " as is"));
}
Map<VirtualMachineProfile.Param,Object> params = null;
if (enterSetup) {
params = new HashMap();
params.put(VirtualMachineProfile.Param.BootIntoSetup, Boolean.TRUE);
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("Adding %s to paramlist", VirtualMachineProfile.Param.BootIntoSetup));
}
}
_itMgr.reboot(vm.getUuid(), params);
}
return _vmDao.findById(vmId);
} else {
@ -2836,7 +2850,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_START, eventDescription = "starting Vm", async = true)
public UserVm startVirtualMachine(StartVMCmd cmd) throws ExecutionException, ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException {
return startVirtualMachine(cmd.getId(), cmd.getPodId(), cmd.getClusterId(), cmd.getHostId(), null, cmd.getDeploymentPlanner()).first();
Map<VirtualMachineProfile.Param, Object> additonalParams = null;
if (cmd.getBootIntoSetup() != null) {
if (additonalParams == null) {
additonalParams = new HashMap<>();
}
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("Adding %s into the param map", VirtualMachineProfile.Param.BootIntoSetup.getName()));
}
additonalParams.put(VirtualMachineProfile.Param.BootIntoSetup, cmd.getBootIntoSetup());
}
return startVirtualMachine(cmd.getId(), cmd.getPodId(), cmd.getClusterId(), cmd.getHostId(), additonalParams, cmd.getDeploymentPlanner()).first();
}
@Override
@ -2866,7 +2892,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId + " corresponding to the vm");
}
UserVm userVm = rebootVirtualMachine(CallContext.current().getCallingUserId(), vmId);
Boolean enterSetup = cmd.getBootIntoSetup();
if (enterSetup != null && !HypervisorType.VMware.equals(vmInstance.getHypervisorType())) {
throw new InvalidParameterValueException("booting into a hardware setup menu does not make sense on " + vmInstance.getHypervisorType());
}
UserVm userVm = rebootVirtualMachine(CallContext.current().getCallingUserId(), vmId, enterSetup == null ? false : cmd.getBootIntoSetup());
if (userVm != null ) {
// update the vmIdCountMap if the vm is in advanced shared network with out services
final List<NicVO> nics = _nicDao.listByVmId(vmId);
@ -4288,7 +4318,7 @@ 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<VirtualMachineProfile.Param, Object> additonalParams = new HashMap<>();
Map<Long, DiskOffering> diskOfferingMap = cmd.getDataDiskTemplateToDiskOfferingMap();
if (cmd instanceof DeployVMCmdByAdmin) {
DeployVMCmdByAdmin adminCmd = (DeployVMCmdByAdmin)cmd;
@ -4296,16 +4326,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
clusterId = adminCmd.getClusterId();
}
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()));
}
if (cmd.getBootIntoSetup() != null) {
additonalParams.put(VirtualMachineProfile.Param.BootIntoSetup, cmd.getBootIntoSetup());
}
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)
private UserVm startVirtualMachine(long vmId, Long podId, Long clusterId, Long hostId, Map<Long, DiskOffering> diskOfferingMap
, Map<VirtualMachineProfile.Param, Object> additonalParams, String deploymentPlannerToUse)
throws ResourceUnavailableException,
InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException {
UserVmVO vm = _vmDao.findById(vmId);
@ -4640,7 +4673,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
@Override
public Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMachine(long vmId, Long podId, Long clusterId, Long hostId, Map<VirtualMachineProfile.Param, Object> additionalParams, String deploymentPlannerToUse)
public Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMachine(long vmId, Long podId, Long clusterId, Long hostId,
Map<VirtualMachineProfile.Param, Object> additionalParams, String deploymentPlannerToUse)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException {
// Input validation
final Account callerAccount = CallContext.current().getCallingAccount();
@ -4743,11 +4777,18 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
// use it to encrypt & save the vm password
encryptAndStorePassword(vm, password);
params = new HashMap<VirtualMachineProfile.Param, Object>();
if (additionalParams != null) {
params.putAll(additionalParams);
params = createParameterInParameterMap(params, additionalParams, VirtualMachineProfile.Param.VmPassword, password);
}
if(null != additionalParams && additionalParams.containsKey(VirtualMachineProfile.Param.BootIntoSetup)) {
if (! HypervisorType.VMware.equals(vm.getHypervisorType())) {
throw new InvalidParameterValueException(ApiConstants.BOOT_INTO_SETUP + " makes no sense for " + vm.getHypervisorType());
}
params.put(VirtualMachineProfile.Param.VmPassword, password);
Object paramValue = additionalParams.get(VirtualMachineProfile.Param.BootIntoSetup);
if (s_logger.isTraceEnabled()) {
s_logger.trace("It was specified whether to enter setup mode: " + paramValue.toString());
}
params = createParameterInParameterMap(params, additionalParams, VirtualMachineProfile.Param.BootIntoSetup, paramValue);
}
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
@ -4782,6 +4823,24 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
return vmParamPair;
}
private Map<VirtualMachineProfile.Param, Object> createParameterInParameterMap(Map<VirtualMachineProfile.Param, Object> params, Map<VirtualMachineProfile.Param, Object> parameterMap, VirtualMachineProfile.Param parameter,
Object parameterValue) {
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("createParameterInParameterMap(%s, %s)", parameter, parameterValue));
}
if (params == null) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("creating new Parameter map");
}
params = new HashMap<>();
if (parameterMap != null) {
params.putAll(parameterMap);
}
}
params.put(parameter, parameterValue);
return params;
}
private Pod getDestinationPod(Long podId, boolean isRootAdmin) {
Pod destinationPod = null;
if (podId != null) {
@ -7114,4 +7173,4 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
id, instanceName, uuidName, hypervisorType, customParameters,
null, null, null, powerState);
}
}
}

View File

@ -504,6 +504,12 @@
</div>
</div>
<div class="select-area">
<div class="value">
<input type="checkbox" name="bootintosetup" id="bootintosetup" />
<label><translate key="label.vm.enterhardwaresetup" /></label>
</div>
</div>
<!-- Zone -->
<div class="select">

View File

@ -789,6 +789,7 @@ var dictionary = {
"label.end.vxlan":"End VXLAN",
"label.endpoint":"Endpoint",
"label.endpoint.or.operation":"Endpoint or Operation",
"label.enter.hardware.setup":"Enter the hardware setup menu",
"label.enter.token":"Enter token",
"label.error":"Error",
"label.error.code":"Error Code",
@ -994,6 +995,7 @@ var dictionary = {
"label.keyboard.language":"Keyboard language",
"label.vm.boottype":"Boot Type",
"label.vm.bootmode":"Boot Mode",
"label.vm.enterhardwaresetup":"Enter hardware setup after boot",
"label.keyboard.type":"Keyboard type",
"label.kubernetes.cluster":"Kubernetes cluster",
"label.kubernetes.cluster.details":"Kubernetes cluster details",

View File

@ -1413,6 +1413,12 @@
bootmode : bootmode
});
}
var bootintosetup = (args.data.bootintosetup == "on");
if (bootintosetup) {
$.extend(deployVmData, {
bootintosetup : bootintosetup
});
}
if (g_hostid != null) {
$.extend(deployVmData, {

View File

@ -74,6 +74,16 @@
});
}
}
},
bootintosetup: {
label: 'label.enter.hardware.setup',
isBoolean: true,
isHidden: function(args) {
if (args.context.instances[0].hypervisor !== 'VMware') {
return true;
}
return false;
}
}
}
},
@ -1049,7 +1059,18 @@
});
}
}
},
bootintosetup: {
label: 'label.enter.hardware.setup',
isBoolean: true,
isHidden: function(args) {
if (args.context.instances[0].hypervisor !== 'VMware') {
return true;
}
return false;
}
}
}
},
action: function(args) {
@ -1071,6 +1092,12 @@
hostid: args.data.hostId
});
}
var bootintosetup = (args.data.bootintosetup == "on");
if (bootintosetup) {
$.extend(data, {
bootintosetup : bootintosetup
});
}
$.ajax({
url: createURL("startVirtualMachine"),
data: data,
@ -1115,10 +1142,34 @@
restart: {
label: 'label.action.reboot.instance',
compactLabel: 'label.reboot',
createForm: {
title: 'label.action.reboot.instance',
desc: 'message.action.reboot.instance',
preFilter: function(args) {
args.$form.find('.form-item[rel=bootintosetup]').find('input').attr('checked', 'checked'); //checked
args.$form.find('.form-item[rel=bootintosetup]').css('display', 'inline-block'); //shown
},
fields: {
bootintosetup: {
label: 'label.enter.hardware.setup',
isBoolean: true,
isHidden: function(args) {
if (args.context.instances[0].hypervisor !== 'VMware') {
return true;
}
return false;
}
}
}
},
action: function(args) {
$.ajax({
url: createURL("rebootVirtualMachine&id=" + args.context.instances[0].id),
url: createURL("rebootVirtualMachine"),
dataType: "json",
data: {
id: args.context.instances[0].id,
bootintosetup: (args.data.bootintosetup == "on")
},
async: true,
success: function(json) {
var jid = json.rebootvirtualmachineresponse.jobid;