Get IQN from newly created volume, store in DB, and return from API call
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/a3f47086 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/a3f47086 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/a3f47086 Branch: refs/heads/sf-plugins Commit: a3f470860feff370bc7faa0a621562ce5441d847 Parents: 0fc4b0c Author: Mike Tutkowski <mike.tutkow...@solidfire.com> Authored: Mon Jul 6 18:06:58 2015 -0600 Committer: CloudStack <cloudstack@cloudstack-virtual-machine.(none)> Committed: Tue Jul 28 13:42:40 2015 -0600 ---------------------------------------------------------------------- .../apache/cloudstack/api/helper/ApiHelper.java | 4 +- .../response/ApiSolidFireVolumeResponse.java | 12 ++ .../solidfire/ApiSolidFireServiceImpl2.java | 4 +- .../solidfire/dataaccess/SfVolume.java | 2 + .../solidfire/dataaccess/vo/SfVolumeVO.java | 11 +- .../solidfire/util/SolidFireConnection.java | 216 +++++++++++++++++-- 6 files changed, 233 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a3f47086/plugins/api/solidfire/src/org/apache/cloudstack/api/helper/ApiHelper.java ---------------------------------------------------------------------- diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/helper/ApiHelper.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/helper/ApiHelper.java index 0e29e90..9a83404 100644 --- a/plugins/api/solidfire/src/org/apache/cloudstack/api/helper/ApiHelper.java +++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/helper/ApiHelper.java @@ -54,6 +54,7 @@ public class ApiHelper { public static final String TOTAL_MIN_IOPS_DESC = "Total minimum IOPS"; public static final String TOTAL_MAX_IOPS_DESC = "Total maximum IOPS"; public static final String TOTAL_BURST_IOPS_DESC = "Total burst IOPS"; + public static final String IQN_DESC = "Volume IQN"; public static final String SIZE_DESC = "Size (in GBs)"; public static final String MIN_IOPS_DESC = "Min IOPS"; public static final String MAX_IOPS_DESC = "Max IOPS"; @@ -66,7 +67,7 @@ public class ApiHelper { public static final String ACCOUNT_ID_DESC = "Account ID"; public static final String VIRTUAL_NETWORK_ID_DESC = "Virtual network ID"; public static final String VOLUME_ID_DESC = "Volume ID"; - public static final String VOLUME_NAME_DESC = "Name for volume"; + public static final String VOLUME_NAME_DESC = "Volume name"; public static final String ZONE_ID_DESC = "Zone ID"; @Inject private AccountDao _accountDao; @@ -174,6 +175,7 @@ public class ApiHelper { sfResponse.setId(sfVolume.getId()); sfResponse.setUuid(sfVolume.getUuid()); sfResponse.setName(sfVolume.getName()); + sfResponse.setIqn(sfVolume.getIqn()); sfResponse.setSize(sfVolume.getSize()); sfResponse.setMinIops(sfVolume.getMinIops()); sfResponse.setMaxIops(sfVolume.getMaxIops()); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a3f47086/plugins/api/solidfire/src/org/apache/cloudstack/api/response/ApiSolidFireVolumeResponse.java ---------------------------------------------------------------------- diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/response/ApiSolidFireVolumeResponse.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/response/ApiSolidFireVolumeResponse.java index 2da7dfb..e4f0e70 100644 --- a/plugins/api/solidfire/src/org/apache/cloudstack/api/response/ApiSolidFireVolumeResponse.java +++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/response/ApiSolidFireVolumeResponse.java @@ -39,6 +39,10 @@ public class ApiSolidFireVolumeResponse extends BaseResponse { @Param(description = ApiHelper.VOLUME_NAME_DESC) private String _name; + @SerializedName("iqn") + @Param(description = ApiHelper.IQN_DESC) + private String _iqn; + @SerializedName("size") @Param(description = ApiHelper.SIZE_DESC) private long _size; @@ -127,6 +131,14 @@ public class ApiSolidFireVolumeResponse extends BaseResponse { return _name; } + public void setIqn(String iqn) { + _iqn = iqn; + } + + public String getIqn() { + return _iqn; + } + public void setSize(long size) { _size = size; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a3f47086/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/ApiSolidFireServiceImpl2.java ---------------------------------------------------------------------- diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/ApiSolidFireServiceImpl2.java b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/ApiSolidFireServiceImpl2.java index 663123b..9af4ac2 100644 --- a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/ApiSolidFireServiceImpl2.java +++ b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/ApiSolidFireServiceImpl2.java @@ -702,7 +702,9 @@ public class ApiSolidFireServiceImpl2 extends AdapterBase implements APIChecker, long sfVolumeId = sfConnection.createVolume(name, sfAccountId, size, minIops, maxIops, burstIops); - SfVolumeVO sfVolumeVO = new SfVolumeVO(sfVolumeId, name, size, minIops, maxIops, burstIops, sfVirtualNetworkId); + SolidFireConnection.SolidFireVolume sfVolume = sfConnection.getVolume(sfVolumeId); + + SfVolumeVO sfVolumeVO = new SfVolumeVO(sfVolumeId, name, sfVolume.getIqn(), size, minIops, maxIops, burstIops, sfVirtualNetworkId); return _sfVolumeDao.persist(sfVolumeVO); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a3f47086/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/dataaccess/SfVolume.java ---------------------------------------------------------------------- diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/dataaccess/SfVolume.java b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/dataaccess/SfVolume.java index 481106c..d59395d 100644 --- a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/dataaccess/SfVolume.java +++ b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/dataaccess/SfVolume.java @@ -24,6 +24,8 @@ public interface SfVolume extends Identity, InternalIdentity { String getName(); + String getIqn(); + long getSize(); long getMinIops(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a3f47086/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/dataaccess/vo/SfVolumeVO.java ---------------------------------------------------------------------- diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/dataaccess/vo/SfVolumeVO.java b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/dataaccess/vo/SfVolumeVO.java index 2710704..f1aede1 100644 --- a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/dataaccess/vo/SfVolumeVO.java +++ b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/dataaccess/vo/SfVolumeVO.java @@ -51,6 +51,9 @@ public class SfVolumeVO implements SfVolume { @Column(name = "name") private String name; + @Column(name = "iqn") + private String iqn; + @Column(name = "size") private long size; @@ -80,10 +83,11 @@ public class SfVolumeVO implements SfVolume { uuid = UUID.randomUUID().toString(); } - public SfVolumeVO(long sfId, String name, long size, long minIops, long maxIops, long burstIops, long sfVirtualNetworkId) { + public SfVolumeVO(long sfId, String name, String iqn, long size, long minIops, long maxIops, long burstIops, long sfVirtualNetworkId) { this.uuid = UUID.randomUUID().toString(); this.sfId = sfId; this.name = name; + this.iqn = iqn; this.size = size; this.minIops = minIops; this.maxIops = maxIops; @@ -111,6 +115,11 @@ public class SfVolumeVO implements SfVolume { return name; } + @Override + public String getIqn() { + return iqn; + } + public void setSize(long size) { this.size = size; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a3f47086/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/util/SolidFireConnection.java ---------------------------------------------------------------------- diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/util/SolidFireConnection.java b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/util/SolidFireConnection.java index 1161b41..813f6e2 100644 --- a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/util/SolidFireConnection.java +++ b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/util/SolidFireConnection.java @@ -22,9 +22,7 @@ import com.google.gson.GsonBuilder; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; import java.net.URI; -import java.net.URISyntaxException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; @@ -39,7 +37,6 @@ import org.apache.cloudstack.utils.security.SSLUtils; import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; @@ -47,11 +44,14 @@ import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.BasicClientConnectionManager; +import org.apache.log4j.Logger; import com.cloud.utils.exception.CloudRuntimeException; @SuppressWarnings("deprecation") public class SolidFireConnection { + private static final Logger s_logger = Logger.getLogger(SolidFireConnection.class.getName()); + private final String _managementVip; private final int _managementPort = 443; private final String _clusterAdminUsername; @@ -127,6 +127,28 @@ public class SolidFireConnection { } } + public SolidFireVolume getVolume(long lVolumeId) { + final Gson gson = new GsonBuilder().create(); + + VolumeToGet volumeToGet = new VolumeToGet(lVolumeId); + + String strVolumeToGetJson = gson.toJson(volumeToGet); + + String strVolumeGetResultJson = executeJsonRpc(strVolumeToGetJson); + + VolumeGetResult volumeGetResult = gson.fromJson(strVolumeGetResultJson, VolumeGetResult.class); + + verifyResult(volumeGetResult.result, strVolumeGetResultJson, gson); + + String strVolumeName = getVolumeName(volumeGetResult, lVolumeId); + String strVolumeIqn = getVolumeIqn(volumeGetResult, lVolumeId); + long lAccountId = getVolumeAccountId(volumeGetResult, lVolumeId); + String strVolumeStatus = getVolumeStatus(volumeGetResult, lVolumeId); + long lTotalSize = getVolumeTotalSize(volumeGetResult, lVolumeId); + + return new SolidFireVolume(lVolumeId, strVolumeName, strVolumeIqn, lAccountId, strVolumeStatus, lTotalSize); + } + public long createVolume(String name, long accountId, long totalSizeInGBs, long minIops, long maxIops, long burstIops) { final Gson gson = new GsonBuilder().create(); @@ -283,14 +305,10 @@ public class SolidFireConnection { }catch (IOException ex) { throw new CloudRuntimeException(ex.getMessage()); } - } catch (UnsupportedEncodingException ex) { - throw new CloudRuntimeException(ex.getMessage()); - } catch (ClientProtocolException ex) { - throw new CloudRuntimeException(ex.getMessage()); - } catch (IOException ex) { - throw new CloudRuntimeException(ex.getMessage()); - } catch (URISyntaxException ex) { - throw new CloudRuntimeException(ex.getMessage()); + } catch (Throwable t) { + s_logger.error(t.getMessage()); + + throw new CloudRuntimeException(t.getMessage()); } finally { if (httpClient != null) { try { @@ -308,6 +326,7 @@ public class SolidFireConnection { try { SSLContext sslContext = SSLUtils.getSSLContext(); + X509TrustManager tm = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { @@ -323,7 +342,7 @@ public class SolidFireConnection { } }; - sslContext.init(null, new TrustManager[] {tm}, new SecureRandom()); + sslContext.init(null, new TrustManager[] { tm }, new SecureRandom()); SSLSocketFactory socketFactory = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); SchemeRegistry registry = new SchemeRegistry(); @@ -335,13 +354,24 @@ public class SolidFireConnection { return new DefaultHttpClient(mgr, client.getParams()); } catch (NoSuchAlgorithmException ex) { + s_logger.error(ex.getMessage()); + throw new CloudRuntimeException(ex.getMessage()); } catch (KeyManagementException ex) { + s_logger.error(ex.getMessage()); + throw new CloudRuntimeException(ex.getMessage()); } finally { if (client != null) { - client.close(); + try { + client.close(); + } + catch (Throwable t) { + s_logger.error(t.getMessage()); + + throw t; + } } } } @@ -453,6 +483,29 @@ public class SolidFireConnection { } @SuppressWarnings("unused") + private static final class VolumeToGet + { + private final String method = "ListActiveVolumes"; + private final VolumeToGetParams params; + + private VolumeToGet(final long lVolumeId) + { + params = new VolumeToGetParams(lVolumeId); + } + + private static final class VolumeToGetParams + { + private final long startVolumeID; + private final long limit = 1; + + private VolumeToGetParams(final long lVolumeId) + { + startVolumeID = lVolumeId; + } + } + } + + @SuppressWarnings("unused") private static final class VolumeToCreate { private final String method = "CreateVolume"; private final VolumeToCreateParams params; @@ -642,6 +695,23 @@ public class SolidFireConnection { } } + private static final class VolumeGetResult { + private Result result; + + private static final class Result { + private Volume[] volumes; + + private static final class Volume { + private long volumeID; + private String name; + private String iqn; + private long accountID; + private String status; + private long totalSize; + } + } + } + private static final class VolumeCreateResult { private Result result; @@ -696,6 +766,83 @@ public class SolidFireConnection { throw new IllegalStateException("Problem with the following JSON: " + strJson); } + private static final String ACTIVE = "active"; + + public static class SolidFireVolume { + private final long _id; + private final String _name; + private final String _iqn; + private final long _accountId; + private final String _status; + private final long _totalSize; + + public SolidFireVolume(long id, String name, String iqn, + long accountId, String status, long totalSize) + { + _id = id; + _name = name; + _iqn = iqn; + _accountId = accountId; + _status = status; + _totalSize = totalSize; + } + + public long getId() { + return _id; + } + + public String getName() { + return _name; + } + + public String getIqn() { + return _iqn; + } + + public long getAccountId() { + return _accountId; + } + + public boolean isActive() { + return ACTIVE.equalsIgnoreCase(_status); + } + + public long getTotalSize() { + return _totalSize; + } + + @Override + public int hashCode() { + return _iqn.hashCode(); + } + + @Override + public String toString() { + return _name; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (!obj.getClass().equals(SolidFireVolume.class)) { + return false; + } + + SolidFireVolume sfv = (SolidFireVolume)obj; + + if (_id == sfv._id && _name.equals(sfv._name) && + _iqn.equals(sfv._iqn) && _accountId == sfv._accountId && + isActive() == sfv.isActive() && getTotalSize() == sfv.getTotalSize()) { + return true; + } + + return false; + } + } + public static class SolidFireAccount { private final long _id; @@ -761,4 +908,47 @@ public class SolidFireConnection { private static long convertGBsToBytes(long gbs) { return gbs * 1024 * 1024 * 1024; } + + private static String getVolumeName(VolumeGetResult volumeGetResult, long lVolumeId) { + if (volumeGetResult.result.volumes != null && volumeGetResult.result.volumes.length == 1 && volumeGetResult.result.volumes[0].volumeID == lVolumeId) { + return volumeGetResult.result.volumes[0].name; + } + + throw new CloudRuntimeException("Could not determine the name of the volume for volume ID of " + lVolumeId + "."); + } + + private static String getVolumeIqn(VolumeGetResult volumeGetResult, long lVolumeId) { + if (volumeGetResult.result.volumes != null && volumeGetResult.result.volumes.length == 1 && volumeGetResult.result.volumes[0].volumeID == lVolumeId) { + return volumeGetResult.result.volumes[0].iqn; + } + + throw new CloudRuntimeException("Could not determine the IQN of the volume for volume ID of " + lVolumeId + "."); + } + + private static long getVolumeAccountId(VolumeGetResult volumeGetResult, long lVolumeId) { + if (volumeGetResult.result.volumes != null && volumeGetResult.result.volumes.length == 1 && volumeGetResult.result.volumes[0].volumeID == lVolumeId) { + return volumeGetResult.result.volumes[0].accountID; + } + + throw new CloudRuntimeException("Could not determine the account ID of the volume for volume ID of " + lVolumeId + "."); + } + + private static String getVolumeStatus(VolumeGetResult volumeGetResult, long lVolumeId) { + if (volumeGetResult.result.volumes != null && volumeGetResult.result.volumes.length == 1 && volumeGetResult.result.volumes[0].volumeID == lVolumeId) { + return volumeGetResult.result.volumes[0].status; + } + + throw new CloudRuntimeException("Could not determine the status of the volume for volume ID of " + lVolumeId + "."); + } + + private static long getVolumeTotalSize(VolumeGetResult volumeGetResult, long lVolumeId) + { + if (volumeGetResult.result.volumes != null && volumeGetResult.result.volumes.length == 1 && + volumeGetResult.result.volumes[0].volumeID == lVolumeId) + { + return volumeGetResult.result.volumes[0].totalSize; + } + + throw new CloudRuntimeException("Could not determine the total size of the volume for volume ID of " + lVolumeId + "."); + } }