You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mt...@apache.org on 2014/06/24 22:50:43 UTC
git commit: updated refs/heads/master to c344693
Repository: cloudstack
Updated Branches:
refs/heads/master 0df156c09 -> c344693e4
Inform the applicable storage plug-in's life cycle that capacity (bytes and/or IOPS) can be updated
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/c344693e
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/c344693e
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/c344693e
Branch: refs/heads/master
Commit: c344693e48d80313270d1a972b0a3badf315567d
Parents: 0df156c
Author: Mike Tutkowski <mi...@solidfire.com>
Authored: Tue Jun 17 19:22:52 2014 -0600
Committer: Mike Tutkowski <mi...@solidfire.com>
Committed: Tue Jun 24 14:39:57 2014 -0600
----------------------------------------------------------------------
.../api/storage/PrimaryDataStoreLifeCycle.java | 8 ++
.../src/com/cloud/capacity/CapacityManager.java | 4 +
.../ElastistorPrimaryDataStoreLifeCycle.java | 4 +-
...CloudStackPrimaryDataStoreLifeCycleImpl.java | 3 +
.../NexentaPrimaryDataStoreLifeCycle.java | 5 +
.../SamplePrimaryDataStoreLifeCycleImpl.java | 4 +
.../SolidFirePrimaryDataStoreLifeCycle.java | 48 +++++--
...olidFireSharedPrimaryDataStoreLifeCycle.java | 59 +++++++-
.../storage/datastore/util/SolidFireUtil.java | 144 ++++++++++++++++++-
.../com/cloud/capacity/CapacityManagerImpl.java | 18 ++-
.../com/cloud/storage/StorageManagerImpl.java | 39 ++---
ui/scripts/sharedFunctions.js | 34 +++++
ui/scripts/system.js | 10 ++
13 files changed, 341 insertions(+), 39 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java
index 28b06f5..7640cf3 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java
@@ -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);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/engine/components-api/src/com/cloud/capacity/CapacityManager.java
----------------------------------------------------------------------
diff --git a/engine/components-api/src/com/cloud/capacity/CapacityManager.java b/engine/components-api/src/com/cloud/capacity/CapacityManager.java
index 038a2c0..51f7332 100755
--- a/engine/components-api/src/com/cloud/capacity/CapacityManager.java
+++ b/engine/components-api/src/com/cloud/capacity/CapacityManager.java
@@ -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);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java
index aa33b2f..33004e3 100755
--- a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java
+++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java
@@ -493,5 +493,7 @@ public class ElastistorPrimaryDataStoreLifeCycle implements PrimaryDataStoreLife
return false;
}
-
+ @Override
+ public void updateStoragePool(StoragePool storagePool, Map<String, String> details) {
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
index 65236d9..49eb8ef 100644
--- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
+++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
@@ -525,4 +525,7 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements PrimaryDataStore
return false;
}
+ @Override
+ public void updateStoragePool(StoragePool storagePool, Map<String, String> details) {
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/plugins/storage/volume/nexenta/src/org/apache/cloudstack/storage/datastore/lifecylce/NexentaPrimaryDataStoreLifeCycle.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/nexenta/src/org/apache/cloudstack/storage/datastore/lifecylce/NexentaPrimaryDataStoreLifeCycle.java b/plugins/storage/volume/nexenta/src/org/apache/cloudstack/storage/datastore/lifecylce/NexentaPrimaryDataStoreLifeCycle.java
index c7ce33a..493f274 100644
--- a/plugins/storage/volume/nexenta/src/org/apache/cloudstack/storage/datastore/lifecylce/NexentaPrimaryDataStoreLifeCycle.java
+++ b/plugins/storage/volume/nexenta/src/org/apache/cloudstack/storage/datastore/lifecylce/NexentaPrimaryDataStoreLifeCycle.java
@@ -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) {
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java
index 6b5e431..579cc24 100644
--- a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java
+++ b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java
@@ -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) {
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFirePrimaryDataStoreLifeCycle.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFirePrimaryDataStoreLifeCycle.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFirePrimaryDataStoreLifeCycle.java
index 7fc3436..c23db14 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFirePrimaryDataStoreLifeCycle.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFirePrimaryDataStoreLifeCycle.java
@@ -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");
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java
index ec2a52f..b03634b 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java
@@ -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);
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
index a27917b..3f35d71 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
@@ -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);
}
@@ -919,6 +968,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
{
private final String method = "ListActiveVolumes";
@@ -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;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/server/src/com/cloud/capacity/CapacityManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java
index 14fbe7f..e57604e 100755
--- a/server/src/com/cloud/capacity/CapacityManagerImpl.java
+++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java
@@ -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);
@@ -542,6 +543,21 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
}
@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;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/server/src/com/cloud/storage/StorageManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java
index de4ad4b..07ae695 100755
--- a/server/src/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/com/cloud/storage/StorageManagerImpl.java
@@ -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;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/ui/scripts/sharedFunctions.js
----------------------------------------------------------------------
diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js
index f58fdd2..e8c4fcb 100644
--- a/ui/scripts/sharedFunctions.js
+++ b/ui/scripts/sharedFunctions.js
@@ -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) {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c344693e/ui/scripts/system.js
----------------------------------------------------------------------
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index 7d49d8d..9a98a5c 100644
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -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