Skip to content

Commit 388fdc2

Browse files
committed
[VMware] Apply IOPS in resize/migrate
1 parent 3b42fbf commit 388fdc2

File tree

11 files changed

+159
-20
lines changed

11 files changed

+159
-20
lines changed

core/src/main/java/com/cloud/agent/api/storage/MigrateVolumeCommand.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public class MigrateVolumeCommand extends Command {
3636
String attachedVmName;
3737
Volume.Type volumeType;
3838
String hostGuidInTargetCluster;
39+
Long newMaxIops;
40+
Long newMinIops;
3941

4042
private DataTO srcData;
4143
private DataTO destData;
@@ -150,4 +152,20 @@ public int getWaitInMillSeconds() {
150152
public boolean isReconcile() {
151153
return true;
152154
}
155+
156+
public Long getNewMinIops() {
157+
return newMinIops;
158+
}
159+
160+
public void setNewMinIops(Long newMinIops) {
161+
this.newMinIops = newMinIops;
162+
}
163+
164+
public Long getNewMaxIops() {
165+
return newMaxIops;
166+
}
167+
168+
public void setNewMaxIops(Long newMaxIops) {
169+
this.newMaxIops = newMaxIops;
170+
}
153171
}

core/src/main/java/com/cloud/agent/api/storage/ResizeVolumeCommand.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public class ResizeVolumeCommand extends Command {
3333
private boolean shrinkOk;
3434
private String vmInstance;
3535
private String chainInfo;
36+
private Long newMaxIops;
37+
private Long newMinIops;
3638

3739
/* For managed storage */
3840
private boolean managed;
@@ -70,7 +72,6 @@ public ResizeVolumeCommand(String path, StorageFilerTO pool, Long currentSize, L
7072
public ResizeVolumeCommand(String path, StorageFilerTO pool, Long currentSize, Long newSize, boolean shrinkOk, String vmInstance,
7173
boolean isManaged, String iScsiName) {
7274
this(path, pool, currentSize, newSize, shrinkOk, vmInstance);
73-
7475
this.iScsiName = iScsiName;
7576
this.managed = isManaged;
7677
}
@@ -120,4 +121,20 @@ public void clearPassphrase() {
120121
public boolean executeInSequence() {
121122
return false;
122123
}
124+
125+
public Long getNewMaxIops() {
126+
return newMaxIops;
127+
}
128+
129+
public void setNewMaxIops(Long newMaxIops) {
130+
this.newMaxIops = newMaxIops;
131+
}
132+
133+
public Long getNewMinIops() {
134+
return newMinIops;
135+
}
136+
137+
public void setNewMinIops(Long newMinIops) {
138+
this.newMinIops = newMinIops;
139+
}
123140
}

engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId,
111111

112112
VolumeInfo createVolumeFromSnapshot(Volume volume, Snapshot snapshot, UserVm vm) throws StorageUnavailableException;
113113

114-
Volume migrateVolume(Volume volume, StoragePool destPool) throws StorageUnavailableException;
114+
Volume migrateVolume(Volume volume, StoragePool destPool, DiskOffering newDiskOffering) throws StorageUnavailableException;
115115

116116
Volume liveMigrateVolume(Volume volume, StoragePool destPool);
117117

engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ public VolumeInfo moveVolume(VolumeInfo volumeInfo, long destPoolDcId, Long dest
329329
throw new CloudRuntimeException(String.format("Failed to find a storage pool with enough capacity to move the volume [%s] to.", volumeToString));
330330
}
331331

332-
Volume newVol = migrateVolume(volumeInfo, destPool);
332+
Volume newVol = migrateVolume(volumeInfo, destPool, diskOffering);
333333
return volFactory.getVolume(newVol.getId());
334334
}
335335

@@ -1419,13 +1419,14 @@ private void checkConcurrentJobsPerDatastoreThreshhold(final StoragePool destPoo
14191419

14201420
@Override
14211421
@DB
1422-
public Volume migrateVolume(Volume volume, StoragePool destPool) throws StorageUnavailableException {
1422+
public Volume migrateVolume(Volume volume, StoragePool destPool, DiskOffering newDiskOffering) throws StorageUnavailableException {
14231423
String volumeToString = getVolumeIdentificationInfos(volume);
14241424

14251425
VolumeInfo vol = volFactory.getVolume(volume.getId());
14261426
if (vol == null) {
14271427
throw new CloudRuntimeException(String.format("Volume migration failed because volume [%s] is null.", volumeToString));
14281428
}
1429+
vol.addPayload(newDiskOffering);
14291430
if (destPool == null) {
14301431
throw new CloudRuntimeException("Volume migration failed because the destination storage pool is not available.");
14311432
}
@@ -1554,7 +1555,7 @@ public boolean storageMigration(VirtualMachineProfile vm, Map<Volume, StoragePoo
15541555
}
15551556
logger.debug("Offline VM migration was not done up the stack in VirtualMachineManager. Trying to migrate the VM here.");
15561557
for (Map.Entry<Volume, StoragePool> entry : volumeStoragePoolMap.entrySet()) {
1557-
Volume result = migrateVolume(entry.getKey(), entry.getValue());
1558+
Volume result = migrateVolume(entry.getKey(), entry.getValue(), null);
15581559
if (result == null) {
15591560
return false;
15601561
}
@@ -2019,7 +2020,7 @@ public void prepare(VirtualMachineProfile vm, DeployDestination dest) throws Sto
20192020
} else if (task.type == VolumeTaskType.MIGRATE) {
20202021
store = (PrimaryDataStore) dataStoreMgr.getDataStore(task.pool.getId(), DataStoreRole.Primary);
20212022
updateVolumeSize(store, task.volume);
2022-
vol = migrateVolume(task.volume, store);
2023+
vol = migrateVolume(task.volume, store, null);
20232024
} else if (task.type == VolumeTaskType.RECREATE) {
20242025
Pair<VolumeVO, DataStore> result = recreateVolume(task.volume, vm, dest);
20252026
store = (PrimaryDataStore) dataStoreMgr.getDataStore(result.second().getId(), DataStoreRole.Primary);

engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ protected Answer migrateVolumeToPool(DataObject srcData, DataObject destData) {
546546
StoragePool srcPool = (StoragePool)dataStoreMgr.getDataStore(srcData.getDataStore().getId(), DataStoreRole.Primary);
547547
StoragePool destPool = (StoragePool)dataStoreMgr.getDataStore(destData.getDataStore().getId(), DataStoreRole.Primary);
548548
MigrateVolumeCommand command = new MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool, volume.getAttachedVmName(), volume.getVolumeType(), waitInterval, volume.getChainInfo());
549+
549550
if (srcPool.getParent() != 0) {
550551
command.setContextParam(DiskTO.PROTOCOL_TYPE, Storage.StoragePoolType.DatastoreCluster.toString());
551552
}

plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.util.UUID;
4646
import java.util.stream.Collectors;
4747

48+
import com.vmware.vim25.StorageIOAllocationInfo;
4849
import com.cloud.agent.api.CleanupVMCommand;
4950
import javax.naming.ConfigurationException;
5051
import javax.xml.datatype.XMLGregorianCalendar;
@@ -78,6 +79,7 @@
7879
import org.apache.commons.lang.ArrayUtils;
7980
import org.apache.commons.lang.math.NumberUtils;
8081
import org.apache.logging.log4j.ThreadContext;
82+
import org.apache.commons.lang3.ObjectUtils;
8183
import org.joda.time.Duration;
8284

8385
import com.cloud.agent.IAgentControl;
@@ -874,6 +876,8 @@ private Answer execute(ResizeVolumeCommand cmd) {
874876
boolean managed = cmd.isManaged();
875877
String poolUUID = cmd.getPoolUuid();
876878
String chainInfo = cmd.getChainInfo();
879+
Long newMinIops = cmd.getNewMinIops();
880+
Long newMaxIops = cmd.getNewMaxIops();
877881
boolean useWorkerVm = false;
878882

879883
VmwareContext context = getServiceContext();
@@ -888,8 +892,6 @@ private Answer execute(ResizeVolumeCommand cmd) {
888892
oldSize / (float) ResourceType.bytesToMiB, newSize / (float) ResourceType.bytesToMiB, vmName);
889893
logger.error(errorMsg);
890894
throw new Exception(errorMsg);
891-
} else if (newSize == oldSize) {
892-
return new ResizeVolumeAnswer(cmd, true, "success", newSize * ResourceType.bytesToKiB);
893895
}
894896

895897
if (vmName.equalsIgnoreCase("none")) {
@@ -983,6 +985,8 @@ private Answer execute(ResizeVolumeCommand cmd) {
983985
VirtualDisk disk = getDiskAfterResizeDiskValidations(vmMo, path);
984986
String vmdkAbsFile = VmwareHelper.getAbsoluteVmdkFile(disk);
985987

988+
setDiskIops(disk, newMinIops, newMaxIops);
989+
986990
if (vmdkAbsFile != null && !vmdkAbsFile.isEmpty()) {
987991
vmMo.updateAdapterTypeIfRequired(vmdkAbsFile);
988992
}
@@ -1034,6 +1038,22 @@ private Answer execute(ResizeVolumeCommand cmd) {
10341038
}
10351039
}
10361040

1041+
/**
1042+
* Sets the disk IOPS which is the sum of min IOPS and max IOPS; if they are null, the IOPS limit is set to -1 (unlimited).
1043+
*/
1044+
private void setDiskIops(VirtualDisk disk, Long newMinIops, Long newMaxIops) {
1045+
StorageIOAllocationInfo storageIOAllocation = new StorageIOAllocationInfo();
1046+
Long iops = -1L;
1047+
1048+
if (ObjectUtils.allNotNull(newMinIops, newMaxIops) && newMinIops > 0 && newMaxIops > 0) {
1049+
iops = newMinIops + newMaxIops;
1050+
}
1051+
1052+
storageIOAllocation.setLimit(iops);
1053+
logger.debug(LogUtils.logGsonWithoutException("Setting [%s] as the IOPS limit of disk [%s].", iops == -1L ? "unlimited" : iops, disk));
1054+
disk.setStorageIOAllocation(storageIOAllocation);
1055+
}
1056+
10371057
private VirtualDisk getDiskAfterResizeDiskValidations(VirtualMachineMO vmMo, String volumePath) throws Exception {
10381058
Pair<VirtualDisk, String> vdisk = vmMo.getDiskDevice(volumePath);
10391059
if (vdisk == null) {
@@ -4426,7 +4446,7 @@ protected GetVolumeStatsAnswer execute(GetVolumeStatsCommand cmd) {
44264446
for (String diskPath : disks) {
44274447
DatastoreFile file = new DatastoreFile(diskPath);
44284448
VirtualMachineMO vmMo = dcMo.findVm(file.getDir());
4429-
Pair<VirtualDisk, String> vds = vmMo.getDiskDevice(file.getFileName(), true);
4449+
Pair<VirtualDisk, String> vds = vmMo.getDiskDevice(file.getFileName(), true, false);
44304450
long virtualsize = vds.first().getCapacityInKB() * 1024;
44314451
long physicalsize = primaryStorageDatastoreMo.fileDiskSize(file.getPath());
44324452
if (statEntry.containsKey(chainInfo)) {
@@ -5179,6 +5199,8 @@ private Answer execute(MigrateVolumeCommand cmd) {
51795199
volumePath = vmMo.getVmdkFileBaseName(disk);
51805200
}
51815201
}
5202+
5203+
setDiskIops(cmd, vmMo, volumePath);
51825204
VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
51835205
chainInfo = _gson.toJson(diskInfoBuilder.getDiskInfoByBackingFileBaseName(volumePath, targetDsMo.getName()));
51845206
MigrateVolumeAnswer answer = new MigrateVolumeAnswer(cmd, true, null, volumePath);
@@ -5191,6 +5213,40 @@ private Answer execute(MigrateVolumeCommand cmd) {
51915213
}
51925214
}
51935215

5216+
/**
5217+
* Sets the disk IOPS limitation, if the {@link MigrateVolumeCommand} did not specify this limitation, then it is set to -1 (unlimited).
5218+
*/
5219+
private void setDiskIops(MigrateVolumeCommand cmd, VirtualMachineMO vmMo, String volumePath) throws Exception {
5220+
Long newIops = -1L;
5221+
Long newMinIops = cmd.getNewMinIops();
5222+
Long newMaxIops = cmd.getNewMaxIops();
5223+
5224+
if (ObjectUtils.allNotNull(newMinIops, newMaxIops) && newMinIops > 0 && newMaxIops > 0) {
5225+
newIops = newMinIops + newMaxIops;
5226+
}
5227+
5228+
VirtualDisk disk = vmMo.getDiskDevice(volumePath, true, true).first();
5229+
5230+
try {
5231+
logger.debug(LogUtils.logGsonWithoutException("Trying to change disk [%s] IOPS to [%s].", disk, newIops));
5232+
VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
5233+
VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
5234+
5235+
StorageIOAllocationInfo storageIOAllocation = new StorageIOAllocationInfo();
5236+
storageIOAllocation.setLimit(newIops);
5237+
disk.setStorageIOAllocation(storageIOAllocation);
5238+
5239+
deviceConfigSpec.setDevice(disk);
5240+
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.EDIT);
5241+
vmConfigSpec.getDeviceChange().add(deviceConfigSpec);
5242+
vmMo.configureVm(vmConfigSpec);
5243+
} catch (Exception e) {
5244+
String vmwareDocumentation = "https://kb.vmware.com/s/article/68164";
5245+
logger.error(LogUtils.logGsonWithoutException("Failed to change disk [%s] IOPS to [%s] due to [%s]. This happens when the disk controller is IDE." +
5246+
" Please read this documentation for more information: [%s]. ", disk, newIops, e.getMessage(), vmwareDocumentation), e);
5247+
}
5248+
}
5249+
51945250
private Pair<VirtualDisk, String> getVirtualDiskInfo(VirtualMachineMO vmMo, String srcDiskName) throws Exception {
51955251
Pair<VirtualDisk, String> deviceInfo = vmMo.getDiskDevice(srcDiskName);
51965252
if (deviceInfo == null) {

plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import javax.inject.Inject;
2828

2929
import com.cloud.agent.api.to.DiskTO;
30+
import com.cloud.storage.DiskOfferingVO;
3031
import com.cloud.storage.Storage;
3132
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
3233
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
@@ -38,6 +39,7 @@
3839
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
3940
import org.apache.cloudstack.storage.to.VolumeObjectTO;
4041
import org.apache.commons.collections.CollectionUtils;
42+
import org.apache.commons.lang3.ObjectUtils;
4143
import org.apache.logging.log4j.Logger;
4244
import org.apache.logging.log4j.LogManager;
4345
import org.springframework.stereotype.Component;
@@ -251,6 +253,25 @@ public void copyAsync(DataObject srcData, DataObject destData, Host destHost, As
251253
, sourcePool
252254
, targetPool
253255
, hostIdForVmAndHostGuidInTargetCluster.second(), ((VolumeObjectTO) srcData.getTO()).getChainInfo());
256+
257+
VolumeInfo volume = (VolumeInfo) srcData;
258+
if (volume.getpayload() instanceof DiskOfferingVO) {
259+
DiskOfferingVO offering = (DiskOfferingVO) volume.getpayload();
260+
261+
Long offeringIopsReadRate = offering.getIopsReadRate();
262+
Long offeringIopsWriteRate = offering.getIopsWriteRate();
263+
264+
Long minIops = null;
265+
Long maxIops = null;
266+
if (ObjectUtils.allNotNull(offeringIopsReadRate, offeringIopsWriteRate)) {
267+
minIops = Math.min(offeringIopsReadRate, offeringIopsWriteRate);
268+
maxIops = Math.max(offeringIopsReadRate, offeringIopsWriteRate);
269+
}
270+
271+
cmd.setNewMinIops(minIops);
272+
cmd.setNewMaxIops(maxIops);
273+
}
274+
254275
if (sourcePool.getParent() != 0) {
255276
cmd.setContextParam(DiskTO.PROTOCOL_TYPE, Storage.StoragePoolType.DatastoreCluster.toString());
256277
}

plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,8 @@ public void resize(DataObject data, AsyncCompletionCallback<CreateCmdResult> cal
469469
}
470470
ResizeVolumeCommand resizeCmd = new ResizeVolumeCommand(vol.getPath(), new StorageFilerTO(pool), vol.getSize(),
471471
resizeParameter.newSize, resizeParameter.shrinkOk, resizeParameter.instanceName, vol.getChainInfo(), vol.getPassphrase(), vol.getEncryptFormat());
472+
resizeCmd.setNewMinIops(resizeParameter.newMinIops);
473+
resizeCmd.setNewMaxIops(resizeParameter.newMaxIops);
472474
if (pool.getParent() != 0) {
473475
resizeCmd.setContextParam(DiskTO.PROTOCOL_TYPE, Storage.StoragePoolType.DatastoreCluster.toString());
474476
}

server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,21 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep
12681268
} else {
12691269
newMinIops = newDiskOffering.getMinIops();
12701270
newMaxIops = newDiskOffering.getMaxIops();
1271+
1272+
if (newDiskOffering.getMinIops() != null) {
1273+
newMinIops = newDiskOffering.getMinIops();
1274+
}
1275+
1276+
if (newDiskOffering.getMaxIops() != null) {
1277+
newMaxIops = newDiskOffering.getMaxIops();
1278+
}
1279+
1280+
Long newDiskOfferingIopsReadRate = newDiskOffering.getIopsReadRate();
1281+
Long newDiskOfferingIopsWriteRate = newDiskOffering.getIopsWriteRate();
1282+
if (ObjectUtils.allNull(newMinIops, newMaxIops) && ObjectUtils.allNotNull(newDiskOfferingIopsReadRate, newDiskOfferingIopsWriteRate)) {
1283+
newMaxIops = Math.max(newDiskOfferingIopsReadRate, newDiskOfferingIopsWriteRate);
1284+
newMinIops = Math.min(newDiskOfferingIopsReadRate, newDiskOfferingIopsWriteRate);
1285+
}
12711286
}
12721287

12731288
// if the hypervisor snapshot reserve value is null, it must remain null (currently only KVM uses null and null is all KVM uses for a value here)
@@ -1335,10 +1350,7 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep
13351350
volumeMigrateRequired = true;
13361351
}
13371352

1338-
boolean volumeResizeRequired = false;
1339-
if (currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops())) {
1340-
volumeResizeRequired = true;
1341-
}
1353+
boolean volumeResizeRequired = currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops());
13421354
if (!volumeMigrateRequired && !volumeResizeRequired && newDiskOffering != null) {
13431355
_volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId());
13441356
volume = _volsDao.findById(volume.getId());
@@ -1403,7 +1415,14 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep
14031415
} else if (jobResult instanceof Throwable) {
14041416
throw new RuntimeException("Unexpected exception", (Throwable) jobResult);
14051417
} else if (jobResult instanceof Long) {
1406-
return _volsDao.findById((Long) jobResult);
1418+
Long volumeId = (Long) jobResult;
1419+
if (newDiskOffering != null) {
1420+
_volsDao.updateDiskOffering(volumeId, newDiskOffering.getId());
1421+
}
1422+
volume.setMinIops(newMinIops);
1423+
volume.setMinIops(newMaxIops);
1424+
_volsDao.update(volumeId, volume);
1425+
return _volsDao.findById(volumeId);
14071426
}
14081427
}
14091428

@@ -3784,9 +3803,9 @@ private Volume orchestrateMigrateVolume(VolumeVO volume, StoragePool destPool, b
37843803
Volume newVol = null;
37853804
try {
37863805
if (liveMigrateVolume) {
3787-
newVol = liveMigrateVolume(volume, destPool);
3806+
newVol = liveMigrateVolume(volume, destPool, newDiskOffering);
37883807
} else {
3789-
newVol = _volumeMgr.migrateVolume(volume, destPool);
3808+
newVol = _volumeMgr.migrateVolume(volume, destPool, newDiskOffering);
37903809
}
37913810
if (newDiskOffering != null) {
37923811
_volsDao.updateDiskOffering(newVol.getId(), newDiskOffering.getId());
@@ -3802,9 +3821,9 @@ private Volume orchestrateMigrateVolume(VolumeVO volume, StoragePool destPool, b
38023821
}
38033822

38043823
@DB
3805-
protected Volume liveMigrateVolume(Volume volume, StoragePool destPool) throws StorageUnavailableException {
3824+
protected Volume liveMigrateVolume(Volume volume, StoragePool destPool, DiskOfferingVO newDiskOffering) throws StorageUnavailableException {
38063825
VolumeInfo vol = volFactory.getVolume(volume.getId());
3807-
3826+
vol.addPayload(newDiskOffering);
38083827
DataStore dataStoreTarget = dataStoreMgr.getDataStore(destPool.getId(), DataStoreRole.Primary);
38093828
AsyncCallFuture<VolumeApiResult> future = volService.migrateVolume(vol, dataStoreTarget);
38103829
try {

server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,7 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ
10381038
if (vm.getState().equals(VirtualMachine.State.Running)) {
10391039
volume = volumeManager.liveMigrateVolume(volumeVO, storagePool);
10401040
} else {
1041-
volume = volumeManager.migrateVolume(volumeVO, storagePool);
1041+
volume = volumeManager.migrateVolume(volumeVO, storagePool, dOffering);
10421042
}
10431043
if (volume == null) {
10441044
String msg = "";

0 commit comments

Comments
 (0)