use of com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost in project cloudstack by apache.
the class VmwareResource method getNewPathAndChainInfoInDatastoreCluster.
private Pair<String, String> getNewPathAndChainInfoInDatastoreCluster(VirtualMachineMO vmMo, String path, String chainInfo, boolean managed, String iscsiName, String poolUUID, String poolType) throws Exception {
VmwareContext context = getServiceContext();
VmwareHypervisorHost hyperHost = getHyperHost(context);
if (poolType != null && poolType.equalsIgnoreCase(Storage.StoragePoolType.DatastoreCluster.toString())) {
VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
VirtualMachineDiskInfo matchingExistingDisk = getMatchingExistingDiskWithVolumeDetails(diskInfoBuilder, path, chainInfo, managed, iscsiName, poolUUID, hyperHost, context);
if (diskInfoBuilder != null && matchingExistingDisk != null) {
String[] diskChain = matchingExistingDisk.getDiskChain();
DatastoreFile file = new DatastoreFile(diskChain[0]);
if (!file.getFileBaseName().equalsIgnoreCase(path)) {
if (s_logger.isInfoEnabled())
s_logger.info("Detected disk-chain top file change on volume: " + path + " -> " + file.getFileBaseName());
path = file.getFileBaseName();
chainInfo = _gson.toJson(matchingExistingDisk);
return new Pair<>(path, chainInfo);
}
}
}
return null;
}
use of com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost in project cloudstack by apache.
the class VmwareResource method relocateVirtualMachine.
/*
* Method to relocate a virtual machine. This migrates VM and its volumes to given host, datastores.
* It is used for MigrateVolumeCommand (detached volume case), MigrateVmToPoolCommand and MigrateVmWithStorageCommand.
*/
private List<VolumeObjectTO> relocateVirtualMachine(final VmwareHypervisorHost hypervisorHost, final String name, final VirtualMachineTO vmTo, final String targetHost, final VmwareHypervisorHost hostInTargetCluster, final String poolUuid, final List<Pair<VolumeTO, StorageFilerTO>> volToFiler) throws Exception {
String vmName = name;
if (vmName == null && vmTo != null) {
vmName = vmTo.getName();
}
VmwareHypervisorHost sourceHyperHost = hypervisorHost;
VmwareHypervisorHost targetHyperHost = hostInTargetCluster;
VirtualMachineMO vmMo = null;
ManagedObjectReference morSourceHostDc = null;
VirtualMachineRelocateSpec relocateSpec = new VirtualMachineRelocateSpec();
List<VirtualMachineRelocateSpecDiskLocator> diskLocators = new ArrayList<VirtualMachineRelocateSpecDiskLocator>();
Set<String> mountedDatastoresAtSource = new HashSet<String>();
List<VolumeObjectTO> volumeToList = new ArrayList<>();
Map<Long, Integer> volumeDeviceKey = new HashMap<Long, Integer>();
try {
if (sourceHyperHost == null) {
sourceHyperHost = getHyperHost(getServiceContext());
}
if (targetHyperHost == null && StringUtils.isNotBlank(targetHost)) {
targetHyperHost = VmwareHelper.getHostMOFromHostName(getServiceContext(), targetHost);
}
morSourceHostDc = sourceHyperHost.getHyperHostDatacenter();
DatacenterMO dcMo = new DatacenterMO(sourceHyperHost.getContext(), morSourceHostDc);
if (targetHyperHost != null) {
ManagedObjectReference morTargetHostDc = targetHyperHost.getHyperHostDatacenter();
if (!morSourceHostDc.getValue().equalsIgnoreCase(morTargetHostDc.getValue())) {
String msg = String.format("VM: %s cannot be migrated between different datacenter", vmName);
throw new CloudRuntimeException(msg);
}
}
// find VM through source host (VM is not at the target host yet)
vmMo = sourceHyperHost.findVmOnHyperHost(vmName);
if (vmMo == null) {
String msg = String.format("VM: %s does not exist on host: %s", vmName, sourceHyperHost.getHyperHostName());
s_logger.warn(msg);
// find VM through source host (VM is not at the target host yet)
vmMo = dcMo.findVm(vmName);
if (vmMo == null) {
msg = String.format("VM: %s does not exist on datacenter: %s", vmName, dcMo.getName());
s_logger.error(msg);
throw new Exception(msg);
}
// VM host has changed
sourceHyperHost = vmMo.getRunningHost();
}
vmName = vmMo.getName();
String srcHostApiVersion = ((HostMO) sourceHyperHost).getHostAboutInfo().getApiVersion();
if (StringUtils.isNotBlank(poolUuid)) {
VmwareHypervisorHost dsHost = targetHyperHost == null ? sourceHyperHost : targetHyperHost;
ManagedObjectReference morDatastore = null;
morDatastore = getTargetDatastoreMOReference(poolUuid, dsHost);
if (morDatastore == null) {
String msg = String.format("Unable to find the target datastore: %s on host: %s to execute migration", poolUuid, dsHost.getHyperHostName());
s_logger.error(msg);
throw new CloudRuntimeException(msg);
}
relocateSpec.setDatastore(morDatastore);
} else if (CollectionUtils.isNotEmpty(volToFiler)) {
// Specify destination datastore location for each volume
VmwareHypervisorHost dsHost = targetHyperHost == null ? sourceHyperHost : targetHyperHost;
for (Pair<VolumeTO, StorageFilerTO> entry : volToFiler) {
VolumeTO volume = entry.first();
StorageFilerTO filerTo = entry.second();
if (s_logger.isDebugEnabled()) {
s_logger.debug(String.format("Preparing spec for volume: %s to migrate it to datastore: %s", volume.getName(), filerTo.getUuid()));
}
ManagedObjectReference morVolumeDatastore = getTargetDatastoreMOReference(filerTo.getUuid(), dsHost);
if (morVolumeDatastore == null) {
String msg = String.format("Unable to find the target datastore: %s in datacenter: %s to execute migration", filerTo.getUuid(), dcMo.getName());
s_logger.error(msg);
throw new CloudRuntimeException(msg);
}
String mountedDs = getMountedDatastoreName(sourceHyperHost, srcHostApiVersion, filerTo);
if (mountedDs != null) {
mountedDatastoresAtSource.add(mountedDs);
}
if (volume.getType() == Volume.Type.ROOT) {
relocateSpec.setDatastore(morVolumeDatastore);
}
VirtualMachineRelocateSpecDiskLocator diskLocator = new VirtualMachineRelocateSpecDiskLocator();
diskLocator.setDatastore(morVolumeDatastore);
Pair<VirtualDisk, String> diskInfo = getVirtualDiskInfo(vmMo, volume.getPath() + VMDK_EXTENSION);
String vmdkAbsFile = getAbsoluteVmdkFile(diskInfo.first());
if (vmdkAbsFile != null && !vmdkAbsFile.isEmpty()) {
vmMo.updateAdapterTypeIfRequired(vmdkAbsFile);
}
int diskId = diskInfo.first().getKey();
diskLocator.setDiskId(diskId);
diskLocators.add(diskLocator);
volumeDeviceKey.put(volume.getId(), diskId);
}
// If a target datastore is provided for the VM, then by default all volumes associated with the VM will be migrated to that target datastore.
// Hence set the existing datastore as target datastore for volumes that are not to be migrated.
List<Pair<Integer, ManagedObjectReference>> diskDatastores = vmMo.getAllDiskDatastores();
for (Pair<Integer, ManagedObjectReference> diskDatastore : diskDatastores) {
if (!volumeDeviceKey.containsValue(diskDatastore.first().intValue())) {
VirtualMachineRelocateSpecDiskLocator diskLocator = new VirtualMachineRelocateSpecDiskLocator();
diskLocator.setDiskId(diskDatastore.first().intValue());
diskLocator.setDatastore(diskDatastore.second());
diskLocators.add(diskLocator);
}
}
relocateSpec.getDisk().addAll(diskLocators);
}
// Specific section for MigrateVmWithStorageCommand
if (vmTo != null) {
// Prepare network at target before migration
NicTO[] nics = vmTo.getNics();
for (NicTO nic : nics) {
// prepare network on the host
prepareNetworkFromNicInfo((HostMO) targetHyperHost, nic, false, vmTo.getType());
}
// Ensure secondary storage mounted on target host
VmwareManager mgr = targetHyperHost.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
Pair<String, Long> secStoreUrlAndId = mgr.getSecondaryStorageStoreUrlAndId(Long.parseLong(_dcId));
String secStoreUrl = secStoreUrlAndId.first();
Long secStoreId = secStoreUrlAndId.second();
if (secStoreUrl == null) {
String msg = "secondary storage for dc " + _dcId + " is not ready yet?";
throw new Exception(msg);
}
mgr.prepareSecondaryStorageStore(secStoreUrl, secStoreId);
ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnSpecificHost(secStoreUrl, targetHyperHost);
if (morSecDs == null) {
throw new Exception(String.format("Failed to prepare secondary storage on host, secondary store url: %s", secStoreUrl));
}
}
if (srcHostApiVersion.compareTo("5.1") < 0) {
// Migrate VM's volumes to target datastore(s).
if (!vmMo.changeDatastore(relocateSpec)) {
throw new Exception("Change datastore operation failed during storage migration");
} else {
s_logger.debug(String.format("Successfully migrated storage of VM: %s to target datastore(s)", vmName));
}
// Migrate VM to target host.
if (targetHyperHost != null) {
ManagedObjectReference morPool = targetHyperHost.getHyperHostOwnerResourcePool();
if (!vmMo.migrate(morPool, targetHyperHost.getMor())) {
throw new Exception("VM migration to target host failed during storage migration");
} else {
s_logger.debug(String.format("Successfully migrated VM: %s from host %s to %s", vmName, sourceHyperHost.getHyperHostName(), targetHyperHost.getHyperHostName()));
}
}
} else {
// Add target host to relocate spec
if (targetHyperHost != null) {
relocateSpec.setHost(targetHyperHost.getMor());
relocateSpec.setPool(targetHyperHost.getHyperHostOwnerResourcePool());
}
if (!vmMo.changeDatastore(relocateSpec)) {
throw new Exception("Change datastore operation failed during storage migration");
} else {
String msg = String.format("Successfully migrated VM: %s with its storage to target datastore(s)", vmName);
if (targetHyperHost != null) {
msg = String.format("%s from host %s to %s", msg, sourceHyperHost.getHyperHostName(), targetHyperHost.getHyperHostName());
}
s_logger.debug(msg);
}
}
// In case of a linked clone VM, if VM's disks are not consolidated, further VM operations such as volume snapshot, VM snapshot etc. will result in DB inconsistencies.
if (!vmMo.consolidateVmDisks()) {
s_logger.warn("VM disk consolidation failed after storage migration. Yet proceeding with VM migration.");
} else {
s_logger.debug(String.format("Successfully consolidated disks of VM: %s", vmName));
}
if (MapUtils.isNotEmpty(volumeDeviceKey)) {
// Update and return volume path and chain info for every disk because that could have changed after migration
VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
for (Pair<VolumeTO, StorageFilerTO> entry : volToFiler) {
final VolumeTO volume = entry.first();
final long volumeId = volume.getId();
VirtualDisk[] disks = vmMo.getAllDiskDevice();
for (VirtualDisk disk : disks) {
if (volumeDeviceKey.get(volumeId) == disk.getKey()) {
VolumeObjectTO newVol = new VolumeObjectTO();
newVol.setDataStoreUuid(entry.second().getUuid());
String newPath = vmMo.getVmdkFileBaseName(disk);
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(targetHyperHost != null ? targetHyperHost : sourceHyperHost, entry.second().getUuid());
DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDs);
VirtualMachineDiskInfo diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(newPath, dsMo.getName());
newVol.setId(volumeId);
newVol.setPath(newPath);
newVol.setChainInfo(_gson.toJson(diskInfo));
volumeToList.add(newVol);
break;
}
}
}
}
} catch (Throwable e) {
if (e instanceof RemoteException) {
s_logger.warn("Encountered remote exception at vCenter, invalidating VMware session context");
invalidateServiceContext();
}
throw e;
} finally {
// Cleanup datastores mounted on source host
for (String mountedDatastore : mountedDatastoresAtSource) {
s_logger.debug("Attempting to unmount datastore " + mountedDatastore + " at " + sourceHyperHost.getHyperHostName());
try {
sourceHyperHost.unmountDatastore(mountedDatastore);
} catch (Exception unmountEx) {
s_logger.warn("Failed to unmount datastore " + mountedDatastore + " at " + sourceHyperHost.getHyperHostName() + ". Seems the datastore is still being used by " + sourceHyperHost.getHyperHostName() + ". Please unmount manually to cleanup.");
}
s_logger.debug("Successfully unmounted datastore " + mountedDatastore + " at " + sourceHyperHost.getHyperHostName());
}
}
// Only when volToFiler is not empty a filled list of VolumeObjectTO is returned else it will be empty
return volumeToList;
}
use of com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost in project cloudstack by apache.
the class VmwareResource method execute.
protected Answer execute(ReadyCommand cmd) {
try {
VmwareContext context = getServiceContext();
VmwareHypervisorHost hyperHost = getHyperHost(context);
if (hyperHost.isHyperHostConnected()) {
return new ReadyAnswer(cmd);
} else {
return new ReadyAnswer(cmd, "Host is not in connect state");
}
} catch (Exception e) {
s_logger.error("Unexpected exception: ", e);
return new ReadyAnswer(cmd, VmwareHelper.getExceptionMessage(e));
}
}
use of com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost in project cloudstack by apache.
the class VmwareResource method getVmStates.
private HashMap<String, PowerState> getVmStates() throws Exception {
VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext());
int key = ((HostMO) hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME);
if (key == 0) {
s_logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!");
}
String instanceNameCustomField = "value[" + key + "]";
// CLOUD_VM_INTERNAL_NAME stores the internal CS generated vm name. This was earlier stored in name. Now, name can be either the hostname or
// the internal CS name, but the custom field CLOUD_VM_INTERNAL_NAME always stores the internal CS name.
ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[] { "name", "runtime.powerState", "config.template", instanceNameCustomField });
HashMap<String, PowerState> newStates = new HashMap<String, PowerState>();
if (ocs != null && ocs.length > 0) {
for (ObjectContent oc : ocs) {
List<DynamicProperty> objProps = oc.getPropSet();
if (objProps != null) {
boolean isTemplate = false;
String name = null;
String VMInternalCSName = null;
VirtualMachinePowerState powerState = VirtualMachinePowerState.POWERED_OFF;
for (DynamicProperty objProp : objProps) {
if (objProp.getName().equals("config.template")) {
if (objProp.getVal().toString().equalsIgnoreCase("true")) {
isTemplate = true;
}
} else if (objProp.getName().equals("runtime.powerState")) {
powerState = (VirtualMachinePowerState) objProp.getVal();
} else if (objProp.getName().equals("name")) {
name = (String) objProp.getVal();
} else if (objProp.getName().contains(instanceNameCustomField)) {
if (objProp.getVal() != null)
VMInternalCSName = ((CustomFieldStringValue) objProp.getVal()).getValue();
} else {
assert (false);
}
}
if (VMInternalCSName != null)
name = VMInternalCSName;
if (!isTemplate) {
newStates.put(name, convertPowerState(powerState));
}
}
}
}
return newStates;
}
use of com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost in project cloudstack by apache.
the class VmwareResource method execute.
protected Answer execute(GetVncPortCommand cmd) {
try {
VmwareContext context = getServiceContext();
VmwareHypervisorHost hyperHost = getHyperHost(context);
assert (hyperHost instanceof HostMO);
VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(cmd.getName());
if (vmMo == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to find the owner VM for GetVncPortCommand on host " + hyperHost.getHyperHostName() + ", try within datacenter");
}
vmMo = hyperHost.findVmOnPeerHyperHost(cmd.getName());
if (vmMo == null) {
throw new Exception("Unable to find VM in vSphere, vm: " + cmd.getName());
}
}
Pair<String, Integer> portInfo = vmMo.getVncPort(mgr.getManagementPortGroupByHost((HostMO) hyperHost));
if (s_logger.isTraceEnabled()) {
s_logger.trace("Found vnc port info. vm: " + cmd.getName() + " host: " + portInfo.first() + ", vnc port: " + portInfo.second());
}
return new GetVncPortAnswer(cmd, portInfo.first(), portInfo.second());
} catch (Throwable e) {
return new GetVncPortAnswer(cmd, createLogMessageException(e, cmd));
}
}
Aggregations