diff --git a/client/pom.xml b/client/pom.xml
index 13e1411b971..a3ae8edb4ab 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -356,6 +356,11 @@
cloud-plugin-network-globodns
${project.version}
+
+ org.apache.cloudstack
+ cloud-plugin-database-quota
+ ${project.version}
+
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index a66a3dce486..82817a538b6 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -781,3 +781,6 @@ listOpenDaylightControllers=1
### GloboDNS commands
addGloboDnsHost=1
+
+### Quota Service
+listQuotaConfigurations=15
diff --git a/plugins/database/quota/pom.xml b/plugins/database/quota/pom.xml
new file mode 100644
index 00000000000..046a9f6cc1b
--- /dev/null
+++ b/plugins/database/quota/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+ cloud-plugin-database-quota
+ Apache CloudStack Plugin - Quota Service
+
+ org.apache.cloudstack
+ cloudstack-plugins
+ 4.5.2-SNAPSHOT
+ ../../pom.xml
+
+
+
+
+ org.apache.cloudstack
+ cloud-api
+ ${project.version}
+
+
+ org.apache.cloudstack
+ cloud-utils
+ ${project.version}
+
+
+ mysql
+ mysql-connector-java
+ provided
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ -Xmx1024m
+
+ org/apache/cloudstack/discovery/integration/*
+
+
+
+
+
+
diff --git a/plugins/database/quota/resources/META-INF/cloudstack/quota/module.properties b/plugins/database/quota/resources/META-INF/cloudstack/quota/module.properties
new file mode 100644
index 00000000000..7332f151828
--- /dev/null
+++ b/plugins/database/quota/resources/META-INF/cloudstack/quota/module.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+name=quota
+parent=api
diff --git a/plugins/database/quota/resources/META-INF/cloudstack/quota/spring-quota-context.xml b/plugins/database/quota/resources/META-INF/cloudstack/quota/spring-quota-context.xml
new file mode 100644
index 00000000000..4c608b45bd8
--- /dev/null
+++ b/plugins/database/quota/resources/META-INF/cloudstack/quota/spring-quota-context.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/command/ListQuotaConfigurationsCmd.java b/plugins/database/quota/src/org/apache/cloudstack/api/command/ListQuotaConfigurationsCmd.java
new file mode 100644
index 00000000000..53200faea57
--- /dev/null
+++ b/plugins/database/quota/src/org/apache/cloudstack/api/command/ListQuotaConfigurationsCmd.java
@@ -0,0 +1,99 @@
+//Licensed to the Apache Software Foundation (ASF) under one
+//or more contributor license agreements. See the NOTICE file
+//distributed with this work for additional information
+//regarding copyright ownership. The ASF licenses this file
+//to you under the Apache License, Version 2.0 (the
+//"License"); you may not use this file except in compliance
+//with the License. You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing,
+//software distributed under the License is distributed on an
+//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+//KIND, either express or implied. See the License for the
+//specific language governing permissions and limitations
+//under the License.
+package org.apache.cloudstack.api.command;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.QuotaConfigurationResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.quota.QuotaConfigurationVO;
+import org.apache.cloudstack.quota.QuotaManager;
+
+import com.cloud.user.Account;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listQuotaConfigurations", responseObject = QuotaConfigurationResponse.class, description = "Lists all Quota and Usage configurations", since = "4.2.0",
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class ListQuotaConfigurationsCmd extends BaseListCmd {
+
+ public static final Logger s_logger = Logger
+ .getLogger(ListQuotaConfigurationsCmd.class.getName());
+
+ private static final String s_name = "quotaconfigurationresponse";
+
+ @Inject
+ private QuotaManager _quotaManager;
+
+ @Parameter(name = "usageType", type = CommandType.STRING, required = false, description = "Usage type of the resource")
+ private String _usageType;
+
+
+ public ListQuotaConfigurationsCmd() {
+ super();
+ }
+
+
+ public ListQuotaConfigurationsCmd(final QuotaManager quotaManager) {
+ super();
+ _quotaManager = quotaManager;
+ }
+
+ @Override
+ public void execute() {
+ final Pair, Integer> result = _quotaManager.listConfigurations(this);
+
+ final List responses = new ArrayList();
+ for (final QuotaConfigurationVO resource : result.first()) {
+ final QuotaConfigurationResponse configurationResponse = _quotaManager.createQuotaConfigurationResponse(resource);
+ configurationResponse.setObjectName("QuotaConfiguration");
+ responses.add(configurationResponse);
+ }
+
+ final ListResponse response = new ListResponse();
+ response.setResponses(responses, responses.size());
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ public String getUsageType() {
+ return _usageType;
+ }
+
+
+ public void setUsageType(String usageType) {
+ this._usageType = usageType;
+ }
+
+
+}
diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaStatementCmd.java b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaStatementCmd.java
new file mode 100644
index 00000000000..f349eba1038
--- /dev/null
+++ b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaStatementCmd.java
@@ -0,0 +1,96 @@
+//Licensed to the Apache Software Foundation (ASF) under one
+//or more contributor license agreements. See the NOTICE file
+//distributed with this work for additional information
+//regarding copyright ownership. The ASF licenses this file
+//to you under the Apache License, Version 2.0 (the
+//"License"); you may not use this file except in compliance
+//with the License. You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing,
+//software distributed under the License is distributed on an
+//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+//KIND, either express or implied. See the License for the
+//specific language governing permissions and limitations
+//under the License.
+package org.apache.cloudstack.api.command;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.quota.QuotaManager;
+import org.apache.cloudstack.api.response.QuotaStatementResponse;
+
+import com.cloud.user.Account;
+
+@APICommand(name = "quotaStatement", responseObject = QuotaStatementResponse.class, description = "Create a quota statement", since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+public class QuotaStatementCmd extends BaseListCmd {
+
+ public static final Logger s_logger = Logger
+ .getLogger(QuotaStatementCmd.class.getName());
+
+ private static final String s_name = "quotastatementresponse";
+
+ @Inject
+ private QuotaManager _quotaManager;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "Optional, Account Id for which statement needs to be generated")
+ private String accountName;
+
+ @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "Optional, If domain Id is given and the caller is domain admin then the statement is generated for domain.")
+ private Long domainId;
+
+
+ public QuotaStatementCmd() {
+ super();
+ }
+
+
+ public QuotaStatementCmd(final QuotaManager quotaManager) {
+ super();
+ _quotaManager = quotaManager;
+ }
+
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ Long accountId = _accountService.finalyzeAccountId(accountName, domainId, null, true);
+ if (accountId == null) {
+ return CallContext.current().getCallingAccount().getId();
+ }
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+
+ @Override
+ public void execute() {
+ /**final Pair, Integer> result = _quotaManager.listConfigurations(this);
+
+ final List responses = new ArrayList();
+ for (final QuotaConfigurationVO resource : result.first()) {
+ final QuotaStatementResponse configurationResponse = _quotaManager.createQuotaConfigurationResponse(resource);
+ configurationResponse.setObjectName("QuotaConfiguration");
+ responses.add(configurationResponse);
+ }**/
+
+ final ListResponse response = new ListResponse();
+ //response.setResponses(responses, responses.size());
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+
+
+}
diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaConfigurationResponse.java b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaConfigurationResponse.java
new file mode 100644
index 00000000000..0e34988c8fd
--- /dev/null
+++ b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaConfigurationResponse.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.api.response;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+
+public class QuotaConfigurationResponse extends BaseResponse {
+
+ @SerializedName("usageType")
+ @Param(description = "usageType")
+ private String usageType;
+
+ @SerializedName("usageUnit")
+ @Param(description = "usageUnit")
+ private String usageUnit;
+
+ @SerializedName("usageDiscriminator")
+ @Param(description = "usageDiscriminator")
+ private String usageDiscriminator;
+
+ @SerializedName("currencyValue")
+ @Param(description = "currencyValue")
+ private int currencyValue;
+
+ @SerializedName("include")
+ @Param(description = "include")
+ private int include;
+
+ @SerializedName("description")
+ @Param(description = "description")
+ private String description;
+
+
+ public QuotaConfigurationResponse() {
+ super();
+ }
+
+ public QuotaConfigurationResponse(final String usageType) {
+ super();
+ this.usageType = usageType;
+ }
+
+ public String getUsageType() {
+ return usageType;
+ }
+
+ public void setUsageType(String usageType) {
+ this.usageType = usageType;
+ }
+
+ 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 int getCurrencyValue() {
+ return currencyValue;
+ }
+
+ public void setCurrencyValue(int currencyValue) {
+ this.currencyValue = currencyValue;
+ }
+
+ public int getInclude() {
+ return include;
+ }
+
+ public void setInclude(int include) {
+ this.include = include;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+}
diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaStatementResponse.java b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaStatementResponse.java
new file mode 100644
index 00000000000..e0598a8df6e
--- /dev/null
+++ b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaStatementResponse.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.api.response;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+
+public class QuotaStatementResponse extends BaseResponse {
+
+ @SerializedName("usageType")
+ @Param(description = "usageType")
+ private String usageType;
+
+ @SerializedName("usageUnit")
+ @Param(description = "usageUnit")
+ private String usageUnit;
+
+ @SerializedName("usageDiscriminator")
+ @Param(description = "usageDiscriminator")
+ private String usageDiscriminator;
+
+ @SerializedName("currencyValue")
+ @Param(description = "currencyValue")
+ private int currencyValue;
+
+ @SerializedName("include")
+ @Param(description = "include")
+ private int include;
+
+ @SerializedName("description")
+ @Param(description = "description")
+ private String description;
+
+
+ public QuotaStatementResponse() {
+ super();
+ }
+
+ public QuotaStatementResponse(final String usageType) {
+ super();
+ this.usageType = usageType;
+ }
+
+ public String getUsageType() {
+ return usageType;
+ }
+
+ public void setUsageType(String usageType) {
+ this.usageType = usageType;
+ }
+
+ 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 int getCurrencyValue() {
+ return currencyValue;
+ }
+
+ public void setCurrencyValue(int currencyValue) {
+ this.currencyValue = currencyValue;
+ }
+
+ public int getInclude() {
+ return include;
+ }
+
+ public void setInclude(int include) {
+ this.include = include;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+}
diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaConfigurationVO.java b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaConfigurationVO.java
new file mode 100644
index 00000000000..fd685b0ac70
--- /dev/null
+++ b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaConfigurationVO.java
@@ -0,0 +1,150 @@
+//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 javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+@Entity
+@Table(name = "quota_configuration")
+public class QuotaConfigurationVO implements InternalIdentity {
+ /**
+ * enable.quota.service: Enable quota service by default all of this
+ * functionality is disabled. quota.period.type : Quota period type: 1 for
+ * every x days, 2 for certain day of the month, 3 for yearly on activation
+ * day - default usage reporting cycle quota.period.config : The value for
+ * the above quota period type quota.activity.generate : Set “Y” to enable a
+ * detailed log of the quota usage, rating and billing activity, on daily
+ * basis. Valid values (“Y”, “N”); record.outgoingEmail: Boolean, yes means
+ * all the emails sent out will be stored in local DB, by default it is no.
+ * quota.enable : enable the usage quota enforcement quota.currencySymbol :
+ * The symbol for the currency in use to measure usage. quota.criticalLimit:
+ * A limit when it is reached user is sent and alert.
+ * quota.incrementalLimit: A incremental limit that is added to
+ * criticalLimit in this increments, when breached a email is send to the
+ * user with details.
+ * */
+
+ private static final long serialVersionUID = -7117933766387653203L;
+
+ @Id
+ @Column(name = "id")
+ private Long id;
+
+ @Column(name = "usage_type")
+ private String usageType;
+
+ @Column(name = "usage_unit")
+ private String usageUnit;
+
+ @Column(name = "usage_discriminator")
+ private String usageDiscriminator;
+
+ @Column(name = "currency_value")
+ private int currencyValue;
+
+ @Column(name = "include")
+ private int include;
+
+ @Column(name = "description")
+ private String description;
+
+
+ public QuotaConfigurationVO() {
+ }
+
+
+ public QuotaConfigurationVO(final String usagetype, final String usageunit, final String usagediscriminator, final int currencyvalue, final int include, final String description) {
+ this.usageType = usagetype;
+ this.usageUnit = usageunit;
+ this.usageDiscriminator = usagediscriminator;
+ this.currencyValue = currencyvalue;
+ this.include = include;
+ this.description = description;
+ }
+
+
+ public String getUsageType() {
+ return usageType;
+ }
+
+
+ public void setUsageType(String usageType) {
+ this.usageType = usageType;
+ }
+
+
+ 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 int getCurrencyValue() {
+ return currencyValue;
+ }
+
+
+ public void setCurrencyValue(int currencyValue) {
+ this.currencyValue = currencyValue;
+ }
+
+
+ public int getInclude() {
+ return include;
+ }
+
+
+ public void setInclude(int include) {
+ this.include = include;
+ }
+
+
+ public String getDescription() {
+ return description;
+ }
+
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+
+ @Override
+ public long getId() {
+ // TODO Auto-generated method stub
+ return this.id;
+ }
+}
\ No newline at end of file
diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManager.java b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManager.java
new file mode 100644
index 00000000000..cf29064323e
--- /dev/null
+++ b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManager.java
@@ -0,0 +1,33 @@
+//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 java.util.List;
+
+import org.apache.cloudstack.api.command.ListQuotaConfigurationsCmd;
+import org.apache.cloudstack.api.response.QuotaConfigurationResponse;
+
+import com.cloud.utils.Pair;
+import com.cloud.utils.component.PluggableService;
+
+public interface QuotaManager extends PluggableService {
+
+ Pair, Integer> listConfigurations(ListQuotaConfigurationsCmd cmd);
+
+ QuotaConfigurationResponse createQuotaConfigurationResponse(QuotaConfigurationVO configuration);
+
+}
diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java
new file mode 100644
index 00000000000..8a4fbd4f65b
--- /dev/null
+++ b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java
@@ -0,0 +1,80 @@
+//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 java.util.ArrayList;
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.command.ListQuotaConfigurationsCmd;
+import org.apache.cloudstack.api.response.QuotaConfigurationResponse;
+import org.apache.cloudstack.quota.dao.QuotaConfigurationDao;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.utils.Pair;
+
+@Component
+@Local(value = QuotaManager.class)
+public class QuotaManagerImpl implements QuotaManager {
+ private static final Logger s_logger = Logger.getLogger(QuotaManagerImpl.class.getName());
+
+
+ @Inject
+ private QuotaConfigurationDao _quotaConfigurationDao;
+
+
+
+ public QuotaManagerImpl() {
+ super();
+ }
+
+ public QuotaManagerImpl(final QuotaConfigurationDao quotaConfigurationDao) {
+ super();
+ _quotaConfigurationDao = quotaConfigurationDao;
+ }
+
+
+ @Override
+ public List> getCommands() {
+ final List> cmdList = new ArrayList>();
+ cmdList.add(ListQuotaConfigurationsCmd.class);
+ return cmdList;
+ }
+
+ @Override
+ public Pair, Integer> listConfigurations(final ListQuotaConfigurationsCmd cmd) {
+ final Pair, Integer> result = _quotaConfigurationDao.searchConfigurations();
+ return result;
+ }
+
+
+ @Override
+ public QuotaConfigurationResponse createQuotaConfigurationResponse(final QuotaConfigurationVO configuration) {
+ final QuotaConfigurationResponse response = new QuotaConfigurationResponse();
+ response.setUsageType(configuration.getUsageType());
+ response.setUsageUnit(configuration.getUsageUnit());
+ response.setUsageDiscriminator(configuration.getUsageDiscriminator());
+ response.setCurrencyValue(configuration.getCurrencyValue());
+ response.setInclude(configuration.getInclude());
+ response.setDescription(configuration.getDescription());
+ return response;
+ }
+
+}
diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/dao/QuotaConfigurationDao.java b/plugins/database/quota/src/org/apache/cloudstack/quota/dao/QuotaConfigurationDao.java
new file mode 100644
index 00000000000..324e7d9e89e
--- /dev/null
+++ b/plugins/database/quota/src/org/apache/cloudstack/quota/dao/QuotaConfigurationDao.java
@@ -0,0 +1,32 @@
+//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.List;
+
+import org.apache.cloudstack.quota.QuotaConfigurationVO;
+
+import com.cloud.utils.Pair;
+import com.cloud.utils.db.GenericDao;
+
+public interface QuotaConfigurationDao extends GenericDao {
+
+ QuotaConfigurationVO findByUsageType(String usageType);
+
+ Pair, Integer> searchConfigurations();
+
+}
diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/dao/QuotaConfigurationDaoImpl.java b/plugins/database/quota/src/org/apache/cloudstack/quota/dao/QuotaConfigurationDaoImpl.java
new file mode 100644
index 00000000000..eafc9eace99
--- /dev/null
+++ b/plugins/database/quota/src/org/apache/cloudstack/quota/dao/QuotaConfigurationDaoImpl.java
@@ -0,0 +1,63 @@
+//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.List;
+
+import javax.ejb.Local;
+
+import org.springframework.stereotype.Component;
+import org.apache.cloudstack.quota.QuotaConfigurationVO;
+
+import com.cloud.utils.Pair;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+@Local(value = {QuotaConfigurationDao.class})
+public class QuotaConfigurationDaoImpl extends GenericDaoBase implements QuotaConfigurationDao {
+ private final SearchBuilder searchUsageType;
+ private final SearchBuilder listAllIncludedUsageType;
+
+ public QuotaConfigurationDaoImpl() {
+ super();
+ searchUsageType = createSearchBuilder();
+ searchUsageType.and("usage_type", searchUsageType.entity().getUsageType(), SearchCriteria.Op.EQ);
+ searchUsageType.done();
+
+ listAllIncludedUsageType = createSearchBuilder();
+ listAllIncludedUsageType.and("include", listAllIncludedUsageType.entity().getInclude(), SearchCriteria.Op.EQ);
+ listAllIncludedUsageType.done();
+ }
+
+ @Override
+ public QuotaConfigurationVO findByUsageType(final String usageType) {
+ final SearchCriteria sc = searchUsageType.create();
+ sc.setParameters("usage_type", usageType);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public Pair, Integer> searchConfigurations() {
+ final SearchCriteria sc = listAllIncludedUsageType.create();
+ sc.setParameters("include", 1);
+ return searchAndCount(sc, null);
+ }
+
+
+}
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 6c826600c48..0c7c2fcda9a 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -90,6 +90,7 @@
network-elements/internal-loadbalancer
network-elements/vxlan
network-elements/globodns
+ database/quota
diff --git a/setup/db/db/schema-451to452.sql b/setup/db/db/schema-451to452.sql
index 5c89008a83e..cdf6e5b1b6b 100644
--- a/setup/db/db/schema-451to452.sql
+++ b/setup/db/db/schema-451to452.sql
@@ -19,6 +19,8 @@
-- Schema upgrade from 4.5.1 to 4.5.2;
--;
+-- SAML
+
DELETE FROM `cloud`.`configuration` WHERE name like 'saml%';
ALTER TABLE `cloud`.`user` ADD COLUMN `external_entity` text DEFAULT NULL COMMENT "reference to external federation entity";
@@ -33,3 +35,49 @@ CREATE TABLE `cloud`.`saml_token` (
PRIMARY KEY (`id`),
CONSTRAINT `fk_saml_token__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- Quota Configuration
+
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.enable.service' , 'true', 'false', 'Enable or Disable Quota service');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.period.type' , '2', '2', 'Quota period type: 1 for every x days, 2 for certain day of the month, 3 for yearly on activation day - default quota usage reporting cycle');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.period.config' , '15', '15', 'The period config in number of days for the quota period type');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.activity.generate' , 'true', 'false', 'Set true to enable a detailed log of the quota usage, rating and billing activity, on daily basis. Valid values (true, false)');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.email.outgoing.record' , 'true', 'false', 'true means all the emails sent out will be stored in local DB, by default it is false');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.enable.enforcement' , 'true', 'false', ' Enable the usage quota enforcement, i.e. on true exceeding quota the respective account will be locked.');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.currency.symbol' , 'R', 'C', ' The symbol for the currency in use to measure usage.');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.limit.critical' , '80', '80', 'A percentage limit for quota when it is reached user is sent and alert.');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.limit.increment' , '5', '5', 'A percentage incremental limit that is added to criticalLimit in this increments, when breached a email is send to the user with details');
+
+-- Quota Emailer
+
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.usage.smtp.host' , '', '', 'SMTP host to for email');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.usage.smtp.connection.timeout' , '60', '60', 'SMTP server timeout in seconds');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.usage.smtp.user' , '', '', 'SMTP user');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.usage.smtp.password' , '', '', 'SMTP Password');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.usage.smtp.port' , '', '', 'SMTP port');
+INSERT IGNORE INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `value`, `default_value`, `description`) VALUES ('Advanced', 'DEFAULT', 'QuotaService', 'quota.usage.smtp.useAuth' , '', '', 'SMTP Auth type');
+
+CREATE TABLE `cloud`.`quota_configuration` (
+ `id` bigint unsigned NOT NULL auto_increment COMMENT 'id',
+ `usage_type` varchar(255) NOT NULL COMMENT 'usage type',
+ `usage_unit` varchar(255) NOT NULL COMMENT 'usage type',
+ `usage_discriminator` varchar(255) NOT NULL COMMENT 'usage type',
+ `currency_value` varchar(255) NOT NULL COMMENT 'usage type',
+ `include` BOOLEAN NOT NULL COMMENT 'usage type',
+ `description` varchar(255) NOT NULL COMMENT 'usage type',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('RUNNING_VM', 'Compute-Hours', '', '5' , '1', 'Quota mapping for running VM');
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('ALLOCATED_VM', 'Compute-Hours', '', '1' , '1', 'Quota mapping for running VM');
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('IP_ADDRESS', 'IP-Hours', '', '0.1' , '1', 'Quota mapping for running VM');
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('NETWORK_BYTES_SENT', 'GB', '', '1' , '1', 'Quota mapping for running VM');
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('NETWORK_BYTES_RECEIVED', 'GB', '', '1' , '1', 'Quota mapping for running VM');
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('VOLUME', 'GB-Month', '', '5' , '1', 'Quota mapping for running VM');
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('TEMPLATE', 'GB-Month', '', '5' , '1', 'Quota mapping for running VM');
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('ISO', 'GB-Month', '', '5' , '1', 'Quota mapping for running VM');
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('SNAPSHOT', 'GB-Month', '', '5' , '1', 'Quota mapping for running VM');
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('LOAD_BALANCER_POLICY', 'Policy-Hours', '', '5' , '0', 'Quota mapping for running VM');
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('PORT_FORWARDING_RULE', 'Policy-Hours', '', '5' , '0', 'Quota mapping for running VM');
+INSERT IGNORE INTO `cloud`.`quota_configuration` (`usage_type`, `usage_unit`, `usage_discriminator`, `currency_value`, `include`, `description`) VALUES ('NETWORK_OFFERING', 'Policy-Hours', '', '5' , '0', 'Quota mapping for running VM');
diff --git a/ui/scripts/globalSettings.js b/ui/scripts/globalSettings.js
index 34d65a2a593..ad0fecaa358 100644
--- a/ui/scripts/globalSettings.js
+++ b/ui/scripts/globalSettings.js
@@ -100,6 +100,154 @@
}
}
},
+ quotaConfiguration: {
+ type: 'select',
+ title: 'label.quota.configuration',
+ listView: {
+ id: 'quota',
+ label: 'label.quota.configuration',
+ fields: {
+ usageType: {
+ label: 'label.usage.type'
+ },
+ usageUnit: {
+ label: 'label.usgae.unit'
+ },
+ currencyValue: {
+ label: 'label.quota.value'
+ },
+ description: {
+ label: 'label.quota.description'
+ }
+
+ },
+ dataProvider: function(args) {
+ var data = {};
+ listViewDataProvider(args, data);
+ $.ajax({
+ url: createURL('listQuotaConfigurations'),
+ data: data,
+ success: function(json) {
+ var items = json.quotaconfigurationresponse.QuotaConfiguration;
+ args.response.success({
+ data: items
+ });
+ },
+ error: function(data) {
+ args.response.error(parseXMLHttpResponse(data));
+ }
+ });
+ },
+ detailView: {
+ name: 'label.details',
+ actions: {
+ remove: {
+ label: 'label.remove.quota',
+ messages: {
+ notification: function(args) {
+ return 'label.remove.quota';
+ },
+ confirm: function() {
+ return 'message.remove.quota';
+ }
+ },
+ action: function(args) {
+ $.ajax({
+ url: createURL("deleteQuotaConfiguration&hostname=" + args.context.quotaConfiguration[0].hostname),
+ success: function(json) {
+ args.response.success();
+ }
+ });
+ $(window).trigger('cloudStack.fullRefresh');
+ }
+ }
+ },
+ tabs: {
+ details: {
+ title: 'label.quota.configuration',
+ fields: [{
+ usageType: {
+ label: 'label.usage.type'
+ },
+ usageUnit: {
+ label: 'label.usgae.unit'
+ },
+ currencyValue: {
+ label: 'label.quota.value'
+ },
+ description: {
+ label: 'label.quota.description'
+ }
+ }],
+ dataProvider: function(args) {
+ var items = [];
+ console.log(args);
+ $.ajax({
+ url: createURL("listQuotaConfigurations&hostname=" + args.context.quotaConfiguration[0].hostname),
+ dataType: "json",
+ async: true,
+ success: function(json) {
+ var item = json.quotaconfigurationresponse.QuotaConfiguration;
+ args.response.success({
+ data: item[0]
+ });
+ }
+ });
+ }
+ }
+ }
+ },
+ actions: {
+ add: {
+ label: 'label.configure.quota',
+ messages: {
+ confirm: function(args) {
+ return 'message.configure.quota';
+ },
+ notification: function(args) {
+ return 'label.configure.quota';
+ }
+ },
+ createForm: {
+ title: 'label.configure.quota',
+ fields: {
+ hostname: {
+ label: 'label.host.name',
+ validation: {
+ required: true
+ }
+ },
+ port: {
+ label: 'label.port',
+ validation: {
+ required: true
+ }
+ }
+ }
+ },
+ action: function(args) {
+ var array = [];
+ array.push("&hostname=" + todb(args.data.hostname));
+ array.push("&port=" + todb(args.data.port));;
+ $.ajax({
+ url: createURL("addQuotaConfiguration" + array.join("")),
+ dataType: "json",
+ async: true,
+ success: function(json) {
+ var items = json.quotaconfigurationresponse.QuotaAddConfiguration;
+ args.response.success({
+ data: items
+ });
+ },
+ error: function(json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+ });
+ }
+ }
+ }
+ }
+ },
ldapConfiguration: {
type: 'select',
title: 'label.ldap.configuration',