use of org.apache.cloudstack.storage.to.VolumeObjectTO in project cloudstack by apache.
the class VmwareResource method execute.
protected Answer execute(MigrateWithStorageCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource MigrateWithStorageCommand: " + _gson.toJson(cmd));
}
VirtualMachineTO vmTo = cmd.getVirtualMachine();
String vmName = vmTo.getName();
VmwareHypervisorHost srcHyperHost = null;
VmwareHypervisorHost tgtHyperHost = null;
VirtualMachineMO vmMo = null;
ManagedObjectReference morDsAtTarget = null;
ManagedObjectReference morDsAtSource = null;
ManagedObjectReference morDc = null;
ManagedObjectReference morDcOfTargetHost = null;
ManagedObjectReference morTgtHost = new ManagedObjectReference();
ManagedObjectReference morTgtDatastore = new ManagedObjectReference();
VirtualMachineRelocateSpec relocateSpec = new VirtualMachineRelocateSpec();
List<VirtualMachineRelocateSpecDiskLocator> diskLocators = new ArrayList<VirtualMachineRelocateSpecDiskLocator>();
VirtualMachineRelocateSpecDiskLocator diskLocator = null;
String tgtDsName = "";
String tgtDsHost;
String tgtDsPath;
int tgtDsPort;
VolumeTO volume;
StorageFilerTO filerTo;
Set<String> mountedDatastoresAtSource = new HashSet<String>();
List<VolumeObjectTO> volumeToList = new ArrayList<VolumeObjectTO>();
Map<Long, Integer> volumeDeviceKey = new HashMap<Long, Integer>();
List<Pair<VolumeTO, StorageFilerTO>> volToFiler = cmd.getVolumeToFilerAsList();
String tgtHost = cmd.getTargetHost();
String tgtHostMorInfo = tgtHost.split("@")[0];
morTgtHost.setType(tgtHostMorInfo.split(":")[0]);
morTgtHost.setValue(tgtHostMorInfo.split(":")[1]);
try {
srcHyperHost = getHyperHost(getServiceContext());
tgtHyperHost = new HostMO(getServiceContext(), morTgtHost);
morDc = srcHyperHost.getHyperHostDatacenter();
morDcOfTargetHost = tgtHyperHost.getHyperHostDatacenter();
if (!morDc.getValue().equalsIgnoreCase(morDcOfTargetHost.getValue())) {
String msg = "Source host & target host are in different datacentesr";
throw new CloudRuntimeException(msg);
}
VmwareManager mgr = tgtHyperHost.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
String srcHostApiVersion = ((HostMO) srcHyperHost).getHostAboutInfo().getApiVersion();
// find VM through datacenter (VM is not at the target host yet)
vmMo = srcHyperHost.findVmOnPeerHyperHost(vmName);
if (vmMo == null) {
String msg = "VM " + vmName + " does not exist in VMware datacenter " + morDc.getValue();
s_logger.error(msg);
throw new Exception(msg);
}
vmName = vmMo.getName();
// Specify destination datastore location for each volume
for (Pair<VolumeTO, StorageFilerTO> entry : volToFiler) {
volume = entry.first();
filerTo = entry.second();
s_logger.debug("Preparing spec for volume : " + volume.getName());
morDsAtTarget = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(tgtHyperHost, filerTo.getUuid());
morDsAtSource = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(srcHyperHost, filerTo.getUuid());
if (morDsAtTarget == null) {
String msg = "Unable to find the target datastore: " + filerTo.getUuid() + " on target host: " + tgtHyperHost.getHyperHostName() + " to execute MigrateWithStorageCommand";
s_logger.error(msg);
throw new Exception(msg);
}
morTgtDatastore = morDsAtTarget;
// So since only the datastore will be changed first, ensure the target datastore is mounted on source host.
if (srcHostApiVersion.compareTo("5.1") < 0) {
tgtDsName = filerTo.getUuid().replace("-", "");
tgtDsHost = filerTo.getHost();
tgtDsPath = filerTo.getPath();
tgtDsPort = filerTo.getPort();
// If datastore is NFS and target datastore is not already mounted on source host then mount the datastore.
if (filerTo.getType().equals(StoragePoolType.NetworkFilesystem)) {
if (morDsAtSource == null) {
morDsAtSource = srcHyperHost.mountDatastore(false, tgtDsHost, tgtDsPort, tgtDsPath, tgtDsName);
if (morDsAtSource == null) {
throw new Exception("Unable to mount NFS datastore " + tgtDsHost + ":/" + tgtDsPath + " on " + _hostName);
}
mountedDatastoresAtSource.add(tgtDsName);
s_logger.debug("Mounted datastore " + tgtDsHost + ":/" + tgtDsPath + " on " + _hostName);
}
}
// If datastore is VMFS and target datastore is not mounted or accessible to source host then fail migration.
if (filerTo.getType().equals(StoragePoolType.VMFS)) {
if (morDsAtSource == null) {
s_logger.warn("If host version is below 5.1, then target VMFS datastore(s) need to manually mounted on source host for a successful live storage migration.");
throw new Exception("Target VMFS datastore: " + tgtDsPath + " is not mounted on source host: " + _hostName);
}
DatastoreMO dsAtSourceMo = new DatastoreMO(getServiceContext(), morDsAtSource);
String srcHostValue = srcHyperHost.getMor().getValue();
if (!dsAtSourceMo.isAccessibleToHost(srcHostValue)) {
s_logger.warn("If host version is below 5.1, then target VMFS datastore(s) need to accessible to source host for a successful live storage migration.");
throw new Exception("Target VMFS datastore: " + tgtDsPath + " is not accessible on source host: " + _hostName);
}
}
morTgtDatastore = morDsAtSource;
}
if (volume.getType() == Volume.Type.ROOT) {
relocateSpec.setDatastore(morTgtDatastore);
}
diskLocator = new VirtualMachineRelocateSpecDiskLocator();
diskLocator.setDatastore(morDsAtSource);
Pair<VirtualDisk, String> diskInfo = getVirtualDiskInfo(vmMo, volume.getPath() + ".vmdk");
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())) {
diskLocator = new VirtualMachineRelocateSpecDiskLocator();
diskLocator.setDiskId(diskDatastore.first().intValue());
diskLocator.setDatastore(diskDatastore.second());
diskLocators.add(diskLocator);
}
}
relocateSpec.getDisk().addAll(diskLocators);
// Prepare network at target before migration
NicTO[] nics = vmTo.getNics();
for (NicTO nic : nics) {
// prepare network on the host
prepareNetworkFromNicInfo(new HostMO(getServiceContext(), morTgtHost), nic, false, vmTo.getType());
}
// Ensure secondary storage mounted on target host
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, tgtHyperHost);
if (morSecDs == null) {
String msg = "Failed to prepare secondary storage on host, secondary store url: " + secStoreUrl;
throw new Exception(msg);
}
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("Successfully migrated storage of VM " + vmName + " to target datastore(s)");
}
// Migrate VM to target host.
ManagedObjectReference morPool = tgtHyperHost.getHyperHostOwnerResourcePool();
if (!vmMo.migrate(morPool, tgtHyperHost.getMor())) {
throw new Exception("VM migration to target host failed during storage migration");
} else {
s_logger.debug("Successfully migrated VM " + vmName + " from " + _hostName + " to " + tgtHyperHost.getHyperHostName());
}
} else {
// Simultaneously migrate VM's volumes to target datastore and VM to target host.
relocateSpec.setHost(tgtHyperHost.getMor());
relocateSpec.setPool(tgtHyperHost.getHyperHostOwnerResourcePool());
if (!vmMo.changeDatastore(relocateSpec)) {
throw new Exception("Change datastore operation failed during storage migration");
} else {
s_logger.debug("Successfully migrated VM " + vmName + " from " + _hostName + " to " + tgtHyperHost.getHyperHostName() + " and its storage to target datastore(s)");
}
}
// 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("Successfully consolidated disks of VM " + vmName + ".");
}
// 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) {
volume = entry.first();
long volumeId = volume.getId();
VirtualDisk[] disks = vmMo.getAllDiskDevice();
for (VirtualDisk disk : disks) {
if (volumeDeviceKey.get(volumeId) == disk.getKey()) {
VolumeObjectTO newVol = new VolumeObjectTO();
String newPath = vmMo.getVmdkFileBaseName(disk);
String poolName = entry.second().getUuid().replace("-", "");
VirtualMachineDiskInfo diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(newPath, poolName);
newVol.setId(volumeId);
newVol.setPath(newPath);
newVol.setChainInfo(_gson.toJson(diskInfo));
volumeToList.add(newVol);
break;
}
}
}
return new MigrateWithStorageAnswer(cmd, volumeToList);
} catch (Throwable e) {
if (e instanceof RemoteException) {
s_logger.warn("Encountered remote exception at vCenter, invalidating VMware session context");
invalidateServiceContext();
}
String msg = "MigrationCommand failed due to " + VmwareHelper.getExceptionMessage(e);
s_logger.warn(msg, e);
return new MigrateWithStorageAnswer(cmd, (Exception) e);
} finally {
// Cleanup datastores mounted on source host
for (String mountedDatastore : mountedDatastoresAtSource) {
s_logger.debug("Attempting to unmount datastore " + mountedDatastore + " at " + _hostName);
try {
srcHyperHost.unmountDatastore(mountedDatastore);
} catch (Exception unmountEx) {
s_logger.debug("Failed to unmount datastore " + mountedDatastore + " at " + _hostName + ". Seems the datastore is still being used by " + _hostName + ". Please unmount manually to cleanup.");
}
s_logger.debug("Successfully unmounted datastore " + mountedDatastore + " at " + _hostName);
}
}
}
use of org.apache.cloudstack.storage.to.VolumeObjectTO in project cloudstack by apache.
the class VmwareResource method syncDiskChain.
// return the finalized disk chain for startup, from top to bottom
private String[] syncDiskChain(DatacenterMO dcMo, VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO vol, VirtualMachineDiskInfo diskInfo, HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails) throws Exception {
VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData();
DataStoreTO primaryStore = volumeTO.getDataStore();
Map<String, String> details = vol.getDetails();
boolean isManaged = false;
String iScsiName = null;
if (details != null) {
isManaged = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
iScsiName = details.get(DiskTO.IQN);
}
// if the storage is managed, iScsiName should not be null
String datastoreName = isManaged ? VmwareResource.getDatastoreName(iScsiName) : primaryStore.getUuid();
Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(datastoreName);
if (volumeDsDetails == null) {
throw new Exception("Primary datastore " + primaryStore.getUuid() + " is not mounted on host.");
}
DatastoreMO dsMo = volumeDsDetails.second();
// we will honor vCenter's meta if it exists
if (diskInfo != null) {
// to deal with run-time upgrade to maintain the new datastore folder structure
String[] disks = diskInfo.getDiskChain();
for (int i = 0; i < disks.length; i++) {
DatastoreFile file = new DatastoreFile(disks[i]);
if (!isManaged && file.getDir() != null && file.getDir().isEmpty()) {
s_logger.info("Perform run-time datastore folder upgrade. sync " + disks[i] + " to VM folder");
disks[i] = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, file.getFileBaseName());
}
}
return disks;
}
final String datastoreDiskPath;
if (isManaged) {
if (volumeTO.getVolumeType() == Volume.Type.ROOT) {
datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getName());
} else {
datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
}
} else {
datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getPath());
}
if (!dsMo.fileExists(datastoreDiskPath)) {
s_logger.warn("Volume " + volumeTO.getId() + " does not seem to exist on datastore, out of sync? path: " + datastoreDiskPath);
}
return new String[] { datastoreDiskPath };
}
use of org.apache.cloudstack.storage.to.VolumeObjectTO in project cloudstack by apache.
the class VmwareResource method postDiskConfigBeforeStart.
private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO[] sortedDisks, int ideControllerKey, int scsiControllerKey, Map<String, String> iqnToPath, VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception {
VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
for (DiskTO vol : sortedDisks) {
if (vol.getType() == Volume.Type.ISO)
continue;
VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData();
VirtualMachineDiskInfo diskInfo = getMatchingExistingDisk(diskInfoBuilder, vol, hyperHost, context);
assert (diskInfo != null);
String[] diskChain = diskInfo.getDiskChain();
assert (diskChain.length > 0);
Map<String, String> details = vol.getDetails();
boolean managed = false;
if (details != null) {
managed = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
}
DatastoreFile file = new DatastoreFile(diskChain[0]);
if (managed) {
DatastoreFile originalFile = new DatastoreFile(volumeTO.getPath());
if (!file.getFileBaseName().equalsIgnoreCase(originalFile.getFileBaseName())) {
if (s_logger.isInfoEnabled())
s_logger.info("Detected disk-chain top file change on volume: " + volumeTO.getId() + " " + volumeTO.getPath() + " -> " + diskChain[0]);
}
} else {
if (!file.getFileBaseName().equalsIgnoreCase(volumeTO.getPath())) {
if (s_logger.isInfoEnabled())
s_logger.info("Detected disk-chain top file change on volume: " + volumeTO.getId() + " " + volumeTO.getPath() + " -> " + file.getFileBaseName());
}
}
VolumeObjectTO volInSpec = getVolumeInSpec(vmSpec, volumeTO);
if (volInSpec != null) {
if (managed) {
String datastoreVolumePath = diskChain[0];
iqnToPath.put(details.get(DiskTO.IQN), datastoreVolumePath);
vol.setPath(datastoreVolumePath);
volumeTO.setPath(datastoreVolumePath);
volInSpec.setPath(datastoreVolumePath);
} else {
volInSpec.setPath(file.getFileBaseName());
}
volInSpec.setChainInfo(_gson.toJson(diskInfo));
}
}
}
use of org.apache.cloudstack.storage.to.VolumeObjectTO in project cloudstack by apache.
the class VmwareResource method inferDatastoreDetailsFromDiskInfo.
private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context, DiskTO[] disks, Command cmd) throws Exception {
HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> mapIdToMors = new HashMap<String, Pair<ManagedObjectReference, DatastoreMO>>();
assert (hyperHost != null) && (context != null);
for (DiskTO vol : disks) {
if (vol.getType() != Volume.Type.ISO) {
VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData();
DataStoreTO primaryStore = volumeTO.getDataStore();
String poolUuid = primaryStore.getUuid();
if (mapIdToMors.get(poolUuid) == null) {
boolean isManaged = false;
Map<String, String> details = vol.getDetails();
if (details != null) {
isManaged = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
}
if (isManaged) {
// details should not be null for managed storage (it may or may not be null for non-managed storage)
String iScsiName = details.get(DiskTO.IQN);
String datastoreName = VmwareResource.getDatastoreName(iScsiName);
ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, datastoreName);
// create the datastore, and create a VMDK file in the datastore
if (morDatastore == null) {
morDatastore = _storageProcessor.prepareManagedStorage(context, hyperHost, null, iScsiName, details.get(DiskTO.STORAGE_HOST), Integer.parseInt(details.get(DiskTO.STORAGE_PORT)), volumeTO.getVolumeType() == Volume.Type.ROOT ? volumeTO.getName() : null, details.get(DiskTO.CHAP_INITIATOR_USERNAME), details.get(DiskTO.CHAP_INITIATOR_SECRET), details.get(DiskTO.CHAP_TARGET_USERNAME), details.get(DiskTO.CHAP_TARGET_SECRET), Long.parseLong(details.get(DiskTO.VOLUME_SIZE)), cmd);
DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDatastore);
String datastoreVolumePath = dsMo.getDatastorePath((volumeTO.getVolumeType() == Volume.Type.ROOT ? volumeTO.getName() : dsMo.getName()) + ".vmdk");
volumeTO.setPath(datastoreVolumePath);
vol.setPath(datastoreVolumePath);
}
mapIdToMors.put(datastoreName, new Pair<ManagedObjectReference, DatastoreMO>(morDatastore, new DatastoreMO(context, morDatastore)));
} else {
ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid);
if (morDatastore == null) {
String msg = "Failed to get the mounted datastore for the volume's pool " + poolUuid;
s_logger.error(msg);
throw new Exception(msg);
}
mapIdToMors.put(poolUuid, new Pair<ManagedObjectReference, DatastoreMO>(morDatastore, new DatastoreMO(context, morDatastore)));
}
}
}
}
return mapIdToMors;
}
use of org.apache.cloudstack.storage.to.VolumeObjectTO in project cloudstack by apache.
the class VMSnapshotManagerImpl method createRestoreCommand.
@Override
public RestoreVMSnapshotCommand createRestoreCommand(UserVmVO userVm, List<VMSnapshotVO> vmSnapshotVOs) {
if (!HypervisorType.KVM.equals(userVm.getHypervisorType()))
return null;
List<VMSnapshotTO> snapshots = new ArrayList<VMSnapshotTO>();
Map<Long, VMSnapshotTO> snapshotAndParents = new HashMap<Long, VMSnapshotTO>();
for (VMSnapshotVO vmSnapshotVO : vmSnapshotVOs) {
if (vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory) {
VMSnapshotVO snapshot = _vmSnapshotDao.findById(vmSnapshotVO.getId());
VMSnapshotTO parent = getSnapshotWithParents(snapshot).getParent();
VMSnapshotOptions options = snapshot.getOptions();
boolean quiescevm = true;
if (options != null)
quiescevm = options.needQuiesceVM();
VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(snapshot.getId(), snapshot.getName(), snapshot.getType(), snapshot.getCreated().getTime(), snapshot.getDescription(), snapshot.getCurrent(), parent, quiescevm);
snapshots.add(vmSnapshotTO);
snapshotAndParents.put(vmSnapshotVO.getId(), parent);
}
}
if (snapshotAndParents.isEmpty())
return null;
// prepare RestoreVMSnapshotCommand
String vmInstanceName = userVm.getInstanceName();
List<VolumeObjectTO> volumeTOs = getVolumeTOList(userVm.getId());
GuestOSVO guestOS = _guestOSDao.findById(userVm.getGuestOSId());
RestoreVMSnapshotCommand restoreSnapshotCommand = new RestoreVMSnapshotCommand(vmInstanceName, null, volumeTOs, guestOS.getDisplayName());
restoreSnapshotCommand.setSnapshots(snapshots);
restoreSnapshotCommand.setSnapshotAndParents(snapshotAndParents);
return restoreSnapshotCommand;
}
Aggregations