This is an automated email from the ASF dual-hosted git repository.
nvazquez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new cd4e7e0 Fix resize volume and migrate volume to update volume path if
DRS is applied on volume in datastore cluster (#5539)
cd4e7e0 is described below
commit cd4e7e031adcf99856802038359f93a41ce31a3e
Author: Harikrishna <[email protected]>
AuthorDate: Tue Oct 5 05:28:25 2021 +0530
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
---
.../agent/api/storage/MigrateVolumeCommand.java | 17 +-
.../agent/api/storage/ResizeVolumeCommand.java | 8 +
.../storage/motion/AncientDataMotionStrategy.java | 9 +-
.../hypervisor/vmware/resource/VmwareResource.java | 290 ++++++++++++++-------
.../motion/VmwareStorageMotionStrategy.java | 7 +-
.../CloudStackPrimaryDataStoreDriverImpl.java | 34 ++-
6 files changed, 260 insertions(+), 105 deletions(-)
diff --git
a/core/src/main/java/com/cloud/agent/api/storage/MigrateVolumeCommand.java
b/core/src/main/java/com/cloud/agent/api/storage/MigrateVolumeCommand.java
index 2dd4023..9fed0f9 100644
--- a/core/src/main/java/com/cloud/agent/api/storage/MigrateVolumeCommand.java
+++ b/core/src/main/java/com/cloud/agent/api/storage/MigrateVolumeCommand.java
@@ -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; }
}
diff --git
a/core/src/main/java/com/cloud/agent/api/storage/ResizeVolumeCommand.java
b/core/src/main/java/com/cloud/agent/api/storage/ResizeVolumeCommand.java
index 22cff13..70d4d3e 100644
--- a/core/src/main/java/com/cloud/agent/api/storage/ResizeVolumeCommand.java
+++ b/core/src/main/java/com/cloud/agent/api/storage/ResizeVolumeCommand.java
@@ -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}
*/
diff --git
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index 51e0c97..74de765 100644
---
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -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) {
diff --git
a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 0e93398..9958b22 100644
---
a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++
b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -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();
-
- 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();
+ Pair<String, String> dsNameAndFileName = getVMDiskInfo(volumePath,
isManaged, iScsiName, datastoreUUID, hyperHost, context);
+ String dsName = dsNameAndFileName.first();
+ String diskBackingFileBaseName = dsNameAndFileName.second();
- 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;
diff --git
a/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
b/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
index 04111bc..9c41885 100644
---
a/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
+++
b/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
@@ -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);
diff --git
a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
index 9326946..fff15fd 100644
---
a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
+++
b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
@@ -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) {}