mirror of https://github.com/apache/cloudstack.git
Improve Quota Statement (#10506)
* Improve Quota Statement * Removes unused import * Fix QuotaUsageJoinDao, QuotaResponseBuilderImpl, QuotaServiceImpl e QuotaServiceImplTest * Reorganize imports * Updates QuotaStatementCmd responseBuilder scope to default * Fix log4j syntax * Address reviews + other improvements * Add missing SQL scripts and injections * Change accountid and domainid logic + add unit tests * Rename QuotaUsageDetail to QuotaTariffUsage * Fix out of bounds exception --------- Co-authored-by: Julien Hervot de Mattos Vaz <julien.vaz@scclouds.com.br> Co-authored-by: Fabricio Duarte <fabricio.duarte.jr@gmail.com>
This commit is contained in:
parent
089eb36e47
commit
a73cc9a22c
|
|
@ -157,6 +157,7 @@ public class ApiConstants {
|
|||
public static final String CUSTOM_ID = "customid";
|
||||
public static final String CUSTOM_ACTION_ID = "customactionid";
|
||||
public static final String CUSTOM_JOB_ID = "customjobid";
|
||||
public static final String CURRENCY = "currency";
|
||||
public static final String CURRENT_START_IP = "currentstartip";
|
||||
public static final String CURRENT_END_IP = "currentendip";
|
||||
public static final String ENCRYPT = "encrypt";
|
||||
|
|
@ -541,6 +542,7 @@ public class ApiConstants {
|
|||
public static final String SESSIONKEY = "sessionkey";
|
||||
public static final String SHOW_CAPACITIES = "showcapacities";
|
||||
public static final String SHOW_REMOVED = "showremoved";
|
||||
public static final String SHOW_RESOURCES = "showresources";
|
||||
public static final String SHOW_RESOURCE_ICON = "showicon";
|
||||
public static final String SHOW_INACTIVE = "showinactive";
|
||||
public static final String SHOW_UNIQUE = "showunique";
|
||||
|
|
@ -606,9 +608,11 @@ public class ApiConstants {
|
|||
public static final String TENANT_NAME = "tenantname";
|
||||
public static final String TOTAL = "total";
|
||||
public static final String TOTAL_SUBNETS = "totalsubnets";
|
||||
public static final String TOTAL_QUOTA = "totalquota";
|
||||
public static final String TYPE = "type";
|
||||
public static final String TRUST_STORE = "truststore";
|
||||
public static final String TRUST_STORE_PASSWORD = "truststorepass";
|
||||
public static final String UNIT = "unit";
|
||||
public static final String URL = "url";
|
||||
public static final String USAGE_INTERFACE = "usageinterface";
|
||||
public static final String USED = "used";
|
||||
|
|
@ -1300,6 +1304,8 @@ public class ApiConstants {
|
|||
public static final String OBJECT_LOCKING = "objectlocking";
|
||||
public static final String ENCRYPTION = "encryption";
|
||||
public static final String QUOTA = "quota";
|
||||
public static final String QUOTA_CONSUMED = "quotaconsumed";
|
||||
public static final String QUOTA_USAGE = "quotausage";
|
||||
public static final String ACCESS_KEY = "accesskey";
|
||||
|
||||
public static final String SOURCE_NAT_IP = "sourcenatipaddress";
|
||||
|
|
|
|||
|
|
@ -117,3 +117,13 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','conserve_mode', 'tin
|
|||
|
||||
--- Disable/enable NICs
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.nics','enabled', 'TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''Indicates whether the NIC is enabled or not'' ');
|
||||
|
||||
--- Quota tariff/usage mapping
|
||||
CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_tariff_usage` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`tariff_id` bigint(20) unsigned NOT NULL COMMENT 'ID of the tariff of the Quota usage detail calculated, foreign key to quota_tariff table',
|
||||
`quota_usage_id` bigint(20) unsigned NOT NULL COMMENT 'ID of the aggregation of Quota usage details, foreign key to quota_usage table',
|
||||
`quota_used` decimal(20,8) NOT NULL COMMENT 'Amount of quota used',
|
||||
PRIMARY KEY (`id`),
|
||||
CONSTRAINT `fk_quota_tariff_usage__tariff_id` FOREIGN KEY (`tariff_id`) REFERENCES `cloud_usage`.`quota_tariff` (`id`),
|
||||
CONSTRAINT `fk_quota_tariff_usage__quota_usage_id` FOREIGN KEY (`quota_usage_id`) REFERENCES `cloud_usage`.`quota_usage` (`id`));
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
-- VIEW `cloud_usage`.`quota_usage_view`;
|
||||
|
||||
DROP VIEW IF EXISTS `cloud_usage`.`quota_usage_view`;
|
||||
CREATE VIEW `cloud_usage`.`quota_usage_view` AS
|
||||
SELECT qu.id,
|
||||
qu.usage_item_id,
|
||||
qu.zone_id,
|
||||
qu.account_id,
|
||||
qu.domain_id,
|
||||
qu.usage_type,
|
||||
qu.quota_used,
|
||||
qu.start_date,
|
||||
qu.end_date,
|
||||
cu.usage_id AS resource_id,
|
||||
cu.network_id as network_id,
|
||||
cu.offering_id as offering_id
|
||||
FROM `cloud_usage`.`quota_usage` qu
|
||||
INNER JOIN `cloud_usage`.`cloud_usage` cu ON (cu.id = qu.usage_item_id);
|
||||
|
|
@ -205,6 +205,12 @@ public class SearchCriteria<K> {
|
|||
|
||||
}
|
||||
|
||||
public void setJoinParametersIfNotNull(String joinName, String conditionName, Object... params) {
|
||||
if (ArrayUtils.isNotEmpty(params) && (params.length > 1 || params[0] != null)) {
|
||||
setJoinParameters(joinName, conditionName, params);
|
||||
}
|
||||
}
|
||||
|
||||
public SearchCriteria<?> getJoin(String joinName) {
|
||||
return _joins.get(joinName).getT();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
//Licensed to the Apache Software Foundation (ASF) under one
|
||||
//or more contributor license agreements. See the NOTICE file
|
||||
//distributed with this work for additional information
|
||||
//regarding copyright ownership. The ASF licenses this file
|
||||
//to you under the Apache License, Version 2.0 (the
|
||||
//"License"); you may not use this file except in compliance
|
||||
//with the License. You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing,
|
||||
//software distributed under the License is distributed on an
|
||||
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
//KIND, either express or implied. See the License for the
|
||||
//specific language governing permissions and limitations
|
||||
//under the License.
|
||||
package org.apache.cloudstack.quota.dao;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffUsageVO;
|
||||
import java.util.List;
|
||||
|
||||
public interface QuotaTariffUsageDao extends GenericDao<QuotaTariffUsageVO, Long> {
|
||||
|
||||
void persistQuotaTariffUsage(QuotaTariffUsageVO quotaTariffUsage);
|
||||
|
||||
List<QuotaTariffUsageVO> listQuotaTariffUsages(Long quotaUsageId);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
//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.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffUsageVO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
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 javax.annotation.PostConstruct;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class QuotaTariffUsageDaoImpl extends GenericDaoBase<QuotaTariffUsageVO, Long> implements QuotaTariffUsageDao {
|
||||
private SearchBuilder<QuotaTariffUsageVO> searchQuotaTariffUsages;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
searchQuotaTariffUsages = createSearchBuilder();
|
||||
searchQuotaTariffUsages.and("quotaUsageId", searchQuotaTariffUsages.entity().getQuotaUsageId(), SearchCriteria.Op.EQ);
|
||||
searchQuotaTariffUsages.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void persistQuotaTariffUsage(final QuotaTariffUsageVO quotaTariffUsage) {
|
||||
logger.trace("Persisting quota tariff usage [{}].", quotaTariffUsage);
|
||||
Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<QuotaTariffUsageVO>) status -> persist(quotaTariffUsage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaTariffUsageVO> listQuotaTariffUsages(Long quotaUsageId) {
|
||||
SearchCriteria<QuotaTariffUsageVO> sc = searchQuotaTariffUsages.create();
|
||||
sc.setParameters("quotaUsageId", quotaUsageId);
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<List<QuotaTariffUsageVO>>) status -> listBy(sc));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// 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.QuotaUsageJoinVO;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface QuotaUsageJoinDao extends GenericDao<QuotaUsageJoinVO, Long> {
|
||||
|
||||
List<QuotaUsageJoinVO> findQuotaUsage(Long accountId, Long domainId, Integer usageType, Long resourceId, Long networkId, Long offeringId, Date startDate, Date endDate, Long tariffId);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// 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.GenericDaoBase;
|
||||
import com.cloud.utils.db.JoinBuilder;
|
||||
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 org.apache.cloudstack.quota.vo.QuotaTariffUsageVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageJoinVO;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class QuotaUsageJoinDaoImpl extends GenericDaoBase<QuotaUsageJoinVO, Long> implements QuotaUsageJoinDao {
|
||||
|
||||
private SearchBuilder<QuotaUsageJoinVO> searchQuotaUsages;
|
||||
|
||||
private SearchBuilder<QuotaUsageJoinVO> searchQuotaUsagesJoinTariffUsages;
|
||||
|
||||
@Inject
|
||||
private QuotaTariffUsageDao quotaTariffUsageDao;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
searchQuotaUsages = createSearchBuilder();
|
||||
prepareQuotaUsageSearchBuilder(searchQuotaUsages);
|
||||
searchQuotaUsages.done();
|
||||
|
||||
SearchBuilder<QuotaTariffUsageVO> searchQuotaTariffUsages = quotaTariffUsageDao.createSearchBuilder();
|
||||
searchQuotaTariffUsages.and("tariffId", searchQuotaTariffUsages.entity().getTariffId(), SearchCriteria.Op.EQ);
|
||||
searchQuotaUsagesJoinTariffUsages = createSearchBuilder();
|
||||
prepareQuotaUsageSearchBuilder(searchQuotaUsagesJoinTariffUsages);
|
||||
searchQuotaUsagesJoinTariffUsages.join("searchQuotaTariffUsages", searchQuotaTariffUsages, searchQuotaUsagesJoinTariffUsages.entity().getId(),
|
||||
searchQuotaTariffUsages.entity().getQuotaUsageId(), JoinBuilder.JoinType.INNER);
|
||||
searchQuotaUsagesJoinTariffUsages.done();
|
||||
}
|
||||
|
||||
private void prepareQuotaUsageSearchBuilder(SearchBuilder<QuotaUsageJoinVO> searchBuilder) {
|
||||
searchBuilder.and("accountId", searchBuilder.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and("domainId", searchBuilder.entity().getDomainId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and("usageType", searchBuilder.entity().getUsageType(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and("resourceId", searchBuilder.entity().getResourceId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and("networkId", searchBuilder.entity().getNetworkId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and("offeringId", searchBuilder.entity().getOfferingId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and("startDate", searchBuilder.entity().getStartDate(), SearchCriteria.Op.BETWEEN);
|
||||
searchBuilder.and("endDate", searchBuilder.entity().getEndDate(), SearchCriteria.Op.BETWEEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaUsageJoinVO> findQuotaUsage(Long accountId, Long domainId, Integer usageType, Long resourceId, Long networkId, Long offeringId, Date startDate, Date endDate, Long tariffId) {
|
||||
SearchCriteria<QuotaUsageJoinVO> sc = tariffId == null ? searchQuotaUsages.create() : searchQuotaUsagesJoinTariffUsages.create();
|
||||
|
||||
sc.setParametersIfNotNull("accountId", accountId);
|
||||
sc.setParametersIfNotNull("domainId", domainId);
|
||||
sc.setParametersIfNotNull("usageType", usageType);
|
||||
sc.setParametersIfNotNull("resourceId", resourceId);
|
||||
sc.setParametersIfNotNull("networkId", networkId);
|
||||
sc.setParametersIfNotNull("offeringId", offeringId);
|
||||
|
||||
if (ObjectUtils.allNotNull(startDate, endDate)) {
|
||||
sc.setParameters("startDate", startDate, endDate);
|
||||
sc.setParameters("endDate", startDate, endDate);
|
||||
}
|
||||
|
||||
sc.setJoinParametersIfNotNull("searchQuotaTariffUsages", "tariffId", tariffId);
|
||||
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<List<QuotaUsageJoinVO>>) status -> listBy(sc));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
//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 javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_tariff_usage")
|
||||
public class QuotaTariffUsageVO implements InternalIdentity {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "tariff_id")
|
||||
private Long tariffId;
|
||||
|
||||
@Column(name = "quota_usage_id")
|
||||
private Long quotaUsageId;
|
||||
|
||||
@Column(name = "quota_used")
|
||||
private BigDecimal quotaUsed;
|
||||
|
||||
public QuotaTariffUsageVO() {
|
||||
quotaUsed = new BigDecimal(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Long getTariffId() {
|
||||
return tariffId;
|
||||
}
|
||||
|
||||
public Long getQuotaUsageId() {
|
||||
return quotaUsageId;
|
||||
}
|
||||
|
||||
public BigDecimal getQuotaUsed() {
|
||||
return quotaUsed;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setTariffId(Long tariffId) {
|
||||
this.tariffId = tariffId;
|
||||
}
|
||||
|
||||
public void setQuotaUsageId(Long quotaUsageId) {
|
||||
this.quotaUsageId = quotaUsageId;
|
||||
}
|
||||
|
||||
public void setQuotaUsed(BigDecimal quotaUsed) {
|
||||
this.quotaUsed = quotaUsed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ReflectionToStringBuilder(this, ToStringStyle.JSON_STYLE).toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
//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.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
|
||||
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_usage_view")
|
||||
public class QuotaUsageJoinVO implements InternalIdentity {
|
||||
|
||||
@Id
|
||||
@Column(name = "id", updatable = false, nullable = false)
|
||||
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;
|
||||
|
||||
@Column(name = "resource_id")
|
||||
private Long resourceId = null;
|
||||
|
||||
@Column(name = "network_id")
|
||||
private Long networkId = null;
|
||||
|
||||
@Column(name = "offering_id")
|
||||
private Long offeringId = null;
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public Long getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
public void setResourceId(Long resourceId) {
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
public Long getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public void setNetworkId(Long networkId) {
|
||||
this.networkId = networkId;
|
||||
}
|
||||
|
||||
public Long getOfferingId() {
|
||||
return offeringId;
|
||||
}
|
||||
|
||||
public void setOfferingId(Long offeringId) {
|
||||
this.offeringId = offeringId;
|
||||
}
|
||||
|
||||
public QuotaUsageJoinVO () {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "zoneId", "accountId", "domainId", "usageItemId", "usageType", "quotaUsed", "startDate",
|
||||
"endDate", "resourceId");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
//
|
||||
|
||||
package org.apache.cloudstack.quota.vo;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class QuotaUsageResourceVO {
|
||||
private String uuid;
|
||||
private String name;
|
||||
private Date removed;
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Date getRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
public void setRemoved(Date removed) {
|
||||
this.removed = removed;
|
||||
}
|
||||
|
||||
public boolean isRemoved() {
|
||||
return this.removed != null;
|
||||
}
|
||||
|
||||
public QuotaUsageResourceVO(String uuid, String name, Date removed) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
this.removed = removed;
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,9 @@
|
|||
<bean id="QuotaEmailTemplatesDao"
|
||||
class="org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDaoImpl" />
|
||||
<bean id="QuotaUsageDao" class="org.apache.cloudstack.quota.dao.QuotaUsageDaoImpl" />
|
||||
<bean id="UserVmDetailsDao" class="org.apache.cloudstack.quota.dao.VMInstanceDetailsDaoImpl" />
|
||||
<bean id="QuotaUsageJoinDao" class="org.apache.cloudstack.quota.dao.QuotaUsageJoinDaoImpl"/>
|
||||
<bean id="QuotaTariffUsageDao" class="org.apache.cloudstack.quota.dao.QuotaTariffUsageDaoImpl" />
|
||||
<bean id="UserVmDetailsDao" class="org.apache.cloudstack.quota.dao.VMInstanceDetailsDaoImpl" />
|
||||
|
||||
<bean id="QuotaManager" class="org.apache.cloudstack.quota.QuotaManagerImpl" />
|
||||
<bean id="QuotaAlertManager" class="org.apache.cloudstack.quota.QuotaAlertManagerImpl" />
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
|
@ -28,24 +27,25 @@ import org.apache.cloudstack.api.BaseCmd;
|
|||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.AccountResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.ProjectResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.api.response.QuotaStatementItemResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaStatementResponse;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
@APICommand(name = "quotaStatement", responseObject = QuotaStatementItemResponse.class, description = "Create a quota statement", since = "4.7.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
httpMethod = "GET")
|
||||
@APICommand(name = "quotaStatement", responseObject = QuotaStatementItemResponse.class, description = "Create a Quota statement for the provided Account, Project, or Domain.",
|
||||
since = "4.7.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, httpMethod = "GET")
|
||||
public class QuotaStatementCmd extends BaseCmd {
|
||||
|
||||
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = true, description = "Optional, Account Id for which statement needs to be generated")
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING,
|
||||
description = "Name of the Account for which the Quota statement will be generated. Deprecated, please use accountid instead.")
|
||||
private String accountName;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "Optional, If domain Id is given and the caller is domain admin then the statement is generated for domain.")
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class,
|
||||
description = "ID of the Domain for which the Quota statement will be generated. May be used individually or with account.")
|
||||
private Long domainId;
|
||||
|
||||
@Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, required = true, description = "End of the period of the Quota statement. " +
|
||||
|
|
@ -56,15 +56,25 @@ public class QuotaStatementCmd extends BaseCmd {
|
|||
ApiConstants.PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS)
|
||||
private Date startDate;
|
||||
|
||||
@Parameter(name = ApiConstants.TYPE, type = CommandType.INTEGER, description = "List quota usage records for the specified usage type")
|
||||
@Parameter(name = ApiConstants.TYPE, type = CommandType.INTEGER,
|
||||
description = "Consider only Quota usage records for the specified usage type in the statement.")
|
||||
private Integer usageType;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "List usage records for the specified Account")
|
||||
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class,
|
||||
description = "ID of the Account for which the Quota statement will be generated. Can not be specified with projectid.")
|
||||
private Long accountId;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class,
|
||||
description = "ID of the Project for which the Quota statement will be generated. Can not be specified with accountid.", since = "4.23.0")
|
||||
private Long projectId;
|
||||
|
||||
@Parameter(name = ApiConstants.SHOW_RESOURCES, type = CommandType.BOOLEAN, description = "List the resources of each Quota type in the period.", since = "4.23.0")
|
||||
private boolean showResources;
|
||||
|
||||
@Inject
|
||||
private QuotaResponseBuilder _responseBuilder;
|
||||
QuotaResponseBuilder responseBuilder;
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
|
|
@ -99,43 +109,47 @@ public class QuotaStatementCmd extends BaseCmd {
|
|||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return _responseBuilder.startOfNextDay(endDate == null ? new Date() : new Date(endDate.getTime()));
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate == null ? null : new Date(startDate.getTime());
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public boolean isShowResources() {
|
||||
return showResources;
|
||||
}
|
||||
|
||||
public void setShowResources(boolean showResources) {
|
||||
this.showResources = showResources;
|
||||
}
|
||||
|
||||
public Long getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
if (accountId != null) {
|
||||
return accountId;
|
||||
if (ObjectUtils.allNull(accountId, accountName, projectId)) {
|
||||
return -1;
|
||||
}
|
||||
Account activeAccountByName = _accountService.getActiveAccountByName(accountName, domainId);
|
||||
if (activeAccountByName != null) {
|
||||
return activeAccountByName.getAccountId();
|
||||
}
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
return _accountService.finalizeAccountId(accountId, accountName, domainId, projectId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
List<QuotaUsageVO> quotaUsage = _responseBuilder.getQuotaUsage(this);
|
||||
|
||||
QuotaStatementResponse response = _responseBuilder.createQuotaStatementResponse(quotaUsage);
|
||||
response.setStartDate(startDate == null ? null : new Date(startDate.getTime()));
|
||||
response.setEndDate(endDate == null ? null : new Date(endDate.getTime()));
|
||||
|
||||
QuotaStatementResponse response = responseBuilder.createQuotaStatementResponse(this);
|
||||
response.setStartDate(startDate);
|
||||
response.setEndDate(endDate);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ import org.apache.cloudstack.api.command.QuotaValidateActivationRuleCmd;
|
|||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
|
@ -49,7 +48,7 @@ public interface QuotaResponseBuilder {
|
|||
|
||||
boolean isUserAllowedToSeeActivationRules(User user);
|
||||
|
||||
QuotaStatementResponse createQuotaStatementResponse(List<QuotaUsageVO> quotaUsage);
|
||||
QuotaStatementResponse createQuotaStatementResponse(QuotaStatementCmd cmd);
|
||||
|
||||
QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaUsage, Date startDate, Date endDate);
|
||||
|
||||
|
|
@ -57,8 +56,6 @@ public interface QuotaResponseBuilder {
|
|||
|
||||
QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate);
|
||||
|
||||
List<QuotaUsageVO> getQuotaUsage(QuotaStatementCmd cmd);
|
||||
|
||||
List<QuotaBalanceVO> getQuotaBalance(QuotaBalanceCmd cmd);
|
||||
|
||||
QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Double amount, Long updatedBy, Boolean enforce);
|
||||
|
|
|
|||
|
|
@ -21,13 +21,11 @@ import java.lang.reflect.Field;
|
|||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
|
|
@ -36,6 +34,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
|
@ -43,12 +42,36 @@ import java.util.stream.Collectors;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.event.ActionEvent;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.projects.dao.ProjectDao;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
|
|
@ -94,7 +117,8 @@ import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
|||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaSummaryVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageJoinVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageResourceVO;
|
||||
import org.apache.cloudstack.utils.jsinterpreter.JsInterpreter;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
|
@ -106,18 +130,6 @@ import org.apache.logging.log4j.LogManager;
|
|||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.event.ActionEvent;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
@Component
|
||||
public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
|
|
@ -140,8 +152,6 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
@Inject
|
||||
private AccountDao _accountDao;
|
||||
@Inject
|
||||
private ProjectDao projectDao;
|
||||
@Inject
|
||||
private QuotaAccountDao quotaAccountDao;
|
||||
@Inject
|
||||
private DomainDao domainDao;
|
||||
|
|
@ -159,6 +169,21 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
private JsInterpreterHelper jsInterpreterHelper;
|
||||
@Inject
|
||||
private ApiDiscoveryService apiDiscoveryService;
|
||||
@Inject
|
||||
private IPAddressDao ipAddressDao;
|
||||
@Inject
|
||||
private NetworkDao networkDao;
|
||||
@Inject
|
||||
private NetworkOfferingDao networkOfferingDao;
|
||||
@Inject
|
||||
private SnapshotDao snapshotDao;
|
||||
@Inject
|
||||
private VMInstanceDao vmInstanceDao;
|
||||
@Inject
|
||||
private VMTemplateDao vmTemplateDao;
|
||||
@Inject
|
||||
private VolumeDao volumeDao;
|
||||
|
||||
|
||||
private final Class<?>[] assignableClasses = {GenericPresetVariable.class, ComputingResources.class};
|
||||
|
||||
|
|
@ -393,78 +418,212 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public QuotaStatementResponse createQuotaStatementResponse(final List<QuotaUsageVO> quotaUsage) {
|
||||
if (quotaUsage == null || quotaUsage.isEmpty()) {
|
||||
throw new InvalidParameterValueException("There is no usage data found for period mentioned.");
|
||||
}
|
||||
public QuotaStatementResponse createQuotaStatementResponse(QuotaStatementCmd cmd) {
|
||||
Long accountId = getAccountIdForQuotaStatement(cmd);
|
||||
Long domainId = getDomainIdForQuotaStatement(cmd, accountId);
|
||||
List<QuotaUsageJoinVO> quotaUsages = _quotaService.getQuotaUsage(accountId, null, domainId, cmd.getUsageType(), cmd.getStartDate(), cmd.getEndDate());
|
||||
|
||||
logger.debug("Creating quota statement from [{}] usage records for parameters [{}].", quotaUsages.size(),
|
||||
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(cmd, "accountName", "accountId", "projectId", "domainId", "startDate", "endDate", "usageType", "showResources"));
|
||||
createDummyRecordForEachQuotaTypeIfUsageTypeIsNotInformed(quotaUsages, cmd.getUsageType());
|
||||
|
||||
Map<Integer, List<QuotaUsageJoinVO>> recordsPerUsageTypes = quotaUsages.stream()
|
||||
.sorted(Comparator.comparingInt(QuotaUsageJoinVO::getUsageType))
|
||||
.collect(Collectors.groupingBy(QuotaUsageJoinVO::getUsageType));
|
||||
|
||||
List<QuotaStatementItemResponse> items = new ArrayList<>();
|
||||
recordsPerUsageTypes.forEach((key, value) -> items.add(createStatementItem(key, value, cmd.isShowResources())));
|
||||
|
||||
QuotaStatementResponse statement = new QuotaStatementResponse();
|
||||
|
||||
HashMap<Integer, QuotaTypes> quotaTariffMap = new HashMap<Integer, QuotaTypes>();
|
||||
Collection<QuotaTypes> result = QuotaTypes.listQuotaTypes().values();
|
||||
|
||||
for (QuotaTypes quotaTariff : result) {
|
||||
quotaTariffMap.put(quotaTariff.getQuotaType(), quotaTariff);
|
||||
// add dummy record for each usage type
|
||||
QuotaUsageVO dummy = new QuotaUsageVO(quotaUsage.get(0));
|
||||
dummy.setUsageType(quotaTariff.getQuotaType());
|
||||
dummy.setQuotaUsed(new BigDecimal(0));
|
||||
quotaUsage.add(dummy);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"createQuotaStatementResponse Type=" + quotaUsage.get(0).getUsageType() + " usage=" + quotaUsage.get(0).getQuotaUsed().setScale(2, RoundingMode.HALF_EVEN)
|
||||
+ " rec.id=" + quotaUsage.get(0).getUsageItemId() + " SD=" + quotaUsage.get(0).getStartDate() + " ED=" + quotaUsage.get(0).getEndDate());
|
||||
}
|
||||
|
||||
Collections.sort(quotaUsage, new Comparator<QuotaUsageVO>() {
|
||||
@Override
|
||||
public int compare(QuotaUsageVO o1, QuotaUsageVO o2) {
|
||||
if (o1.getUsageType() == o2.getUsageType()) {
|
||||
return 0;
|
||||
}
|
||||
return o1.getUsageType() < o2.getUsageType() ? -1 : 1;
|
||||
}
|
||||
});
|
||||
|
||||
List<QuotaStatementItemResponse> items = new ArrayList<QuotaStatementItemResponse>();
|
||||
QuotaStatementItemResponse lineitem;
|
||||
int type = -1;
|
||||
BigDecimal usage = new BigDecimal(0);
|
||||
BigDecimal totalUsage = new BigDecimal(0);
|
||||
quotaUsage.add(new QuotaUsageVO());// boundary
|
||||
QuotaUsageVO prev = quotaUsage.get(0);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("createQuotaStatementResponse record count=" + quotaUsage.size());
|
||||
}
|
||||
for (final QuotaUsageVO quotaRecord : quotaUsage) {
|
||||
if (type != quotaRecord.getUsageType()) {
|
||||
if (type != -1) {
|
||||
lineitem = new QuotaStatementItemResponse(type);
|
||||
lineitem.setQuotaUsed(usage);
|
||||
lineitem.setAccountId(prev.getAccountId());
|
||||
lineitem.setDomainId(prev.getDomainId());
|
||||
lineitem.setUsageUnit(quotaTariffMap.get(type).getQuotaUnit());
|
||||
lineitem.setUsageName(quotaTariffMap.get(type).getQuotaName());
|
||||
lineitem.setObjectName("quotausage");
|
||||
items.add(lineitem);
|
||||
totalUsage = totalUsage.add(usage);
|
||||
usage = new BigDecimal(0);
|
||||
}
|
||||
type = quotaRecord.getUsageType();
|
||||
}
|
||||
prev = quotaRecord;
|
||||
usage = usage.add(quotaRecord.getQuotaUsed());
|
||||
}
|
||||
|
||||
statement.setLineItem(items);
|
||||
statement.setTotalQuota(totalUsage);
|
||||
statement.setTotalQuota(items.stream().map(QuotaStatementItemResponse::getQuotaUsed).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
statement.setCurrency(QuotaConfig.QuotaCurrencySymbol.value());
|
||||
statement.setObjectName("statement");
|
||||
|
||||
if (accountId != null) {
|
||||
Account account = _accountDao.findByIdIncludingRemoved(accountId);
|
||||
statement.setAccountId(account.getUuid());
|
||||
statement.setAccountName(account.getAccountName());
|
||||
domainId = account.getDomainId();
|
||||
}
|
||||
if (domainId != null) {
|
||||
DomainVO domain = domainDao.findByIdIncludingRemoved(domainId);
|
||||
statement.setDomainId(domain.getUuid());
|
||||
}
|
||||
|
||||
return statement;
|
||||
}
|
||||
|
||||
protected Long getAccountIdForQuotaStatement(QuotaStatementCmd cmd) {
|
||||
if (Account.Type.NORMAL.equals(CallContext.current().getCallingAccount().getType())) {
|
||||
logger.debug("Limiting the Quota statement for the calling Account, as they are a User Account.");
|
||||
return CallContext.current().getCallingAccountId();
|
||||
}
|
||||
|
||||
long accountId = cmd.getEntityOwnerId();
|
||||
if (accountId != -1) {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
if (cmd.getDomainId() == null) {
|
||||
logger.debug("Limiting the Quota statement for the calling Account, as 'domainid' was not informed.");
|
||||
return CallContext.current().getCallingAccountId();
|
||||
}
|
||||
|
||||
logger.debug("Allowing admin/domain admin to generate the Quota statement for the provided Domain.");
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Long getDomainIdForQuotaStatement(QuotaStatementCmd cmd, Long accountId) {
|
||||
if (accountId != null) {
|
||||
logger.debug("Quota statement is already limited to Account [{}].", accountId);
|
||||
Account account = _accountDao.findByIdIncludingRemoved(accountId);
|
||||
return account.getDomainId();
|
||||
}
|
||||
|
||||
Long domainId = cmd.getDomainId();
|
||||
if (domainId != null) {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
logger.debug("Limiting the Quota statement for the calling Account's Domain.");
|
||||
return CallContext.current().getCallingAccount().getDomainId();
|
||||
}
|
||||
|
||||
protected void createDummyRecordForEachQuotaTypeIfUsageTypeIsNotInformed(List<QuotaUsageJoinVO> quotaUsages, Integer usageType) {
|
||||
if (usageType != null) {
|
||||
logger.debug("As the usage type [{}] was informed as parameter of the API quotaStatement, we will not create dummy records.", usageType);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
for (Integer quotaType : QuotaTypes.listQuotaTypes().keySet()) {
|
||||
QuotaUsageJoinVO dummy = new QuotaUsageJoinVO();
|
||||
dummy.setUsageType(quotaType);
|
||||
dummy.setQuotaUsed(BigDecimal.ZERO);
|
||||
quotaUsages.add(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
protected QuotaStatementItemResponse createStatementItem(int usageType, List<QuotaUsageJoinVO> usageRecords, boolean showResources) {
|
||||
QuotaUsageJoinVO firstRecord = usageRecords.get(0);
|
||||
int type = firstRecord.getUsageType();
|
||||
|
||||
QuotaTypes quotaType = QuotaTypes.listQuotaTypes().get(type);
|
||||
|
||||
QuotaStatementItemResponse item = new QuotaStatementItemResponse(type);
|
||||
item.setQuotaUsed(usageRecords.stream().map(QuotaUsageJoinVO::getQuotaUsed).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
item.setUsageUnit(quotaType.getQuotaUnit());
|
||||
item.setUsageName(quotaType.getQuotaName());
|
||||
|
||||
setStatementItemResources(item, usageType, usageRecords, showResources);
|
||||
return item;
|
||||
}
|
||||
|
||||
protected void setStatementItemResources(QuotaStatementItemResponse statementItem, int usageType, List<QuotaUsageJoinVO> quotaUsageRecords, boolean showResources) {
|
||||
if (!showResources) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<QuotaStatementItemResourceResponse> itemDetails = new ArrayList<>();
|
||||
|
||||
Map<Long, BigDecimal> quotaUsagesValuesAggregatedById = quotaUsageRecords
|
||||
.stream()
|
||||
.filter(quotaUsageJoinVo -> getResourceIdByUsageType(quotaUsageJoinVo, usageType) != null)
|
||||
.collect(Collectors.groupingBy(
|
||||
quotaUsageJoinVo -> getResourceIdByUsageType(quotaUsageJoinVo, usageType),
|
||||
Collectors.reducing(new BigDecimal(0), QuotaUsageJoinVO::getQuotaUsed, BigDecimal::add)
|
||||
));
|
||||
|
||||
for (Map.Entry<Long, BigDecimal> entry : quotaUsagesValuesAggregatedById.entrySet()) {
|
||||
QuotaStatementItemResourceResponse detail = new QuotaStatementItemResourceResponse();
|
||||
|
||||
detail.setQuotaUsed(entry.getValue());
|
||||
|
||||
QuotaUsageResourceVO resource = getResourceFromIdAndType(entry.getKey(), usageType);
|
||||
if (resource != null) {
|
||||
detail.setResourceId(resource.getUuid());
|
||||
detail.setDisplayName(resource.getName());
|
||||
detail.setRemoved(resource.isRemoved());
|
||||
} else {
|
||||
detail.setDisplayName("<untraceable>");
|
||||
|
||||
}
|
||||
itemDetails.add(detail);
|
||||
}
|
||||
statementItem.setResources(itemDetails);
|
||||
}
|
||||
|
||||
protected Long getResourceIdByUsageType(QuotaUsageJoinVO quotaUsageJoinVo, int usageType) {
|
||||
switch (usageType) {
|
||||
case QuotaTypes.NETWORK_BYTES_SENT:
|
||||
case QuotaTypes.NETWORK_BYTES_RECEIVED:
|
||||
return quotaUsageJoinVo.getNetworkId();
|
||||
case QuotaTypes.NETWORK_OFFERING:
|
||||
return quotaUsageJoinVo.getOfferingId();
|
||||
default:
|
||||
return quotaUsageJoinVo.getResourceId();
|
||||
}
|
||||
}
|
||||
|
||||
protected QuotaUsageResourceVO getResourceFromIdAndType(long resourceId, int usageType) {
|
||||
switch (usageType) {
|
||||
case QuotaTypes.ALLOCATED_VM:
|
||||
case QuotaTypes.RUNNING_VM:
|
||||
VMInstanceVO vmInstance = vmInstanceDao.findByIdIncludingRemoved(resourceId);
|
||||
if (vmInstance != null) {
|
||||
return new QuotaUsageResourceVO(vmInstance.getUuid(), vmInstance.getHostName(), vmInstance.getRemoved());
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.VOLUME:
|
||||
case QuotaTypes.VOLUME_SECONDARY:
|
||||
case QuotaTypes.VM_DISK_BYTES_READ:
|
||||
case QuotaTypes.VM_DISK_BYTES_WRITE:
|
||||
case QuotaTypes.VM_DISK_IO_READ:
|
||||
case QuotaTypes.VM_DISK_IO_WRITE:
|
||||
VolumeVO volume = volumeDao.findByIdIncludingRemoved(resourceId);
|
||||
if (volume != null) {
|
||||
return new QuotaUsageResourceVO(volume.getUuid(), volume.getName(), volume.getRemoved());
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.VM_SNAPSHOT_ON_PRIMARY:
|
||||
case QuotaTypes.VM_SNAPSHOT:
|
||||
case QuotaTypes.SNAPSHOT:
|
||||
SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(resourceId);
|
||||
if (snapshot != null) {
|
||||
return new QuotaUsageResourceVO(snapshot.getUuid(), snapshot.getName(), snapshot.getRemoved());
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.NETWORK_BYTES_SENT:
|
||||
case QuotaTypes.NETWORK_BYTES_RECEIVED:
|
||||
NetworkVO network = networkDao.findByIdIncludingRemoved(resourceId);
|
||||
if (network != null) {
|
||||
return new QuotaUsageResourceVO(network.getUuid(), network.getName(), network.getRemoved());
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.TEMPLATE:
|
||||
case QuotaTypes.ISO:
|
||||
VMTemplateVO vmTemplate = vmTemplateDao.findByIdIncludingRemoved(resourceId);
|
||||
if (vmTemplate != null) {
|
||||
return new QuotaUsageResourceVO(vmTemplate.getUuid(), vmTemplate.getName(), vmTemplate.getRemoved());
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.NETWORK_OFFERING:
|
||||
NetworkOfferingVO networkOffering = networkOfferingDao.findByIdIncludingRemoved(resourceId);
|
||||
if (networkOffering != null) {
|
||||
return new QuotaUsageResourceVO(networkOffering.getUuid(), networkOffering.getName(), networkOffering.getRemoved());
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.IP_ADDRESS:
|
||||
IPAddressVO ipAddress = ipAddressDao.findByIdIncludingRemoved(resourceId);
|
||||
if (ipAddress != null) {
|
||||
return new QuotaUsageResourceVO(ipAddress.getUuid(), ipAddress.getName(), ipAddress.getRemoved());
|
||||
}
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<QuotaTariffVO>, Integer> listQuotaTariffPlans(final QuotaTariffListCmd cmd) {
|
||||
Date startDate = cmd.getEffectiveDate();
|
||||
|
|
@ -518,14 +677,14 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
}
|
||||
|
||||
protected void warnQuotaTariffUpdateDeprecatedFields(QuotaTariffUpdateCmd cmd) {
|
||||
String warnMessage = "The parameter 's%s' for API 'quotaTariffUpdate' is no longer needed and it will be removed in future releases.";
|
||||
String warnMessage = "The parameter '{}' for API 'quotaTariffUpdate' is no longer needed and it will be removed in future releases.";
|
||||
|
||||
if (cmd.getStartDate() != null) {
|
||||
logger.warn(String.format(warnMessage,"startdate"));
|
||||
logger.warn(warnMessage, "startdate");
|
||||
}
|
||||
|
||||
if (cmd.getUsageType() != null) {
|
||||
logger.warn(String.format(warnMessage,"usagetype"));
|
||||
logger.warn(warnMessage, "usagetype");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -712,11 +871,6 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
return resp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaUsageVO> getQuotaUsage(QuotaStatementCmd cmd) {
|
||||
return _quotaService.getQuotaUsage(cmd.getAccountId(), cmd.getAccountName(), cmd.getDomainId(), cmd.getUsageType(), cmd.getStartDate(), cmd.getEndDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaBalanceVO> getQuotaBalance(QuotaBalanceCmd cmd) {
|
||||
return _quotaService.findQuotaBalanceVO(cmd.getAccountId(), cmd.getAccountName(), cmd.getDomainId(), cmd.getStartDate(), cmd.getEndDate());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
//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 java.math.BigDecimal;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
|
||||
public class QuotaStatementItemResourceResponse extends BaseResponse {
|
||||
|
||||
@SerializedName(ApiConstants.QUOTA_CONSUMED)
|
||||
@Param(description = "Quota consumed.")
|
||||
private BigDecimal quotaUsed;
|
||||
|
||||
@SerializedName(ApiConstants.RESOURCE_ID)
|
||||
@Param(description = "Resources's ID.")
|
||||
private String resourceId;
|
||||
|
||||
@SerializedName(ApiConstants.DISPLAY_NAME)
|
||||
@Param(description = "Resource's display name.")
|
||||
private String displayName;
|
||||
|
||||
@SerializedName(ApiConstants.REMOVED)
|
||||
@Param(description = "Indicates whether the resource is removed or active.")
|
||||
private boolean removed;
|
||||
|
||||
public void setQuotaUsed(BigDecimal quotaUsed) {
|
||||
this.quotaUsed = quotaUsed;
|
||||
}
|
||||
|
||||
public void setResourceId(String resourceId) {
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public void setRemoved(boolean removed) {
|
||||
this.removed = removed;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,72 +17,41 @@
|
|||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
|
||||
public class QuotaStatementItemResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("type")
|
||||
@Param(description = "Usage type")
|
||||
@SerializedName(ApiConstants.TYPE)
|
||||
@Param(description = "Usage type.")
|
||||
private int usageType;
|
||||
|
||||
@SerializedName("accountid")
|
||||
@Param(description = "Account id")
|
||||
private Long accountId;
|
||||
|
||||
@SerializedName("account")
|
||||
@Param(description = "Account name")
|
||||
private String accountName;
|
||||
|
||||
@SerializedName("domain")
|
||||
@Param(description = "Domain id")
|
||||
private Long domainId;
|
||||
|
||||
@SerializedName("name")
|
||||
@Param(description = "Usage type name")
|
||||
@SerializedName(ApiConstants.NAME)
|
||||
@Param(description = "Name of the Usage type.")
|
||||
private String usageName;
|
||||
|
||||
@SerializedName("unit")
|
||||
@Param(description = "Usage unit")
|
||||
@SerializedName(ApiConstants.UNIT)
|
||||
@Param(description = "Unit of the Usage type.")
|
||||
private String usageUnit;
|
||||
|
||||
@SerializedName("quota")
|
||||
@Param(description = "Quota consumed")
|
||||
@SerializedName(ApiConstants.QUOTA)
|
||||
@Param(description = "Quota consumed.")
|
||||
private BigDecimal quotaUsed;
|
||||
|
||||
@SerializedName(ApiConstants.RESOURCES)
|
||||
@Param(description = "Item's resources.")
|
||||
private List<QuotaStatementItemResourceResponse> resources;
|
||||
|
||||
public QuotaStatementItemResponse(final int usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public String getUsageName() {
|
||||
return usageName;
|
||||
}
|
||||
|
|
@ -112,7 +81,15 @@ public class QuotaStatementItemResponse extends BaseResponse {
|
|||
}
|
||||
|
||||
public void setQuotaUsed(BigDecimal quotaUsed) {
|
||||
this.quotaUsed = quotaUsed.setScale(2, RoundingMode.HALF_EVEN);
|
||||
this.quotaUsed = quotaUsed;
|
||||
}
|
||||
|
||||
public List<QuotaStatementItemResourceResponse> getResources() {
|
||||
return resources;
|
||||
}
|
||||
|
||||
public void setResources(List<QuotaStatementItemResourceResponse> resources) {
|
||||
this.resources = resources;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,56 +18,56 @@ package org.apache.cloudstack.api.response;
|
|||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class QuotaStatementResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("accountid")
|
||||
@Param(description = "Account ID")
|
||||
private Long accountId;
|
||||
@SerializedName(ApiConstants.ACCOUNT_ID)
|
||||
@Param(description = "ID of the Account.")
|
||||
private String accountId;
|
||||
|
||||
@SerializedName("account")
|
||||
@Param(description = "Account name")
|
||||
@SerializedName(ApiConstants.ACCOUNT)
|
||||
@Param(description = "Name of the Account.")
|
||||
private String accountName;
|
||||
|
||||
@SerializedName("domain")
|
||||
@Param(description = "Domain ID")
|
||||
private Long domainId;
|
||||
@SerializedName(ApiConstants.DOMAIN)
|
||||
@Param(description = "ID of the Domain.")
|
||||
private String domainId;
|
||||
|
||||
@SerializedName("quotausage")
|
||||
@Param(description = "List of quota usage under various types", responseObject = QuotaStatementItemResponse.class)
|
||||
@SerializedName(ApiConstants.QUOTA_USAGE)
|
||||
@Param(description = "List of Quota usage under various types.", responseObject = QuotaStatementItemResponse.class)
|
||||
private List<QuotaStatementItemResponse> lineItem;
|
||||
|
||||
@SerializedName("totalquota")
|
||||
@Param(description = "Total quota used during this period")
|
||||
@SerializedName(ApiConstants.TOTAL_QUOTA)
|
||||
@Param(description = "Total Quota consumed during this period.")
|
||||
private BigDecimal totalQuota;
|
||||
|
||||
@SerializedName("startdate")
|
||||
@Param(description = "Start date")
|
||||
@SerializedName(ApiConstants.START_DATE)
|
||||
@Param(description = "Start date of the Quota statement.")
|
||||
private Date startDate = null;
|
||||
|
||||
@SerializedName("enddate")
|
||||
@Param(description = "End date")
|
||||
@SerializedName(ApiConstants.END_DATE)
|
||||
@Param(description = "End date of the Quota statement.")
|
||||
private Date endDate = null;
|
||||
|
||||
@SerializedName("currency")
|
||||
@Param(description = "Currency")
|
||||
@SerializedName(ApiConstants.CURRENCY)
|
||||
@Param(description = "Currency of the Quota statement.")
|
||||
private String currency;
|
||||
|
||||
public QuotaStatementResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
public String getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
public void setAccountId(String accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
|
|
@ -79,45 +79,36 @@ public class QuotaStatementResponse extends BaseResponse {
|
|||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
public String getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
public void setDomainId(String domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public List<QuotaStatementItemResponse> getLineItem() {
|
||||
return lineItem;
|
||||
}
|
||||
|
||||
public void setLineItem(List<QuotaStatementItemResponse> lineItem) {
|
||||
this.lineItem = lineItem;
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate == null ? null : new Date(startDate.getTime());
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate == null ? null : new Date(endDate.getTime());
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
|
||||
public BigDecimal getTotalQuota() {
|
||||
return totalQuota;
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public void setTotalQuota(BigDecimal totalQuota) {
|
||||
this.totalQuota = totalQuota.setScale(2, RoundingMode.HALF_EVEN);
|
||||
this.totalQuota = totalQuota;
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageJoinVO;
|
||||
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.utils.component.PluggableService;
|
||||
|
||||
public interface QuotaService extends PluggableService {
|
||||
|
||||
List<QuotaUsageVO> getQuotaUsage(Long accountId, String accountName, Long domainId, Integer usageType, Date startDate, Date endDate);
|
||||
List<QuotaUsageJoinVO> getQuotaUsage(Long accountId, String accountName, Long domainId, Integer usageType, Date startDate, Date endDate);
|
||||
|
||||
List<QuotaBalanceVO> findQuotaBalanceVO(Long accountId, String accountName, Long domainId, Date startDate, Date endDate);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,10 +53,10 @@ 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.QuotaBalanceDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageJoinDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageJoinVO;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
|||
@Inject
|
||||
private QuotaAccountDao _quotaAcc;
|
||||
@Inject
|
||||
private QuotaUsageDao _quotaUsageDao;
|
||||
private QuotaUsageJoinDao quotaUsageJoinDao;
|
||||
@Inject
|
||||
private DomainDao _domainDao;
|
||||
@Inject
|
||||
|
|
@ -213,27 +213,7 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaUsageVO> getQuotaUsage(Long accountId, String accountName, Long domainId, Integer usageType, Date startDate, Date endDate) {
|
||||
// if accountId is not specified, use accountName and domainId
|
||||
if ((accountId == null) && (accountName != null) && (domainId != null)) {
|
||||
Account userAccount = null;
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
if (_domainDao.isChildDomain(caller.getDomainId(), domainId)) {
|
||||
Filter filter = new Filter(AccountVO.class, "id", Boolean.FALSE, null, null);
|
||||
List<AccountVO> accounts = _accountDao.listAccounts(accountName, domainId, filter);
|
||||
if (!accounts.isEmpty()) {
|
||||
userAccount = accounts.get(0);
|
||||
}
|
||||
if (userAccount != null) {
|
||||
accountId = userAccount.getId();
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
|
||||
}
|
||||
} else {
|
||||
throw new PermissionDeniedException("Invalid Domain Id or Account");
|
||||
}
|
||||
}
|
||||
|
||||
public List<QuotaUsageJoinVO> getQuotaUsage(Long accountId, String accountName, Long domainId, Integer usageType, Date startDate, Date endDate) {
|
||||
if (startDate.after(endDate)) {
|
||||
throw new InvalidParameterValueException("Incorrect Date Range. Start date: " + startDate + " is after end date:" + endDate);
|
||||
}
|
||||
|
|
@ -241,7 +221,7 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
|||
logger.debug("Getting quota records of type [{}] for account [{}] in domain [{}], between [{}] and [{}].",
|
||||
usageType, accountId, domainId, startDate, endDate);
|
||||
|
||||
return _quotaUsageDao.findQuotaUsage(accountId, domainId, usageType, startDate, endDate);
|
||||
return quotaUsageJoinDao.findQuotaUsage(accountId, domainId, usageType, null, null, null, startDate, endDate, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -16,38 +16,29 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.api.response.QuotaStatementResponse;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaStatementCmdTest extends TestCase {
|
||||
public class QuotaStatementCmdTest {
|
||||
@Mock
|
||||
QuotaResponseBuilder responseBuilder;
|
||||
QuotaResponseBuilder responseBuilderMock;
|
||||
|
||||
@Test
|
||||
public void testQuotaStatementCmd() throws NoSuchFieldException, IllegalAccessException {
|
||||
public void executeTestVerifyCalls() {
|
||||
QuotaStatementCmd cmd = new QuotaStatementCmd();
|
||||
cmd.setAccountName("admin");
|
||||
cmd.responseBuilder = responseBuilderMock;
|
||||
|
||||
Field rbField = QuotaStatementCmd.class.getDeclaredField("_responseBuilder");
|
||||
rbField.setAccessible(true);
|
||||
rbField.set(cmd, responseBuilder);
|
||||
Mockito.doReturn(new QuotaStatementResponse()).when(responseBuilderMock).createQuotaStatementResponse(Mockito.any());
|
||||
|
||||
List<QuotaUsageVO> quotaUsageVOList = new ArrayList<QuotaUsageVO>();
|
||||
Mockito.when(responseBuilder.getQuotaUsage(Mockito.eq(cmd))).thenReturn(quotaUsageVOList);
|
||||
Mockito.when(responseBuilder.createQuotaStatementResponse(Mockito.eq(quotaUsageVOList))).thenReturn(new QuotaStatementResponse());
|
||||
cmd.execute();
|
||||
Mockito.verify(responseBuilder, Mockito.times(1)).getQuotaUsage(Mockito.eq(cmd));
|
||||
|
||||
Mockito.verify(responseBuilderMock).createQuotaStatementResponse(cmd);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
|
|
@ -42,6 +44,7 @@ import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd;
|
|||
import org.apache.cloudstack.api.command.QuotaCreditsListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaSummaryCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaValidateActivationRuleCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
|
|
@ -67,6 +70,7 @@ import org.apache.cloudstack.quota.vo.QuotaCreditsVO;
|
|||
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageJoinVO;
|
||||
import org.apache.cloudstack.utils.jsinterpreter.JsInterpreter;
|
||||
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
|
|
@ -914,4 +918,199 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
|||
Assert.assertTrue(formattedVariables.containsValue("accountname"));
|
||||
Assert.assertTrue(formattedVariables.containsValue("zonename"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createDummyRecordForEachQuotaTypeIfUsageTypeIsNotInformedTestUsageTypeDifferentFromNullDoNothing() {
|
||||
List<QuotaUsageJoinVO> listUsage = new ArrayList<>();
|
||||
|
||||
quotaResponseBuilderSpy.createDummyRecordForEachQuotaTypeIfUsageTypeIsNotInformed(listUsage, 1);
|
||||
|
||||
Assert.assertTrue(listUsage.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createDummyRecordForEachQuotaTypeIfUsageTypeIsNotInformedTestUsageTypeIsNullAddDummyForAllQuotaTypes() {
|
||||
List<QuotaUsageJoinVO> listUsage = new ArrayList<>();
|
||||
listUsage.add(new QuotaUsageJoinVO());
|
||||
|
||||
quotaResponseBuilderSpy.createDummyRecordForEachQuotaTypeIfUsageTypeIsNotInformed(listUsage, null);
|
||||
|
||||
Assert.assertEquals(QuotaTypes.listQuotaTypes().size() + 1, listUsage.size());
|
||||
|
||||
QuotaTypes.listQuotaTypes().entrySet().forEach(entry -> {
|
||||
Assert.assertTrue(listUsage.stream().anyMatch(usage -> usage.getUsageType() == entry.getKey() && usage.getQuotaUsed().equals(BigDecimal.ZERO)));
|
||||
});
|
||||
}
|
||||
|
||||
private List<QuotaUsageJoinVO> getQuotaUsagesForTest() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
List<QuotaUsageJoinVO> quotaUsages = new ArrayList<>();
|
||||
|
||||
QuotaUsageJoinVO quotaUsage = new QuotaUsageJoinVO();
|
||||
quotaUsage.setAccountId(1l);
|
||||
quotaUsage.setDomainId(2l);
|
||||
quotaUsage.setUsageType(3);
|
||||
quotaUsage.setQuotaUsed(BigDecimal.valueOf(10));
|
||||
try {
|
||||
quotaUsage.setStartDate(sdf.parse("2022-01-01"));
|
||||
quotaUsage.setEndDate(sdf.parse("2022-01-02"));
|
||||
} catch (ParseException ignored) {
|
||||
}
|
||||
quotaUsages.add(quotaUsage);
|
||||
|
||||
quotaUsage = new QuotaUsageJoinVO();
|
||||
quotaUsage.setAccountId(4l);
|
||||
quotaUsage.setDomainId(5l);
|
||||
quotaUsage.setUsageType(3);
|
||||
quotaUsage.setQuotaUsed(null);
|
||||
try {
|
||||
quotaUsage.setStartDate(sdf.parse("2022-01-03"));
|
||||
quotaUsage.setEndDate(sdf.parse("2022-01-04"));
|
||||
} catch (ParseException ignored) {
|
||||
}
|
||||
quotaUsages.add(quotaUsage);
|
||||
|
||||
quotaUsage = new QuotaUsageJoinVO();
|
||||
quotaUsage.setAccountId(6l);
|
||||
quotaUsage.setDomainId(7l);
|
||||
quotaUsage.setUsageType(3);
|
||||
quotaUsage.setQuotaUsed(BigDecimal.valueOf(5));
|
||||
try {
|
||||
quotaUsage.setStartDate(sdf.parse("2022-01-05"));
|
||||
quotaUsage.setEndDate(sdf.parse("2022-01-06"));
|
||||
} catch (ParseException ignored) {
|
||||
}
|
||||
quotaUsages.add(quotaUsage);
|
||||
|
||||
return quotaUsages;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createStatementItemTestReturnItem() {
|
||||
List<QuotaUsageJoinVO> quotaUsages = getQuotaUsagesForTest();
|
||||
Mockito.doNothing().when(quotaResponseBuilderSpy).setStatementItemResources(Mockito.any(), Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean());
|
||||
|
||||
QuotaStatementItemResponse result = quotaResponseBuilderSpy.createStatementItem(0, quotaUsages, false);
|
||||
|
||||
QuotaUsageJoinVO expected = quotaUsages.get(0);
|
||||
QuotaTypes quotaTypeExpected = QuotaTypes.listQuotaTypes().get(expected.getUsageType());
|
||||
Assert.assertEquals(BigDecimal.valueOf(15), result.getQuotaUsed());
|
||||
Assert.assertEquals(quotaTypeExpected.getQuotaUnit(), result.getUsageUnit());
|
||||
Assert.assertEquals(quotaTypeExpected.getQuotaName(), result.getUsageName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setStatementItemResourcesTestDoNotShowResourcesDoNothing() {
|
||||
QuotaStatementItemResponse item = new QuotaStatementItemResponse(1);
|
||||
|
||||
quotaResponseBuilderSpy.setStatementItemResources(item, 0, getQuotaUsagesForTest(), false);
|
||||
|
||||
Assert.assertNull(item.getResources());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAccountIdForQuotaStatementTestLimitsToCallingAccountForNormalUser() {
|
||||
QuotaStatementCmd cmd = Mockito.mock(QuotaStatementCmd.class);
|
||||
|
||||
Mockito.doReturn(accountMock).when(callContextMock).getCallingAccount();
|
||||
Mockito.doReturn(Account.Type.NORMAL).when(accountMock).getType();
|
||||
|
||||
try (MockedStatic<CallContext> callContextMocked = Mockito.mockStatic(CallContext.class)) {
|
||||
callContextMocked.when(CallContext::current).thenReturn(callContextMock);
|
||||
|
||||
Long result = quotaResponseBuilderSpy.getAccountIdForQuotaStatement(cmd);
|
||||
|
||||
Assert.assertEquals(Long.valueOf(callerAccountMock.getAccountId()), result);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAccountIdForQuotaStatementTestReturnsEntityOwnerIdWhenProvided() {
|
||||
QuotaStatementCmd cmd = Mockito.mock(QuotaStatementCmd.class);
|
||||
|
||||
Mockito.doReturn(42L).when(cmd).getEntityOwnerId();
|
||||
|
||||
Long result = quotaResponseBuilderSpy.getAccountIdForQuotaStatement(cmd);
|
||||
|
||||
Assert.assertEquals(Long.valueOf(42L), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAccountIdForQuotaStatementTestLimitsToCallingAccountWhenCallerIsAdminAndDomainIsNotProvided() {
|
||||
QuotaStatementCmd cmd = Mockito.mock(QuotaStatementCmd.class);
|
||||
|
||||
Mockito.doReturn(accountMock).when(callContextMock).getCallingAccount();
|
||||
Mockito.doReturn(Account.Type.ADMIN).when(accountMock).getType();
|
||||
Mockito.doReturn(-1L).when(cmd).getEntityOwnerId();
|
||||
Mockito.doReturn(null).when(cmd).getDomainId();
|
||||
|
||||
try (MockedStatic<CallContext> callContextMocked = Mockito.mockStatic(CallContext.class)) {
|
||||
callContextMocked.when(CallContext::current).thenReturn(callContextMock);
|
||||
|
||||
Long result = quotaResponseBuilderSpy.getAccountIdForQuotaStatement(cmd);
|
||||
|
||||
Assert.assertEquals(Long.valueOf(callerAccountMock.getAccountId()), result);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAccountIdForQuotaStatementTestReturnsNullWhenCallerIsAdminAndDomainIsProvided() {
|
||||
QuotaStatementCmd cmd = Mockito.mock(QuotaStatementCmd.class);
|
||||
|
||||
Mockito.doReturn(accountMock).when(callContextMock).getCallingAccount();
|
||||
Mockito.doReturn(Account.Type.ADMIN).when(accountMock).getType();
|
||||
Mockito.doReturn(-1L).when(cmd).getEntityOwnerId();
|
||||
Mockito.doReturn(10L).when(cmd).getDomainId();
|
||||
|
||||
try (MockedStatic<CallContext> callContextMocked = Mockito.mockStatic(CallContext.class)) {
|
||||
callContextMocked.when(CallContext::current).thenReturn(callContextMock);
|
||||
|
||||
Long result = quotaResponseBuilderSpy.getAccountIdForQuotaStatement(cmd);
|
||||
|
||||
Assert.assertNull(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDomainIdForQuotaStatementTestReturnsAccountDomainIdWhenAccountIdIsProvided() {
|
||||
QuotaStatementCmd cmd = Mockito.mock(QuotaStatementCmd.class);
|
||||
AccountVO account = Mockito.mock(AccountVO.class);
|
||||
|
||||
Mockito.doReturn(account).when(accountDaoMock).findByIdIncludingRemoved(55L);
|
||||
Mockito.doReturn(77L).when(account).getDomainId();
|
||||
|
||||
Long result = quotaResponseBuilderSpy.getDomainIdForQuotaStatement(cmd, 55L);
|
||||
|
||||
Assert.assertEquals(Long.valueOf(77L), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDomainIdForQuotaStatementTestReturnsProvidedDomainIdWhenAccountIdIsNull() {
|
||||
QuotaStatementCmd cmd = Mockito.mock(QuotaStatementCmd.class);
|
||||
|
||||
Mockito.doReturn(99L).when(cmd).getDomainId();
|
||||
|
||||
Long result = quotaResponseBuilderSpy.getDomainIdForQuotaStatement(cmd, null);
|
||||
|
||||
Assert.assertEquals(Long.valueOf(99L), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDomainIdForQuotaStatementTestFallsBackToCallingAccountDomainIdWhenNeitherAccountNorDomainIsProvided() {
|
||||
QuotaStatementCmd cmd = Mockito.mock(QuotaStatementCmd.class);
|
||||
Account account = Mockito.mock(Account.class);
|
||||
|
||||
Mockito.doReturn(null).when(cmd).getDomainId();
|
||||
Mockito.doReturn(123L).when(account).getDomainId();
|
||||
Mockito.doReturn(account).when(callContextMock).getCallingAccount();
|
||||
|
||||
try (MockedStatic<CallContext> callContextMocked = Mockito.mockStatic(CallContext.class)) {
|
||||
callContextMocked.when(CallContext::current).thenReturn(callContextMock);
|
||||
|
||||
Long result = quotaResponseBuilderSpy.getDomainIdForQuotaStatement(cmd, null);
|
||||
|
||||
Assert.assertEquals(123L, result.longValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import org.apache.cloudstack.quota.constant.QuotaTypes;
|
|||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageJoinDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.joda.time.DateTime;
|
||||
|
|
@ -63,6 +64,8 @@ public class QuotaServiceImplTest extends TestCase {
|
|||
@Mock
|
||||
QuotaBalanceDao quotaBalanceDao;
|
||||
@Mock
|
||||
QuotaUsageJoinDao quotaUsageJoinDaoMock;
|
||||
@Mock
|
||||
QuotaResponseBuilder respBldr;
|
||||
@Mock
|
||||
private AccountVO accountVoMock;
|
||||
|
|
@ -85,9 +88,9 @@ public class QuotaServiceImplTest extends TestCase {
|
|||
quotaAccountDaoField.setAccessible(true);
|
||||
quotaAccountDaoField.set(quotaServiceImplSpy, quotaAcc);
|
||||
|
||||
Field quotaUsageDaoField = QuotaServiceImpl.class.getDeclaredField("_quotaUsageDao");
|
||||
Field quotaUsageDaoField = QuotaServiceImpl.class.getDeclaredField("quotaUsageJoinDao");
|
||||
quotaUsageDaoField.setAccessible(true);
|
||||
quotaUsageDaoField.set(quotaServiceImplSpy, quotaUsageDao);
|
||||
quotaUsageDaoField.set(quotaServiceImplSpy, quotaUsageJoinDaoMock);
|
||||
|
||||
Field domainDaoField = QuotaServiceImpl.class.getDeclaredField("_domainDao");
|
||||
domainDaoField.setAccessible(true);
|
||||
|
|
@ -142,7 +145,8 @@ public class QuotaServiceImplTest extends TestCase {
|
|||
final Date endDate = new Date();
|
||||
|
||||
quotaServiceImplSpy.getQuotaUsage(accountId, accountName, domainId, QuotaTypes.IP_ADDRESS, startDate, endDate);
|
||||
Mockito.verify(quotaUsageDao, Mockito.times(1)).findQuotaUsage(Mockito.eq(accountId), Mockito.eq(domainId), Mockito.eq(QuotaTypes.IP_ADDRESS), Mockito.any(Date.class), Mockito.any(Date.class));
|
||||
Mockito.verify(quotaUsageJoinDaoMock, Mockito.times(1)).findQuotaUsage(Mockito.eq(accountId), Mockito.eq(domainId), Mockito.eq(QuotaTypes.IP_ADDRESS), Mockito.any(),
|
||||
Mockito.any(), Mockito.any(), Mockito.any(Date.class), Mockito.any(Date.class), Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue