Inform the applicable storage plug-in's life cycle that capacity (bytes and/or IOPS) can be updated

This commit is contained in:
Mike Tutkowski 2014-06-17 19:22:52 -06:00
parent 0df156c09e
commit c344693e48
13 changed files with 341 additions and 39 deletions

View File

@ -18,5 +18,13 @@
*/
package org.apache.cloudstack.engine.subsystem.api.storage;
import java.util.Map;
import com.cloud.storage.StoragePool;
public interface PrimaryDataStoreLifeCycle extends DataStoreLifeCycle {
public static final String CAPACITY_BYTES = "capacityBytes";
public static final String CAPACITY_IOPS = "capacityIops";
void updateStoragePool(StoragePool storagePool, Map<String, String> details);
}

View File

@ -102,4 +102,8 @@ public interface CapacityManager {
boolean checkIfClusterCrossesThreshold(Long clusterId, Integer cpuRequested, long ramRequested);
float getClusterOverProvisioningFactor(Long clusterId, short capacityType);
long getUsedBytes(StoragePoolVO pool);
long getUsedIops(StoragePoolVO pool);
}

View File

@ -493,5 +493,7 @@ public class ElastistorPrimaryDataStoreLifeCycle implements PrimaryDataStoreLife
return false;
}
@Override
public void updateStoragePool(StoragePool storagePool, Map<String, String> details) {
}
}

View File

@ -525,4 +525,7 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements PrimaryDataStore
return false;
}
@Override
public void updateStoragePool(StoragePool storagePool, Map<String, String> details) {
}
}

View File

@ -41,6 +41,7 @@ import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.resource.ResourceManager;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolAutomation;
public class NexentaPrimaryDataStoreLifeCycle
@ -173,4 +174,8 @@ public class NexentaPrimaryDataStoreLifeCycle
public boolean migrateToObjectStore(DataStore store) {
return false;
}
@Override
public void updateStoragePool(StoragePool storagePool, Map<String, String> details) {
}
}

View File

@ -41,6 +41,7 @@ import com.cloud.agent.api.StoragePoolInfo;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus;
public class SamplePrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle {
@ -135,4 +136,7 @@ public class SamplePrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLife
return false;
}
@Override
public void updateStoragePool(StoragePool storagePool, Map<String, String> details) {
}
}

View File

@ -33,15 +33,18 @@ import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCy
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.util.SolidFireUtil;
import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper;
import com.cloud.agent.api.StoragePoolInfo;
import com.cloud.capacity.CapacityManager;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.resource.ResourceManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolAutomation;
@ -50,18 +53,13 @@ import com.cloud.utils.exception.CloudRuntimeException;
public class SolidFirePrimaryDataStoreLifeCycle implements PrimaryDataStoreLifeCycle {
private static final Logger s_logger = Logger.getLogger(SolidFirePrimaryDataStoreLifeCycle.class);
@Inject
private DataCenterDao zoneDao;
@Inject
private PrimaryDataStoreDao storagePoolDao;
@Inject
private PrimaryDataStoreHelper dataStoreHelper;
@Inject
private ResourceManager _resourceMgr;
@Inject
private StorageManager _storageMgr;
@Inject
private StoragePoolAutomation storagePoolAutomation;
@Inject CapacityManager _capacityMgr;
@Inject private DataCenterDao zoneDao;
@Inject private PrimaryDataStoreDao storagePoolDao;
@Inject private PrimaryDataStoreHelper dataStoreHelper;
@Inject private ResourceManager _resourceMgr;
@Inject private StorageManager _storageMgr;
@Inject private StoragePoolAutomation storagePoolAutomation;
// invoked to add primary storage that is based on the SolidFire plug-in
@Override
@ -244,4 +242,30 @@ public class SolidFirePrimaryDataStoreLifeCycle implements PrimaryDataStoreLifeC
return false;
}
@Override
public void updateStoragePool(StoragePool storagePool, Map<String, String> details) {
StoragePoolVO storagePoolVo = storagePoolDao.findById(storagePool.getId());
String strCapacityBytes = details.get(PrimaryDataStoreLifeCycle.CAPACITY_BYTES);
Long capacityBytes = strCapacityBytes != null ? Long.parseLong(strCapacityBytes) : null;
if (capacityBytes != null) {
long usedBytes = _capacityMgr.getUsedBytes(storagePoolVo);
if (capacityBytes < usedBytes) {
throw new CloudRuntimeException("Cannot reduce the number of bytes for this storage pool as it would lead to an insufficient number of bytes");
}
}
String strCapacityIops = details.get(PrimaryDataStoreLifeCycle.CAPACITY_IOPS);
Long capacityIops = strCapacityIops != null ? Long.parseLong(strCapacityIops) : null;
if (capacityIops != null) {
long usedIops = _capacityMgr.getUsedIops(storagePoolVo);
if (capacityIops < usedIops) {
throw new CloudRuntimeException("Cannot reduce the number of IOPS for this storage pool as it would lead to an insufficient number of IOPS");
}
}
}
}

View File

@ -209,6 +209,10 @@ public class SolidFireSharedPrimaryDataStoreLifeCycle implements PrimaryDataStor
throw new CloudRuntimeException("The parameter '" + CAPACITY_IOPS + "' must be equal to the parameter '" + SolidFireUtil.MIN_IOPS + "'.");
}
if (lMinIops > SolidFireUtil.MAX_IOPS_PER_VOLUME || lMaxIops > SolidFireUtil.MAX_IOPS_PER_VOLUME || lBurstIops > SolidFireUtil.MAX_IOPS_PER_VOLUME) {
throw new CloudRuntimeException("This volume cannot exceed " + NumberFormat.getInstance().format(SolidFireUtil.MAX_IOPS_PER_VOLUME) + " IOPS.");
}
details.put(SolidFireUtil.MIN_IOPS, String.valueOf(lMinIops));
details.put(SolidFireUtil.MAX_IOPS, String.valueOf(lMaxIops));
details.put(SolidFireUtil.BURST_IOPS, String.valueOf(lBurstIops));
@ -302,7 +306,7 @@ public class SolidFireSharedPrimaryDataStoreLifeCycle implements PrimaryDataStor
}
long sfVolumeId = SolidFireUtil.createSolidFireVolume(sfConnection, SolidFireUtil.getSolidFireVolumeName(volumeName), sfAccount.getId(), volumeSize,
true, NumberFormat.getInstance().format(volumeSize), minIops, maxIops, burstIops);
true, null, minIops, maxIops, burstIops);
SolidFireUtil.SolidFireVolume sfVolume = SolidFireUtil.getSolidFireVolume(sfConnection, sfVolumeId);
return sfVolume;
@ -523,6 +527,14 @@ public class SolidFireSharedPrimaryDataStoreLifeCycle implements PrimaryDataStor
return Long.parseLong(volumeId);
}
private long getIopsValue(long storagePoolId, String iopsKey) {
StoragePoolDetailVO storagePoolDetail = _storagePoolDetailsDao.findDetail(storagePoolId, iopsKey);
String iops = storagePoolDetail.getValue();
return Long.parseLong(iops);
}
private static boolean isSupportedHypervisorType(HypervisorType hypervisorType) {
return HypervisorType.XenServer.equals(hypervisorType) || HypervisorType.VMware.equals(hypervisorType);
}
@ -545,4 +557,49 @@ public class SolidFireSharedPrimaryDataStoreLifeCycle implements PrimaryDataStor
return false;
}
@Override
public void updateStoragePool(StoragePool storagePool, Map<String, String> details) {
String strCapacityBytes = details.get(PrimaryDataStoreLifeCycle.CAPACITY_BYTES);
String strCapacityIops = details.get(PrimaryDataStoreLifeCycle.CAPACITY_IOPS);
Long capacityBytes = strCapacityBytes != null ? Long.parseLong(strCapacityBytes) : null;
Long capacityIops = strCapacityIops != null ? Long.parseLong(strCapacityIops) : null;
SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePool.getId(), _storagePoolDetailsDao);
long size = capacityBytes != null ? capacityBytes : storagePool.getCapacityBytes();
long currentMinIops = getIopsValue(storagePool.getId(), SolidFireUtil.MIN_IOPS);
long currentMaxIops = getIopsValue(storagePool.getId(), SolidFireUtil.MAX_IOPS);
long currentBurstIops = getIopsValue(storagePool.getId(), SolidFireUtil.BURST_IOPS);
long minIops = currentMinIops;
long maxIops = currentMaxIops;
long burstIops = currentBurstIops;
if (capacityIops != null) {
if (capacityIops > SolidFireUtil.MAX_IOPS_PER_VOLUME) {
throw new CloudRuntimeException("This volume cannot exceed " + NumberFormat.getInstance().format(SolidFireUtil.MAX_IOPS_PER_VOLUME) + " IOPS.");
}
float maxPercentOfMin = currentMaxIops / (float)currentMinIops;
float burstPercentOfMax = currentBurstIops / (float)currentMaxIops;
minIops = capacityIops;
maxIops = (long)(minIops * maxPercentOfMin);
burstIops = (long)(maxIops * burstPercentOfMax);
if (maxIops > SolidFireUtil.MAX_IOPS_PER_VOLUME) {
maxIops = SolidFireUtil.MAX_IOPS_PER_VOLUME;
}
if (burstIops > SolidFireUtil.MAX_IOPS_PER_VOLUME) {
burstIops = SolidFireUtil.MAX_IOPS_PER_VOLUME;
}
}
SolidFireUtil.modifySolidFireVolume(sfConnection, getVolumeId(storagePool.getId()), size, minIops, maxIops, burstIops);
SolidFireUtil.updateCsDbWithSolidFireIopsInfo(storagePool.getId(), _primaryDataStoreDao, _storagePoolDetailsDao, minIops, maxIops, burstIops);
}
}

View File

@ -28,7 +28,10 @@ import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.UUID;
@ -36,6 +39,7 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
import org.apache.commons.lang.StringUtils;
@ -99,6 +103,8 @@ public class SolidFireUtil {
public static final String DATASTORE_NAME = "datastoreName";
public static final String IQN = "iqn";
public static final long MAX_IOPS_PER_VOLUME = 100000;
private static final int DEFAULT_MANAGEMENT_PORT = 443;
private static final int DEFAULT_STORAGE_PORT = 3260;
@ -156,6 +162,30 @@ public class SolidFireUtil {
return "CloudStack_" + csAccountUuid + "_" + csAccountId;
}
public static void updateCsDbWithSolidFireIopsInfo(long storagePoolId, PrimaryDataStoreDao primaryDataStoreDao, StoragePoolDetailsDao storagePoolDetailsDao,
long minIops, long maxIops, long burstIops) {
Map<String, String> existingDetails = storagePoolDetailsDao.listDetailsKeyPairs(storagePoolId);
Set<String> existingKeys = existingDetails.keySet();
Map<String, String> existingDetailsToKeep = new HashMap<String, String>();
for (String existingKey : existingKeys) {
String existingValue = existingDetails.get(existingKey);
if (!SolidFireUtil.MIN_IOPS.equalsIgnoreCase(existingValue) &&
!SolidFireUtil.MAX_IOPS.equalsIgnoreCase(existingValue) &&
!SolidFireUtil.BURST_IOPS.equalsIgnoreCase(existingValue)) {
existingDetailsToKeep.put(existingKey, existingValue);
}
}
existingDetailsToKeep.put(SolidFireUtil.MIN_IOPS, String.valueOf(minIops));
existingDetailsToKeep.put(SolidFireUtil.MAX_IOPS, String.valueOf(maxIops));
existingDetailsToKeep.put(SolidFireUtil.BURST_IOPS, String.valueOf(burstIops));
primaryDataStoreDao.updateDetails(storagePoolId, existingDetailsToKeep);
}
public static void updateCsDbWithSolidFireAccountInfo(long csAccountId, SolidFireUtil.SolidFireAccount sfAccount,
AccountDetailsDao accountDetailsDao) {
AccountDetailVO accountDetail = new AccountDetailVO(csAccountId,
@ -402,11 +432,13 @@ public class SolidFireUtil {
}
public static long createSolidFireVolume(SolidFireConnection sfConnection, String strSfVolumeName, long lSfAccountId, long lTotalSize,
boolean bEnable512e, final String strCloudStackVolumeSize, long lMinIops, long lMaxIops, long lBurstIops)
boolean bEnable512e, String strCloudStackVolumeSize, long minIops, long maxIops, long burstIops)
{
final Gson gson = new GsonBuilder().create();
VolumeToCreate volumeToCreate = new VolumeToCreate(strSfVolumeName, lSfAccountId, lTotalSize, bEnable512e, strCloudStackVolumeSize, lMinIops, lMaxIops, lBurstIops);
Object volumeToCreate = strCloudStackVolumeSize != null && strCloudStackVolumeSize.trim().length() > 0 ?
new VolumeToCreateWithCloudStackVolumeSize(strSfVolumeName, lSfAccountId, lTotalSize, bEnable512e, strCloudStackVolumeSize, minIops, maxIops, burstIops) :
new VolumeToCreate(strSfVolumeName, lSfAccountId, lTotalSize, bEnable512e, minIops, maxIops, burstIops);
String strVolumeToCreateJson = gson.toJson(volumeToCreate);
@ -419,6 +451,23 @@ public class SolidFireUtil {
return volumeCreateResult.result.volumeID;
}
public static void modifySolidFireVolume(SolidFireConnection sfConnection, long volumeId, long totalSize, long minIops, long maxIops, long burstIops)
{
final Gson gson = new GsonBuilder().create();
VolumeToModify volumeToModify = new VolumeToModify(volumeId, totalSize, minIops, maxIops, burstIops);
String strVolumeToModifyJson = gson.toJson(volumeToModify);
String strVolumeModifyResultJson = executeJsonRpc(sfConnection, strVolumeToModifyJson);
JsonError jsonError = gson.fromJson(strVolumeModifyResultJson, JsonError.class);
if (jsonError.error != null) {
throw new IllegalStateException(jsonError.error.message);
}
}
public static SolidFireVolume getSolidFireVolume(SolidFireConnection sfConnection, long lVolumeId)
{
final Gson gson = new GsonBuilder().create();
@ -868,12 +917,12 @@ public class SolidFireUtil {
}
@SuppressWarnings("unused")
private static final class VolumeToCreate {
private static final class VolumeToCreateWithCloudStackVolumeSize {
private final String method = "CreateVolume";
private final VolumeToCreateParams params;
private VolumeToCreate(final String strVolumeName, final long lAccountId, final long lTotalSize, final boolean bEnable512e, final String strCloudStackVolumeSize,
final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) {
private VolumeToCreateWithCloudStackVolumeSize(final String strVolumeName, final long lAccountId, final long lTotalSize,
final boolean bEnable512e, final String strCloudStackVolumeSize, final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) {
params = new VolumeToCreateParams(strVolumeName, lAccountId, lTotalSize, bEnable512e, strCloudStackVolumeSize, lMinIOPS, lMaxIOPS, lBurstIOPS);
}
@ -918,6 +967,87 @@ public class SolidFireUtil {
}
}
@SuppressWarnings("unused")
private static final class VolumeToCreate {
private final String method = "CreateVolume";
private final VolumeToCreateParams params;
private VolumeToCreate(final String strVolumeName, final long lAccountId, final long lTotalSize, final boolean bEnable512e,
final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) {
params = new VolumeToCreateParams(strVolumeName, lAccountId, lTotalSize, bEnable512e, lMinIOPS, lMaxIOPS, lBurstIOPS);
}
private static final class VolumeToCreateParams {
private final String name;
private final long accountID;
private final long totalSize;
private final boolean enable512e;
private final VolumeToCreateParamsQoS qos;
private VolumeToCreateParams(final String strVolumeName, final long lAccountId, final long lTotalSize, final boolean bEnable512e,
final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) {
name = strVolumeName;
accountID = lAccountId;
totalSize = lTotalSize;
enable512e = bEnable512e;
qos = new VolumeToCreateParamsQoS(lMinIOPS, lMaxIOPS, lBurstIOPS);
}
private static final class VolumeToCreateParamsQoS {
private final long minIOPS;
private final long maxIOPS;
private final long burstIOPS;
private VolumeToCreateParamsQoS(final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) {
minIOPS = lMinIOPS;
maxIOPS = lMaxIOPS;
burstIOPS = lBurstIOPS;
}
}
}
}
@SuppressWarnings("unused")
private static final class VolumeToModify
{
private final String method = "ModifyVolume";
private final VolumeToModifyParams params;
private VolumeToModify(final long lVolumeId, final long lTotalSize, final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS)
{
params = new VolumeToModifyParams(lVolumeId, lTotalSize, lMinIOPS, lMaxIOPS, lBurstIOPS);
}
private static final class VolumeToModifyParams
{
private final long volumeID;
private final long totalSize;
private final VolumeToModifyParamsQoS qos;
private VolumeToModifyParams(final long lVolumeId, final long lTotalSize, final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS)
{
volumeID = lVolumeId;
totalSize = lTotalSize;
qos = new VolumeToModifyParamsQoS(lMinIOPS, lMaxIOPS, lBurstIOPS);
}
}
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 VolumeToGet
{
@ -1376,8 +1506,8 @@ public class SolidFireUtil {
return iCode >= 200 && iCode < 300;
}
private static void verifyResult(Object obj, String strJson, Gson gson) throws IllegalStateException {
if (obj != null) {
private static void verifyResult(Object result, String strJson, Gson gson) throws IllegalStateException {
if (result != null) {
return;
}

View File

@ -514,7 +514,8 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
}
private long getUsedBytes(StoragePoolVO pool) {
@Override
public long getUsedBytes(StoragePoolVO pool) {
long usedBytes = 0;
List<VolumeVO> volumes = _volumeDao.findByPoolId(pool.getId(), null);
@ -541,6 +542,21 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
return usedBytes;
}
@Override
public long getUsedIops(StoragePoolVO pool) {
long usedIops = 0;
List<VolumeVO> volumes = _volumeDao.findByPoolId(pool.getId(), null);
if (volumes != null && volumes.size() > 0) {
for (VolumeVO volume : volumes) {
usedIops += volume.getMinIops();
}
}
return usedIops;
}
@Override
public long getAllocatedPoolCapacity(StoragePoolVO pool, VMTemplateVO templateForVmCreation) {
long totalAllocatedSize = 0;

View File

@ -67,6 +67,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener
import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
@ -755,10 +756,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
Long capacityBytes = cmd.getCapacityBytes();
if (capacityBytes != null) {
if (capacityBytes > pool.getCapacityBytes()) {
if (capacityBytes != pool.getCapacityBytes()) {
updatedCapacityBytes = capacityBytes;
} else if (capacityBytes < pool.getCapacityBytes()) {
throw new CloudRuntimeException("The value of 'Capacity bytes' cannot be reduced in this version.");
}
}
@ -766,10 +765,23 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
Long capacityIops = cmd.getCapacityIops();
if (capacityIops != null) {
if (capacityIops > pool.getCapacityIops()) {
if (capacityIops != pool.getCapacityIops()) {
updatedCapacityIops = capacityIops;
} else if (capacityIops < pool.getCapacityIops()) {
throw new CloudRuntimeException("The value of 'Capacity IOPS' cannot be reduced in this version.");
}
}
if (updatedCapacityBytes != null || updatedCapacityIops != null) {
StoragePoolVO storagePool = _storagePoolDao.findById(id);
DataStoreProvider dataStoreProvider = dataStoreProviderMgr.getDataStoreProvider(storagePool.getStorageProviderName());
DataStoreLifeCycle dataStoreLifeCycle = dataStoreProvider.getDataStoreLifeCycle();
if (dataStoreLifeCycle instanceof PrimaryDataStoreLifeCycle) {
Map<String, String> details = new HashMap<String, String>();
details.put(PrimaryDataStoreLifeCycle.CAPACITY_BYTES, updatedCapacityBytes != null ? String.valueOf(updatedCapacityBytes) : null);
details.put(PrimaryDataStoreLifeCycle.CAPACITY_IOPS, updatedCapacityIops != null ? String.valueOf(updatedCapacityIops) : null);
((PrimaryDataStoreLifeCycle)dataStoreLifeCycle).updateStoragePool(storagePool, details);
}
}
@ -1507,20 +1519,13 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
// Only IOPS guaranteed primary storage like SolidFire is using/setting IOPS.
// This check returns true for storage that does not specify IOPS.
if (pool.getCapacityIops() == null ) {
s_logger.info("Storage pool " + pool.getName() + " (" + pool.getId() + ") does not supply Iops capacity, assuming enough capacity");
s_logger.info("Storage pool " + pool.getName() + " (" + pool.getId() + ") does not supply IOPS capacity, assuming enough capacity");
return true;
}
long currentIops = 0;
List<VolumeVO> volumesInPool = _volumeDao.findByPoolId(pool.getId(), null);
for (VolumeVO volumeInPool : volumesInPool) {
Long minIops = volumeInPool.getMinIops();
if (minIops != null && minIops > 0) {
currentIops += minIops;
}
}
StoragePoolVO storagePoolVo = _storagePoolDao.findById(pool.getId());
long currentIops = _capacityMgr.getUsedIops(storagePoolVo);
long requestedIops = 0;

View File

@ -900,6 +900,40 @@ cloudStack.converters = {
return (bytes / 1024 / 1024 / 1024 / 1024).toFixed(2) + " TB";
}
},
toBytes: function(str) {
if (str === undefined) {
return "0";
}
var res = str.split(" ");
if (res.length === 1) {
// assume a number in GB
return parseInt(str, 10) * 1024 * 1024 * 1024;
}
// assume first string is a number and second string is a unit of size
if (res[1] === "KB") {
return parseInt(res[0], 10) * 1024;
}
if (res[1] === "MB") {
return parseInt(res[0], 10) * 1024 * 1024;
}
if (res[1] === "GB") {
return parseInt(res[0], 10) * 1024 * 1024 * 1024;
}
if (res[1] === "TB") {
return parseInt(res[0], 10) * 1024 * 1024 * 1024 * 1024;
}
// assume GB
return parseInt(res[0], 10) * 1024 * 1024 * 1024;
},
toLocalDate: function(UtcDate) {
var localDate = "";
if (UtcDate != null && UtcDate.length > 0) {

View File

@ -16113,6 +16113,14 @@
var array1 =[];
array1.push("&tags=" + todb(args.data.tags));
if (args.data.disksizetotal != null && args.data.disksizetotal.length > 0) {
array1.push("&capacitybytes=" + cloudStack.converters.toBytes(args.data.disksizetotal));
}
if (args.data.capacityiops != null && args.data.capacityiops.length > 0) {
array1.push("&capacityiops=" + args.data.capacityiops);
}
$.ajax({
url: createURL("updateStoragePool&id=" + args.context.primarystorages[0].id + array1.join("")),
dataType: "json",
@ -16279,6 +16287,7 @@
},
disksizetotal: {
label: 'label.disk.total',
isEditable: true,
converter: function (args) {
if (args == null || args == 0)
return ""; else
@ -16295,6 +16304,7 @@
},
capacityiops: {
label: 'label.disk.iops.total',
isEditable: true,
converter: function (args) {
if (args == null || args == 0)
return ""; else