mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
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:
parent
6e216dd0d1
commit
cd4e7e031a
@ -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; }
|
||||
}
|
||||
|
||||
@ -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}
|
||||
*/
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user