Fix resize volume and migrate volume to update volume path if DRS is applied on volume in datastore cluster (#5539)

* Fix resize volume and migrate volume to update volume path if DRS is applied on volume in datastore cluster

* Change in constructors

* Naming changes

* Remove commented code

* Refactor code for more readability

* Addressed review comments on code refactor
This commit is contained in:
Harikrishna 2021-10-05 05:28:25 +05:30 committed by GitHub
parent 6e216dd0d1
commit cd4e7e031a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 260 additions and 105 deletions

View File

@ -30,6 +30,7 @@ import com.cloud.storage.Volume;
public class MigrateVolumeCommand extends Command {
long volumeId;
String volumePath;
String chainInfo;
StorageFilerTO pool;
StorageFilerTO sourcePool;
String attachedVmName;
@ -49,14 +50,22 @@ public class MigrateVolumeCommand extends Command {
}
public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool pool, String attachedVmName, Volume.Type volumeType, int timeout) {
this(volumeId,volumePath,pool,timeout);
this(volumeId, volumePath, pool, timeout);
this.attachedVmName = attachedVmName;
this.volumeType = volumeType;
this.setWait(timeout);
}
public MigrateVolumeCommand(long volumeId, String volumePath, String attachedVmName, StoragePool sourcePool, StoragePool targetPool, String hostGuidInTargetCluster) {
this(volumeId,volumePath,targetPool, attachedVmName, Volume.Type.UNKNOWN, -1);
public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool pool, String attachedVmName, Volume.Type volumeType, int timeout, String chainInfo) {
this(volumeId, volumePath, pool, timeout);
this.attachedVmName = attachedVmName;
this.volumeType = volumeType;
this.chainInfo = chainInfo;
this.setWait(timeout);
}
public MigrateVolumeCommand(long volumeId, String volumePath, String attachedVmName, StoragePool sourcePool, StoragePool targetPool, String hostGuidInTargetCluster, String chainInfo) {
this(volumeId,volumePath,targetPool, attachedVmName, Volume.Type.UNKNOWN, -1, chainInfo);
this.sourcePool = new StorageFilerTO(sourcePool);
this.hostGuidInTargetCluster = hostGuidInTargetCluster;
}
@ -134,4 +143,6 @@ public class MigrateVolumeCommand extends Command {
public int getWaitInMillSeconds() {
return getWait() * 1000;
}
public String getChainInfo() { return chainInfo; }
}

View File

@ -29,6 +29,7 @@ public class ResizeVolumeCommand extends Command {
private Long newSize;
private boolean shrinkOk;
private String vmInstance;
private String chainInfo;
/* For managed storage */
private boolean managed;
@ -47,6 +48,11 @@ public class ResizeVolumeCommand extends Command {
this.managed = false;
}
public ResizeVolumeCommand(String path, StorageFilerTO pool, Long currentSize, Long newSize, boolean shrinkOk, String vmInstance, String chainInfo) {
this(path, pool, currentSize, newSize, shrinkOk, vmInstance);
this.chainInfo = chainInfo;
}
public ResizeVolumeCommand(String path, StorageFilerTO pool, Long currentSize, Long newSize, boolean shrinkOk, String vmInstance,
boolean isManaged, String iScsiName) {
this(path, pool, currentSize, newSize, shrinkOk, vmInstance);
@ -81,6 +87,8 @@ public class ResizeVolumeCommand extends Command {
public String get_iScsiName() {return iScsiName; }
public String getChainInfo() {return chainInfo; }
/**
* {@inheritDoc}
*/

View File

@ -24,6 +24,8 @@ import java.util.Map;
import javax.inject.Inject;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.storage.Storage;
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
@ -447,8 +449,13 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
int waitInterval = NumbersUtil.parseInt(value, Integer.parseInt(Config.MigrateWait.getDefaultValue()));
VolumeInfo volume = (VolumeInfo)srcData;
StoragePool srcPool = (StoragePool)dataStoreMgr.getDataStore(srcData.getDataStore().getId(), DataStoreRole.Primary);
StoragePool destPool = (StoragePool)dataStoreMgr.getDataStore(destData.getDataStore().getId(), DataStoreRole.Primary);
MigrateVolumeCommand command = new MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool, volume.getAttachedVmName(), volume.getVolumeType(), waitInterval);
MigrateVolumeCommand command = new MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool, volume.getAttachedVmName(), volume.getVolumeType(), waitInterval, volume.getChainInfo());
if (srcPool.getParent() != 0) {
command.setContextParam(DiskTO.PROTOCOL_TYPE, Storage.StoragePoolType.DatastoreCluster.toString());
}
EndPoint ep = selector.select(srcData, StorageAction.MIGRATEVOLUME);
Answer answer = null;
if (ep == null) {

View File

@ -775,9 +775,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
String vmName = cmd.getInstanceName();
long newSize = cmd.getNewSize() / ResourceType.bytesToKiB;
long oldSize = cmd.getCurrentSize() / ResourceType.bytesToKiB;
boolean managed = cmd.isManaged();
String poolUUID = cmd.getPoolUuid();
String chainInfo = cmd.getChainInfo();
boolean useWorkerVm = false;
VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext());
VmwareContext context = getServiceContext();
VmwareHypervisorHost hyperHost = getHyperHost(context);
VirtualMachineMO vmMo = null;
String vmdkDataStorePath = null;
@ -789,24 +793,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
} else if (newSize == oldSize) {
return new ResizeVolumeAnswer(cmd, true, "success", newSize * ResourceType.bytesToKiB);
}
/*
// FR41 this is yet to fix
ManagedObjectReference morDS1 = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, cmd.getPoolUuid());
DatastoreMO dsMo1 = new DatastoreMO(hyperHost.getContext(), morDS1);
vmdkDataStorePath = VmwareStorageLayoutHelper.getLegacyDatastorePathFromVmdkFileName(dsMo1, path + VMDK_EXTENSION);
DatastoreFile dsFile1 = new DatastoreFile(vmdkDataStorePath);
s_logger.debug("vDiskid does not exist for volume " + vmdkDataStorePath + " registering the disk now");
VirtualStorageObjectManagerMO vStorageObjectManagerMO = new VirtualStorageObjectManagerMO(getServiceContext());
try {
VStorageObject vStorageObject = vStorageObjectManagerMO.registerVirtualDisk(dsFile1, null, dsMo1.getOwnerDatacenter().second());
VStorageObjectConfigInfo diskConfigInfo = vStorageObject.getConfig();
ID vdiskId = diskConfigInfo.getId();
} catch (Throwable e) {
if (e instanceof AlreadyExistsFaultMsg) {
}
}*/
if (vmName.equalsIgnoreCase("none")) {
// OfflineVmwareMigration: we need to refactor the worker vm creation out for use in migration methods as well as here
@ -852,26 +838,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
throw new Exception(msg);
}
// OfflineVmwareMigration: 5. ignore/replace the rest of the try-block; It is the functional bit
Pair<VirtualDisk, String> vdisk = vmMo.getDiskDevice(path);
if (vdisk == null) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("resize volume done (failed)");
}
throw new Exception("No such disk device: " + path);
}
// IDE virtual disk cannot be re-sized if VM is running
if (vdisk.second() != null && vdisk.second().contains("ide")) {
throw new Exception("Re-sizing a virtual disk over an IDE controller is not supported in the VMware hypervisor. " +
"Please re-try when virtual disk is attached to a VM using a SCSI controller.");
}
if (cmd.isManaged()) {
VmwareContext context = getServiceContext();
if (managed) {
ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
ClusterMO clusterMO = new ClusterMO(context, morCluster);
@ -892,15 +860,26 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
_storageProcessor.expandDatastore(hostDatastoreSystem, dsMo);
}
if (vdisk.second() != null && !vdisk.second().toLowerCase().startsWith("scsi")) {
s_logger.error("Unsupported disk device bus " + vdisk.second());
throw new Exception("Unsupported disk device bus " + vdisk.second());
boolean volumePathChangeObserved = false;
boolean datastoreChangeObserved = false;
Pair<String, String> pathAndChainInfo = getNewPathAndChainInfoInDatastoreCluster(vmMo, path, chainInfo, managed, cmd.get_iScsiName(), poolUUID, cmd.getContextParam(DiskTO.PROTOCOL_TYPE));
Pair<String, String> poolUUIDandChainInfo = getNewPoolUUIDAndChainInfoInDatastoreCluster(vmMo, path, chainInfo, managed, cmd.get_iScsiName(), poolUUID, cmd.getContextParam(DiskTO.PROTOCOL_TYPE));
if (pathAndChainInfo != null) {
volumePathChangeObserved = true;
path = pathAndChainInfo.first();
chainInfo = pathAndChainInfo.second();
}
VirtualDisk disk = vdisk.first();
if ((VirtualDiskFlatVer2BackingInfo) disk.getBacking() != null && ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent() != null) {
s_logger.error("Resize is not supported because Disk device has Parent " + ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent().getUuid());
throw new Exception("Resize is not supported because Disk device has Parent " + ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent().getUuid());
if (poolUUIDandChainInfo != null) {
datastoreChangeObserved = true;
poolUUID = poolUUIDandChainInfo.first();
chainInfo = poolUUIDandChainInfo.second();
}
// OfflineVmwareMigration: 5. ignore/replace the rest of the try-block; It is the functional bit
VirtualDisk disk = getDiskAfterResizeDiskValidations(vmMo, path);
String vmdkAbsFile = getAbsoluteVmdkFile(disk);
if (vmdkAbsFile != null && !vmdkAbsFile.isEmpty()) {
@ -922,7 +901,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
throw new Exception("Failed to configure VM to resize disk. vmName: " + vmName);
}
return new ResizeVolumeAnswer(cmd, true, "success", newSize * 1024);
ResizeVolumeAnswer answer = new ResizeVolumeAnswer(cmd, true, "success", newSize * 1024);
if (datastoreChangeObserved) {
answer.setContextParam("datastoreUUID", poolUUID);
answer.setContextParam("chainInfo", chainInfo);
}
if (volumePathChangeObserved) {
answer.setContextParam("volumePath", path);
answer.setContextParam("chainInfo", chainInfo);
}
return answer;
} catch (Exception e) {
s_logger.error("Unable to resize volume", e);
@ -944,6 +933,79 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
private VirtualDisk getDiskAfterResizeDiskValidations(VirtualMachineMO vmMo, String volumePath) throws Exception {
Pair<VirtualDisk, String> vdisk = vmMo.getDiskDevice(volumePath);
if (vdisk == null) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("resize volume done (failed)");
}
throw new Exception("No such disk device: " + volumePath);
}
// IDE virtual disk cannot be re-sized if VM is running
if (vdisk.second() != null && vdisk.second().contains("ide")) {
throw new Exception("Re-sizing a virtual disk over an IDE controller is not supported in the VMware hypervisor. " +
"Please re-try when virtual disk is attached to a VM using a SCSI controller.");
}
if (vdisk.second() != null && !vdisk.second().toLowerCase().startsWith("scsi")) {
s_logger.error("Unsupported disk device bus " + vdisk.second());
throw new Exception("Unsupported disk device bus " + vdisk.second());
}
VirtualDisk disk = vdisk.first();
if ((VirtualDiskFlatVer2BackingInfo) disk.getBacking() != null && ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent() != null) {
s_logger.error("Resize is not supported because Disk device has Parent " + ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent().getUuid());
throw new Exception("Resize is not supported because Disk device has Parent " + ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent().getUuid());
}
return disk;
}
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;
}
private Pair<String, String> getNewPoolUUIDAndChainInfoInDatastoreCluster(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]);
DatacenterMO dcMo = new DatacenterMO(hyperHost.getContext(), hyperHost.getHyperHostDatacenter());
DatastoreMO diskDatastoreMofromVM = new DatastoreMO(context, dcMo.findDatastore(file.getDatastoreName()));
if (diskDatastoreMofromVM != null) {
String actualPoolUuid = diskDatastoreMofromVM.getCustomFieldValue(CustomFieldConstants.CLOUD_UUID);
if (!actualPoolUuid.equalsIgnoreCase(poolUUID)) {
s_logger.warn(String.format("Volume %s found to be in a different storage pool %s", path, actualPoolUuid));
poolUUID = actualPoolUuid;
chainInfo = _gson.toJson(matchingExistingDisk);
return new Pair<>(poolUUID, chainInfo);
}
}
}
}
return null;
}
protected Answer execute(CheckNetworkCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource CheckNetworkCommand " + _gson.toJson(cmd));
@ -1911,7 +1973,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
s_logger.error(msg);
throw new Exception(msg);
}
if (rootDisk.getDetails().get(DiskTO.PROTOCOL_TYPE) != null && rootDisk.getDetails().get(DiskTO.PROTOCOL_TYPE).equalsIgnoreCase("DatastoreCluster")) {
if (rootDisk.getDetails().get(DiskTO.PROTOCOL_TYPE) != null && rootDisk.getDetails().get(DiskTO.PROTOCOL_TYPE).equalsIgnoreCase(Storage.StoragePoolType.DatastoreCluster.toString())) {
if (diskInfoBuilder != null) {
DatastoreMO diskDatastoreMofromVM = getDataStoreWhereDiskExists(hyperHost, context, diskInfoBuilder, rootDisk, diskDatastores);
if (diskDatastoreMofromVM != null) {
@ -3254,70 +3316,82 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
nicIndex++;
}
}
private VirtualMachineDiskInfo getMatchingExistingDiskWithVolumeDetails(VirtualMachineDiskInfoBuilder diskInfoBuilder, String volumePath,
String chainInfo, boolean isManaged, String iScsiName, String datastoreUUID,
VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception {
private VirtualMachineDiskInfo getMatchingExistingDisk(VirtualMachineDiskInfoBuilder diskInfoBuilder, DiskTO vol, VmwareHypervisorHost hyperHost, VmwareContext context)
throws Exception {
if (diskInfoBuilder != null) {
VolumeObjectTO volume = (VolumeObjectTO) vol.getData();
Pair<String, String> dsNameAndFileName = getVMDiskInfo(volumePath, isManaged, iScsiName, datastoreUUID, hyperHost, context);
String dsName = dsNameAndFileName.first();
String diskBackingFileBaseName = dsNameAndFileName.second();
String dsName = null;
String diskBackingFileBaseName = null;
Map<String, String> details = vol.getDetails();
boolean isManaged = details != null && Boolean.parseBoolean(details.get(DiskTO.MANAGED));
if (isManaged) {
String iScsiName = details.get(DiskTO.IQN);
// if the storage is managed, iScsiName should not be null
dsName = VmwareResource.getDatastoreName(iScsiName);
diskBackingFileBaseName = new DatastoreFile(volume.getPath()).getFileBaseName();
} else {
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, volume.getDataStore().getUuid());
DatastoreMO dsMo = new DatastoreMO(context, morDs);
dsName = dsMo.getName();
diskBackingFileBaseName = volume.getPath();
}
VirtualMachineDiskInfo diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(diskBackingFileBaseName, dsName);
if (diskInfo != null) {
s_logger.info("Found existing disk info from volume path: " + volume.getPath());
return diskInfo;
} else {
String chainInfo = volume.getChainInfo();
if (chainInfo != null) {
VirtualMachineDiskInfo infoInChain = _gson.fromJson(chainInfo, VirtualMachineDiskInfo.class);
if (infoInChain != null) {
String[] disks = infoInChain.getDiskChain();
if (disks.length > 0) {
for (String diskPath : disks) {
DatastoreFile file = new DatastoreFile(diskPath);
diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(file.getFileBaseName(), dsName);
if (diskInfo != null) {
s_logger.info("Found existing disk from chain info: " + diskPath);
return diskInfo;
}
}
}
if (diskInfo == null) {
diskInfo = diskInfoBuilder.getDiskInfoByDeviceBusName(infoInChain.getDiskDeviceBusName());
VirtualMachineDiskInfo diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(diskBackingFileBaseName, dsName);
if (diskInfo != null) {
s_logger.info("Found existing disk info from volume path: " + volumePath);
return diskInfo;
} else {
if (chainInfo != null) {
VirtualMachineDiskInfo infoInChain = _gson.fromJson(chainInfo, VirtualMachineDiskInfo.class);
if (infoInChain != null) {
String[] disks = infoInChain.getDiskChain();
if (disks.length > 0) {
for (String diskPath : disks) {
DatastoreFile file = new DatastoreFile(diskPath);
diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(file.getFileBaseName(), dsName);
if (diskInfo != null) {
s_logger.info("Found existing disk from from chain device bus information: " + infoInChain.getDiskDeviceBusName());
s_logger.info("Found existing disk from chain info: " + diskPath);
return diskInfo;
}
}
}
if (diskInfo == null) {
diskInfo = diskInfoBuilder.getDiskInfoByDeviceBusName(infoInChain.getDiskDeviceBusName());
if (diskInfo != null) {
s_logger.info("Found existing disk from from chain device bus information: " + infoInChain.getDiskDeviceBusName());
return diskInfo;
}
}
}
}
}
return null;
}
private Pair<String, String> getVMDiskInfo(String volumePath, boolean isManaged, String iScsiName, String datastoreUUID,
VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception {
String dsName = null;
String diskBackingFileBaseName = null;
if (isManaged) {
// if the storage is managed, iScsiName should not be null
dsName = VmwareResource.getDatastoreName(iScsiName);
diskBackingFileBaseName = new DatastoreFile(volumePath).getFileBaseName();
} else {
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, datastoreUUID);
DatastoreMO dsMo = new DatastoreMO(context, morDs);
dsName = dsMo.getName();
diskBackingFileBaseName = volumePath;
}
return new Pair<>(dsName, diskBackingFileBaseName);
}
private VirtualMachineDiskInfo getMatchingExistingDisk(VirtualMachineDiskInfoBuilder diskInfoBuilder, DiskTO vol, VmwareHypervisorHost hyperHost, VmwareContext context)
throws Exception {
if (diskInfoBuilder != null) {
VolumeObjectTO volume = (VolumeObjectTO) vol.getData();
String chainInfo = volume.getChainInfo();
Map<String, String> details = vol.getDetails();
boolean isManaged = details != null && Boolean.parseBoolean(details.get(DiskTO.MANAGED));
String iScsiName = details.get(DiskTO.IQN);
String datastoreUUID = volume.getDataStore().getUuid();
return getMatchingExistingDiskWithVolumeDetails(diskInfoBuilder, volume.getPath(), chainInfo, isManaged, iScsiName, datastoreUUID, hyperHost, context);
} else {
return null;
}
}
private String getDiskController(VirtualMachineMO vmMo, VirtualMachineDiskInfo matchingExistingDisk, DiskTO vol, Pair<String, String> controllerInfo, boolean deployAsIs) throws Exception {
DiskControllerType controllerType = DiskControllerType.none;
if (deployAsIs && matchingExistingDisk != null) {
@ -4791,7 +4865,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
// OfflineVmwareMigration: refactor to be able to handle a detached volume
private Answer execute(MigrateVolumeCommand cmd) {
String volumePath = cmd.getVolumePath();
String chainInfo = cmd.getChainInfo();
StorageFilerTO poolTo = cmd.getPool();
VolumeObjectTO volumeObjectTO = (VolumeObjectTO)cmd.getSrcData();
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource MigrateVolumeCommand: " + _gson.toJson(cmd));
@ -4838,6 +4914,22 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
DatastoreMO targetDsMo = new DatastoreMO(srcHyperHost.getContext(), morDs);
if (cmd.getContextParam(DiskTO.PROTOCOL_TYPE) != null && cmd.getContextParam(DiskTO.PROTOCOL_TYPE).equalsIgnoreCase("DatastoreCluster")) {
VmwareContext context = getServiceContext();
VmwareHypervisorHost hyperHost = getHyperHost(context);
VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
VirtualMachineDiskInfo matchingExistingDisk = getMatchingExistingDiskWithVolumeDetails(diskInfoBuilder, volumePath, chainInfo, false, null, poolTo.getUuid(), hyperHost, context);
if (diskInfoBuilder != null && matchingExistingDisk != null) {
String[] diskChain = matchingExistingDisk.getDiskChain();
DatastoreFile file = new DatastoreFile(diskChain[0]);
if (!file.getFileBaseName().equalsIgnoreCase(volumePath)) {
if (s_logger.isInfoEnabled())
s_logger.info("Detected disk-chain top file change on volume: " + volumePath + " -> " + file.getFileBaseName());
volumePath = file.getFileBaseName();
}
}
}
String fullVolumePath = VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(targetDsMo, vmName, volumePath + VMDK_EXTENSION);
Pair<VirtualDisk, String> diskInfo = getVirtualDiskInfo(vmMo, appendFileType(volumePath, VMDK_EXTENSION));
String vmdkAbsFile = getAbsoluteVmdkFile(diskInfo.first());
@ -4892,7 +4984,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
String chainInfo = _gson.toJson(diskInfoBuilder.getDiskInfoByBackingFileBaseName(volumePath, targetDsMo.getName()));
chainInfo = _gson.toJson(diskInfoBuilder.getDiskInfoByBackingFileBaseName(volumePath, targetDsMo.getName()));
MigrateVolumeAnswer answer = new MigrateVolumeAnswer(cmd, true, null, volumePath);
answer.setVolumeChainInfo(chainInfo);
return answer;

View File

@ -26,6 +26,8 @@ import java.util.Map;
import javax.inject.Inject;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.storage.Storage;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
@ -247,7 +249,10 @@ public class VmwareStorageMotionStrategy implements DataMotionStrategy {
, vm != null ? vm.getInstanceName() : null
, sourcePool
, targetPool
, hostIdForVmAndHostGuidInTargetCluster.second());
, hostIdForVmAndHostGuidInTargetCluster.second(), ((VolumeObjectTO) srcData.getTO()).getChainInfo());
if (sourcePool.getParent() != 0) {
cmd.setContextParam(DiskTO.PROTOCOL_TYPE, Storage.StoragePoolType.DatastoreCluster.toString());
}
Answer answer;
if (hostId != null) {
answer = agentMgr.easySend(hostId, cmd);

View File

@ -26,6 +26,8 @@ import java.util.UUID;
import javax.inject.Inject;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.storage.VolumeVO;
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
@ -408,7 +410,10 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
ResizeVolumeCommand resizeCmd =
new ResizeVolumeCommand(vol.getPath(), new StorageFilerTO(pool), vol.getSize(), resizeParameter.newSize, resizeParameter.shrinkOk,
resizeParameter.instanceName);
resizeParameter.instanceName, vol.getChainInfo());
if (pool.getParent() != 0) {
resizeCmd.setContextParam(DiskTO.PROTOCOL_TYPE, Storage.StoragePoolType.DatastoreCluster.toString());
}
CreateCmdResult result = new CreateCmdResult(null, null);
try {
ResizeVolumeAnswer answer = (ResizeVolumeAnswer) storageMgr.sendToPool(pool, resizeParameter.hosts, resizeCmd);
@ -418,6 +423,8 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
vol.setSize(finalSize);
vol.update();
updateVolumePathDetails(vol, answer);
} else if (answer != null) {
result.setResult(answer.getDetails());
} else {
@ -433,6 +440,31 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
callback.complete(result);
}
private void updateVolumePathDetails(VolumeObject vol, ResizeVolumeAnswer answer) {
VolumeVO volumeVO = volumeDao.findById(vol.getId());
String datastoreUUID = answer.getContextParam("datastoreUUID");
if (datastoreUUID != null) {
StoragePoolVO storagePoolVO = primaryStoreDao.findByUuid(datastoreUUID);
if (storagePoolVO != null) {
volumeVO.setPoolId(storagePoolVO.getId());
} else {
s_logger.warn(String.format("Unable to find datastore %s while updating the new datastore of the volume %d", datastoreUUID, vol.getId()));
}
}
String volumePath = answer.getContextParam("volumePath");
if (volumePath != null) {
volumeVO.setPath(volumePath);
}
String chainInfo = answer.getContextParam("chainInfo");
if (chainInfo != null) {
volumeVO.setChainInfo(chainInfo);
}
volumeDao.update(volumeVO.getId(), volumeVO);
}
@Override
public void handleQualityOfServiceForVolumeMigration(VolumeInfo volumeInfo, QualityOfServiceState qualityOfServiceState) {}