cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From t..@apache.org
Subject [15/25] git commit: updated refs/heads/bvt to 5727bd0
Date Fri, 29 Mar 2013 12:46:17 GMT
CLOUDSTACK-1156: Limit Primary and Secondary storage for domain/accounts

    Addition of two new resource types i.e. Primary and Secondary storage space in the existing pool of
    resource types.
    Added methods to set the limits on these resources using updateResourceLimit
    API command and to get a count using updateResourceCount. Also added calls in the
    Templates, Volumes, Snapshots life cycle to check these limits and to increment/decrement the new
    resource types

    Resource Name          :: Resource type number
        Primary Storage               10
        Secondary Storage             11

    Also added jUnit Tests for the same.
Reviewed by : nitin mehta<nitin.mehta@citrix.com>


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

Branch: refs/heads/bvt
Commit: 18695276f79a4cf90279f6ff25ebc7c66b6a9c49
Parents: d6e11f2
Author: Sanjay Tripathi <sanja.tripathi@citrix.com>
Authored: Fri Mar 29 11:21:10 2013 +0530
Committer: Nitin Mehta <nitin.mehta@citrix.com>
Committed: Fri Mar 29 11:26:38 2013 +0530

----------------------------------------------------------------------
 api/src/com/cloud/configuration/Resource.java      |    7 +-
 api/src/com/cloud/storage/VolumeApiService.java    |    5 +-
 .../user/resource/UpdateResourceCountCmd.java      |    6 +-
 .../user/resource/UpdateResourceLimitCmd.java      |    6 +-
 .../api/command/user/volume/ResizeVolumeCmd.java   |    3 +-
 .../cloudstack/api/response/AccountResponse.java   |   54 +++++-
 .../api/response/ResourceCountResponse.java        |    2 +-
 .../api/response/ResourceLimitResponse.java        |    2 +-
 .../manager/BareMetalTemplateAdapter.java          |   15 ++-
 server/src/com/cloud/alert/AlertManagerImpl.java   |    3 +-
 server/src/com/cloud/api/ApiResponseHelper.java    |  149 ++++++++++----
 .../cloud/api/query/dao/AccountJoinDaoImpl.java    |   18 ++
 .../src/com/cloud/api/query/vo/AccountJoinVO.java  |   54 +++++
 server/src/com/cloud/configuration/Config.java     |    5 +-
 .../resourcelimit/ResourceLimitManagerImpl.java    |   54 +++++
 server/src/com/cloud/storage/VolumeManager.java    |    3 +-
 .../src/com/cloud/storage/VolumeManagerImpl.java   |   95 +++++++--
 server/src/com/cloud/storage/dao/SnapshotDao.java  |   12 +-
 .../src/com/cloud/storage/dao/SnapshotDaoImpl.java |   65 ++++--
 server/src/com/cloud/storage/dao/VolumeDao.java    |   66 ++++---
 .../src/com/cloud/storage/dao/VolumeDaoImpl.java   |   48 ++++-
 .../cloud/storage/download/DownloadListener.java   |   62 +++++-
 .../storage/download/DownloadMonitorImpl.java      |   56 +++++-
 .../storage/snapshot/SnapshotManagerImpl.java      |   70 ++++---
 .../cloud/template/HypervisorTemplateAdapter.java  |   29 ++--
 .../com/cloud/template/TemplateManagerImpl.java    |   47 +++--
 server/src/com/cloud/vm/UserVmManagerImpl.java     |   15 ++-
 .../ResourceLimitManagerImplTest.java              |   18 ++-
 .../cloud/vpc/MockResourceLimitManagerImpl.java    |    8 +
 setup/db/db/schema-40to410.sql                     |   24 ---
 setup/db/db/schema-410to420.sql                    |  153 ++++++++++++++-
 utils/src/com/cloud/utils/UriUtils.java            |   33 +++
 32 files changed, 936 insertions(+), 251 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/api/src/com/cloud/configuration/Resource.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/configuration/Resource.java b/api/src/com/cloud/configuration/Resource.java
index 7614c8a..5550e29 100644
--- a/api/src/com/cloud/configuration/Resource.java
+++ b/api/src/com/cloud/configuration/Resource.java
@@ -20,7 +20,7 @@ public interface Resource {
 
     public static final short RESOURCE_UNLIMITED = -1;
 
-    public enum ResourceType {
+    public enum ResourceType { // Primary and Secondary storage are allocated_storage and not the physical storage.
         user_vm("user_vm", 0, ResourceOwnerType.Account, ResourceOwnerType.Domain),
         public_ip("public_ip", 1, ResourceOwnerType.Account, ResourceOwnerType.Domain),
         volume("volume", 2, ResourceOwnerType.Account, ResourceOwnerType.Domain),
@@ -30,11 +30,14 @@ public interface Resource {
         network("network", 6, ResourceOwnerType.Account, ResourceOwnerType.Domain),
         vpc("vpc", 7, ResourceOwnerType.Account, ResourceOwnerType.Domain),
         cpu("cpu", 8, ResourceOwnerType.Account, ResourceOwnerType.Domain),
-        memory("memory", 9, ResourceOwnerType.Account, ResourceOwnerType.Domain);
+        memory("memory", 9, ResourceOwnerType.Account, ResourceOwnerType.Domain),
+        primary_storage("primary_storage", 10, ResourceOwnerType.Account, ResourceOwnerType.Domain),
+        secondary_storage("secondary_storage", 11, ResourceOwnerType.Account, ResourceOwnerType.Domain);
 
         private String name;
         private ResourceOwnerType[] supportedOwners;
         private int ordinal;
+        public static final long bytesToGiB = 1024 * 1024 * 1024;
 
         ResourceType(String name, int ordinal, ResourceOwnerType... supportedOwners) {
             this.name = name;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/api/src/com/cloud/storage/VolumeApiService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/VolumeApiService.java b/api/src/com/cloud/storage/VolumeApiService.java
index 8517988..09a07d4 100644
--- a/api/src/com/cloud/storage/VolumeApiService.java
+++ b/api/src/com/cloud/storage/VolumeApiService.java
@@ -59,9 +59,10 @@ public interface VolumeApiService {
      * @param cmd
      *            the API command wrapping the criteria
      * @return the volume object
+     * @throws ResourceAllocationException
      */
-    Volume resizeVolume(ResizeVolumeCmd cmd);
-    
+    Volume resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationException;
+
     Volume migrateVolume(MigrateVolumeCmd cmd) throws ConcurrentOperationException;
 
     /**

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java b/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java
index f6d3a98..0f4c932 100644
--- a/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java
@@ -53,7 +53,7 @@ public class UpdateResourceCountCmd extends BaseCmd {
             required=true, description="If account parameter specified then updates resource counts for a specified account in this domain else update resource counts for all accounts & child domains in specified domain.")
     private Long domainId;
 
-    @Parameter(name=ApiConstants.RESOURCE_TYPE, type=CommandType.INTEGER, description=  "Type of resource to update. If specifies valid values are 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9. If not specified will update all resource counts" +
+    @Parameter(name=ApiConstants.RESOURCE_TYPE, type=CommandType.INTEGER, description=  "Type of resource to update. If specifies valid values are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 and 11. If not specified will update all resource counts" +
                                                                                         "0 - Instance. Number of instances a user can create. " +
                                                                                         "1 - IP. Number of public IP addresses a user can own. " +
                                                                                         "2 - Volume. Number of disk volumes a user can create." +
@@ -63,7 +63,9 @@ public class UpdateResourceCountCmd extends BaseCmd {
                                                                                         "6 - Network. Number of guest network a user can create." +
                                                                                         "7 - VPC. Number of VPC a user can create." +
                                                                                         "8 - CPU. Total number of CPU cores a user can use." +
-                                                                                        "9 - Memory. Total Memory (in MB) a user can use." )
+                                                                                        "9 - Memory. Total Memory (in MB) a user can use." +
+                                                                                        "10 - PrimaryStorage. Total primary storage space (in GiB) a user can use." +
+                                                                                        "11 - SecondaryStorage. Total secondary storage space (in GiB) a user can use." )
     private Integer resourceType;
 
     @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmd.java b/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmd.java
index 0039f62..826596c 100644
--- a/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmd.java
@@ -54,7 +54,7 @@ public class UpdateResourceLimitCmd extends BaseCmd {
     @Parameter(name=ApiConstants.MAX, type=CommandType.LONG, description="  Maximum resource limit.")
     private Long max;
 
-    @Parameter(name=ApiConstants.RESOURCE_TYPE, type=CommandType.INTEGER, required=true, description="Type of resource to update. Values are 0, 1, 2, 3, 4, 6, 7, 8 and 9. 0 - Instance. Number of instances a user can create. " +
+    @Parameter(name=ApiConstants.RESOURCE_TYPE, type=CommandType.INTEGER, required=true, description="Type of resource to update. Values are 0, 1, 2, 3, 4, 6, 7, 8, 9, 10 and 11. 0 - Instance. Number of instances a user can create. " +
                                                                                         "1 - IP. Number of public IP addresses a user can own. " +
                                                                                         "2 - Volume. Number of disk volumes a user can create." +
                                                                                         "3 - Snapshot. Number of snapshots a user can create." +
@@ -62,7 +62,9 @@ public class UpdateResourceLimitCmd extends BaseCmd {
                                                                                         "6 - Network. Number of guest network a user can create." +
                                                                                         "7 - VPC. Number of VPC a user can create." +
                                                                                         "8 - CPU. Total number of CPU cores a user can use." +
-                                                                                        "9 - Memory. Total Memory (in MB) a user can use." )
+                                                                                        "9 - Memory. Total Memory (in MB) a user can use." +
+                                                                                        "10 - PrimaryStorage. Total primary storage space (in GiB) a user can use." +
+                                                                                        "11 - SecondaryStorage. Total secondary storage space (in GiB) a user can use." )
     private Integer resourceType;
 
     /////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java
index 955727a..871bf45 100644
--- a/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java
@@ -30,6 +30,7 @@ import com.cloud.async.AsyncJob;
 import com.cloud.event.EventTypes;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.PermissionDeniedException;
+import com.cloud.exception.ResourceAllocationException;
 import com.cloud.projects.Project;
 import com.cloud.storage.Volume;
 import com.cloud.user.Account;
@@ -131,7 +132,7 @@ public class ResizeVolumeCmd extends BaseAsyncCmd {
     }
 
     @Override
-    public void execute(){
+    public void execute() throws ResourceAllocationException{
         UserContext.current().setEventDetails("Volume Id: " + getEntityId() + " to size " + getSize() + "G");
     	Volume volume = _volumeService.resizeVolume(this);
     	if (volume != null) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/api/src/org/apache/cloudstack/api/response/AccountResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/AccountResponse.java b/api/src/org/apache/cloudstack/api/response/AccountResponse.java
index 9a98a35..c109a63 100644
--- a/api/src/org/apache/cloudstack/api/response/AccountResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/AccountResponse.java
@@ -132,24 +132,42 @@ public class AccountResponse extends BaseResponse {
     @SerializedName("vpcavailable") @Param(description="the total number of vpcs available to be created for this account", since="4.0.0")
     private String vpcAvailable;
 
-    @SerializedName("cpulimit") @Param(description="the total number of cpu cores the account can own", since="4.1.0")
+    @SerializedName("cpulimit") @Param(description="the total number of cpu cores the account can own", since="4.2.0")
     private String cpuLimit;
 
-    @SerializedName("cputotal") @Param(description="the total number of cpu cores owned by account", since="4.1.0")
+    @SerializedName("cputotal") @Param(description="the total number of cpu cores owned by account", since="4.2.0")
     private Long cpuTotal;
 
-    @SerializedName("cpuavailable") @Param(description="the total number of cpu cores available to be created for this account", since="4.1.0")
+    @SerializedName("cpuavailable") @Param(description="the total number of cpu cores available to be created for this account", since="4.2.0")
     private String cpuAvailable;
 
-    @SerializedName("memorylimit") @Param(description="the total memory (in MB) the account can own", since="4.1.0")
+    @SerializedName("memorylimit") @Param(description="the total memory (in MB) the account can own", since="4.2.0")
     private String memoryLimit;
 
-    @SerializedName("memorytotal") @Param(description="the total memory (in MB) owned by account", since="4.1.0")
+    @SerializedName("memorytotal") @Param(description="the total memory (in MB) owned by account", since="4.2.0")
     private Long memoryTotal;
 
-    @SerializedName("memoryavailable") @Param(description="the total memory (in MB) available to be created for this account", since="4.1.0")
+    @SerializedName("memoryavailable") @Param(description="the total memory (in MB) available to be created for this account", since="4.2.0")
     private String memoryAvailable;
 
+    @SerializedName("primarystoragelimit") @Param(description="the total primary storage space (in GiB) the account can own", since="4.2.0")
+    private String primaryStorageLimit;
+
+    @SerializedName("primarystoragetotal") @Param(description="the total primary storage space (in GiB) owned by account", since="4.2.0")
+    private Long primaryStorageTotal;
+
+    @SerializedName("primarystorageavailable") @Param(description="the total primary storage space (in GiB) available to be used for this account", since="4.2.0")
+    private String primaryStorageAvailable;
+
+    @SerializedName("secondarystoragelimit") @Param(description="the total secondary storage space (in GiB) the account can own", since="4.2.0")
+    private String secondaryStorageLimit;
+
+    @SerializedName("secondarystoragetotal") @Param(description="the total secondary storage space (in GiB) owned by account", since="4.2.0")
+    private Long secondaryStorageTotal;
+
+    @SerializedName("secondarystorageavailable") @Param(description="the total secondary storage space (in GiB) available to be used for this account", since="4.2.0")
+    private String secondaryStorageAvailable;
+
 
     @SerializedName(ApiConstants.STATE) @Param(description="the state of the account")
     private String state;
@@ -336,6 +354,30 @@ public class AccountResponse extends BaseResponse {
         this.memoryAvailable = memoryAvailable;
     }
 
+    public void setPrimaryStorageLimit(String primaryStorageLimit) {
+        this.primaryStorageLimit = primaryStorageLimit;
+    }
+
+    public void setPrimaryStorageTotal(Long primaryStorageTotal) {
+        this.primaryStorageTotal = primaryStorageTotal;
+    }
+
+    public void setPrimaryStorageAvailable(String primaryStorageAvailable) {
+        this.primaryStorageAvailable = primaryStorageAvailable;
+    }
+
+    public void setSecondaryStorageLimit(String secondaryStorageLimit) {
+        this.secondaryStorageLimit = secondaryStorageLimit;
+    }
+
+    public void setSecondaryStorageTotal(Long secondaryStorageTotal) {
+        this.secondaryStorageTotal = secondaryStorageTotal;
+    }
+
+    public void setSecondaryStorageAvailable(String secondaryStorageAvailable) {
+        this.secondaryStorageAvailable = secondaryStorageAvailable;
+    }
+
     public void setDefaultZone(String defaultZoneId) {
         this.defaultZoneId = defaultZoneId;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/api/src/org/apache/cloudstack/api/response/ResourceCountResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/ResourceCountResponse.java b/api/src/org/apache/cloudstack/api/response/ResourceCountResponse.java
index a7fbbf2..842eaa6 100644
--- a/api/src/org/apache/cloudstack/api/response/ResourceCountResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/ResourceCountResponse.java
@@ -40,7 +40,7 @@ public class ResourceCountResponse extends BaseResponse implements ControlledEnt
     @SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name for which resource count's are updated")
     private String domainName;
 
-    @SerializedName(ApiConstants.RESOURCE_TYPE) @Param(description="resource type. Values include 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. See the resourceType parameter for more information on these values.")
+    @SerializedName(ApiConstants.RESOURCE_TYPE) @Param(description="resource type. Values include 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11. See the resourceType parameter for more information on these values.")
     private String resourceType;
 
     @SerializedName("resourcecount") @Param(description="resource count")

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/api/src/org/apache/cloudstack/api/response/ResourceLimitResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/ResourceLimitResponse.java b/api/src/org/apache/cloudstack/api/response/ResourceLimitResponse.java
index b444e7a..e7735f5 100644
--- a/api/src/org/apache/cloudstack/api/response/ResourceLimitResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/ResourceLimitResponse.java
@@ -36,7 +36,7 @@ public class ResourceLimitResponse extends BaseResponse implements ControlledEnt
     @SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name of the resource limit")
     private String domainName;
 
-    @SerializedName(ApiConstants.RESOURCE_TYPE) @Param(description="resource type. Values include 0, 1, 2, 3, 4, 6, 7, 8, 9. See the resourceType parameter for more information on these values.")
+    @SerializedName(ApiConstants.RESOURCE_TYPE) @Param(description="resource type. Values include 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11. See the resourceType parameter for more information on these values.")
     private String resourceType;
 
     @SerializedName("max") @Param(description="the maximum number of the resource. A -1 means the resource currently has no limit.")

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java
index 33725f6..928183b 100755
--- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java
@@ -50,6 +50,7 @@ import com.cloud.storage.VMTemplateZoneVO;
 import com.cloud.template.TemplateAdapter;
 import com.cloud.template.TemplateAdapterBase;
 import com.cloud.user.Account;
+import com.cloud.utils.UriUtils;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.exception.CloudRuntimeException;
 
@@ -82,7 +83,11 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem
 				throw new CloudRuntimeException("Please add PXE server before adding baremetal template in zone " + profile.getZoneId());
 			}
 		}
-		
+
+        // Check that the resource limit for secondary storage won't be exceeded
+        _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()),
+                ResourceType.secondary_storage, UriUtils.getRemoteSize(profile.getUrl()));
+
 		return profile;
 	}
 	
@@ -133,6 +138,8 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem
 		}
 		
 		_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
+        _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.secondary_storage,
+                UriUtils.getRemoteSize(profile.getUrl()));
 		return template;
 	}
 
@@ -205,8 +212,10 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem
 					s_logger.debug("Failed to acquire lock when deleting template with ID: " + templateId);
 					success = false;
 				} else if (_tmpltDao.remove(templateId)) {
-					// Decrement the number of templates
-				    _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template);
+                    // Decrement the number of templates and total secondary storage space used by the account.
+                    _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template);
+                    _resourceLimitMgr.recalculateResourceCount(accountId, template.getDomainId(),
+                            ResourceType.secondary_storage.getOrdinal());
 				}
 
 			} finally {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/alert/AlertManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/alert/AlertManagerImpl.java b/server/src/com/cloud/alert/AlertManagerImpl.java
index a45482f..655ed98 100755
--- a/server/src/com/cloud/alert/AlertManagerImpl.java
+++ b/server/src/com/cloud/alert/AlertManagerImpl.java
@@ -802,7 +802,8 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager {
                     (alertType != AlertManager.ALERT_TYPE_CONSOLE_PROXY) &&
                     (alertType != AlertManager.ALERT_TYPE_SSVM) &&
                     (alertType != AlertManager.ALERT_TYPE_STORAGE_MISC) &&
-                    (alertType != AlertManager.ALERT_TYPE_MANAGMENT_NODE)) {
+                    (alertType != AlertManager.ALERT_TYPE_MANAGMENT_NODE) &&
+                    (alertType != AlertManager.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED)) {
                 alert = _alertDao.getLastAlert(alertType, dataCenterId, podId, clusterId);
             }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/api/ApiResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index f33601f..ec80909 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -16,10 +16,32 @@
 // under the License.
 package com.cloud.api;
 
-import com.cloud.api.query.ViewResponseHelper;
-import com.cloud.api.query.vo.*;
-import com.cloud.api.response.ApiResponseSerializer;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
 
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.TimeZone;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.acl.ControlledEntity;
+import org.apache.cloudstack.acl.ControlledEntity.ACLType;
+import org.apache.cloudstack.api.ApiConstants.HostDetails;
+import org.apache.cloudstack.api.ApiConstants.VMDetails;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.ResponseGenerator;
+import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
+import org.apache.cloudstack.api.response.AccountResponse;
 import org.apache.cloudstack.api.response.AsyncJobResponse;
 import org.apache.cloudstack.api.response.AutoScalePolicyResponse;
 import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse;
@@ -30,6 +52,7 @@ import org.apache.cloudstack.api.response.ClusterResponse;
 import org.apache.cloudstack.api.response.ConditionResponse;
 import org.apache.cloudstack.api.response.ConfigurationResponse;
 import org.apache.cloudstack.api.response.ControlledEntityResponse;
+import org.apache.cloudstack.api.response.ControlledViewEntityResponse;
 import org.apache.cloudstack.api.response.CounterResponse;
 import org.apache.cloudstack.api.response.CreateCmdResponse;
 import org.apache.cloudstack.api.response.DiskOfferingResponse;
@@ -39,10 +62,10 @@ import org.apache.cloudstack.api.response.EventResponse;
 import org.apache.cloudstack.api.response.ExtractResponse;
 import org.apache.cloudstack.api.response.FirewallResponse;
 import org.apache.cloudstack.api.response.FirewallRuleResponse;
+import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse;
 import org.apache.cloudstack.api.response.GuestOSResponse;
 import org.apache.cloudstack.api.response.HostResponse;
 import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse;
-import org.apache.cloudstack.api.response.ControlledViewEntityResponse;
 import org.apache.cloudstack.api.response.IPAddressResponse;
 import org.apache.cloudstack.api.response.InstanceGroupResponse;
 import org.apache.cloudstack.api.response.IpForwardingRuleResponse;
@@ -56,6 +79,7 @@ import org.apache.cloudstack.api.response.NetworkACLResponse;
 import org.apache.cloudstack.api.response.NetworkOfferingResponse;
 import org.apache.cloudstack.api.response.NetworkResponse;
 import org.apache.cloudstack.api.response.NicResponse;
+import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
 import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
 import org.apache.cloudstack.api.response.PodResponse;
 import org.apache.cloudstack.api.response.PrivateGatewayResponse;
@@ -63,10 +87,12 @@ import org.apache.cloudstack.api.response.ProjectAccountResponse;
 import org.apache.cloudstack.api.response.ProjectInvitationResponse;
 import org.apache.cloudstack.api.response.ProjectResponse;
 import org.apache.cloudstack.api.response.ProviderResponse;
+import org.apache.cloudstack.api.response.RegionResponse;
 import org.apache.cloudstack.api.response.RemoteAccessVpnResponse;
 import org.apache.cloudstack.api.response.ResourceCountResponse;
 import org.apache.cloudstack.api.response.ResourceLimitResponse;
 import org.apache.cloudstack.api.response.ResourceTagResponse;
+import org.apache.cloudstack.api.response.S3Response;
 import org.apache.cloudstack.api.response.SecurityGroupResponse;
 import org.apache.cloudstack.api.response.SecurityGroupRuleResponse;
 import org.apache.cloudstack.api.response.ServiceOfferingResponse;
@@ -90,6 +116,7 @@ import org.apache.cloudstack.api.response.TrafficTypeResponse;
 import org.apache.cloudstack.api.response.UsageRecordResponse;
 import org.apache.cloudstack.api.response.UserResponse;
 import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.cloudstack.api.response.VMSnapshotResponse;
 import org.apache.cloudstack.api.response.VirtualRouterProviderResponse;
 import org.apache.cloudstack.api.response.VlanIpRangeResponse;
 import org.apache.cloudstack.api.response.VolumeResponse;
@@ -97,37 +124,86 @@ import org.apache.cloudstack.api.response.VpcOfferingResponse;
 import org.apache.cloudstack.api.response.VpcResponse;
 import org.apache.cloudstack.api.response.VpnUsersResponse;
 import org.apache.cloudstack.api.response.ZoneResponse;
-import org.apache.cloudstack.api.response.S3Response;
+import org.apache.cloudstack.region.Region;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.cloudstack.usage.Usage;
+import org.apache.cloudstack.usage.UsageService;
+import org.apache.cloudstack.usage.UsageTypes;
+import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
+import com.cloud.api.query.ViewResponseHelper;
+import com.cloud.api.query.vo.AccountJoinVO;
+import com.cloud.api.query.vo.AsyncJobJoinVO;
+import com.cloud.api.query.vo.ControlledViewEntity;
+import com.cloud.api.query.vo.DataCenterJoinVO;
+import com.cloud.api.query.vo.DiskOfferingJoinVO;
+import com.cloud.api.query.vo.DomainRouterJoinVO;
+import com.cloud.api.query.vo.EventJoinVO;
+import com.cloud.api.query.vo.HostJoinVO;
+import com.cloud.api.query.vo.InstanceGroupJoinVO;
+import com.cloud.api.query.vo.ProjectAccountJoinVO;
+import com.cloud.api.query.vo.ProjectInvitationJoinVO;
+import com.cloud.api.query.vo.ProjectJoinVO;
+import com.cloud.api.query.vo.ResourceTagJoinVO;
+import com.cloud.api.query.vo.SecurityGroupJoinVO;
+import com.cloud.api.query.vo.ServiceOfferingJoinVO;
+import com.cloud.api.query.vo.StoragePoolJoinVO;
+import com.cloud.api.query.vo.UserAccountJoinVO;
+import com.cloud.api.query.vo.UserVmJoinVO;
+import com.cloud.api.query.vo.VolumeJoinVO;
+import com.cloud.api.response.ApiResponseSerializer;
 import com.cloud.async.AsyncJob;
 import com.cloud.capacity.Capacity;
 import com.cloud.capacity.CapacityVO;
 import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity;
 import com.cloud.configuration.Configuration;
 import com.cloud.configuration.Resource.ResourceOwnerType;
+import com.cloud.configuration.Resource.ResourceType;
 import com.cloud.configuration.ResourceCount;
 import com.cloud.configuration.ResourceLimit;
 import com.cloud.dao.EntityManager;
-import com.cloud.dc.*;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.HostPodVO;
+import com.cloud.dc.Pod;
+import com.cloud.dc.StorageNetworkIpRange;
+import com.cloud.dc.Vlan;
 import com.cloud.dc.Vlan.VlanType;
+import com.cloud.dc.VlanVO;
 import com.cloud.domain.Domain;
 import com.cloud.event.Event;
 import com.cloud.host.Host;
 import com.cloud.host.HostVO;
 import com.cloud.hypervisor.HypervisorCapabilities;
-import com.cloud.network.*;
+import com.cloud.network.IpAddress;
+import com.cloud.network.Network;
 import com.cloud.network.Network.Capability;
 import com.cloud.network.Network.Provider;
 import com.cloud.network.Network.Service;
+import com.cloud.network.NetworkProfile;
 import com.cloud.network.Networks.TrafficType;
-import com.cloud.network.as.*;
+import com.cloud.network.PhysicalNetwork;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.PhysicalNetworkTrafficType;
+import com.cloud.network.RemoteAccessVpn;
+import com.cloud.network.Site2SiteCustomerGateway;
+import com.cloud.network.Site2SiteVpnConnection;
+import com.cloud.network.Site2SiteVpnGateway;
+import com.cloud.network.VirtualRouterProvider;
+import com.cloud.network.VpnUser;
+import com.cloud.network.as.AutoScalePolicy;
+import com.cloud.network.as.AutoScaleVmGroup;
+import com.cloud.network.as.AutoScaleVmProfile;
+import com.cloud.network.as.AutoScaleVmProfileVO;
+import com.cloud.network.as.Condition;
+import com.cloud.network.as.ConditionVO;
+import com.cloud.network.as.Counter;
 import com.cloud.network.dao.IPAddressVO;
 import com.cloud.network.dao.NetworkVO;
 import com.cloud.network.dao.PhysicalNetworkVO;
 import com.cloud.network.router.VirtualRouter;
-import com.cloud.network.rules.*;
 import com.cloud.network.rules.FirewallRule;
 import com.cloud.network.rules.FirewallRuleVO;
 import com.cloud.network.rules.HealthCheckPolicy;
@@ -156,12 +232,25 @@ import com.cloud.server.Criteria;
 import com.cloud.server.ResourceTag;
 import com.cloud.server.ResourceTag.TaggedResourceType;
 import com.cloud.service.ServiceOfferingVO;
-import com.cloud.storage.*;
+import com.cloud.storage.DiskOfferingVO;
+import com.cloud.storage.GuestOS;
+import com.cloud.storage.GuestOSCategoryVO;
+import com.cloud.storage.S3;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.SnapshotVO;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.Storage.StoragePoolType;
 import com.cloud.storage.Storage.TemplateType;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.Swift;
+import com.cloud.storage.UploadVO;
+import com.cloud.storage.VMTemplateHostVO;
+import com.cloud.storage.VMTemplateS3VO;
 import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
-
+import com.cloud.storage.VMTemplateSwiftVO;
+import com.cloud.storage.VMTemplateVO;
+import com.cloud.storage.Volume;
+import com.cloud.storage.VolumeVO;
 import com.cloud.storage.snapshot.SnapshotPolicy;
 import com.cloud.storage.snapshot.SnapshotSchedule;
 import com.cloud.template.VirtualMachineTemplate;
@@ -179,40 +268,10 @@ import com.cloud.vm.Nic;
 import com.cloud.vm.NicProfile;
 import com.cloud.vm.NicVO;
 import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.NicSecondaryIp;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachine.Type;
 import com.cloud.vm.dao.NicSecondaryIpVO;
-
-import org.apache.cloudstack.acl.ControlledEntity;
-import org.apache.cloudstack.acl.ControlledEntity.ACLType;
-import org.apache.cloudstack.api.ApiConstants.HostDetails;
-import org.apache.cloudstack.api.ApiConstants.VMDetails;
-import org.apache.cloudstack.api.BaseCmd;
-import org.apache.cloudstack.api.ResponseGenerator;
-import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
-import org.apache.cloudstack.api.response.*;
-import org.apache.cloudstack.region.Region;
-import org.apache.cloudstack.usage.Usage;
-import org.apache.cloudstack.usage.UsageService;
-import org.apache.cloudstack.usage.UsageTypes;
-import com.cloud.vm.VmStats;                                                                                                        
-import com.cloud.vm.dao.UserVmData;                                                                                                 
-import com.cloud.vm.dao.UserVmData.NicData;                                                                                         
-import com.cloud.vm.dao.UserVmData.SecurityGroupData;                                                                               
-import com.cloud.vm.snapshot.VMSnapshot;                                                                                            
-import org.apache.cloudstack.api.ResponseGenerator;                                                                                 
-import org.apache.cloudstack.api.response.VMSnapshotResponse;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import java.text.DecimalFormat;
-import java.util.*;
-
-import javax.inject.Inject;
-
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
+import com.cloud.vm.snapshot.VMSnapshot;
 
 @Component
 public class ApiResponseHelper implements ResponseGenerator {
@@ -290,7 +349,11 @@ public class ApiResponseHelper implements ResponseGenerator {
             populateDomain(resourceLimitResponse, accountTemp.getDomainId());
         }
         resourceLimitResponse.setResourceType(Integer.valueOf(limit.getType().getOrdinal()).toString());
-        resourceLimitResponse.setMax(limit.getMax());
+        if(limit.getType() == ResourceType.primary_storage || limit.getType() == ResourceType.secondary_storage) {
+            resourceLimitResponse.setMax((long) Math.ceil(limit.getMax()/ResourceType.bytesToGiB));
+        } else {
+            resourceLimitResponse.setMax(limit.getMax());
+        }
         resourceLimitResponse.setObjectName("resourcelimit");
 
         return resourceLimitResponse;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java
index 898bafc..51ac5e6 100644
--- a/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java
@@ -175,6 +175,24 @@ public class AccountJoinDaoImpl extends GenericDaoBase<AccountJoinVO, Long> impl
         accountResponse.setMemoryTotal(memoryTotal);
         accountResponse.setMemoryAvailable(memoryAvail);
 
+      //get resource limits for primary storage space and convert it from Bytes to GiB
+        long primaryStorageLimit = ApiDBUtils.findCorrectResourceLimit(account.getPrimaryStorageLimit(), account.getType(), ResourceType.primary_storage);
+        String primaryStorageLimitDisplay = (accountIsAdmin || primaryStorageLimit == -1) ? "Unlimited" : String.valueOf(primaryStorageLimit / ResourceType.bytesToGiB);
+        long primaryStorageTotal = (account.getPrimaryStorageTotal() == null) ? 0 : (account.getPrimaryStorageTotal() / ResourceType.bytesToGiB);
+        String primaryStorageAvail = (accountIsAdmin || primaryStorageLimit == -1) ? "Unlimited" : String.valueOf((primaryStorageLimit / ResourceType.bytesToGiB) - primaryStorageTotal);
+        accountResponse.setPrimaryStorageLimit(primaryStorageLimitDisplay);
+        accountResponse.setPrimaryStorageTotal(primaryStorageTotal);
+        accountResponse.setPrimaryStorageAvailable(primaryStorageAvail);
+
+        //get resource limits for secondary storage space and convert it from Bytes to GiB
+        long secondaryStorageLimit = ApiDBUtils.findCorrectResourceLimit(account.getSecondaryStorageLimit(), account.getType(), ResourceType.secondary_storage);
+        String secondaryStorageLimitDisplay = (accountIsAdmin || secondaryStorageLimit == -1) ? "Unlimited" : String.valueOf(secondaryStorageLimit / ResourceType.bytesToGiB);
+        long secondaryStorageTotal = (account.getSecondaryStorageTotal() == null) ? 0 : (account.getSecondaryStorageTotal() / ResourceType.bytesToGiB);
+        String secondaryStorageAvail = (accountIsAdmin || secondaryStorageLimit == -1) ? "Unlimited" : String.valueOf((secondaryStorageLimit / ResourceType.bytesToGiB) - secondaryStorageTotal);
+        accountResponse.setSecondaryStorageLimit(secondaryStorageLimitDisplay);
+        accountResponse.setSecondaryStorageTotal(secondaryStorageTotal);
+        accountResponse.setSecondaryStorageAvailable(secondaryStorageAvail);
+
         // adding all the users for an account as part of the response obj
         List<UserAccountJoinVO> usersForAccount = ApiDBUtils.findUserViewByAccountId(account.getId());
         List<UserResponse> userResponses = ViewResponseHelper.createUserResponse(usersForAccount.toArray(new UserAccountJoinVO[usersForAccount.size()]));

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/api/query/vo/AccountJoinVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/AccountJoinVO.java b/server/src/com/cloud/api/query/vo/AccountJoinVO.java
index cd7231c..1cb17ef 100644
--- a/server/src/com/cloud/api/query/vo/AccountJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/AccountJoinVO.java
@@ -162,6 +162,20 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident
     @Column(name="memoryTotal")
     private Long memoryTotal;
 
+
+    @Column(name="primaryStorageLimit")
+    private Long primaryStorageLimit;
+
+    @Column(name="primaryStorageTotal")
+    private Long primaryStorageTotal;
+
+
+    @Column(name="secondaryStorageLimit")
+    private Long secondaryStorageLimit;
+
+    @Column(name="secondaryStorageTotal")
+    private Long secondaryStorageTotal;
+
     @Column(name="job_id")
     private long jobId;
 
@@ -478,6 +492,7 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident
         this.cpuTotal = cpuTotal;
     }
 
+
     public Long getMemoryTotal() {
         return memoryTotal;
     }
@@ -488,6 +503,25 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident
     }
 
 
+    public Long getPrimaryStorageTotal() {
+        return primaryStorageTotal;
+    }
+
+
+    public void setPrimaryStorageTotal(Long primaryStorageTotal) {
+        this.primaryStorageTotal = primaryStorageTotal;
+    }
+
+    public Long getSecondaryStorageTotal() {
+        return secondaryStorageTotal;
+    }
+
+
+    public void setSecondaryStorageTotal(Long secondaryStorageTotal) {
+        this.secondaryStorageTotal = secondaryStorageTotal;
+    }
+
+
     public Long getVmLimit() {
         return vmLimit;
     }
@@ -588,6 +622,26 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident
     }
 
 
+    public Long getPrimaryStorageLimit() {
+        return primaryStorageLimit;
+    }
+
+
+    public void setPrimaryStorageLimit(Long primaryStorageLimit) {
+        this.primaryStorageLimit = primaryStorageLimit;
+    }
+
+
+    public Long getSecondaryStorageLimit() {
+        return secondaryStorageLimit;
+    }
+
+
+    public void setSecondaryStorageLimit(Long secondaryStorageLimit) {
+        this.secondaryStorageLimit = secondaryStorageLimit;
+    }
+
+
     public long getJobId() {
         return jobId;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index ba4ae62..5b2616f 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -323,7 +323,8 @@ public enum Config {
 	DefaultMaxAccountVpcs("Account Defaults", ManagementServer.class, Long.class, "max.account.vpcs", "20", "The default maximum number of vpcs that can be created for an account", null),
 	DefaultMaxAccountCpus("Account Defaults", ManagementServer.class, Long.class, "max.account.cpus", "40", "The default maximum number of cpu cores that can be used for an account", null),
 	DefaultMaxAccountMemory("Account Defaults", ManagementServer.class, Long.class, "max.account.memory", "40960", "The default maximum memory (in MB) that can be used for an account", null),
-
+	DefaultMaxAccountPrimayStorage("Account Defaults", ManagementServer.class, Long.class, "max.account.primary.storage", "200", "The default maximum primary storage space (in GiB) that can be used for an account", null),
+	DefaultMaxAccountSecondaryStorage("Account Defaults", ManagementServer.class, Long.class, "max.account.secondary.storage", "400", "The default maximum secondary storage space (in GiB) that can be used for an account", null),
 
 	ResourceCountCheckInterval("Advanced", ManagementServer.class, Long.class, "resourcecount.check.interval", "0", "Time (in seconds) to wait before retrying resource count check task. Default is 0 which is to never run the task", "Seconds"),
 	DirectAgentLoadSize("Advanced", ManagementServer.class, Integer.class, "direct.agent.load.size", "16", "The number of direct agents to load each time", null),
@@ -349,6 +350,8 @@ public enum Config {
     DefaultMaxProjectVpcs("Project Defaults", ManagementServer.class, Long.class, "max.project.vpcs", "20", "The default maximum number of vpcs that can be created for a project", null),
     DefaultMaxProjectCpus("Project Defaults", ManagementServer.class, Long.class, "max.project.cpus", "40", "The default maximum number of cpu cores that can be used for a project", null),
     DefaultMaxProjectMemory("Project Defaults", ManagementServer.class, Long.class, "max.project.memory", "40960", "The default maximum memory (in MB) that can be used for a project", null),
+    DefaultMaxProjectPrimayStorage("Project Defaults", ManagementServer.class, Long.class, "max.project.primary.storage", "200", "The default maximum primary storage space (in GiB) that can be used for an project", null),
+    DefaultMaxProjectSecondaryStorage("Project Defaults", ManagementServer.class, Long.class, "max.project.secondary.storage", "400", "The default maximum secondary storage space (in GiB) that can be used for an project", null),
 
     ProjectInviteRequired("Project Defaults", ManagementServer.class, Boolean.class, "project.invite.required", "false", "If invitation confirmation is required when add account to project. Default value is false", null),
     ProjectInvitationExpirationTime("Project Defaults", ManagementServer.class, Long.class, "project.invite.timeout", "86400", "Invitation expiration time (in seconds). Default is 1 day - 86400 seconds", null),

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java
index 23c0796..bbe0190 100755
--- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java
+++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java
@@ -61,8 +61,12 @@ import com.cloud.projects.dao.ProjectAccountDao;
 import com.cloud.projects.dao.ProjectDao;
 import com.cloud.service.ServiceOfferingVO;
 import com.cloud.service.dao.ServiceOfferingDao;
+import com.cloud.storage.VMTemplateHostVO;
+import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
+import com.cloud.storage.VMTemplateVO;
 import com.cloud.storage.dao.SnapshotDao;
 import com.cloud.storage.dao.VMTemplateDao;
+import com.cloud.storage.dao.VMTemplateHostDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.storage.dao.VolumeDaoImpl.SumCount;
 import com.cloud.user.Account;
@@ -135,6 +139,10 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
     private VpcDao _vpcDao;
     @Inject
     private ServiceOfferingDao _serviceOfferingDao;
+    @Inject
+    private VMTemplateHostDao _vmTemplateHostDao;
+
+    protected GenericSearchBuilder<VMTemplateHostVO, SumCount> templateSizeSearch;
 
     protected SearchBuilder<ResourceCountVO> ResourceCountSearch;
     ScheduledExecutorService _rcExecutor;
@@ -164,6 +172,15 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
         ResourceCountSearch.and("domainId", ResourceCountSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
         ResourceCountSearch.done();
 
+        templateSizeSearch = _vmTemplateHostDao.createSearchBuilder(SumCount.class);
+        templateSizeSearch.select("sum", Func.SUM, templateSizeSearch.entity().getSize());
+        templateSizeSearch.and("downloadState", templateSizeSearch.entity().getDownloadState(), Op.EQ);
+        templateSizeSearch.and("destroyed", templateSizeSearch.entity().getDestroyed(), Op.EQ);
+        SearchBuilder<VMTemplateVO> join1 = _vmTemplateDao.createSearchBuilder();
+        join1.and("accountId", join1.entity().getAccountId(), Op.EQ);
+        templateSizeSearch.join("templates", join1, templateSizeSearch.entity().getTemplateId(), join1.entity().getId(), JoinBuilder.JoinType.INNER);
+        templateSizeSearch.done();
+
         _resourceCountCheckInterval = NumbersUtil.parseInt(_configDao.getValue(Config.ResourceCountCheckInterval.key()), 0);
         if (_resourceCountCheckInterval > 0) {
             _rcExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("ResourceCountChecker"));
@@ -178,6 +195,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
         projectResourceLimitMap.put(Resource.ResourceType.vpc, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectVpcs.key())));
         projectResourceLimitMap.put(Resource.ResourceType.cpu, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectCpus.key())));
         projectResourceLimitMap.put(Resource.ResourceType.memory, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectMemory.key())));
+        projectResourceLimitMap.put(Resource.ResourceType.primary_storage, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectPrimayStorage.key())));
+        projectResourceLimitMap.put(Resource.ResourceType.secondary_storage, Long.parseLong(_configDao.getValue(Config.DefaultMaxProjectSecondaryStorage.key())));
 
         accountResourceLimitMap.put(Resource.ResourceType.public_ip, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountPublicIPs.key())));
         accountResourceLimitMap.put(Resource.ResourceType.snapshot, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountSnapshots.key())));
@@ -188,6 +207,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
         accountResourceLimitMap.put(Resource.ResourceType.vpc, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountVpcs.key())));
         accountResourceLimitMap.put(Resource.ResourceType.cpu, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountCpus.key())));
         accountResourceLimitMap.put(Resource.ResourceType.memory, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountMemory.key())));
+        accountResourceLimitMap.put(Resource.ResourceType.primary_storage, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountPrimayStorage.key())));
+        accountResourceLimitMap.put(Resource.ResourceType.secondary_storage, Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountSecondaryStorage.key())));
 
         return true;
     }
@@ -246,6 +267,10 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
                 value = accountResourceLimitMap.get(type);
             }
             if (value != null) {
+                // convert the value from GiB to bytes in case of primary or secondary storage.
+                if (type == ResourceType.primary_storage || type == ResourceType.secondary_storage) {
+                    value = value * ResourceType.bytesToGiB;
+                }
                 return value;
             }
         }
@@ -276,6 +301,9 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
                 value = accountResourceLimitMap.get(type);
             }
             if (value != null) {
+                if (type == ResourceType.primary_storage || type == ResourceType.secondary_storage) {
+                    value = value * ResourceType.bytesToGiB;
+                }
                 return value;
             }
         }
@@ -548,6 +576,11 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
             }
         }
 
+        //Convert max storage size from GiB to bytes
+        if (resourceType == ResourceType.primary_storage || resourceType == ResourceType.secondary_storage) {
+            max = max * ResourceType.bytesToGiB;
+        }
+
         ResourceOwnerType ownerType = null;
         Long ownerId = null;
 
@@ -789,6 +822,10 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
             newCount = countCpusForAccount(accountId);
         } else if (type == Resource.ResourceType.memory) {
             newCount = calculateMemoryForAccount(accountId);
+        } else if (type == Resource.ResourceType.primary_storage) {
+            newCount = _volumeDao.primaryStorageUsedForAccount(accountId);
+        } else if (type == Resource.ResourceType.secondary_storage) {
+            newCount = calculateSecondaryStorageForAccount(accountId);
         } else {
             throw new InvalidParameterValueException("Unsupported resource type " + type);
         }
@@ -847,6 +884,23 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
         }
     }
 
+    public long calculateSecondaryStorageForAccount(long accountId) {
+        long totalVolumesSize = _volumeDao.secondaryStorageUsedForAccount(accountId);
+        long totalSnapshotsSize = _snapshotDao.secondaryStorageUsedForAccount(accountId);
+        long totalTemplatesSize = 0;
+
+        SearchCriteria<SumCount> sc = templateSizeSearch.create();
+        sc.setParameters("downloadState", Status.DOWNLOADED);
+        sc.setParameters("destroyed", false);
+        sc.setJoinParameters("templates", "accountId", accountId);
+        List<SumCount> templates = _vmTemplateHostDao.customSearch(sc, null);
+        if (templates != null) {
+            totalTemplatesSize = templates.get(0).sum;
+        }
+
+        return totalVolumesSize + totalSnapshotsSize + totalTemplatesSize;
+    }
+
     @Override
     public long getResourceCount(Account account, ResourceType type) {
         return _resourceCountDao.getResourceCount(account.getId(), ResourceOwnerType.Account, type);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/storage/VolumeManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeManager.java b/server/src/com/cloud/storage/VolumeManager.java
index af3cbbf..2101038 100644
--- a/server/src/com/cloud/storage/VolumeManager.java
+++ b/server/src/com/cloud/storage/VolumeManager.java
@@ -61,7 +61,8 @@ public interface VolumeManager extends VolumeApiService {
 
     VolumeVO createVolume(CreateVolumeCmd cmd);
 
-    VolumeVO resizeVolume(ResizeVolumeCmd cmd);
+    VolumeVO resizeVolume(ResizeVolumeCmd cmd)
+            throws ResourceAllocationException;
 
     boolean deleteVolume(long volumeId, Account caller)
             throws ConcurrentOperationException;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/storage/VolumeManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java
index 737ed0a..ff0235f 100644
--- a/server/src/com/cloud/storage/VolumeManagerImpl.java
+++ b/server/src/com/cloud/storage/VolumeManagerImpl.java
@@ -146,6 +146,7 @@ import com.cloud.uservm.UserVm;
 import com.cloud.utils.EnumUtils;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.Pair;
+import com.cloud.utils.UriUtils;
 import com.cloud.utils.component.ManagerBase;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.JoinBuilder;
@@ -469,6 +470,10 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
         }
         validateUrl(url);
 
+        // Check that the resource limit for secondary storage won't be exceeded
+        _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.secondary_storage,
+                UriUtils.getRemoteSize(url));
+
         return false;
     }
     
@@ -736,6 +741,8 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
         // decrement it
         _resourceLimitMgr.incrementResourceCount(volume.getAccountId(),
                 ResourceType.volume);
+        _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.secondary_storage,
+                UriUtils.getRemoteSize(url));
 
         txn.commit();
         return volume;
@@ -906,6 +913,10 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
             _accountMgr.checkAccess(caller, null, true, snapshotCheck);
         }
 
+        // Check that the resource limit for primary storage won't be exceeded
+        _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.primary_storage,
+                new Long(size));
+
         // Verify that zone exists
         DataCenterVO zone = _dcDao.findById(zoneId);
         if (zone == null) {
@@ -974,6 +985,8 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
         // decrement it
         _resourceLimitMgr.incrementResourceCount(volume.getAccountId(),
                 ResourceType.volume);
+        _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.primary_storage,
+                new Long(volume.getSize()));
 
         txn.commit();
 
@@ -1006,6 +1019,8 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
                         + " as volume failed to create on the backend");
                 _resourceLimitMgr.decrementResourceCount(volume.getAccountId(),
                         ResourceType.volume);
+                _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage,
+                        new Long(volume.getSize()));
             }
         }
     }
@@ -1013,7 +1028,8 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
     @Override
     @DB
     @ActionEvent(eventType = EventTypes.EVENT_VOLUME_RESIZE, eventDescription = "resizing volume", async = true)
-    public VolumeVO resizeVolume(ResizeVolumeCmd cmd) {
+    public VolumeVO resizeVolume(ResizeVolumeCmd cmd)
+            throws ResourceAllocationException {
         Long newSize = null;
         boolean shrinkOk = cmd.getShrinkOk();
         
@@ -1149,6 +1165,12 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
                             + " would shrink the volume, need to sign off by supplying the shrinkok parameter with value of true");
         }
 
+        if (!shrinkOk) {
+            /* Check resource limit for this account on primary storage resource */
+            _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()),
+                    ResourceType.primary_storage, new Long(newSize - currentSize));
+        }
+
         /*
          * get a list of hosts to send the commands to, try the system the
          * associated vm is running on first, then the last known place it ran.
@@ -1176,27 +1198,35 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
         ResizeVolumePayload payload = new ResizeVolumePayload(newSize, shrinkOk, instanceName, hosts);
         
         try {
-        	VolumeInfo vol = this.volFactory.getVolume(volume.getId());
+            VolumeInfo vol = this.volFactory.getVolume(volume.getId());
             vol.addPayload(payload);
-            
-        	AsyncCallFuture<VolumeApiResult> future = this.volService.resize(vol);
-        	future.get();
-        	volume = _volsDao.findById(volume.getId());
-
-        	if (newDiskOffering != null) {
-        		volume.setDiskOfferingId(cmd.getNewDiskOfferingId());
-        	}
-        	_volsDao.update(volume.getId(), volume);
-
-        	return volume;
-		} catch (InterruptedException e) {
-			s_logger.debug("failed get resize volume result", e);
-		} catch (ExecutionException e) {
-			s_logger.debug("failed get resize volume result", e);
-		} catch (Exception e) {
-			s_logger.debug("failed get resize volume result", e);
-		}
-       
+
+            AsyncCallFuture<VolumeApiResult> future = this.volService.resize(vol);
+            future.get();
+            volume = _volsDao.findById(volume.getId());
+
+            if (newDiskOffering != null) {
+                volume.setDiskOfferingId(cmd.getNewDiskOfferingId());
+            }
+            _volsDao.update(volume.getId(), volume);
+
+            /* Update resource count for the account on primary storage resource */
+            if (!shrinkOk) {
+                _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.primary_storage,
+                        new Long(newSize - currentSize));
+            } else {
+                _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage,
+                        new Long(currentSize - newSize));
+            }
+            return volume;
+        } catch (InterruptedException e) {
+            s_logger.debug("failed get resize volume result", e);
+        } catch (ExecutionException e) {
+            s_logger.debug("failed get resize volume result", e);
+        } catch (Exception e) {
+            s_logger.debug("failed get resize volume result", e);
+        }
+
         return null;
     }
     
@@ -1243,9 +1273,19 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
                 VMInstanceVO vmInstance = this._vmInstanceDao.findById(instanceId);
                 if (instanceId == null
                         || (vmInstance.getType().equals(VirtualMachine.Type.User))) {
-                    // Decrement the resource count for volumes belonging user VM's only
+                    // Decrement the resource count for volumes and primary storage belonging user VM's only
                     _resourceLimitMgr.decrementResourceCount(volume.getAccountId(),
                             ResourceType.volume);
+                    /* If volume is in primary storage, decrement primary storage count else decrement secondary
+                     storage count (in case of upload volume). */
+                    if (volume.getFolder() != null) {
+                        _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage,
+                                new Long(volume.getSize()));
+                    } else {
+                        _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(),
+                                ResourceType.secondary_storage.getOrdinal());
+                    }
+
                     // Log usage event for volumes belonging user VM's only
                     UsageEventVO usageEvent = new UsageEventVO(
                             EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(),
@@ -1317,6 +1357,8 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
 
             _resourceLimitMgr.incrementResourceCount(vm.getAccountId(),
                     ResourceType.volume);
+            _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage,
+                    new Long(vol.getSize()));
         }
         return toDiskProfile(vol, offering);
     }
@@ -1364,6 +1406,8 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
 
             _resourceLimitMgr.incrementResourceCount(vm.getAccountId(),
                     ResourceType.volume);
+            _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage,
+                    new Long(vol.getSize()));
         }
         return toDiskProfile(vol, offering);
     }
@@ -1435,6 +1479,13 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
             vol = copyVolume(rootDiskPool
                     , volume, vm, rootDiskTmplt,  dcVO,
                     pod,  diskVO,  svo,  rootDiskHyperType);
+            if (vol != null) {
+                // Moving of Volume is successful, decrement the volume resource count from secondary for an account and increment it into primary storage under same account.
+                _resourceLimitMgr.decrementResourceCount(volume.getAccountId(),
+                        ResourceType.secondary_storage, new Long(volume.getSize()));
+                _resourceLimitMgr.incrementResourceCount(volume.getAccountId(),
+                        ResourceType.primary_storage, new Long(volume.getSize()));
+            }
         }
         return vol;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/storage/dao/SnapshotDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/SnapshotDao.java b/server/src/com/cloud/storage/dao/SnapshotDao.java
index 0e378a7..3ac9e77 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDao.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDao.java
@@ -40,7 +40,15 @@ public interface SnapshotDao extends GenericDao<SnapshotVO, Long>, StateDao<Snap
     List<SnapshotVO> listByHostId(Filter filter, long hostId);
     List<SnapshotVO> listByHostId(long hostId);
     public Long countSnapshotsForAccount(long accountId);
-	List<SnapshotVO> listByInstanceId(long instanceId, Snapshot.State... status);
-	List<SnapshotVO> listByStatus(long volumeId, Snapshot.State... status);
+    List<SnapshotVO> listByInstanceId(long instanceId, Snapshot.State... status);
+    List<SnapshotVO> listByStatus(long volumeId, Snapshot.State... status);
     List<SnapshotVO> listAllByStatus(Snapshot.State... status);
+    /**
+     * Gets the Total Secondary Storage space (in bytes) used by snapshots allocated for an account
+     *
+     * @param account
+     * @return total Secondary Storage space allocated
+     */
+    long secondaryStorageUsedForAccount(long accountId);
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
index 825b6d5..f55663f 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
@@ -35,15 +35,20 @@ import com.cloud.storage.Snapshot.Type;
 import com.cloud.storage.SnapshotVO;
 import com.cloud.storage.Volume;
 import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.VolumeDaoImpl.SumCount;
 import com.cloud.tags.dao.ResourceTagDao;
-import com.cloud.tags.dao.ResourceTagsDaoImpl;
-
-import com.cloud.utils.db.*;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.Filter;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.GenericSearchBuilder;
 import com.cloud.utils.db.JoinBuilder.JoinType;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.SearchCriteria.Func;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.Transaction;
 import com.cloud.vm.VMInstanceVO;
 import com.cloud.vm.dao.VMInstanceDao;
-import com.cloud.vm.dao.VMInstanceDaoImpl;
 
 @Component
 @Local (value={SnapshotDao.class})
@@ -53,19 +58,19 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
     private static final String UPDATE_SNAPSHOT_VERSION = "UPDATE snapshots SET version = ? WHERE volume_id = ? AND version = ?";
     private static final String GET_SECHOST_ID = "SELECT sechost_id FROM snapshots where volume_id = ? AND backup_snap_id IS NOT NULL AND sechost_id IS NOT NULL LIMIT 1";
     private static final String UPDATE_SECHOST_ID = "UPDATE snapshots SET sechost_id = ? WHERE data_center_id = ?";
-    
+
     private SearchBuilder<SnapshotVO> VolumeIdSearch;
     private SearchBuilder<SnapshotVO> VolumeIdTypeSearch;
     private SearchBuilder<SnapshotVO> ParentIdSearch;
-    private SearchBuilder<SnapshotVO> backupUuidSearch;   
+    private SearchBuilder<SnapshotVO> backupUuidSearch;
     private SearchBuilder<SnapshotVO> VolumeIdVersionSearch;
     private SearchBuilder<SnapshotVO> HostIdSearch;
     private SearchBuilder<SnapshotVO> AccountIdSearch;
     private SearchBuilder<SnapshotVO> InstanceIdSearch;
     private SearchBuilder<SnapshotVO> StatusSearch;
     private GenericSearchBuilder<SnapshotVO, Long> CountSnapshotsByAccount;
+    private GenericSearchBuilder<SnapshotVO, SumCount> secondaryStorageSearch;
     @Inject ResourceTagDao _tagsDao;
-    
     @Inject protected VMInstanceDao _instanceDao;
     @Inject protected VolumeDao _volumeDao;
 
@@ -187,23 +192,29 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
         CountSnapshotsByAccount.and("removed", CountSnapshotsByAccount.entity().getRemoved(), SearchCriteria.Op.NULL);
         CountSnapshotsByAccount.done();
         
-    	InstanceIdSearch = createSearchBuilder();
+        InstanceIdSearch = createSearchBuilder();
         InstanceIdSearch.and("status", InstanceIdSearch.entity().getState(), SearchCriteria.Op.IN);
-    	
-    	SearchBuilder<VMInstanceVO> instanceSearch = _instanceDao.createSearchBuilder();
-    	instanceSearch.and("instanceId", instanceSearch.entity().getId(), SearchCriteria.Op.EQ);
-    	
-    	SearchBuilder<VolumeVO> volumeSearch = _volumeDao.createSearchBuilder();
-    	volumeSearch.and("state", volumeSearch.entity().getState(), SearchCriteria.Op.EQ);
-    	volumeSearch.join("instanceVolumes", instanceSearch, instanceSearch.entity().getId(), volumeSearch.entity().getInstanceId(), JoinType.INNER);
-    	
-    	InstanceIdSearch.join("instanceSnapshots", volumeSearch, volumeSearch.entity().getId(), InstanceIdSearch.entity().getVolumeId(), JoinType.INNER);
-    	InstanceIdSearch.done();
+
+        SearchBuilder<VMInstanceVO> instanceSearch = _instanceDao.createSearchBuilder();
+        instanceSearch.and("instanceId", instanceSearch.entity().getId(), SearchCriteria.Op.EQ);
+
+        SearchBuilder<VolumeVO> volumeSearch = _volumeDao.createSearchBuilder();
+        volumeSearch.and("state", volumeSearch.entity().getState(), SearchCriteria.Op.EQ);
+        volumeSearch.join("instanceVolumes", instanceSearch, instanceSearch.entity().getId(), volumeSearch.entity().getInstanceId(), JoinType.INNER);
+
+        InstanceIdSearch.join("instanceSnapshots", volumeSearch, volumeSearch.entity().getId(), InstanceIdSearch.entity().getVolumeId(), JoinType.INNER);
+        InstanceIdSearch.done();
+
+        secondaryStorageSearch = createSearchBuilder(SumCount.class);
+        secondaryStorageSearch.select("sum", Func.SUM, secondaryStorageSearch.entity().getSize());
+        secondaryStorageSearch.and("accountId", secondaryStorageSearch.entity().getAccountId(), Op.EQ);
+        secondaryStorageSearch.and("isRemoved", secondaryStorageSearch.entity().getRemoved(), Op.NULL);
+        secondaryStorageSearch.done();
     }
-    
-    @Override 
+
+    @Override
     public Long getSecHostId(long volumeId) {
-        
+
         Transaction txn = Transaction.currentTxn();
         PreparedStatement pstmt = null;
         String sql = GET_SECHOST_ID;
@@ -331,4 +342,16 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
         txn.commit();
         return true;
     }
+
+    @Override
+    public long secondaryStorageUsedForAccount(long accountId) {
+        SearchCriteria<SumCount> sc = secondaryStorageSearch.create();
+        sc.setParameters("accountId", accountId);
+        List<SumCount> storageSpace = customSearch(sc, null);
+        if (storageSpace != null) {
+            return storageSpace.get(0).sum;
+        } else {
+            return 0;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/storage/dao/VolumeDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/VolumeDao.java b/server/src/com/cloud/storage/dao/VolumeDao.java
index d7a2667..2513181 100755
--- a/server/src/com/cloud/storage/dao/VolumeDao.java
+++ b/server/src/com/cloud/storage/dao/VolumeDao.java
@@ -27,50 +27,66 @@ import com.cloud.utils.db.GenericDao;
 import com.cloud.utils.fsm.StateDao;
 
 public interface VolumeDao extends GenericDao<VolumeVO, Long>, StateDao<Volume.State, Volume.Event, Volume> {
-    
-	List<VolumeVO> findDetachedByAccount(long accountId);
-	
+
+    List<VolumeVO> findDetachedByAccount(long accountId);
+
     List<VolumeVO> findByAccount(long accountId);
-    
+
     Pair<Long, Long> getCountAndTotalByPool(long poolId);
-    
+
     Pair<Long, Long> getNonDestroyedCountAndTotalByPool(long poolId);
-    
+
     List<VolumeVO> findByInstance(long id);
-    
+
     List<VolumeVO> findByInstanceAndType(long id, Volume.Type vType);
-    
+
     List<VolumeVO> findByInstanceIdDestroyed(long vmId);
-    
+
     List<VolumeVO> findByAccountAndPod(long accountId, long podId);
-    
+
     List<VolumeVO> findByTemplateAndZone(long templateId, long zoneId);
-    
+
     void deleteVolumesByInstance(long instanceId);
-    
+
     void attachVolume(long volumeId, long vmId, long deviceId);
-    
+
     void detachVolume(long volumeId);
-    
+
     boolean isAnyVolumeActivelyUsingTemplateOnPool(long templateId, long poolId);
-    
+
     List<VolumeVO> findCreatedByInstance(long id);
-    
+
     List<VolumeVO> findByPoolId(long poolId);
-    
-	List<VolumeVO> findByInstanceAndDeviceId(long instanceId, long deviceId);
-	
+
+    List<VolumeVO> findByInstanceAndDeviceId(long instanceId, long deviceId);
+
     List<VolumeVO> findUsableVolumesForInstance(long instanceId);
-    
+
     Long countAllocatedVolumesForAccount(long accountId); 
-   
+
     HypervisorType getHypervisorType(long volumeId);
-    
+
     List<VolumeVO> listVolumesToBeDestroyed();
-    
+
     ImageFormat getImageFormat(Long volumeId);
-    
+
     List<VolumeVO> findReadyRootVolumesByInstance(long instanceId);
-    
+
     List<Long> listPoolIdsByVolumeCount(long dcId, Long podId, Long clusterId, long accountId);
+
+    /**
+     * Gets the Total Primary Storage space allocated for an account
+     *
+     * @param account
+     * @return total Primary Storage space (in bytes) used
+     */
+    long primaryStorageUsedForAccount(long accountId);
+
+    /**
+     * Gets the Total Secondary Storage space used by volumes allocated for an account
+     *
+     * @param account
+     * @return total Secondary Storage space (in bytes) used
+     */
+    long secondaryStorageUsedForAccount(long accountId);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/VolumeDaoImpl.java b/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
index 40ed875..12ca3c7 100755
--- a/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
@@ -38,7 +38,6 @@ import com.cloud.storage.Volume.State;
 import com.cloud.storage.Volume.Type;
 import com.cloud.storage.VolumeVO;
 import com.cloud.tags.dao.ResourceTagDao;
-import com.cloud.tags.dao.ResourceTagsDaoImpl;
 import com.cloud.utils.Pair;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.GenericDaoBase;
@@ -62,8 +61,10 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
     protected final SearchBuilder<VolumeVO> InstanceStatesSearch;
     protected final SearchBuilder<VolumeVO> AllFieldsSearch;
     protected GenericSearchBuilder<VolumeVO, Long> CountByAccount;
+    protected GenericSearchBuilder<VolumeVO, SumCount> primaryStorageSearch;
+    protected GenericSearchBuilder<VolumeVO, SumCount> secondaryStorageSearch;
     @Inject ResourceTagDao _tagsDao;
-    
+
     protected static final String SELECT_VM_SQL = "SELECT DISTINCT instance_id from volumes v where v.host_id = ? and v.mirror_state = ?";
     protected static final String SELECT_HYPERTYPE_FROM_VOLUME = "SELECT c.hypervisor_type from volumes v, storage_pool s, cluster c where v.pool_id = s.id and s.cluster_id = c.id and v.id = ?";
 
@@ -298,8 +299,22 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
         CountByAccount = createSearchBuilder(Long.class);
         CountByAccount.select(null, Func.COUNT, null);
         CountByAccount.and("account", CountByAccount.entity().getAccountId(), SearchCriteria.Op.EQ);
-        CountByAccount.and("state", CountByAccount.entity().getState(), SearchCriteria.Op.NIN);        
+        CountByAccount.and("state", CountByAccount.entity().getState(), SearchCriteria.Op.NIN);
         CountByAccount.done();
+
+        primaryStorageSearch = createSearchBuilder(SumCount.class);
+        primaryStorageSearch.select("sum", Func.SUM, primaryStorageSearch.entity().getSize());
+        primaryStorageSearch.and("accountId", primaryStorageSearch.entity().getAccountId(), Op.EQ);
+        primaryStorageSearch.and("path", primaryStorageSearch.entity().getPath(), Op.NNULL);
+        primaryStorageSearch.and("isRemoved", primaryStorageSearch.entity().getRemoved(), Op.NULL);
+        primaryStorageSearch.done();
+
+        secondaryStorageSearch = createSearchBuilder(SumCount.class);
+        secondaryStorageSearch.select("sum", Func.SUM, secondaryStorageSearch.entity().getSize());
+        secondaryStorageSearch.and("accountId", secondaryStorageSearch.entity().getAccountId(), Op.EQ);
+        secondaryStorageSearch.and("path", secondaryStorageSearch.entity().getPath(), Op.NULL);
+        secondaryStorageSearch.and("isRemoved", secondaryStorageSearch.entity().getRemoved(), Op.NULL);
+        secondaryStorageSearch.done();
 	}
 
 	@Override @DB(txn=false)
@@ -316,9 +331,34 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
 	  	SearchCriteria<Long> sc = CountByAccount.create();
         sc.setParameters("account", accountId);
 		sc.setParameters("state", Volume.State.Destroy);
-        return customSearch(sc, null).get(0);		
+        return customSearch(sc, null).get(0);
 	}
 
+    @Override
+    public long primaryStorageUsedForAccount(long accountId) {
+        SearchCriteria<SumCount> sc = primaryStorageSearch.create();
+        sc.setParameters("accountId", accountId);
+        List<SumCount> storageSpace = customSearch(sc, null);
+        if (storageSpace != null) {
+            return storageSpace.get(0).sum;
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    public long secondaryStorageUsedForAccount(long accountId) {
+        SearchCriteria<SumCount> sc = secondaryStorageSearch.create();
+        sc.setParameters("accountId", accountId);
+        List<SumCount> storageSpace = customSearch(sc, null);
+        if (storageSpace != null) {
+            return storageSpace.get(0).sum;
+        } else {
+            return 0;
+        }
+    }
+
+
 	public static class SumCount {
 	    public long sum;
 	    public long count;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18695276/server/src/com/cloud/storage/download/DownloadListener.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/download/DownloadListener.java b/server/src/com/cloud/storage/download/DownloadListener.java
index d4c20cf..1d48803 100755
--- a/server/src/com/cloud/storage/download/DownloadListener.java
+++ b/server/src/com/cloud/storage/download/DownloadListener.java
@@ -22,6 +22,8 @@ import java.util.Map;
 import java.util.Timer;
 import java.util.TimerTask;
 
+import javax.inject.Inject;
+
 import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
 
@@ -36,28 +38,31 @@ import com.cloud.agent.api.StartupSecondaryStorageCommand;
 import com.cloud.agent.api.StartupStorageCommand;
 import com.cloud.agent.api.storage.DownloadAnswer;
 import com.cloud.agent.api.storage.DownloadCommand;
-import com.cloud.agent.api.storage.DownloadProgressCommand;
 import com.cloud.agent.api.storage.DownloadCommand.ResourceType;
+import com.cloud.agent.api.storage.DownloadProgressCommand;
 import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
+import com.cloud.alert.AlertManager;
 import com.cloud.exception.AgentUnavailableException;
 import com.cloud.exception.ConnectionException;
+import com.cloud.exception.ResourceAllocationException;
 import com.cloud.host.HostVO;
-
+import com.cloud.host.dao.HostDao;
 import com.cloud.storage.Storage;
 import com.cloud.storage.StorageManager;
 import com.cloud.storage.VMTemplateHostVO;
+import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
 import com.cloud.storage.VMTemplateVO;
 import com.cloud.storage.VolumeHostVO;
 import com.cloud.storage.VolumeVO;
-import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
-import com.cloud.storage.Volume.Event;
 import com.cloud.storage.dao.VMTemplateDao;
 import com.cloud.storage.dao.VMTemplateHostDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.storage.dao.VolumeHostDao;
 import com.cloud.storage.download.DownloadState.DownloadEvent;
+import com.cloud.user.AccountManager;
+import com.cloud.user.ResourceLimitService;
+import com.cloud.utils.UriUtils;
 import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.utils.fsm.NoTransitionException;
 
 /**
  * Monitor progress of template download to a single storage server
@@ -119,6 +124,9 @@ public class DownloadListener implements Listener {
 	private StorageManager _storageMgr;
 	private VMTemplateHostDao vmTemplateHostDao;
 	private VMTemplateDao _vmTemplateDao;
+	private ResourceLimitService _resourceLimitMgr;
+	private AccountManager _accountMgr;
+	private AlertManager _alertMgr;
 
 	private final DownloadMonitorImpl downloadMonitor;
 	
@@ -137,7 +145,7 @@ public class DownloadListener implements Listener {
 	private Long templateHostId;
 	private Long volumeHostId;
 	
-	public DownloadListener(HostVO ssAgent, HostVO host, VMTemplateVO template, Timer _timer, VMTemplateHostDao dao, Long templHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VMTemplateDao templateDao) {
+	public DownloadListener(HostVO ssAgent, HostVO host, VMTemplateVO template, Timer _timer, VMTemplateHostDao dao, Long templHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VMTemplateDao templateDao, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr) {
 	    this.ssAgent = ssAgent;
         this.sserver = host;
 		this.template = template;
@@ -151,10 +159,13 @@ public class DownloadListener implements Listener {
 		this.timeoutTask = new TimeoutTask(this);
 		this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL);
 		this._vmTemplateDao = templateDao;
+		this._resourceLimitMgr = _resourceLimitMgr;
+		this._accountMgr = _accountMgr;
+		this._alertMgr = _alertMgr;
 		updateDatabase(Status.NOT_DOWNLOADED, "");
 	}
 	
-	public DownloadListener(HostVO ssAgent, HostVO host, VolumeVO volume, Timer _timer, VolumeHostDao dao, Long volHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VolumeDao volumeDao, StorageManager storageMgr) {
+	public DownloadListener(HostVO ssAgent, HostVO host, VolumeVO volume, Timer _timer, VolumeHostDao dao, Long volHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VolumeDao volumeDao, StorageManager storageMgr, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr) {
 	    this.ssAgent = ssAgent;
         this.sserver = host;
 		this.volume = volume;
@@ -169,6 +180,9 @@ public class DownloadListener implements Listener {
 		this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL);
 		this._volumeDao = volumeDao;
 		this._storageMgr = storageMgr;
+		this._resourceLimitMgr = _resourceLimitMgr;
+		this._accountMgr = _accountMgr;
+		this._alertMgr = _alertMgr;
 		updateDatabase(Status.NOT_DOWNLOADED, "");
 	}
 	
@@ -332,6 +346,24 @@ public class DownloadListener implements Listener {
 				templateDaoBuilder.setChecksum(answer.getCheckSum());
 				_vmTemplateDao.update(template.getId(), templateDaoBuilder);
 			}
+
+            if (answer.getTemplateSize() > 0) {
+                //long hostId = vmTemplateHostDao.findByTemplateId(template.getId()).getHostId();
+                long accountId = template.getAccountId();
+                try {
+                    _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId),
+                            com.cloud.configuration.Resource.ResourceType.secondary_storage,
+                            answer.getTemplateSize() - UriUtils.getRemoteSize(template.getUrl()));
+                } catch (ResourceAllocationException e) {
+                    s_logger.warn(e.getMessage());
+                    _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, sserver.getDataCenterId(),
+                            null, e.getMessage(), e.getMessage());
+                } finally {
+                    _resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId).getDomainId(),
+                            com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal());
+                }
+            }
+
 		} else {
 	        VolumeHostVO updateBuilder = volumeHostDao.createForUpdate();
 			updateBuilder.setDownloadPercent(answer.getDownloadPct());
@@ -351,6 +383,22 @@ public class DownloadListener implements Listener {
 			updateVolume.setSize(answer.getTemplateSize());
 			_volumeDao.update(volume.getId(), updateVolume);
 
+            if (answer.getTemplateSize() > 0) {
+                try {
+                    String url = volumeHostDao.findByVolumeId(volume.getId()).getDownloadUrl();
+                    _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()),
+                            com.cloud.configuration.Resource.ResourceType.secondary_storage,
+                            answer.getTemplateSize() - UriUtils.getRemoteSize(url));
+                } catch (ResourceAllocationException e) {
+                    s_logger.warn(e.getMessage());
+                    _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, volume.getDataCenterId(),
+                            volume.getPodId(), e.getMessage(), e.getMessage());
+                } finally {
+                    _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(),
+                            com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal());
+                }
+            }
+
 			/*if (answer.getCheckSum() != null) {
 				VMTemplateVO templateDaoBuilder = _vmTemplateDao.createForUpdate();
 				templateDaoBuilder.setChecksum(answer.getCheckSum());


Mime
View raw message