Update to volume-resize logic

This commit is contained in:
Mike Tutkowski 2014-08-21 14:47:40 -06:00
parent 1436ce62b6
commit 3773ff060e
5 changed files with 98 additions and 20 deletions

View File

@ -1928,7 +1928,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
Long volumeSize = Long.parseLong(details.get(DiskTO.VOLUME_SIZE));
if (vdi == null) {
vdi = createVdi(sr, vdiNameLabel, volumeSize);
} else {
// if VDI is not null, it must have already been created, so check whether a resize of the volume was performed
@ -1939,7 +1938,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
long vdiVirtualSize = vdi.getVirtualSize(conn);
if (vdiVirtualSize != volumeSize) {
s_logger.info("resizing the datadisk(vdi) from vdiVirtualsize :"+ vdiVirtualSize + "to volumeSize :" + volumeSize);
s_logger.info("resizing the data disk (vdi) from vdiVirtualsize: "+ vdiVirtualSize + " to volumeSize: " + volumeSize);
try {
vdi.resize(conn, volumeSize);

View File

@ -420,8 +420,8 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
verifySufficientIopsForStoragePool(storagePoolId, volumeInfo.getId(), payload.newMinIops);
SolidFireUtil.modifySolidFireVolume(sfConnection, sfVolumeId, sfVolume.getTotalSize(), payload.newMinIops, payload.newMaxIops,
getDefaultBurstIops(storagePoolId, payload.newMaxIops));
SolidFireUtil.modifySolidFireVolume(sfConnection, sfVolumeId, sfVolume.getTotalSize(), NumberFormat.getInstance().format(payload.newSize),
payload.newMinIops, payload.newMaxIops, getDefaultBurstIops(storagePoolId, payload.newMaxIops));
VolumeVO volume = _volumeDao.findById(volumeInfo.getId());

View File

@ -621,7 +621,7 @@ public class SolidFireSharedPrimaryDataStoreLifeCycle implements PrimaryDataStor
}
}
SolidFireUtil.modifySolidFireVolume(sfConnection, getVolumeId(storagePool.getId()), size, minIops, maxIops, burstIops);
SolidFireUtil.modifySolidFireVolume(sfConnection, getVolumeId(storagePool.getId()), size, null, minIops, maxIops, burstIops);
SolidFireUtil.updateCsDbWithSolidFireIopsInfo(storagePool.getId(), _primaryDataStoreDao, _storagePoolDetailsDao, minIops, maxIops, burstIops);
}

View File

@ -467,11 +467,14 @@ public class SolidFireUtil {
return volumeCreateResult.result.volumeID;
}
public static void modifySolidFireVolume(SolidFireConnection sfConnection, long volumeId, long totalSize, long minIops, long maxIops, long burstIops)
public static void modifySolidFireVolume(SolidFireConnection sfConnection, long volumeId, long totalSize, String strCloudStackVolumeSize,
long minIops, long maxIops, long burstIops)
{
final Gson gson = new GsonBuilder().create();
VolumeToModify volumeToModify = new VolumeToModify(volumeId, totalSize, minIops, maxIops, burstIops);
Object volumeToModify = strCloudStackVolumeSize != null && strCloudStackVolumeSize.trim().length() > 0 ?
new VolumeToModifyWithCloudStackVolumeSize(volumeId, totalSize, strCloudStackVolumeSize, minIops, maxIops, burstIops) :
new VolumeToModify(volumeId, totalSize, minIops, maxIops, burstIops);
String strVolumeToModifyJson = gson.toJson(volumeToModify);
@ -947,8 +950,8 @@ public class SolidFireUtil {
private final long accountID;
private final long totalSize;
private final boolean enable512e;
private final VolumeToCreateParamsQoS qos;
private final VolumeToCreateParamsAttributes attributes;
private final VolumeToCreateParamsQoS qos;
private VolumeToCreateParams(final String strVolumeName, final long lAccountId, final long lTotalSize, final boolean bEnable512e,
final String strCloudStackVolumeSize, final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) {
@ -1024,6 +1027,57 @@ public class SolidFireUtil {
}
}
@SuppressWarnings("unused")
private static final class VolumeToModifyWithCloudStackVolumeSize
{
private final String method = "ModifyVolume";
private final VolumeToModifyParams params;
private VolumeToModifyWithCloudStackVolumeSize(final long lVolumeId, final long lTotalSize, final String strCloudStackVolumeSize,
final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS)
{
params = new VolumeToModifyParams(lVolumeId, lTotalSize, strCloudStackVolumeSize, lMinIOPS, lMaxIOPS, lBurstIOPS);
}
private static final class VolumeToModifyParams
{
private final long volumeID;
private final long totalSize;
private final VolumeToModifyParamsAttributes attributes;
private final VolumeToModifyParamsQoS qos;
private VolumeToModifyParams(final long lVolumeId, final long lTotalSize, String strCloudStackVolumeSize, final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS)
{
volumeID = lVolumeId;
totalSize = lTotalSize;
attributes = new VolumeToModifyParamsAttributes(strCloudStackVolumeSize);
qos = new VolumeToModifyParamsQoS(lMinIOPS, lMaxIOPS, lBurstIOPS);
}
}
private static final class VolumeToModifyParamsAttributes {
private final String CloudStackVolumeSize;
private VolumeToModifyParamsAttributes(final String strCloudStackVolumeSize) {
CloudStackVolumeSize = strCloudStackVolumeSize;
}
}
private static final class VolumeToModifyParamsQoS {
private final long minIOPS;
private final long maxIOPS;
private final long burstIOPS;
private VolumeToModifyParamsQoS(final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) {
minIOPS = lMinIOPS;
maxIOPS = lMaxIOPS;
burstIOPS = lBurstIOPS;
}
}
}
@SuppressWarnings("unused")
private static final class VolumeToModify
{

View File

@ -851,7 +851,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
}
}
// Note: The storage plug-in in question should perform validation on the IOPS to check if a sufficient number of IOPS are available to perform
// Note: The storage plug-in in question should perform validation on the IOPS to check if a sufficient number of IOPS is available to perform
// the requested change
/* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */
@ -970,9 +970,21 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
hosts = new long[] {userVm.getLastHostId()};
}
final String errorMsg = "The VM must be stopped or the disk detached in order to resize with the XenServer Hypervisor.";
StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
if (storagePool.isManaged() && storagePool.getHypervisor() == HypervisorType.Any && hosts != null && hosts.length > 0) {
HostVO host = this._hostDao.findById(hosts[0]);
if (currentSize != newSize && host.getHypervisorType() == HypervisorType.XenServer && !userVm.getState().equals(State.Stopped)) {
throw new InvalidParameterValueException(errorMsg);
}
}
/* Xen only works offline, SR does not support VDI.resizeOnline */
if (currentSize != newSize && _volsDao.getHypervisorType(volume.getId()) == HypervisorType.XenServer && !userVm.getState().equals(State.Stopped)) {
throw new InvalidParameterValueException("VM must be stopped or disk detached in order to resize with the Xen HV");
throw new InvalidParameterValueException(errorMsg);
}
}
@ -982,8 +994,30 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
VolumeInfo vol = volFactory.getVolume(volume.getId());
vol.addPayload(payload);
StoragePoolVO storagePool = _storagePoolDao.findById(vol.getPoolId());
// managed storage is designed in such a way that the storage plug-in does not
// talk to the hypervisor layer; as such, if the storage is managed and the
// current and new sizes are different, then CloudStack (i.e. not a storage plug-in)
// needs to tell the hypervisor to resize the disk
if (storagePool.isManaged() && currentSize != newSize) {
if (hosts != null && hosts.length > 0) {
volService.resizeVolumeOnHypervisor(volumeId, newSize, hosts[0], instanceName);
}
volume.setSize(newSize);
_volsDao.update(volume.getId(), volume);
}
// this call to resize has a different impact depending on whether the
// underlying primary storage is managed or not
// if managed, this is the chance for the plug-in to change IOPS value, if applicable
// if not managed, this is the chance for the plug-in to talk to the hypervisor layer
// to change the size of the disk
AsyncCallFuture<VolumeApiResult> future = volService.resize(vol);
VolumeApiResult result = future.get();
if (result.isFailed()) {
s_logger.warn("Failed to resize the volume " + volume);
String details = "";
@ -995,19 +1029,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
volume = _volsDao.findById(volume.getId());
StoragePoolVO storagePool = _storagePoolDao.findById(vol.getPoolId());
if (currentSize != newSize && storagePool.isManaged()) {
if (hosts != null && hosts.length > 0) {
volService.resizeVolumeOnHypervisor(volumeId, newSize, hosts[0], instanceName);
}
volume.setSize(newSize);
}
if (newDiskOfferingId != null) {
volume.setDiskOfferingId(newDiskOfferingId);
}
_volsDao.update(volume.getId(), volume);
// Log usage event for volumes belonging user VM's only
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_RESIZE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(),