cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r...@apache.org
Subject [5/8] git commit: updated refs/heads/master to 24d0609
Date Mon, 07 Dec 2015 18:25:35 GMT
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaTariffDaoImpl.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaTariffDaoImpl.java b/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaTariffDaoImpl.java
new file mode 100644
index 0000000..294b404
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaTariffDaoImpl.java
@@ -0,0 +1,133 @@
+//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.quota.dao;
+
+import com.cloud.utils.db.Filter;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallback;
+import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.utils.db.TransactionStatus;
+import org.apache.cloudstack.quota.constant.QuotaTypes;
+import org.apache.cloudstack.quota.vo.QuotaTariffVO;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import javax.ejb.Local;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@Component
+@Local(value = {QuotaTariffDao.class})
+public class QuotaTariffDaoImpl extends GenericDaoBase<QuotaTariffVO, Long> implements QuotaTariffDao {
+    private static final Logger s_logger = Logger.getLogger(QuotaTariffDaoImpl.class.getName());
+
+    private final SearchBuilder<QuotaTariffVO> searchUsageType;
+    private final SearchBuilder<QuotaTariffVO> listAllIncludedUsageType;
+
+    public QuotaTariffDaoImpl() {
+        super();
+        searchUsageType = createSearchBuilder();
+        searchUsageType.and("usage_type", searchUsageType.entity().getUsageType(), SearchCriteria.Op.EQ);
+        searchUsageType.done();
+
+        listAllIncludedUsageType = createSearchBuilder();
+        listAllIncludedUsageType.and("onorbefore", listAllIncludedUsageType.entity().getEffectiveOn(), SearchCriteria.Op.LTEQ);
+        listAllIncludedUsageType.and("quotatype", listAllIncludedUsageType.entity().getUsageType(), SearchCriteria.Op.EQ);
+        listAllIncludedUsageType.done();
+    }
+
+    public QuotaTariffVO findTariffPlanByUsageType(final int quotaType, final Date effectiveDate) {
+        return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaTariffVO>() {
+            @Override
+            public QuotaTariffVO doInTransaction(final TransactionStatus status) {
+                List<QuotaTariffVO> result = new ArrayList<>();
+                final Filter filter = new Filter(QuotaTariffVO.class, "updatedOn", false, 0L, 1L);
+                final SearchCriteria<QuotaTariffVO> sc = listAllIncludedUsageType.create();
+                sc.setParameters("onorbefore", effectiveDate);
+                sc.setParameters("quotatype", quotaType);
+                result = search(sc, filter);
+                if (result != null && !result.isEmpty()) {
+                    return result.get(0);
+                } else {
+                    if (s_logger.isDebugEnabled()) {
+                        s_logger.debug("QuotaTariffDaoImpl::findTariffPlanByUsageType: Missing quota type " + quotaType);
+                    }
+                    return null;
+                }
+            }
+        });
+    }
+
+    public List<QuotaTariffVO> listAllTariffPlans() {
+        return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaTariffVO>>() {
+            @Override
+            public List<QuotaTariffVO> doInTransaction(final TransactionStatus status) {
+                return listAll();
+            }
+        });
+    }
+
+    public List<QuotaTariffVO> listAllTariffPlans(final Date effectiveDate) {
+        return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaTariffVO>>() {
+            @Override
+            public List<QuotaTariffVO> doInTransaction(final TransactionStatus status) {
+                List<QuotaTariffVO> tariffs = new ArrayList<QuotaTariffVO>();
+                final Filter filter = new Filter(QuotaTariffVO.class, "updatedOn", false, 0L, 1L);
+                final SearchCriteria<QuotaTariffVO> sc = listAllIncludedUsageType.create();
+                sc.setParameters("onorbefore", effectiveDate);
+                for (Integer quotaType : QuotaTypes.listQuotaTypes().keySet()) {
+                    sc.setParameters("quotatype", quotaType);
+                    List<QuotaTariffVO> result = search(sc, filter);
+                    if (result != null && !result.isEmpty()) {
+                        tariffs.add(result.get(0));
+                        if (s_logger.isDebugEnabled()) {
+                            s_logger.debug("ListAllTariffPlans on or before " + effectiveDate + " quota type " + result.get(0).getDescription() + " , effective Date="
+                                    + result.get(0).getEffectiveOn() + " val=" + result.get(0).getCurrencyValue());
+                        }
+                    }
+                }
+                return tariffs;
+            }
+        });
+    }
+
+    public Boolean updateQuotaTariff(final QuotaTariffVO plan) {
+        return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<Boolean>() {
+            @Override
+            public Boolean doInTransaction(final TransactionStatus status) {
+                return update(plan.getId(), plan);
+            }
+        });
+    }
+
+    public QuotaTariffVO addQuotaTariff(final QuotaTariffVO plan) {
+        if (plan.getIdObj() != null) {
+            throw new IllegalStateException("The QuotaTariffVO being added should not have an Id set ");
+        }
+        return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaTariffVO>() {
+            @Override
+            public QuotaTariffVO doInTransaction(final TransactionStatus status) {
+                return persist(plan);
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaUsageDao.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaUsageDao.java b/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaUsageDao.java
new file mode 100644
index 0000000..d0c984c
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaUsageDao.java
@@ -0,0 +1,35 @@
+//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.quota.dao;
+
+import com.cloud.utils.db.GenericDao;
+import org.apache.cloudstack.quota.vo.QuotaUsageVO;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+public interface QuotaUsageDao extends GenericDao<QuotaUsageVO, Long> {
+
+    QuotaUsageVO persistQuotaUsage(QuotaUsageVO quotaUsage);
+
+    List<QuotaUsageVO> findQuotaUsage(Long accountId, Long domainId, Integer usageType, Date startDate, Date endDate);
+
+    BigDecimal findTotalQuotaUsage(Long accountId, Long domainId, Integer usageType, Date startDate, Date endDate);
+
+    QuotaUsageVO findLastQuotaUsageEntry(Long accountId, Long domainId, Date beforeThis);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaUsageDaoImpl.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaUsageDaoImpl.java b/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaUsageDaoImpl.java
new file mode 100644
index 0000000..8c0fae6
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/dao/QuotaUsageDaoImpl.java
@@ -0,0 +1,116 @@
+//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.quota.dao;
+
+import com.cloud.utils.db.Filter;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.QueryBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallback;
+import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.utils.db.TransactionStatus;
+
+import org.apache.cloudstack.quota.vo.QuotaUsageVO;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import javax.ejb.Local;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@Component
+@Local(value = {QuotaUsageDao.class})
+public class QuotaUsageDaoImpl extends GenericDaoBase<QuotaUsageVO, Long> implements QuotaUsageDao {
+    private static final Logger s_logger = Logger.getLogger(QuotaUsageDaoImpl.class);
+
+    public BigDecimal findTotalQuotaUsage(final Long accountId, final Long domainId, final Integer usageType, final Date startDate, final Date endDate) {
+        List<QuotaUsageVO> quotaUsage = findQuotaUsage(accountId, domainId, null, startDate, endDate);
+        BigDecimal total = new BigDecimal(0);
+        for (QuotaUsageVO quotaRecord : quotaUsage) {
+            total = total.add(quotaRecord.getQuotaUsed());
+        }
+        return total;
+    }
+
+    public List<QuotaUsageVO> findQuotaUsage(final Long accountId, final Long domainId, final Integer usageType, final Date startDate, final Date endDate) {
+        return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaUsageVO>>() {
+            @Override
+            public List<QuotaUsageVO> doInTransaction(final TransactionStatus status) {
+                List<QuotaUsageVO> quv;
+                if ((startDate != null) && (endDate != null) && startDate.before(endDate)) {
+                    QueryBuilder<QuotaUsageVO> qb = QueryBuilder.create(QuotaUsageVO.class);
+                    if (accountId != null) {
+                        qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
+                    }
+                    if (domainId != null) {
+                        qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
+                    }
+                    if (usageType != null) {
+                        qb.and(qb.entity().getUsageType(), SearchCriteria.Op.EQ, usageType);
+                    }
+                    qb.and(qb.entity().getStartDate(), SearchCriteria.Op.BETWEEN, startDate, endDate);
+                    qb.and(qb.entity().getEndDate(), SearchCriteria.Op.BETWEEN, startDate, endDate);
+                    quv = listBy(qb.create());
+                } else {
+                    quv = new ArrayList<QuotaUsageVO>();
+                }
+                if (quv.isEmpty()){
+                    //add a dummy entry
+                    QuotaUsageVO qu = new  QuotaUsageVO();
+                    qu.setAccountId(accountId);
+                    qu.setDomainId(domainId);
+                    qu.setStartDate(startDate);
+                    qu.setEndDate(endDate);
+                    qu.setQuotaUsed(new BigDecimal(0));
+                    qu.setUsageType(-1);
+                    quv.add(qu);
+                }
+                return quv;
+            }
+        });
+    }
+
+    public QuotaUsageVO findLastQuotaUsageEntry(final Long accountId, final Long domainId, final Date beforeThis) {
+        return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaUsageVO>() {
+            @Override
+            public QuotaUsageVO doInTransaction(final TransactionStatus status) {
+                List<QuotaUsageVO> quotaUsageEntries = new ArrayList<>();
+                Filter filter = new Filter(QuotaUsageVO.class, "startDate", false, 0L, 1L);
+                QueryBuilder<QuotaUsageVO> qb = QueryBuilder.create(QuotaUsageVO.class);
+                qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
+                qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
+                qb.and(qb.entity().getStartDate(), SearchCriteria.Op.LT, beforeThis);
+                quotaUsageEntries = search(qb.create(), filter);
+                return !quotaUsageEntries.isEmpty() ? quotaUsageEntries.get(0) : null;
+            }
+        });
+    }
+
+    public QuotaUsageVO persistQuotaUsage(final QuotaUsageVO quotaUsage) {
+        return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaUsageVO>() {
+            @Override
+            public QuotaUsageVO doInTransaction(final TransactionStatus status) {
+                return persist(quotaUsage);
+            }
+        });
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/dao/ServiceOfferingDao.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/dao/ServiceOfferingDao.java b/framework/quota/src/org/apache/cloudstack/quota/dao/ServiceOfferingDao.java
new file mode 100644
index 0000000..8353977
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/dao/ServiceOfferingDao.java
@@ -0,0 +1,25 @@
+// 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.quota.dao;
+
+import org.apache.cloudstack.quota.vo.ServiceOfferingVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface ServiceOfferingDao extends GenericDao<ServiceOfferingVO, Long> {
+    ServiceOfferingVO findServiceOffering(Long vmId, long serviceOfferingId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/dao/ServiceOfferingDaoImpl.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/dao/ServiceOfferingDaoImpl.java b/framework/quota/src/org/apache/cloudstack/quota/dao/ServiceOfferingDaoImpl.java
new file mode 100644
index 0000000..1d8b1b6
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/dao/ServiceOfferingDaoImpl.java
@@ -0,0 +1,84 @@
+// 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.quota.dao;
+
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+import org.apache.cloudstack.quota.vo.ServiceOfferingVO;
+
+import com.cloud.event.UsageEventVO;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallback;
+import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.utils.db.TransactionStatus;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@Component
+@Local(value = {ServiceOfferingDao.class})
+@DB()
+public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Long> implements ServiceOfferingDao {
+    protected static final Logger s_logger = Logger.getLogger(ServiceOfferingDaoImpl.class);
+
+    @Inject
+    UserVmDetailsDao userVmDetailsDao;
+
+    public ServiceOfferingVO findServiceOffering(final Long vmId, final long serviceOfferingId) {
+        return Transaction.execute(TransactionLegacy.CLOUD_DB, new TransactionCallback<ServiceOfferingVO>() {
+            @Override
+            public ServiceOfferingVO doInTransaction(final TransactionStatus status) {
+                ServiceOfferingVO offering = findById(serviceOfferingId);
+                if (offering.isDynamic()) {
+                    if (vmId == null) {
+                        throw new CloudRuntimeException("missing argument vmId");
+                    }
+                    offering.setDynamicFlag(true);
+                    Map<String, String> dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId);
+                    return getcomputeOffering(offering, dynamicOffering);
+                }
+                return offering;
+            }
+        });
+    }
+
+    private ServiceOfferingVO getcomputeOffering(final ServiceOfferingVO serviceOffering, final Map<String, String> customParameters) {
+        return Transaction.execute(TransactionLegacy.CLOUD_DB, new TransactionCallback<ServiceOfferingVO>() {
+            @Override
+            public ServiceOfferingVO doInTransaction(final TransactionStatus status) {
+                ServiceOfferingVO dummyoffering = new ServiceOfferingVO(serviceOffering);
+                dummyoffering.setDynamicFlag(true);
+                if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuNumber.name())) {
+                    dummyoffering.setCpu(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.cpuNumber.name())));
+                }
+                if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuSpeed.name())) {
+                    dummyoffering.setSpeed(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.cpuSpeed.name())));
+                }
+                if (customParameters.containsKey(UsageEventVO.DynamicParameters.memory.name())) {
+                    dummyoffering.setRamSize(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.memory.name())));
+                }
+                return dummyoffering;
+            }
+        });
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/dao/UserVmDetailsDao.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/dao/UserVmDetailsDao.java b/framework/quota/src/org/apache/cloudstack/quota/dao/UserVmDetailsDao.java
new file mode 100644
index 0000000..f8ab3b9
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/dao/UserVmDetailsDao.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.quota.dao;
+
+import java.util.Map;
+
+import com.cloud.utils.db.GenericDao;
+
+import org.apache.cloudstack.quota.vo.UserVmDetailVO;
+
+public interface UserVmDetailsDao extends GenericDao<UserVmDetailVO, Long> {
+    Map<String, String> listDetailsKeyPairs(long resourceId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/dao/UserVmDetailsDaoImpl.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/dao/UserVmDetailsDaoImpl.java b/framework/quota/src/org/apache/cloudstack/quota/dao/UserVmDetailsDaoImpl.java
new file mode 100644
index 0000000..beb3cdf
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/dao/UserVmDetailsDaoImpl.java
@@ -0,0 +1,59 @@
+// 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.quota.dao;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+
+import org.springframework.stereotype.Component;
+import org.apache.cloudstack.quota.vo.UserVmDetailVO;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+@Local(value = UserVmDetailsDao.class)
+public class UserVmDetailsDaoImpl extends GenericDaoBase<UserVmDetailVO, Long> implements UserVmDetailsDao {
+    private SearchBuilder<UserVmDetailVO> AllFieldsSearch;
+
+    public UserVmDetailsDaoImpl() {
+        AllFieldsSearch = createSearchBuilder();
+        AllFieldsSearch.and("resourceId", AllFieldsSearch.entity().getResourceId(), SearchCriteria.Op.EQ);
+        AllFieldsSearch.and("name", AllFieldsSearch.entity().getName(), SearchCriteria.Op.EQ);
+        AllFieldsSearch.and("value", AllFieldsSearch.entity().getValue(), SearchCriteria.Op.EQ);
+        AllFieldsSearch.and("display", AllFieldsSearch.entity().isDisplay(), SearchCriteria.Op.EQ);
+        AllFieldsSearch.done();
+    }
+
+    @Override
+    public Map<String, String> listDetailsKeyPairs(long resourceId) {
+        Map<String, String> details = new HashMap<String, String>();
+        SearchCriteria<UserVmDetailVO> sc = AllFieldsSearch.create();
+        sc.setParameters("resourceId", resourceId);
+
+        List<UserVmDetailVO> results = search(sc, null);
+        for (UserVmDetailVO result : results) {
+            details.put(result.getName(), result.getValue());
+        }
+        return details;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaAccountVO.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaAccountVO.java b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaAccountVO.java
new file mode 100644
index 0000000..00bc33a
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaAccountVO.java
@@ -0,0 +1,149 @@
+//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.quota.vo;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Entity
+@Table(name = "quota_account")
+public class QuotaAccountVO implements InternalIdentity {
+
+    private static final long serialVersionUID = -7112846845287653210L;
+
+    @Id
+    @Column(name = "account_id")
+    private Long accountId = null;
+
+    @Column(name = "quota_enforce")
+    private Integer quotaEnforce = 0;
+
+    @Column(name = "quota_balance")
+    private BigDecimal quotaBalance;
+
+    @Column(name = "quota_balance_date")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date quotaBalanceDate = null;
+
+    @Column(name = "quota_min_balance")
+    private BigDecimal quotaMinBalance;
+
+    @Column(name = "quota_alert_type")
+    private Integer quotaAlertType = null;
+
+    @Column(name = "quota_alert_date")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date quotaAlertDate = null;
+
+    @Column(name = "last_statement_date")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date lastStatementDate = null;
+
+    public QuotaAccountVO() {
+    }
+
+    public QuotaAccountVO(Long accountId) {
+        super();
+        this.accountId = accountId;
+    }
+
+    @Override
+    public long getId() {
+        return accountId;
+    }
+
+    public Long getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(Long accountId) {
+        this.accountId = accountId;
+    }
+
+    public Integer getQuotaEnforce() {
+        return quotaEnforce == null ? 0 : quotaEnforce;
+    }
+
+    public void setQuotaEnforce(Integer quotaEnforce) {
+        this.quotaEnforce = quotaEnforce;
+    }
+
+    public BigDecimal getQuotaBalance() {
+        return quotaBalance;
+    }
+
+    public void setQuotaBalance(BigDecimal quotaBalance) {
+        this.quotaBalance = quotaBalance;
+    }
+
+    public BigDecimal getQuotaMinBalance() {
+        return quotaMinBalance == null ? new BigDecimal(0) : quotaMinBalance;
+    }
+
+    public void setQuotaMinBalance(BigDecimal quotaMinBalance) {
+        this.quotaMinBalance = quotaMinBalance;
+    }
+
+    public Integer getQuotaAlertType() {
+        return quotaAlertType;
+    }
+
+    public void setQuotaAlertType(Integer quotaAlertType) {
+        this.quotaAlertType = quotaAlertType;
+    }
+
+    public Date getQuotaAlertDate() {
+        return quotaAlertDate == null ? null : new Date(quotaAlertDate.getTime());
+    }
+
+    public void setQuotaAlertDate(Date quotaAlertDate) {
+        this.quotaAlertDate = quotaAlertDate == null ? null : new Date(quotaAlertDate.getTime());
+    }
+
+    public Date getQuotaBalanceDate() {
+        return quotaBalanceDate  == null ? null : new Date(quotaBalanceDate.getTime());
+    }
+
+    public void setQuotaBalanceDate(Date quotaBalanceDate) {
+        this.quotaBalanceDate = quotaBalanceDate == null ? null : new Date(quotaBalanceDate.getTime());
+    }
+
+    public Date getLastStatementDate() {
+        return lastStatementDate  == null ? null : new Date(lastStatementDate.getTime());
+    }
+
+    public void setLastStatementDate(Date lastStatementDate) {
+        this.lastStatementDate = lastStatementDate  == null ? null : new Date(lastStatementDate.getTime());
+    }
+
+    @Override
+    public String toString() {
+        return "QuotaAccountVO [accountId=" + accountId + ", quotaEnforce=" + quotaEnforce + ", quotaBalance=" + quotaBalance + ", quotaBalanceDate=" + quotaBalanceDate
+                + ", quotaMinBalance=" + quotaMinBalance + ", quotaAlertType=" + quotaAlertType + ", quotaAlertDate=" + quotaAlertDate + ", lastStatementDate=" + lastStatementDate
+                + "]";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaBalanceVO.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaBalanceVO.java b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaBalanceVO.java
new file mode 100644
index 0000000..b454a14
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaBalanceVO.java
@@ -0,0 +1,133 @@
+//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.quota.vo;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Entity
+@Table(name = "quota_balance")
+public class QuotaBalanceVO implements InternalIdentity {
+
+    private static final long serialVersionUID = -7112846845287653210L;
+
+    @Id
+    @Column(name = "id")
+    private Long id;
+
+    @Column(name = "account_id")
+    private Long accountId = null;
+
+    @Column(name = "domain_id")
+    private Long domainId = null;
+
+    @Column(name = "credit_balance")
+    private BigDecimal creditBalance;
+
+    @Column(name = "credits_id")
+    private Long creditsId;
+
+    @Column(name = "updated_on")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date updatedOn = null;
+
+    public QuotaBalanceVO() {
+    }
+
+    public QuotaBalanceVO(final QuotaCreditsVO credit) {
+        super();
+        this.accountId = credit.getAccountId();
+        this.domainId = credit.getDomainId();
+        this.creditBalance = credit.getCredit();
+        this.updatedOn = credit.getUpdatedOn()  == null ? null : new Date(credit.getUpdatedOn().getTime());
+        this.creditsId = credit.getId();
+    }
+
+    public QuotaBalanceVO(final Long accountId, final Long domainId, final BigDecimal creditBalance, final Date updatedOn) {
+        super();
+        this.accountId = accountId;
+        this.domainId = domainId;
+        this.creditBalance = creditBalance;
+        this.creditsId = 0L;
+        this.updatedOn = updatedOn  == null ? null : new Date(updatedOn.getTime());
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(Long accountId) {
+        this.accountId = accountId;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public void setDomainId(Long domainId) {
+        this.domainId = domainId;
+    }
+
+    public Long getCreditsId() {
+        return creditsId;
+    }
+
+    public void setCreditsId(Long creditsId) {
+        this.creditsId = creditsId;
+    }
+
+    public BigDecimal getCreditBalance() {
+        return creditBalance;
+    }
+
+    public void setCreditBalance(BigDecimal creditBalance) {
+        this.creditBalance = creditBalance;
+    }
+
+    public Date getUpdatedOn() {
+        return updatedOn == null ? null : new Date(updatedOn.getTime());
+    }
+
+    public void setUpdatedOn(Date updatedOn) {
+        this.updatedOn =  updatedOn == null ? null : new Date(updatedOn.getTime());
+    }
+
+    @Override
+    public String toString() {
+        return "QuotaBalanceVO [id=" + id + ", accountId=" + accountId + ", domainId=" + domainId + ", creditBalance=" + creditBalance + ", creditsId=" + creditsId + ", updatedOn="
+                + updatedOn + "]";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaCreditsVO.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaCreditsVO.java b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaCreditsVO.java
new file mode 100644
index 0000000..f9c7b45
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaCreditsVO.java
@@ -0,0 +1,116 @@
+//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.quota.vo;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Entity
+@Table(name = "quota_credits")
+public class QuotaCreditsVO implements InternalIdentity {
+
+    private static final long serialVersionUID = -3576833845287653210L;
+
+    @Id
+    @Column(name = "id")
+    private Long id;
+
+    @Column(name = "account_id")
+    private Long accountId = null;
+
+    @Column(name = "domain_id")
+    private Long domainId = null;
+
+    @Column(name = "credit")
+    private BigDecimal credit;
+
+    @Column(name = "updated_on")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date updatedOn = null;
+
+    public QuotaCreditsVO() {
+    }
+
+    public QuotaCreditsVO(long accountId, long domainId, BigDecimal credit, long updatedBy) {
+        super();
+        this.accountId = accountId;
+        this.domainId = domainId;
+        this.credit = credit;
+        this.updatedBy = updatedBy;
+    }
+
+    public Long getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(Long accountId) {
+        this.accountId = accountId;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public void setDomainId(Long domainId) {
+        this.domainId = domainId;
+    }
+
+    public BigDecimal getCredit() {
+        return credit;
+    }
+
+    public void setCredit(BigDecimal credit) {
+        this.credit = credit;
+    }
+
+    public Date getUpdatedOn() {
+        return updatedOn == null ? null : new Date(updatedOn.getTime());
+    }
+
+    public void setUpdatedOn(Date updatedOn) {
+        this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime());
+    }
+
+    public Long getUpdatedBy() {
+        return updatedBy;
+    }
+
+    public void setUpdatedBy(Long updatedBy) {
+        this.updatedBy = updatedBy;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    // User ID of the creditor
+    @Column(name = "updated_by")
+    private Long updatedBy = null;
+
+    @Override
+    public long getId() {
+        return this.id;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaEmailTemplatesVO.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaEmailTemplatesVO.java b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaEmailTemplatesVO.java
new file mode 100644
index 0000000..1ad4b37
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaEmailTemplatesVO.java
@@ -0,0 +1,109 @@
+//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.quota.vo;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+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 java.util.Date;
+
+@Entity
+@Table(name = "quota_email_templates")
+public class QuotaEmailTemplatesVO implements InternalIdentity {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private Long id;
+
+    @Column(name = "template_name")
+    private String templateName;
+
+    @Column(name = "template_subject")
+    private String templateSubject;
+
+    @Column(name = "template_body")
+    private String templateBody;
+
+    @Column(name = "locale")
+    private String locale;
+
+    @Column(name = "updated")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date lastUpdated = null;
+
+    public QuotaEmailTemplatesVO() {
+    }
+
+    public QuotaEmailTemplatesVO(String templateName, String templateSubject, String templateBody) {
+        super();
+        this.templateName = templateName;
+        this.templateSubject = templateSubject;
+        this.templateBody = templateBody;
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+
+    public String getTemplateName() {
+        return templateName;
+    }
+
+    public void setTemplateName(String templateName) {
+        this.templateName = templateName;
+    }
+
+    public String getTemplateSubject() {
+        return templateSubject;
+    }
+
+    public void setTemplateSubject(String templateSubject) {
+        this.templateSubject = templateSubject;
+    }
+
+    public String getTemplateBody() {
+        return templateBody;
+    }
+
+    public void setTemplateBody(String templateBody) {
+        this.templateBody = templateBody;
+    }
+
+    public Date getLastUpdated() {
+        return lastUpdated == null ? null : new Date(lastUpdated.getTime());
+    }
+
+    public void setLastUpdated(Date lastUpdated) {
+        this.lastUpdated = lastUpdated == null ? null : new Date(lastUpdated.getTime());
+    }
+
+    public String getLocale() {
+        return locale;
+    }
+
+    public void setLocale(String locale) {
+        this.locale = locale;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaTariffVO.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaTariffVO.java b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaTariffVO.java
new file mode 100644
index 0000000..8450d09
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaTariffVO.java
@@ -0,0 +1,170 @@
+//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.quota.vo;
+
+import org.apache.cloudstack.api.InternalIdentity;
+import org.apache.cloudstack.quota.constant.QuotaTypes;
+
+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 java.math.BigDecimal;
+import java.util.Date;
+
+@Entity
+@Table(name = "quota_tariff")
+public class QuotaTariffVO implements InternalIdentity {
+    private static final long serialVersionUID = -7117933766387653203L;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private Long id;
+
+    @Column(name = "usage_type")
+    private int usageType;
+
+    @Column(name = "usage_name")
+    private String usageName;
+
+    @Column(name = "usage_unit")
+    private String usageUnit;
+
+    @Column(name = "usage_discriminator")
+    private String usageDiscriminator;
+
+    @Column(name = "currency_value")
+    private BigDecimal currencyValue;
+
+    @Column(name = "effective_on")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date effectiveOn = null;
+
+    @Column(name = "updated_on")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date updatedOn = null;
+
+    @Column(name = "updated_by")
+    private Long updatedBy = null;
+
+    public QuotaTariffVO() {
+    }
+
+    public QuotaTariffVO(final int usagetype) {
+        this.usageType = usagetype;
+    }
+
+    public QuotaTariffVO(final int usagetype, final String usagename, final String usageunit, final String usagediscriminator, final BigDecimal currencyvalue,
+            final Date effectiveOn, final Date updatedOn, final long updatedBy) {
+        this.usageType = usagetype;
+        this.usageName = usagename;
+        this.usageUnit = usageunit;
+        this.usageDiscriminator = usagediscriminator;
+        this.currencyValue = currencyvalue;
+        this.effectiveOn = effectiveOn;
+        this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime());
+        this.updatedBy = updatedBy;
+    }
+
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Date getEffectiveOn() {
+        return effectiveOn == null ? null : new Date(effectiveOn.getTime());
+    }
+
+    public void setEffectiveOn(Date effectiveOn) {
+        this.effectiveOn = effectiveOn == null ? null : new Date(effectiveOn.getTime());
+    }
+
+    public Date getUpdatedOn() {
+        return updatedOn == null ? null : new Date(updatedOn.getTime());
+    }
+
+    public void setUpdatedOn(Date updatedOn) {
+        this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime());
+    }
+
+    public Long getUpdatedBy() {
+        return updatedBy;
+    }
+
+    public void setUpdatedBy(Long updatedBy) {
+        this.updatedBy = updatedBy;
+    }
+
+    public int getUsageType() {
+        return usageType;
+    }
+
+    public void setUsageType(int usageType) {
+        this.usageType = usageType;
+    }
+
+    public String getUsageName() {
+        return usageName;
+    }
+
+    public void setUsageName(String usageName) {
+        this.usageName = usageName;
+    }
+
+    public String getUsageUnit() {
+        return usageUnit;
+    }
+
+    public void setUsageUnit(String usageUnit) {
+        this.usageUnit = usageUnit;
+    }
+
+    public String getUsageDiscriminator() {
+        return usageDiscriminator;
+    }
+
+    public void setUsageDiscriminator(String usageDiscriminator) {
+        this.usageDiscriminator = usageDiscriminator;
+    }
+
+    public BigDecimal getCurrencyValue() {
+        return currencyValue;
+    }
+
+    public void setCurrencyValue(BigDecimal currencyValue) {
+        this.currencyValue = currencyValue;
+    }
+
+    public String getDescription() {
+        return QuotaTypes.getDescription(usageType);
+    }
+
+    public Long getIdObj(){
+        return id;
+    }
+
+    @Override
+    public long getId() {
+        return this.id;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaUsageVO.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaUsageVO.java b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaUsageVO.java
new file mode 100644
index 0000000..2a26951
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaUsageVO.java
@@ -0,0 +1,177 @@
+//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.quota.vo;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+@Entity
+@Table(name = "quota_usage")
+public class QuotaUsageVO implements InternalIdentity {
+
+    private static final long serialVersionUID = -7117933845287204781L;
+
+    @Id
+    @Column(name = "id")
+    private Long id;
+
+    @Column(name = "zone_id")
+    private Long zoneId = null;
+
+    @Column(name = "account_id")
+    private Long accountId = null;
+
+    @Column(name = "domain_id")
+    private Long domainId = null;
+
+    @Column(name = "usage_item_id")
+    private Long usageItemId;
+
+    @Column(name = "usage_type")
+    private int usageType;
+
+    @Column(name = "quota_used")
+    private BigDecimal quotaUsed;
+
+    @Column(name = "start_date")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date startDate = null;
+
+    @Column(name = "end_date")
+    @Temporal(value = TemporalType.TIMESTAMP)
+    private Date endDate = null;
+
+    public QuotaUsageVO() {
+        usageType = -1;
+        quotaUsed = new BigDecimal(0);
+        endDate = new Date();
+        startDate = new Date();
+    }
+
+    public QuotaUsageVO(Long usageItemId, Long zoneId, Long accountId, Long domainId, int usageType, BigDecimal quotaUsed, Date startDate, Date endDate) {
+        super();
+        this.usageItemId = usageItemId;
+        this.zoneId = zoneId;
+        this.accountId = accountId;
+        this.domainId = domainId;
+        this.usageType = usageType;
+        this.quotaUsed = quotaUsed;
+        this.startDate = startDate == null ? null : new Date(startDate.getTime());
+        this.endDate = endDate == null ? null : new Date(endDate.getTime());
+    }
+
+    public QuotaUsageVO(QuotaUsageVO toclone) {
+        super();
+        this.usageItemId = toclone.usageItemId;
+        this.zoneId = toclone.zoneId;
+        this.accountId = toclone.accountId;
+        this.domainId = toclone.domainId;
+        this.usageType = toclone.usageType;
+        this.quotaUsed = toclone.quotaUsed;
+        this.startDate = startDate == null ? null : new Date(startDate.getTime());
+        this.endDate = endDate == null ? null : new Date(endDate.getTime());
+    }
+
+    public Long getZoneId() {
+        return zoneId;
+    }
+
+    public void setZoneId(Long zoneId) {
+        this.zoneId = zoneId;
+    }
+
+    public Long getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(Long accountId) {
+        this.accountId = accountId;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public void setDomainId(Long domainId) {
+        this.domainId = domainId;
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+
+    public Long getUsageItemId() {
+        return usageItemId;
+    }
+
+    public void setUsageItemId(Long usageItemId) {
+        this.usageItemId = usageItemId;
+    }
+
+    public int getUsageType() {
+        return usageType;
+    }
+
+    public void setUsageType(int usageType) {
+        this.usageType = usageType;
+    }
+
+    public BigDecimal getQuotaUsed() {
+        return quotaUsed;
+    }
+
+    public void setQuotaUsed(BigDecimal quotaUsed) {
+        this.quotaUsed = quotaUsed;
+    }
+
+    public Date getStartDate() {
+        return startDate == null ? null : new Date(startDate.getTime());
+    }
+
+    public void setStartDate(Date startDate) {
+        this.startDate = startDate == null ? null : new Date(startDate.getTime());
+    }
+
+    public Date getEndDate() {
+        return endDate == null ? null : new Date(endDate.getTime());
+    }
+
+    public void setEndDate(Date endDate) {
+        this.endDate = endDate == null ? null : new Date(endDate.getTime());
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    @Override
+    public String toString() {
+        return "QuotaUsageVO [id=" + id + ", zoneId=" + zoneId + ", accountId=" + accountId + ", domainId=" + domainId + ", usageItemId=" + usageItemId + ", usageType=" + usageType
+                + ", quotaUsed=" + quotaUsed + ", startDate=" + startDate + ", endDate=" + endDate + "]";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/vo/ServiceOfferingVO.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/vo/ServiceOfferingVO.java b/framework/quota/src/org/apache/cloudstack/quota/vo/ServiceOfferingVO.java
new file mode 100644
index 0000000..2d11edd
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/vo/ServiceOfferingVO.java
@@ -0,0 +1,336 @@
+//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.quota.vo;
+
+import java.util.Map;
+
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import javax.persistence.PrimaryKeyJoinColumn;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import com.cloud.offering.ServiceOffering;
+import com.cloud.storage.DiskOfferingVO;
+import com.cloud.storage.Storage.ProvisioningType;
+import com.cloud.vm.VirtualMachine;
+
+@Entity
+@Table(name = "service_offering")
+@DiscriminatorValue(value = "Service")
+@PrimaryKeyJoinColumn(name = "id")
+public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering {
+    @Column(name = "cpu")
+    private Integer cpu;
+
+    @Column(name = "speed")
+    private Integer speed;
+
+    @Column(name = "ram_size")
+    private Integer ramSize;
+
+    @Column(name = "nw_rate")
+    private Integer rateMbps;
+
+    @Column(name = "mc_rate")
+    private Integer multicastRateMbps;
+
+    @Column(name = "ha_enabled")
+    private boolean offerHA;
+
+    @Column(name = "limit_cpu_use")
+    private boolean limitCpuUse;
+
+    @Column(name = "is_volatile")
+    private boolean volatileVm;
+
+    @Column(name = "host_tag")
+    private String hostTag;
+
+    @Column(name = "default_use")
+    private boolean defaultUse;
+
+    @Column(name = "vm_type")
+    private String vmType;
+
+    @Column(name = "sort_key")
+    int sortKey;
+
+    @Column(name = "deployment_planner")
+    private String deploymentPlanner = null;
+
+    // This is a delayed load value.  If the value is null,
+    // then this field has not been loaded yet.
+    // Call service offering dao to load it.
+    @Transient
+    Map<String, String> details;
+
+    // This flag is required to tell if the offering is dynamic once the cpu, memory and speed are set.
+    // In some cases cpu, memory and speed are set to non-null values even if the offering is dynamic.
+    @Transient
+    boolean isDynamic;
+
+    protected ServiceOfferingVO() {
+        super();
+    }
+
+    public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, String displayText,
+                             ProvisioningType provisioningType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vmType, boolean defaultUse) {
+        super(name, displayText, provisioningType, false, tags, recreatable, useLocalStorage, systemUse, true);
+        this.cpu = cpu;
+        this.ramSize = ramSize;
+        this.speed = speed;
+        this.rateMbps = rateMbps;
+        this.multicastRateMbps = multicastRateMbps;
+        this.offerHA = offerHA;
+        limitCpuUse = false;
+        volatileVm = false;
+        this.defaultUse = defaultUse;
+        this.vmType = vmType == null ? null : vmType.toString().toLowerCase();
+    }
+
+    public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitCpuUse,
+                             boolean volatileVm, String displayText, ProvisioningType provisioningType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vmType, Long domainId) {
+        super(name, displayText, provisioningType, false, tags, recreatable, useLocalStorage, systemUse, true, domainId);
+        this.cpu = cpu;
+        this.ramSize = ramSize;
+        this.speed = speed;
+        this.rateMbps = rateMbps;
+        this.multicastRateMbps = multicastRateMbps;
+        this.offerHA = offerHA;
+        this.limitCpuUse = limitCpuUse;
+        this.volatileVm = volatileVm;
+        this.vmType = vmType == null ? null : vmType.toString().toLowerCase();
+    }
+
+    public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA,
+                             boolean limitResourceUse, boolean volatileVm, String displayText, ProvisioningType provisioningType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse,
+                             VirtualMachine.Type vmType, Long domainId, String hostTag) {
+        this(name,
+                cpu,
+                ramSize,
+                speed,
+                rateMbps,
+                multicastRateMbps,
+                offerHA,
+                limitResourceUse,
+                volatileVm,
+                displayText,
+                provisioningType,
+                useLocalStorage,
+                recreatable,
+                tags,
+                systemUse,
+                vmType,
+                domainId);
+        this.hostTag = hostTag;
+    }
+
+    public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA,
+                             boolean limitResourceUse, boolean volatileVm, String displayText, ProvisioningType provisioningType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse,
+                             VirtualMachine.Type vmType, Long domainId, String hostTag, String deploymentPlanner) {
+        this(name,
+                cpu,
+                ramSize,
+                speed,
+                rateMbps,
+                multicastRateMbps,
+                offerHA,
+                limitResourceUse,
+                volatileVm,
+                displayText,
+                provisioningType,
+                useLocalStorage,
+                recreatable,
+                tags,
+                systemUse,
+                vmType,
+                domainId,
+                hostTag);
+        this.deploymentPlanner = deploymentPlanner;
+    }
+
+    public ServiceOfferingVO(ServiceOfferingVO offering) {
+        super(offering.getId(),
+                offering.getName(),
+                offering.getDisplayText(),
+                offering.getProvisioningType(),
+                false,
+                offering.getTags(),
+                offering.isRecreatable(),
+                offering.getUseLocalStorage(),
+                offering.getSystemUse(),
+                true,
+                offering.isCustomizedIops()== null ? false:offering.isCustomizedIops(),
+                offering.getDomainId(),
+                offering.getMinIops(),
+                offering.getMaxIops());
+        cpu = offering.getCpu();
+        ramSize = offering.getRamSize();
+        speed = offering.getSpeed();
+        rateMbps = offering.getRateMbps();
+        multicastRateMbps = offering.getMulticastRateMbps();
+        offerHA = offering.getOfferHA();
+        limitCpuUse = offering.getLimitCpuUse();
+        volatileVm = offering.getVolatileVm();
+        hostTag = offering.getHostTag();
+        vmType = offering.getSystemVmType();
+    }
+
+    @Override
+    public boolean getOfferHA() {
+        return offerHA;
+    }
+
+    public void setOfferHA(boolean offerHA) {
+        this.offerHA = offerHA;
+    }
+
+    @Override
+    public boolean getLimitCpuUse() {
+        return limitCpuUse;
+    }
+
+    public void setLimitResourceUse(boolean limitCpuUse) {
+        this.limitCpuUse = limitCpuUse;
+    }
+
+    @Override
+    public boolean getDefaultUse() {
+        return defaultUse;
+    }
+
+    @Override
+    @Transient
+    public String[] getTagsArray() {
+        String tags = getTags();
+        if (tags == null || tags.length() == 0) {
+            return new String[0];
+        }
+
+        return tags.split(",");
+    }
+
+    @Override
+    public Integer getCpu() {
+        return cpu;
+    }
+
+    public void setCpu(int cpu) {
+        this.cpu = cpu;
+    }
+
+    public void setSpeed(int speed) {
+        this.speed = speed;
+    }
+
+    public void setRamSize(int ramSize) {
+        this.ramSize = ramSize;
+    }
+
+    @Override
+    public Integer getSpeed() {
+        return speed;
+    }
+
+    @Override
+    public Integer getRamSize() {
+        return ramSize;
+    }
+
+    public void setRateMbps(Integer rateMbps) {
+        this.rateMbps = rateMbps;
+    }
+
+    @Override
+    public Integer getRateMbps() {
+        return rateMbps;
+    }
+
+    public void setMulticastRateMbps(Integer multicastRateMbps) {
+        this.multicastRateMbps = multicastRateMbps;
+    }
+
+    @Override
+    public Integer getMulticastRateMbps() {
+        return multicastRateMbps;
+    }
+
+    public void setHostTag(String hostTag) {
+        this.hostTag = hostTag;
+    }
+
+    @Override
+    public String getHostTag() {
+        return hostTag;
+    }
+
+    @Override
+    public String getSystemVmType() {
+        return vmType;
+    }
+
+    @Override
+    public void setSortKey(int key) {
+        sortKey = key;
+    }
+
+    @Override
+    public int getSortKey() {
+        return sortKey;
+    }
+
+    @Override
+    public boolean getVolatileVm() {
+        return volatileVm;
+    }
+
+    @Override
+    public String getDeploymentPlanner() {
+        return deploymentPlanner;
+    }
+
+    public Map<String, String> getDetails() {
+        return details;
+    }
+
+    public String getDetail(String name) {
+        assert (details != null) : "Did you forget to load the details?";
+
+        return details != null ? details.get(name) : null;
+    }
+
+    public void setDetail(String name, String value) {
+        assert (details != null) : "Did you forget to load the details?";
+
+        details.put(name, value);
+    }
+
+    public void setDetails(Map<String, String> details) {
+        this.details = details;
+    }
+
+    @Override
+    public boolean isDynamic() {
+        return cpu == null || speed == null || ramSize == null || isDynamic;
+    }
+
+    public void setDynamicFlag(boolean isdynamic) {
+        isDynamic = isdynamic;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/src/org/apache/cloudstack/quota/vo/UserVmDetailVO.java
----------------------------------------------------------------------
diff --git a/framework/quota/src/org/apache/cloudstack/quota/vo/UserVmDetailVO.java b/framework/quota/src/org/apache/cloudstack/quota/vo/UserVmDetailVO.java
new file mode 100644
index 0000000..21fcdbd
--- /dev/null
+++ b/framework/quota/src/org/apache/cloudstack/quota/vo/UserVmDetailVO.java
@@ -0,0 +1,83 @@
+//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.quota.vo;
+
+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 org.apache.cloudstack.api.ResourceDetail;
+
+@Entity
+@Table(name = "user_vm_details")
+public class UserVmDetailVO implements ResourceDetail {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private long id;
+
+    @Column(name = "vm_id")
+    private long resourceId;
+
+    @Column(name = "name")
+    private String name;
+
+    @Column(name = "value", length = 5120)
+    private String value;
+
+    @Column(name = "display")
+    private boolean display = true;
+
+    public UserVmDetailVO() {
+    }
+
+    public UserVmDetailVO(long vmId, String name, String value, boolean display) {
+        this.resourceId = vmId;
+        this.name = name;
+        this.value = value;
+        this.display = display;
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getValue() {
+        return value;
+    }
+
+    @Override
+    public long getResourceId() {
+        return resourceId;
+    }
+
+    @Override
+    public boolean isDisplay() {
+        return display;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/test/org/apache/cloudstack/quota/QuotaAlertManagerImplTest.java
----------------------------------------------------------------------
diff --git a/framework/quota/test/org/apache/cloudstack/quota/QuotaAlertManagerImplTest.java b/framework/quota/test/org/apache/cloudstack/quota/QuotaAlertManagerImplTest.java
new file mode 100644
index 0000000..14244fc
--- /dev/null
+++ b/framework/quota/test/org/apache/cloudstack/quota/QuotaAlertManagerImplTest.java
@@ -0,0 +1,197 @@
+// 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.quota;
+
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.user.Account;
+import com.cloud.user.AccountVO;
+import com.cloud.user.UserVO;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.user.dao.UserDao;
+import com.cloud.utils.db.TransactionLegacy;
+import junit.framework.TestCase;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.quota.constant.QuotaConfig;
+import org.apache.cloudstack.quota.dao.QuotaAccountDao;
+import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
+import org.apache.cloudstack.quota.dao.QuotaUsageDao;
+import org.apache.cloudstack.quota.vo.QuotaAccountVO;
+import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
+import org.joda.time.DateTime;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import javax.mail.MessagingException;
+import javax.naming.ConfigurationException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@RunWith(MockitoJUnitRunner.class)
+public class QuotaAlertManagerImplTest extends TestCase {
+
+    @Mock
+    AccountDao accountDao;
+    @Mock
+    QuotaAccountDao quotaAcc;
+    @Mock
+    UserDao userDao;
+    @Mock
+    DomainDao domainDao;
+    @Mock
+    QuotaEmailTemplatesDao quotaEmailTemplateDao;
+    @Mock
+    ConfigurationDao configDao;
+    @Mock
+    QuotaUsageDao quotaUsage;
+    @Mock
+    QuotaAlertManagerImpl.EmailQuotaAlert emailQuotaAlert;
+
+    @Spy
+    QuotaAlertManagerImpl quotaAlertManager = new QuotaAlertManagerImpl();
+
+    private void injectMockToField(Object mock, String fieldName) throws NoSuchFieldException, IllegalAccessException {
+        Field f = QuotaAlertManagerImpl.class.getDeclaredField(fieldName);
+        f.setAccessible(true);
+        f.set(quotaAlertManager, mock);
+    }
+
+    @Before
+    public void setup() throws IllegalAccessException, NoSuchFieldException, ConfigurationException {
+        // Dummy transaction stack setup
+        TransactionLegacy.open("QuotaAlertManagerImplTest");
+
+        injectMockToField(accountDao, "_accountDao");
+        injectMockToField(quotaAcc, "_quotaAcc");
+        injectMockToField(userDao, "_userDao");
+        injectMockToField(domainDao, "_domainDao");
+        injectMockToField(quotaEmailTemplateDao, "_quotaEmailTemplateDao");
+        injectMockToField(configDao, "_configDao");
+        injectMockToField(quotaUsage, "_quotaUsage");
+        injectMockToField(emailQuotaAlert, "_emailQuotaAlert");
+    }
+
+    @Test
+    public void testCheckAndSendQuotaAlertEmails() {
+        AccountVO accountVO = new AccountVO();
+        accountVO.setId(2L);
+        accountVO.setDomainId(1L);
+        accountVO.setType(Account.ACCOUNT_TYPE_NORMAL);
+        Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(accountVO);
+
+        QuotaAccountVO acc = new QuotaAccountVO(2L);
+        acc.setQuotaBalance(new BigDecimal(404));
+        acc.setQuotaMinBalance(new BigDecimal(100));
+        acc.setQuotaBalanceDate(new Date());
+        acc.setQuotaAlertDate(null);
+        acc.setQuotaEnforce(0);
+        List<QuotaAccountVO> accounts = new ArrayList<>();
+        accounts.add(acc);
+        Mockito.when(quotaAcc.listAllQuotaAccount()).thenReturn(accounts);
+
+        // Don't test sendQuotaAlert yet
+        Mockito.doNothing().when(quotaAlertManager).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
+        Mockito.doReturn(true).when(quotaAlertManager).lockAccount(Mockito.anyLong());
+
+        // call real method on send monthly statement
+        Mockito.doCallRealMethod().when(quotaAlertManager).checkAndSendQuotaAlertEmails();
+
+        // Case1: valid balance, no email should be sent
+        quotaAlertManager.checkAndSendQuotaAlertEmails();
+        Mockito.verify(quotaAlertManager, Mockito.times(0)).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
+
+        // Case2: low balance, email should be sent
+        accounts.get(0).setQuotaBalance(new BigDecimal(99));
+        //Mockito.when(quotaAcc.listAll()).thenReturn(accounts);
+        quotaAlertManager.checkAndSendQuotaAlertEmails();
+        Mockito.verify(quotaAlertManager, Mockito.times(1)).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
+    }
+
+    @Test
+    public void testSendQuotaAlert() throws UnsupportedEncodingException, MessagingException {
+        Mockito.doCallRealMethod().when(quotaAlertManager).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
+
+        AccountVO account = new AccountVO();
+        account.setId(2L);
+        account.setDomainId(1L);
+        account.setType(Account.ACCOUNT_TYPE_NORMAL);
+        account.setAccountName("admin");
+        account.setUuid("uuid");
+
+        QuotaAccountVO quotaAccount = new QuotaAccountVO(2L);
+        quotaAccount.setQuotaBalance(new BigDecimal(404));
+        quotaAccount.setQuotaMinBalance(new BigDecimal(100));
+        quotaAccount.setQuotaBalanceDate(new Date());
+        quotaAccount.setQuotaAlertDate(null);
+        quotaAccount.setQuotaEnforce(0);
+
+        QuotaAlertManagerImpl.DeferredQuotaEmail email = new QuotaAlertManagerImpl.DeferredQuotaEmail(account, quotaAccount, new BigDecimal(100),
+                QuotaConfig.QuotaEmailTemplateTypes.QUOTA_LOW);
+
+        QuotaEmailTemplatesVO quotaEmailTemplatesVO = new QuotaEmailTemplatesVO();
+        quotaEmailTemplatesVO.setTemplateSubject("Low quota");
+        quotaEmailTemplatesVO.setTemplateBody("Low quota {{accountID}}");
+        List<QuotaEmailTemplatesVO> emailTemplates = new ArrayList<>();
+        emailTemplates.add(quotaEmailTemplatesVO);
+        Mockito.when(quotaEmailTemplateDao.listAllQuotaEmailTemplates(Mockito.anyString())).thenReturn(emailTemplates);
+
+        DomainVO domain = new DomainVO();
+        domain.setUuid("uuid");
+        domain.setName("/domain");
+        Mockito.when(domainDao.findByIdIncludingRemoved(Mockito.anyLong())).thenReturn(new DomainVO());
+
+        UserVO user = new UserVO();
+        user.setUsername("user1");
+        user.setEmail("user1@apache.org");
+        List<UserVO> users = new ArrayList<>();
+        users.add(user);
+        Mockito.when(userDao.listByAccount(Mockito.anyLong())).thenReturn(users);
+
+        quotaAlertManager.sendQuotaAlert(email);
+        assertTrue(email.getSendDate()!= null);
+        Mockito.verify(emailQuotaAlert, Mockito.times(1)).sendQuotaAlert(Mockito.anyList(), Mockito.anyString(), Mockito.anyString());
+    }
+
+    @Test
+    public void testGetDifferenceDays() {
+        Date now = new Date();
+        assertTrue(QuotaAlertManagerImpl.getDifferenceDays(now, now) == 0L);
+        assertTrue(QuotaAlertManagerImpl.getDifferenceDays(now, new DateTime(now).plusDays(1).toDate()) == 1L);
+    }
+
+    @Test
+    public void testLockAccount() {
+        AccountVO accountVO = new AccountVO();
+        accountVO.setId(2L);
+        accountVO.setDomainId(1L);
+        accountVO.setType(Account.ACCOUNT_TYPE_NORMAL);
+        accountVO.setState(Account.State.enabled);
+        Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(accountVO);
+        Mockito.when(accountDao.createForUpdate()).thenReturn(accountVO);
+        Mockito.when(accountDao.update(Mockito.eq(accountVO.getId()), Mockito.eq(accountVO))).thenReturn(true);
+        assertTrue(quotaAlertManager.lockAccount(accountVO.getId()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/987fcbd4/framework/quota/test/org/apache/cloudstack/quota/QuotaManagerImplTest.java
----------------------------------------------------------------------
diff --git a/framework/quota/test/org/apache/cloudstack/quota/QuotaManagerImplTest.java b/framework/quota/test/org/apache/cloudstack/quota/QuotaManagerImplTest.java
new file mode 100644
index 0000000..792728f
--- /dev/null
+++ b/framework/quota/test/org/apache/cloudstack/quota/QuotaManagerImplTest.java
@@ -0,0 +1,200 @@
+// 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.quota;
+
+import com.cloud.usage.UsageVO;
+import com.cloud.usage.dao.UsageDao;
+import com.cloud.user.Account;
+import com.cloud.user.AccountVO;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.Pair;
+import com.cloud.utils.db.TransactionLegacy;
+import junit.framework.TestCase;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.quota.dao.QuotaAccountDao;
+import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
+import org.apache.cloudstack.quota.dao.QuotaTariffDao;
+import org.apache.cloudstack.quota.dao.QuotaUsageDao;
+import org.apache.cloudstack.quota.dao.ServiceOfferingDao;
+import org.apache.cloudstack.quota.vo.QuotaAccountVO;
+import org.apache.cloudstack.quota.vo.QuotaTariffVO;
+import org.apache.cloudstack.quota.vo.QuotaUsageVO;
+import org.apache.cloudstack.usage.UsageTypes;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import javax.naming.ConfigurationException;
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RunWith(MockitoJUnitRunner.class)
+public class QuotaManagerImplTest extends TestCase {
+
+    @Mock
+    private AccountDao accountDao;
+    @Mock
+    private QuotaAccountDao quotaAcc;
+    @Mock
+    private UsageDao usageDao;
+    @Mock
+    private QuotaTariffDao quotaTariffDao;
+    @Mock
+    private QuotaUsageDao quotaUsageDao;
+    @Mock
+    private ServiceOfferingDao serviceOfferingDao;
+    @Mock
+    private QuotaBalanceDao quotaBalanceDao;
+    @Mock
+    private ConfigurationDao configDao;
+
+    @Spy
+    QuotaManagerImpl quotaManager = new QuotaManagerImpl();
+
+    private void injectMockToField(Object mock, String fieldName) throws NoSuchFieldException, IllegalAccessException {
+        Field f = QuotaManagerImpl.class.getDeclaredField(fieldName);
+        f.setAccessible(true);
+        f.set(quotaManager, mock);
+    }
+
+    @Before
+    public void setup() throws IllegalAccessException, NoSuchFieldException, ConfigurationException {
+        // Dummy transaction stack setup
+        TransactionLegacy.open("QuotaManagerImplTest");
+
+        injectMockToField(accountDao, "_accountDao");
+        injectMockToField(quotaAcc, "_quotaAcc");
+        injectMockToField(usageDao, "_usageDao");
+        injectMockToField(quotaTariffDao, "_quotaTariffDao");
+        injectMockToField(quotaUsageDao, "_quotaUsageDao");
+        injectMockToField(serviceOfferingDao, "_serviceOfferingDao");
+        injectMockToField(quotaBalanceDao, "_quotaBalanceDao");
+        injectMockToField(configDao, "_configDao");
+    }
+
+    @Test
+    public void testConfig() throws ConfigurationException {
+        Mockito.when(configDao.getConfiguration(Mockito.anyMapOf(String.class, Object.class))).thenReturn(new HashMap<String, String>());
+        Map<String, Object> map = new HashMap<>();
+        map.put("usage.stats.job.aggregation.range", "0");
+        assertTrue(quotaManager.configure("quotaManager", map));
+    }
+
+    @Test
+    public void testCalculateQuotaUsage() {
+        AccountVO accountVO = new AccountVO();
+        accountVO.setId(2L);
+        accountVO.setDomainId(1L);
+        accountVO.setType(Account.ACCOUNT_TYPE_NORMAL);
+        List<AccountVO> accountVOList = new ArrayList<>();
+        accountVOList.add(accountVO);
+        Mockito.when(accountDao.listAll()).thenReturn(accountVOList);
+
+        UsageVO usageVO = new UsageVO();
+        usageVO.setQuotaCalculated(0);
+        List<UsageVO> usageVOList = new ArrayList<UsageVO>();
+        usageVOList.add(usageVO);
+        Pair<List<? extends UsageVO>, Integer> usageRecords = new Pair<List<? extends UsageVO>, Integer>(usageVOList, usageVOList.size());
+        Mockito.when(usageDao.getUsageRecordsPendingQuotaAggregation(Mockito.anyLong(), Mockito.anyLong())).thenReturn(usageRecords);
+
+        QuotaUsageVO quotaUsageVO = new QuotaUsageVO();
+        quotaUsageVO.setAccountId(2L);
+        List<QuotaUsageVO> quotaListForAccount = new ArrayList<>();
+        quotaListForAccount.add(quotaUsageVO);
+        Mockito.doReturn(quotaListForAccount).when(quotaManager).aggregatePendingQuotaRecordsForAccount(Mockito.eq(accountVO), Mockito.eq(usageRecords));
+        Mockito.doNothing().when(quotaManager).processQuotaBalanceForAccount(Mockito.eq(accountVO), Mockito.eq(quotaListForAccount));
+
+        assertTrue(quotaManager.calculateQuotaUsage());
+    }
+
+    @Test
+    public void testAggregatePendingQuotaRecordsForAccount() {
+        AccountVO accountVO = new AccountVO();
+        accountVO.setId(2L);
+        accountVO.setDomainId(1L);
+        accountVO.setType(Account.ACCOUNT_TYPE_NORMAL);
+
+        UsageVO usageVO = new UsageVO();
+        usageVO.setQuotaCalculated(0);
+        usageVO.setUsageType(UsageTypes.ALLOCATED_VM);
+        List<UsageVO> usageVOList = new ArrayList<UsageVO>();
+        usageVOList.add(usageVO);
+        Pair<List<? extends UsageVO>, Integer> usageRecords = new Pair<List<? extends UsageVO>, Integer>(usageVOList, usageVOList.size());
+
+        QuotaUsageVO quotaUsageVO = new QuotaUsageVO();
+        quotaUsageVO.setAccountId(2L);
+        Mockito.doReturn(quotaUsageVO).when(quotaManager).updateQuotaAllocatedVMUsage(Mockito.eq(usageVO), Mockito.any(BigDecimal.class));
+
+        assertTrue(quotaManager.aggregatePendingQuotaRecordsForAccount(accountVO, new Pair<List<? extends UsageVO>, Integer>(null, 0)).size() == 0);
+        assertTrue(quotaManager.aggregatePendingQuotaRecordsForAccount(accountVO, usageRecords).size() == 1);
+    }
+
+    @Test
+    public void testUpdateQuotaRecords() {
+        UsageVO usageVO = new UsageVO();
+        usageVO.setId(100L);
+        usageVO.setQuotaCalculated(0);
+        usageVO.setUsageType(UsageTypes.NETWORK_BYTES_SENT);
+        usageVO.setRawUsage(9000000000.0);
+        usageVO.setSize(1010101010L);
+
+        QuotaTariffVO tariffVO = new QuotaTariffVO();
+        tariffVO.setCurrencyValue(new BigDecimal(1));
+        Mockito.when(quotaTariffDao.findTariffPlanByUsageType(Mockito.anyInt(), Mockito.any(Date.class))).thenReturn(tariffVO);
+
+        QuotaUsageVO qu = quotaManager.updateQuotaNetwork(usageVO, UsageTypes.NETWORK_BYTES_SENT);
+        assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
+        qu = quotaManager.updateQuotaAllocatedVMUsage(usageVO, new BigDecimal(0.5));
+        assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
+        qu = quotaManager.updateQuotaDiskUsage(usageVO, new BigDecimal(0.5), UsageTypes.VOLUME);
+        assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
+        qu = quotaManager.updateQuotaRaw(usageVO, new BigDecimal(0.5), UsageTypes.VPN_USERS);
+        assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
+
+        Mockito.verify(quotaUsageDao, Mockito.times(4)).persistQuotaUsage(Mockito.any(QuotaUsageVO.class));
+        Mockito.verify(usageDao, Mockito.times(4)).persistUsage(Mockito.any(UsageVO.class));
+    }
+
+    @Test
+    public void testProcessQuotaBalanceForAccount() {
+        Date now = new Date();
+        AccountVO accountVO = new AccountVO();
+        accountVO.setId(2L);
+        accountVO.setDomainId(1L);
+        accountVO.setType(Account.ACCOUNT_TYPE_NORMAL);
+
+        QuotaUsageVO quotaUsageVO = new QuotaUsageVO();
+        quotaUsageVO.setAccountId(2L);
+        quotaUsageVO.setStartDate(new Date(now.getTime()));
+        quotaUsageVO.setEndDate(new Date(now.getTime()));
+        List<QuotaUsageVO> quotaListForAccount = new ArrayList<>();
+        quotaListForAccount.add(quotaUsageVO);
+
+        quotaManager.processQuotaBalanceForAccount(accountVO, quotaListForAccount);
+        Mockito.verify(quotaAcc, Mockito.times(1)).persistQuotaAccount(Mockito.any(QuotaAccountVO.class));
+    }
+
+}


Mime
View raw message