diff --git a/client/pom.xml b/client/pom.xml
index 615d2441516..d8dbde72a8d 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -35,6 +35,11 @@
cloud-plugin-storage-volume-solidfire
${project.version}
+
+ org.apache.cloudstack
+ cloud-plugin-storage-volume-cloudbyte
+ ${project.version}
+
org.apache.cloudstack
cloud-server
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 9366be1cafe..9b391b8b2ca 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -78,6 +78,7 @@
storage/image/sample
storage/volume/nexenta
storage/volume/solidfire
+ storage/volume/cloudbyte
storage/volume/default
storage/volume/sample
alert-handlers/snmp-alerts
diff --git a/plugins/storage/volume/cloudbyte/pom.xml b/plugins/storage/volume/cloudbyte/pom.xml
new file mode 100755
index 00000000000..3d3c9f020d0
--- /dev/null
+++ b/plugins/storage/volume/cloudbyte/pom.xml
@@ -0,0 +1,71 @@
+
+
+ 4.0.0
+ cloud-plugin-storage-volume-cloudbyte
+ Apache CloudStack Plugin - Storage Volume CloudByte Provider
+
+ org.apache.cloudstack
+ cloudstack-plugins
+ 4.4.0-SNAPSHOT
+ ../../../pom.xml
+
+
+
+ org.apache.cloudstack
+ cloud-plugin-storage-volume-default
+ ${project.version}
+
+
+ org.apache.cloudstack
+ cloud-engine-storage-volume
+ ${project.version}
+
+
+ mysql
+ mysql-connector-java
+ ${cs.mysql.version}
+ provided
+
+
+ com.google.code.gson
+ gson
+ ${cs.gson.version}
+
+
+ com.sun.jersey
+ jersey-bundle
+ 1.17.1
+
+
+
+ install
+ src
+ test
+
+
+ maven-surefire-plugin
+
+ true
+
+
+
+ integration-test
+
+ test
+
+
+
+
+
+
+
diff --git a/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/module.properties b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/module.properties
new file mode 100755
index 00000000000..730e376c925
--- /dev/null
+++ b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/module.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+name=storage-volume-cloudbyte
+parent=storage
\ No newline at end of file
diff --git a/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/spring-storage-volume-cloudbyte-context.xml b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/spring-storage-volume-cloudbyte-context.xml
new file mode 100755
index 00000000000..87c5f513935
--- /dev/null
+++ b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/spring-storage-volume-cloudbyte-context.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java
new file mode 100755
index 00000000000..f603b349db4
--- /dev/null
+++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java
@@ -0,0 +1,88 @@
+package org.apache.cloudstack.storage.datastore.driver;
+
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
+import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
+import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+import org.apache.cloudstack.storage.command.CommandResult;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.storage.dao.DiskOfferingDao;
+import com.cloud.user.AccountManager;
+
+/**
+ * The implementation class for PrimaryDataStoreDriver. This
+ * directs the public interface methods to use CloudByte's Elastistor based
+ * volumes.
+ *
+ * @author amit.das@cloudbyte.com
+ * @author punith.s@cloudbyte.com
+ *
+ */
+public class ElastistorPrimaryDataStoreDriver extends CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver{
+
+ private static final Logger s_logger = Logger.getLogger(ElastistorPrimaryDataStoreDriver.class);
+
+ @Inject
+ AccountManager _accountMgr;
+ @Inject
+ DiskOfferingDao _diskOfferingDao;
+ @Override
+ public DataTO getTO(DataObject data) {
+ return null;
+ }
+
+ @Override
+ public DataStoreTO getStoreTO(DataStore store) {
+ return null;
+ }
+
+ public void createAsync(DataStore dataStore, DataObject dataObject, AsyncCompletionCallback callback) {
+ super.createAsync(dataStore, dataObject, callback);
+ }
+
+ public void deleteAsync(DataStore dataStore, DataObject dataObject, AsyncCompletionCallback callback) {
+ super.deleteAsync(dataStore, dataObject, callback);
+ }
+
+ @Override
+ public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback callback) {
+ throw new UnsupportedOperationException();
+
+ }
+
+ @Override
+ public boolean canCopy(DataObject srcData, DataObject destData) {
+ return false;
+ }
+
+ @Override
+ public void resize(DataObject data, AsyncCompletionCallback callback) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ChapInfo getChapInfo(VolumeInfo volumeInfo) {
+ return super.getChapInfo(volumeInfo);
+ }
+
+ @Override
+ public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) {
+ throw new UnsupportedOperationException();
+ }
+
+}
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
new file mode 100755
index 00000000000..9719ba85d68
--- /dev/null
+++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java
@@ -0,0 +1,479 @@
+package org.apache.cloudstack.storage.datastore.lifecycle;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
+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.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.StoragePoolDetailsDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.cloudstack.storage.datastore.util.ElastistorUtil;
+import org.apache.cloudstack.storage.datastore.util.ElastistorUtil.CreateTsmCmdResponse;
+import org.apache.cloudstack.storage.datastore.util.ElastistorUtil.CreateVolumeCmdResponse;
+import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.CreateStoragePoolCommand;
+import com.cloud.agent.api.DeleteStoragePoolCommand;
+import com.cloud.agent.api.StoragePoolInfo;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.resource.ResourceManager;
+import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.storage.StorageManager;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.StoragePoolAutomation;
+import com.cloud.storage.StoragePoolHostVO;
+import com.cloud.storage.dao.StoragePoolHostDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+public class ElastistorPrimaryDataStoreLifeCycle implements PrimaryDataStoreLifeCycle {
+ private static final Logger s_logger = Logger.getLogger(ElastistorPrimaryDataStoreLifeCycle.class);
+
+ @Inject
+ HostDao _hostDao;
+ @Inject
+ StoragePoolHostDao _storagePoolHostDao;
+ @Inject
+ protected ResourceManager _resourceMgr;
+ @Inject
+ PrimaryDataStoreDao primaryDataStoreDao;
+ @Inject
+ AgentManager agentMgr;
+ @Inject
+ StorageManager storageMgr;
+ @Inject
+ PrimaryDataStoreHelper dataStoreHelper;
+ @Inject
+ PrimaryDataStoreDao _storagePoolDao;
+ @Inject
+ PrimaryDataStoreHelper _dataStoreHelper;
+ @Inject
+ StoragePoolAutomation _storagePoolAutomation;
+ @Inject
+ StoragePoolDetailsDao _storagePoolDetailsDao;
+ @Inject
+ DataCenterDao _zoneDao;
+
+ @Override
+ public DataStore initialize(Map dsInfos) {
+
+ String url = (String) dsInfos.get("url");
+ Long zoneId = (Long) dsInfos.get("zoneId");
+ Long podId = (Long) dsInfos.get("podId");
+ Long clusterId = (Long) dsInfos.get("clusterId");
+ String storagePoolName = (String) dsInfos.get("name");
+ String providerName = (String) dsInfos.get("providerName");
+ Long capacityBytes = (Long) dsInfos.get("capacityBytes");
+ Long capacityIops = (Long) dsInfos.get("capacityIops");
+ String tags = (String) dsInfos.get("tags");
+ Map details = (Map) dsInfos.get("details");
+ String storageIp = getStorageIp(url);
+ int storagePort = getDefaultStoragePort(url);
+ StoragePoolType storagetype = getStorageType(url);
+ String accesspath = getAccessPath(url);
+ String protocoltype = getProtocolType(url);
+ String[] mp = accesspath.split("/");
+ String mountpoint = mp[1];
+ String uuid = null ;
+
+ /**
+ * if the elastistor params which are required for plugin configuration
+ * are not injected through spring-storage-volume-cloudbyte-context.xml, it can be set from details map.
+ */
+ if(details.get("esaccountid") != null)
+ ElastistorUtil.setElastistorAccountId(details.get("esaccountid"));
+ if(details.get("esapikey") != null)
+ ElastistorUtil.setElastistorApiKey(details.get("esapikey"));
+ if(details.get("esdefaultgateway") != null)
+ ElastistorUtil.setElastistorGateway(details.get("esdefaultgateway"));
+ if(details.get("estntinterface") != null)
+ ElastistorUtil.setElastistorInterface(details.get("estntinterface"));
+ if(details.get("esmanagementip") != null)
+ ElastistorUtil.setElastistorManagementIp(details.get("esmanagementip"));
+ if(details.get("espoolid") != null)
+ ElastistorUtil.setElastistorPoolId(details.get("espoolid"));
+ if(details.get("essubnet") != null)
+ ElastistorUtil.setElastistorSubnet(details.get("essubnet"));
+
+ if (capacityBytes == null || capacityBytes <= 0) {
+ throw new IllegalArgumentException("'capacityBytes' must be present and greater than 0.");
+ }
+
+ if (capacityIops == null || capacityIops <= 0) {
+ throw new IllegalArgumentException("'capacityIops' must be present and greater than 0.");
+ }
+
+ // elastistor does not allow same name and ip pools.
+ List storagePoolVO = _storagePoolDao.listAll();
+ for(StoragePoolVO poolVO : storagePoolVO){
+ if (storagePoolName.equals(poolVO.getName())) {
+ throw new IllegalArgumentException("storage pool with that name already exists in elastistor,please specify a unique name .");
+ }
+ if (storageIp.equals(poolVO.getHostAddress())) {
+ throw new IllegalArgumentException("storage pool with that ip already exists in elastistor,please specify a unique ip .");
+ }
+ }
+
+ PrimaryDataStoreParameters parameters = new PrimaryDataStoreParameters();
+
+ // creates the volume in elastistor
+ parameters = createElastistorVolume(parameters, storagePoolName, storageIp, capacityBytes, capacityIops, protocoltype, mountpoint);
+
+ parameters.setHost(storageIp);
+ parameters.setPort(storagePort);
+ if(protocoltype.contentEquals("nfs")){
+ parameters.setPath(accesspath);
+ }
+ parameters.setType(storagetype);
+ parameters.setZoneId(zoneId);
+ parameters.setPodId(podId);
+ parameters.setName(storagePoolName);
+ parameters.setProviderName(providerName);
+ parameters.setManaged(false);
+ parameters.setCapacityBytes(capacityBytes);
+ parameters.setUsedBytes(0);
+ parameters.setCapacityIops(capacityIops);
+ parameters.setHypervisorType(HypervisorType.Any);
+ parameters.setTags(tags);
+ parameters.setDetails(details);
+ parameters.setClusterId(clusterId);
+
+ return _dataStoreHelper.createPrimaryDataStore(parameters);
+ }
+
+ private PrimaryDataStoreParameters createElastistorVolume(PrimaryDataStoreParameters parameters, String storagePoolName, String storageIp, Long capacityBytes, Long capacityIops, String protocoltype, String mountpoint){
+
+ s_logger.info("creation of elastistor volume started");
+ try {
+
+ CreateTsmCmdResponse tsmCmdResponse = ElastistorUtil.createElastistorTsm(storagePoolName, storageIp, capacityBytes, capacityIops);
+
+ String uuid = tsmCmdResponse.getTsm().getUuid();
+ parameters.setUuid(uuid);
+
+ CreateVolumeCmdResponse volumeCmdResponse = ElastistorUtil.createElastistorVolume(storagePoolName, tsmCmdResponse, capacityBytes, capacityIops, protocoltype ,mountpoint);
+
+ if(protocoltype.contentEquals("iscsi")){
+ String accesspath = "/"+volumeCmdResponse.getFileSystem().getIqn()+"/0";
+ parameters.setPath(accesspath);
+ }
+ s_logger.info("creation of elastistor volume complete");
+
+ return parameters;
+ } catch (Throwable e) {
+ throw new CloudRuntimeException("Failed to create volume in elastistor" + e.toString());
+ }
+
+ }
+
+ private String getAccessPath(String url) {
+ StringTokenizer st = new StringTokenizer(url ,"/");
+ int count = 0;
+ while (st.hasMoreElements()) {
+ if(count == 2)
+ { String s = "/" ;
+ return s.concat(st.nextElement().toString());
+ }
+ st.nextElement();
+ count++;
+ }
+ return null;
+ }
+
+
+ private StoragePoolType getStorageType(String url) {
+
+ StringTokenizer st = new StringTokenizer(url ,":");
+
+ while (st.hasMoreElements())
+ {
+ String accessprotocol = st.nextElement().toString();
+
+ if(accessprotocol.contentEquals("nfs"))
+ {
+ return StoragePoolType.NetworkFilesystem;
+ }
+ else if(accessprotocol.contentEquals("iscsi"))
+ {
+ return StoragePoolType.IscsiLUN;
+ }
+
+ else
+
+ break;
+
+ }
+ return null;
+ }
+
+ private String getProtocolType(String url) {
+ StringTokenizer st = new StringTokenizer(url ,":");
+
+ while (st.hasMoreElements())
+ {
+ String accessprotocol = st.nextElement().toString();
+
+ if(accessprotocol.contentEquals("nfs")){
+ return "nfs";
+ }else if(accessprotocol.contentEquals("iscsi")){
+ return "iscsi";
+ } else
+ break;
+ }
+ return null;
+ }
+
+ // this method parses the url and gets the default storage port based on access protocol
+ private int getDefaultStoragePort(String url) {
+
+ StringTokenizer st = new StringTokenizer(url ,":");
+
+ while (st.hasMoreElements())
+ {
+
+ String accessprotocol = st.nextElement().toString();
+
+ if(accessprotocol.contentEquals("nfs")){
+ return 2049;
+ }
+ else if(accessprotocol.contentEquals("iscsi")){
+ return 3260;
+ }
+ else
+ break;
+
+ }
+ return -1;
+
+ }
+
+ // parses the url and returns the storage volume ip
+ private String getStorageIp(String url) {
+
+ StringTokenizer st = new StringTokenizer(url ,"/");
+ int count = 0;
+
+ while (st.hasMoreElements()) {
+ if(count == 1)
+ return st.nextElement().toString();
+
+ st.nextElement();
+ count++;
+ }
+ return null;
+ }
+
+ @Override
+ public boolean attachCluster(DataStore store, ClusterScope scope) {
+
+ dataStoreHelper.attachCluster(store);
+
+ PrimaryDataStoreInfo primarystore = (PrimaryDataStoreInfo) store;
+ // Check if there is host up in this cluster
+ List allHosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, primarystore.getClusterId(),
+ primarystore.getPodId(), primarystore.getDataCenterId());
+ if (allHosts.isEmpty()) {
+ primaryDataStoreDao.expunge(primarystore.getId());
+ throw new CloudRuntimeException("No host up to associate a storage pool with in cluster "
+ + primarystore.getClusterId());
+ }
+
+
+ boolean success = false;
+ for (HostVO h : allHosts) {
+ success = createStoragePool(h.getId(), primarystore);
+ if (success) {
+ break;
+ }
+ }
+
+ s_logger.debug("In createPool Adding the pool to each of the hosts");
+ List poolHosts = new ArrayList();
+ for (HostVO h : allHosts) {
+ try {
+ storageMgr.connectHostToSharedPool(h.getId(), primarystore.getId());
+ poolHosts.add(h);
+ } catch (Exception e) {
+ s_logger.warn("Unable to establish a connection between " + h + " and " + primarystore, e);
+ }
+
+ if (poolHosts.isEmpty()) {
+ s_logger.warn("No host can access storage pool " + primarystore + " on cluster "
+ + primarystore.getClusterId());
+ primaryDataStoreDao.expunge(primarystore.getId());
+ throw new CloudRuntimeException("Failed to access storage pool");
+ }
+ }
+
+ return true;
+ }
+
+ private boolean createStoragePool(long hostId, StoragePool pool) {
+ s_logger.debug("creating pool " + pool.getName() + " on host " + hostId);
+ if (pool.getPoolType() != StoragePoolType.NetworkFilesystem && pool.getPoolType() != StoragePoolType.Filesystem
+ && pool.getPoolType() != StoragePoolType.IscsiLUN && pool.getPoolType() != StoragePoolType.Iscsi
+ && pool.getPoolType() != StoragePoolType.VMFS && pool.getPoolType() != StoragePoolType.SharedMountPoint
+ && pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2
+ && pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM) {
+ s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType());
+ return false;
+ }
+ CreateStoragePoolCommand cmd = new CreateStoragePoolCommand(true, pool);
+ final Answer answer = agentMgr.easySend(hostId, cmd);
+ if (answer != null && answer.getResult()) {
+ return true;
+ } else {
+ primaryDataStoreDao.expunge(pool.getId());
+ String msg = "";
+ if (answer != null) {
+ msg = "Can not create storage pool through host " + hostId + " due to " + answer.getDetails();
+ s_logger.warn(msg);
+ } else {
+ msg = "Can not create storage pool through host " + hostId + " due to CreateStoragePoolCommand returns null";
+ s_logger.warn(msg);
+ }
+ throw new CloudRuntimeException(msg);
+ }
+ }
+
+
+ @Override
+ public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) {
+ _dataStoreHelper.attachHost(store, scope, existingInfo);
+ return true;
+ }
+
+ @Override
+ public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) {
+ List hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(hypervisorType, scope.getScopeId());
+ s_logger.debug("In createPool. Attaching the pool to each of the hosts.");
+ List poolHosts = new ArrayList();
+ for (HostVO host : hosts) {
+ try {
+ storageMgr.connectHostToSharedPool(host.getId(), dataStore.getId());
+ poolHosts.add(host);
+ } catch (Exception e) {
+ s_logger.warn("Unable to establish a connection between " + host + " and " + dataStore, e);
+ }
+ }
+ if (poolHosts.isEmpty()) {
+ s_logger.warn("No host can access storage pool " + dataStore + " in this zone.");
+ primaryDataStoreDao.expunge(dataStore.getId());
+ throw new CloudRuntimeException("Failed to create storage pool as it is not accessible to hosts.");
+ }
+ dataStoreHelper.attachZone(dataStore, hypervisorType);
+ return true;
+ }
+
+ @Override
+ public boolean maintain(DataStore store) {
+ _storagePoolAutomation.maintain(store);
+ _dataStoreHelper.maintain(store);
+ return true;
+ }
+
+ @Override
+ public boolean cancelMaintain(DataStore store) {
+ _dataStoreHelper.cancelMaintain(store);
+ _storagePoolAutomation.cancelMaintain(store);
+ return true;
+ }
+
+ @SuppressWarnings("finally")
+ @Override
+ public boolean deleteDataStore(DataStore store) {
+ List hostPoolRecords = _storagePoolHostDao.listByPoolId(store.getId());
+ StoragePool pool = (StoragePool) store;
+
+ // find the hypervisor where the storage is attached to.
+ HypervisorType hType = null;
+ if(hostPoolRecords.size() > 0 ){
+ hType = getHypervisorType(hostPoolRecords.get(0).getHostId());
+ }
+
+ // Remove the SR associated with the Xenserver
+ for (StoragePoolHostVO host : hostPoolRecords) {
+ DeleteStoragePoolCommand deleteCmd = new DeleteStoragePoolCommand(pool);
+ final Answer answer = agentMgr.easySend(host.getHostId(), deleteCmd);
+
+ if (answer != null && answer.getResult()) {
+ // if host is KVM hypervisor then send deleteStoragepoolcmd to all the kvm hosts.
+ if (HypervisorType.KVM != hType) {
+ break;
+ }
+ } else {
+ if (answer != null) {
+ s_logger.error("Failed to delete storage pool: " + answer.getResult());
+ }
+ }
+ }
+
+ //delete the Elastistor volume at backend
+ deleteElastistorVolume(pool);
+
+ return _dataStoreHelper.deletePrimaryDataStore(store);
+ }
+
+ private void deleteElastistorVolume(StoragePool pool){
+
+ String poolip = pool.getHostAddress();
+ String esip = null;
+ String apikey = null;
+
+ // check if apikey and managentip is empty, if so getting it from stragepooldetails
+ if(ElastistorUtil.s_esIPVAL == "" && ElastistorUtil.s_esAPIKEYVAL == ""){
+ Map detailsMap = _storagePoolDetailsDao.listDetailsKeyPairs(pool.getId());
+ ElastistorUtil.setElastistorManagementIp(detailsMap.get("esmanagementip"));
+ esip=ElastistorUtil.s_esIPVAL;
+ ElastistorUtil.setElastistorApiKey(detailsMap.get("esapikey"));
+ apikey = ElastistorUtil.s_esAPIKEYVAL;
+ }else{
+ esip = ElastistorUtil.s_esIPVAL;
+ apikey = ElastistorUtil.s_esAPIKEYVAL;
+ }
+
+ boolean status;
+ try {
+ status = ElastistorUtil.deleteElastistorVolume(poolip,esip,apikey);
+ } catch (Throwable e) {
+ throw new CloudRuntimeException("Failed to delete primary storage on elastistor" + e);
+ }
+
+ if(status == true){
+ s_logger.info("deletion of elastistor primary storage complete");
+ }else{
+ s_logger.error("deletion of elastistor volume failed");
+ }
+
+ }
+
+ private HypervisorType getHypervisorType(long hostId) {
+ HostVO host = _hostDao.findById(hostId);
+ if (host != null)
+ return host.getHypervisorType();
+ return HypervisorType.None;
+ }
+
+ @Override
+ public boolean migrateToObjectStore(DataStore store) {
+ return false;
+ }
+
+
+}
diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorHostListener.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorHostListener.java
new file mode 100755
index 00000000000..23ea2ddfb72
--- /dev/null
+++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorHostListener.java
@@ -0,0 +1,69 @@
+package org.apache.cloudstack.storage.datastore.provider;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.ModifyStoragePoolAnswer;
+import com.cloud.agent.api.ModifyStoragePoolCommand;
+import com.cloud.alert.AlertManager;
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.StoragePoolHostVO;
+import com.cloud.storage.dao.StoragePoolHostDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+public class ElastistorHostListener implements HypervisorHostListener {
+ private static final Logger s_logger = Logger.getLogger(DefaultHostListener.class);
+ @Inject
+ AgentManager agentMgr;
+ @Inject
+ DataStoreManager dataStoreMgr;
+ @Inject
+ AlertManager alertMgr;
+ @Inject
+ StoragePoolHostDao storagePoolHostDao;
+ @Inject
+ PrimaryDataStoreDao primaryStoreDao;
+
+ @Override
+ public boolean hostConnect(long hostId, long poolId) {
+ StoragePool pool = (StoragePool) this.dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary);
+ ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(true, pool);
+ final Answer answer = agentMgr.easySend(hostId, cmd);
+
+ if (answer == null) {
+ throw new CloudRuntimeException("Unable to get an answer to the modify storage pool command" + pool.getId());
+ }
+
+ if (!answer.getResult()) {
+ String msg = "Unable to attach storage pool" + poolId + " to the host" + hostId;
+
+ alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST,pool.getDataCenterId(), pool.getPodId(), msg, msg);
+
+ throw new CloudRuntimeException("Unable establish connection from storage head to storage pool " + pool.getId() + " due to " + answer.getDetails() + pool.getId());
+ }
+
+ assert (answer instanceof ModifyStoragePoolAnswer) : "Well, now why won't you actually return the ModifyStoragePoolAnswer when it's ModifyStoragePoolCommand? Pool=" + pool.getId() + "Host=" + hostId;
+
+ s_logger.info("Connection established between " + pool + " host + " + hostId);
+ return true;
+ }
+
+ @Override
+ public boolean hostDisconnected(long hostId, long poolId) {
+ StoragePoolHostVO storagePoolHost = storagePoolHostDao.findByPoolHost(
+ poolId, hostId);
+
+ if (storagePoolHost != null) {
+ storagePoolHostDao.deleteStoragePoolHostDetails(hostId, poolId);
+ }
+ return false;
+ }
+
+}
diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorPrimaryDataStoreProvider.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorPrimaryDataStoreProvider.java
new file mode 100755
index 00000000000..e0a154a026a
--- /dev/null
+++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorPrimaryDataStoreProvider.java
@@ -0,0 +1,165 @@
+package org.apache.cloudstack.storage.datastore.provider;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.driver.ElastistorPrimaryDataStoreDriver;
+import org.apache.cloudstack.storage.datastore.lifecycle.ElastistorPrimaryDataStoreLifeCycle;
+import org.apache.cloudstack.storage.datastore.util.ElastistorUtil;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.alert.AlertManager;
+import com.cloud.storage.dao.StoragePoolHostDao;
+import com.cloud.utils.component.ComponentContext;
+
+/**
+ * This is the starting point of the elastistor storage plugin. This bean will
+ * be detected by Spring container & initialized. This will be one of the
+ * providers available via {@link DataStoreProviderManagerImpl} object.
+ *
+ * @author amit.das@cloudbyte.com
+ * @author punith.s@cloudbyte.com
+ */
+@Component
+public class ElastistorPrimaryDataStoreProvider implements PrimaryDataStoreProvider {
+
+ private static final Logger s_logger = Logger.getLogger(DefaultHostListener.class);
+
+ //these classes will be injected by spring
+ private ElastistorPrimaryDataStoreLifeCycle lifecycle;
+ private PrimaryDataStoreDriver driver;
+ private HypervisorHostListener listener;
+
+ // these params will be initialized with respective values given in spring-storage-volume-cloudbyte-context.xml bean for the elastistor porpose only.
+ private String esmanagementip;
+ private String esapikey;
+ private String esaccountid;
+ private String espoolid;
+ private String esdefaultgateway;
+ private String essubnet;
+ private String estntinterface;
+
+ @Inject
+ AgentManager agentMgr;
+ @Inject
+ DataStoreManager dataStoreMgr;
+ @Inject
+ AlertManager alertMgr;
+ @Inject
+ StoragePoolHostDao storagePoolHostDao;
+ @Inject
+ PrimaryDataStoreDao primaryStoreDao;
+
+
+ @Override
+ public String getName() {
+ return ElastistorUtil.ES_PROVIDER_NAME;
+ }
+
+ @Override
+ public DataStoreLifeCycle getDataStoreLifeCycle() {
+ return lifecycle;
+ }
+
+ @Override
+ public PrimaryDataStoreDriver getDataStoreDriver() {
+ return driver;
+ }
+
+ @Override
+ public HypervisorHostListener getHostListener() {
+ return listener;
+ }
+
+ @Override
+ public boolean configure(Map params) {
+
+ lifecycle = ComponentContext.inject(ElastistorPrimaryDataStoreLifeCycle.class);
+ driver = ComponentContext.inject(ElastistorPrimaryDataStoreDriver.class);
+ listener = ComponentContext.inject(ElastistorHostListener.class);
+
+ ElastistorUtil.setElastistorAccountId(esaccountid);
+ ElastistorUtil.setElastistorApiKey(esapikey);
+ ElastistorUtil.setElastistorManagementIp(esmanagementip);
+ ElastistorUtil.setElastistorPoolId(espoolid);
+ ElastistorUtil.setElastistorGateway(esdefaultgateway);
+ ElastistorUtil.setElastistorInterface(estntinterface);
+ ElastistorUtil.setElastistorSubnet(essubnet);
+
+ return true;
+ }
+
+ @Override
+ public Set getTypes() {
+ Set types = new HashSet();
+
+ types.add(DataStoreProviderType.PRIMARY);
+
+ return types;
+ }
+ public String getEspoolid() {
+ return espoolid;
+ }
+
+ public void setEspoolid(String espoolid) {
+ this.espoolid = espoolid;
+ }
+
+ public String getEsmanagementip() {
+ return esmanagementip;
+ }
+
+ public void setEsmanagementip(String esmanagementip) {
+ this.esmanagementip = esmanagementip;
+ }
+
+ public String getEsaccountid() {
+ return esaccountid;
+ }
+
+ public void setEsaccountid(String esaccountid) {
+ this.esaccountid = esaccountid;
+ }
+
+ public String getEsapikey() {
+ return esapikey;
+ }
+
+ public void setEsapikey(String esapikey) {
+ this.esapikey = esapikey;
+ }
+
+ public String getesdefaultgateway() {
+ return esdefaultgateway;
+ }
+
+ public void setesdefaultgateway(String esdefaultgateway) {
+ this.esdefaultgateway = esdefaultgateway;
+ }
+ public String getEssubnet() {
+ return essubnet;
+ }
+
+ public void setEssubnet(String essubnet) {
+ this.essubnet = essubnet;
+ }
+
+ public String getEstntinterface(){
+ return estntinterface;
+ }
+
+ public void setEstntinterface(String estntinterface){
+ this.estntinterface = estntinterface;
+ }
+}
diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java
new file mode 100755
index 00000000000..09b2a309b56
--- /dev/null
+++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java
@@ -0,0 +1,1144 @@
+package org.apache.cloudstack.storage.datastore.util;
+
+import java.net.ConnectException;
+import java.security.InvalidParameterException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+
+import javax.naming.ServiceUnavailableException;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriBuilder;
+
+import org.apache.http.auth.InvalidCredentialsException;
+import org.apache.log4j.Logger;
+
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.google.gson.Gson;
+import com.google.gson.annotations.SerializedName;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
+/**
+ * The util class for elastistor's storage plugin codebase.
+ *
+ * @author amit.das@cloudbyte.com
+ * @author punith.s@cloudbyte.com
+ *
+ */
+public class ElastistorUtil {
+
+ private static final Logger s_logger = Logger.getLogger(ElastistorUtil.class);
+
+
+ /**
+ * Elastistor REST API Param Keys. These should match exactly with the
+ * elastistor API commands' params.
+ */
+ public static final String REST_PARAM_COMMAND = "command";
+ public static final String REST_PARAM_APIKEY = "apikey";
+ public static final String REST_PARAM_KEYWORD = "keyword";
+ public static final String REST_PARAM_ID = "id";
+ public static final String REST_PARAM_QUOTA_SIZE = "quotasize";
+ public static final String REST_PARAM_READONLY = "readonly";
+ public static final String REST_PARAM_RESPONSE = "response";
+ public static final String REST_PARAM_POOLID = "poolid";
+ public static final String REST_PARAM_ACCOUNTID = "accountid";
+ public static final String REST_PARAM_GATEWAY = "router";
+ public static final String REST_PARAM_SUBNET = "subnet";
+ public static final String REST_PARAM_INTERFACE = "tntinterface";
+ public static final String REST_PARAM_IPADDRESS = "ipaddress";
+ public static final String REST_PARAM_JOBID = "jobId";
+ public static final String REST_PARAM_FORECEDELETE = "forcedelete";
+ public static final String REST_PARAM_TSM_THROUGHPUT = "totalthroughput";
+ public static final String REST_PARAM_NAME = "name";
+ public static final String REST_PARAM_NOOFCOPIES = "noofcopies";
+ public static final String REST_PARAM_RECORDSIZE = "recordsize";
+ public static final String REST_PARAM_TOTALIOPS = "totaliops";
+ public static final String REST_PARAM_LATENCY = "latency";
+ public static final String REST_PARAM_BLOCKSIZE = "blocksize";
+ public static final String REST_PARAM_GRACEALLOWED = "graceallowed";
+ public static final String REST_PARAM_IOPS = "iops";
+ public static final String REST_PARAM_THROUGHPUT = "throughput";
+ public static final String REST_PARAM_MEMLIMIT= "memlimit";
+ public static final String REST_PARAM_NETWORKSPEED = "networkspeed";
+ public static final String REST_PARAM_TSMID = "tsmid";
+ public static final String REST_PARAM_DATASETID = "datasetid";
+ public static final String REST_PARAM_QOSGROUPID = "qosgroupid";
+ public static final String REST_PARAM_DEDUPLICATION = "deduplication";
+ public static final String REST_PARAM_COMPRESSION = "compression";
+ public static final String REST_PARAM_SYNC = "sync";
+ public static final String REST_PARAM_MOUNTPOINT= "mountpoint";
+ public static final String REST_PARAM_CASESENSITIVITY = "casesensitivity";
+ public static final String REST_PARAM_UNICODE = "unicode";
+ public static final String REST_PARAM_PROTOCOLTYPE= "protocoltype";
+ public static final String REST_PARAM_AUTHNETWORK = "authnetwork";
+ public static final String REST_PARAM_MAPUSERSTOROOT = "mapuserstoroot";
+
+ /**
+ * Constants related to elastistor which are persisted in cloudstack
+ * databases as keys.
+ */
+ public static final String ES_SUBNET = "essubnet";
+ public static final String ES_INTERFACE = "estntinterface";
+ public static final String ES_GATEWAY = "esdefaultgateway";
+ public static final String ES_PROVIDER_NAME = "elastistor";
+ public static final String ES_ACCOUNT_ID = "esAccountId";
+ public static final String ES_POOL_ID = "esPoolId";
+ public static final String ES_ACCOUNT_NAME = "esAccountName";
+ public static final String ES_STORAGE_IP = "esStorageIp";
+ public static final String ES_STORAGE_PORT = "esStoragePort";
+ public static final String ES_STORAGE_TYPE = "esStorageType";
+ public static final String ES_MANAGEMENT_IP = "esMgmtIp";
+ public static final String ES_MANAGEMENT_PORT = "esMgmtPort";
+ public static final String ES_API_KEY = "esApiKey";
+ public static final String ES_VOLUME_ID = "esVolumeId";
+ public static final String ES_VOLUME_GROUP_ID = "esVolumeGroupId";
+ public static final String ES_FILE_SYSTEM_ID = "esFilesystemId";
+
+ /**
+ * Values from configuration that are required for every invocation of
+ * ElastiCenter API. These might in turn be saved as DB updates along with
+ * above keys.
+ */
+ public static String s_esIPVAL = "";
+ public static String s_esAPIKEYVAL = "";
+ public static String s_esACCOUNTIDVAL = "";
+ public static String s_esPOOLIDVAL = "";
+ public static String s_esSUBNETVAL = "";
+ public static String s_esINTERFACEVAL = "";
+ public static String s_esGATEWAYVAL = "";
+
+ /**
+ * hardcoded constants for elastistor api calls.
+ */
+ private static final String ES_NOOFCOPIES_VAL = "1";
+ private static final String ES_BLOCKSIZE_VAL = "4K";
+ private static final String ES_LATENCY_VAL = "15";
+ private static final String ES_GRACEALLOWED_VAL = "false";
+ private static final String ES_MEMLIMIT_VAL = "0";
+ private static final String ES_NETWORKSPEED_VAL = "0";
+ private static final String ES_DEDUPLICATION_VAL = "off";
+ private static final String ES_COMPRESSION_VAL = "off";
+ private static final String ES_CASESENSITIVITY_VAL = "sensitive";
+ private static final String ES_READONLY_VAL = "off";
+ private static final String ES_UNICODE_VAL = "off";
+ private static final String ES_AUTHNETWORK_VAL = "all";
+ private static final String ES_MAPUSERSTOROOT_VAL = "yes";
+ private static final String ES_SYNC_VAL = "always";
+
+
+ /**
+ * Private constructor s.t. its never instantiated.
+ */
+ private ElastistorUtil() {
+
+ }
+
+ /**
+ * This intializes a new jersey restclient for http call with elasticenter
+ */
+ public static ElastiCenterClient getElastistorRestClient(String managementIp , String apiKey) {
+ ElastiCenterClient restclient = null;
+ try {
+
+ restclient = new ElastiCenterClient(managementIp, apiKey);
+
+ } catch (InvalidCredentialsException e) {
+ throw new CloudRuntimeException("InvalidCredentialsException", e);
+ } catch (InvalidParameterException e) {
+ throw new CloudRuntimeException("InvalidParameterException", e);
+ } catch (SSLHandshakeException e) {
+ throw new CloudRuntimeException("SSLHandshakeException", e);
+ } catch (ServiceUnavailableException e) {
+ throw new CloudRuntimeException("ServiceUnavailableException", e);
+ }
+ return restclient;
+ }
+
+ public static void setElastistorApiKey(String value) {
+ s_esAPIKEYVAL = value;
+ }
+
+ public static void setElastistorManagementIp(String value) {
+ s_esIPVAL = value;
+ }
+
+ public static void setElastistorPoolId(String value) {
+ s_esPOOLIDVAL = value;
+ }
+
+ public static void setElastistorAccountId(String value) {
+ s_esACCOUNTIDVAL = value;
+ }
+
+ public static void setElastistorGateway(String value) {
+ s_esGATEWAYVAL = value;
+ }
+
+ public static void setElastistorInterface(String value) {
+ s_esINTERFACEVAL = value;
+ }
+
+ public static void setElastistorSubnet(String value) {
+ s_esSUBNETVAL = value;
+ }
+
+ /**
+ * This creates a new tenant storage machine(TSM) for the given storagepool ip in elastistor.
+ */
+ public static CreateTsmCmdResponse createElastistorTsm(String storagePoolName, String storageIp, Long capacityBytes, Long capacityIops) throws Throwable {
+
+ String totalthroughput = String.valueOf(capacityIops*4);
+ String totaliops = String.valueOf(capacityIops);
+
+ String quotasize = convertCapacityBytes(capacityBytes);
+
+ CreateTsmCmd createTsmCmd = new CreateTsmCmd();
+
+ if ( null != ElastistorUtil.s_esACCOUNTIDVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ACCOUNTID, ElastistorUtil.s_esACCOUNTIDVAL);
+ if ( null != totalthroughput ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TSM_THROUGHPUT, totalthroughput);
+ if ( null != ElastistorUtil.s_esPOOLIDVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_POOLID, ElastistorUtil.s_esPOOLIDVAL);
+ if ( null != storagePoolName ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NAME, "TSM"+storagePoolName);
+ if ( null != quotasize ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_QUOTA_SIZE, quotasize);
+ if ( null != storageIp ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_IPADDRESS, storageIp);
+ if ( null != ElastistorUtil.s_esSUBNETVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_SUBNET, ElastistorUtil.s_esSUBNETVAL);
+ if ( null != ElastistorUtil.s_esGATEWAYVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_GATEWAY, ElastistorUtil.s_esGATEWAYVAL);
+ if ( null != ElastistorUtil.s_esINTERFACEVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_INTERFACE, ElastistorUtil.s_esINTERFACEVAL);
+ if ( null != ElastistorUtil.ES_NOOFCOPIES_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NOOFCOPIES, ElastistorUtil.ES_NOOFCOPIES_VAL);
+ if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_RECORDSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL);
+ if ( null != totaliops ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TOTALIOPS, totaliops);
+ if ( null != ElastistorUtil.ES_LATENCY_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_LATENCY, ElastistorUtil.ES_LATENCY_VAL);
+ if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL);
+ if ( null != ElastistorUtil.ES_GRACEALLOWED_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_GRACEALLOWED, ElastistorUtil.ES_GRACEALLOWED_VAL);
+
+ CreateTsmCmdResponse cmdResponse;
+
+ try {
+ cmdResponse = (CreateTsmCmdResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(createTsmCmd);
+
+ if ( cmdResponse.getTsm().getUuid() == null ){
+ throw new CloudRuntimeException("tsm creation failed , contact elatistor admin");
+ }
+ return cmdResponse;
+ } catch (Exception e) {
+ throw new CloudRuntimeException("tsm creation failed , contact elatistor admin" + e.toString());
+ }
+
+ }
+
+ /**
+ * This creates the specified volume on the created tsm.
+ */
+ public static CreateVolumeCmdResponse createElastistorVolume(String storagePoolName, CreateTsmCmdResponse cmdResponse, Long capacityBytes, Long capacityIops,String protocoltype, String mountpoint) throws Throwable {
+
+ String datasetid;
+ String tsmid;
+ String qosgroupid;
+ String VolumeName = storagePoolName;
+ String totaliops = String.valueOf(capacityIops);
+ String totalthroughput = String.valueOf(capacityIops*4);
+
+ String quotasize = convertCapacityBytes(capacityBytes);
+
+ AddQosGroupCmd addQosGroupCmd = new AddQosGroupCmd();
+
+
+ tsmid = cmdResponse.getTsm().getUuid();
+ datasetid = cmdResponse.getTsm().getDatasetid();
+
+ if (null != VolumeName)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NAME, "QOS_" + VolumeName);
+ if (null != totaliops)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_IOPS, totaliops);
+ if (null != ElastistorUtil.ES_LATENCY_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_LATENCY, ElastistorUtil.ES_LATENCY_VAL);
+ if (null != ElastistorUtil.ES_BLOCKSIZE_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL);
+ if (null != totalthroughput)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_THROUGHPUT, totalthroughput);
+ if (null != ElastistorUtil.ES_MEMLIMIT_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_MEMLIMIT, ElastistorUtil.ES_MEMLIMIT_VAL);
+ if (null != ElastistorUtil.ES_NETWORKSPEED_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NETWORKSPEED, ElastistorUtil.ES_NETWORKSPEED_VAL);
+ if (null != tsmid)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TSMID, tsmid);
+ if (null != datasetid)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_DATASETID, datasetid);
+ if (null != ElastistorUtil.ES_GRACEALLOWED_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_GRACEALLOWED, ElastistorUtil.ES_GRACEALLOWED_VAL);
+
+ AddQosGroupCmdResponse addQosGroupCmdResponse = (AddQosGroupCmdResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(addQosGroupCmd);
+
+ if (addQosGroupCmdResponse.getQoSGroup().getUuid() == null) {
+
+ throw new CloudRuntimeException("adding qos group failed , contact elatistor admin");
+
+ }
+
+ else {
+
+ CreateVolumeCmd createVolumeCmd = new CreateVolumeCmd();
+
+ qosgroupid = addQosGroupCmdResponse.getQoSGroup().getUuid();
+
+ if (null != ElastistorUtil.s_esACCOUNTIDVAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ACCOUNTID,ElastistorUtil.s_esACCOUNTIDVAL);
+ if (null != qosgroupid)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_QOSGROUPID, qosgroupid);
+ if (null != tsmid)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TSMID, tsmid);
+ if (null != ElastistorUtil.s_esPOOLIDVAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_POOLID,ElastistorUtil.s_esPOOLIDVAL);
+ if (null != VolumeName)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NAME, VolumeName);
+ if (null != quotasize)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_QUOTA_SIZE, quotasize);
+ if(protocoltype.equalsIgnoreCase("nfs")){
+ if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL);
+ if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_RECORDSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL);
+ }
+ else{
+ if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, "512B");
+ if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_RECORDSIZE, "512B");
+ }
+ if (null != ElastistorUtil.ES_DEDUPLICATION_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_DEDUPLICATION, ElastistorUtil.ES_DEDUPLICATION_VAL);
+ if (null != ElastistorUtil.ES_SYNC_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_SYNC, ElastistorUtil.ES_SYNC_VAL);
+ if (null != ElastistorUtil.ES_COMPRESSION_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_COMPRESSION, ElastistorUtil.ES_COMPRESSION_VAL);
+ if (null != ElastistorUtil.ES_NOOFCOPIES_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NOOFCOPIES, ElastistorUtil.ES_NOOFCOPIES_VAL);
+ createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_MOUNTPOINT, mountpoint);
+ if (null != ElastistorUtil.ES_CASESENSITIVITY_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_CASESENSITIVITY, ElastistorUtil.ES_CASESENSITIVITY_VAL);
+ if (null != ElastistorUtil.ES_READONLY_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_READONLY, ElastistorUtil.ES_READONLY_VAL);
+ if (null != datasetid)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_DATASETID, datasetid);
+ if (null != ElastistorUtil.ES_UNICODE_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_UNICODE, ElastistorUtil.ES_UNICODE_VAL);
+ createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_PROTOCOLTYPE, protocoltype);
+ if (null != ElastistorUtil.ES_AUTHNETWORK_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_AUTHNETWORK, ElastistorUtil.ES_AUTHNETWORK_VAL);
+ if (null != ElastistorUtil.ES_MAPUSERSTOROOT_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_MAPUSERSTOROOT, ElastistorUtil.ES_MAPUSERSTOROOT_VAL);
+
+ CreateVolumeCmdResponse createVolumeCmdResponse;
+ try {
+ createVolumeCmdResponse = (CreateVolumeCmdResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(createVolumeCmd);
+
+ if (createVolumeCmdResponse.getFileSystem().getUuid() == null) {
+
+ throw new CloudRuntimeException("creating volume failed , contact elatistor admin");
+
+ } else {
+ return createVolumeCmdResponse;
+ }
+
+ } catch (Exception e) {
+ throw new CloudRuntimeException("creating volume failed , contact elatistor admin", e);
+ }
+
+ }
+
+ }
+
+ /**
+ * This deletes both the volume and the tsm in elastistor.
+ */
+ public static boolean deleteElastistorVolume(String poolip, String esmanagementip, String esapikey) throws Throwable {
+
+ String esvolumeid = null;
+ String estsmid = null;
+
+ ListTsmsResponse listTsmsResponse = listTsm(poolip);
+
+ if (listTsmsResponse.getTsmsCount() != 0) {
+ int i;
+
+ for (i = 0; i < listTsmsResponse.getTsmsCount(); i++) {
+ if (poolip.compareTo(listTsmsResponse.getTsms().getTsm(i).getIpaddress()) == 0) {
+ estsmid = listTsmsResponse.getTsms().getTsm(i).getUuid();
+ break;
+ }
+ }
+
+ if (listTsmsResponse.getTsms().getTsm(i).checkvolume()) {
+ esvolumeid = listTsmsResponse.getTsms().getTsm(i).getVolumeProperties(0).getid();
+ DeleteVolumeResponse deleteVolumeResponse = deleteVolume(esvolumeid, null);
+
+ if (deleteVolumeResponse != null) {
+ String jobid = deleteVolumeResponse.getJobId();
+ int jobstatus = queryAsyncJobResult(jobid);
+
+ if (jobstatus == 1) {
+ s_logger.info("elastistor volume successfully deleted");
+ } else {
+ s_logger.info("now farce deleting the volume");
+
+ while (jobstatus != 1) {
+ DeleteVolumeResponse deleteVolumeResponse1 = deleteVolume(esvolumeid, "true");
+
+ if (deleteVolumeResponse1 != null) {
+ String jobid1 = deleteVolumeResponse1.getJobId();
+ jobstatus = queryAsyncJobResult(jobid1);
+ }
+ }
+ s_logger.info("elastistor volume successfully deleted");
+ }
+ }
+ } else {
+ s_logger.info("no volume present in on the given tsm");
+ }
+ s_logger.info("now trying to delete elastistor tsm");
+
+ if (estsmid != null) {
+ DeleteTsmCmd deleteTsmCmd = new DeleteTsmCmd();
+ deleteTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ID,estsmid);
+ DeleteTsmResponse deleteTsmResponse = (DeleteTsmResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(deleteTsmCmd);
+
+ if (deleteTsmResponse != null) {
+ String jobstatus = deleteTsmResponse.getJobStatus();
+
+ if (jobstatus.equalsIgnoreCase("true")) {
+ s_logger.info("deletion of elastistor tsm successful");
+ return true;
+ } else {
+ s_logger.info("failed to delete elastistor tsm");
+ return false;
+ }
+ } else {
+ s_logger.info("elastistor tsm id not present");
+ }
+ }
+ else {
+ s_logger.error("no volume is present in the tsm");
+ }
+ } else {
+ s_logger.error("List tsm failed, no tsm present in the eastistor for the given IP ");
+ return false;
+ }
+ return false;
+
+ }
+
+ /**
+ * This give a json response containing the list of tsm's in elastistor.
+ */
+ private static ListTsmsResponse listTsm(String poolip) throws Throwable {
+
+ ListTsmCmd listTsmCmd = new ListTsmCmd();
+
+ listTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_IPADDRESS,poolip);
+
+ ListTsmsResponse listTsmsResponse = (ListTsmsResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(listTsmCmd);
+
+ return listTsmsResponse;
+ }
+
+ private static DeleteVolumeResponse deleteVolume(String esvolumeid, String forcedelete)throws Throwable {
+
+ DeleteVolumeCmd deleteVolumeCmd = new DeleteVolumeCmd();
+
+ deleteVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ID,esvolumeid);
+ deleteVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_FORECEDELETE, forcedelete);
+
+ DeleteVolumeResponse deleteVolumeResponse = (DeleteVolumeResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(deleteVolumeCmd);
+
+ return deleteVolumeResponse;
+ }
+
+ private static int queryAsyncJobResult(String jobid) throws Throwable {
+
+ QueryAsyncJobResultCmd asyncJobResultCmd = new QueryAsyncJobResultCmd();
+ ElastiCenterClient restclient = getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL);
+
+ asyncJobResultCmd.putCommandParameter(ElastistorUtil.REST_PARAM_JOBID, jobid);
+
+ QueryAsyncJobResultResponse asyncJobResultResponse = (QueryAsyncJobResultResponse) restclient.executeCommand(asyncJobResultCmd);
+
+ if (asyncJobResultResponse != null) {
+ int jobstatus = asyncJobResultResponse.getAsync().getJobStatus();
+
+ while (jobstatus == 0) {
+
+ QueryAsyncJobResultResponse jobResultResponse = (QueryAsyncJobResultResponse) restclient.executeCommand(asyncJobResultCmd);
+
+ jobstatus = jobResultResponse.getAsync().getJobStatus();
+ }
+ return jobstatus;
+ }
+ return 0;
+
+ }
+
+ /**
+ * this method converts the long capacitybytes to string format, which is feasible for elastistor rest api
+ * 214748364800 = 200G.
+ */
+ private static String convertCapacityBytes(Long capacityBytes){
+
+ String quotasize;
+
+ if((1099511627776L)>capacityBytes &&(capacityBytes>(1073741824))){
+ return quotasize =(String.valueOf(capacityBytes/(1024*1024*1024))+"G");
+ }else
+ { int temp1 = (int) (capacityBytes/(1024*1024*1024));
+ int temp2 = temp1/1024;
+ return quotasize =(String.valueOf(temp2)+"T");
+ }
+ }
+
+ static interface ElastiCenterCommand {
+
+ /*
+ * Returns the command string to be sent to the ElastiCenter
+ */
+ public String getCommandName();
+
+ /*
+ * Utility method to allow the client to validate the input parameters
+ * before sending to the ElastiCenter.
+ *
+ * This command will be executed by the ElastiCenterClient only this method
+ * returns true.
+ */
+ public boolean validate();
+
+ /*
+ * Returns the query parameters that have to be passed to execute the
+ * command.
+ *
+ * Returns null if there are query parameters associated with the command
+ */
+ public MultivaluedMap getCommandParameters();
+
+ /*
+ * Adds new key-value pair to the query paramters lists.
+ */
+ public void putCommandParameter(String key, String value);
+
+ /*
+ * Return an instance of the Response Object Type.
+ *
+ * Return null if no response is expected.
+ */
+ public Object getResponseObject();
+ }
+
+ private static class BaseCommand implements ElastiCenterCommand {
+
+ private String commandName = null;
+ private MultivaluedMap commandParameters = null;
+ private Object responseObject = null;
+
+ /*
+ * Enforce the Commands to be initialized with command name and optional
+ * response object
+ */
+ protected BaseCommand(String cmdName, Object responseObj) {
+ commandName = cmdName;
+ responseObject = responseObj;
+ }
+
+ @Override
+ public String getCommandName() {
+ return commandName;
+ }
+
+ @Override
+ public boolean validate() {
+ // TODO This method can be extended to do some generic
+ // validations.
+ return true;
+ }
+
+ @Override
+ public MultivaluedMap getCommandParameters() {
+ return commandParameters;
+ }
+
+ @Override
+ public void putCommandParameter(String key, String value) {
+ if (null == commandParameters) {
+ commandParameters = new MultivaluedMapImpl();
+ }
+ commandParameters.add(key, value);
+ }
+
+ @Override
+ public Object getResponseObject() {
+ return responseObject;
+ }
+
+ }
+
+/**
+ * this is a rest client which is used to call the http rest calls to elastistor
+ * @author punith
+ *
+ */
+ private static final class ElastiCenterClient {
+
+ public static boolean debug = false;
+
+ private boolean initialized = false;
+
+ private String apiKey = null;
+ private String elastiCenterAddress = null;
+ private String responseType = "json";
+ private boolean ignoreSSLCertificate = false;
+
+ private String restprotocol = "https://";
+ private String restpath = "/client/api";
+ private String restdefaultcommand = "listCapabilities";
+
+ private String queryparamcommand = "command";
+ private String queryparamapikey = "apikey";
+ private String queryparamresponse = "response";
+
+ public ElastiCenterClient(String address, String key)throws InvalidCredentialsException, InvalidParameterException,SSLHandshakeException, ServiceUnavailableException {
+ this.elastiCenterAddress = address;
+ this.apiKey = key;
+ this.initialize();
+ }
+
+ public void initialize() throws InvalidParameterException,
+ SSLHandshakeException, InvalidCredentialsException,
+ ServiceUnavailableException {
+
+ if (apiKey == null || apiKey.trim().isEmpty()) {
+ throw new InvalidParameterException("Unable to initialize. Please specify a valid API Key.");
+ }
+
+ if (elastiCenterAddress == null || elastiCenterAddress.trim().isEmpty()) {
+ // TODO : Validate the format, like valid IP address or hostname.
+ throw new InvalidParameterException("Unable to initialize. Please specify a valid ElastiCenter IP Address or Hostname.");
+ }
+
+ if (ignoreSSLCertificate) {
+ // Create a trust manager that does not validate certificate chains
+ TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ public void checkClientTrusted(X509Certificate[] certs,
+ String authType) {
+ }
+
+ public void checkServerTrusted(X509Certificate[] certs,
+ String authType) {
+ }
+ } };
+
+ HostnameVerifier hv = new HostnameVerifier() {
+ @Override
+ public boolean verify(String urlHostName, SSLSession session) {
+ return true;
+ }
+ };
+
+ // Install the all-trusting trust manager
+ try {
+ SSLContext sc = SSLContext.getInstance("TLS");
+ sc.init(null, trustAllCerts, new SecureRandom());
+ HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+ HttpsURLConnection.setDefaultHostnameVerifier(hv);
+ } catch (Exception e) {
+ ;
+ }
+ }
+
+ ListCapabilitiesResponse listCapabilitiesResponse = null;
+ try {
+ initialized = true;
+ listCapabilitiesResponse = (ListCapabilitiesResponse) executeCommand(restdefaultcommand, null, new ListCapabilitiesResponse());
+
+ } catch (Throwable t) {
+ initialized = false;
+ if (t instanceof InvalidCredentialsException) {
+ throw (InvalidCredentialsException) t;
+ } else if (t instanceof ServiceUnavailableException) {
+ throw (ServiceUnavailableException) t;
+ } else if (t.getCause() instanceof SSLHandshakeException) {
+ throw new SSLHandshakeException(
+ "Unable to initialize. An untrusted SSL Certificate was received from "
+ + elastiCenterAddress
+ + ". Please verify your truststore or configure ElastiCenterClient to skip the SSL Validation. ");
+ } else if (t.getCause() instanceof ConnectException) {
+ throw new ServiceUnavailableException(
+ "Unable to initialize. Failed to connect to "
+ + elastiCenterAddress
+ + ". Please verify the IP Address, Network Connectivity and ensure that Services are running on the ElastiCenter Server. ");
+ }
+ throw new ServiceUnavailableException("Unable to initialize. Please contact your ElastiCenter Administrator. Exception " + t.getMessage());
+ }
+
+ if (null == listCapabilitiesResponse || null == listCapabilitiesResponse.getCapabilities() || null == listCapabilitiesResponse.getCapabilities().getVersion()) {
+ initialized = false;
+ throw new ServiceUnavailableException("Unable to execute command on the server");
+ }
+
+ }
+
+ public Object executeCommand(ElastiCenterCommand cmd) throws Throwable {
+ return executeCommand(cmd.getCommandName(), cmd.getCommandParameters(),cmd.getResponseObject());
+ }
+
+ public Object executeCommand(String command,MultivaluedMap params, Object responeObj) throws Throwable {
+
+ if (!initialized) {
+ throw new IllegalStateException("Error : ElastiCenterClient is not initialized.");
+ }
+
+ if (command == null || command.trim().isEmpty()) {
+ throw new InvalidParameterException("No command to execute.");
+ }
+
+ try {
+ ClientConfig config = new DefaultClientConfig();
+ Client client = Client.create(config);
+ WebResource webResource = client.resource(UriBuilder.fromUri(restprotocol + elastiCenterAddress + restpath).build());
+
+ MultivaluedMap queryParams = new MultivaluedMapImpl();
+ queryParams.add(queryparamapikey, apiKey);
+ queryParams.add(queryparamresponse, responseType);
+
+ queryParams.add(queryparamcommand, command);
+
+ if (null != params) {
+ for (String key : params.keySet()) {
+ queryParams.add(key, params.getFirst(key));
+ }
+ }
+ if (debug) {
+ System.out.println("Command Sent " + command + " : "+ queryParams);
+ }
+ ClientResponse response = webResource.queryParams(queryParams).accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+
+ if (response.getStatus() >= 300) {
+ if (debug)
+ System.out.println("ElastiCenter returned error code : " + response.getStatus());
+ if (401 == response.getStatus()) {
+ throw new InvalidCredentialsException("Please specify a valid API Key.");
+ } else if (431 == response.getStatus()) {
+ throw new InvalidParameterException(response.getHeaders().getFirst("X-Description"));
+ } else if (432 == response.getStatus()) {
+ throw new InvalidParameterException(command + " does not exist on the ElastiCenter server. Please specify a valid command or contact your ElastiCenter Administrator.");
+ } else {
+ throw new ServiceUnavailableException("Internal Error. Please contact your ElastiCenter Administrator.");
+ }
+ } else if (null != responeObj) {
+ String jsonResponse = response.getEntity(String.class);
+ if (debug) {
+ System.out.println("Command Response : " + jsonResponse);
+ }
+ Gson gson = new Gson();
+ return gson.fromJson(jsonResponse, responeObj.getClass());
+ } else {
+ return "Success";
+ }
+ } catch (Throwable t) {
+ throw t;
+ }
+ }
+ }
+
+ /**
+ * these are the list of Elastistor rest commands being called from the plugin.
+ *
+ */
+ private static final class CreateTsmCmd extends BaseCommand {
+
+ public CreateTsmCmd() {
+ super("createTsm", new CreateTsmCmdResponse());
+
+ }
+
+ }
+
+ private static final class AddQosGroupCmd extends BaseCommand {
+
+ public AddQosGroupCmd() {
+
+ super("addQosGroup", new AddQosGroupCmdResponse());
+
+ }
+
+ }
+
+ private static final class CreateVolumeCmd extends BaseCommand {
+
+ public CreateVolumeCmd() {
+ super("createVolume", new CreateVolumeCmdResponse());
+
+ }
+
+ }
+
+ private static final class DeleteTsmCmd extends BaseCommand {
+
+ public DeleteTsmCmd() {
+ super("deleteTsm", new DeleteTsmResponse());
+ }
+
+ }
+
+ private static final class DeleteVolumeCmd extends BaseCommand {
+
+ public DeleteVolumeCmd() {
+ super("deleteFileSystem", new DeleteVolumeResponse());
+ }
+
+ }
+
+ private static final class QueryAsyncJobResultCmd extends BaseCommand {
+
+ public QueryAsyncJobResultCmd() {
+ super("queryAsyncJobResult", new QueryAsyncJobResultResponse());
+ }
+
+ }
+
+ private static final class ListTsmCmd extends BaseCommand {
+
+ public ListTsmCmd() {
+ super("listTsm", new ListTsmsResponse());
+ }
+
+ }
+
+ /**
+ * these are the list of Elastistor rest json response classes for parsing the json response sent by elastistor.
+ *
+ */
+ public static final class CreateTsmCmdResponse {
+
+ @SerializedName("createTsmResponse")
+ private TsmWrapper tsmWrapper;
+
+ public Tsm getTsm() {
+ return tsmWrapper.getTsm();
+ }
+
+ }
+
+ public static final class Tsm {
+
+ @SerializedName("id")
+ private String uuid;
+
+ @SerializedName("name")
+ private String name;
+
+ @SerializedName("datasetid")
+ private String datasetid;
+
+ @SerializedName("ipaddress")
+ private String ipaddress;
+
+ @SerializedName("volumes")
+ private VolumeProperties[] volumeProperties;
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getIpaddress() {
+ return ipaddress;
+ }
+
+ public String getDatasetid() {
+ return datasetid;
+ }
+
+ public boolean checkvolume() {
+
+ if(volumeProperties != null){
+ return true;
+ }
+ else{
+ return false;
+ }
+
+ }
+
+ public VolumeProperties getVolumeProperties(int i) {
+ return volumeProperties[i];
+ }
+
+ }
+
+ public static final class VolumeProperties {
+
+ @SerializedName("id")
+ private String id;
+
+ @SerializedName("groupid")
+ private String groupid;
+
+ @SerializedName("iops")
+ private String iops;
+
+ @SerializedName("name")
+ private String name;
+
+ public String getid() {
+ return id;
+ }
+
+ public String getQosgroupid() {
+ return groupid;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getIops() {
+ return iops;
+ }
+ }
+
+ public static final class TsmWrapper {
+
+ @SerializedName("tsm")
+ private Tsm tsm;
+
+ public Tsm getTsm() {
+ return tsm;
+ }
+
+ }
+
+ public static final class AddQosGroupCmdResponse {
+
+ @SerializedName("addqosgroupresponse")
+ private QoSGroupWrapper qosGroupWrapper;
+
+ public QoSGroup getQoSGroup() {
+ return qosGroupWrapper.getQosGroup();
+ }
+ }
+
+ public static final class QoSGroupWrapper {
+
+ @SerializedName("qosgroup")
+ private QoSGroup qoSGroup;
+
+ public QoSGroup getQosGroup() {
+
+ return qoSGroup;
+ }
+
+ }
+
+ public static final class QoSGroup {
+
+ @SerializedName("id")
+ private String uuid;
+
+ @SerializedName("name")
+ private String name;
+
+ @SerializedName("qosgroupproperties")
+ private HashMap qosGroupProperties;
+
+ public String getName() {
+ return name;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public String getIops() {
+ return qosGroupProperties.get("iops");
+ }
+
+ public String getThroughput() {
+ return qosGroupProperties.get("throughput");
+ }
+
+ public String getLatency() {
+ return qosGroupProperties.get("latency");
+ }
+ }
+
+ public static final class CreateVolumeCmdResponse {
+
+ @SerializedName("adddatasetresponse")
+ private FileSystemWrapper fileSystemWrapper;
+
+ public FileSystem getFileSystem() {
+
+ return fileSystemWrapper.getFileSystem();
+ }
+
+ }
+
+ public static final class FileSystemWrapper {
+
+ @SerializedName("filesystem")
+ private FileSystem fileSystem;
+
+ public FileSystem getFileSystem() {
+ return fileSystem;
+ }
+
+ }
+
+ public static final class FileSystem {
+
+ @SerializedName("id")
+ private String uuid;
+
+ @SerializedName("name")
+ private String name;
+
+ @SerializedName("quota")
+ private String quota;
+
+ @SerializedName("timestamp")
+ private String timestamp;
+
+ @SerializedName("iqnname")
+ private String iqnname;
+
+ @SerializedName("filesystemproperties")
+ private HashMap[] filesystemproperties;
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getIqn() {
+ return iqnname;
+ }
+
+ public String getQuota() {
+ return quota;
+ }
+
+ public String getTimestamp() {
+ return timestamp;
+ }
+
+ }
+
+ public static final class DeleteTsmResponse {
+
+ @SerializedName("deleteTsmResponse")
+ private JobId jobId;
+
+ public String getJobStatus() {
+ return jobId.getJobStatus();
+ }
+
+ }
+
+ public static final class JobId {
+
+ @SerializedName("jobid")
+ private String jobid;
+
+ @SerializedName("success")
+ private String jobStatus;
+
+ public String getJobid() {
+ return jobid;
+ }
+
+ public String getJobStatus() {
+ return jobStatus;
+ }
+
+ }
+
+ public static final class DeleteVolumeResponse {
+
+ @SerializedName("deleteFileSystemResponse")
+ private JobId jobId;
+
+ public String getJobId() {
+ return jobId.getJobid();
+ }
+
+ }
+
+ public static final class ListCapabilitiesResponse {
+
+ @SerializedName("listcapabilitiesresponse")
+ private Capabilities capabilities;
+
+ public Capabilities getCapabilities() {
+ return capabilities;
+ }
+ }
+
+ public static final class ListTsmsResponse {
+
+ @SerializedName("listTsmResponse")
+ private Tsms tsms;
+
+ public int getTsmsCount() {
+ return tsms.getCount();
+ }
+
+ public Tsms getTsms() {
+ return tsms;
+ }
+ }
+
+ public static final class Tsms {
+
+ @SerializedName("count")
+ private int count;
+
+ @SerializedName("listTsm")
+ private Tsm[] tsms;
+
+ public int getCount() {
+ return count;
+ }
+
+ public Tsm getTsm(int i) {
+ return tsms[i];
+ }
+ }
+
+ public static final class QueryAsyncJobResultResponse {
+
+ @SerializedName("queryasyncjobresultresponse")
+ private Async async;
+
+ public Async getAsync() {
+ return async;
+ }
+ }
+
+ public static final class Async {
+
+ @SerializedName("jobstatus")
+ private int jobstatus;
+
+ @SerializedName("cmd")
+ private String cmd;
+
+ public int getJobStatus() {
+ return jobstatus;
+ }
+
+ public String getCmd() {
+ return cmd;
+ }
+
+ }
+
+ public static final class Capabilities {
+
+ @SerializedName("capability")
+ private HashMap capabilites;
+
+ public String getVersion() {
+ return capabilites.get("cloudByteVersion");
+ }
+ }
+}