You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mt...@apache.org on 2015/10/14 20:09:41 UTC

[1/7] git commit: updated refs/heads/sf-plugins-a to 49ca3b4

Repository: cloudstack
Updated Branches:
  refs/heads/sf-plugins-a 5a33835d9 -> 49ca3b40a (forced update)


CLOUDSTACK-8848: ensure power state is up to date when handling missing VMs in powerReport

There 2 things which has been changed.

* We look on power_state_update_time instead of update_time. Didn't make sense to me at all to look at update_time.
* Due DB update optimisation, powerState will only be updated if < MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT. That is why we can not rely on these information unless we make sure these are up to date.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/30c70491
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/30c70491
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/30c70491

Branch: refs/heads/sf-plugins-a
Commit: 30c704915c882f8ac2ab551aa157d0b7a0bdb47f
Parents: f1f1fef
Author: Rene Moser <re...@apache.org>
Authored: Thu Sep 24 21:10:26 2015 +0200
Committer: Rene Moser <re...@apache.org>
Committed: Sun Oct 11 14:05:23 2015 +0200

----------------------------------------------------------------------
 .../src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java  | 9 ++++++++-
 engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java       | 2 ++
 engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java   | 6 ++++++
 3 files changed, 16 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30c70491/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
index d3dcdec..19ed71c 100644
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
@@ -111,7 +111,14 @@ public class VirtualMachinePowerStateSyncImpl implements VirtualMachinePowerStat
 
             for (VMInstanceVO instance : vmsThatAreMissingReport) {
 
-                Date vmStateUpdateTime = instance.getUpdateTime();
+                // Make sure powerState is up to date for missing VMs
+                if (!_instanceDao.isPowerStateUpToDate(instance.getId())) {
+                    s_logger.warn("Detected missing VM but power state is outdated, wait for another process report run for VM id: " + instance.getId());
+                    _instanceDao.resetVmPowerStateTracking(instance.getId());
+                    continue;
+                }
+
+                Date vmStateUpdateTime = instance.getPowerStateUpdateTime();
                 if (vmStateUpdateTime == null) {
                     s_logger.warn("VM state was updated but update time is null?! vm id: " + instance.getId());
                     vmStateUpdateTime = currentTime;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30c70491/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java b/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java
index 1d522dc..8d457fa 100644
--- a/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java
+++ b/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java
@@ -138,4 +138,6 @@ public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<
     HashMap<String, Long> countVgpuVMs(Long dcId, Long podId, Long clusterId);
 
     VMInstanceVO findVMByHostNameInZone(String hostName, long zoneId);
+
+    boolean isPowerStateUpToDate(long instanceId);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30c70491/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
index be0e366..48b56d1 100644
--- a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
+++ b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
@@ -804,6 +804,12 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
     }
 
     @Override
+    public boolean isPowerStateUpToDate(final long instanceId) {
+        VMInstanceVO instance = findById(instanceId);
+        return instance.getPowerStateUpdateCount() < MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT;
+    }
+
+    @Override
     public void resetVmPowerStateTracking(final long instanceId) {
         Transaction.execute(new TransactionCallbackNoReturn() {
             @Override


[6/7] git commit: updated refs/heads/sf-plugins-a to 49ca3b4

Posted by mt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/ListSolidFireVirtualNetworksCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/ListSolidFireVirtualNetworksCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/ListSolidFireVirtualNetworksCmd.java
new file mode 100644
index 0000000..c5ac3bf
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/ListSolidFireVirtualNetworksCmd.java
@@ -0,0 +1,114 @@
+// 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.api.command.user.solidfire;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.ResponseObject.ResponseView;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireVirtualNetworkResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfVirtualNetwork;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "listSolidFireVirtualNetworks", responseObject = ApiSolidFireVirtualNetworkResponse.class, description = "List SolidFire Virtual Networks",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class ListSolidFireVirtualNetworksCmd extends BaseListCmd {
+    private static final Logger s_logger = Logger.getLogger(ListSolidFireVirtualNetworksCmd.class.getName());
+    private static final String s_name = "listsolidfirevirtualnetworksresponse";
+
+    @Inject private SolidFireManager _solidFireManager;
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ApiSolidFireVirtualNetworkResponse.class, description = SfApiConstants.VIRTUAL_NETWORK_ID_DESC)
+    private Long _id;
+
+    @Parameter(name = SfApiConstants.CLUSTER_NAME, type = CommandType.STRING, description = SfApiConstants.SOLIDFIRE_CLUSTER_NAME_DESC)
+    private String _clusterName;
+
+    @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, description = SfApiConstants.ZONE_ID_DESC)
+    private Long _zoneId;
+
+    @Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = SfApiConstants.ACCOUNT_ID_DESC)
+    private Long _accountId;
+
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(ListSolidFireVirtualNetworksCmd.class.getName() + ".execute invoked");
+
+            final List<SfVirtualNetwork> sfVirtualNetworks;
+
+            if (_id != null) {
+                sfVirtualNetworks = new ArrayList<>();
+
+                SfVirtualNetwork sfVirtualNetwork = _solidFireManager.listSolidFireVirtualNetworkById(_id);
+
+                if (sfVirtualNetwork != null) {
+                    sfVirtualNetworks.add(sfVirtualNetwork);
+                }
+            }
+            else if (_clusterName != null) {
+                sfVirtualNetworks = _solidFireManager.listSolidFireVirtualNetworkByClusterName(_clusterName);
+            }
+            else {
+                sfVirtualNetworks = _solidFireManager.listSolidFireVirtualNetworks(_zoneId, _accountId);
+            }
+
+            ResponseView responseView = _sfUtil.isRootAdmin() ? ResponseView.Full : ResponseView.Restricted;
+
+            List<ApiSolidFireVirtualNetworkResponse> responses = _sfUtil.getApiSolidFireVirtualNetworkResponse(sfVirtualNetworks, responseView);
+
+            ListResponse<ApiSolidFireVirtualNetworkResponse> listReponse = new ListResponse<>();
+
+            listReponse.setResponses(responses);
+            listReponse.setResponseName(getCommandName());
+            listReponse.setObjectName("apilistsolidfirevirtualnetworks");
+
+            setResponseObject(listReponse);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/ListSolidFireVolumesCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/ListSolidFireVolumesCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/ListSolidFireVolumesCmd.java
new file mode 100644
index 0000000..33bb758
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/ListSolidFireVolumesCmd.java
@@ -0,0 +1,99 @@
+// 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.api.command.user.solidfire;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.ResponseObject.ResponseView;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireVolumeResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfVolume;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "listSolidFireVolumes", responseObject = ApiSolidFireVolumeResponse.class, description = "List SolidFire Volumes",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class ListSolidFireVolumesCmd extends BaseListCmd {
+    private static final Logger s_logger = Logger.getLogger(ListSolidFireVolumesCmd.class.getName());
+    private static final String s_name = "listsolidfirevolumesresponse";
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ApiSolidFireVolumeResponse.class, description = SfApiConstants.VOLUME_ID_DESC)
+    private Long _id;
+
+    @Inject private SolidFireManager _solidFireManager;
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(ListSolidFireVolumesCmd.class.getName() + ".execute invoked");
+
+            final List<SfVolume> sfVolumes;
+
+            if (_id != null) {
+                sfVolumes = new ArrayList<>();
+
+                SfVolume sfVolume = _solidFireManager.listSolidFireVolume(_id);
+
+                if (sfVolume != null) {
+                    sfVolumes.add(sfVolume);
+                }
+            }
+            else {
+                sfVolumes = _solidFireManager.listSolidFireVolumes();
+            }
+
+            ResponseView responseView = _sfUtil.isRootAdmin() ? ResponseView.Full : ResponseView.Restricted;
+
+            List<ApiSolidFireVolumeResponse> responses = _sfUtil.getApiSolidFireVolumeResponse(sfVolumes, responseView);
+
+            ListResponse<ApiSolidFireVolumeResponse> listReponse = new ListResponse<>();
+
+            listReponse.setResponses(responses);
+            listReponse.setResponseName(getCommandName());
+            listReponse.setObjectName("apilistsolidfirevolumes");
+
+            setResponseObject(listReponse);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/UpdateSolidFireVolumeCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/UpdateSolidFireVolumeCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/UpdateSolidFireVolumeCmd.java
new file mode 100644
index 0000000..6958619
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/UpdateSolidFireVolumeCmd.java
@@ -0,0 +1,108 @@
+// 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.api.command.user.solidfire;
+
+import com.cloud.user.Account;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.ResponseObject.ResponseView;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireVolumeResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfVirtualNetwork;
+import org.apache.cloudstack.solidfire.SfVolume;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "updateSolidFireVolume", responseObject = ApiSolidFireVolumeResponse.class, description = "Update SolidFire Volume",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class UpdateSolidFireVolumeCmd extends BaseCmd {
+    private static final Logger s_logger = Logger.getLogger(UpdateSolidFireVolumeCmd.class.getName());
+    private static final String s_name = "updatesolidfirevolumeresponse";
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ApiSolidFireVolumeResponse.class, description = SfApiConstants.VOLUME_ID_DESC, required = true)
+    private long _id;
+
+    @Parameter(name = ApiConstants.SIZE, type = CommandType.LONG, description = SfApiConstants.SIZE_DESC, required = true)
+    private long _size;
+
+    @Parameter(name = ApiConstants.MIN_IOPS, type = CommandType.LONG, description = SfApiConstants.MIN_IOPS_DESC, required = true)
+    private long _minIops;
+
+    @Parameter(name = ApiConstants.MAX_IOPS, type = CommandType.LONG, description = SfApiConstants.MAX_IOPS_DESC, required = true)
+    private long _maxIops;
+
+    @Parameter(name = SfApiConstants.BURST_IOPS, type = CommandType.LONG, description = SfApiConstants.BURST_IOPS_DESC, required = true)
+    private long _burstIops;
+
+    @Inject private SolidFireManager _solidFireManager;
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        SfVolume sfVolume = _entityMgr.findById(SfVolume.class, _id);
+
+        if (sfVolume != null) {
+            SfVirtualNetwork sfVirtualNetwork = _entityMgr.findById(SfVirtualNetwork.class, sfVolume.getSfVirtualNetworkId());
+
+            if (sfVirtualNetwork != null) {
+                sfVirtualNetwork.getAccountId();
+            }
+        }
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(UpdateSolidFireVolumeCmd.class.getName() + ".execute invoked");
+
+            SfVolume sfVolume = _solidFireManager.updateSolidFireVolume(_id, _size, _minIops, _maxIops, _burstIops);
+
+            ResponseView responseView = _sfUtil.isRootAdmin() ? ResponseView.Full : ResponseView.Restricted;
+
+            ApiSolidFireVolumeResponse response = _sfUtil.getApiSolidFireVolumeResponse(sfVolume, responseView);
+
+            response.setResponseName(getCommandName());
+            response.setObjectName("apiupdatesolidfirevolume");
+
+            setResponseObject(response);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireClusterResponse.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireClusterResponse.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireClusterResponse.java
new file mode 100644
index 0000000..5c6c688
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireClusterResponse.java
@@ -0,0 +1,161 @@
+// 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.api.response.solidfire;
+
+import com.cloud.serializer.Param;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfCluster;
+
+@EntityReference(value = SfCluster.class)
+public class ApiSolidFireClusterResponse extends BaseResponse {
+    @SerializedName("id")
+    @Param(description = "CloudStack ID")
+    private long _id;
+
+    @SerializedName("uuid")
+    @Param(description = "CloudStack UUID")
+    private String _uuid;
+
+    @SerializedName("name")
+    @Param(description = SfApiConstants.SOLIDFIRE_CLUSTER_NAME_DESC)
+    private String _name;
+
+    @SerializedName("mvip")
+    @Param(description = SfApiConstants.SOLIDFIRE_MVIP_DESC)
+    private String _mvip;
+
+    @SerializedName("username")
+    @Param(description = SfApiConstants.SOLIDFIRE_USERNAME_DESC)
+    private String _username;
+
+    @SerializedName("totalcapacity")
+    @Param(description = "SolidFire cluster total capacity for CloudStack (in GBs)")
+    private long _totalCapacity;
+
+    @SerializedName("totalminiops")
+    @Param(description = "SolidFire cluster total minimum IOPS for CloudStack")
+    private long _totalMinIops;
+
+    @SerializedName("totalmaxiops")
+    @Param(description = "SolidFire cluster total maximum IOPS for CloudStack")
+    private long _totalMaxIops;
+
+    @SerializedName("totalburstiops")
+    @Param(description = "SolidFire cluster total burst IOPS for CloudStack")
+    private long _totalBurstIops;
+
+    @SerializedName("zoneid")
+    @Param(description = "Zone ID that the SolidFire cluster is associated with")
+    private long _zoneId;
+
+    @SerializedName("zonename")
+    @Param(description = "Zone name that the SolidFire cluster is associated with")
+    private String _zoneName;
+
+    public void setId(long id) {
+        _id = id;
+    }
+
+    public long getId() {
+        return _id;
+    }
+
+    public void setUuid(String uuid) {
+        _uuid = uuid;
+    }
+
+    public String getUuid() {
+        return _uuid;
+    }
+
+    public void setName(String name) {
+        _name = name;
+    }
+
+    public String getName() {
+        return _name;
+    }
+
+    public void setMvip(String mvip) {
+        _mvip = mvip;
+    }
+
+    public String getMvip() {
+        return _mvip;
+    }
+
+    public void setUsername(String username) {
+        _username = username;
+    }
+
+    public String getUsername() {
+        return _username;
+    }
+
+    public void setTotalCapacity(long totalCapacity) {
+        _totalCapacity = totalCapacity;
+    }
+
+    public long getTotalCapacity() {
+        return _totalCapacity;
+    }
+
+    public void setTotalMinIops(long totalMinIops) {
+        _totalMinIops = totalMinIops;
+    }
+
+    public long getTotalMinIops() {
+        return _totalMinIops;
+    }
+
+    public void setTotalMaxIops(long totalMaxIops) {
+        _totalMaxIops = totalMaxIops;
+    }
+
+    public long getTotalMaxIops() {
+        return _totalMaxIops;
+    }
+
+    public void setTotalBurstIops(long totalBurstIops) {
+        _totalBurstIops = totalBurstIops;
+    }
+
+    public long getTotalBurstIops() {
+        return _totalBurstIops;
+    }
+
+    public void setZoneId(long zoneId) {
+        _zoneId = zoneId;
+    }
+
+    public long getZoneId() {
+        return _zoneId;
+    }
+
+    public void setZoneName(String zoneName) {
+        _zoneName = zoneName;
+    }
+
+    public String getZoneName() {
+        return _zoneName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireVirtualNetworkResponse.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireVirtualNetworkResponse.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireVirtualNetworkResponse.java
new file mode 100644
index 0000000..b47cae0
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireVirtualNetworkResponse.java
@@ -0,0 +1,209 @@
+// 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.api.response.solidfire;
+
+import com.cloud.serializer.Param;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfVirtualNetwork;
+
+@EntityReference(value = SfVirtualNetwork.class)
+public class ApiSolidFireVirtualNetworkResponse extends BaseResponse {
+    @SerializedName("id")
+    @Param(description = "CloudStack ID")
+    private long _id;
+
+    @SerializedName("uuid")
+    @Param(description = "CloudStack UUID")
+    private String _uuid;
+
+    @SerializedName("name")
+    @Param(description = SfApiConstants.VIRTUAL_NETWORK_NAME_DESC)
+    private String _name;
+
+    @SerializedName("tag")
+    @Param(description = SfApiConstants.VIRTUAL_NETWORK_TAG_DESC)
+    private String _tag;
+
+    @SerializedName("startip")
+    @Param(description = SfApiConstants.START_IP_ADDRESS_DESC)
+    private String _startIp;
+
+    @SerializedName("size")
+    @Param(description = SfApiConstants.SIZE_DESC)
+    private int _size;
+
+    @SerializedName("netmask")
+    @Param(description = SfApiConstants.NETMASK_DESC)
+    private String _netmask;
+
+    @SerializedName("svip")
+    @Param(description = SfApiConstants.SOLIDFIRE_SVIP_DESC)
+    private String _svip;
+
+    @SerializedName("accountid")
+    @Param(description = "ID of the account the VLAN is associated with")
+    private long _accountId;
+
+    @SerializedName("accountuuid")
+    @Param(description = "UUID of the account the VLAN is associated with")
+    private String _accountUuid;
+
+    @SerializedName("accountname")
+    @Param(description = "Name of the account the volume is associated with")
+    private String _accountName;
+
+    @SerializedName("zoneid")
+    @Param(description = "ID of the zone the VLAN is associated with")
+    private long _zoneId;
+
+    @SerializedName("zoneuuid")
+    @Param(description = "UUID of the zone the VLAN is associated with")
+    private String _zoneUuid;
+
+    @SerializedName("zonename")
+    @Param(description = "Name of the zone the volume is associated with")
+    private String _zoneName;
+
+    @SerializedName("clustername")
+    @Param(description = "Name of cluster the VLAN belongs to")
+    private String _clusterName;
+
+    public void setId(long id) {
+        _id = id;
+    }
+
+    public long getId() {
+        return _id;
+    }
+
+    public void setUuid(String uuid) {
+        _uuid = uuid;
+    }
+
+    public String getUuid() {
+        return _uuid;
+    }
+
+    public void setName(String name) {
+        _name = name;
+    }
+
+    public String getName() {
+        return _name;
+    }
+
+    public void setTag(String tag) {
+        _tag = tag;
+    }
+
+    public String getTag() {
+        return _tag;
+    }
+
+    public void setStartIp(String startIp) {
+        _startIp = startIp;
+    }
+
+    public String getStartIp() {
+        return _startIp;
+    }
+
+    public void setSize(int size) {
+        _size = size;
+    }
+
+    public int getSize() {
+        return _size;
+    }
+
+    public void setNetmask(String netmask) {
+        _netmask = netmask;
+    }
+
+    public String getNetmask() {
+        return _netmask;
+    }
+
+    public void setSvip(String svip) {
+        _svip = svip;
+    }
+
+    public String getSvip() {
+        return _svip;
+    }
+
+    public void setAccountId(long accountId) {
+        _accountId = accountId;
+    }
+
+    public long getAccountId() {
+        return _accountId;
+    }
+
+    public void setAccountUuid(String accountUuid) {
+        _accountUuid = accountUuid;
+    }
+
+    public String getAccountUuid() {
+        return _accountUuid;
+    }
+
+    public void setAccountName(String accountName) {
+        _accountName = accountName;
+    }
+
+    public String getAccountName() {
+        return _accountName;
+    }
+
+    public void setZoneId(long zoneId) {
+        _zoneId = zoneId;
+    }
+
+    public long getZoneId() {
+        return _zoneId;
+    }
+
+    public void setZoneUuid(String zoneUuid) {
+        _zoneUuid = zoneUuid;
+    }
+
+    public String getZoneUuid() {
+        return _zoneUuid;
+    }
+
+    public void setZoneName(String zoneName) {
+        _zoneName = zoneName;
+    }
+
+    public String getZoneName() {
+        return _zoneName;
+    }
+
+    public void setClusterName(String clusterName) {
+        _clusterName = clusterName;
+    }
+
+    public String getClusterName() {
+        return _clusterName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireVolumeResponse.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireVolumeResponse.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireVolumeResponse.java
new file mode 100644
index 0000000..d6e6029
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/response/solidfire/ApiSolidFireVolumeResponse.java
@@ -0,0 +1,320 @@
+// 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.api.response.solidfire;
+
+import java.util.Date;
+
+import com.cloud.serializer.Param;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfVolume;
+
+@EntityReference(value = SfVolume.class)
+public class ApiSolidFireVolumeResponse extends BaseResponse {
+    @SerializedName("id")
+    @Param(description = "CloudStack ID")
+    private long _id;
+
+    @SerializedName("uuid")
+    @Param(description = "CloudStack UUID")
+    private String _uuid;
+
+    @SerializedName("name")
+    @Param(description = SfApiConstants.VOLUME_NAME_DESC)
+    private String _name;
+
+    @SerializedName("iqn")
+    @Param(description = SfApiConstants.IQN_DESC)
+    private String _iqn;
+
+    @SerializedName("size")
+    @Param(description = SfApiConstants.SIZE_DESC)
+    private long _size;
+
+    @SerializedName("miniops")
+    @Param(description = SfApiConstants.MIN_IOPS_DESC)
+    private long _minIops;
+
+    @SerializedName("maxiops")
+    @Param(description = SfApiConstants.MAX_IOPS_DESC)
+    private long _maxIops;
+
+    @SerializedName("burstiops")
+    @Param(description = SfApiConstants.BURST_IOPS_DESC)
+    private long _burstIops;
+
+    @SerializedName("accountid")
+    @Param(description = "ID of the account the volume is associated with")
+    private long _accountId;
+
+    @SerializedName("accountuuid")
+    @Param(description = "UUID of the account the volume is associated with")
+    private String _accountUuid;
+
+    @SerializedName("accountname")
+    @Param(description = "Name of the account the volume is associated with")
+    private String _accountName;
+
+    @SerializedName("vlanid")
+    @Param(description = "ID of the VLAN the volume is associated with")
+    private long _vlanId;
+
+    @SerializedName("vlanuuid")
+    @Param(description = "UUID of the VLAN the volume is associated with")
+    private String _vlanUuid;
+
+    @SerializedName("vlanname")
+    @Param(description = "Name of the VLAN the volume is associated with")
+    private String _vlanName;
+
+    @SerializedName("zoneid")
+    @Param(description = "ID of the zone the volume is associated with")
+    private long _zoneId;
+
+    @SerializedName("zoneuuid")
+    @Param(description = "UUID of the zone the volume is associated with")
+    private String _zoneUuid;
+
+    @SerializedName("zonename")
+    @Param(description = "Name of the zone the volume is associated with")
+    private String _zoneName;
+
+    @SerializedName("clustername")
+    @Param(description = "Name of cluster the volume belongs to")
+    private String _clusterName;
+
+    @SerializedName("targetportal")
+    @Param(description = "Target portal")
+    private String _targetPortal;
+
+    @SerializedName("chapinitiatorusername")
+    @Param(description = "CHAP initiator username")
+    private String _chapInitiatorUsername;
+
+    @SerializedName("chapinitiatorsecret")
+    @Param(description = "CHAP initiator secret")
+    private String _chapInitiatorSecret;
+
+    @SerializedName("chaptargetusername")
+    @Param(description = "CHAP target username")
+    private String _chapTargetUsername;
+
+    @SerializedName("chaptargetsecret")
+    @Param(description = "CHAP target secret")
+    private String _chapTargetSecret;
+
+    @SerializedName(ApiConstants.CREATED)
+    @Param(description = "Date volume was created")
+    private Date _created;
+
+    public void setId(long id) {
+        _id = id;
+    }
+
+    public long getId() {
+        return _id;
+    }
+
+    public void setUuid(String uuid) {
+        _uuid = uuid;
+    }
+
+    public String getUuid() {
+        return _uuid;
+    }
+
+    public void setName(String name) {
+        _name = name;
+    }
+
+    public String getName() {
+        return _name;
+    }
+
+    public void setIqn(String iqn) {
+        _iqn = iqn;
+    }
+
+    public String getIqn() {
+        return _iqn;
+    }
+
+    public void setSize(long size) {
+        _size = size;
+    }
+
+    public long getSize() {
+        return _size;
+    }
+
+    public void setMinIops(long minIops) {
+        _minIops = minIops;
+    }
+
+    public long getMinIops() {
+        return _minIops;
+    }
+
+    public void setMaxIops(long maxIops) {
+        _maxIops = maxIops;
+    }
+
+    public long getMaxIops() {
+        return _maxIops;
+    }
+
+    public void setBurstIops(long burstIops) {
+        _burstIops = burstIops;
+    }
+
+    public long getBurstIops() {
+        return _burstIops;
+    }
+
+    public void setAccountId(long accountId) {
+        _accountId = accountId;
+    }
+
+    public long getAccountId() {
+        return _accountId;
+    }
+
+    public void setAccountUuid(String accountUuid) {
+        _accountUuid = accountUuid;
+    }
+
+    public String getAccountUuid() {
+        return _accountUuid;
+    }
+
+    public void setAccountName(String accountName) {
+        _accountName = accountName;
+    }
+
+    public String getAccountName() {
+        return _accountName;
+    }
+
+    public void setVlanId(long vlanId) {
+        _vlanId = vlanId;
+    }
+
+    public long getVlanId() {
+        return _vlanId;
+    }
+
+    public void setVlanUuid(String vlanUuid) {
+        _vlanUuid = vlanUuid;
+    }
+
+    public String getVlanUuid() {
+        return _vlanUuid;
+    }
+
+    public void setVlanName(String vlanName) {
+        _vlanName = vlanName;
+    }
+
+    public String getVlanName() {
+        return _vlanName;
+    }
+
+    public void setZoneId(long zoneId) {
+        _zoneId = zoneId;
+    }
+
+    public long getZoneId() {
+        return _zoneId;
+    }
+
+    public void setZoneUuid(String zoneUuid) {
+        _zoneUuid = zoneUuid;
+    }
+
+    public String getZoneUuid() {
+        return _zoneUuid;
+    }
+
+    public void setZoneName(String zoneName) {
+        _zoneName = zoneName;
+    }
+
+    public String getZoneName() {
+        return _zoneName;
+    }
+
+    public void setClusterName(String clusterName) {
+        _clusterName = clusterName;
+    }
+
+    public String getClusterName() {
+        return _clusterName;
+    }
+
+    public void setTargetPortal(String targetPortal) {
+        _targetPortal = targetPortal;
+    }
+
+    public String getTargetPortal() {
+        return _targetPortal;
+    }
+
+    public void setChapInitiatorUsername(String chapInitiatorUsername) {
+        _chapInitiatorUsername = chapInitiatorUsername;
+    }
+
+    public String getChapInitiatorUsername() {
+        return _chapInitiatorUsername;
+    }
+
+    public void setChapInitiatorSecret(String chapInitiatorSecret) {
+        _chapInitiatorSecret = chapInitiatorSecret;
+    }
+
+    public String getChapInitiatorSecret() {
+        return _chapInitiatorSecret;
+    }
+
+    public void setChapTargetUsername(String chapTargetUsername) {
+        _chapTargetUsername = chapTargetUsername;
+    }
+
+    public String getTargetInitiatorUsername() {
+        return _chapTargetUsername;
+    }
+
+    public void setChapTargetSecret(String chapTargetSecret) {
+        _chapTargetSecret = chapTargetSecret;
+    }
+
+    public String getTargetInitiatorSecret() {
+        return _chapTargetSecret;
+    }
+
+    public void setCreated(Date created) {
+        _created = created;
+    }
+
+    public Date getCreated() {
+        return _created;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/ApiSolidFireService.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/ApiSolidFireService.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/ApiSolidFireService.java
new file mode 100644
index 0000000..5715c01
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/ApiSolidFireService.java
@@ -0,0 +1,6 @@
+package org.apache.cloudstack.api.solidfire;
+
+import com.cloud.utils.component.PluggableService;
+
+public interface ApiSolidFireService extends PluggableService {
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/ApiSolidFireServiceImpl.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/ApiSolidFireServiceImpl.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/ApiSolidFireServiceImpl.java
new file mode 100644
index 0000000..9d33fcf
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/ApiSolidFireServiceImpl.java
@@ -0,0 +1,45 @@
+package org.apache.cloudstack.api.solidfire;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cloudstack.api.command.admin.solidfire.CreateReferenceToSolidFireClusterCmd;
+import org.apache.cloudstack.api.command.admin.solidfire.CreateSolidFireVirtualNetworkCmd;
+import org.apache.cloudstack.api.command.admin.solidfire.DeleteReferenceToSolidFireClusterCmd;
+import org.apache.cloudstack.api.command.admin.solidfire.DeleteSolidFireVirtualNetworkCmd;
+import org.apache.cloudstack.api.command.admin.solidfire.ListSolidFireClustersCmd;
+import org.apache.cloudstack.api.command.admin.solidfire.UpdateReferenceToSolidFireClusterCmd;
+import org.apache.cloudstack.api.command.admin.solidfire.UpdateSolidFireVirtualNetworkCmd;
+import org.apache.cloudstack.api.command.user.solidfire.CreateSolidFireVolumeCmd;
+import org.apache.cloudstack.api.command.user.solidfire.DeleteSolidFireVolumeCmd;
+import org.apache.cloudstack.api.command.user.solidfire.ListSolidFireVirtualNetworksCmd;
+import org.apache.cloudstack.api.command.user.solidfire.ListSolidFireVolumesCmd;
+import org.apache.cloudstack.api.command.user.solidfire.UpdateSolidFireVolumeCmd;
+import org.springframework.stereotype.Component;
+
+import com.cloud.utils.component.AdapterBase;
+
+@Component
+public class ApiSolidFireServiceImpl extends AdapterBase implements ApiSolidFireService {
+    @Override
+    public List<Class<?>> getCommands() {
+        List<Class<?>> cmdList = new ArrayList<Class<?>>();
+
+        cmdList.add(ListSolidFireClustersCmd.class);
+        cmdList.add(CreateReferenceToSolidFireClusterCmd.class);
+        cmdList.add(UpdateReferenceToSolidFireClusterCmd.class);
+        cmdList.add(DeleteReferenceToSolidFireClusterCmd.class);
+
+        cmdList.add(ListSolidFireVirtualNetworksCmd.class);
+        cmdList.add(CreateSolidFireVirtualNetworkCmd.class);
+        cmdList.add(UpdateSolidFireVirtualNetworkCmd.class);
+        cmdList.add(DeleteSolidFireVirtualNetworkCmd.class);
+
+        cmdList.add(ListSolidFireVolumesCmd.class);
+        cmdList.add(CreateSolidFireVolumeCmd.class);
+        cmdList.add(UpdateSolidFireVolumeCmd.class);
+        cmdList.add(DeleteSolidFireVolumeCmd.class);
+
+        return cmdList;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/SfApiConstants.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/SfApiConstants.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/SfApiConstants.java
new file mode 100644
index 0000000..193361c
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/solidfire/SfApiConstants.java
@@ -0,0 +1,44 @@
+package org.apache.cloudstack.api.solidfire;
+
+public class SfApiConstants {
+    public static final String MVIP = "mvip";
+    public static final String SVIP = "svip";
+    public static final String CLUSTER_NAME = "clustername";
+    public static final String NAME = "name";
+    public static final String TAG = "tag";
+    public static final String START_IP = "startip";
+    public static final String SIZE = "size";
+    public static final String NETMASK = "netmask";
+    public static final String TOTAL_CAPACITY = "totalcapacity";
+    public static final String TOTAL_MIN_IOPS = "totalminiops";
+    public static final String TOTAL_MAX_IOPS = "totalmaxiops";
+    public static final String TOTAL_BURST_IOPS = "totalburstiops";
+    public static final String BURST_IOPS = "burstiops";
+    public static final String SF_VIRTUAL_NETWORK_ID = "sfvirtualnetworkid";
+
+    // descriptions
+    public static final String SOLIDFIRE_CLUSTER_NAME_DESC = "SolidFire cluster name";
+    public static final String SOLIDFIRE_MVIP_DESC = "SolidFire management virtual IP address";
+    public static final String SOLIDFIRE_SVIP_DESC = "SolidFire storage virtual IP address for VLAN";
+    public static final String SOLIDFIRE_USERNAME_DESC = "SolidFire cluster admin username";
+    public static final String SOLIDFIRE_PASSWORD_DESC = "SolidFire cluster admin password";
+    public static final String TOTAL_CAPACITY_DESC = "Total capacity (in GBs)";
+    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";
+    public static final String BURST_IOPS_DESC = "Burst IOPS";
+    public static final String VIRTUAL_NETWORK_NAME_DESC = "VLAN name";
+    public static final String VIRTUAL_NETWORK_TAG_DESC = "VLAN tag";
+    public static final String START_IP_ADDRESS_DESC = "Start IP address";
+    public static final String NUMBER_OF_IP_ADDRESSES_DESC = "Number of contiguous IP addresses starting at '" + SfApiConstants.START_IP + "'";
+    public static final String NETMASK_DESC = "Netmask of VLAN";
+    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 = "Volume name";
+    public static final String ZONE_ID_DESC = "Zone ID";
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfClusterDao.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfClusterDao.java b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfClusterDao.java
new file mode 100644
index 0000000..a2537be
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfClusterDao.java
@@ -0,0 +1,29 @@
+// 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.dataaccess.dao.solidfire;
+
+import java.util.List;
+
+import org.apache.cloudstack.dataaccess.vo.solidfire.SfClusterVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface SfClusterDao extends GenericDao<SfClusterVO, Long> {
+    SfClusterVO findByName(String name);
+
+    List<SfClusterVO> findByZoneId(long zoneId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfClusterDaoImpl.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfClusterDaoImpl.java b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfClusterDaoImpl.java
new file mode 100644
index 0000000..f4db610
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfClusterDaoImpl.java
@@ -0,0 +1,62 @@
+// 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.dataaccess.dao.solidfire;
+
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.apache.cloudstack.dataaccess.vo.solidfire.SfClusterVO;
+import org.springframework.stereotype.Component;
+
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+
+@Component
+@Local(value = SfClusterVO.class)
+public class SfClusterDaoImpl extends GenericDaoBase<SfClusterVO, Long> implements SfClusterDao {
+    @SuppressWarnings("deprecation")
+    @Override
+    @DB()
+    public SfClusterVO findByName(final String name) {
+        SearchCriteria<SfClusterVO> sc = createSearchCriteria();
+
+        sc.addAnd("name", SearchCriteria.Op.EQ, name);
+
+        return findOneBy(sc);
+    }
+
+    @Override
+    public List<SfClusterVO> findByZoneId(long zoneId) {
+        String columnName = "zoneId";
+
+        SearchBuilder<SfClusterVO> searchBuilder = createSearchBuilder();
+
+        searchBuilder.and(columnName, searchBuilder.entity().getZoneId(), Op.EQ);
+
+        searchBuilder.done();
+
+        SearchCriteria<SfClusterVO> sc = searchBuilder.create();
+
+        sc.setParameters(columnName, zoneId);
+
+        return listBy(sc);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVirtualNetworkDao.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVirtualNetworkDao.java b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVirtualNetworkDao.java
new file mode 100644
index 0000000..3a3a2a6
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVirtualNetworkDao.java
@@ -0,0 +1,29 @@
+// 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.dataaccess.dao.solidfire;
+
+import java.util.List;
+
+import org.apache.cloudstack.dataaccess.vo.solidfire.SfVirtualNetworkVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface SfVirtualNetworkDao extends GenericDao<SfVirtualNetworkVO, Long> {
+    List<SfVirtualNetworkVO> findByClusterId(long clusterId);
+
+    List<SfVirtualNetworkVO> findByAccountId(long accountId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVirtualNetworkDaoImpl.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVirtualNetworkDaoImpl.java b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVirtualNetworkDaoImpl.java
new file mode 100644
index 0000000..56bd5b9
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVirtualNetworkDaoImpl.java
@@ -0,0 +1,67 @@
+// 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.dataaccess.dao.solidfire;
+
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.apache.cloudstack.dataaccess.vo.solidfire.SfVirtualNetworkVO;
+import org.springframework.stereotype.Component;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+
+@Component
+@Local(value = SfVirtualNetworkVO.class)
+public class SfVirtualNetworkDaoImpl extends GenericDaoBase<SfVirtualNetworkVO, Long> implements SfVirtualNetworkDao {
+    @Override
+    public List<SfVirtualNetworkVO> findByClusterId(long clusterId) {
+        String columnName = "sf_cluster_id";
+
+        SearchBuilder<SfVirtualNetworkVO> searchBuilder = createSearchBuilder();
+
+        searchBuilder.and(columnName, searchBuilder.entity().getSfClusterId(), Op.EQ);
+
+        searchBuilder.done();
+
+        SearchCriteria<SfVirtualNetworkVO> sc = searchBuilder.create();
+
+        sc.setParameters(columnName, clusterId);
+
+        return listBy(sc);
+    }
+
+    @Override
+    public List<SfVirtualNetworkVO> findByAccountId(long accountId) {
+        String columnName = "account_id";
+
+        SearchBuilder<SfVirtualNetworkVO> searchBuilder = createSearchBuilder();
+
+        searchBuilder.and(columnName, searchBuilder.entity().getAccountId(), Op.EQ);
+
+        searchBuilder.done();
+
+        SearchCriteria<SfVirtualNetworkVO> sc = searchBuilder.create();
+
+        sc.setParameters(columnName, accountId);
+
+        return listBy(sc);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVolumeDao.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVolumeDao.java b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVolumeDao.java
new file mode 100644
index 0000000..10a58ef
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVolumeDao.java
@@ -0,0 +1,27 @@
+// 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.dataaccess.dao.solidfire;
+
+import java.util.List;
+
+import org.apache.cloudstack.dataaccess.vo.solidfire.SfVolumeVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface SfVolumeDao extends GenericDao<SfVolumeVO, Long> {
+    List<SfVolumeVO> findBySfVirtualNetworkId(long sfVirtualNetworkId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVolumeDaoImpl.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVolumeDaoImpl.java b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVolumeDaoImpl.java
new file mode 100644
index 0000000..23824a3
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/dao/solidfire/SfVolumeDaoImpl.java
@@ -0,0 +1,50 @@
+// 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.dataaccess.dao.solidfire;
+
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.apache.cloudstack.dataaccess.vo.solidfire.SfVolumeVO;
+import org.springframework.stereotype.Component;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+
+@Component
+@Local(value = SfVolumeVO.class)
+public class SfVolumeDaoImpl extends GenericDaoBase<SfVolumeVO, Long> implements SfVolumeDao {
+    @Override
+    public List<SfVolumeVO> findBySfVirtualNetworkId(long sfVirtualNetworkId) {
+        String columnName = "sf_virtual_network_id";
+
+        SearchBuilder<SfVolumeVO> searchBuilder = createSearchBuilder();
+
+        searchBuilder.and(columnName, searchBuilder.entity().getSfVirtualNetworkId(), Op.EQ);
+
+        searchBuilder.done();
+
+        SearchCriteria<SfVolumeVO> sc = searchBuilder.create();
+
+        sc.setParameters(columnName, sfVirtualNetworkId);
+
+        return listBy(sc);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfClusterVO.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfClusterVO.java b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfClusterVO.java
new file mode 100644
index 0000000..ca5bb60
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfClusterVO.java
@@ -0,0 +1,173 @@
+// 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.dataaccess.vo.solidfire;
+
+import java.util.Date;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.apache.cloudstack.solidfire.SfCluster;
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = "sf_cluster")
+public class SfClusterVO implements SfCluster {
+    private static final long serialVersionUID = 1;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private long id;
+
+    @Column(name = "uuid")
+    private String uuid;
+
+    @Column(name = "name")
+    private String name;
+
+    @Column(name = "mvip")
+    private String mvip;
+
+    @Column(name = "username")
+    private String username;
+
+    @Column(name = "password")
+    private String password;
+
+    @Column(name = "total_capacity")
+    private long totalCapacity;
+
+    @Column(name = "total_min_iops")
+    private long totalMinIops;
+
+    @Column(name = "total_max_iops")
+    private long totalMaxIops;
+
+    @Column(name = "total_burst_iops")
+    private long totalBurstIops;
+
+    @Column(name = "zone_id")
+    private long zoneId;
+
+    @Column(name = GenericDao.CREATED_COLUMN)
+    private Date created;
+
+    @Column(name = "updated")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date updated;
+
+    @Column(name = GenericDao.REMOVED_COLUMN)
+    private Date removed;
+
+    public SfClusterVO() {
+        uuid = UUID.randomUUID().toString();
+    }
+
+    public SfClusterVO(String name, String mvip, String username, String password, long totalCapacity,
+            long totalMinIops, long totalMaxIops, long totalBurstIops,long zoneId) {
+        this.uuid = UUID.randomUUID().toString();
+        this.name = name;
+        this.mvip = mvip;
+        this.username = username;
+        this.password = password;
+        this.totalCapacity = totalCapacity;
+        this.totalMinIops = totalMinIops;
+        this.totalMaxIops = totalMaxIops;
+        this.totalBurstIops = totalBurstIops;
+        this.zoneId = zoneId;
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+
+    @Override
+    public String getUuid() {
+        return uuid;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getMvip() {
+        return mvip;
+    }
+
+    @Override
+    public String getUsername() {
+        return username;
+    }
+
+    @Override
+    public String getPassword() {
+        return password;
+    }
+
+    public void setTotalCapacity(long totalCapacity) {
+        this.totalCapacity = totalCapacity;
+    }
+
+    @Override
+    public long getTotalCapacity() {
+        return totalCapacity;
+    }
+
+    public void setTotalMinIops(long totalMinIops) {
+        this.totalMinIops = totalMinIops;
+    }
+
+    @Override
+    public long getTotalMinIops() {
+        return totalMinIops;
+    }
+
+    public void setTotalMaxIops(long totalMaxIops) {
+        this.totalMaxIops = totalMaxIops;
+    }
+
+    @Override
+    public long getTotalMaxIops() {
+        return totalMaxIops;
+    }
+
+    public void setTotalBurstIops(long totalBurstIops) {
+        this.totalBurstIops = totalBurstIops;
+    }
+
+    @Override
+    public long getTotalBurstIops() {
+        return totalBurstIops;
+    }
+
+    @Override
+    public long getZoneId() {
+        return zoneId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfVirtualNetworkVO.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfVirtualNetworkVO.java b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfVirtualNetworkVO.java
new file mode 100644
index 0000000..2f0fb02
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfVirtualNetworkVO.java
@@ -0,0 +1,180 @@
+// 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.dataaccess.vo.solidfire;
+
+import java.util.Date;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.apache.cloudstack.solidfire.SfVirtualNetwork;
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = "sf_virtual_network")
+public class SfVirtualNetworkVO implements SfVirtualNetwork {
+    private static final long serialVersionUID = 1;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private long id;
+
+    @Column(name = "uuid")
+    private String uuid;
+
+    @Column(name = "sf_id")
+    private long sfId;
+
+    @Column(name = "name")
+    private String name;
+
+    @Column(name = "tag")
+    private String tag;
+
+    @Column(name = "start_ip")
+    private String startIp;
+
+    @Column(name = "size")
+    private int size;
+
+    @Column(name = "netmask")
+    private String netmask;
+
+    @Column(name = "svip")
+    private String svip;
+
+    @Column(name = "account_id")
+    private long accountId;
+
+    @Column(name = "sf_cluster_id")
+    private long sfClusterId;
+
+    @Column(name = GenericDao.CREATED_COLUMN)
+    private Date created;
+
+    @Column(name = "updated")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date updated;
+
+    @Column(name = GenericDao.REMOVED_COLUMN)
+    private Date removed;
+
+    public SfVirtualNetworkVO() {
+        uuid = UUID.randomUUID().toString();
+    }
+
+    public SfVirtualNetworkVO(long sfId, String name, String tag, String startIp, int size, String netmask, String svip, long accountId, long sfClusterId) {
+        this.uuid = UUID.randomUUID().toString();
+        this.sfId = sfId;
+        this.name = name;
+        this.tag = tag;
+        this.startIp = startIp;
+        this.size = size;
+        this.netmask = netmask;
+        this.svip = svip;
+        this.accountId = accountId;
+        this.sfClusterId = sfClusterId;
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+
+    @Override
+    public String getUuid() {
+        return uuid;
+    }
+
+    @Override
+    public long getSfId() {
+        return sfId;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    public void setTag(String tag) {
+        this.tag = tag;
+    }
+
+    @Override
+    public String getTag() {
+        return tag;
+    }
+
+    public void setStartIp(String startIp) {
+        this.startIp = startIp;
+    }
+
+    @Override
+    public String getStartIp() {
+        return startIp;
+    }
+
+    public void setSize(int size) {
+        this.size = size;
+    }
+
+    @Override
+    public int getSize() {
+        return size;
+    }
+
+    public void setNetmask(String netmask) {
+        this.netmask = netmask;
+    }
+
+    @Override
+    public String getNetmask() {
+        return netmask;
+    }
+
+    public void setSvip(String svip) {
+        this.svip = svip;
+    }
+
+    @Override
+    public String getSvip() {
+        return svip;
+    }
+
+    @Override
+    public long getAccountId() {
+        return accountId;
+    }
+
+    @Override
+    public long getSfClusterId() {
+        return sfClusterId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfVolumeVO.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfVolumeVO.java b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfVolumeVO.java
new file mode 100644
index 0000000..0fe748e
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/dataaccess/vo/solidfire/SfVolumeVO.java
@@ -0,0 +1,168 @@
+// 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.dataaccess.vo.solidfire;
+
+import java.util.Date;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.apache.cloudstack.solidfire.SfVolume;
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = "sf_volume")
+public class SfVolumeVO implements SfVolume {
+    private static final long serialVersionUID = 1;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private long id;
+
+    @Column(name = "uuid")
+    private String uuid;
+
+    @Column(name = "sf_id")
+    private long sfId;
+
+    @Column(name = "name")
+    private String name;
+
+    @Column(name = "iqn")
+    private String iqn;
+
+    @Column(name = "size")
+    private long size;
+
+    @Column(name = "min_iops")
+    private long minIops;
+
+    @Column(name = "max_iops")
+    private long maxIops;
+
+    @Column(name = "burst_iops")
+    private long burstIops;
+
+    @Column(name = "sf_virtual_network_id")
+    private long sfVirtualNetworkId;
+
+    @Column(name = GenericDao.CREATED_COLUMN)
+    private Date created;
+
+    @Column(name = "updated")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date updated;
+
+    @Column(name = GenericDao.REMOVED_COLUMN)
+    private Date removed;
+
+    public SfVolumeVO() {
+        uuid = UUID.randomUUID().toString();
+    }
+
+    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;
+        this.burstIops = burstIops;
+        this.sfVirtualNetworkId = sfVirtualNetworkId;
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+
+    @Override
+    public String getUuid() {
+        return uuid;
+    }
+
+    @Override
+    public long getSfId() {
+        return sfId;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getIqn() {
+        return iqn;
+    }
+
+    public void setSize(long size) {
+        this.size = size;
+    }
+
+    @Override
+    public long getSize() {
+        return size;
+    }
+
+    public void setMinIops(long minIops) {
+        this.minIops = minIops;
+    }
+
+    @Override
+    public long getMinIops() {
+        return minIops;
+    }
+
+    public void setMaxIops(long maxIops) {
+        this.maxIops = maxIops;
+    }
+
+    @Override
+    public long getMaxIops() {
+        return maxIops;
+    }
+
+    public void setBurstIops(long burstIops) {
+        this.burstIops = burstIops;
+    }
+
+    @Override
+    public long getBurstIops() {
+        return burstIops;
+    }
+
+    @Override
+    public long getSfVirtualNetworkId() {
+        return sfVirtualNetworkId;
+    }
+
+    @Override
+    public Date getCreated() {
+        return created;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfCluster.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfCluster.java b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfCluster.java
new file mode 100644
index 0000000..b2e0a32
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfCluster.java
@@ -0,0 +1,40 @@
+// 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.solidfire;
+
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface SfCluster extends Identity, InternalIdentity {
+    String getName();
+
+    String getMvip();
+
+    String getUsername();
+
+    String getPassword();
+
+    long getTotalCapacity();
+
+    long getTotalMinIops();
+
+    long getTotalMaxIops();
+
+    long getTotalBurstIops();
+
+    long getZoneId();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfVirtualNetwork.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfVirtualNetwork.java b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfVirtualNetwork.java
new file mode 100644
index 0000000..f41e319
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfVirtualNetwork.java
@@ -0,0 +1,40 @@
+// 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.solidfire;
+
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface SfVirtualNetwork extends Identity, InternalIdentity {
+    long getSfId();
+
+    String getName();
+
+    String getTag();
+
+    String getStartIp();
+
+    int getSize();
+
+    String getNetmask();
+
+    String getSvip();
+
+    long getAccountId();
+
+    long getSfClusterId();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfVolume.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfVolume.java b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfVolume.java
new file mode 100644
index 0000000..84218d0
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SfVolume.java
@@ -0,0 +1,42 @@
+// 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.solidfire;
+
+import java.util.Date;
+
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface SfVolume extends Identity, InternalIdentity {
+    long getSfId();
+
+    String getName();
+
+    String getIqn();
+
+    long getSize();
+
+    long getMinIops();
+
+    long getMaxIops();
+
+    long getBurstIops();
+
+    long getSfVirtualNetworkId();
+
+    Date getCreated();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SolidFireManager.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SolidFireManager.java b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SolidFireManager.java
new file mode 100644
index 0000000..458d96b
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SolidFireManager.java
@@ -0,0 +1,66 @@
+// 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.solidfire;
+
+import java.util.List;
+
+import org.apache.cloudstack.framework.config.Configurable;
+
+public interface SolidFireManager extends Configurable {
+    // ********** Cluster-related commands **********
+
+    SfCluster listSolidFireCluster(String clusterName);
+
+    List<SfCluster> listSolidFireClusters();
+
+    SfCluster createReferenceToSolidFireCluster(String mvip, String username, String password, long totalCapacity,
+            long totalMinIops, long totalMaxIops, long totalBurstIops, long zoneId);
+
+    SfCluster updateReferenceToSolidFireCluster(String clusterName, long totalCapacity,
+            long totalMinIops, long totalMaxIops, long totalBurstIops);
+
+    SfCluster deleteReferenceToSolidFireCluster(String clusterName);
+
+    // ********** VLAN-related commands **********
+
+    SfVirtualNetwork listSolidFireVirtualNetworkById(long id);
+
+    List<SfVirtualNetwork> listSolidFireVirtualNetworkByClusterName(String clusterName);
+
+    // Long (instead of long) for both zoneId and accountId because they're optional and null is used to indicate that they're not present
+    // zoneId and accountId are not dependent upon one another (i.e. either one can be null, both can be null, or both can be not be null)
+    List<SfVirtualNetwork> listSolidFireVirtualNetworks(Long zoneId, Long accountId);
+
+    SfVirtualNetwork createSolidFireVirtualNetwork(String clusterName, String name, String tag, String startIp, int size,
+            String netmask, String svip, long accountId);
+
+    SfVirtualNetwork updateSolidFireVirtualNetwork(long id, String name, String startIp, int size, String netmask);
+
+    SfVirtualNetwork deleteSolidFireVirtualNetwork(long id);
+
+ // ********** Volume-related commands **********
+
+    SfVolume listSolidFireVolume(long id);
+
+    List<SfVolume> listSolidFireVolumes();
+
+    SfVolume createSolidFireVolume(String name, long size, long minIops, long maxIops, long burstIops, long accountId, long sfVirtualNetworkId);
+
+    SfVolume updateSolidFireVolume(long id, long size, long minIops, long maxIops, long burstIops);
+
+    SfVolume deleteSolidFireVolume(long id);
+}


[2/7] git commit: updated refs/heads/sf-plugins-a to 49ca3b4

Posted by mt...@apache.org.
CLOUDSTACK-8848: added null pointer guard to new public method


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/8cd8b6c8
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8cd8b6c8
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8cd8b6c8

Branch: refs/heads/sf-plugins-a
Commit: 8cd8b6c83c360777a3648be709424365bc121cae
Parents: 30c7049
Author: Daan Hoogland <da...@onecht.net>
Authored: Fri Oct 2 11:42:42 2015 +0200
Committer: Rene Moser <re...@apache.org>
Committed: Mon Oct 12 13:03:02 2015 +0200

----------------------------------------------------------------------
 .../com/cloud/vm/VirtualMachinePowerStateSyncImpl.java | 13 +++++++++----
 .../schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java |  3 +++
 2 files changed, 12 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8cd8b6c8/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
index 19ed71c..3b9d6f5 100644
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
@@ -24,13 +24,13 @@ import java.util.Map;
 import javax.inject.Inject;
 
 import org.apache.log4j.Logger;
-
 import org.apache.cloudstack.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.messagebus.MessageBus;
 import org.apache.cloudstack.framework.messagebus.PublishScope;
 
 import com.cloud.agent.api.HostVmStateReportEntry;
 import com.cloud.utils.DateUtil;
+import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.vm.dao.VMInstanceDao;
 
 public class VirtualMachinePowerStateSyncImpl implements VirtualMachinePowerStateSync {
@@ -112,9 +112,14 @@ public class VirtualMachinePowerStateSyncImpl implements VirtualMachinePowerStat
             for (VMInstanceVO instance : vmsThatAreMissingReport) {
 
                 // Make sure powerState is up to date for missing VMs
-                if (!_instanceDao.isPowerStateUpToDate(instance.getId())) {
-                    s_logger.warn("Detected missing VM but power state is outdated, wait for another process report run for VM id: " + instance.getId());
-                    _instanceDao.resetVmPowerStateTracking(instance.getId());
+                try {
+                    if (!_instanceDao.isPowerStateUpToDate(instance.getId())) {
+                        s_logger.warn("Detected missing VM but power state is outdated, wait for another process report run for VM id: " + instance.getId());
+                        _instanceDao.resetVmPowerStateTracking(instance.getId());
+                        continue;
+                    }
+                } catch (CloudRuntimeException e) {
+                    s_logger.warn("Checked for missing powerstate of a none existing vm", e);
                     continue;
                 }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8cd8b6c8/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
index 48b56d1..aa940ce 100644
--- a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
+++ b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
@@ -806,6 +806,9 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
     @Override
     public boolean isPowerStateUpToDate(final long instanceId) {
         VMInstanceVO instance = findById(instanceId);
+        if(instance == null) {
+            throw new CloudRuntimeException("checking power state update count on non existing instance " + instanceId);
+        }
         return instance.getPowerStateUpdateCount() < MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT;
     }
 


[5/7] git commit: updated refs/heads/sf-plugins-a to 49ca3b4

Posted by mt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SolidFireManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SolidFireManagerImpl.java b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SolidFireManagerImpl.java
new file mode 100644
index 0000000..e02a9c5
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/solidfire/SolidFireManagerImpl.java
@@ -0,0 +1,977 @@
+// 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.solidfire;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+import org.apache.cloudstack.dataaccess.dao.solidfire.SfClusterDao;
+import org.apache.cloudstack.dataaccess.dao.solidfire.SfVirtualNetworkDao;
+import org.apache.cloudstack.dataaccess.dao.solidfire.SfVolumeDao;
+import org.apache.cloudstack.dataaccess.vo.solidfire.SfClusterVO;
+import org.apache.cloudstack.dataaccess.vo.solidfire.SfVirtualNetworkVO;
+import org.apache.cloudstack.dataaccess.vo.solidfire.SfVolumeVO;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.storage.datastore.util.SolidFireUtil;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+import org.apache.cloudstack.util.solidfire.SolidFireConnection;
+import org.springframework.stereotype.Component;
+
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.user.Account;
+import com.cloud.user.AccountDetailVO;
+import com.cloud.user.AccountDetailsDao;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.db.GlobalLock;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@Component
+public class SolidFireManagerImpl implements SolidFireManager {
+    private static final Logger s_logger = Logger.getLogger(SolidFireManagerImpl.class);
+    private static final int s_lockTimeInSeconds = 180;
+
+    private static final ConfigKey<Long> s_sfTotalAccountCapacity =
+            new ConfigKey<>(
+                    "Advanced",
+                    Long.class,
+                    "sf.total.capacity",
+                    "0",
+                    "Total capacity the account can draw from any and all SolidFire clusters (in GBs)",
+                    true, ConfigKey.Scope.Account);
+
+    private static final ConfigKey<Long> s_sfTotalAccountMinIops =
+            new ConfigKey<>(
+                    "Advanced",
+                    Long.class,
+                    "sf.total.min.iops",
+                    "0",
+                    "Total minimum IOPS the account can draw from any and all SolidFire clusters",
+                    true, ConfigKey.Scope.Account);
+
+    private static final ConfigKey<Long> s_sfTotalAccountMaxIops =
+            new ConfigKey<>(
+                    "Advanced",
+                    Long.class,
+                    "sf.total.max.iops",
+                    "0",
+                    "Total maximum IOPS the account can draw from any and all SolidFire clusters",
+                    true, ConfigKey.Scope.Account);
+
+    private static final ConfigKey<Long> s_sfTotalAccountBurstIops =
+            new ConfigKey<>(
+                    "Advanced",
+                    Long.class,
+                    "sf.total.burst.iops",
+                    "0",
+                    "Total burst IOPS the account can draw from any and all SolidFire clusters",
+                    true, ConfigKey.Scope.Account);
+
+    @Inject private AccountDao _accountDao;
+    @Inject private AccountDetailsDao _accountDetailsDao;
+    @Inject private DataCenterDao _zoneDao;
+    @Inject private SfClusterDao _sfClusterDao;
+    @Inject private SfVirtualNetworkDao _sfVirtualNetworkDao;
+    @Inject private SfVolumeDao _sfVolumeDao;
+    @Inject private SfUtil _sfUtil;
+
+    private SolidFireManagerImpl() {
+    }
+
+    @Override
+    public SfCluster listSolidFireCluster(String clusterName) {
+        s_logger.info("listSolidFireCluster invoked");
+
+        verifyRootAdmin();
+
+        return getSfCluster(clusterName);
+    }
+
+    @Override
+    public List<SfCluster> listSolidFireClusters() {
+        s_logger.info("listSolidFireClusters invoked");
+
+        verifyRootAdmin();
+
+        List<SfCluster> sfClusters = new ArrayList<>();
+
+        List<SfClusterVO> sfClusterVOs = _sfClusterDao.listAll();
+
+        if (sfClusterVOs != null) {
+            sfClusters.addAll(sfClusterVOs);
+        }
+
+        return sfClusters;
+    }
+
+    @Override
+    public SfCluster createReferenceToSolidFireCluster(String mvip, String username, String password, long totalCapacity,
+            long totalMinIops, long totalMaxIops, long totalBurstIops, long zoneId) {
+        s_logger.info("createReferenceToSolidFireCluster invoked");
+
+        verifyRootAdmin();
+
+        verifyClusterQuotas(totalCapacity, totalMinIops, totalMaxIops, totalBurstIops);
+
+        verifyZone(zoneId);
+
+        SolidFireConnection sfConnection = new SolidFireConnection(mvip, username, password);
+
+        String clusterName = sfConnection.getClusterName();
+
+        List<SfClusterVO> sfClusterVOs = _sfClusterDao.listAll();
+
+        for (SfCluster sfCluster : sfClusterVOs) {
+            if (sfCluster.getName().equals(clusterName)) {
+                throw new CloudRuntimeException("Unable to add a reference to cluster '" + clusterName + "' as a reference to a cluster by this name already exists");
+            }
+        }
+
+        SfClusterVO sfClusterVO = new SfClusterVO(clusterName, mvip, username, password, totalCapacity, totalMinIops, totalMaxIops, totalBurstIops, zoneId);
+
+        return _sfClusterDao.persist(sfClusterVO);
+    }
+
+    @Override
+    public SfCluster updateReferenceToSolidFireCluster(String clusterName, long newTotalCapacity,
+            long newTotalMinIops, long newTotalMaxIops, long newTotalBurstIops) {
+        s_logger.info("updateReferenceToSolidFireCluster invoked");
+
+        verifyRootAdmin();
+
+        verifyClusterQuotas(newTotalCapacity, newTotalMinIops, newTotalMaxIops, newTotalBurstIops);
+
+        SfClusterVO sfClusterVO = getSfCluster(clusterName);
+
+        GlobalLock sfClusterLock = GlobalLock.getInternLock(sfClusterVO.getUuid());
+
+        if (!sfClusterLock.lock(s_lockTimeInSeconds)) {
+            String errMsg = "Couldn't lock the DB on the following string (Storage cluster UUID): " + sfClusterVO.getUuid();
+
+            s_logger.debug(errMsg);
+
+            throw new CloudRuntimeException(errMsg);
+        }
+
+        try {
+            TotalRemaining totalRemainingInCluster = getTotalRemainingInCluster(sfClusterVO);
+
+            long totalUsedCapacityInCluster = sfClusterVO.getTotalCapacity() - totalRemainingInCluster.getTotalRemainingCapacity();
+            long totalUsedMinIopsInCluster = sfClusterVO.getTotalMinIops() - totalRemainingInCluster.getTotalRemainingMinIops();
+            long totalUsedMaxIopsInCluster = sfClusterVO.getTotalMaxIops() - totalRemainingInCluster.getTotalRemainingMaxIops();
+            long totalUsedBurstIopsInCluster = sfClusterVO.getTotalBurstIops() - totalRemainingInCluster.getTotalRemainingBurstIops();
+
+            if (totalUsedCapacityInCluster <= newTotalCapacity && totalUsedMinIopsInCluster <= newTotalMinIops &&
+                    totalUsedMaxIopsInCluster <= newTotalMaxIops && totalUsedBurstIopsInCluster <= newTotalBurstIops) {
+                sfClusterVO.setTotalCapacity(newTotalCapacity);
+                sfClusterVO.setTotalMinIops(newTotalMinIops);
+                sfClusterVO.setTotalMaxIops(newTotalMaxIops);
+                sfClusterVO.setTotalBurstIops(newTotalBurstIops);
+
+                if (_sfClusterDao.update(sfClusterVO.getId(), sfClusterVO)) {
+                    return sfClusterVO;
+                }
+
+                throw new CloudRuntimeException("Unable to update the cluster table");
+            }
+            else {
+                throw new CloudRuntimeException("Unable to update the cluster table as more capacity and/or performance is in use " +
+                        "in the storage cluster than one or more of the values passed in");
+            }
+        }
+        finally {
+            sfClusterLock.unlock();
+            sfClusterLock.releaseRef();
+        }
+    }
+
+    @Override
+    public SfCluster deleteReferenceToSolidFireCluster(String clusterName) {
+        s_logger.info("deleteReferenceToSolidFireCluster invoked");
+
+        verifyRootAdmin();
+
+        SfCluster sfCluster = getSfCluster(clusterName);
+
+        List<SfVirtualNetworkVO> sfVirtualNetworks = _sfVirtualNetworkDao.findByClusterId(sfCluster.getId());
+
+        if (sfVirtualNetworks != null && sfVirtualNetworks.size() > 0) {
+            throw new CloudRuntimeException("Unable to delete a reference to a cluster that has one or more virtual networks");
+        }
+
+        if (!_sfClusterDao.remove(sfCluster.getId())) {
+            throw new CloudRuntimeException("Unable to remove the following cluster: " + clusterName);
+        }
+
+        return sfCluster;
+    }
+
+    @Override
+    public SfVirtualNetwork listSolidFireVirtualNetworkById(long id) {
+        s_logger.info("listSolidFireVirtualNetworkById invoked");
+
+        SfVirtualNetwork sfVirtualNetwork = getSfVirtualNetwork(id);
+
+        verifyPermissionsForAccount(sfVirtualNetwork.getAccountId());
+
+        return getSfVirtualNetwork(id);
+    }
+
+    @Override
+    public List<SfVirtualNetwork> listSolidFireVirtualNetworkByClusterName(String clusterName) {
+        s_logger.info("listSolidFireVirtualNetworkByClusterName invoked");
+
+        verifyRootAdmin();
+
+        SfCluster sfCluster = getSfCluster(clusterName);
+
+        return filterVirtualNetworksByCluster(_sfVirtualNetworkDao.listAll(), sfCluster.getId());
+    }
+
+    @Override
+    public List<SfVirtualNetwork> listSolidFireVirtualNetworks(Long zoneId, Long accountId) {
+        s_logger.info("listSolidFireVirtualNetworks invoked");
+
+        final List<SfVirtualNetworkVO> sfVirtualNetworkVOs;
+
+        if (_sfUtil.isRootAdmin()) {
+            if (zoneId != null) {
+                if (accountId != null) {
+                    sfVirtualNetworkVOs = filterVirtualNetworksByZone(_sfVirtualNetworkDao.findByAccountId(accountId), zoneId);
+                }
+                else {
+                    sfVirtualNetworkVOs = filterVirtualNetworksByZone(_sfVirtualNetworkDao.listAll(), zoneId);
+                }
+            }
+            else {
+                if (accountId != null) {
+                    sfVirtualNetworkVOs = _sfVirtualNetworkDao.findByAccountId(accountId);
+                }
+                else {
+                    sfVirtualNetworkVOs = _sfVirtualNetworkDao.listAll();
+                }
+            }
+        }
+        else {
+            if (accountId != null && accountId != _sfUtil.getCallingAccount().getId()) {
+                throw new CloudRuntimeException("Only a root admin can specify an account other than his own.");
+            }
+
+            if (zoneId != null) {
+                sfVirtualNetworkVOs = filterVirtualNetworksByZone(_sfVirtualNetworkDao.findByAccountId(_sfUtil.getCallingAccount().getId()), zoneId);
+            }
+            else {
+                sfVirtualNetworkVOs = _sfVirtualNetworkDao.findByAccountId(_sfUtil.getCallingAccount().getId());
+            }
+        }
+
+        List<SfVirtualNetwork> sfVirtualNetworks = new ArrayList<>();
+
+        if (sfVirtualNetworkVOs != null) {
+            sfVirtualNetworks.addAll(sfVirtualNetworkVOs);
+        }
+
+        return sfVirtualNetworks;
+    }
+
+    @Override
+    public SfVirtualNetwork createSolidFireVirtualNetwork(String clusterName, String name, String tag, String startIp, int size,
+            String netmask, String svip, long accountId) {
+        s_logger.info("createSolidFireVirtualNetwork invoked");
+
+        verifyRootAdmin();
+
+        verifyAccount(accountId);
+
+        SfCluster sfCluster = getSfCluster(clusterName);
+
+        SolidFireConnection sfConnection = new SolidFireConnection(sfCluster.getMvip(), sfCluster.getUsername(), sfCluster.getPassword());
+
+        long sfVirtualNetworkId = sfConnection.createVirtualNetwork(name, tag, startIp, size, netmask, svip);
+
+        SfVirtualNetworkVO sfVirtualNetworkVO = new SfVirtualNetworkVO(sfVirtualNetworkId, name, tag, startIp, size, netmask, svip, accountId, sfCluster.getId());
+
+        return _sfVirtualNetworkDao.persist(sfVirtualNetworkVO);
+    }
+
+    @Override
+    public SfVirtualNetwork updateSolidFireVirtualNetwork(long id, String name, String startIp, int size, String netmask) {
+        s_logger.info("updateSolidFireVirtualNetwork invoked");
+
+        verifyRootAdmin();
+
+        SfVirtualNetworkVO sfVirtualNetworkVO = getSfVirtualNetwork(id);
+
+        long sfClusterId = sfVirtualNetworkVO.getSfClusterId();
+
+        SfClusterVO sfClusterVO = getSfCluster(sfClusterId);
+
+        SolidFireConnection sfConnection = new SolidFireConnection(sfClusterVO.getMvip(), sfClusterVO.getUsername(), sfClusterVO.getPassword());
+
+        sfConnection.modifyVirtualNetwork(sfVirtualNetworkVO.getSfId(), name, startIp, size, netmask);
+
+        sfVirtualNetworkVO.setName(name);
+        sfVirtualNetworkVO.setStartIp(startIp);
+        sfVirtualNetworkVO.setSize(size);
+        sfVirtualNetworkVO.setNetmask(netmask);
+
+        if (_sfVirtualNetworkDao.update(sfVirtualNetworkVO.getId(), sfVirtualNetworkVO)) {
+            return sfVirtualNetworkVO;
+        }
+
+        throw new CloudRuntimeException("Unable to update the virtual network table");
+    }
+
+    @Override
+    public SfVirtualNetwork deleteSolidFireVirtualNetwork(long id) {
+        s_logger.info("deleteSolidFireVirtualNetwork invoked");
+
+        verifyRootAdmin();
+
+        SfVirtualNetwork sfVirtualNetwork = getSfVirtualNetwork(id);
+
+        List<SfVolumeVO> sfVolumes = _sfVolumeDao.findBySfVirtualNetworkId(sfVirtualNetwork.getId());
+
+        if (sfVolumes != null && sfVolumes.size() > 0) {
+            throw new CloudRuntimeException("Unable to delete a virtual network that has one or more volumes");
+        }
+
+        if (!_sfVirtualNetworkDao.remove(id)) {
+            throw new CloudRuntimeException("Unable to remove the following virtual network: " + id);
+        }
+
+        SfCluster sfCluster = getSfCluster(sfVirtualNetwork.getSfClusterId());
+
+        SolidFireConnection sfConnection = new SolidFireConnection(sfCluster.getMvip(), sfCluster.getUsername(), sfCluster.getPassword());
+
+        sfConnection.deleteVirtualNetwork(sfVirtualNetwork.getSfId());
+
+        return sfVirtualNetwork;
+    }
+
+    @Override
+    public SfVolume listSolidFireVolume(long id) {
+        s_logger.info("listSolidFireVolume invoked");
+
+        SfVolume sfVolume = getSfVolume(id);
+
+        SfVirtualNetwork sfVirtualNetwork = getSfVirtualNetwork(sfVolume.getSfVirtualNetworkId());
+
+        verifyPermissionsForAccount(sfVirtualNetwork.getAccountId());
+
+        return sfVolume;
+    }
+
+    @Override
+    public List<SfVolume> listSolidFireVolumes() {
+        s_logger.info("listSolidFireVolumes invoked");
+
+        final List<SfVolumeVO> sfVolumeVOs;
+
+        if (_sfUtil.isRootAdmin()) {
+            sfVolumeVOs = _sfVolumeDao.listAll();
+        }
+        else {
+            sfVolumeVOs = new ArrayList<>();
+
+            List<SfVirtualNetworkVO> sfVirtualNetworkVOs = _sfVirtualNetworkDao.findByAccountId(_sfUtil.getCallingAccount().getId());
+
+            if (sfVirtualNetworkVOs != null) {
+                for (SfVirtualNetwork sfVirtualNetwork : sfVirtualNetworkVOs) {
+                    List<SfVolumeVO> sfVolumeVOsForVirtualNetwork = _sfVolumeDao.findBySfVirtualNetworkId(sfVirtualNetwork.getId());
+
+                    sfVolumeVOs.addAll(sfVolumeVOsForVirtualNetwork);
+                }
+            }
+        }
+
+        List<SfVolume> sfVolumes = new ArrayList<>();
+
+        if (sfVolumeVOs != null) {
+            sfVolumes.addAll(sfVolumeVOs);
+        }
+
+        return sfVolumes;
+    }
+
+    @Override
+    public SfVolume createSolidFireVolume(String name, long size, long minIops, long maxIops, long burstIops, long accountId, long sfVirtualNetworkId) {
+        s_logger.info("createSolidFireVolume invoked");
+
+        verifyPermissionsForAccount(accountId);
+
+        verifySfVirtualNetwork(sfVirtualNetworkId);
+
+        SfVolume sfVolume = createVolume(name, size, minIops, maxIops, burstIops, accountId, sfVirtualNetworkId);
+
+        if (sfVolume != null) {
+            return sfVolume;
+        }
+
+        throw new CloudRuntimeException("Unable to create the volume");
+    }
+
+    @Override
+    public SfVolume updateSolidFireVolume(long id, long size, long minIops, long maxIops, long burstIops) {
+        s_logger.info("updateSolidFireVolume invoked");
+
+        SfVolumeVO sfVolumeVO = getSfVolume(id);
+
+        SfVirtualNetwork sfVirtualNetwork = getSfVirtualNetwork(sfVolumeVO.getSfVirtualNetworkId());
+
+        verifyPermissionsForAccount(sfVirtualNetwork.getAccountId());
+
+        if ((sfVolumeVO = updateVolume(sfVolumeVO, size, minIops, maxIops, burstIops)) != null) {
+            return sfVolumeVO;
+        }
+
+        throw new CloudRuntimeException("Unable to update the volume with the following id: " + id);
+    }
+
+    @Override
+    public SfVolume deleteSolidFireVolume(long id) {
+        s_logger.info("deleteSolidFireVolume invoked");
+
+        SfVolume sfVolume = getSfVolume(id);
+
+        SfVirtualNetwork sfVirtualNetwork = getSfVirtualNetwork(sfVolume.getSfVirtualNetworkId());
+
+        verifyPermissionsForAccount(sfVirtualNetwork.getAccountId());
+
+        if (!_sfVolumeDao.remove(id)) {
+            throw new CloudRuntimeException("Unable to remove the following volume: " + id);
+        }
+
+        SfCluster sfCluster = getSfCluster(sfVirtualNetwork.getSfClusterId());
+
+        SolidFireConnection sfConnection = new SolidFireConnection(sfCluster.getMvip(), sfCluster.getUsername(), sfCluster.getPassword());
+
+        sfConnection.deleteVolume(sfVolume.getSfId());
+
+        return sfVolume;
+    }
+
+    @Override
+    public String getConfigComponentName() {
+        return SolidFireManagerImpl.class.getSimpleName();
+    }
+
+    @Override
+    public ConfigKey<?>[] getConfigKeys() {
+        return new ConfigKey<?>[] { s_sfTotalAccountCapacity, s_sfTotalAccountMinIops, s_sfTotalAccountMaxIops, s_sfTotalAccountBurstIops };
+    }
+
+    private SfClusterVO getSfCluster(String clusterName) {
+        SfClusterVO sfClusterVO = _sfClusterDao.findByName(clusterName);
+
+        if (sfClusterVO == null) {
+            throw new CloudRuntimeException("The following SolidFire cluster name cannot be located in the database: '" + clusterName + "'.");
+        }
+
+        return sfClusterVO;
+    }
+
+    private SfClusterVO getSfCluster(long sfClusterId) {
+        SfClusterVO sfClusterVO = _sfClusterDao.findById(sfClusterId);
+
+        if (sfClusterVO == null) {
+            throw new CloudRuntimeException("The SolidFire cluster with the following ID cannot be located in the database: '" + sfClusterId + "'.");
+        }
+
+        return sfClusterVO;
+    }
+
+    private SfVirtualNetworkVO getSfVirtualNetwork(long id) {
+        SfVirtualNetworkVO sfVirtualNetworkVO = _sfVirtualNetworkDao.findById(id);
+
+        if (sfVirtualNetworkVO == null) {
+            throw new CloudRuntimeException("The SolidFire VLAN with the following ID cannot be located in the database: '" + id + "'.");
+        }
+
+        return sfVirtualNetworkVO;
+    }
+
+    private SfVolumeVO getSfVolume(long id) {
+        SfVolumeVO sfVolumeVO = _sfVolumeDao.findById(id);
+
+        if (sfVolumeVO == null) {
+            throw new CloudRuntimeException("The SolidFire volume with the following ID cannot be located in the database: '" + id + "'.");
+        }
+
+        return sfVolumeVO;
+    }
+
+    private void verifyRootAdmin() {
+        if (!_sfUtil.isRootAdmin()) {
+            throw new PermissionDeniedException("Only a root admin can perform this operation.");
+        }
+    }
+
+    private void verifyPermissionsForAccount(long accountId) {
+        Account account = _sfUtil.getCallingAccount();
+
+        if (_sfUtil.isRootAdmin(account.getId())) {
+            return; // permissions OK
+        }
+
+        if (account.getId() == accountId) {
+            return; // permissions OK
+        }
+
+        throw new PermissionDeniedException("Only a root admin or a user of the owning account can perform this operation.");
+    }
+
+    private void verifyClusterQuotas(long totalCapacity, long totalMinIops, long totalMaxIops, long totalBurstIops) {
+        if (totalCapacity < 0) {
+            throw new CloudRuntimeException("The total capacity of the cluster must be a positive whole number.");
+        }
+
+        if (totalMinIops < 0) {
+            throw new CloudRuntimeException("The total minimum IOPS of the cluster must be a positive whole number.");
+        }
+
+        if (totalMaxIops < 0) {
+            throw new CloudRuntimeException("The total maximum IOPS of the cluster must be a positive whole number.");
+        }
+
+        if (totalBurstIops < 0) {
+            throw new CloudRuntimeException("The total burst IOPS of the cluster must be a positive whole number.");
+        }
+
+        if (totalMinIops > totalMaxIops) {
+            throw new CloudRuntimeException("The total minimum IOPS of the cluster must be less than or equal to the total maximum IOPS of the cluster.");
+        }
+
+        if (totalMaxIops > totalBurstIops) {
+            throw new CloudRuntimeException("The total maximum IOPS of the cluster must be less than or equal to the total burst IOPS of the cluster.");
+        }
+    }
+
+    private void verifyAccount(long accountId) {
+        Account account = _accountDao.findById(accountId);
+
+        if (account == null) {
+            throw new CloudRuntimeException("Unable to locate the following account: " + accountId);
+        }
+     }
+
+    private void verifySfVirtualNetwork(long sfVirtualNetworkId) {
+        SfVirtualNetwork sfVirtualNetwork = _sfVirtualNetworkDao.findById(sfVirtualNetworkId);
+
+        if (sfVirtualNetwork == null) {
+            throw new CloudRuntimeException("Unable to locate the following virtual network: " + sfVirtualNetworkId);
+        }
+     }
+
+    private void verifyZone(long zoneId) {
+       DataCenterVO dataCenterVO = _zoneDao.findById(zoneId);
+
+       if (dataCenterVO == null) {
+           throw new CloudRuntimeException("Unable to locate the following zone: " + zoneId);
+       }
+    }
+
+    private SfVolume createVolume(String name, long size, long minIops, long maxIops, long burstIops, long accountId, long sfVirtualNetworkId) {
+        verifyIops(minIops, maxIops, burstIops);
+
+        Account account = _accountDao.findById(accountId);
+
+        SfVirtualNetwork sfVirtualNetwork = getSfVirtualNetwork(sfVirtualNetworkId);
+        SfCluster sfCluster = getSfCluster(sfVirtualNetwork.getSfClusterId());
+
+        GlobalLock accountLock = GlobalLock.getInternLock(account.getUuid());
+
+        if (!accountLock.lock(s_lockTimeInSeconds)) {
+            String errMsg = "Couldn't lock the DB on the following string (Account UUID): " + sfCluster.getUuid();
+
+            s_logger.debug(errMsg);
+
+            throw new CloudRuntimeException(errMsg);
+        }
+
+        GlobalLock sfClusterLock = GlobalLock.getInternLock(sfCluster.getUuid());
+
+        boolean clusterLockSuccess = false;
+
+        try {
+            clusterLockSuccess = sfClusterLock.lock(s_lockTimeInSeconds);
+        }
+        catch (Throwable t) {
+            // clusterLockSuccess should still be false
+        }
+
+        if (!clusterLockSuccess) {
+            accountLock.unlock();
+            accountLock.releaseRef();
+
+            String errMsg = "Couldn't lock the DB on the following string (Storage cluster UUID): " + sfCluster.getUuid();
+
+            s_logger.debug(errMsg);
+
+            throw new CloudRuntimeException(errMsg);
+        }
+
+        try {
+            TotalRemaining totalRemainingInAccount = getTotalRemainingInAccount(accountId);
+
+            long totalRemainingCapacityInAccount = totalRemainingInAccount.getTotalRemainingCapacity() - size;
+            long totalRemainingMinIopsInAccount = totalRemainingInAccount.getTotalRemainingMinIops() - minIops;
+            long totalRemainingMaxIopsInAccount = totalRemainingInAccount.getTotalRemainingMaxIops() - maxIops;
+            long totalRemainingBurstIopsInAccount = totalRemainingInAccount.getTotalRemainingBurstIops() - burstIops;
+
+            if (totalRemainingCapacityInAccount >= 0 && totalRemainingMinIopsInAccount >= 0 && totalRemainingMaxIopsInAccount >= 0 && totalRemainingBurstIopsInAccount >= 0) {
+                TotalRemaining totalRemainingInCluster = getTotalRemainingInCluster(sfCluster);
+
+                long totalRemainingCapacityInCluster = totalRemainingInCluster.getTotalRemainingCapacity() - size;
+                long totalRemainingMinIopsInCluster = totalRemainingInCluster.getTotalRemainingMinIops() - minIops;
+                long totalRemainingMaxIopsInCluster = totalRemainingInCluster.getTotalRemainingMaxIops() - maxIops;
+                long totalRemainingBurstIopsInCluster = totalRemainingInCluster.getTotalRemainingBurstIops() - burstIops;
+
+                if (totalRemainingCapacityInCluster >= 0 && totalRemainingMinIopsInCluster >= 0 && totalRemainingMaxIopsInCluster >= 0 && totalRemainingBurstIopsInCluster >= 0) {
+                    SolidFireConnection sfConnection = new SolidFireConnection(sfCluster.getMvip(), sfCluster.getUsername(), sfCluster.getPassword());
+
+                    long sfClusterId = sfCluster.getId();
+
+                    AccountDetailVO accountDetail = getAccountDetail(accountId, sfClusterId);
+
+                    if (accountDetail == null || accountDetail.getValue() == null) {
+                        String sfAccountName = getSolidFireAccountName(accountId, account.getUuid());
+                        SolidFireConnection.SolidFireAccount sfAccount = sfConnection.getSolidFireAccount(sfAccountName);
+
+                        if (sfAccount == null) {
+                            sfAccount = createSolidFireAccount(sfConnection, sfAccountName);
+                        }
+
+                        updateCsDbWithSolidFireAccountInfo(account.getId(), sfAccount, sfClusterId);
+
+                        accountDetail = getAccountDetail(accountId, sfClusterId);
+                    }
+
+                    long sfAccountId = Long.parseLong(accountDetail.getValue());
+
+                    long sfVolumeId = sfConnection.createVolume(name, sfAccountId, size, minIops, maxIops, burstIops);
+
+                    SolidFireConnection.SolidFireVolume sfVolume = sfConnection.getVolume(sfVolumeId);
+
+                    SfVolumeVO sfVolumeVO = new SfVolumeVO(sfVolumeId, name, sfVolume.getIqn(), size, minIops, maxIops, burstIops, sfVirtualNetworkId);
+
+                    return _sfVolumeDao.persist(sfVolumeVO);
+                }
+                else {
+                    throw new CloudRuntimeException("Unable to create the volume due to insufficient capacity or performance remaining in the storage cluster");
+                }
+            }
+            else {
+                throw new CloudRuntimeException("Unable to create the volume due to insufficient capacity or performance remaining in the account");
+            }
+        }
+        finally {
+            sfClusterLock.unlock();
+            sfClusterLock.releaseRef();
+
+            accountLock.unlock();
+            accountLock.releaseRef();
+        }
+    }
+
+    private SfVolumeVO updateVolume(SfVolumeVO sfVolumeVO, long size, long minIops, long maxIops, long burstIops) {
+        verifyIops(minIops, maxIops, burstIops);
+
+        SfVirtualNetwork sfVirtualNetwork = getSfVirtualNetwork(sfVolumeVO.getSfVirtualNetworkId());
+
+        Account account = _accountDao.findById(sfVirtualNetwork.getAccountId());
+        SfCluster sfCluster = getSfCluster(sfVirtualNetwork.getSfClusterId());
+
+        GlobalLock accountLock = GlobalLock.getInternLock(account.getUuid());
+
+        if (!accountLock.lock(s_lockTimeInSeconds)) {
+            String errMsg = "Couldn't lock the DB on the following string (Account UUID): " + sfCluster.getUuid();
+
+            s_logger.debug(errMsg);
+
+            throw new CloudRuntimeException(errMsg);
+        }
+
+        GlobalLock sfClusterLock = GlobalLock.getInternLock(sfCluster.getUuid());
+
+        boolean clusterLockSuccess = false;
+
+        try {
+            clusterLockSuccess = sfClusterLock.lock(s_lockTimeInSeconds);
+        }
+        catch (Throwable t) {
+            // clusterLockSuccess should still be false
+        }
+
+        if (!clusterLockSuccess) {
+            accountLock.unlock();
+            accountLock.releaseRef();
+
+            String errMsg = "Couldn't lock the DB on the following string (Storage cluster UUID): " + sfCluster.getUuid();
+
+            s_logger.debug(errMsg);
+
+            throw new CloudRuntimeException(errMsg);
+        }
+
+        try {
+            TotalRemaining totalRemainingInAccount = getTotalRemainingInAccount(account.getId());
+
+            long totalRemainingCapacityInAccount = totalRemainingInAccount.getTotalRemainingCapacity() - size;
+            long totalRemainingMinIopsInAccount = totalRemainingInAccount.getTotalRemainingMinIops() - minIops;
+            long totalRemainingMaxIopsInAccount = totalRemainingInAccount.getTotalRemainingMaxIops() - maxIops;
+            long totalRemainingBurstIopsInAccount = totalRemainingInAccount.getTotalRemainingBurstIops() - burstIops;
+
+            if (totalRemainingCapacityInAccount >= 0 && totalRemainingMinIopsInAccount >= 0 && totalRemainingMaxIopsInAccount >= 0 && totalRemainingBurstIopsInAccount >= 0) {
+                TotalRemaining totalRemainingInCluster = getTotalRemainingInCluster(sfCluster, sfVolumeVO);
+
+                long totalRemainingCapacityInCluster = totalRemainingInCluster.getTotalRemainingCapacity() - size;
+                long totalRemainingMinIopsInCluster = totalRemainingInCluster.getTotalRemainingMinIops() - minIops;
+                long totalRemainingMaxIopsInCluster = totalRemainingInCluster.getTotalRemainingMaxIops() - maxIops;
+                long totalRemainingBurstIopsInCluster = totalRemainingInCluster.getTotalRemainingBurstIops() - burstIops;
+
+                if (totalRemainingCapacityInCluster >= 0 && totalRemainingMinIopsInCluster >= 0 && totalRemainingMaxIopsInCluster >= 0 && totalRemainingBurstIopsInCluster >= 0) {
+                    SolidFireConnection sfConnection = new SolidFireConnection(sfCluster.getMvip(), sfCluster.getUsername(), sfCluster.getPassword());
+
+                    sfConnection.modifyVolume(sfVolumeVO.getSfId(), size, minIops, maxIops, burstIops);
+
+                    sfVolumeVO.setSize(size);
+                    sfVolumeVO.setMinIops(minIops);
+                    sfVolumeVO.setMaxIops(maxIops);
+                    sfVolumeVO.setBurstIops(burstIops);
+
+                    if (!_sfVolumeDao.update(sfVolumeVO.getId(), sfVolumeVO)) {
+                        throw new CloudRuntimeException("Unable to update the following volume:" + sfVolumeVO.getId());
+                    }
+
+                    return sfVolumeVO;
+                }
+                else {
+                    throw new CloudRuntimeException("Unable to update the volume due to insufficient capacity or performance remaining in the storage cluster");
+                }
+            }
+            else {
+                throw new CloudRuntimeException("Unable to update the volume due to insufficient capacity or performance remaining in the account");
+            }
+        }
+        finally {
+            sfClusterLock.unlock();
+            sfClusterLock.releaseRef();
+
+            accountLock.unlock();
+            accountLock.releaseRef();
+        }
+    }
+
+    private TotalRemaining getTotalRemainingInAccount(long accountId) {
+        return getTotalRemainingInAccount(accountId, null);
+    }
+
+    private TotalRemaining getTotalRemainingInAccount(long accountId, SfVolume volumeToExclude) {
+        Long totalRemainingCapacity = s_sfTotalAccountCapacity.valueIn(accountId);
+        Long totalRemainingMinIops = s_sfTotalAccountMinIops.valueIn(accountId);
+        Long totalRemainingMaxIops = s_sfTotalAccountMaxIops.valueIn(accountId);
+        Long totalRemainingBurstIops = s_sfTotalAccountBurstIops.valueIn(accountId);
+
+        List<SfVolume> sfVolumesInAccount = new ArrayList<>();
+
+        List<SfVirtualNetworkVO> sfVirtualNetworkVOs = _sfVirtualNetworkDao.findByAccountId(accountId);
+
+        if (sfVirtualNetworkVOs != null) {
+            for (SfVirtualNetwork sfVirtualNetwork : sfVirtualNetworkVOs) {
+                List<SfVolumeVO> sfVolumeVOs = _sfVolumeDao.findBySfVirtualNetworkId(sfVirtualNetwork.getId());
+
+                sfVolumesInAccount.addAll(sfVolumeVOs);
+            }
+        }
+
+        for (SfVolume sfVolumeInAccount : sfVolumesInAccount) {
+            if (volumeToExclude == null || sfVolumeInAccount.getId() != volumeToExclude.getId()) {
+                totalRemainingCapacity -= sfVolumeInAccount.getSize();
+                totalRemainingMinIops -= sfVolumeInAccount.getMinIops();
+                totalRemainingMaxIops -= sfVolumeInAccount.getMaxIops();
+                totalRemainingBurstIops -= sfVolumeInAccount.getBurstIops();
+            }
+        }
+
+        return new TotalRemaining(totalRemainingCapacity, totalRemainingMinIops, totalRemainingMaxIops, totalRemainingBurstIops);
+    }
+
+    private TotalRemaining getTotalRemainingInCluster(SfCluster sfCluster) {
+        return getTotalRemainingInCluster(sfCluster, null);
+    }
+
+    private TotalRemaining getTotalRemainingInCluster(SfCluster sfCluster, SfVolume volumeToExclude) {
+        long totalRemainingCapacity = sfCluster.getTotalCapacity();
+        long totalRemainingMinIops = sfCluster.getTotalMinIops();
+        long totalRemainingMaxIops = sfCluster.getTotalMaxIops();
+        long totalRemainingBurstIops = sfCluster.getTotalBurstIops();
+
+        List<SfVolume> sfVolumesInCluster = new ArrayList<>();
+
+        List<SfVirtualNetworkVO> sfVirtualNetworkVOs = _sfVirtualNetworkDao.findByClusterId(sfCluster.getId());
+
+        if (sfVirtualNetworkVOs != null) {
+            for (SfVirtualNetwork sfVirtualNetwork : sfVirtualNetworkVOs) {
+                List<SfVolumeVO> sfVolumeVOs = _sfVolumeDao.findBySfVirtualNetworkId(sfVirtualNetwork.getId());
+
+                sfVolumesInCluster.addAll(sfVolumeVOs);
+            }
+        }
+
+        for (SfVolume sfVolumeInCluster : sfVolumesInCluster) {
+            if (volumeToExclude == null || sfVolumeInCluster.getId() != volumeToExclude.getId()) {
+                totalRemainingCapacity -= sfVolumeInCluster.getSize();
+                totalRemainingMinIops -= sfVolumeInCluster.getMinIops();
+                totalRemainingMaxIops -= sfVolumeInCluster.getMaxIops();
+                totalRemainingBurstIops -= sfVolumeInCluster.getBurstIops();
+            }
+        }
+
+        return new TotalRemaining(totalRemainingCapacity, totalRemainingMinIops, totalRemainingMaxIops, totalRemainingBurstIops);
+    }
+
+    private static class TotalRemaining {
+        private final long _totalRemainingCapacity;
+        private final long _totalRemainingMinIops;
+        private final long _totalRemainingMaxIops;
+        private final long _totalRemainingBurstIops;
+
+        public TotalRemaining(long totalRemainingCapacity, long totalRemainingMinIops, long totalRemainingMaxIops, long totalRemainingBurstIops) {
+            _totalRemainingCapacity = totalRemainingCapacity;
+            _totalRemainingMinIops = totalRemainingMinIops;
+            _totalRemainingMaxIops = totalRemainingMaxIops;
+            _totalRemainingBurstIops = totalRemainingBurstIops;
+        }
+
+        public long getTotalRemainingCapacity() {
+            return _totalRemainingCapacity;
+        }
+
+        public long getTotalRemainingMinIops() {
+            return _totalRemainingMinIops;
+        }
+
+        public long getTotalRemainingMaxIops() {
+            return _totalRemainingMaxIops;
+        }
+
+        public long getTotalRemainingBurstIops() {
+            return _totalRemainingBurstIops;
+        }
+    }
+
+    private static String getSolidFireAccountName(long accountId, String accountUuid) {
+        return "CloudStack_" + accountId + "_" + accountUuid;
+    }
+
+    private static String getAccountKey(long sfClusterId) {
+        return "sfAccountIdForClusterId_" + sfClusterId;
+    }
+
+    private AccountDetailVO getAccountDetail(long accountId, long sfClusterId) {
+        return _accountDetailsDao.findDetail(accountId, getAccountKey(sfClusterId));
+    }
+
+    private SolidFireConnection.SolidFireAccount createSolidFireAccount(SolidFireConnection sfConnection, String sfAccountName) {
+        long accountNumber = sfConnection.createSolidFireAccount(sfAccountName);
+
+        return sfConnection.getSolidFireAccountById(accountNumber);
+    }
+
+    private void updateCsDbWithSolidFireAccountInfo(long accountId, SolidFireConnection.SolidFireAccount sfAccount, long sfClusterId) {
+        AccountDetailVO accountDetail = new AccountDetailVO(accountId,
+                getAccountKey(sfClusterId),
+                String.valueOf(sfAccount.getId()));
+
+        _accountDetailsDao.persist(accountDetail);
+
+        accountDetail = new AccountDetailVO(accountId,
+                SolidFireUtil.CHAP_INITIATOR_USERNAME,
+                sfAccount.getName());
+
+        _accountDetailsDao.persist(accountDetail);
+
+        accountDetail = new AccountDetailVO(accountId,
+                SolidFireUtil.CHAP_INITIATOR_SECRET,
+                sfAccount.getInitiatorSecret());
+
+        _accountDetailsDao.persist(accountDetail);
+
+        accountDetail = new AccountDetailVO(accountId,
+                SolidFireUtil.CHAP_TARGET_USERNAME,
+                sfAccount.getName());
+
+        _accountDetailsDao.persist(accountDetail);
+
+        accountDetail = new AccountDetailVO(accountId,
+                SolidFireUtil.CHAP_TARGET_SECRET,
+                sfAccount.getTargetSecret());
+
+        _accountDetailsDao.persist(accountDetail);
+    }
+
+    private List<SfVirtualNetwork> filterVirtualNetworksByCluster(List<SfVirtualNetworkVO> sfVirtualNetworkVOs, long clusterId) {
+        List<SfVirtualNetwork> sfVirtualNetworkVOsToReturn = new ArrayList<>();
+
+        if (sfVirtualNetworkVOs != null) {
+            for (SfVirtualNetworkVO sfVirtualNetworkVO : sfVirtualNetworkVOs) {
+                long sfClusterId = sfVirtualNetworkVO.getSfClusterId();
+
+                if (sfClusterId == clusterId) {
+                    sfVirtualNetworkVOsToReturn.add(sfVirtualNetworkVO);
+                }
+            }
+        }
+
+        return sfVirtualNetworkVOsToReturn;
+    }
+
+    private List<SfVirtualNetworkVO> filterVirtualNetworksByZone(List<SfVirtualNetworkVO> sfVirtualNetworkVOs, long zoneId) {
+        List<SfVirtualNetworkVO> sfVirtualNetworkVOsToReturn = new ArrayList<>();
+
+        if (sfVirtualNetworkVOs != null) {
+            for (SfVirtualNetworkVO sfVirtualNetworkVO : sfVirtualNetworkVOs) {
+                SfCluster sfCluster = getSfCluster(sfVirtualNetworkVO.getSfClusterId());
+
+                if (sfCluster.getZoneId() == zoneId) {
+                    sfVirtualNetworkVOsToReturn.add(sfVirtualNetworkVO);
+                }
+            }
+        }
+
+        return sfVirtualNetworkVOsToReturn;
+    }
+
+    private static void verifyIops(long minIops, long maxIops, long burstIops) {
+        if (minIops <= 0 || maxIops <= 0 || burstIops <= 0) {
+            throw new IllegalArgumentException("The 'Min IOPS', 'Max IOPS', and 'Burst IOPS' values must be greater than 0.");
+        }
+
+        if (minIops > maxIops) {
+            throw new IllegalArgumentException("The 'Min IOPS' value cannot exceed the 'Max IOPS' value.");
+        }
+
+        if (maxIops > burstIops) {
+            throw new IllegalArgumentException("The 'Max IOPS' value cannot exceed the 'Burst IOPS' value.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/util/solidfire/SfUtil.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/util/solidfire/SfUtil.java b/plugins/api/solidfire/src/org/apache/cloudstack/util/solidfire/SfUtil.java
new file mode 100644
index 0000000..ea9df30
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/util/solidfire/SfUtil.java
@@ -0,0 +1,221 @@
+package org.apache.cloudstack.util.solidfire;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.ResponseObject.ResponseView;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireClusterResponse;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireVirtualNetworkResponse;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireVolumeResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.dataaccess.dao.solidfire.SfClusterDao;
+import org.apache.cloudstack.dataaccess.dao.solidfire.SfVirtualNetworkDao;
+import org.apache.cloudstack.solidfire.SfCluster;
+import org.apache.cloudstack.solidfire.SfVirtualNetwork;
+import org.apache.cloudstack.solidfire.SfVolume;
+import org.apache.cloudstack.storage.datastore.util.SolidFireUtil;
+
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.user.Account;
+import com.cloud.user.AccountDetailVO;
+import com.cloud.user.AccountDetailsDao;
+import com.cloud.user.AccountManager;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+public class SfUtil {
+    @Inject private AccountDao _accountDao;
+    @Inject private AccountDetailsDao _accountDetailsDao;
+    @Inject private AccountManager _accountMgr;
+    @Inject private SfClusterDao _sfClusterDao;
+    @Inject private DataCenterDao _zoneDao;
+    @Inject private SfVirtualNetworkDao _sfVirtualNetworkDao;
+
+    private SfUtil() {
+    }
+
+    public ApiSolidFireClusterResponse getApiSolidFireClusterResponse(SfCluster sfCluster) {
+        ApiSolidFireClusterResponse sfResponse = new ApiSolidFireClusterResponse();
+
+        sfResponse.setId(sfCluster.getId());
+        sfResponse.setUuid(sfCluster.getUuid());
+        sfResponse.setName(sfCluster.getName());
+        sfResponse.setMvip(sfCluster.getMvip());
+        sfResponse.setUsername(sfCluster.getUsername());
+        sfResponse.setTotalCapacity(sfCluster.getTotalCapacity());
+        sfResponse.setTotalMinIops(sfCluster.getTotalMinIops());
+        sfResponse.setTotalMaxIops(sfCluster.getTotalMaxIops());
+        sfResponse.setTotalBurstIops(sfCluster.getTotalBurstIops());
+        sfResponse.setZoneId(sfCluster.getZoneId());
+
+        DataCenterVO dataCenterVO = _zoneDao.findById(sfCluster.getZoneId());
+
+        sfResponse.setZoneName(dataCenterVO.getName());
+
+        sfResponse.setObjectName("sfcluster");
+
+        return sfResponse;
+    }
+
+    public List<ApiSolidFireClusterResponse> getApiSolidFireClusterResponse(List<SfCluster> sfClusters) {
+        List<ApiSolidFireClusterResponse> sfResponse = new ArrayList<>();
+
+        if (sfClusters != null) {
+            for (SfCluster sfCluster : sfClusters) {
+                ApiSolidFireClusterResponse response = getApiSolidFireClusterResponse(sfCluster);
+
+                sfResponse.add(response);
+            }
+        }
+
+        return sfResponse;
+    }
+
+    public ApiSolidFireVirtualNetworkResponse getApiSolidFireVirtualNetworkResponse(SfVirtualNetwork sfVirtualNetwork, ResponseView responseView) {
+        ApiSolidFireVirtualNetworkResponse sfResponse = new ApiSolidFireVirtualNetworkResponse();
+
+        sfResponse.setId(sfVirtualNetwork.getId());
+        sfResponse.setUuid(sfVirtualNetwork.getUuid());
+        sfResponse.setName(sfVirtualNetwork.getName());
+        sfResponse.setSvip(sfVirtualNetwork.getSvip());
+        sfResponse.setAccountId(sfVirtualNetwork.getAccountId());
+
+        Account account = _accountDao.findById(sfVirtualNetwork.getAccountId());
+
+        sfResponse.setAccountUuid(account.getUuid());
+        sfResponse.setAccountName(account.getAccountName());
+
+        SfCluster sfCluster = _sfClusterDao.findById(sfVirtualNetwork.getSfClusterId());
+
+        sfResponse.setZoneId(sfCluster.getZoneId());
+
+        DataCenterVO dataCenterVO = _zoneDao.findById(sfCluster.getZoneId());
+
+        sfResponse.setZoneUuid(dataCenterVO.getUuid());
+        sfResponse.setZoneName(dataCenterVO.getName());
+
+        if (ResponseView.Full.equals(responseView)) {
+            sfResponse.setTag(sfVirtualNetwork.getTag());
+            sfResponse.setStartIp(sfVirtualNetwork.getStartIp());
+            sfResponse.setSize(sfVirtualNetwork.getSize());
+            sfResponse.setNetmask(sfVirtualNetwork.getNetmask());
+            sfResponse.setClusterName(sfCluster.getName());
+        }
+
+        sfResponse.setObjectName("sfvirtualnetwork");
+
+        return sfResponse;
+    }
+
+    public List<ApiSolidFireVirtualNetworkResponse> getApiSolidFireVirtualNetworkResponse(List<SfVirtualNetwork> sfVirtualNetworks, ResponseView responseView) {
+        List<ApiSolidFireVirtualNetworkResponse> sfResponse = new ArrayList<>();
+
+        if (sfVirtualNetworks != null) {
+            for (SfVirtualNetwork sfVirtualNetwork : sfVirtualNetworks) {
+                ApiSolidFireVirtualNetworkResponse response = getApiSolidFireVirtualNetworkResponse(sfVirtualNetwork, responseView);
+
+                sfResponse.add(response);
+            }
+        }
+
+        return sfResponse;
+    }
+
+    public ApiSolidFireVolumeResponse getApiSolidFireVolumeResponse(SfVolume sfVolume, ResponseView responseView) {
+        ApiSolidFireVolumeResponse sfResponse = new ApiSolidFireVolumeResponse();
+
+        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());
+        sfResponse.setBurstIops(sfVolume.getBurstIops());
+        sfResponse.setCreated(sfVolume.getCreated());
+
+        SfVirtualNetwork sfVirtualNetwork = _sfVirtualNetworkDao.findById(sfVolume.getSfVirtualNetworkId());
+
+        sfResponse.setAccountId(sfVirtualNetwork.getAccountId());
+
+        Account account = _accountDao.findById(sfVirtualNetwork.getAccountId());
+
+        sfResponse.setAccountUuid(account.getUuid());
+        sfResponse.setAccountName(account.getAccountName());
+
+        SfCluster sfCluster = _sfClusterDao.findById(sfVirtualNetwork.getSfClusterId());
+
+        sfResponse.setZoneId(sfCluster.getZoneId());
+
+        DataCenterVO dataCenterVO = _zoneDao.findById(sfCluster.getZoneId());
+
+        sfResponse.setZoneUuid(dataCenterVO.getUuid());
+        sfResponse.setZoneName(dataCenterVO.getName());
+
+        if (ResponseView.Full.equals(responseView)) {
+            sfResponse.setClusterName(sfCluster.getName());
+        }
+
+        sfResponse.setTargetPortal(sfVirtualNetwork.getSvip());
+        sfResponse.setVlanId(sfVirtualNetwork.getId());
+        sfResponse.setVlanUuid(sfVirtualNetwork.getUuid());
+        sfResponse.setVlanName(sfVirtualNetwork.getName());
+
+        AccountDetailVO accountDetail = _accountDetailsDao.findDetail(sfVirtualNetwork.getAccountId(), SolidFireUtil.CHAP_INITIATOR_USERNAME);
+
+        sfResponse.setChapInitiatorUsername(accountDetail.getValue());
+
+        accountDetail = _accountDetailsDao.findDetail(sfVirtualNetwork.getAccountId(), SolidFireUtil.CHAP_INITIATOR_SECRET);
+
+        sfResponse.setChapInitiatorSecret(accountDetail.getValue());
+
+        accountDetail = _accountDetailsDao.findDetail(sfVirtualNetwork.getAccountId(), SolidFireUtil.CHAP_TARGET_USERNAME);
+
+        sfResponse.setChapTargetUsername(accountDetail.getValue());
+
+        accountDetail = _accountDetailsDao.findDetail(sfVirtualNetwork.getAccountId(), SolidFireUtil.CHAP_TARGET_SECRET);
+
+        sfResponse.setChapTargetSecret(accountDetail.getValue());
+
+        sfResponse.setObjectName("sfvolume");
+
+        return sfResponse;
+    }
+
+    public List<ApiSolidFireVolumeResponse> getApiSolidFireVolumeResponse(List<SfVolume> sfVolumes, ResponseView responseView) {
+        List<ApiSolidFireVolumeResponse> sfResponse = new ArrayList<>();
+
+        if (sfVolumes != null) {
+            for (SfVolume sfVolume : sfVolumes) {
+                ApiSolidFireVolumeResponse response = getApiSolidFireVolumeResponse(sfVolume, responseView);
+
+                sfResponse.add(response);
+            }
+        }
+
+        return sfResponse;
+    }
+
+    public boolean isRootAdmin() {
+        Account account = getCallingAccount();
+
+        return isRootAdmin(account.getId());
+    }
+
+    public boolean isRootAdmin(long accountId) {
+        return _accountMgr.isRootAdmin(accountId);
+    }
+
+    public Account getCallingAccount() {
+        Account account = CallContext.current().getCallingAccount();
+
+        if (account == null) {
+            throw new CloudRuntimeException("The user's account cannot be determined.");
+        }
+
+        return account;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/util/solidfire/SolidFireConnection.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/util/solidfire/SolidFireConnection.java b/plugins/api/solidfire/src/org/apache/cloudstack/util/solidfire/SolidFireConnection.java
new file mode 100644
index 0000000..e9e011c
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/util/solidfire/SolidFireConnection.java
@@ -0,0 +1,950 @@
+// 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.util.solidfire;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+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.methods.HttpPost;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+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;
+    private final String _clusterAdminPassword;
+
+    public SolidFireConnection(String managementVip, String clusterAdminUsername, String clusterAdminPassword) {
+        _managementVip = managementVip;
+        _clusterAdminUsername = clusterAdminUsername;
+        _clusterAdminPassword = clusterAdminPassword;
+    }
+
+    public String getClusterName() {
+        final Gson gson = new GsonBuilder().create();
+
+        ClusterInfoToGet clusterInfoToGet = new ClusterInfoToGet();
+
+        String strClusterInfoToGetJson = gson.toJson(clusterInfoToGet);
+
+        String strClusterInfoToGetResultJson = executeJsonRpc(strClusterInfoToGetJson);
+
+        ClusterInfoGetResult clusterInfoGetResult = gson.fromJson(strClusterInfoToGetResultJson, ClusterInfoGetResult.class);
+
+        verifyResult(clusterInfoGetResult.result, strClusterInfoToGetResultJson, gson);
+
+        return clusterInfoGetResult.result.clusterInfo.name;
+    }
+
+    public long createVirtualNetwork(String name, String tag, String startIp, int size, String netmask, String svip) {
+        final Gson gson = new GsonBuilder().create();
+
+        VirtualNetworkToAdd virtualNetworkToAdd = new VirtualNetworkToAdd(name, tag, startIp, size, netmask, svip);
+
+        String strVirtualNetworkToAddJson = gson.toJson(virtualNetworkToAdd);
+
+        String strVirtualNetworkToAddResultJson = executeJsonRpc(strVirtualNetworkToAddJson);
+
+        VirtualNetworkAddResult virtualNetworkAddResult = gson.fromJson(strVirtualNetworkToAddResultJson, VirtualNetworkAddResult.class);
+
+        verifyResult(virtualNetworkAddResult.result, strVirtualNetworkToAddResultJson, gson);
+
+        return virtualNetworkAddResult.result.virtualNetworkID;
+    }
+
+    public void modifyVirtualNetwork(long id, String name, String startIp, int size, String netmask) {
+        final Gson gson = new GsonBuilder().create();
+
+        VirtualNetworkToModify virtualNetworkToModify = new VirtualNetworkToModify(id, name, startIp, size, netmask);
+
+        String strVirtualNetworkToModifyJson = gson.toJson(virtualNetworkToModify);
+
+        String strVirtualNetworkToModifyResultJson = executeJsonRpc(strVirtualNetworkToModifyJson);
+
+        JsonError jsonError = gson.fromJson(strVirtualNetworkToModifyResultJson, JsonError.class);
+
+        if (jsonError.error != null) {
+            throw new IllegalStateException(jsonError.error.message);
+        }
+    }
+
+    public void deleteVirtualNetwork(long id) {
+        final Gson gson = new GsonBuilder().create();
+
+        VirtualNetworkToDelete virtualNetworkToDelete = new VirtualNetworkToDelete(id);
+
+        String strVolumeToDeleteJson = gson.toJson(virtualNetworkToDelete);
+
+        String strVirtualNetworkToDeleteResultJson = executeJsonRpc(strVolumeToDeleteJson);
+
+        JsonError jsonError = gson.fromJson(strVirtualNetworkToDeleteResultJson, JsonError.class);
+
+        if (jsonError.error != null) {
+            throw new IllegalStateException(jsonError.error.message);
+        }
+    }
+
+    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();
+
+        long totalSizeInBytes = convertGBsToBytes(totalSizeInGBs);
+
+        VolumeToCreate volumeToCreate = new VolumeToCreate(name, accountId, totalSizeInBytes, true, minIops, maxIops, burstIops);
+
+        String strVolumeToCreateJson = gson.toJson(volumeToCreate);
+
+        String strVolumeCreateResultJson = executeJsonRpc(strVolumeToCreateJson);
+
+        VolumeCreateResult volumeCreateResult = gson.fromJson(strVolumeCreateResultJson, VolumeCreateResult.class);
+
+        verifyResult(volumeCreateResult.result, strVolumeCreateResultJson, gson);
+
+        return volumeCreateResult.result.volumeID;
+    }
+
+    public void modifyVolume(long volumeId, long totalSizeInGBs, long minIops, long maxIops, long burstIops)
+    {
+        final Gson gson = new GsonBuilder().create();
+
+        long totalSizeInBytes = convertGBsToBytes(totalSizeInGBs);
+
+        VolumeToModify volumeToModify = new VolumeToModify(volumeId, totalSizeInBytes, minIops, maxIops, burstIops);
+
+        String strVolumeToModifyJson = gson.toJson(volumeToModify);
+
+        String strVolumeModifyResultJson = executeJsonRpc(strVolumeToModifyJson);
+
+        JsonError jsonError = gson.fromJson(strVolumeModifyResultJson, JsonError.class);
+
+        if (jsonError.error != null) {
+            throw new IllegalStateException(jsonError.error.message);
+        }
+    }
+
+    public void deleteVolume(long id)
+    {
+        final Gson gson = new GsonBuilder().create();
+
+        VolumeToDelete volumeToDelete = new VolumeToDelete(id);
+
+        String strVolumeToDeleteJson = gson.toJson(volumeToDelete);
+
+        String strVolumeToDeleteResultJson = executeJsonRpc(strVolumeToDeleteJson);
+
+        JsonError jsonError = gson.fromJson(strVolumeToDeleteResultJson, JsonError.class);
+
+        if (jsonError.error != null) {
+            throw new IllegalStateException(jsonError.error.message);
+        }
+    }
+
+    public long createSolidFireAccount(String strAccountName)
+    {
+        final Gson gson = new GsonBuilder().create();
+
+        AccountToAdd accountToAdd = new AccountToAdd(strAccountName);
+
+        String strAccountAddJson = gson.toJson(accountToAdd);
+
+        String strAccountAddResultJson = executeJsonRpc(strAccountAddJson);
+
+        AccountAddResult accountAddResult = gson.fromJson(strAccountAddResultJson, AccountAddResult.class);
+
+        verifyResult(accountAddResult.result, strAccountAddResultJson, gson);
+
+        return accountAddResult.result.accountID;
+    }
+
+    public SolidFireAccount getSolidFireAccount(String sfAccountName) {
+        try {
+            return getSolidFireAccountByName(sfAccountName);
+        } catch (Exception ex) {
+            return null;
+        }
+    }
+
+    public SolidFireAccount getSolidFireAccountById(long lSfAccountId)
+    {
+        final Gson gson = new GsonBuilder().create();
+
+        AccountToGetById accountToGetById = new AccountToGetById(lSfAccountId);
+
+        String strAccountToGetByIdJson = gson.toJson(accountToGetById);
+
+        String strAccountGetByIdResultJson = executeJsonRpc(strAccountToGetByIdJson);
+
+        AccountGetResult accountGetByIdResult = gson.fromJson(strAccountGetByIdResultJson, AccountGetResult.class);
+
+        verifyResult(accountGetByIdResult.result, strAccountGetByIdResultJson, gson);
+
+        String strSfAccountName = accountGetByIdResult.result.account.username;
+        String strSfAccountInitiatorSecret = accountGetByIdResult.result.account.initiatorSecret;
+        String strSfAccountTargetSecret = accountGetByIdResult.result.account.targetSecret;
+
+        return new SolidFireAccount(lSfAccountId, strSfAccountName, strSfAccountInitiatorSecret, strSfAccountTargetSecret);
+    }
+
+    public SolidFireAccount getSolidFireAccountByName(String strSfAccountName)
+    {
+        final Gson gson = new GsonBuilder().create();
+
+        AccountToGetByName accountToGetByName = new AccountToGetByName(strSfAccountName);
+
+        String strAccountToGetByNameJson = gson.toJson(accountToGetByName);
+
+        String strAccountGetByNameResultJson = executeJsonRpc(strAccountToGetByNameJson);
+
+        AccountGetResult accountGetByNameResult = gson.fromJson(strAccountGetByNameResultJson, AccountGetResult.class);
+
+        verifyResult(accountGetByNameResult.result, strAccountGetByNameResultJson, gson);
+
+        long lSfAccountId = accountGetByNameResult.result.account.accountID;
+        String strSfAccountInitiatorSecret = accountGetByNameResult.result.account.initiatorSecret;
+        String strSfAccountTargetSecret = accountGetByNameResult.result.account.targetSecret;
+
+        return new SolidFireAccount(lSfAccountId, strSfAccountName, strSfAccountInitiatorSecret, strSfAccountTargetSecret);
+    }
+
+    private String executeJsonRpc(String strJsonToExecute) {
+        DefaultHttpClient httpClient = null;
+        StringBuilder sb = new StringBuilder();
+
+        try {
+            StringEntity input = new StringEntity(strJsonToExecute);
+
+            input.setContentType("application/json");
+
+            httpClient = getHttpClient(_managementPort);
+
+            URI uri = new URI("https://" + _managementVip + ":" + _managementPort + "/json-rpc/7.0");
+            AuthScope authScope = new AuthScope(uri.getHost(), uri.getPort(), AuthScope.ANY_SCHEME);
+            UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(_clusterAdminUsername, _clusterAdminPassword);
+
+            httpClient.getCredentialsProvider().setCredentials(authScope, credentials);
+
+            HttpPost postRequest = new HttpPost(uri);
+
+            postRequest.setEntity(input);
+
+            HttpResponse response = httpClient.execute(postRequest);
+
+            if (!isSuccess(response.getStatusLine().getStatusCode())) {
+                throw new CloudRuntimeException("Failed on JSON-RPC API call. HTTP error code = " + response.getStatusLine().getStatusCode());
+            }
+
+            try(BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));) {
+                String strOutput;
+                while ((strOutput = br.readLine()) != null) {
+                    sb.append(strOutput);
+                }
+            }catch (IOException ex) {
+                throw new CloudRuntimeException(ex.getMessage());
+            }
+        } catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new CloudRuntimeException(t.getMessage());
+        } finally {
+            if (httpClient != null) {
+                try {
+                    httpClient.getConnectionManager().shutdown();
+                } catch (Exception t) {
+                }
+            }
+        }
+
+        return sb.toString();
+    }
+
+    private static DefaultHttpClient getHttpClient(int iPort) {
+        DefaultHttpClient client = null;
+
+        try {
+            SSLContext sslContext = SSLUtils.getSSLContext();
+
+            X509TrustManager tm = new X509TrustManager() {
+                @Override
+                public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
+                }
+
+                @Override
+                public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
+                }
+
+                @Override
+                public X509Certificate[] getAcceptedIssuers() {
+                    return null;
+                }
+            };
+
+            sslContext.init(null, new TrustManager[] { tm }, new SecureRandom());
+
+            SSLSocketFactory socketFactory = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+            SchemeRegistry registry = new SchemeRegistry();
+
+            registry.register(new Scheme("https", iPort, socketFactory));
+
+            BasicClientConnectionManager mgr = new BasicClientConnectionManager(registry);
+            client = new DefaultHttpClient();
+
+            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) {
+                try {
+                    client.close();
+                }
+                catch (Throwable t) {
+                    s_logger.error(t.getMessage());
+
+                    throw t;
+                }
+            }
+        }
+    }
+
+    private static boolean isSuccess(int iCode) {
+        return iCode >= 200 && iCode < 300;
+    }
+
+    @SuppressWarnings("unused")
+    private static final class ClusterInfoToGet {
+        private final String method = "GetClusterInfo";
+    }
+
+    @SuppressWarnings("unused")
+    private static final class VirtualNetworkToAdd {
+        private final String method = "AddVirtualNetwork";
+        private final VirtualNetworkToAddParams params;
+
+        public VirtualNetworkToAdd(String name, String tag, String startIp, int size, String netmask, String svip) {
+            params = new VirtualNetworkToAddParams(name, tag, startIp, size, netmask, svip);
+        }
+
+        private static final class VirtualNetworkToAddParams {
+            private final String name;
+            private final String virtualNetworkTag;
+            private final AddressBlock[] addressBlocks = new AddressBlock[1];
+            private final String netmask;
+            private final String svip;
+
+            public VirtualNetworkToAddParams(String name, String tag, String startIp, int size, String netmask, String svip) {
+                this.name = name;
+                this.virtualNetworkTag = tag;
+
+                this.addressBlocks[0] = new AddressBlock(startIp, size);
+
+                this.netmask = netmask;
+                this.svip = svip;
+            }
+
+            private static final class AddressBlock {
+                private final String start;
+                private final int size;
+
+                public AddressBlock(String start, int size) {
+                    this.start = start;
+                    this.size = size;
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static final class VirtualNetworkToModify {
+        private final String method = "ModifyVirtualNetwork";
+        private final VirtualNetworkToModifyParams params;
+
+        public VirtualNetworkToModify(long id, String name, String startIp, int size, String netmask) {
+            params = new VirtualNetworkToModifyParams(id, name, startIp, size, netmask);
+        }
+
+        private static final class VirtualNetworkToModifyParams {
+            private final long virtualNetworkID;
+            private final String name;
+            private final AddressBlock[] addressBlocks = new AddressBlock[1];
+            private final String netmask;
+
+            public VirtualNetworkToModifyParams(long id, String name, String startIp, int size, String netmask) {
+                this.virtualNetworkID = id;
+                this.name = name;
+
+                this.addressBlocks[0] = new AddressBlock(startIp, size);
+
+                this.netmask = netmask;
+            }
+
+            private static final class AddressBlock {
+                private final String start;
+                private final int size;
+
+                public AddressBlock(String start, int size) {
+                    this.start = start;
+                    this.size = size;
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static final class VirtualNetworkToDelete
+    {
+        private final String method = "RemoveVirtualNetwork";
+        private final VirtualNetworkToDeleteParams params;
+
+        private VirtualNetworkToDelete(long id) {
+            params = new VirtualNetworkToDeleteParams(id);
+        }
+
+        private static final class VirtualNetworkToDeleteParams {
+            private final long virtualNetworkID;
+
+            private VirtualNetworkToDeleteParams(long id) {
+                virtualNetworkID = id;
+            }
+        }
+    }
+
+    @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;
+
+        private VolumeToCreate(final String strVolumeName, final long lAccountId, final long lTotalSize, final boolean bEnable512e,
+                final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) {
+            params = new VolumeToCreateParams(strVolumeName, lAccountId, lTotalSize, bEnable512e, lMinIOPS, lMaxIOPS, lBurstIOPS);
+        }
+
+        private static final class VolumeToCreateParams {
+            private final String name;
+            private final long accountID;
+            private final long totalSize;
+            private final boolean enable512e;
+            private final VolumeToCreateParamsQoS qos;
+
+            private VolumeToCreateParams(final String strVolumeName, final long lAccountId, final long lTotalSize, final boolean bEnable512e,
+                    final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) {
+                name = strVolumeName;
+                accountID = lAccountId;
+                totalSize = lTotalSize;
+                enable512e = bEnable512e;
+
+                qos = new VolumeToCreateParamsQoS(lMinIOPS, lMaxIOPS, lBurstIOPS);
+            }
+
+            private static final class VolumeToCreateParamsQoS {
+                private final long minIOPS;
+                private final long maxIOPS;
+                private final long burstIOPS;
+
+                private VolumeToCreateParamsQoS(final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) {
+                    minIOPS = lMinIOPS;
+                    maxIOPS = lMaxIOPS;
+                    burstIOPS = lBurstIOPS;
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static final class VolumeToModify
+    {
+        private final String method = "ModifyVolume";
+        private final VolumeToModifyParams params;
+
+        private VolumeToModify(long id, long totalSize, long minIOPS, long maxIOPS, long burstIOPS)
+        {
+            params = new VolumeToModifyParams(id, totalSize, minIOPS, maxIOPS, burstIOPS);
+        }
+
+        private static final class VolumeToModifyParams
+        {
+            private final long volumeID;
+            private final long totalSize;
+            private final VolumeToModifyParamsQoS qos;
+
+            private VolumeToModifyParams(long id, long totalSize, long minIOPS, long maxIOPS, long burstIOPS)
+            {
+                this.volumeID = id;
+                this.totalSize = totalSize;
+
+                this.qos = new VolumeToModifyParamsQoS(minIOPS, maxIOPS, burstIOPS);
+            }
+        }
+
+        private static final class VolumeToModifyParamsQoS {
+            private final long minIOPS;
+            private final long maxIOPS;
+            private final long burstIOPS;
+
+            private VolumeToModifyParamsQoS(long minIOPS, long maxIOPS, long burstIOPS) {
+                this.minIOPS = minIOPS;
+                this.maxIOPS = maxIOPS;
+                this.burstIOPS = burstIOPS;
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static final class VolumeToDelete
+    {
+        private final String method = "DeleteVolume";
+        private final VolumeToDeleteParams params;
+
+        private VolumeToDelete(final long lVolumeId) {
+            params = new VolumeToDeleteParams(lVolumeId);
+        }
+
+        private static final class VolumeToDeleteParams {
+            private long volumeID;
+
+            private VolumeToDeleteParams(final long lVolumeId) {
+                volumeID = lVolumeId;
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static final class AccountToAdd
+    {
+        private final String method = "AddAccount";
+        private final AccountToAddParams params;
+
+        private AccountToAdd(final String strAccountName)
+        {
+            params = new AccountToAddParams(strAccountName);
+        }
+
+        private static final class AccountToAddParams
+        {
+            private final String username;
+
+            private AccountToAddParams(final String strAccountName)
+            {
+                username = strAccountName;
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static final class AccountToGetById
+    {
+        private final String method = "GetAccountByID";
+        private final AccountToGetByIdParams params;
+
+        private AccountToGetById(final long lAccountId)
+        {
+            params = new AccountToGetByIdParams(lAccountId);
+        }
+
+        private static final class AccountToGetByIdParams
+        {
+            private final long accountID;
+
+            private AccountToGetByIdParams(final long lAccountId)
+            {
+                accountID = lAccountId;
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static final class AccountToGetByName
+    {
+        private final String method = "GetAccountByName";
+        private final AccountToGetByNameParams params;
+
+        private AccountToGetByName(final String strUsername)
+        {
+            params = new AccountToGetByNameParams(strUsername);
+        }
+
+        private static final class AccountToGetByNameParams
+        {
+            private final String username;
+
+            private AccountToGetByNameParams(final String strUsername)
+            {
+                username = strUsername;
+            }
+        }
+    }
+
+    private static final class ClusterInfoGetResult
+    {
+        private Result result;
+
+        private static final class Result
+        {
+            private ClusterInfo clusterInfo;
+
+            private static final class ClusterInfo
+            {
+                private String name;
+            }
+        }
+    }
+
+    private static final class VirtualNetworkAddResult
+    {
+        private Result result;
+
+        private static final class Result
+        {
+            private long virtualNetworkID;
+        }
+    }
+
+    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;
+
+        private static final class Result {
+            private long volumeID;
+        }
+    }
+
+    private static final class AccountAddResult {
+        private Result result;
+
+        private static final class Result {
+            private long accountID;
+        }
+    }
+
+    private static final class AccountGetResult {
+        private Result result;
+
+        private static final class Result {
+            private Account account;
+
+            private static final class Account {
+                private long accountID;
+                private String username;
+                private String initiatorSecret;
+                private String targetSecret;
+            }
+        }
+    }
+
+    private static final class JsonError
+    {
+        private Error error;
+
+        private static final class Error {
+            private String message;
+        }
+    }
+
+    private static void verifyResult(Object result, String strJson, Gson gson) throws IllegalStateException {
+        if (result != null) {
+            return;
+        }
+
+        JsonError jsonError = gson.fromJson(strJson, JsonError.class);
+
+        if (jsonError != null) {
+            throw new IllegalStateException(jsonError.error.message);
+        }
+
+        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;
+        private final String _name;
+        private final String _initiatorSecret;
+        private final String _targetSecret;
+
+        public SolidFireAccount(long id, String name, String initiatorSecret, String targetSecret) {
+            _id = id;
+            _name = name;
+            _initiatorSecret = initiatorSecret;
+            _targetSecret = targetSecret;
+        }
+
+        public long getId() {
+            return _id;
+        }
+
+        public String getName() {
+            return _name;
+        }
+
+        public String getInitiatorSecret() {
+            return _initiatorSecret;
+        }
+
+        public String getTargetSecret() {
+            return _targetSecret;
+        }
+
+        @Override
+        public int hashCode() {
+            return (_id + _name).hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return _name;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == null) {
+                return false;
+            }
+
+            if (!obj.getClass().equals(SolidFireAccount.class)) {
+                return false;
+            }
+
+            SolidFireAccount sfa = (SolidFireAccount)obj;
+
+            if (_id == sfa._id && _name.equals(sfa._name) &&
+                _initiatorSecret.equals(sfa._initiatorSecret) &&
+                _targetSecret.equals(sfa._targetSecret)) {
+                return true;
+            }
+
+            return false;
+        }
+    }
+
+    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 + ".");
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 1706fe8..cf74dc4 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -38,6 +38,7 @@
   </build>
   <modules>
     <module>api/rate-limit</module>
+    <module>api/solidfire</module>
     <module>api/solidfire-intg-test</module>
     <module>api/discovery</module>
     <module>acl/static-role-based</module>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java
index dcbabe6..6c6c41d 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java
@@ -259,8 +259,10 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
         Integer hypervisorSnapshotReserve = volume.getHypervisorSnapshotReserve();
 
         if (hypervisorSnapshotReserve != null) {
-            if (hypervisorSnapshotReserve < 50) {
-                hypervisorSnapshotReserve = 50;
+            int minimumHypervisorSnapshotReserve = 10;
+
+            if (hypervisorSnapshotReserve < minimumHypervisorSnapshotReserve) {
+                hypervisorSnapshotReserve = minimumHypervisorSnapshotReserve;
             }
 
             volumeSize += volumeSize * (hypervisorSnapshotReserve / 100f);


[3/7] git commit: updated refs/heads/sf-plugins-a to 49ca3b4

Posted by mt...@apache.org.
Merge pull request #922 from resmo/fix/4.5-8848

[4.5] CLOUDSTACK-8848: ensure power state is up to date for missing PowerState handling1:1 cherry-picks, see #909

* pr/922:
  CLOUDSTACK-8848: added null pointer guard to new public method
  CLOUDSTACK-8848: ensure power state is up to date when handling missing VMs in powerReport

Signed-off-by: Rohit Yadav <ro...@shapeblue.com>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/59f337da
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/59f337da
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/59f337da

Branch: refs/heads/sf-plugins-a
Commit: 59f337da56b9824f7026fd855b4357b78584ed13
Parents: f1f1fef 8cd8b6c
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Tue Oct 13 15:06:25 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Tue Oct 13 15:06:25 2015 +0530

----------------------------------------------------------------------
 .../cloud/vm/VirtualMachinePowerStateSyncImpl.java  | 16 ++++++++++++++--
 .../schema/src/com/cloud/vm/dao/VMInstanceDao.java  |  2 ++
 .../src/com/cloud/vm/dao/VMInstanceDaoImpl.java     |  9 +++++++++
 3 files changed, 25 insertions(+), 2 deletions(-)
----------------------------------------------------------------------



[4/7] git commit: updated refs/heads/sf-plugins-a to 49ca3b4

Posted by mt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFireSharedPrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFireSharedPrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFireSharedPrimaryDataStoreDriver.java
index a16408e..365533c 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFireSharedPrimaryDataStoreDriver.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFireSharedPrimaryDataStoreDriver.java
@@ -16,50 +16,5 @@
 // under the License.
 package org.apache.cloudstack.storage.datastore.driver;
 
-import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
-import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
-import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
-import org.apache.cloudstack.storage.command.CommandResult;
-
-import com.cloud.agent.api.to.DataStoreTO;
-import com.cloud.agent.api.to.DataTO;
-
 public class SolidFireSharedPrimaryDataStoreDriver extends CloudStackPrimaryDataStoreDriverImpl {
-    @Override
-    public DataTO getTO(DataObject data) {
-        return null;
-    }
-
-    @Override
-    public DataStoreTO getStoreTO(DataStore store) {
-        return null;
-    }
-
-    @Override
-    public boolean canCopy(DataObject srcData, DataObject destData) {
-        return false;
-    }
-
-    @Override
-    public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void resize(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CommandResult> callback) {
-        throw new UnsupportedOperationException();
-    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/ui/plugins/plugins.js
----------------------------------------------------------------------
diff --git a/ui/plugins/plugins.js b/ui/plugins/plugins.js
index 386ec06..d115eef 100644
--- a/ui/plugins/plugins.js
+++ b/ui/plugins/plugins.js
@@ -16,6 +16,8 @@
 // under the License.
 (function($, cloudStack) {
   cloudStack.plugins = [
-    // 'testPlugin'
+    // 'testPlugin',
+    // 'sfSharedVolume',
+    // 'sfAdministration'
   ];
 }(jQuery, cloudStack));

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/ui/plugins/sfAdministration/config.js
----------------------------------------------------------------------
diff --git a/ui/plugins/sfAdministration/config.js b/ui/plugins/sfAdministration/config.js
new file mode 100644
index 0000000..376ae56
--- /dev/null
+++ b/ui/plugins/sfAdministration/config.js
@@ -0,0 +1,9 @@
+(function (cloudStack) {
+  cloudStack.plugins.sfAdministration.config = {
+    title: 'SolidFire Administration',
+    desc: 'SolidFire Administration',
+    externalLink: 'http://www.solidfire.com/',
+    authorName: 'Mike Tutkowski',
+    authorEmail: 'mike.tutkowski@solidfire.com'
+  };
+}(cloudStack));
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/ui/plugins/sfAdministration/icon.png
----------------------------------------------------------------------
diff --git a/ui/plugins/sfAdministration/icon.png b/ui/plugins/sfAdministration/icon.png
new file mode 100644
index 0000000..a313d35
Binary files /dev/null and b/ui/plugins/sfAdministration/icon.png differ

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/ui/plugins/sfAdministration/sfAdministration.js
----------------------------------------------------------------------
diff --git a/ui/plugins/sfAdministration/sfAdministration.js b/ui/plugins/sfAdministration/sfAdministration.js
new file mode 100644
index 0000000..ca07318
--- /dev/null
+++ b/ui/plugins/sfAdministration/sfAdministration.js
@@ -0,0 +1,566 @@
+(function (cloudStack) {
+  cloudStack.plugins.sfAdministration = function(plugin) {
+    plugin.ui.addSection({
+      id: 'sfAdministration',
+      title: 'SolidFire Administration',
+      sectionSelect: {
+        label: 'label.select-view',
+        preFilter: function() {
+          return ['sfAdministration'];
+        }
+      },
+      preFilter: function(args) {
+        return isAdmin();
+      },
+      sections: {
+        sfAdministration: {
+          id: 'sfAdministration',
+          type: 'select',
+          title: 'SolidFire Clusters',
+          listView: {
+            section: 'sfAdministration',
+            id: 'sfAdministration',
+            fields: {
+              name: { label: 'label.name' },
+              mvip: { label: 'MVIP' },
+              username: { label: 'Username' },
+              zonename: { label: 'label.zone' }
+            },
+            dataProvider: function(args) {
+              plugin.ui.apiCall('listSolidFireClusters', {
+                success: function(json) {
+                  var sfclustersfiltered = [];
+                  var sfclusters = json.listsolidfireclustersresponse.sfcluster;
+                  var search = args.filterBy.search.value == null ? "" : args.filterBy.search.value.toLowerCase();
+
+                  if (search == "") {
+                    sfclustersfiltered = sfclusters;
+                  }
+                  else {
+                    for (i = 0; i < sfclusters.length; i++) {
+                      sfcluster = sfclusters[i];
+
+                      if (sfcluster.name.toLowerCase().indexOf(search) > -1 ) {
+                        sfclustersfiltered.push(sfcluster);
+                      }
+                    }
+                  }
+
+                  args.response.success({ data: sfclustersfiltered });
+                },
+                error: function(errorMessage) {
+                  args.response.error(errorMessage);
+                }
+              });
+            },
+            actions: {
+              add: {
+                label: 'Add Reference to Cluster',
+                preFilter: function(args) {
+                  return true;
+                },
+                messages: {
+                  confirm: function(args) {
+                    return 'Please fill in the following data to add a reference to a cluster.';
+                  },
+                  notification: function(args) {
+                    return 'Add Reference to Cluster';
+                  }
+                },
+                createForm: {
+                  title: 'Add Reference to Cluster',
+                  desc: 'Please fill in the following data to add a reference to a cluster.',
+                  fields: {
+                    availabilityZone: {
+                      label: 'label.availability.zone',
+                      docID: 'helpVolumeAvailabilityZone',
+                      validation: {
+                        required: true
+                      },
+                      select: function(args) {
+                        $.ajax({
+                          url: createURL("listZones&available=true"),
+                          dataType: "json",
+                          async: true,
+                          success: function(json) {
+                            var zoneObjs = json.listzonesresponse.zone;
+
+                            args.response.success({
+                              descriptionField: 'name',
+                              data: zoneObjs
+                            });
+                          }
+                        });
+                      }
+                    },
+                    mvip: {
+                      label: 'MVIP',
+                      validation: {
+                        required: true
+                      }
+                    },
+                    username: {
+                      label: 'label.username',
+                      validation: {
+                        required: true
+                      }
+                    },
+                    password: {
+                      label: 'label.password',
+                      isPassword: true,
+                      validation: {
+                        required: true
+                      }
+                    },
+                    totalCapacity: {
+                      label: 'Total Capacity (in GB)',
+                      validation: {
+                        required: true,
+                        number: true
+                      }
+                    },
+                    totalMinIops: {
+                      label: 'Total Min IOPS',
+                      validation: {
+                        required: true,
+                        number: true
+                      }
+                    },
+                    totalMaxIops: {
+                      label: 'Total Max IOPS',
+                      validation: {
+                        required: true,
+                        number: true
+                      }
+                    },
+                    totalBurstIops: {
+                      label: 'Total Burst IOPS',
+                      validation: {
+                        required: true,
+                        number: true
+                      }
+                    }
+                  }
+                },
+                action: function(args) {
+                  var data = {
+                    zoneid: args.data.availabilityZone,
+                    mvip: args.data.mvip,
+                    username: args.data.username,
+                    password: args.data.password,
+                    totalcapacity: args.data.totalCapacity,
+                    totalminiops: args.data.totalMinIops,
+                    totalmaxiops: args.data.totalMaxIops,
+                    totalburstiops: args.data.totalBurstIops
+                  };
+
+                  $.ajax({
+                    url: createURL('createReferenceToSolidFireCluster'),
+                    data: data,
+                    success: function(json) {
+                      var sfclusterObj = json.createreferencetosolidfireclusterresponse.apicreatereferencetosolidfirecluster;
+
+                      args.response.success({
+                        data: sfclusterObj
+                      });
+                    },
+                    error: function(json) {
+                      args.response.error(parseXMLHttpResponse(json));
+                    }
+                  });
+                }
+              }
+            },
+            detailView: {
+              name: 'label.details',
+              viewAll: {
+                path: 'sfAdministration.sfVirtualNetworks',
+                label: 'Virtual Networks'
+              },
+              actions: {
+                edit: {
+                  label: 'label.edit',
+                  messages: {
+                    notification: function(args) {
+                      return 'Edit Cluster';
+                    }
+                  },
+                  action: function (args) {
+                    var params = [];
+
+                    params.push("&name=" + args.context.sfAdministration[0].name);
+                    params.push("&totalcapacity=" + args.data.totalcapacity);
+                    params.push("&totalminiops=" + args.data.totalminiops);
+                    params.push("&totalmaxiops=" + args.data.totalmaxiops);
+                    params.push("&totalburstiops=" + args.data.totalburstiops);
+
+                    $.ajax({
+                      url: createURL('updateReferenceToSolidFireCluster' + params.join("")),
+                      success: function(json) {
+                        var sfclusterObj = json.updatereferencetosolidfireclusterresponse.apiupdatereferencetosolidfirecluster;
+
+                        args.response.success({
+                          data: sfclusterObj
+                        });
+                      },
+                      error: function(json) {
+                        args.response.error(parseXMLHttpResponse(json));
+                      }
+                    });
+                  }
+                },
+                remove: {
+                  label: 'Delete Reference to Cluster',
+                  messages: {
+                    confirm: function(args) {
+                      return 'Are you sure you would like to delete this reference to a SolidFire cluster?';
+                    },
+                    notification: function(args) {
+                      return 'Delete Reference to Cluster';
+                    }
+                  },
+                  action: function(args) {
+                    $.ajax({
+                      url: createURL('deleteReferenceToSolidFireCluster&name=' + args.context.sfAdministration[0].name),
+                      success: function(json) {
+                        args.response.success();
+                      },
+                      error: function(json) {
+                        args.response.error(parseXMLHttpResponse(json));
+                      }
+                    });
+                  }
+                }
+              },
+              tabs: {
+                details: {
+                  title: 'label.details',
+                  preFilter: function(args) {
+                    return [];
+                  },
+                  fields: [
+                    {
+                      name: {
+                        label: 'label.name'
+                      }
+                    },
+                    {
+                      uuid: {
+                        label: 'label.id'
+                      },
+                      zonename: {
+                        label: 'label.zone'
+                      },
+                      mvip: {
+                        label: 'MVIP'
+                      },
+                      username: {
+                        label: 'Username'
+                      },
+                      totalcapacity: {
+                        label: 'Total Capacity (in GB)',
+                        isEditable: true
+                      },
+                      totalminiops: {
+                        label: 'Total Min IOPS',
+                        isEditable: true
+                      },
+                      totalmaxiops: {
+                        label: 'Total Max IOPS',
+                        isEditable: true
+                      },
+                      totalburstiops: {
+                        label: 'Total Burst IOPS',
+                        isEditable: true
+                      }
+                    }
+                  ],
+                  dataProvider: function(args) {
+                    $.ajax({
+                      url: createURL("listSolidFireClusters&name=" + args.context.sfAdministration[0].name),
+                      dataType: "json",
+                      async: true,
+                      success: function(json) {
+                        var jsonObj = json.listsolidfireclustersresponse.sfcluster[0];
+
+                        args.response.success({
+                          data: jsonObj
+                        });
+                      }
+                    });
+                  }
+                }
+              }
+            }
+          }
+        },
+        sfVirtualNetworks: {
+          id: 'sfVirtualNetworks',
+          type: 'select',
+          title: 'SolidFire Virtual Networks',
+          listView: {
+            section: 'sfVirtualNetworks',
+            id: 'sfVirtualNetworks',
+            fields: {
+              name: { label: 'label.name' },
+              tag: { label: 'Tag' },
+              svip: { label: 'SVIP' },
+              accountname: { label: 'label.account' }
+            },
+            dataProvider: function(args) {
+              var clustername = args.context.sfAdministration[0].name;
+
+              plugin.ui.apiCall('listSolidFireVirtualNetworks&clustername=' + clustername, {
+                success: function(json) {
+                  var sfvirtualnetworksfiltered = [];
+                  var sfvirtualnetworks = json.listsolidfirevirtualnetworksresponse.sfvirtualnetwork;
+                  var search = args.filterBy.search.value == null ? "" : args.filterBy.search.value.toLowerCase();
+
+                  if (search == "") {
+                    sfvirtualnetworksfiltered = sfvirtualnetworks;
+                  }
+                  else {
+                    for (i = 0; i < sfvirtualnetworks.length; i++) {
+                      sfvirtualnetwork = sfvirtualnetworks[i];
+
+                      if (sfvirtualnetwork.name.toLowerCase().indexOf(search) > -1 ) {
+                        sfvirtualnetworksfiltered.push(sfvirtualnetwork);
+                      }
+                    }
+                  }
+
+                  args.response.success({ data: sfvirtualnetworksfiltered });
+                },
+                error: function(errorMessage) {
+                  args.response.error(errorMessage);
+                }
+              });
+            },
+            actions: {
+              add: {
+                label: 'Add Virtual Network',
+                preFilter: function(args) {
+                  return true;
+                },
+                messages: {
+                  confirm: function(args) {
+                    return 'Please fill in the following data to add a virtual network.';
+                  },
+                  notification: function(args) {
+                    return 'Add Virtual Network';
+                  }
+                },
+                createForm: {
+                  title: 'Add Virtual Network',
+                  desc: 'Please fill in the following data to add a virtual network.',
+                  fields: {
+                    account: {
+                      label: 'Account',
+                      validation: {
+                        required: true
+                      },
+                      select: function(args) {
+                        $.ajax({
+                          url: createURL("listAccounts&listAll=true"),
+                          dataType: "json",
+                          async: true,
+                          success: function(json) {
+                            var accountObjs = json.listaccountsresponse.account;
+
+                            args.response.success({
+                              descriptionField: 'name',
+                              data: accountObjs
+                            });
+                          }
+                        });
+                      }
+                    },
+                    name: {
+                      label: 'Name',
+                      validation: {
+                        required: true
+                      }
+                    },
+                    tag: {
+                      label: 'Tag',
+                      validation: {
+                        required: true
+                      }
+                    },
+                    netmask: {
+                      label: 'Netmask',
+                      validation: {
+                        required: true
+                      }
+                    },
+                    startip: {
+                      label: 'Start IP',
+                      validation: {
+                        required: true
+                      }
+                    },
+                    size: {
+                      label: 'Size',
+                      validation: {
+                        required: true,
+                        number: true
+                      }
+                    },
+                    svip: {
+                      label: 'SVIP',
+                      validation: {
+                        required: true
+                      }
+                    }
+                  }
+                },
+                action: function(args) {
+                  var data = {
+                    clustername: args.context.sfAdministration[0].name,
+                    accountid: args.data.account,
+                    name: args.data.name,
+                    tag: args.data.tag,
+                    netmask: args.data.netmask,
+                    startip: args.data.startip,
+                    size: args.data.size,
+                    svip: args.data.svip
+                  };
+
+                  $.ajax({
+                    url: createURL('createSolidFireVirtualNetwork'),
+                    data: data,
+                    success: function(json) {
+                      var sfVirtualNetworkObj = json.createsolidfirevirtualnetworkresponse.apicreatesolidfirevirtualnetwork;
+
+                      args.response.success({
+                        data: sfVirtualNetworkObj
+                      });
+                    },
+                    error: function(json) {
+                      args.response.error(parseXMLHttpResponse(json));
+                    }
+                  });
+                }
+              }
+            },
+            detailView: {
+              name: 'label.details',
+              actions: {
+                edit: {
+                  label: 'label.edit',
+                  messages: {
+                    notification: function(args) {
+                      return 'Edit Virtual Network';
+                    }
+                  },
+                  action: function (args) {
+                    var params = [];
+
+                    params.push("&id=" + args.context.sfVirtualNetworks[0].id);
+                    params.push("&name=" + args.data.name);
+                    params.push("&netmask=" + args.data.netmask);
+                    params.push("&startip=" + args.data.startip);
+                    params.push("&size=" + args.data.size);
+
+                    $.ajax({
+                      url: createURL('updateSolidFireVirtualNetwork' + params.join("")),
+                      success: function(json) {
+                        var sfVirtualNetworkObj = json.updatesolidfirevirtualnetworkresponse.apiupdatesolidfirevirtualnetwork;
+
+                        args.response.success({
+                          data: sfVirtualNetworkObj
+                        });
+                      },
+                      error: function(json) {
+                        args.response.error(parseXMLHttpResponse(json));
+                      }
+                    });
+                  }
+                },
+                remove: {
+                  label: 'Delete Virtual Network',
+                  messages: {
+                    confirm: function(args) {
+                      return 'Are you sure you would like to delete this virtual network?';
+                    },
+                    notification: function(args) {
+                      return 'Delete Virtual Network';
+                    }
+                  },
+                  action: function(args) {
+                    $.ajax({
+                      url: createURL('deleteSolidFireVirtualNetwork&id=' + args.context.sfVirtualNetworks[0].id),
+                      success: function(json) {
+                        args.response.success();
+                      },
+                      error: function(json) {
+                        args.response.error(parseXMLHttpResponse(json));
+                      }
+                    });
+                  }
+                }
+              },
+              tabs: {
+                details: {
+                  title: 'label.details',
+                  preFilter: function(args) {
+                    return [];
+                  },
+                  fields: [
+                    {
+                      name: {
+                        label: 'label.name',
+                        isEditable: true
+                      }
+                    },
+                    {
+                      uuid: {
+                        label: 'label.id'
+                      },
+                      accountname: {
+                        label: 'label.account'
+                      },
+                      tag: {
+                        label: 'Tag'
+                      },
+                      netmask: {
+                        label: 'Netmask',
+                        isEditable: true
+                      },
+                      startip: {
+                        label: 'Start IP',
+                        isEditable: true
+                      },
+                      size: {
+                        label: 'Size',
+                        number: true,
+                        isEditable: true
+                      },
+                      svip: {
+                        label: 'SVIP'
+                      }
+                    }
+                  ],
+                  dataProvider: function(args) {
+                    $.ajax({
+                      url: createURL("listSolidFireVirtualNetworks&id=" + args.context.sfVirtualNetworks[0].id),
+                      dataType: "json",
+                      async: true,
+                      success: function(json) {
+                        var jsonObj = json.listsolidfirevirtualnetworksresponse.sfvirtualnetwork[0];
+
+                        args.response.success({
+                          data: jsonObj
+                        });
+                      }
+                    });
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    });
+  };
+}(cloudStack));
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/ui/plugins/sfSharedVolume/config.js
----------------------------------------------------------------------
diff --git a/ui/plugins/sfSharedVolume/config.js b/ui/plugins/sfSharedVolume/config.js
new file mode 100644
index 0000000..3784be6
--- /dev/null
+++ b/ui/plugins/sfSharedVolume/config.js
@@ -0,0 +1,9 @@
+(function (cloudStack) {
+  cloudStack.plugins.sfSharedVolume.config = {
+    title: 'Shared Volume',
+    desc: 'Shared Volume',
+    externalLink: 'http://www.solidfire.com/',
+    authorName: 'Mike Tutkowski',
+    authorEmail: 'mike.tutkowski@solidfire.com'
+  };
+}(cloudStack));
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/ui/plugins/sfSharedVolume/icon.png
----------------------------------------------------------------------
diff --git a/ui/plugins/sfSharedVolume/icon.png b/ui/plugins/sfSharedVolume/icon.png
new file mode 100644
index 0000000..a313d35
Binary files /dev/null and b/ui/plugins/sfSharedVolume/icon.png differ

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/ui/plugins/sfSharedVolume/sfSharedVolume.js
----------------------------------------------------------------------
diff --git a/ui/plugins/sfSharedVolume/sfSharedVolume.js b/ui/plugins/sfSharedVolume/sfSharedVolume.js
new file mode 100644
index 0000000..6d4c791
--- /dev/null
+++ b/ui/plugins/sfSharedVolume/sfSharedVolume.js
@@ -0,0 +1,377 @@
+(function (cloudStack) {
+  cloudStack.plugins.sfSharedVolume = function(plugin) {
+    plugin.ui.addSection({
+      id: 'sfSharedVolume',
+      title: 'Shared Volume',
+      preFilter: function(args) {
+        return true;
+      },
+      listView: {
+        id: 'sfSharedVolumes',
+        fields: {
+          name: { label: 'label.name' },
+          iqn: { label: 'IQN' },
+          size: { label: 'Size (GB)' },
+          miniops: { label: 'Min IOPS' },
+          maxiops: { label: 'Max IOPS' },
+          burstiops: { label: 'Burst IOPS' }
+        },
+        dataProvider: function(args) {
+          plugin.ui.apiCall('listSolidFireVolumes', {
+            success: function(json) {
+              var sfvolumesfiltered = [];
+              var sfvolumes = json.listsolidfirevolumesresponse.sfvolume;
+              var search = args.filterBy.search.value == null ? "" : args.filterBy.search.value.toLowerCase();
+
+              if (search == "") {
+                sfvolumesfiltered = sfvolumes;
+              }
+              else {
+                for (i = 0; i < sfvolumes.length; i++) {
+                  sfvolume = sfvolumes[i];
+
+                  if (sfvolume.name.toLowerCase().indexOf(search) > -1 ) {
+                    sfvolumesfiltered.push(sfvolume);
+                  }
+                }
+              }
+
+              args.response.success({ data: sfvolumesfiltered });
+            },
+            error: function(errorMessage) {
+              args.response.error(errorMessage);
+            }
+          });
+        },
+        actions: {
+          add: {
+            label: 'Add Shared Volume',
+            preFilter: function(args) {
+              return true;
+            },
+            messages: {
+              confirm: function(args) {
+                return 'Please fill in the following data to add a new shared volume.';
+              },
+              notification: function(args) {
+                return 'Add Shared Volume';
+              }
+            },
+            createForm: {
+              title: 'Add Shared Volume',
+              desc: 'Please fill in the following data to add a new shared volume.',
+              fields: {
+                availabilityZone: {
+                  label: 'label.availability.zone',
+                  docID: 'helpVolumeAvailabilityZone',
+                  validation: {
+                    required: true
+                  },
+                  select: function(args) {
+                    $.ajax({
+                      url: createURL("listZones&available=true"),
+                      dataType: "json",
+                      async: true,
+                      success: function(json) {
+                        var zoneObjs = json.listzonesresponse.zone;
+
+                        args.response.success({
+                          descriptionField: 'name',
+                          data: zoneObjs
+                        });
+                      }
+                    });
+                  }
+                },
+                name: {
+                  label: 'label.name',
+                  docID: 'helpVolumeName',
+                  validation: {
+                    required: true
+                  }
+                },
+                diskSize: {
+                  label: 'label.disk.size.gb',
+                  validation: {
+                    required: true,
+                    number: true
+                  }
+                },
+                minIops: {
+                  label: 'label.disk.iops.min',
+                  validation: {
+                    required: true,
+                    number: true
+                  }
+                },
+                maxIops: {
+                  label: 'label.disk.iops.max',
+                  validation: {
+                    required: true,
+                    number: true
+                  }
+                },
+                burstIops: {
+                  label: 'Burst IOPS',
+                  validation: {
+                    required: true,
+                    number: true
+                  }
+                },
+                account: {
+                  label: 'Account',
+                  validation: {
+                    required: true
+                  },
+                  isHidden: true,
+                  select: function(args) {
+                    var accountNameParam = "";
+
+                    if (isAdmin()) {
+                      args.$form.find('.form-item[rel=account]').show();
+                    }
+                    else {
+                      accountNameParam = "&name=" + g_account;
+                    }
+
+                    $.ajax({
+                      url: createURL("listAccounts&listAll=true" + accountNameParam),
+                      dataType: "json",
+                      async: true,
+                      success: function(json) {
+                        var accountObjs = json.listaccountsresponse.account;
+                        var filteredAccountObjs = [];
+
+                        if (isAdmin()) {
+                          filteredAccountObjs = accountObjs;
+                        }
+                        else {
+                          for (i = 0; i < accountObjs.length; i++) {
+                            var accountObj = accountObjs[i];
+
+                            if (accountObj.domainid == g_domainid) {
+                              filteredAccountObjs.push(accountObj);
+
+                              break; // there should only be one account with a particular name in a domain
+                            }
+                          }
+                        }
+
+                        args.response.success({
+                          descriptionField: 'name',
+                          data: filteredAccountObjs
+                        });
+                      }
+                    });
+                  }
+                },
+                vlan: {
+                  label: 'VLAN',
+                  validation: {
+                    required: true
+                  },
+                  dependsOn: ['availabilityZone', 'account'],
+                  select: function(args) {
+                    if (args.data.availabilityZone == null || args.data.availabilityZone == "" ||
+                        args.data.account == null || args.data.account == "") {
+                      return;
+                    }
+
+                    var params = [];
+
+                    params.push("&zoneid=" + args.data.availabilityZone);
+                    params.push("&accountid=" + args.data.account);
+
+                    $.ajax({
+                      url: createURL("listSolidFireVirtualNetworks" + params.join("")),
+                      dataType: "json",
+                      async: true,
+                      success: function(json) {
+                        var virtualNetworkObjs = json.listsolidfirevirtualnetworksresponse.sfvirtualnetwork;
+
+                        args.response.success({
+                          descriptionField: 'name',
+                          data: virtualNetworkObjs
+                        });
+                      }
+                    });
+                  }
+                }
+              }
+            },
+            action: function(args) {
+              var data = {
+                name: args.data.name,
+                size: args.data.diskSize,
+                miniops: args.data.minIops,
+                maxiops: args.data.maxIops,
+                burstiops: args.data.burstIops,
+                accountid: args.data.account,
+                sfvirtualnetworkid: args.data.vlan
+              };
+
+              $.ajax({
+                url: createURL('createSolidFireVolume'),
+                data: data,
+                success: function(json) {
+                  var sfvolumeObj = json.createsolidfirevolumeresponse.apicreatesolidfirevolume;
+
+                  args.response.success({
+                    data: sfvolumeObj
+                  });
+                },
+                error: function(json) {
+                  args.response.error(parseXMLHttpResponse(json));
+                }
+              });
+            }
+          }
+        },
+        detailView: {
+          name: 'label.volume.details',
+          actions: {
+            edit: {
+              label: 'label.edit',
+              messages: {
+                notification: function(args) {
+                  return 'Edit Shared Volume';
+                }
+              },
+              action: function (args) {
+                var params = [];
+
+                params.push("&id=" + args.context.sfSharedVolumes[0].id);
+                params.push("&size=" + args.data.size);
+                params.push("&miniops=" + args.data.miniops);
+                params.push("&maxiops=" + args.data.maxiops);
+                params.push("&burstiops=" + args.data.burstiops);
+
+                $.ajax({
+                  url: createURL('updateSolidFireVolume' + params.join("")),
+                  success: function(json) {
+                    var sfvolumeObj = json.updatesolidfirevolumeresponse.apiupdatesolidfirevolume;
+
+                    args.response.success({
+                      data: sfvolumeObj
+                    });
+                  },
+                  error: function(json) {
+                    args.response.error(parseXMLHttpResponse(json));
+                  }
+                });
+              }
+            },
+            remove: {
+              label: 'label.delete',
+              messages: {
+                confirm: function(args) {
+                  return 'Are you sure you would like to delete this shared volume?';
+                },
+                notification: function(args) {
+                  return 'Delete Shared Volume';
+                }
+              },
+              action: function(args) {
+                $.ajax({
+                  url: createURL('deleteSolidFireVolume&id=' + args.context.sfSharedVolumes[0].id),
+                  success: function(json) {
+                    args.response.success();
+                  },
+                  error: function(json) {
+                    args.response.error(parseXMLHttpResponse(json));
+                  }
+                });
+              }
+            }
+          },
+          tabs: {
+            details: {
+              title: 'label.details',
+              preFilter: function(args) {
+                var hiddenFields;
+
+                if (isAdmin()) {
+                  hiddenFields = [];
+                } else {
+                  hiddenFields = ['clustername', 'accountname'];
+                }
+
+                return hiddenFields;
+              },
+              fields: [
+                {
+                  name: {
+                    label: 'label.name'
+                  }
+                },
+                {
+                  uuid: {
+                    label: 'label.id'
+                  },
+                  clustername: {
+                    label: 'Cluster'
+                  },
+                  zonename: {
+                    label: 'label.zone'
+                  },
+                  accountname: {
+                    label: 'label.account'
+                  },
+                  vlanname: {
+                    label: 'VLAN'
+                  },
+                  size: {
+                    label: 'label.disk.size.gb',
+                    isEditable: true
+                  },
+                  miniops: {
+                    label: 'label.disk.iops.min',
+                    isEditable: true
+                  },
+                  maxiops: {
+                    label: 'label.disk.iops.max',
+                    isEditable: true
+                  },
+                  burstiops: {
+                    label: 'Burst IOPS',
+                    isEditable: true
+                  },
+                  targetportal: {
+                    label: 'Target Portal'
+                  },
+                  iqn: {
+                    label: 'IQN'
+                  },
+                  chapinitiatorusername: {
+                    label: 'Initiator Username'
+                  },
+                  chapinitiatorsecret: {
+                    label: 'Initiator Secret'
+                  },
+                  created: {
+                    label: 'label.created',
+                    converter: cloudStack.converters.toLocalDate
+                  }
+                }
+              ],
+              dataProvider: function(args) {
+                $.ajax({
+                  url: createURL("listSolidFireVolumes&id=" + args.context.sfSharedVolumes[0].id),
+                  dataType: "json",
+                  async: true,
+                  success: function(json) {
+                    var jsonObj = json.listsolidfirevolumesresponse.sfvolume[0];
+
+                    args.response.success({
+                      data: jsonObj
+                    });
+                  }
+                });
+              }
+            }
+          }
+        }
+      }
+    });
+  };
+}(cloudStack));
\ No newline at end of file


[7/7] git commit: updated refs/heads/sf-plugins-a to 49ca3b4

Posted by mt...@apache.org.
SolidFire API and GUI plug-ins


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/49ca3b40
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/49ca3b40
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/49ca3b40

Branch: refs/heads/sf-plugins-a
Commit: 49ca3b40af707495874a2d1d9fd2db02136814e7
Parents: 59f337d
Author: Mike Tutkowski <mi...@solidfire.com>
Authored: Thu May 7 12:21:35 2015 -0600
Committer: Mike Tutkowski <mt...@mtutkowski-LT.local>
Committed: Wed Oct 14 12:06:49 2015 -0600

----------------------------------------------------------------------
 client/pom.xml                                  |   5 +
 client/tomcatconf/commands.properties.in        |  14 +
 .../spring-solidfire-intg-test-context.xml      |   2 +-
 .../solidfire/GetSolidFireAccountIdCmd.java     |   8 +-
 .../GetSolidFireVolumeAccessGroupIdCmd.java     |   8 +-
 .../GetSolidFireVolumeIscsiNameCmd.java         |   8 +-
 .../solidfire/GetSolidFireVolumeSizeCmd.java    |   8 +-
 .../solidfire/ApiSolidFireIntgTestService.java  |  37 +
 .../ApiSolidFireIntgTestServiceImpl.java        | 128 +++
 .../solidfire/ApiSolidFireService.java          |  37 -
 .../solidfire/ApiSolidFireServiceImpl.java      | 128 ---
 plugins/api/solidfire/pom.xml                   |  50 +
 .../cloudstack/solidfire/module.properties      |  18 +
 .../solidfire/spring-solidfire-context.xml      |  37 +
 .../CreateReferenceToSolidFireClusterCmd.java   | 106 ++
 .../CreateSolidFireVirtualNetworkCmd.java       | 104 ++
 .../DeleteReferenceToSolidFireClusterCmd.java   |  82 ++
 .../DeleteSolidFireVirtualNetworkCmd.java       |  90 ++
 .../solidfire/ListSolidFireClustersCmd.java     |  95 ++
 .../UpdateReferenceToSolidFireClusterCmd.java   |  95 ++
 .../UpdateSolidFireVirtualNetworkCmd.java       | 103 ++
 .../solidfire/CreateSolidFireVolumeCmd.java     | 105 ++
 .../solidfire/DeleteSolidFireVolumeCmd.java     |  97 ++
 .../ListSolidFireVirtualNetworksCmd.java        | 114 +++
 .../user/solidfire/ListSolidFireVolumesCmd.java |  99 ++
 .../solidfire/UpdateSolidFireVolumeCmd.java     | 108 ++
 .../solidfire/ApiSolidFireClusterResponse.java  | 161 +++
 .../ApiSolidFireVirtualNetworkResponse.java     | 209 ++++
 .../solidfire/ApiSolidFireVolumeResponse.java   | 320 ++++++
 .../api/solidfire/ApiSolidFireService.java      |   6 +
 .../api/solidfire/ApiSolidFireServiceImpl.java  |  45 +
 .../api/solidfire/SfApiConstants.java           |  44 +
 .../dataaccess/dao/solidfire/SfClusterDao.java  |  29 +
 .../dao/solidfire/SfClusterDaoImpl.java         |  62 ++
 .../dao/solidfire/SfVirtualNetworkDao.java      |  29 +
 .../dao/solidfire/SfVirtualNetworkDaoImpl.java  |  67 ++
 .../dataaccess/dao/solidfire/SfVolumeDao.java   |  27 +
 .../dao/solidfire/SfVolumeDaoImpl.java          |  50 +
 .../dataaccess/vo/solidfire/SfClusterVO.java    | 173 ++++
 .../vo/solidfire/SfVirtualNetworkVO.java        | 180 ++++
 .../dataaccess/vo/solidfire/SfVolumeVO.java     | 168 ++++
 .../apache/cloudstack/solidfire/SfCluster.java  |  40 +
 .../cloudstack/solidfire/SfVirtualNetwork.java  |  40 +
 .../apache/cloudstack/solidfire/SfVolume.java   |  42 +
 .../cloudstack/solidfire/SolidFireManager.java  |  66 ++
 .../solidfire/SolidFireManagerImpl.java         | 977 +++++++++++++++++++
 .../cloudstack/util/solidfire/SfUtil.java       | 221 +++++
 .../util/solidfire/SolidFireConnection.java     | 950 ++++++++++++++++++
 plugins/pom.xml                                 |   1 +
 .../driver/SolidFirePrimaryDataStoreDriver.java |   6 +-
 .../SolidFireSharedPrimaryDataStoreDriver.java  |  45 -
 ui/plugins/plugins.js                           |   4 +-
 ui/plugins/sfAdministration/config.js           |   9 +
 ui/plugins/sfAdministration/icon.png            | Bin 0 -> 7943 bytes
 ui/plugins/sfAdministration/sfAdministration.js | 566 +++++++++++
 ui/plugins/sfSharedVolume/config.js             |   9 +
 ui/plugins/sfSharedVolume/icon.png              | Bin 0 -> 7943 bytes
 ui/plugins/sfSharedVolume/sfSharedVolume.js     | 377 +++++++
 58 files changed, 6383 insertions(+), 226 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/client/pom.xml
----------------------------------------------------------------------
diff --git a/client/pom.xml b/client/pom.xml
index bcb1391..633319e 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -348,6 +348,11 @@
     </dependency>
     <dependency>
         <groupId>org.apache.cloudstack</groupId>
+        <artifactId>cloud-plugin-api-solidfire</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+    <dependency>
+        <groupId>org.apache.cloudstack</groupId>
         <artifactId>cloud-plugin-api-solidfire-intg-test</artifactId>
         <version>${project.version}</version>
     </dependency>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index a69605c..a1e9b8e 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -663,6 +663,20 @@ getApiLimit=15
 resetApiLimit=1
 
 #### API SolidFire Service Command
+createReferenceToSolidFireCluster=1
+createSolidFireVirtualNetwork=1
+deleteReferenceToSolidFireCluster=1
+deleteSolidFireVirtualNetwork=1
+listSolidFireClusters=1
+updateReferenceToSolidFireCluster=1
+updateSolidFireVirtualNetwork=1
+createSolidFireVolume=15
+deleteSolidFireVolume=15
+listSolidFireVirtualNetworks=15
+listSolidFireVolumes=15
+updateSolidFireVolume=15
+
+#### API SolidFire Integration-Testing Service Command
 getSolidFireAccountId=15
 getSolidFireVolumeSize=15
 getSolidFireVolumeAccessGroupId=15

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire-intg-test/resources/META-INF/cloudstack/solidfire-intg-test/spring-solidfire-intg-test-context.xml
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire-intg-test/resources/META-INF/cloudstack/solidfire-intg-test/spring-solidfire-intg-test-context.xml b/plugins/api/solidfire-intg-test/resources/META-INF/cloudstack/solidfire-intg-test/spring-solidfire-intg-test-context.xml
index 1bab734..f9bc021 100644
--- a/plugins/api/solidfire-intg-test/resources/META-INF/cloudstack/solidfire-intg-test/spring-solidfire-intg-test-context.xml
+++ b/plugins/api/solidfire-intg-test/resources/META-INF/cloudstack/solidfire-intg-test/spring-solidfire-intg-test-context.xml
@@ -27,6 +27,6 @@
                       http://www.springframework.org/schema/context/spring-context-3.0.xsd"
                       >
 
-      <bean id="apiSolidFireServiceImpl" class="org.apache.cloudstack.solidfire.ApiSolidFireServiceImpl"/>
+      <bean id="apiSolidFireIntgTestServiceImpl" class="org.apache.cloudstack.solidfire.ApiSolidFireIntgTestServiceImpl"/>
 
 </beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireAccountIdCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireAccountIdCmd.java b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireAccountIdCmd.java
index f4c0076..f54a3d2 100644
--- a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireAccountIdCmd.java
+++ b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireAccountIdCmd.java
@@ -29,7 +29,7 @@ import org.apache.cloudstack.api.BaseCmd;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.response.ApiSolidFireAccountIdResponse;
 import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.solidfire.ApiSolidFireService;
+import org.apache.cloudstack.solidfire.ApiSolidFireIntgTestService;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 
@@ -44,7 +44,7 @@ public class GetSolidFireAccountIdCmd extends BaseCmd {
     @Parameter(name = ApiConstants.STORAGE_ID, type = CommandType.STRING, description = "Storage Pool UUID", required = true)
     private String storagePoolUuid;
 
-    @Inject private ApiSolidFireService _apiSolidFireService;
+    @Inject private ApiSolidFireIntgTestService _apiSolidFireIntgTestService;
     @Inject private AccountDao _accountDao;
     @Inject private PrimaryDataStoreDao _storagePoolDao;
 
@@ -70,10 +70,12 @@ public class GetSolidFireAccountIdCmd extends BaseCmd {
 
     @Override
     public void execute() {
+        s_logger.info(GetSolidFireAccountIdCmd.class.getName() + ".execute invoked");
+
         Account account = _accountDao.findByUuid(accountUuid);
         StoragePoolVO storagePool = _storagePoolDao.findByUuid(storagePoolUuid);
 
-        ApiSolidFireAccountIdResponse response = _apiSolidFireService.getSolidFireAccountId(account.getId(), storagePool.getId());
+        ApiSolidFireAccountIdResponse response = _apiSolidFireIntgTestService.getSolidFireAccountId(account.getId(), storagePool.getId());
 
         response.setResponseName(getCommandName());
         response.setObjectName("apisolidfireaccountid");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeAccessGroupIdCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeAccessGroupIdCmd.java b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeAccessGroupIdCmd.java
index c432fb1..df03685 100644
--- a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeAccessGroupIdCmd.java
+++ b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeAccessGroupIdCmd.java
@@ -31,7 +31,7 @@ import org.apache.cloudstack.api.BaseCmd;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.response.ApiSolidFireVolumeAccessGroupIdResponse;
 import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.solidfire.ApiSolidFireService;
+import org.apache.cloudstack.solidfire.ApiSolidFireIntgTestService;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 
 @APICommand(name = "getSolidFireVolumeAccessGroupId", responseObject = ApiSolidFireVolumeAccessGroupIdResponse.class, description = "Get the SF Volume Access Group ID",
@@ -45,7 +45,7 @@ public class GetSolidFireVolumeAccessGroupIdCmd extends BaseCmd {
     @Parameter(name = ApiConstants.STORAGE_ID, type = CommandType.STRING, description = "Storage Pool UUID", required = true)
     private String storagePoolUuid;
 
-    @Inject private ApiSolidFireService _apiSolidFireService;
+    @Inject private ApiSolidFireIntgTestService _apiSolidFireIntgTestService;
     @Inject private ClusterDao _clusterDao;
     @Inject private PrimaryDataStoreDao _storagePoolDao;
 
@@ -71,10 +71,12 @@ public class GetSolidFireVolumeAccessGroupIdCmd extends BaseCmd {
 
     @Override
     public void execute() {
+        s_logger.info(GetSolidFireVolumeAccessGroupIdCmd.class.getName() + ".execute invoked");
+
         Cluster cluster = _clusterDao.findByUuid(clusterUuid);
         StoragePool storagePool = _storagePoolDao.findByUuid(storagePoolUuid);
 
-        ApiSolidFireVolumeAccessGroupIdResponse response = _apiSolidFireService.getSolidFireVolumeAccessGroupId(cluster.getId(), storagePool.getId());
+        ApiSolidFireVolumeAccessGroupIdResponse response = _apiSolidFireIntgTestService.getSolidFireVolumeAccessGroupId(cluster.getId(), storagePool.getId());
 
         response.setResponseName(getCommandName());
         response.setObjectName("apisolidfirevolumeaccessgroupid");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeIscsiNameCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeIscsiNameCmd.java b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeIscsiNameCmd.java
index 7afa301..49a384d 100644
--- a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeIscsiNameCmd.java
+++ b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeIscsiNameCmd.java
@@ -29,7 +29,7 @@ import org.apache.cloudstack.api.BaseCmd;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.response.ApiSolidFireVolumeIscsiNameResponse;
 import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.solidfire.ApiSolidFireService;
+import org.apache.cloudstack.solidfire.ApiSolidFireIntgTestService;
 
 @APICommand(name = "getSolidFireVolumeIscsiName", responseObject = ApiSolidFireVolumeIscsiNameResponse.class, description = "Get SolidFire Volume's Iscsi Name",
         requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@@ -41,7 +41,7 @@ public class GetSolidFireVolumeIscsiNameCmd extends BaseCmd {
     @Parameter(name = ApiConstants.VOLUME_ID, type = CommandType.STRING, description = "CloudStack Volume UUID", required = true)
     private String volumeUuid;
 
-    @Inject private ApiSolidFireService _apiSolidFireService;
+    @Inject private ApiSolidFireIntgTestService _apiSolidFireIntgTestService;
     @Inject private VolumeDao _volumeDao;
 
     /////////////////////////////////////////////////////
@@ -66,9 +66,11 @@ public class GetSolidFireVolumeIscsiNameCmd extends BaseCmd {
 
     @Override
     public void execute() {
+        s_logger.info(GetSolidFireVolumeIscsiNameCmd.class.getName() + ".execute invoked");
+
         Volume volume = _volumeDao.findByUuid(volumeUuid);
 
-        ApiSolidFireVolumeIscsiNameResponse response = _apiSolidFireService.getSolidFireVolumeIscsiName(volume);
+        ApiSolidFireVolumeIscsiNameResponse response = _apiSolidFireIntgTestService.getSolidFireVolumeIscsiName(volume);
 
         response.setResponseName(getCommandName());
         response.setObjectName("apisolidfirevolumeiscsiname");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeSizeCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeSizeCmd.java b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeSizeCmd.java
index 3a27a66..55b6d1f 100644
--- a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeSizeCmd.java
+++ b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/api/command/user/solidfire/GetSolidFireVolumeSizeCmd.java
@@ -31,7 +31,7 @@ import org.apache.cloudstack.api.BaseCmd;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.response.ApiSolidFireVolumeSizeResponse;
 import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.solidfire.ApiSolidFireService;
+import org.apache.cloudstack.solidfire.ApiSolidFireIntgTestService;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 
 @APICommand(name = "getSolidFireVolumeSize", responseObject = ApiSolidFireVolumeSizeResponse.class, description = "Get the SF volume size including Hypervisor Snapshot Reserve",
@@ -45,7 +45,7 @@ public class GetSolidFireVolumeSizeCmd extends BaseCmd {
     @Parameter(name = ApiConstants.STORAGE_ID, type = CommandType.STRING, description = "Storage Pool UUID", required = true)
     private String storagePoolUuid;
 
-    @Inject private ApiSolidFireService _apiSolidFireService;
+    @Inject private ApiSolidFireIntgTestService _apiSolidFireIntgTestService;
     @Inject private VolumeDao _volumeDao;
     @Inject private PrimaryDataStoreDao _storagePoolDao;
 
@@ -71,10 +71,12 @@ public class GetSolidFireVolumeSizeCmd extends BaseCmd {
 
     @Override
     public void execute() {
+        s_logger.info(GetSolidFireVolumeSizeCmd.class.getName() + ".execute invoked");
+
         Volume volume = _volumeDao.findByUuid(volumeUuid);
         StoragePool storagePool = _storagePoolDao.findByUuid(storagePoolUuid);
 
-        ApiSolidFireVolumeSizeResponse response = _apiSolidFireService.getSolidFireVolumeSize(volume, storagePool);
+        ApiSolidFireVolumeSizeResponse response = _apiSolidFireIntgTestService.getSolidFireVolumeSize(volume, storagePool);
 
         response.setResponseName(getCommandName());
         response.setObjectName("apisolidfirevolumesize");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireIntgTestService.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireIntgTestService.java b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireIntgTestService.java
new file mode 100644
index 0000000..b6a54f6
--- /dev/null
+++ b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireIntgTestService.java
@@ -0,0 +1,37 @@
+// 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.solidfire;
+
+import com.cloud.utils.component.PluggableService;
+import com.cloud.storage.Volume;
+import com.cloud.storage.StoragePool;
+
+import org.apache.cloudstack.api.response.ApiSolidFireAccountIdResponse;
+import org.apache.cloudstack.api.response.ApiSolidFireVolumeSizeResponse;
+import org.apache.cloudstack.api.response.ApiSolidFireVolumeAccessGroupIdResponse;
+import org.apache.cloudstack.api.response.ApiSolidFireVolumeIscsiNameResponse;
+
+/**
+ * Provide API for SolidFire integration tests
+ *
+ */
+public interface ApiSolidFireIntgTestService extends PluggableService {
+    public ApiSolidFireAccountIdResponse getSolidFireAccountId(Long csAccountId, Long storagePoolId);
+    public ApiSolidFireVolumeSizeResponse getSolidFireVolumeSize(Volume volume, StoragePool storagePool);
+    public ApiSolidFireVolumeAccessGroupIdResponse getSolidFireVolumeAccessGroupId(Long csClusterId, Long storagePoolId);
+    public ApiSolidFireVolumeIscsiNameResponse getSolidFireVolumeIscsiName(Volume volume);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireIntgTestServiceImpl.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireIntgTestServiceImpl.java b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireIntgTestServiceImpl.java
new file mode 100644
index 0000000..1ea33a6
--- /dev/null
+++ b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireIntgTestServiceImpl.java
@@ -0,0 +1,128 @@
+// 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.solidfire;
+
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+// import org.apache.log4j.Logger;
+import org.apache.cloudstack.acl.APIChecker;
+import org.apache.cloudstack.storage.datastore.util.SolidFireUtil;
+import org.apache.cloudstack.api.command.user.solidfire.GetSolidFireAccountIdCmd;
+import org.apache.cloudstack.api.command.user.solidfire.GetSolidFireVolumeAccessGroupIdCmd;
+import org.apache.cloudstack.api.command.user.solidfire.GetSolidFireVolumeIscsiNameCmd;
+import org.apache.cloudstack.api.command.user.solidfire.GetSolidFireVolumeSizeCmd;
+import org.apache.cloudstack.api.response.ApiSolidFireAccountIdResponse;
+import org.apache.cloudstack.api.response.ApiSolidFireVolumeAccessGroupIdResponse;
+import org.apache.cloudstack.api.response.ApiSolidFireVolumeIscsiNameResponse;
+import org.apache.cloudstack.api.response.ApiSolidFireVolumeSizeResponse;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
+import org.springframework.stereotype.Component;
+
+import com.cloud.dc.ClusterDetailsDao;
+import com.cloud.dc.ClusterDetailsVO;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.Volume;
+import com.cloud.user.AccountDetailsDao;
+import com.cloud.user.AccountDetailVO;
+import com.cloud.user.User;
+import com.cloud.utils.component.AdapterBase;
+
+@Component
+@Local(value = APIChecker.class)
+public class ApiSolidFireIntgTestServiceImpl extends AdapterBase implements APIChecker, ApiSolidFireIntgTestService {
+    // private static final Logger s_logger = Logger.getLogger(ApiSolidFireServiceImpl.class);
+
+    @Inject private AccountDetailsDao _accountDetailsDao;
+    @Inject private DataStoreProviderManager _dataStoreProviderMgr;
+    @Inject private ClusterDetailsDao _clusterDetailsDao;
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        super.configure(name, params);
+
+        return true;
+    }
+
+    @Override
+    public ApiSolidFireAccountIdResponse getSolidFireAccountId(Long csAccountId, Long storagePoolId) {
+        AccountDetailVO accountDetail = _accountDetailsDao.findDetail(csAccountId, SolidFireUtil.getAccountKey(storagePoolId));
+        String sfAccountId = accountDetail.getValue();
+
+        return new ApiSolidFireAccountIdResponse(Long.parseLong(sfAccountId));
+    }
+
+    @Override
+    public ApiSolidFireVolumeSizeResponse getSolidFireVolumeSize(Volume volume, StoragePool storagePool) {
+        PrimaryDataStoreDriver primaryStoreDriver = null;
+
+        try {
+            DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(storagePool.getStorageProviderName());
+            DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();
+
+            if (storeDriver instanceof PrimaryDataStoreDriver) {
+                primaryStoreDriver = (PrimaryDataStoreDriver)storeDriver;
+            }
+        }
+        catch (InvalidParameterValueException e) {
+            throw new InvalidParameterValueException("Invalid Storage Driver Type");
+        }
+
+        return new ApiSolidFireVolumeSizeResponse(primaryStoreDriver.getVolumeSizeIncludingHypervisorSnapshotReserve(volume, storagePool));
+    }
+
+    @Override
+    public ApiSolidFireVolumeAccessGroupIdResponse getSolidFireVolumeAccessGroupId(Long csClusterId, Long storagePoolId) {
+        ClusterDetailsVO clusterDetails = _clusterDetailsDao.findDetail(csClusterId, SolidFireUtil.getVagKey(storagePoolId));
+        String sfVagId = clusterDetails.getValue();
+
+        return new ApiSolidFireVolumeAccessGroupIdResponse(Long.parseLong(sfVagId));
+    }
+
+    @Override
+    public ApiSolidFireVolumeIscsiNameResponse getSolidFireVolumeIscsiName(Volume volume) {
+        return new ApiSolidFireVolumeIscsiNameResponse(volume.get_iScsiName());
+    }
+
+
+    @Override
+    public boolean checkAccess(User user, String apiCommandName) throws PermissionDeniedException {
+        return true;
+    }
+
+    @Override
+    public List<Class<?>> getCommands() {
+        List<Class<?>> cmdList = new ArrayList<Class<?>>();
+
+        cmdList.add(GetSolidFireAccountIdCmd.class);
+        cmdList.add(GetSolidFireVolumeSizeCmd.class);
+        cmdList.add(GetSolidFireVolumeAccessGroupIdCmd.class);
+        cmdList.add(GetSolidFireVolumeIscsiNameCmd.class);
+
+        return cmdList;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireService.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireService.java b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireService.java
deleted file mode 100644
index 92828d4..0000000
--- a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireService.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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.solidfire;
-
-import com.cloud.utils.component.PluggableService;
-import com.cloud.storage.Volume;
-import com.cloud.storage.StoragePool;
-
-import org.apache.cloudstack.api.response.ApiSolidFireAccountIdResponse;
-import org.apache.cloudstack.api.response.ApiSolidFireVolumeSizeResponse;
-import org.apache.cloudstack.api.response.ApiSolidFireVolumeAccessGroupIdResponse;
-import org.apache.cloudstack.api.response.ApiSolidFireVolumeIscsiNameResponse;
-
-/**
- * Provide API for SolidFire integration tests
- *
- */
-public interface ApiSolidFireService extends PluggableService {
-    public ApiSolidFireAccountIdResponse getSolidFireAccountId(Long csAccountId, Long storagePoolId);
-    public ApiSolidFireVolumeSizeResponse getSolidFireVolumeSize(Volume volume, StoragePool storagePool);
-    public ApiSolidFireVolumeAccessGroupIdResponse getSolidFireVolumeAccessGroupId(Long csClusterId, Long storagePoolId);
-    public ApiSolidFireVolumeIscsiNameResponse getSolidFireVolumeIscsiName(Volume volume);
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireServiceImpl.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireServiceImpl.java b/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireServiceImpl.java
deleted file mode 100644
index a95272a..0000000
--- a/plugins/api/solidfire-intg-test/src/org/apache/cloudstack/solidfire/ApiSolidFireServiceImpl.java
+++ /dev/null
@@ -1,128 +0,0 @@
-// 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.solidfire;
-
-import java.util.Map;
-import java.util.List;
-import java.util.ArrayList;
-
-import javax.ejb.Local;
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-
-// import org.apache.log4j.Logger;
-import org.apache.cloudstack.acl.APIChecker;
-import org.apache.cloudstack.storage.datastore.util.SolidFireUtil;
-import org.apache.cloudstack.api.command.user.solidfire.GetSolidFireAccountIdCmd;
-import org.apache.cloudstack.api.command.user.solidfire.GetSolidFireVolumeAccessGroupIdCmd;
-import org.apache.cloudstack.api.command.user.solidfire.GetSolidFireVolumeIscsiNameCmd;
-import org.apache.cloudstack.api.command.user.solidfire.GetSolidFireVolumeSizeCmd;
-import org.apache.cloudstack.api.response.ApiSolidFireAccountIdResponse;
-import org.apache.cloudstack.api.response.ApiSolidFireVolumeAccessGroupIdResponse;
-import org.apache.cloudstack.api.response.ApiSolidFireVolumeIscsiNameResponse;
-import org.apache.cloudstack.api.response.ApiSolidFireVolumeSizeResponse;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
-import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
-import org.springframework.stereotype.Component;
-
-import com.cloud.dc.ClusterDetailsDao;
-import com.cloud.dc.ClusterDetailsVO;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.exception.PermissionDeniedException;
-import com.cloud.storage.StoragePool;
-import com.cloud.storage.Volume;
-import com.cloud.user.AccountDetailsDao;
-import com.cloud.user.AccountDetailVO;
-import com.cloud.user.User;
-import com.cloud.utils.component.AdapterBase;
-
-@Component
-@Local(value = APIChecker.class)
-public class ApiSolidFireServiceImpl extends AdapterBase implements APIChecker, ApiSolidFireService {
-    // private static final Logger s_logger = Logger.getLogger(ApiSolidFireServiceImpl.class);
-
-    @Inject private AccountDetailsDao _accountDetailsDao;
-    @Inject private DataStoreProviderManager _dataStoreProviderMgr;
-    @Inject private ClusterDetailsDao _clusterDetailsDao;
-
-    @Override
-    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
-        super.configure(name, params);
-
-        return true;
-    }
-
-    @Override
-    public ApiSolidFireAccountIdResponse getSolidFireAccountId(Long csAccountId, Long storagePoolId) {
-        AccountDetailVO accountDetail = _accountDetailsDao.findDetail(csAccountId, SolidFireUtil.getAccountKey(storagePoolId));
-        String sfAccountId = accountDetail.getValue();
-
-        return new ApiSolidFireAccountIdResponse(Long.parseLong(sfAccountId));
-    }
-
-    @Override
-    public ApiSolidFireVolumeSizeResponse getSolidFireVolumeSize(Volume volume, StoragePool storagePool) {
-        PrimaryDataStoreDriver primaryStoreDriver = null;
-
-        try {
-            DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(storagePool.getStorageProviderName());
-            DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();
-
-            if (storeDriver instanceof PrimaryDataStoreDriver) {
-                primaryStoreDriver = (PrimaryDataStoreDriver)storeDriver;
-            }
-        }
-        catch (InvalidParameterValueException e) {
-            throw new InvalidParameterValueException("Invalid Storage Driver Type");
-        }
-
-        return new ApiSolidFireVolumeSizeResponse(primaryStoreDriver.getVolumeSizeIncludingHypervisorSnapshotReserve(volume, storagePool));
-    }
-
-    @Override
-    public ApiSolidFireVolumeAccessGroupIdResponse getSolidFireVolumeAccessGroupId(Long csClusterId, Long storagePoolId) {
-        ClusterDetailsVO clusterDetails = _clusterDetailsDao.findDetail(csClusterId, SolidFireUtil.getVagKey(storagePoolId));
-        String sfVagId = clusterDetails.getValue();
-
-        return new ApiSolidFireVolumeAccessGroupIdResponse(Long.parseLong(sfVagId));
-    }
-
-    @Override
-    public ApiSolidFireVolumeIscsiNameResponse getSolidFireVolumeIscsiName(Volume volume) {
-        return new ApiSolidFireVolumeIscsiNameResponse(volume.get_iScsiName());
-    }
-
-
-    @Override
-    public boolean checkAccess(User user, String apiCommandName) throws PermissionDeniedException {
-        return true;
-    }
-
-    @Override
-    public List<Class<?>> getCommands() {
-        List<Class<?>> cmdList = new ArrayList<Class<?>>();
-
-        cmdList.add(GetSolidFireAccountIdCmd.class);
-        cmdList.add(GetSolidFireVolumeSizeCmd.class);
-        cmdList.add(GetSolidFireVolumeAccessGroupIdCmd.class);
-        cmdList.add(GetSolidFireVolumeIscsiNameCmd.class);
-
-        return cmdList;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/pom.xml b/plugins/api/solidfire/pom.xml
new file mode 100644
index 0000000..35ee222
--- /dev/null
+++ b/plugins/api/solidfire/pom.xml
@@ -0,0 +1,50 @@
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>cloud-plugin-api-solidfire</artifactId>
+  <name>SolidFire API Plugin</name>
+  <parent>
+    <groupId>org.apache.cloudstack</groupId>
+    <artifactId>cloudstack-plugins</artifactId>
+    <version>4.5.3-SNAPSHOT</version>
+    <relativePath>../../pom.xml</relativePath>
+  </parent>
+  <dependencies>
+      <dependency>
+          <groupId>org.apache.cloudstack</groupId>
+          <artifactId>cloud-plugin-storage-volume-solidfire</artifactId>
+          <version>${project.version}</version>
+      </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <argLine>-Xmx1024m</argLine>
+          <excludes>
+            <exclude>org/apache/cloudstack/solidfire/integration/*</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/resources/META-INF/cloudstack/solidfire/module.properties
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/resources/META-INF/cloudstack/solidfire/module.properties b/plugins/api/solidfire/resources/META-INF/cloudstack/solidfire/module.properties
new file mode 100644
index 0000000..00c290d
--- /dev/null
+++ b/plugins/api/solidfire/resources/META-INF/cloudstack/solidfire/module.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+name=solidfire
+parent=api
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/resources/META-INF/cloudstack/solidfire/spring-solidfire-context.xml
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/resources/META-INF/cloudstack/solidfire/spring-solidfire-context.xml b/plugins/api/solidfire/resources/META-INF/cloudstack/solidfire/spring-solidfire-context.xml
new file mode 100644
index 0000000..f9a5037
--- /dev/null
+++ b/plugins/api/solidfire/resources/META-INF/cloudstack/solidfire/spring-solidfire-context.xml
@@ -0,0 +1,37 @@
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:aop="http://www.springframework.org/schema/aop"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+                      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
+                      http://www.springframework.org/schema/context
+                      http://www.springframework.org/schema/context/spring-context-3.0.xsd"
+                      >
+
+      <bean id="sfUtil" class="org.apache.cloudstack.util.solidfire.SfUtil" />
+      <bean id="solidFireManagerImpl" class="org.apache.cloudstack.solidfire.SolidFireManagerImpl" />
+      <bean id="apiSolidFireServiceImpl" class="org.apache.cloudstack.api.solidfire.ApiSolidFireServiceImpl" />
+      <bean id="sfClusterDao" class="org.apache.cloudstack.dataaccess.dao.solidfire.SfClusterDaoImpl" />
+      <bean id="sfVolumeDao" class="org.apache.cloudstack.dataaccess.dao.solidfire.SfVolumeDaoImpl" />
+      <bean id="sfVirtualNetworkDao" class="org.apache.cloudstack.dataaccess.dao.solidfire.SfVirtualNetworkDaoImpl" />
+
+</beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/CreateReferenceToSolidFireClusterCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/CreateReferenceToSolidFireClusterCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/CreateReferenceToSolidFireClusterCmd.java
new file mode 100644
index 0000000..0741399
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/CreateReferenceToSolidFireClusterCmd.java
@@ -0,0 +1,106 @@
+// 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.api.command.admin.solidfire;
+
+import com.cloud.user.Account;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireClusterResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfCluster;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "createReferenceToSolidFireCluster", responseObject = ApiSolidFireClusterResponse.class, description = "Create Reference to SolidFire Cluster",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class CreateReferenceToSolidFireClusterCmd extends BaseCmd {
+    private static final Logger s_logger = Logger.getLogger(CreateReferenceToSolidFireClusterCmd.class.getName());
+    private static final String s_name = "createreferencetosolidfireclusterresponse";
+
+    @Parameter(name = SfApiConstants.MVIP, type = CommandType.STRING, description = SfApiConstants.SOLIDFIRE_MVIP_DESC, required = true)
+    private String _mvip;
+
+    @Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = SfApiConstants.SOLIDFIRE_USERNAME_DESC, required = true)
+    private String _username;
+
+    @Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, description = SfApiConstants.SOLIDFIRE_PASSWORD_DESC, required = true)
+    private String _password;
+
+    @Parameter(name = SfApiConstants.TOTAL_CAPACITY, type = CommandType.LONG, description = SfApiConstants.TOTAL_CAPACITY_DESC, required = true)
+    private long _totalCapacity;
+
+    @Parameter(name = SfApiConstants.TOTAL_MIN_IOPS, type = CommandType.LONG, description = SfApiConstants.TOTAL_MIN_IOPS_DESC, required = true)
+    private long _totalMinIops;
+
+    @Parameter(name = SfApiConstants.TOTAL_MAX_IOPS, type = CommandType.LONG, description = SfApiConstants.TOTAL_MAX_IOPS_DESC, required = true)
+    private long _totalMaxIops;
+
+    @Parameter(name = SfApiConstants.TOTAL_BURST_IOPS, type = CommandType.LONG, description = SfApiConstants.TOTAL_BURST_IOPS_DESC, required = true)
+    private long _totalBurstIops;
+
+    @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, description = SfApiConstants.ZONE_ID_DESC, required = true)
+    private long _zoneId;
+
+    @Inject private SolidFireManager _solidFireManager;
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(CreateReferenceToSolidFireClusterCmd.class.getName() + ".execute invoked");
+
+            SfCluster sfCluster = _solidFireManager.createReferenceToSolidFireCluster(_mvip, _username, _password, _totalCapacity,
+                    _totalMinIops, _totalMaxIops, _totalBurstIops, _zoneId);
+
+            ApiSolidFireClusterResponse response = _sfUtil.getApiSolidFireClusterResponse(sfCluster);
+
+            response.setResponseName(getCommandName());
+            response.setObjectName("apicreatereferencetosolidfirecluster");
+
+            setResponseObject(response);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/CreateSolidFireVirtualNetworkCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/CreateSolidFireVirtualNetworkCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/CreateSolidFireVirtualNetworkCmd.java
new file mode 100644
index 0000000..f78baac
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/CreateSolidFireVirtualNetworkCmd.java
@@ -0,0 +1,104 @@
+// 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.api.command.admin.solidfire;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ResponseObject.ResponseView;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireVirtualNetworkResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfVirtualNetwork;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "createSolidFireVirtualNetwork", responseObject = ApiSolidFireVirtualNetworkResponse.class, description = "Create SolidFire Virtual Network",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class CreateSolidFireVirtualNetworkCmd extends BaseCmd {
+    private static final Logger s_logger = Logger.getLogger(CreateSolidFireVirtualNetworkCmd.class.getName());
+    private static final String s_name = "createsolidfirevirtualnetworkresponse";
+
+    @Parameter(name = SfApiConstants.CLUSTER_NAME, type = CommandType.STRING, description = SfApiConstants.SOLIDFIRE_CLUSTER_NAME_DESC, required = true)
+    private String _clusterName;
+
+    @Parameter(name = SfApiConstants.NAME, type = CommandType.STRING, description = SfApiConstants.VIRTUAL_NETWORK_NAME_DESC, required = true)
+    private String _name;
+
+    @Parameter(name = SfApiConstants.TAG, type = CommandType.STRING, description = SfApiConstants.VIRTUAL_NETWORK_TAG_DESC, required = true)
+    private String _tag;
+
+    @Parameter(name = SfApiConstants.START_IP, type = CommandType.STRING, description = SfApiConstants.START_IP_ADDRESS_DESC, required = true)
+    private String _startIp;
+
+    @Parameter(name = SfApiConstants.SIZE, type = CommandType.INTEGER, description = SfApiConstants.NUMBER_OF_IP_ADDRESSES_DESC, required = true)
+    private int _size;
+
+    @Parameter(name = SfApiConstants.NETMASK, type = CommandType.STRING, description = SfApiConstants.NETMASK_DESC, required = true)
+    private String _netmask;
+
+    @Parameter(name = SfApiConstants.SVIP, type = CommandType.STRING, description = SfApiConstants.SOLIDFIRE_SVIP_DESC, required = true)
+    private String _svip;
+
+    @Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = SfApiConstants.ACCOUNT_ID_DESC, required = true)
+    private long _accountId;
+
+    @Inject private SolidFireManager _solidFireManager;
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return _accountId;
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(CreateSolidFireVirtualNetworkCmd.class.getName() + ".execute invoked");
+
+            SfVirtualNetwork sfVirtualNetwork = _solidFireManager.createSolidFireVirtualNetwork(_clusterName, _name, _tag, _startIp, _size, _netmask, _svip, _accountId);
+
+            ApiSolidFireVirtualNetworkResponse response = _sfUtil.getApiSolidFireVirtualNetworkResponse(sfVirtualNetwork, ResponseView.Full);
+
+            response.setResponseName(getCommandName());
+            response.setObjectName("apicreatesolidfirevirtualnetwork");
+
+            setResponseObject(response);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/DeleteReferenceToSolidFireClusterCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/DeleteReferenceToSolidFireClusterCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/DeleteReferenceToSolidFireClusterCmd.java
new file mode 100644
index 0000000..7ee063c
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/DeleteReferenceToSolidFireClusterCmd.java
@@ -0,0 +1,82 @@
+// 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.api.command.admin.solidfire;
+
+import com.cloud.user.Account;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireClusterResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfCluster;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "deleteReferenceToSolidFireCluster", responseObject = ApiSolidFireClusterResponse.class, description = "Delete Reference to SolidFire Cluster",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class DeleteReferenceToSolidFireClusterCmd extends BaseCmd {
+    private static final Logger s_logger = Logger.getLogger(DeleteReferenceToSolidFireClusterCmd.class.getName());
+    private static final String s_name = "deletereferencetosolidfireclusterresponse";
+
+    @Parameter(name = SfApiConstants.NAME, type = CommandType.STRING, description = SfApiConstants.SOLIDFIRE_CLUSTER_NAME_DESC, required = true)
+    private String _name;
+
+    @Inject private SolidFireManager _solidFireManager;
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(DeleteReferenceToSolidFireClusterCmd.class.getName() + ".execute invoked");
+
+            SfCluster sfCluster = _solidFireManager.deleteReferenceToSolidFireCluster(_name);
+
+            ApiSolidFireClusterResponse response = _sfUtil.getApiSolidFireClusterResponse(sfCluster);
+
+            response.setResponseName(getCommandName());
+            response.setObjectName("apideletereferencetosolidfirecluster");
+
+            setResponseObject(response);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/DeleteSolidFireVirtualNetworkCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/DeleteSolidFireVirtualNetworkCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/DeleteSolidFireVirtualNetworkCmd.java
new file mode 100644
index 0000000..56b57b2
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/DeleteSolidFireVirtualNetworkCmd.java
@@ -0,0 +1,90 @@
+// 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.api.command.admin.solidfire;
+
+import com.cloud.user.Account;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.ResponseObject.ResponseView;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireVirtualNetworkResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfVirtualNetwork;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "deleteSolidFireVirtualNetwork", responseObject = ApiSolidFireVirtualNetworkResponse.class, description = "Delete SolidFire Virtual Network",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class DeleteSolidFireVirtualNetworkCmd extends BaseCmd {
+    private static final Logger s_logger = Logger.getLogger(DeleteSolidFireVirtualNetworkCmd.class.getName());
+    private static final String s_name = "deletesolidfirevirtualnetworkresponse";
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ApiSolidFireVirtualNetworkResponse.class, description = SfApiConstants.VIRTUAL_NETWORK_ID_DESC, required = true)
+    private long _id;
+
+    @Inject private SolidFireManager _solidFireManager;
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        SfVirtualNetwork sfVirtualNetwork = _entityMgr.findById(SfVirtualNetwork.class, _id);
+
+        if (sfVirtualNetwork != null) {
+            sfVirtualNetwork.getAccountId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(DeleteSolidFireVirtualNetworkCmd.class.getName() + ".execute invoked");
+
+            SfVirtualNetwork sfVirtualNetwork = _solidFireManager.deleteSolidFireVirtualNetwork(_id);
+
+            ApiSolidFireVirtualNetworkResponse response = _sfUtil.getApiSolidFireVirtualNetworkResponse(sfVirtualNetwork, ResponseView.Full);
+
+            response.setResponseName(getCommandName());
+            response.setObjectName("apideletesolidfirevirtualnetwork");
+
+            setResponseObject(response);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/ListSolidFireClustersCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/ListSolidFireClustersCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/ListSolidFireClustersCmd.java
new file mode 100644
index 0000000..e2e168c
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/ListSolidFireClustersCmd.java
@@ -0,0 +1,95 @@
+// 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.api.command.admin.solidfire;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireClusterResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfCluster;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "listSolidFireClusters", responseObject = ApiSolidFireClusterResponse.class, description = "List SolidFire Clusters",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class ListSolidFireClustersCmd extends BaseListCmd {
+    private static final Logger s_logger = Logger.getLogger(ListSolidFireClustersCmd.class.getName());
+    private static final String s_name = "listsolidfireclustersresponse";
+
+    @Parameter(name = SfApiConstants.NAME, type = CommandType.STRING, description = SfApiConstants.SOLIDFIRE_CLUSTER_NAME_DESC)
+    private String _name;
+
+    @Inject private SolidFireManager _solidFireManager;
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(ListSolidFireClustersCmd.class.getName() + ".execute invoked");
+
+            final List<SfCluster> sfClusters;
+
+            if (_name != null) {
+                sfClusters = new ArrayList<>();
+
+                SfCluster sfCluster = _solidFireManager.listSolidFireCluster(_name);
+
+                if (sfCluster != null) {
+                    sfClusters.add(sfCluster);
+                }
+            }
+            else {
+                sfClusters = _solidFireManager.listSolidFireClusters();
+            }
+
+            List<ApiSolidFireClusterResponse> responses = _sfUtil.getApiSolidFireClusterResponse(sfClusters);
+
+            ListResponse<ApiSolidFireClusterResponse> listReponse = new ListResponse<>();
+
+            listReponse.setResponses(responses);
+            listReponse.setResponseName(getCommandName());
+            listReponse.setObjectName("apilistsolidfireclusters");
+
+            setResponseObject(listReponse);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/UpdateReferenceToSolidFireClusterCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/UpdateReferenceToSolidFireClusterCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/UpdateReferenceToSolidFireClusterCmd.java
new file mode 100644
index 0000000..6f102a4
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/UpdateReferenceToSolidFireClusterCmd.java
@@ -0,0 +1,95 @@
+// 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.api.command.admin.solidfire;
+
+import com.cloud.user.Account;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireClusterResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfCluster;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "updateReferenceToSolidFireCluster", responseObject = ApiSolidFireClusterResponse.class, description = "Update Reference to SolidFire Cluster",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class UpdateReferenceToSolidFireClusterCmd extends BaseCmd {
+    private static final Logger s_logger = Logger.getLogger(UpdateReferenceToSolidFireClusterCmd.class.getName());
+    private static final String s_name = "updatereferencetosolidfireclusterresponse";
+
+    @Parameter(name = SfApiConstants.NAME, type = CommandType.STRING, description = SfApiConstants.SOLIDFIRE_CLUSTER_NAME_DESC, required = true)
+    private String _name;
+
+    @Parameter(name = SfApiConstants.TOTAL_CAPACITY, type = CommandType.LONG, description = SfApiConstants.TOTAL_CAPACITY_DESC, required = true)
+    private long _totalCapacity;
+
+    @Parameter(name = SfApiConstants.TOTAL_MIN_IOPS, type = CommandType.LONG, description = SfApiConstants.TOTAL_MIN_IOPS_DESC, required = true)
+    private long _totalMinIops;
+
+    @Parameter(name = SfApiConstants.TOTAL_MAX_IOPS, type = CommandType.LONG, description = SfApiConstants.TOTAL_MAX_IOPS_DESC, required = true)
+    private long _totalMaxIops;
+
+    @Parameter(name = SfApiConstants.TOTAL_BURST_IOPS, type = CommandType.LONG, description = SfApiConstants.TOTAL_BURST_IOPS_DESC, required = true)
+    private long _totalBurstIops;
+
+    @Inject private SolidFireManager _solidFireManager;
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(UpdateReferenceToSolidFireClusterCmd.class.getName() + ".execute invoked");
+
+            SfCluster sfCluster = _solidFireManager.updateReferenceToSolidFireCluster(_name, _totalCapacity,
+                    _totalMinIops, _totalMaxIops, _totalBurstIops);
+
+            ApiSolidFireClusterResponse response = _sfUtil.getApiSolidFireClusterResponse(sfCluster);
+
+            response.setResponseName(getCommandName());
+            response.setObjectName("apiupdatereferencetosolidfirecluster");
+
+            setResponseObject(response);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/UpdateSolidFireVirtualNetworkCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/UpdateSolidFireVirtualNetworkCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/UpdateSolidFireVirtualNetworkCmd.java
new file mode 100644
index 0000000..26c717c
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/admin/solidfire/UpdateSolidFireVirtualNetworkCmd.java
@@ -0,0 +1,103 @@
+// 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.api.command.admin.solidfire;
+
+import com.cloud.user.Account;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.ResponseObject.ResponseView;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireVirtualNetworkResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfVirtualNetwork;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "updateSolidFireVirtualNetwork", responseObject = ApiSolidFireVirtualNetworkResponse.class, description = "Update SolidFire Virtual Network",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class UpdateSolidFireVirtualNetworkCmd extends BaseCmd {
+    private static final Logger s_logger = Logger.getLogger(UpdateSolidFireVirtualNetworkCmd.class.getName());
+    private static final String s_name = "updatesolidfirevirtualnetworkresponse";
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ApiSolidFireVirtualNetworkResponse.class, description = SfApiConstants.VIRTUAL_NETWORK_ID_DESC,
+            required = true)
+    private long _id;
+
+    @Parameter(name = SfApiConstants.NAME, type = CommandType.STRING, description = SfApiConstants.VIRTUAL_NETWORK_NAME_DESC, required = true)
+    private String _name;
+
+    @Parameter(name = SfApiConstants.START_IP, type = CommandType.STRING, description = SfApiConstants.START_IP_ADDRESS_DESC, required = true)
+    private String _startIp;
+
+    @Parameter(name = SfApiConstants.SIZE, type = CommandType.INTEGER, description = SfApiConstants.NUMBER_OF_IP_ADDRESSES_DESC, required = true)
+    private int _size;
+
+    @Parameter(name = SfApiConstants.NETMASK, type = CommandType.STRING, description = SfApiConstants.NETMASK, required = true)
+    private String _netmask;
+
+    @Inject private SolidFireManager _solidFireManager;
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        SfVirtualNetwork sfVirtualNetwork = _entityMgr.findById(SfVirtualNetwork.class, _id);
+
+        if (sfVirtualNetwork != null) {
+            sfVirtualNetwork.getAccountId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(UpdateSolidFireVirtualNetworkCmd.class.getName() + ".execute invoked");
+
+            SfVirtualNetwork sfVirtualNetwork = _solidFireManager.updateSolidFireVirtualNetwork(_id, _name, _startIp, _size, _netmask);
+
+            ApiSolidFireVirtualNetworkResponse response = _sfUtil.getApiSolidFireVirtualNetworkResponse(sfVirtualNetwork, ResponseView.Full);
+
+            response.setResponseName(getCommandName());
+            response.setObjectName("apiupdatesolidfirevirtualnetwork");
+
+            setResponseObject(response);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/CreateSolidFireVolumeCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/CreateSolidFireVolumeCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/CreateSolidFireVolumeCmd.java
new file mode 100644
index 0000000..ffb59a3
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/CreateSolidFireVolumeCmd.java
@@ -0,0 +1,105 @@
+// 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.api.command.user.solidfire;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.ResponseObject.ResponseView;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireVirtualNetworkResponse;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireVolumeResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfVolume;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "createSolidFireVolume", responseObject = ApiSolidFireVolumeResponse.class, description = "Create SolidFire Volume",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class CreateSolidFireVolumeCmd extends BaseCmd {
+    private static final Logger s_logger = Logger.getLogger(CreateSolidFireVolumeCmd.class.getName());
+    private static final String s_name = "createsolidfirevolumeresponse";
+
+    @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = SfApiConstants.VOLUME_NAME_DESC, required = true)
+    private String _name;
+
+    @Parameter(name = ApiConstants.SIZE, type = CommandType.LONG, description = SfApiConstants.SIZE_DESC, required = true)
+    private long _size;
+
+    @Parameter(name = ApiConstants.MIN_IOPS, type = CommandType.LONG, description = SfApiConstants.MIN_IOPS_DESC, required = true)
+    private long _minIops;
+
+    @Parameter(name = ApiConstants.MAX_IOPS, type = CommandType.LONG, description = SfApiConstants.MAX_IOPS_DESC, required = true)
+    private long _maxIops;
+
+    @Parameter(name = SfApiConstants.BURST_IOPS, type = CommandType.LONG, description = SfApiConstants.BURST_IOPS_DESC, required = true)
+    private long _burstIops;
+
+    @Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = SfApiConstants.ACCOUNT_ID_DESC, required = true)
+    private long _accountId;
+
+    @Parameter(name = SfApiConstants.SF_VIRTUAL_NETWORK_ID, type = CommandType.UUID, entityType = ApiSolidFireVirtualNetworkResponse.class,
+            description = SfApiConstants.VIRTUAL_NETWORK_ID_DESC, required = true)
+    private long _sfVirtualNetworkId;
+
+    @Inject private SolidFireManager _solidFireManager;
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return _accountId;
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(CreateSolidFireVolumeCmd.class.getName() + ".execute invoked");
+
+            SfVolume sfVolume = _solidFireManager.createSolidFireVolume(_name, _size, _minIops, _maxIops, _burstIops, _accountId, _sfVirtualNetworkId);
+
+            ResponseView responseView = _sfUtil.isRootAdmin() ? ResponseView.Full : ResponseView.Restricted;
+
+            ApiSolidFireVolumeResponse response = _sfUtil.getApiSolidFireVolumeResponse(sfVolume, responseView);
+
+            response.setResponseName(getCommandName());
+            response.setObjectName("apicreatesolidfirevolume");
+
+            setResponseObject(response);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/49ca3b40/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/DeleteSolidFireVolumeCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/DeleteSolidFireVolumeCmd.java b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/DeleteSolidFireVolumeCmd.java
new file mode 100644
index 0000000..6185db1
--- /dev/null
+++ b/plugins/api/solidfire/src/org/apache/cloudstack/api/command/user/solidfire/DeleteSolidFireVolumeCmd.java
@@ -0,0 +1,97 @@
+// 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.api.command.user.solidfire;
+
+import com.cloud.user.Account;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.ResponseObject.ResponseView;
+import org.apache.cloudstack.api.response.solidfire.ApiSolidFireVolumeResponse;
+import org.apache.cloudstack.api.solidfire.SfApiConstants;
+import org.apache.cloudstack.solidfire.SfVirtualNetwork;
+import org.apache.cloudstack.solidfire.SfVolume;
+import org.apache.cloudstack.solidfire.SolidFireManager;
+import org.apache.cloudstack.util.solidfire.SfUtil;
+
+@APICommand(name = "deleteSolidFireVolume", responseObject = ApiSolidFireVolumeResponse.class, description = "Delete SolidFire Volume",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class DeleteSolidFireVolumeCmd extends BaseCmd {
+    private static final Logger s_logger = Logger.getLogger(DeleteSolidFireVolumeCmd.class.getName());
+    private static final String s_name = "deletesolidfirevolumeresponse";
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ApiSolidFireVolumeResponse.class, description = SfApiConstants.VOLUME_ID_DESC, required = true)
+    private long _id;
+
+    @Inject private SolidFireManager _solidFireManager;
+    @Inject private SfUtil _sfUtil;
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        SfVolume sfVolume = _entityMgr.findById(SfVolume.class, _id);
+
+        if (sfVolume != null) {
+            SfVirtualNetwork sfVirtualNetwork = _entityMgr.findById(SfVirtualNetwork.class, sfVolume.getSfVirtualNetworkId());
+
+            if (sfVirtualNetwork != null) {
+                sfVirtualNetwork.getAccountId();
+            }
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    @Override
+    public void execute() {
+        try {
+            s_logger.info(DeleteSolidFireVolumeCmd.class.getName() + ".execute invoked");
+
+            SfVolume sfVolume = _solidFireManager.deleteSolidFireVolume(_id);
+
+            ResponseView responseView = _sfUtil.isRootAdmin() ? ResponseView.Full : ResponseView.Restricted;
+
+            ApiSolidFireVolumeResponse response = _sfUtil.getApiSolidFireVolumeResponse(sfVolume, responseView);
+
+            response.setResponseName(getCommandName());
+            response.setObjectName("apideletesolidfirevolume");
+
+            setResponseObject(response);
+        }
+        catch (Throwable t) {
+            s_logger.error(t.getMessage());
+
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, t.getMessage());
+        }
+    }
+}