mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Inform the applicable storage plug-in's life cycle that capacity (bytes and/or IOPS) can be updated
This commit is contained in:
parent
0df156c09e
commit
c344693e48
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -493,5 +493,7 @@ public class ElastistorPrimaryDataStoreLifeCycle implements PrimaryDataStoreLife
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateStoragePool(StoragePool storagePool, Map<String, String> details) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -525,4 +525,7 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements PrimaryDataStore
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStoragePool(StoragePool storagePool, Map<String, String> details) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user