boolean isFirstDs = true;
String tgtDsName = "";
String tgtDsNfsHost;
String tgtDsNfsPath;
int tgtDsNfsPort;
VolumeTO volume;
StorageFilerTO filerTo;
Set<String> mountedDatastoresAtSource = new HashSet<String>();
List<VolumeObjectTO> volumeToList = new ArrayList<VolumeObjectTO>();
Map<Long, Integer> volumeDeviceKey = new HashMap<Long, Integer>();
Map<VolumeTO, StorageFilerTO> volToFiler = cmd.getVolumeToFiler();
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);
// 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);
}
// Get details of each target datastore & attach to source host.
for (Entry<VolumeTO, StorageFilerTO> entry : volToFiler.entrySet()) {
volume = entry.getKey();
filerTo = entry.getValue();
tgtDsName = filerTo.getUuid().replace("-", "");
tgtDsNfsHost = filerTo.getHost();
tgtDsNfsPath = filerTo.getPath();
tgtDsNfsPort = filerTo.getPort();
s_logger.debug("Preparing spec for volume : " + volume.getName());
morDsAtTarget = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(tgtHyperHost, filerTo.getUuid());
if (morDsAtTarget == null) {
String msg = "Unable to find the mounted datastore with uuid " + morDsAtTarget + " to execute MigrateWithStorageCommand";
s_logger.error(msg);
throw new Exception(msg);
}
morDsAtSource = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(srcHyperHost, filerTo.getUuid());
if (morDsAtSource == null) {
morDsAtSource = srcHyperHost.mountDatastore(false, tgtDsNfsHost, tgtDsNfsPort, tgtDsNfsPath, tgtDsName);
if (morDsAtSource == null) {
throw new Exception("Unable to mount datastore " + tgtDsNfsHost + ":/" + tgtDsNfsPath + " on " + _hostName);
}
mountedDatastoresAtSource.add(tgtDsName);
s_logger.debug("Mounted datastore " + tgtDsNfsHost + ":/" + tgtDsNfsPath + " on " + _hostName);
}
if (isFirstDs) {
relocateSpec.setDatastore(morDsAtSource);
isFirstDs = false;
}
VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(new DatastoreMO(srcHyperHost.getContext(), morDsAtSource), vmName, volume.getPath() +
".vmdk");
diskLocator = new VirtualMachineRelocateSpecDiskLocator();
diskLocator.setDatastore(morDsAtSource);
int diskId = getVirtualDiskInfo(vmMo, volume.getPath() + ".vmdk");
diskLocator.setDiskId(diskId);
diskLocators.add(diskLocator);
volumeDeviceKey.put(volume.getId(), diskId);
}
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
String secStoreUrl = mgr.getSecondaryStorageStoreUrl(Long.parseLong(_dcId));
if (secStoreUrl == null) {
String msg = "secondary storage for dc " + _dcId + " is not ready yet?";
throw new Exception(msg);
}
mgr.prepareSecondaryStorageStore(secStoreUrl);
ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnHost(secStoreUrl);
if (morSecDs == null) {
String msg = "Failed to prepare secondary storage on host, secondary store url: " + secStoreUrl;
throw new Exception(msg);
}
// Change datastore
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)");
}
// Update and return volume path for every disk because that could have changed after migration
for (Entry<VolumeTO, StorageFilerTO> entry : volToFiler.entrySet()) {
volume = entry.getKey();
long volumeId = volume.getId();
VirtualDisk[] disks = vmMo.getAllDiskDevice();
for (VirtualDisk disk : disks) {
if (volumeDeviceKey.get(volumeId) == disk.getKey()) {
VolumeObjectTO newVol = new VolumeObjectTO();
newVol.setId(volumeId);