mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
[Usage] Create VPC billing (#7235)
Co-authored-by: SadiJr <sadi@scclouds.com.br> Co-authored-by: Bryan Lima <bryan.lima@hotmail.com>
This commit is contained in:
parent
78e07cff62
commit
49d244f251
@ -1219,4 +1219,8 @@ public class EventTypes {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isVpcEvent(String eventType) {
|
||||||
|
return EventTypes.EVENT_VPC_CREATE.equals(eventType) || EventTypes.EVENT_VPC_DELETE.equals(eventType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,6 +46,7 @@ public class UsageTypes {
|
|||||||
public static final int VM_SNAPSHOT_ON_PRIMARY = 27;
|
public static final int VM_SNAPSHOT_ON_PRIMARY = 27;
|
||||||
public static final int BACKUP = 28;
|
public static final int BACKUP = 28;
|
||||||
public static final int BUCKET = 29;
|
public static final int BUCKET = 29;
|
||||||
|
public static final int VPC = 31;
|
||||||
|
|
||||||
public static List<UsageTypeResponse> listUsageTypes() {
|
public static List<UsageTypeResponse> listUsageTypes() {
|
||||||
List<UsageTypeResponse> responseList = new ArrayList<UsageTypeResponse>();
|
List<UsageTypeResponse> responseList = new ArrayList<UsageTypeResponse>();
|
||||||
@ -72,6 +73,7 @@ public class UsageTypes {
|
|||||||
responseList.add(new UsageTypeResponse(VM_SNAPSHOT_ON_PRIMARY, "VM Snapshot on primary storage usage"));
|
responseList.add(new UsageTypeResponse(VM_SNAPSHOT_ON_PRIMARY, "VM Snapshot on primary storage usage"));
|
||||||
responseList.add(new UsageTypeResponse(BACKUP, "Backup storage usage"));
|
responseList.add(new UsageTypeResponse(BACKUP, "Backup storage usage"));
|
||||||
responseList.add(new UsageTypeResponse(BUCKET, "Bucket storage usage"));
|
responseList.add(new UsageTypeResponse(BUCKET, "Bucket storage usage"));
|
||||||
|
responseList.add(new UsageTypeResponse(VPC, "VPC usage"));
|
||||||
return responseList;
|
return responseList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
130
engine/schema/src/main/java/com/cloud/usage/UsageVpcVO.java
Normal file
130
engine/schema/src/main/java/com/cloud/usage/UsageVpcVO.java
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// 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 com.cloud.usage;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Temporal;
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
import org.apache.cloudstack.api.InternalIdentity;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "usage_vpc")
|
||||||
|
public class UsageVpcVO implements InternalIdentity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Column(name = "vpc_id")
|
||||||
|
private long vpcId;
|
||||||
|
|
||||||
|
@Column(name = "zone_id")
|
||||||
|
private long zoneId;
|
||||||
|
|
||||||
|
@Column(name = "account_id")
|
||||||
|
private long accountId;
|
||||||
|
|
||||||
|
@Column(name = "domain_id")
|
||||||
|
private long domainId;
|
||||||
|
|
||||||
|
|
||||||
|
@Column(name = "state")
|
||||||
|
private String state;
|
||||||
|
|
||||||
|
@Column(name = "created")
|
||||||
|
@Temporal(value = TemporalType.TIMESTAMP)
|
||||||
|
private Date created = null;
|
||||||
|
|
||||||
|
@Column(name = "removed")
|
||||||
|
@Temporal(value = TemporalType.TIMESTAMP)
|
||||||
|
private Date removed = null;
|
||||||
|
|
||||||
|
protected UsageVpcVO(){}
|
||||||
|
|
||||||
|
public UsageVpcVO(long id, long vpcId, long zoneId, long accountId, long domainId, String state, Date created, Date removed) {
|
||||||
|
this.id = id;
|
||||||
|
this.vpcId = vpcId;
|
||||||
|
this.zoneId = zoneId;
|
||||||
|
this.domainId = domainId;
|
||||||
|
this.accountId = accountId;
|
||||||
|
this.state = state;
|
||||||
|
this.created = created;
|
||||||
|
this.removed = removed;
|
||||||
|
}
|
||||||
|
public UsageVpcVO(long vpcId, long zoneId, long accountId, long domainId, String state, Date created, Date removed) {
|
||||||
|
this.vpcId = vpcId;
|
||||||
|
this.zoneId = zoneId;
|
||||||
|
this.domainId = domainId;
|
||||||
|
this.accountId = accountId;
|
||||||
|
this.state = state;
|
||||||
|
this.created = created;
|
||||||
|
this.removed = removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getZoneId() {
|
||||||
|
return zoneId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDomainId() {
|
||||||
|
return domainId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getVpcId() {
|
||||||
|
return vpcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVpcId(long vpcId) {
|
||||||
|
this.vpcId = vpcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(String state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreated() {
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getRemoved() {
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemoved(Date removed) {
|
||||||
|
this.removed = removed;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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 com.cloud.usage.dao;
|
||||||
|
|
||||||
|
import com.cloud.usage.UsageVpcVO;
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface UsageVpcDao extends GenericDao<UsageVpcVO, Long> {
|
||||||
|
void update(UsageVpcVO usage);
|
||||||
|
void remove(long vpcId, Date removed);
|
||||||
|
List<UsageVpcVO> getUsageRecords(Long accountId, Date startDate, Date endDate);
|
||||||
|
}
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
// 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 com.cloud.usage.dao;
|
||||||
|
|
||||||
|
import com.cloud.network.vpc.Vpc;
|
||||||
|
import com.cloud.usage.UsageVpcVO;
|
||||||
|
import com.cloud.utils.DateUtil;
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
|
import com.cloud.utils.db.TransactionLegacy;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class UsageVpcDaoImpl extends GenericDaoBase<UsageVpcVO, Long> implements UsageVpcDao {
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(UsageVpcDaoImpl.class);
|
||||||
|
protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = "SELECT id, vpc_id, zone_id, account_id, domain_id, state, created, removed FROM usage_vpc WHERE " +
|
||||||
|
" account_id = ? AND ((removed IS NULL AND created <= ?) OR (created BETWEEN ? AND ?) OR (removed BETWEEN ? AND ?) " +
|
||||||
|
" OR ((created <= ?) AND (removed >= ?)))";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(UsageVpcVO usage) {
|
||||||
|
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||||
|
try {
|
||||||
|
SearchCriteria<UsageVpcVO> sc = this.createSearchCriteria();
|
||||||
|
sc.addAnd("vpcId", SearchCriteria.Op.EQ, usage.getVpcId());
|
||||||
|
sc.addAnd("created", SearchCriteria.Op.EQ, usage.getCreated());
|
||||||
|
UsageVpcVO vo = findOneBy(sc);
|
||||||
|
if (vo != null) {
|
||||||
|
vo.setRemoved(usage.getRemoved());
|
||||||
|
update(vo.getId(), vo);
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
LOGGER.error(String.format("Error updating usage of VPC due to [%s].", e.getMessage()), e);
|
||||||
|
txn.rollback();
|
||||||
|
} finally {
|
||||||
|
txn.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(long vpcId, Date removed) {
|
||||||
|
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||||
|
try {
|
||||||
|
SearchCriteria<UsageVpcVO> sc = this.createSearchCriteria();
|
||||||
|
sc.addAnd("vpcId", SearchCriteria.Op.EQ, vpcId);
|
||||||
|
sc.addAnd("removed", SearchCriteria.Op.NULL);
|
||||||
|
UsageVpcVO vo = findOneBy(sc);
|
||||||
|
if (vo != null) {
|
||||||
|
vo.setRemoved(removed);
|
||||||
|
vo.setState(Vpc.State.Inactive.name());
|
||||||
|
update(vo.getId(), vo);
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
txn.rollback();
|
||||||
|
LOGGER.error(String.format("Error updating usage of VPC due to [%s].", e.getMessage()), e);
|
||||||
|
} finally {
|
||||||
|
txn.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<UsageVpcVO> getUsageRecords(Long accountId, Date startDate, Date endDate) {
|
||||||
|
List<UsageVpcVO> usageRecords = new ArrayList<>();
|
||||||
|
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||||
|
PreparedStatement pstmt;
|
||||||
|
try {
|
||||||
|
int i = 1;
|
||||||
|
pstmt = txn.prepareAutoCloseStatement(GET_USAGE_RECORDS_BY_ACCOUNT);
|
||||||
|
pstmt.setLong(i++, accountId);
|
||||||
|
|
||||||
|
pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), endDate));
|
||||||
|
pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), startDate));
|
||||||
|
pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), endDate));
|
||||||
|
pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), startDate));
|
||||||
|
pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), endDate));
|
||||||
|
pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), startDate));
|
||||||
|
pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), endDate));
|
||||||
|
|
||||||
|
ResultSet rs = pstmt.executeQuery();
|
||||||
|
while (rs.next()) {
|
||||||
|
long id = rs.getLong(1);
|
||||||
|
long vpcId = rs.getLong(2);
|
||||||
|
long zoneId = rs.getLong(3);
|
||||||
|
long acctId = rs.getLong(4);
|
||||||
|
long domId = rs.getLong(5);
|
||||||
|
String stateTS = rs.getString(6);
|
||||||
|
Date createdDate = null;
|
||||||
|
Date removedDate = null;
|
||||||
|
String createdTS = rs.getString(7);
|
||||||
|
String removedTS = rs.getString(8);
|
||||||
|
|
||||||
|
if (createdTS != null) {
|
||||||
|
createdDate = DateUtil.parseDateString(s_gmtTimeZone, createdTS);
|
||||||
|
}
|
||||||
|
if (removedTS != null) {
|
||||||
|
removedDate = DateUtil.parseDateString(s_gmtTimeZone, removedTS);
|
||||||
|
}
|
||||||
|
usageRecords.add(new UsageVpcVO(id, vpcId, zoneId, acctId, domId, stateTS, createdDate, removedDate));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
txn.rollback();
|
||||||
|
LOGGER.warn("Error getting VPC usage records", e);
|
||||||
|
} finally {
|
||||||
|
txn.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return usageRecords;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -67,6 +67,7 @@
|
|||||||
<bean id="vMInstanceDaoImpl" class="com.cloud.vm.dao.VMInstanceDaoImpl" />
|
<bean id="vMInstanceDaoImpl" class="com.cloud.vm.dao.VMInstanceDaoImpl" />
|
||||||
<bean id="vMSnapshotDaoImpl" class="com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl" />
|
<bean id="vMSnapshotDaoImpl" class="com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl" />
|
||||||
<bean id="VmTemplateDaoImpl" class="org.apache.cloudstack.quota.dao.VmTemplateDaoImpl" />
|
<bean id="VmTemplateDaoImpl" class="org.apache.cloudstack.quota.dao.VmTemplateDaoImpl" />
|
||||||
|
<bean id="VpcDaoImpl" class="org.apache.cloudstack.quota.dao.VpcDaoImpl" />
|
||||||
<bean id="volumeDaoImpl" class="com.cloud.storage.dao.VolumeDaoImpl" />
|
<bean id="volumeDaoImpl" class="com.cloud.storage.dao.VolumeDaoImpl" />
|
||||||
<bean id="backupOfferingDaoImpl" class="org.apache.cloudstack.backup.dao.BackupOfferingDaoImpl" />
|
<bean id="backupOfferingDaoImpl" class="org.apache.cloudstack.backup.dao.BackupOfferingDaoImpl" />
|
||||||
</beans>
|
</beans>
|
||||||
|
|||||||
@ -203,6 +203,7 @@
|
|||||||
<bean id="usageStorageDaoImpl" class="com.cloud.usage.dao.UsageStorageDaoImpl" />
|
<bean id="usageStorageDaoImpl" class="com.cloud.usage.dao.UsageStorageDaoImpl" />
|
||||||
<bean id="usageVMInstanceDaoImpl" class="com.cloud.usage.dao.UsageVMInstanceDaoImpl" />
|
<bean id="usageVMInstanceDaoImpl" class="com.cloud.usage.dao.UsageVMInstanceDaoImpl" />
|
||||||
<bean id="usageVPNUserDaoImpl" class="com.cloud.usage.dao.UsageVPNUserDaoImpl" />
|
<bean id="usageVPNUserDaoImpl" class="com.cloud.usage.dao.UsageVPNUserDaoImpl" />
|
||||||
|
<bean id="usageVpcDaoImpl" class="com.cloud.usage.dao.UsageVpcDaoImpl" />
|
||||||
<bean id="usageVolumeDaoImpl" class="com.cloud.usage.dao.UsageVolumeDaoImpl" />
|
<bean id="usageVolumeDaoImpl" class="com.cloud.usage.dao.UsageVolumeDaoImpl" />
|
||||||
<bean id="usageVmDiskDaoImpl" class="com.cloud.usage.dao.UsageVmDiskDaoImpl" />
|
<bean id="usageVmDiskDaoImpl" class="com.cloud.usage.dao.UsageVmDiskDaoImpl" />
|
||||||
<bean id="usageBackupDaoImpl" class="com.cloud.usage.dao.UsageBackupDaoImpl" />
|
<bean id="usageBackupDaoImpl" class="com.cloud.usage.dao.UsageBackupDaoImpl" />
|
||||||
|
|||||||
@ -30,3 +30,18 @@ UPDATE cloud_usage.quota_tariff
|
|||||||
SET usage_unit = 'IOPS', updated_on = NOW()
|
SET usage_unit = 'IOPS', updated_on = NOW()
|
||||||
WHERE effective_on = '2010-05-04 00:00:00'
|
WHERE effective_on = '2010-05-04 00:00:00'
|
||||||
AND name IN ('VM_DISK_IO_READ', 'VM_DISK_IO_WRITE');
|
AND name IN ('VM_DISK_IO_READ', 'VM_DISK_IO_WRITE');
|
||||||
|
|
||||||
|
-- PR #7235 - [Usage] Create VPC billing
|
||||||
|
CREATE TABLE IF NOT EXISTS `cloud_usage`.`usage_vpc` (
|
||||||
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`vpc_id` bigint(20) unsigned NOT NULL,
|
||||||
|
`zone_id` bigint(20) unsigned NOT NULL,
|
||||||
|
`account_id` bigint(20) unsigned NOT NULL,
|
||||||
|
`domain_id` bigint(20) unsigned NOT NULL,
|
||||||
|
`state` varchar(100) DEFAULT NULL,
|
||||||
|
`created` datetime NOT NULL,
|
||||||
|
`removed` datetime DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB CHARSET=utf8;
|
||||||
|
|
||||||
|
CALL `cloud_usage`.`IDEMPOTENT_ADD_COLUMN`('cloud_usage.cloud_usage', 'state', 'VARCHAR(100) DEFAULT NULL');
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import java.util.Map;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.cloud.host.HostTagVO;
|
import com.cloud.host.HostTagVO;
|
||||||
|
import com.cloud.network.vpc.VpcVO;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import com.cloud.hypervisor.Hypervisor;
|
import com.cloud.hypervisor.Hypervisor;
|
||||||
@ -37,6 +38,7 @@ import org.apache.cloudstack.backup.dao.BackupOfferingDao;
|
|||||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||||
import org.apache.cloudstack.quota.dao.VmTemplateDao;
|
import org.apache.cloudstack.quota.dao.VmTemplateDao;
|
||||||
|
import org.apache.cloudstack.quota.dao.VpcDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||||
@ -170,6 +172,10 @@ public class PresetVariableHelper {
|
|||||||
@Inject
|
@Inject
|
||||||
BackupOfferingDao backupOfferingDao;
|
BackupOfferingDao backupOfferingDao;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
VpcDao vpcDao;
|
||||||
|
|
||||||
|
|
||||||
protected boolean backupSnapshotAfterTakingSnapshot = SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value();
|
protected boolean backupSnapshotAfterTakingSnapshot = SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value();
|
||||||
|
|
||||||
private List<Integer> runningAndAllocatedVmUsageTypes = Arrays.asList(UsageTypes.RUNNING_VM, UsageTypes.ALLOCATED_VM);
|
private List<Integer> runningAndAllocatedVmUsageTypes = Arrays.asList(UsageTypes.RUNNING_VM, UsageTypes.ALLOCATED_VM);
|
||||||
@ -273,6 +279,7 @@ public class PresetVariableHelper {
|
|||||||
loadPresetVariableValueForNetworkOffering(usageRecord, value);
|
loadPresetVariableValueForNetworkOffering(usageRecord, value);
|
||||||
loadPresetVariableValueForVmSnapshot(usageRecord, value);
|
loadPresetVariableValueForVmSnapshot(usageRecord, value);
|
||||||
loadPresetVariableValueForBackup(usageRecord, value);
|
loadPresetVariableValueForBackup(usageRecord, value);
|
||||||
|
loadPresetVariableValueForVpc(usageRecord, value);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -689,6 +696,21 @@ public class PresetVariableHelper {
|
|||||||
return backupOffering;
|
return backupOffering;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void loadPresetVariableValueForVpc(UsageVO usageRecord, Value value) {
|
||||||
|
int usageType = usageRecord.getUsageType();
|
||||||
|
if (usageType != QuotaTypes.VPC) {
|
||||||
|
logNotLoadingMessageInTrace("VPC", usageType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long vpcId = usageRecord.getUsageId();
|
||||||
|
VpcVO vpc = vpcDao.findByIdIncludingRemoved(vpcId);
|
||||||
|
validateIfObjectIsNull(vpc, vpcId, "VPC");
|
||||||
|
|
||||||
|
value.setId(vpc.getUuid());
|
||||||
|
value.setName(vpc.getName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws a {@link CloudRuntimeException} if the object is null;
|
* Throws a {@link CloudRuntimeException} if the object is null;
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -56,6 +56,7 @@ public class QuotaTypes extends UsageTypes {
|
|||||||
quotaTypeList.put(VM_SNAPSHOT_ON_PRIMARY, new QuotaTypes(VM_SNAPSHOT_ON_PRIMARY, "VM_SNAPSHOT_ON_PRIMARY", UsageUnitTypes.GB_MONTH.toString(), "VM Snapshot primary storage usage"));
|
quotaTypeList.put(VM_SNAPSHOT_ON_PRIMARY, new QuotaTypes(VM_SNAPSHOT_ON_PRIMARY, "VM_SNAPSHOT_ON_PRIMARY", UsageUnitTypes.GB_MONTH.toString(), "VM Snapshot primary storage usage"));
|
||||||
quotaTypeList.put(BACKUP, new QuotaTypes(BACKUP, "BACKUP", UsageUnitTypes.GB_MONTH.toString(), "Backup storage usage"));
|
quotaTypeList.put(BACKUP, new QuotaTypes(BACKUP, "BACKUP", UsageUnitTypes.GB_MONTH.toString(), "Backup storage usage"));
|
||||||
quotaTypeList.put(BUCKET, new QuotaTypes(BUCKET, "BUCKET", UsageUnitTypes.GB_MONTH.toString(), "Object Store bucket usage"));
|
quotaTypeList.put(BUCKET, new QuotaTypes(BUCKET, "BUCKET", UsageUnitTypes.GB_MONTH.toString(), "Object Store bucket usage"));
|
||||||
|
quotaTypeList.put(VPC, new QuotaTypes(VPC, "VPC", UsageUnitTypes.COMPUTE_MONTH.toString(), "VPC usage"));
|
||||||
quotaTypeMap = Collections.unmodifiableMap(quotaTypeList);
|
quotaTypeMap = Collections.unmodifiableMap(quotaTypeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
// 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.network.vpc.VpcVO;
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
|
public interface VpcDao extends GenericDao<VpcVO, Long> {
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
// 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.network.vpc.VpcVO;
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
|
||||||
|
public class VpcDaoImpl extends GenericDaoBase<VpcVO, Long> implements VpcDao {
|
||||||
|
}
|
||||||
@ -471,6 +471,7 @@ public class PresetVariableHelperTest {
|
|||||||
Mockito.doNothing().when(presetVariableHelperSpy).loadPresetVariableValueForNetworkOffering(Mockito.any(UsageVO.class), Mockito.any(Value.class));
|
Mockito.doNothing().when(presetVariableHelperSpy).loadPresetVariableValueForNetworkOffering(Mockito.any(UsageVO.class), Mockito.any(Value.class));
|
||||||
Mockito.doNothing().when(presetVariableHelperSpy).loadPresetVariableValueForVmSnapshot(Mockito.any(UsageVO.class), Mockito.any(Value.class));
|
Mockito.doNothing().when(presetVariableHelperSpy).loadPresetVariableValueForVmSnapshot(Mockito.any(UsageVO.class), Mockito.any(Value.class));
|
||||||
Mockito.doNothing().when(presetVariableHelperSpy).loadPresetVariableValueForBackup(Mockito.any(UsageVO.class), Mockito.any(Value.class));
|
Mockito.doNothing().when(presetVariableHelperSpy).loadPresetVariableValueForBackup(Mockito.any(UsageVO.class), Mockito.any(Value.class));
|
||||||
|
Mockito.doNothing().when(presetVariableHelperSpy).loadPresetVariableValueForVpc(Mockito.any(UsageVO.class), Mockito.any(Value.class));
|
||||||
|
|
||||||
Value result = presetVariableHelperSpy.getPresetVariableValue(usageVoMock);
|
Value result = presetVariableHelperSpy.getPresetVariableValue(usageVoMock);
|
||||||
|
|
||||||
|
|||||||
@ -37,6 +37,7 @@ import java.util.concurrent.Future;
|
|||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import com.cloud.event.UsageEventUtils;
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
@ -1147,7 +1148,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||||||
+ "and the hyphen ('-'); can't start or end with \"-\"");
|
+ "and the hyphen ('-'); can't start or end with \"-\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Transaction.execute(new TransactionCallback<VpcVO>() {
|
VpcVO vpcVO = Transaction.execute(new TransactionCallback<VpcVO>() {
|
||||||
@Override
|
@Override
|
||||||
public VpcVO doInTransaction(final TransactionStatus status) {
|
public VpcVO doInTransaction(final TransactionStatus status) {
|
||||||
final VpcVO persistedVpc = vpcDao.persist(vpc, finalizeServicesAndProvidersForVpc(vpc.getZoneId(), vpc.getVpcOfferingId()));
|
final VpcVO persistedVpc = vpcDao.persist(vpc, finalizeServicesAndProvidersForVpc(vpc.getZoneId(), vpc.getVpcOfferingId()));
|
||||||
@ -1157,6 +1158,10 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||||||
return persistedVpc;
|
return persistedVpc;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (vpcVO != null) {
|
||||||
|
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VPC_CREATE, vpcVO.getAccountId(), vpcVO.getZoneId(), vpcVO.getId(), vpcVO.getName(), Vpc.class.getName(), vpcVO.getUuid(), vpcVO.isDisplay());
|
||||||
|
}
|
||||||
|
return vpcVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, List<String>> finalizeServicesAndProvidersForVpc(final long zoneId, final long offeringId) {
|
private Map<String, List<String>> finalizeServicesAndProvidersForVpc(final long zoneId, final long offeringId) {
|
||||||
@ -1255,6 +1260,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||||||
// executed successfully
|
// executed successfully
|
||||||
if (vpcDao.remove(vpc.getId())) {
|
if (vpcDao.remove(vpc.getId())) {
|
||||||
s_logger.debug("Vpc " + vpc + " is destroyed successfully");
|
s_logger.debug("Vpc " + vpc + " is destroyed successfully");
|
||||||
|
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VPC_DELETE, vpc.getAccountId(), vpc.getZoneId(), vpc.getId(), vpc.getName(), Vpc.class.getName(), vpc.getUuid(), vpc.isDisplay());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
s_logger.warn("Vpc " + vpc + " failed to destroy");
|
s_logger.warn("Vpc " + vpc + " failed to destroy");
|
||||||
|
|||||||
@ -32,6 +32,9 @@ import java.util.concurrent.Future;
|
|||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import com.cloud.network.vpc.Vpc;
|
||||||
|
import com.cloud.usage.dao.UsageVpcDao;
|
||||||
|
import com.cloud.usage.parser.VpcUsageParser;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
import javax.persistence.EntityExistsException;
|
import javax.persistence.EntityExistsException;
|
||||||
@ -170,6 +173,9 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||||||
@Inject
|
@Inject
|
||||||
private BucketStatisticsDao _bucketStatisticsDao;
|
private BucketStatisticsDao _bucketStatisticsDao;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private UsageVpcDao usageVpcDao;
|
||||||
|
|
||||||
private String _version = null;
|
private String _version = null;
|
||||||
private final Calendar _jobExecTime = Calendar.getInstance();
|
private final Calendar _jobExecTime = Calendar.getInstance();
|
||||||
private int _aggregationDuration = 0;
|
private int _aggregationDuration = 0;
|
||||||
@ -1034,6 +1040,10 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||||||
s_logger.debug("Bucket usage successfully parsed? " + parsed + " (for account: " + account.getAccountName() + ", id: " + account.getId() + ")");
|
s_logger.debug("Bucket usage successfully parsed? " + parsed + " (for account: " + account.getAccountName() + ", id: " + account.getId() + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
parsed = VpcUsageParser.parse(account, currentStartDate, currentEndDate);
|
||||||
|
if (!parsed) {
|
||||||
|
s_logger.debug(String.format("VPC usage failed to parse for account [%s].", account));
|
||||||
|
}
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1068,6 +1078,8 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||||||
createVmSnapshotOnPrimaryEvent(event);
|
createVmSnapshotOnPrimaryEvent(event);
|
||||||
} else if (isBackupEvent(eventType)) {
|
} else if (isBackupEvent(eventType)) {
|
||||||
createBackupEvent(event);
|
createBackupEvent(event);
|
||||||
|
} else if (EventTypes.isVpcEvent(eventType)) {
|
||||||
|
handleVpcEvent(event);
|
||||||
}
|
}
|
||||||
} catch (EntityExistsException e) {
|
} catch (EntityExistsException e) {
|
||||||
s_logger.warn(String.format("Failed to create usage event id: %d type: %s due to %s", event.getId(), eventType, e.getMessage()), e);
|
s_logger.warn(String.format("Failed to create usage event id: %d type: %s due to %s", event.getId(), eventType, e.getMessage()), e);
|
||||||
@ -2113,6 +2125,19 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleVpcEvent(UsageEventVO event) {
|
||||||
|
Account account = _accountDao.findByIdIncludingRemoved(event.getAccountId());
|
||||||
|
long domainId = account.getDomainId();
|
||||||
|
if (EventTypes.EVENT_VPC_DELETE.equals(event.getType())) {
|
||||||
|
usageVpcDao.remove(event.getResourceId(), event.getCreateDate());
|
||||||
|
} else if (EventTypes.EVENT_VPC_CREATE.equals(event.getType())) {
|
||||||
|
UsageVpcVO usageVPCVO = new UsageVpcVO(event.getResourceId(), event.getZoneId(), event.getAccountId(), domainId, Vpc.State.Enabled.name(), event.getCreateDate(), null);
|
||||||
|
usageVpcDao.persist(usageVPCVO);
|
||||||
|
} else {
|
||||||
|
s_logger.error(String.format("Unknown event type [%s] in VPC event parser. Skipping it.", event.getType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class Heartbeat extends ManagedContextRunnable {
|
private class Heartbeat extends ManagedContextRunnable {
|
||||||
@Override
|
@Override
|
||||||
protected void runInContext() {
|
protected void runInContext() {
|
||||||
|
|||||||
@ -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 com.cloud.usage.parser;
|
||||||
|
|
||||||
|
import com.cloud.usage.UsageVpcVO;
|
||||||
|
import com.cloud.usage.dao.UsageDao;
|
||||||
|
import com.cloud.usage.UsageVO;
|
||||||
|
import com.cloud.usage.dao.UsageVpcDao;
|
||||||
|
import com.cloud.user.AccountVO;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import org.apache.cloudstack.usage.UsageTypes;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class VpcUsageParser {
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(VpcUsageParser.class.getName());
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private UsageVpcDao vpcDao;
|
||||||
|
@Inject
|
||||||
|
private UsageDao usageDao;
|
||||||
|
|
||||||
|
private static UsageDao s_usageDao;
|
||||||
|
private static UsageVpcDao s_usageVpcDao;
|
||||||
|
@PostConstruct
|
||||||
|
void init() {
|
||||||
|
s_usageDao = usageDao;
|
||||||
|
s_usageVpcDao = vpcDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean parse(AccountVO account, Date startDate, Date endDate) {
|
||||||
|
LOGGER.debug(String.format("Parsing all VPC usage events for account [%s].", account.getId()));
|
||||||
|
if ((endDate == null) || endDate.after(new Date())) {
|
||||||
|
endDate = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<UsageVpcVO> usageVPCs = s_usageVpcDao.getUsageRecords(account.getId(), startDate, endDate);
|
||||||
|
if (usageVPCs == null || usageVPCs.isEmpty()) {
|
||||||
|
LOGGER.debug(String.format("Cannot find any VPC usage for account [%s] in period between [%s] and [%s].", account, startDate, endDate));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final UsageVpcVO usageVPC : usageVPCs) {
|
||||||
|
Long zoneId = usageVPC.getZoneId();
|
||||||
|
Date createdDate = usageVPC.getCreated();
|
||||||
|
Date removedDate = usageVPC.getRemoved();
|
||||||
|
if (createdDate.before(startDate)) {
|
||||||
|
createdDate = startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removedDate == null || removedDate.after(endDate)) {
|
||||||
|
removedDate = endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
final long duration = (removedDate.getTime() - createdDate.getTime()) + 1;
|
||||||
|
final float usage = duration / 1000f / 60f / 60f;
|
||||||
|
DecimalFormat dFormat = new DecimalFormat("#.######");
|
||||||
|
String usageDisplay = dFormat.format(usage);
|
||||||
|
|
||||||
|
long vpcId = usageVPC.getVpcId();
|
||||||
|
LOGGER.debug(String.format("Creating VPC usage record with id [%s], usage [%s], startDate [%s], and endDate [%s], for account [%s].",
|
||||||
|
vpcId, usageDisplay, startDate, endDate, account.getId()));
|
||||||
|
|
||||||
|
String description = String.format("VPC usage for VPC ID: %d", usageVPC.getVpcId());
|
||||||
|
UsageVO usageRecord =
|
||||||
|
new UsageVO(zoneId, account.getAccountId(), account.getDomainId(), description, usageDisplay + " Hrs",
|
||||||
|
UsageTypes.VPC, (double) usage, null, null, null, null, usageVPC.getVpcId(),
|
||||||
|
(long)0, null, startDate, endDate);
|
||||||
|
s_usageDao.persist(usageRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user