content: //
  // 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.
  //
  
  package org.apache.cloudstack.storage.datastore.util;
  
  import com.cloud.agent.api.Answer;
  import com.cloud.exception.InvalidParameterValueException;
  import com.cloud.utils.Pair;
  import com.cloud.utils.exception.CloudRuntimeException;
  import com.google.gson.Gson;
  import com.google.gson.annotations.SerializedName;
  import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
  import org.apache.cloudstack.utils.security.SSLUtils;
  import org.apache.cloudstack.utils.security.SecureSSLSocketFactory;
  import org.apache.http.auth.InvalidCredentialsException;
  import org.apache.logging.log4j.Logger;
  import org.apache.logging.log4j.LogManager;
  import org.glassfish.jersey.client.ClientConfig;
  import org.glassfish.jersey.client.ClientResponse;
  
  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.client.Client;
  import javax.ws.rs.client.ClientBuilder;
  import javax.ws.rs.client.WebTarget;
  import javax.ws.rs.core.MediaType;
  import javax.ws.rs.core.UriBuilder;
  import java.net.ConnectException;
  import java.security.SecureRandom;
  import java.security.cert.X509Certificate;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  
  public class ElastistorUtil {
  
      protected static Logger LOGGER = LogManager.getLogger(ElastistorUtil.class);
  
      private static ConfigurationDao configurationDao;
  
      public static ConfigurationDao getConfigurationDao() {
          return configurationDao;
      }
  
      public static void setConfigurationDao(ConfigurationDao configurationDao) {
          ElastistorUtil.configurationDao = configurationDao;
      }
  
      /**
       * 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";
      public static final String REST_PARAM_STORAGEID = "storageid";
      public static final String REST_PARAM_TPCONTROL = "tpcontrol";
      public static final String REST_PARAM_IOPSCONTROL = "iopscontrol";
  
      /**
       * 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 = "CloudByte";
      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 static final String ES_TPCONTROL_VAL = "false";
      private static final String ES_IOPSCONTROL_VAL = "true";
  
      /**
       * Private constructor s.t. its never instantiated.
       */
      private ElastistorUtil() {
  
      }
  
      /**
       * This intializes a new jersey restclient for http call with elasticenter
       */
      public static ElastiCenterClient getElastistorRestClient() {
          ElastiCenterClient restclient = null;
          try {
              String ip = getConfigurationDao().getValue("cloudbyte.management.ip");
              String apikey = getConfigurationDao().getValue("cloudbyte.management.apikey");
  
              if (ip == null) {
                  throw new CloudRuntimeException("set the value of cloudbyte.management.ip in global settings");
              }
              if (apikey == null) {
                  throw new CloudRuntimeException("set the value of cloudbyte.management.apikey in global settings");
              }
  
              restclient = new ElastiCenterClient(ip, apikey);
  
          } catch (InvalidCredentialsException e) {
              throw new CloudRuntimeException("InvalidCredentialsException:" + e.getMessage(), e);
          } catch (InvalidParameterValueException e) {
              throw new CloudRuntimeException("InvalidParameterValueException:" + e.getMessage(), e);
          } catch (SSLHandshakeException e) {
              throw new CloudRuntimeException("SSLHandshakeException:" + e.getMessage(), e);
          } catch (ServiceUnavailableException e) {
              throw new CloudRuntimeException("ServiceUnavailableException:" + e.getMessage(), 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 Account in Elasticenter for the given Domain Name.
       *
       * @return
       */
      public static String getElastistorAccountId(String domainName) throws Throwable {
  
          ListAccountResponse listAccountResponse = ListElastistorAccounts();
  
          if (listAccountResponse.getAccounts().getCount() != 0) {
              int i;
              // check whether an account in elasticenter with given Domain name is
              // already present in the list of accounts
              for (i = 0; i < listAccountResponse.getAccounts().getCount(); i++) {
                  if (domainName.equals(listAccountResponse.getAccounts().getAccount(i).getName())) {
                      return listAccountResponse.getAccounts().getAccount(i).getUuid();
                  }
              }
  
              // if no account matches the give Domain Name , create one with the
              // Domain name
              CreateAccountResponse createAccountResponse = createElastistorAccount(domainName);
              return createAccountResponse.getAccount().getUuid();
  
          } else {
              // if no account is present in the elasticenter create one
              CreateAccountResponse createAccountResponse = createElastistorAccount(domainName);
              return createAccountResponse.getAccount().getUuid();
          }
      }
  
      /**
       * This creates a new tenant storage machine(TSM) for the given storagepool
       * ip in elastistor.
       *
       * @param domainName
       *            TODO
       */
      public static Tsm createElastistorTsm(String storagePoolName, String storageIp, Long capacityBytes, Long capacityIops, String domainName) 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, domainName);
          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, 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 createTsmCmdResponse;
          Tsm tsm = null;
          try {
              createTsmCmdResponse = (CreateTsmCmdResponse) getElastistorRestClient().executeCommand(createTsmCmd);
  
              if (createTsmCmdResponse.getJobid() == null) {
                  throw new CloudRuntimeException("tsm creation failed , contact elatistor admin");
              } else {
                  tsm = queryAsyncTsmJobResult(createTsmCmdResponse.getJobid());
                  if (tsm == null) {
                      throw new CloudRuntimeException("tsm queryAsync failed , contact elatistor admin");
                  }
              }
              return tsm;
          } 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 FileSystem createElastistorVolume(String volumeName, String tsmid, Long capacityBytes, Long capacityIops, String protocoltype, String mountpoint) throws Throwable {
  
          String datasetid;
          String qosgroupid;
          String VolumeName = volumeName;
          String totaliops = String.valueOf(capacityIops);
          //String totalthroughput = String.valueOf(capacityIops * 4);
          String totalthroughput = "0";
  
          String quotasize = convertCapacityBytes(capacityBytes);
  
          AddQosGroupCmd addQosGroupCmd = new AddQosGroupCmd();
  
          ListTsmsResponse listTsmsResponse = listTsm(tsmid);
  
          tsmid = listTsmsResponse.getTsms().getTsm(0).getUuid();
          datasetid = listTsmsResponse.getTsms().getTsm(0).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 != 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);
          if (null != ElastistorUtil.ES_IOPSCONTROL_VAL)
              addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_IOPSCONTROL, ElastistorUtil.ES_IOPSCONTROL_VAL);
          if (null != ElastistorUtil.ES_TPCONTROL_VAL)
              addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TPCONTROL, ElastistorUtil.ES_TPCONTROL_VAL);
  
          AddQosGroupCmdResponse addQosGroupCmdResponse = (AddQosGroupCmdResponse) getElastistorRestClient().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;
              FileSystem volume = null;
              FileSystem fileSystem = null;
  
              try {
                  createVolumeCmdResponse = (CreateVolumeCmdResponse) getElastistorRestClient().executeCommand(createVolumeCmd);
  
                  if (createVolumeCmdResponse.getJobid() == null) {
  
                      throw new CloudRuntimeException("creating volume failed , contact elatistor admin");
  
                  } else {
                      volume = queryAsyncVolumeJobResult(createVolumeCmdResponse.getJobid());
                      if (volume == null) {
                          throw new CloudRuntimeException("tsm queryAsync failed , contact elatistor admin");
                      } else {
                          if (protocoltype.equalsIgnoreCase("nfs")) {
                              fileSystem = updateNfsService(volume.getUuid());
  
                          } else {
                              fileSystem = updateIscsiService(volume.getUuid());
                          }
                      }
                  }
                  return fileSystem;
              } catch (Exception e) {
                  throw new CloudRuntimeException("creating volume failed , contact elatistor admin", e);
              }
  
          }
  
      }
  
      public static FileSystem updateNfsService(String volumeid) throws Throwable {
  
          FileSystem fileSystem = null;
  
          String datasetid = updateElastistorNfsVolume(volumeid);
  
          if (datasetid == null) {
              throw new CloudRuntimeException("Updating Nfs Volume Failed");
          } else {
  
              fileSystem = listVolume(datasetid);
              if (fileSystem == null) {
                  throw new CloudRuntimeException("Volume Creation failed : List Filesystem failed");
              }
          }
          return fileSystem;
  
      }
  
      public static FileSystem updateIscsiService(String volumeid) throws Throwable {
  
          Volumeiscsioptions volumeiscsioptions = null;
          FileSystem fileSystem = null;
          String accountId;
  
          fileSystem = listVolume(volumeid);
  
          accountId = fileSystem.getAccountid();
  
          volumeiscsioptions = updateElastistorIscsiVolume(volumeid, accountId);
  
          if (volumeiscsioptions == null) {
              throw new CloudRuntimeException("Updating Iscsi Volume Failed");
          } else {
  
              fileSystem = listVolume(volumeiscsioptions.getVolumeid());
              if (fileSystem == null) {
                  throw new CloudRuntimeException("Volume Creation failed : List Filesystem failed");
              }
          }
          return fileSystem;
  
      }
  
      public static String updateElastistorNfsVolume(String volumeid) throws Throwable {
  
          NfsServiceCmd nfsServiceCmd = new NfsServiceCmd();
  
          nfsServiceCmd.putCommandParameter("datasetid", volumeid);
          nfsServiceCmd.putCommandParameter("authnetwork", "all");
          nfsServiceCmd.putCommandParameter("managedstate", "true");
          nfsServiceCmd.putCommandParameter("alldirs", "yes");
          nfsServiceCmd.putCommandParameter("mapuserstoroot", "yes");
          nfsServiceCmd.putCommandParameter("readonly", "no");
  
          NfsServiceResponse nfsServiceResponse = (NfsServiceResponse) getElastistorRestClient().executeCommand(nfsServiceCmd);
  
          if (nfsServiceResponse.getNfsService().getUuid() != null) {
  
              UpdateControllerCmd controllerCmd = new UpdateControllerCmd();
  
              controllerCmd.putCommandParameter("nfsid", nfsServiceResponse.getNfsService().getUuid());
              controllerCmd.putCommandParameter("type", "configurenfs");
              controllerCmd.putCommandParameter("id", nfsServiceResponse.getNfsService().getControllerid());
  
              UpdateControllerResponse controllerResponse = (UpdateControllerResponse) getElastistorRestClient().executeCommand(controllerCmd);
  
              if (controllerResponse.getController().getUuid() != null) {
                  LOGGER.info("updated nfs service to ALL");
                  return nfsServiceResponse.getNfsService().getDatasetid();
              } else {
                  throw new CloudRuntimeException("Updating Nfs Volume Failed");
              }
  
          }
          return null;
      }
  
      public static Volumeiscsioptions updateElastistorIscsiVolume(String volumeid, String accountid) throws Throwable {
  
          // now listing the iscsi volume service group to get iscsi id
  
          ListVolumeiSCSIServiceCmd listVolumeiSCSIServiceCmd = new ListVolumeiSCSIServiceCmd();
  
          if (null != volumeid)
              listVolumeiSCSIServiceCmd.putCommandParameter(ElastistorUtil.REST_PARAM_STORAGEID, volumeid);
  
          ListVolumeiSCSIServiceResponse volumeiSCSIServiceResponse = (ListVolumeiSCSIServiceResponse) getElastistorRestClient().executeCommand(listVolumeiSCSIServiceCmd);
  
          String iscsiId = volumeiSCSIServiceResponse.getIscsiVolume().getIscsiVolume(0).getUuid();
          String AG_Id = volumeiSCSIServiceResponse.getIscsiVolume().getIscsiVolume(0).getAg_id();
  
          // now listing the initiator group to get initiator id
  
          ListiSCSIInitiatorCmd initiatorCmd = new ListiSCSIInitiatorCmd();
  
          if (null != volumeid)
              initiatorCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ACCOUNTID, accountid);
  
          ListiSCSIInitiatorResponse initiatorResponse = (ListiSCSIInitiatorResponse) getElastistorRestClient().executeCommand(initiatorCmd);
  
          String IG_Id;
          if (initiatorResponse.getIInitiator().getInterface(0).getInitiatorgroup().equalsIgnoreCase("ALL")) {
              IG_Id = initiatorResponse.getIInitiator().getInterface(0).getUuid();
          } else {
              IG_Id = initiatorResponse.getIInitiator().getInterface(1).getUuid();
          }
  
          if (iscsiId != null) {
  
              UpdateVolumeiSCSIServiceCmd updateVolumeiSCSIServiceCmd = new UpdateVolumeiSCSIServiceCmd();
  
              if (null != volumeid)
                  updateVolumeiSCSIServiceCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ID, iscsiId);
              if (null != volumeid)
                  updateVolumeiSCSIServiceCmd.putCommandParameter("status", "true");
              if (null != volumeid)
                  updateVolumeiSCSIServiceCmd.putCommandParameter("igid", IG_Id);
              if (null != volumeid)
                  updateVolumeiSCSIServiceCmd.putCommandParameter("authgroupid", AG_Id);
              if (null != volumeid)
                  updateVolumeiSCSIServiceCmd.putCommandParameter("initialdigest", "Auto");
              if (null != volumeid)
                  updateVolumeiSCSIServiceCmd.putCommandParameter("queuedepth", "32");
  
              UpdateVolumeiSCSIServiceCmdResponse cmdResponse = (UpdateVolumeiSCSIServiceCmdResponse) getElastistorRestClient().executeCommand(updateVolumeiSCSIServiceCmd);
  
              if (cmdResponse.getVolumeiscsioptions().getVolumeid() == null) {
                  throw new CloudRuntimeException("Updating Iscsi Volume Failed");
              }
              return cmdResponse.getVolumeiscsioptions();
          }
          return null;
  
      }
  
      /**
       * This deletes both the volume and the tsm in elastistor.
       */
      public static boolean deleteElastistorTsm(String tsmid, boolean managed) throws Throwable {
  
          if (!managed) {
  
              LOGGER.info("elastistor pool is NOT a managed storage , hence deleting the volume then tsm");
  
              String esvolumeid = null;
              ListTsmsResponse listTsmsResponse = listTsm(tsmid);
  
              if (listTsmsResponse.getTsmsCount() != 0) {
  
                  if (listTsmsResponse.getTsms().getTsm(0).checkvolume()) {
                      esvolumeid = listTsmsResponse.getTsms().getTsm(0).getVolumeProperties(0).getid();
                      DeleteVolumeResponse deleteVolumeResponse = deleteVolume(esvolumeid, null);
  
                      if (deleteVolumeResponse != null) {
                          String jobid = deleteVolumeResponse.getJobId();
                          int jobstatus = queryAsyncJobResult(jobid);
  
                          if (jobstatus == 1) {
                              LOGGER.info("elastistor volume successfully deleted");
                          } else {
                              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);
                                  }
                              }
                              LOGGER.info("elastistor volume successfully deleted");
                          }
                      }
                  } else {
                      LOGGER.info("no volume present in on the given tsm");
                  }
  
              }
          }
  
          LOGGER.info("now trying to delete elastistor tsm");
  
          if (tsmid != null) {
              DeleteTsmCmd deleteTsmCmd = new DeleteTsmCmd();
              deleteTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ID, tsmid);
              DeleteTsmResponse deleteTsmResponse = (DeleteTsmResponse) getElastistorRestClient().executeCommand(deleteTsmCmd);
  
              if (deleteTsmResponse != null) {
                  String jobstatus = deleteTsmResponse.getJobStatus();
  
                  if (jobstatus.equalsIgnoreCase("true")) {
                      LOGGER.info("deletion of elastistor tsm successful");
                      return true;
                  } else {
                      LOGGER.info("failed to delete elastistor tsm");
                      return false;
                  }
              } else {
                  LOGGER.info("elastistor tsm id not present");
              }
          }
          LOGGER.info("tsm id is null");
          return false;
  
          /*
           * else { LOGGER.error("no volume is present in the tsm"); } } else {
           * LOGGER.error(
           * "List tsm failed, no tsm present in the eastistor for the given IP "
           * ); return false; } return false;
           */
  
      }
  
      public static boolean deleteElastistorVolume(String esvolumeid) throws Throwable {
  
          FileSystem fileSystem = listVolume(esvolumeid);
  
          if (fileSystem != null) {
              DeleteVolumeResponse deleteVolumeResponse = deleteVolume(esvolumeid, null);
  
              if (deleteVolumeResponse != null) {
                  String jobid = deleteVolumeResponse.getJobId();
                  int jobstatus = queryAsyncJobResult(jobid);
  
                  if (jobstatus == 1) {
                      LOGGER.info("elastistor volume successfully deleted");
                      return true;
                  } else {
                      LOGGER.info("now force deleting the volume");
  
                      while (jobstatus != 1) {
                          DeleteVolumeResponse deleteVolumeResponse1 = deleteVolume(esvolumeid, "true");
  
                          if (deleteVolumeResponse1 != null) {
                              String jobid1 = deleteVolumeResponse1.getJobId();
                              jobstatus = queryAsyncJobResult(jobid1);
                          }
                      }
                      LOGGER.info("elastistor volume successfully deleted");
                      return true;
                  }
              } else {
                  LOGGER.info("the given volume is not present on elastistor, datasetrespone is NULL");
                  return false;
              }
          } else {
              LOGGER.info("the given volume is not present on elastistor");
              return false;
          }
  
      }
  
      /**
       * This give a json response containing the list of Interface's in
       * elastistor.
       */
  
      public static ListInterfacesResponse ListElastistorInterfaces(String controllerid) throws Throwable {
  
          ListInterfacesCmd listInterfacesCmd = new ListInterfacesCmd();
          listInterfacesCmd.putCommandParameter("controllerid", controllerid);
  
          ListInterfacesResponse interfacesResponse = (ListInterfacesResponse) getElastistorRestClient().executeCommand(listInterfacesCmd);
  
          if (interfacesResponse != null && interfacesResponse.getInterfaces() != null) {
              return interfacesResponse;
          } else {
              throw new CloudRuntimeException("There are no elastistor interfaces.");
          }
      }
  
      /**
       * This give a json response containing the list of Accounts's in
       * elastistor.
       */
  
      public static CreateAccountResponse createElastistorAccount(String domainName) throws Throwable {
  
          CreateAccountCmd createAccountCmd = new CreateAccountCmd();
  
          createAccountCmd.putCommandParameter("name", domainName);
          CreateAccountResponse createAccountResponse = (CreateAccountResponse) getElastistorRestClient().executeCommand(createAccountCmd);
  
          if (createAccountResponse != null) {
              return createAccountResponse;
          } else {
              throw new CloudRuntimeException("Creating Elastistor Account failed");
          }
  
      }
  
      /**
       * This give a json response containing the list of Accounts's in
       * elastistor.
       */
  
      public static ListAccountResponse ListElastistorAccounts() throws Throwable {
  
          ListAccountsCmd listAccountsCmd = new ListAccountsCmd();
  
          ListAccountResponse accountResponse = (ListAccountResponse) getElastistorRestClient().executeCommand(listAccountsCmd);
  
          if (accountResponse != null) {
              return accountResponse;
          } else {
              throw new CloudRuntimeException("List Elastistor Account failed");
          }
  
      }
  
      /**
       * This give a json response containing the list of Pool's in elastistor.
       */
  
      public static ListPoolsResponse ListElastistorPools() throws Throwable {
  
          ListPoolsCmd listPoolsCmd = new ListPoolsCmd();
  
          ListPoolsResponse listPoolsResponse = (ListPoolsResponse) getElastistorRestClient().executeCommand(listPoolsCmd);
  
          if (listPoolsResponse != null) {
              return listPoolsResponse;
          } else {
              throw new CloudRuntimeException("List Elastistor pool failed");
          }
  
      }
  
      /**
       * This give a json response containing the list of tsm's in elastistor.
       */
      private static ListTsmsResponse listTsm(String uuid) throws Throwable {
  
          ListTsmCmd listTsmCmd = new ListTsmCmd();
  
          listTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ID, uuid);
  
          ListTsmsResponse listTsmsResponse = (ListTsmsResponse) getElastistorRestClient().executeCommand(listTsmCmd);
  
          return listTsmsResponse;
      }
  
      /**
       * This give a json response containing the list of Volume in elastistor.
       */
      public static FileSystem listVolume(String uuid) throws Throwable {
  
          ListFileSystemCmd listFileSystemCmd = new ListFileSystemCmd();
  
          listFileSystemCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ID, uuid);
  
          ListFileSystemResponse listFileSystemResponse = (ListFileSystemResponse) getElastistorRestClient().executeCommand(listFileSystemCmd);
  
          return listFileSystemResponse.getFilesystems().getFileSystem(0);
      }
  
      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().executeCommand(deleteVolumeCmd);
  
          return deleteVolumeResponse;
      }
  
      private static int queryAsyncJobResult(String jobid) throws Throwable {
  
          QueryAsyncJobResultCmd asyncJobResultCmd = new QueryAsyncJobResultCmd();
          ElastiCenterClient restclient = getElastistorRestClient();
  
          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;
  
      }
  
      private static Tsm queryAsyncTsmJobResult(String jobid) throws Throwable {
  
          QueryAsyncJobResultCmd asyncJobResultCmd = new QueryAsyncJobResultCmd();
          ElastiCenterClient restclient = getElastistorRestClient();
  
          asyncJobResultCmd.putCommandParameter(ElastistorUtil.REST_PARAM_JOBID, jobid);
  
          QueryAsyncJobResultResponse asyncJobResultResponse = (QueryAsyncJobResultResponse) restclient.executeCommand(asyncJobResultCmd);
  
          if (asyncJobResultResponse != null) {
              int jobstatus = asyncJobResultResponse.getAsync().getJobStatus();
              Tsm tsm = null;
              while (jobstatus == 0) {
  
                  asyncJobResultResponse = (QueryAsyncJobResultResponse) restclient.executeCommand(asyncJobResultCmd);
  
                  jobstatus = asyncJobResultResponse.getAsync().getJobStatus();
  
              }
              if (jobstatus == 1) {
                  tsm = asyncJobResultResponse.getAsync().getJobResult().getTsm();
                  return tsm;
              }
          }
          return null;
  
      }
  
      private static FileSystem queryAsyncVolumeJobResult(String jobid) throws Throwable {
  
          QueryAsyncJobResultCmd asyncJobResultCmd = new QueryAsyncJobResultCmd();
          ElastiCenterClient restclient = getElastistorRestClient();
  
          asyncJobResultCmd.putCommandParameter(ElastistorUtil.REST_PARAM_JOBID, jobid);
  
          QueryAsyncJobResultResponse asyncJobResultResponse = (QueryAsyncJobResultResponse) restclient.executeCommand(asyncJobResultCmd);
  
          if (asyncJobResultResponse != null) {
              int jobstatus = asyncJobResultResponse.getAsync().getJobStatus();
              FileSystem volume = null;
              while (jobstatus == 0) {
  
                  asyncJobResultResponse = (QueryAsyncJobResultResponse) restclient.executeCommand(asyncJobResultCmd);
  
                  jobstatus = asyncJobResultResponse.getAsync().getJobStatus();
  
              }
              if (jobstatus == 1) {
                  volume = asyncJobResultResponse.getAsync().getJobResult().getVolume();
                  return volume;
              }
          }
          return null;
  
      }
  
      /**
       * this method converts the long capacitybytes to string format, which is
       * feasible for elastistor rest api 214748364800 = 200G.
       */
      private static String convertCapacityBytes(Long capacityBytes) {
  
          if ((1099511627776L) > capacityBytes && (capacityBytes > (1073741824))) {
              return (String.valueOf(capacityBytes / (1024 * 1024 * 1024)) + "G");
          } else {
              int temp1 = (int) (capacityBytes / (1024 * 1024 * 1024));
              int temp2 = temp1 / 1024;
              return (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 List<Pair<String, String>> getCommandParameters();
  
          /*
           * Adds new key-value pair to the query parameters 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 List<Pair<String, String>> 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 List<Pair<String, String>> getCommandParameters() {
              return commandParameters;
          }
  
          @Override
          public void putCommandParameter(String key, String value) {
              if (null == commandParameters) {
                  commandParameters = new ArrayList<>();
              }
              commandParameters.add(new Pair<>(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, InvalidParameterValueException, SSLHandshakeException, ServiceUnavailableException {
              elastiCenterAddress = address;
              apiKey = key;
              initialize();
          }
  
          public void initialize() throws InvalidParameterValueException, SSLHandshakeException, InvalidCredentialsException, ServiceUnavailableException {
  
              if (apiKey == null || apiKey.trim().isEmpty()) {
                  throw new InvalidParameterValueException("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 InvalidParameterValueException("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() {
                      @Override
                      public X509Certificate[] getAcceptedIssuers() {
                          return null;
                      }
  
                      @Override
                      public void checkClientTrusted(X509Certificate[] certs, String authType) {
                      }
  
                      @Override
                      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 = SSLUtils.getSSLContext();
                      sc.init(null, trustAllCerts, new SecureRandom());
                      HttpsURLConnection.setDefaultSSLSocketFactory(new SecureSSLSocketFactory(sc));
                      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, List<Pair<String, String>> params, Object responeObj) throws Throwable {
  
              if (!initialized) {
                  throw new IllegalStateException("Error : ElastiCenterClient is not initialized.");
              }
  
              if (command == null || command.trim().isEmpty()) {
                  throw new InvalidParameterValueException("No command to execute.");
              }
  
              try {
                  ClientConfig config = new ClientConfig();
                  Client client = ClientBuilder.newClient(config);
                  WebTarget webResource = client.target(UriBuilder.fromUri(restprotocol + elastiCenterAddress + restpath).build())
                      .queryParam(queryparamapikey, apiKey)
                      .queryParam(queryparamresponse, responseType)
                      .queryParam(queryparamcommand, command);
  
                  if (null != params) {
                      for (Pair<String, String> pair : params) {
                          webResource = webResource.queryParam(pair.first(), pair.second());
                      }
                  }
                  if (debug) {
                      List<Pair<String, String>> qryParams = new ArrayList<>();
                      qryParams.add(new Pair<>(queryparamapikey, apiKey));
                      qryParams.add(new Pair<>(queryparamresponse, responseType));
                      qryParams.add(new Pair<>(queryparamcommand, command));
                      qryParams.addAll(params);
                      System.out.println("Command Sent " + command + " : " + params);
                  }
                  ClientResponse response = webResource.request(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 InvalidParameterValueException(response.getHeaders().getFirst("X-Description"));
                      } else if (432 == response.getStatus()) {
                          throw new InvalidParameterValueException(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 = String.valueOf(response.readEntity(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 ListVolumeiSCSIServiceCmd extends BaseCommand {
  
          public ListVolumeiSCSIServiceCmd() {
              super("listVolumeiSCSIService", new ListVolumeiSCSIServiceResponse());
  
          }
  
      }
  
      private static final class ListiSCSIInitiatorCmd extends BaseCommand {
  
          public ListiSCSIInitiatorCmd() {
              super("listiSCSIInitiator", new ListiSCSIInitiatorResponse());
  
          }
  
      }
  
      private static final class NfsServiceCmd extends BaseCommand {
  
          public NfsServiceCmd() {
              super("nfsService", new NfsServiceResponse());
  
          }
  
      }
  
      private static final class UpdateControllerCmd extends BaseCommand {
  
          public UpdateControllerCmd() {
              super("updateController", new UpdateControllerResponse());
  
          }
  
      }
  
      private static final class UpdateVolumeiSCSIServiceCmd extends BaseCommand {
  
          public UpdateVolumeiSCSIServiceCmd() {
              super("updateVolumeiSCSIService", new UpdateVolumeiSCSIServiceCmdResponse());
  
          }
  
      }
  
      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());
          }
  
      }
  
      private static final class ListFileSystemCmd extends BaseCommand {
  
          public ListFileSystemCmd() {
              super("listFileSystem", new ListFileSystemResponse());
          }
  
      }
  
      private static final class ListAccountsCmd extends BaseCommand {
  
          public ListAccountsCmd() {
              super("listAccount", new ListAccountResponse());
          }
  
      }
  
      private static final class CreateAccountCmd extends BaseCommand {
  
          public CreateAccountCmd() {
              super("createAccount", new CreateAccountResponse());
          }
  
      }
  
      private static final class ListInterfacesCmd extends BaseCommand {
  
          public ListInterfacesCmd() {
              super("listSharedNICs", new ListInterfacesResponse());
          }
  
      }
  
      private static final class ListPoolsCmd extends BaseCommand {
  
          public ListPoolsCmd() {
              super("listHAPool", new ListPoolsResponse());
          }
  
      }
  
      /**
       * these are the list of Elastistor rest json response classes for parsing
       * the json response sent by elastistor.
       *
       */
      public static final class CreateTsmCmdResponse {
  
          @SerializedName("addTsmResponse")
          private JobId jobId;
  
          public String getJobid() {
              return jobId.getJobid();
          }
  
          public String getJobStatus() {
              return jobId.getJobStatus();
          }
  
          @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<String, String> 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 UpdateVolumeiSCSIServiceCmdResponse {
  
          @SerializedName("updatingvolumeiscsidetails")
          private VolumeiSCSIServiceWrapper volumeiSCSIServiceWrapper;
  
          public Volumeiscsioptions getVolumeiscsioptions() {
  
              return volumeiSCSIServiceWrapper.getVolumeiscsioptions();
          }
  
      }
  
      public static final class VolumeiSCSIServiceWrapper {
  
          @SerializedName("viscsioptions")
          private Volumeiscsioptions viscsioptions;
  
          public Volumeiscsioptions getVolumeiscsioptions() {
              return viscsioptions;
          }
  
      }
  
      public static final class Volumeiscsioptions {
  
          @SerializedName("id")
          private String uuid;
  
          @SerializedName("volume_id")
          private String volumeid;
  
          @SerializedName("iqnname")
          private String iqnname;
  
          public String getUuid() {
              return uuid;
          }
  
          public String getVolumeid() {
              return volumeid;
          }
  
          public String getIqn() {
              return iqnname;
          }
  
      }
  
      public static final class NfsServiceResponse {
  
          @SerializedName("nfsserviceprotocolresponse")
          private NfsServiceWrapper nfsServiceWrapper;
  
          public NfsService getNfsService() {
  
              return nfsServiceWrapper.getNfsservice();
          }
  
      }
  
      public static final class NfsServiceWrapper {
  
          @SerializedName("nfs")
          private NfsService nfsService;
  
          public NfsService getNfsservice() {
              return nfsService;
          }
  
      }
  
      public static final class NfsService {
  
          @SerializedName("id")
          private String uuid;
  
          @SerializedName("STORAGEID")
          private String datasetid;
  
          @SerializedName("controllerid")
          private String controllerid;
  
          @SerializedName("authnetwork")
          private String authnetwork;
  
          public String getUuid() {
              return uuid;
          }
  
          public String getDatasetid() {
              return datasetid;
          }
  
          public String getControllerid() {
              return controllerid;
          }
  
          public String getAuthnetwork() {
              return authnetwork;
          }
  
      }
  
      public static final class UpdateControllerResponse {
  
          @SerializedName("updateControllerResponse")
          private UpdateControllerWrapper controllerWrapper;
  
          public Controller getController() {
  
              return controllerWrapper.getController();
          }
  
      }
  
      public static final class UpdateControllerWrapper {
  
          @SerializedName("controller")
          private Controller controller;
  
          public Controller getController() {
              return controller;
          }
  
      }
  
      public static final class Controller {
  
          @SerializedName("id")
          private String uuid;
  
          public String getUuid() {
              return uuid;
          }
  
      }
  
      public static final class CreateVolumeCmdResponse {
  
          @SerializedName("createvolumeresponse")
          private JobId jobId;
  
          public String getJobid() {
              return jobId.getJobid();
          }
  
          @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("accountid")
          private String accountid;
  
          @SerializedName("iqnname")
          private String iqnname;
  
          @SerializedName("nfsenabled")
          private String nfsenabled;
  
          @SerializedName("iscsienabled")
          private String iscsienabled;
  
          @SerializedName("path")
          private String path;
  
          @SerializedName("groupid")
          private String groupid;
  
          @SerializedName("compression")
          private String compression;
  
          @SerializedName("sync")
          private String sync;
  
          @SerializedName("deduplication")
          private String deduplication;
  
          @SerializedName("graceallowed")
          private String graceallowed;
  
          public String getCompression() {
              return compression;
          }
  
          public String getSync() {
              return sync;
          }
  
          public String getDeduplication() {
              return deduplication;
          }
  
          public String getGraceallowed() {
              return graceallowed;
          }
  
          public String getUuid() {
              return uuid;
          }
  
          public String getQosGroupid() {
              return groupid;
          }
  
          public String getName() {
              return name;
          }
  
          public String getNfsenabled() {
              return nfsenabled;
          }
  
          public String getIscsienabled() {
              return iscsienabled;
          }
  
          public String getPath() {
              return path;
          }
  
          public String getIqn() {
              return iqnname;
          }
  
          public String getQuota() {
              return quota;
          }
  
          public String getAccountid() {
              return accountid;
          }
  
      }
  
      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;
  
          @SerializedName("jobresult")
          private JobResult jobresult;
  
          @SerializedName("tsm")
          private Tsm tsm;
  
          @SerializedName("storage")
          private FileSystem volume;
  
          public Tsm getTsm() {
              return tsm;
          }
  
          public FileSystem getVolume() {
              return volume;
          }
  
          public JobResult getJobResult() {
              return jobresult;
          }
  
          public String getJobid() {
              return jobid;
          }
  
          public String getJobStatus() {
              return jobStatus;
          }
  
      }
  
      public static final class JobResult {
  
          @SerializedName("tsm")
          private Tsm tsm;
  
          @SerializedName("storage")
          private FileSystem volume;
  
          public Tsm getTsm() {
              return tsm;
          }
  
          public FileSystem getVolume() {
              return volume;
          }
  
      }
  
      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 ListFileSystemResponse {
  
          @SerializedName("listFilesystemResponse")
          private Filesystems filesystems;
  
          public int getFilesystemCount() {
              return filesystems.getCount();
          }
  
          public Filesystems getFilesystems() {
              return filesystems;
          }
      }
  
      public static final class Filesystems {
  
          @SerializedName("count")
          private int count;
  
          @SerializedName("filesystem")
          private FileSystem[] fileSystems;
  
          public int getCount() {
              return count;
          }
  
          public FileSystem getFileSystem(int i) {
              return fileSystems[i];
          }
      }
  
      public static final class ListPoolsResponse {
  
          @SerializedName("listHAPoolResponse")
          private Pools pools;
  
          public Pools getPools() {
              return pools;
          }
      }
  
      public static final class Pools {
  
          @SerializedName("hapool")
          private Pool[] pool;
  
          @SerializedName("count")
          private int count;
  
          public Pool getPool(int i) {
              return pool[i];
          }
  
          public int getCount() {
              return count;
          }
      }
  
      public static final class Pool {
  
          @SerializedName("id")
          private String uuid;
  
          @SerializedName("name")
          private String name;
  
          @SerializedName("currentAvailableSpace")
          private String currentAvailableSpace;
  
          @SerializedName("availIOPS")
          private String availIOPS;
  
          @SerializedName("status")
          private String state;
  
          @SerializedName("controllerid")
          private String controllerid;
  
          @SerializedName("gateway")
          private String gateway;
  
          public String getControllerid() {
              return controllerid;
          }
  
          public String getUuid() {
              return uuid;
          }
  
          public String getName() {
              return name;
          }
  
          public String getAvailableSpace() {
              return currentAvailableSpace;
          }
  
          public String getAvailIOPS() {
              return availIOPS;
          }
  
          public String getState() {
              return state;
          }
  
          public String getGateway() {
              return gateway;
          }
      }
  
      public static final class ListInterfacesResponse {
  
          @SerializedName("listSharedNICsResponse")
          private Interfaces interfaces;
  
          public Interfaces getInterfaces() {
              return interfaces;
          }
      }
  
      public static final class Interfaces {
  
          @SerializedName("nic")
          private Interface[] interfaces;
  
          @SerializedName("count")
          private int count;
  
          public Interface getInterface(int i) {
              return interfaces[i];
          }
  
          public int getCount() {
              return count;
          }
      }
  
      public static final class Interface {
  
          @SerializedName("id")
          private String uuid;
  
          @SerializedName("name")
          private String name;
  
          @SerializedName("status")
          private String status;
  
          public String getUuid() {
              return uuid;
          }
  
          public String getName() {
              return name;
          }
  
          public String getStatus() {
              return status;
          }
      }
  
      public static final class ListiSCSIInitiatorResponse {
  
          @SerializedName("listInitiatorsResponse")
          private Initiators initiators;
  
          public Initiators getIInitiator() {
              return initiators;
          }
      }
  
      public static final class Initiators {
  
          @SerializedName("initiator")
          private Initiator[] initiators;
  
          @SerializedName("count")
          private int count;
  
          public Initiator getInterface(int i) {
              return initiators[i];
          }
  
          public int getCount() {
              return count;
          }
      }
  
      public static final class Initiator {
  
          @SerializedName("id")
          private String uuid;
  
          @SerializedName("name")
          private String name;
  
          @SerializedName("initiatorgroup")
          private String initiatorgroup;
  
          public String getUuid() {
              return uuid;
          }
  
          public String getName() {
              return name;
          }
  
          public String getInitiatorgroup() {
              return initiatorgroup;
          }
      }
  
      public static final class ListAccountResponse {
  
          @SerializedName("listAccountResponse")
          private Accounts accounts;
  
          public Accounts getAccounts() {
              return accounts;
          }
      }
  
      public static final class Accounts {
  
          @SerializedName("account")
          private Account[] Accounts;
  
          @SerializedName("count")
          private int count;
  
          public Account getAccount(int i) {
              return Accounts[i];
          }
  
          public int getCount() {
              return count;
          }
      }
  
      public static final class CreateAccountResponse {
  
          @SerializedName("createaccountresponse")
          private Accounts2 accounts;
  
          public Account getAccount() {
              return accounts.getAccount();
          }
      }
  
      public static final class Accounts2 {
  
          @SerializedName("account2")
          private Account Account;
  
          @SerializedName("count")
          private int count;
  
          public Account getAccount() {
              return Account;
          }
  
          public int getCount() {
              return count;
          }
      }
  
      public static final class Account {
  
          @SerializedName("id")
          private String uuid;
  
          @SerializedName("name")
          private String name;
  
          public String getUuid() {
              return uuid;
          }
  
          public String getName() {
              return name;
          }
      }
  
      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 ListVolumeiSCSIServiceResponse {
  
          @SerializedName("listVolumeiSCSIServiceResponse")
          private IscsiVolumeService iscsiVolumes;
  
          public int getVolumeCount() {
              return iscsiVolumes.getCount();
          }
  
          public IscsiVolumeService getIscsiVolume() {
              return iscsiVolumes;
          }
      }
  
      public static final class IscsiVolumeService {
  
          @SerializedName("count")
          private int count;
  
          @SerializedName("iSCSIService")
          private IscsiVolume[] iscsiVolumes;
  
          public int getCount() {
              return count;
          }
  
          public IscsiVolume getIscsiVolume(int i) {
              return iscsiVolumes[i];
          }
      }
  
      public static final class IscsiVolume {
  
          @SerializedName("id")
          private String uuid;
  
          @SerializedName("ag_id")
          private String agid;
  
          @SerializedName("ig_id")
          private String igid;
  
          public String getAg_id() {
              return agid;
          }
  
          public String getUuid() {
              return uuid;
          }
  
          public String getIg_id() {
              return igid;
          }
      }
  
      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("jobresult")
          private JobId jobresult;
  
          @SerializedName("cmd")
          private String cmd;
  
          public int getJobStatus() {
              return jobstatus;
          }
  
          public JobId getJobResult() {
              return jobresult;
          }
  
          public String getCmd() {
              return cmd;
          }
  
      }
  
      public static final class Capabilities {
  
          @SerializedName("capability")
          private HashMap<String, String> capabilites;
  
          public String getVersion() {
              return capabilites.get("cloudByteVersion");
          }
      }
  
      /*
       *
       * change Volume IOPS
       */
  
      public static Answer updateElastistorVolumeQosGroup(String volumeId, Long newIOPS, String graceAllowed) throws Throwable {
  
          FileSystem fileSystem = listVolume(volumeId);
  
          String qosid = fileSystem.getQosGroupid();
  
          if (qosid != null) {
  
              UpdateQosGroupCmdResponse qosGroupCmdResponse = updateQosGroupVolume(newIOPS.toString(), qosid, graceAllowed);
  
              if (qosGroupCmdResponse.getQoSGroup(0).uuid != null) {
                  return new Answer(null, true, null);
              } else {
                  return new Answer(null, false, "Update Qos Group Failed");
              }
          } else {
              return new Answer(null, false, "Qos Group id is NULL");
          }
  
      }
  
      private static UpdateQosGroupCmdResponse updateQosGroupVolume(String iops, String qosgroupid, String graceAllowed) throws Throwable {
  
          UpdateQosGroupCmd updateQosGroupCmd = new UpdateQosGroupCmd();
          updateQosGroupCmd.putCommandParameter("id", qosgroupid);
          updateQosGroupCmd.putCommandParameter("iops", iops);
          updateQosGroupCmd.putCommandParameter("graceallowed", graceAllowed);
  
          UpdateQosGroupCmdResponse updateQosGroupCmdResponse = (UpdateQosGroupCmdResponse) getElastistorRestClient().executeCommand(updateQosGroupCmd);
  
          return updateQosGroupCmdResponse;
      }
  
      private static final class UpdateQosGroupCmd extends BaseCommand {
  
          public UpdateQosGroupCmd() {
              super("updateQosGroup", new UpdateQosGroupCmdResponse());
          }
  
      }
  
      public static final class UpdateQosGroupCmdResponse {
  
          @SerializedName("updateqosresponse")
          private QoSGroupWrapperChangeVolumeIops qosGroupWrapper;
  
          public QoSGroup getQoSGroup(int i) {
              return qosGroupWrapper.getQosGroup(i);
          }
      }
  
      public static final class QoSGroupWrapperChangeVolumeIops {
  
          @SerializedName("qosgroup")
          private QoSGroup qoSGroup[];
  
          public QoSGroup getQosGroup(int i) {
  
              return qoSGroup[i];
          }
  
      }
  
      /*
       * resize volume
       */
  
      public static Boolean updateElastistorVolumeSize(String volumeId, Long newSize) throws Throwable {
  
          Boolean status = false;
  
          String quotasize = (String.valueOf(newSize / (1024 * 1024 * 1024)) + "G");
  
          UpdateFileSystemCmdResponse fileSystemCmdResponse = updateFileSystem(quotasize, volumeId, null, null, null);
  
          if (fileSystemCmdResponse.getFileSystem(0).uuid != null) {
              status = true;
              return status;
          }
  
          return status;
      }
  
      public static UpdateFileSystemCmdResponse updateFileSystem(String quotasize, String esvolumeid, String dedeplication, String compression, String sync) throws Throwable {
  
          UpdateFileSystemCmd fileSystemCmd = new UpdateFileSystemCmd();
  
          fileSystemCmd.putCommandParameter("id", esvolumeid);
          if (null != quotasize)
              fileSystemCmd.putCommandParameter("quotasize", quotasize);
          if (null != dedeplication)
              fileSystemCmd.putCommandParameter("deduplication", dedeplication);
          if (null != compression)
              fileSystemCmd.putCommandParameter("compression", compression);
          if (null != sync)
              fileSystemCmd.putCommandParameter("sync", sync);
  
          UpdateFileSystemCmdResponse fileSystemCmdResponse = (UpdateFileSystemCmdResponse) getElastistorRestClient().executeCommand(fileSystemCmd);
  
          return fileSystemCmdResponse;
      }
  
      private static final class UpdateFileSystemCmd extends BaseCommand {
  
          public UpdateFileSystemCmd() {
              super("updateFileSystem", new UpdateFileSystemCmdResponse());
          }
  
      }
  
      private static final class UpdateFileSystemCmdResponse {
  
          @SerializedName("updatefilesystemresponse")
          private UpdateFileSystemWrapper fileSystemWrapper;
  
          public FileSystem getFileSystem(int i) {
  
              return fileSystemWrapper.getFileSystem(i);
          }
      }
  
      public class UpdateFileSystemWrapper {
  
          @SerializedName("filesystem")
          private FileSystem fileSystem[];
  
          public FileSystem getFileSystem(int i) {
              return fileSystem[i];
          }
  
      }
      /*
       * create snapshot
       */
  
       public static Answer createElastistorVolumeSnapshot(String volumeId, String snapshotName) throws Throwable{
  
           CreateStorageSnapshotCmd snapshotCmd = new CreateStorageSnapshotCmd();
  
           snapshotCmd.putCommandParameter("id", volumeId);
           snapshotCmd.putCommandParameter("name", snapshotName);
  
           CreateStorageSnapshotCmdResponse snapshotCmdResponse = (CreateStorageSnapshotCmdResponse) getElastistorRestClient().executeCommand(snapshotCmd);
  
           if(snapshotCmdResponse.getStorageSnapshot().getId() != null){
               return new Answer(null, true, snapshotCmdResponse.getStorageSnapshot().getId());
           }else{
               return new Answer(null, false, "snapshot failed");
           }
       }
  
       private static final class CreateStorageSnapshotCmd extends BaseCommand {
  
              public CreateStorageSnapshotCmd() {
                  super("createStorageSnapshot", new CreateStorageSnapshotCmdResponse() );
              }
  
          }
  
       private static final class CreateStorageSnapshotCmdResponse {
  
              @SerializedName("createStorageSnapshotResponse")
               private StorageSnapshotWrapper StorageSnapshot;
  
              public StorageSnapshot getStorageSnapshot() {
                  return StorageSnapshot.getStorageSnapshot();
              }
          }
  
       public static final class StorageSnapshotWrapper {
  
              @SerializedName("StorageSnapshot")
              private StorageSnapshot snapshot;
  
  
  
              public StorageSnapshot getStorageSnapshot() {
                  return snapshot;
              }
  
          }
  
       public static final class StorageSnapshot {
  
           @SerializedName("id")
           private String uuid;
  
           @SerializedName("name")
           private String name;
  
           public String getId(){
               return uuid;
           }
  
           public String getName(){
               return name;
           }
       }
  
       // update the TSM storage
       public static UpdateTsmStorageCmdResponse updateElastistorTsmStorage(String capacityBytes,String uuid) throws Throwable{
  
           Long size = (Long.parseLong(capacityBytes)/(1024 * 1024 * 1024));
  
           String quotasize = null;
  
           if(size > 1024){
              quotasize = (String.valueOf(Long.parseLong(capacityBytes)/(1024)) + "T");
           }else{
              quotasize = String.valueOf(quotasize) + "G";
           }
           LOGGER.info("elastistor tsm storage is updating to " + quotasize);
           UpdateTsmStorageCmd updateTsmStorageCmd = new UpdateTsmStorageCmd();
  
           updateTsmStorageCmd.putCommandParameter("id", uuid);
           updateTsmStorageCmd.putCommandParameter("quotasize", quotasize);
  
           UpdateTsmStorageCmdResponse updateTsmStorageCmdResponse = (UpdateTsmStorageCmdResponse) getElastistorRestClient().executeCommand(updateTsmStorageCmd);
  
         return updateTsmStorageCmdResponse;
       }
  
       private static final class UpdateTsmStorageCmd extends BaseCommand {
  
           public UpdateTsmStorageCmd() {
               super("updateStorage", new UpdateTsmStorageCmdResponse());
           }
  
       }
  
       public static final class UpdateTsmStorageCmdResponse {
  
           @SerializedName("updatedatasetresponse")
            private StorageWrapper storageWrapper;
  
           public Storage getStorage() {
               return storageWrapper.getStorage();
           }
       }
  
       public static final class StorageWrapper {
  
           @SerializedName("storage")
           private Storage storage;
  
           public Storage getStorage() {
               return storage;
           }
  
       }
  
       public static final class Storage {
  
           @SerializedName("id")
           private String uuid;
  
           @SerializedName("name")
           private String name;
  
           @SerializedName("quota")
           private String quota;
  
           public String getId(){
               return uuid;
           }
  
           public String getName(){
               return name;
           }
  
           public String getsize(){
               return quota;
           }
       }
  
    // update the TSM IOPS
       public static UpdateTsmCmdResponse updateElastistorTsmIOPS(String capacityIOPs,String uuid) throws Throwable{
  
           LOGGER.info("elastistor tsm IOPS is updating to " + capacityIOPs);
           UpdateTsmCmd updateTsmCmd = new UpdateTsmCmd();
           String throughput = String.valueOf(Long.parseLong(capacityIOPs)*4);
  
           updateTsmCmd.putCommandParameter("id", uuid);
           updateTsmCmd.putCommandParameter("iops", capacityIOPs);
           updateTsmCmd.putCommandParameter("throughput", throughput);
  
           UpdateTsmCmdResponse updateTsmStorageCmdResponse = (UpdateTsmCmdResponse) getElastistorRestClient().executeCommand(updateTsmCmd);
  
         return updateTsmStorageCmdResponse;
       }
  
       private static final class UpdateTsmCmd extends BaseCommand {
  
           public UpdateTsmCmd() {
               super("updateTsm", new UpdateTsmCmdResponse());
           }
  
       }
  
       public static final class UpdateTsmCmdResponse {
  
           @SerializedName("updateTsmResponse")
            private UpdateTsmWrapper tsmWrapper;
  
           public Tsm getTsm(int i) {
               return tsmWrapper.getTsm(i);
           }
       }
  
       public static final class UpdateTsmWrapper {
  
           @SerializedName("count")
           private int count;
  
           @SerializedName("tsm")
           private Tsm[] tsms;
  
           public int getCount() {
               return count;
           }
  
           public Tsm getTsm(int i) {
               return tsms[i];
           }
       }
  
  }
  