Skip to content

Commit 083badf

Browse files
committed
Track volume usage data at vm granularity as well.
1 parent c6daeb4 commit 083badf

File tree

18 files changed

+320
-153
lines changed

18 files changed

+320
-153
lines changed

engine/components-api/src/main/java/com/cloud/event/UsageEventUtils.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ public static void publishUsageEvent(String usageType, long accountId, long zone
9494

9595
}
9696

97+
public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId,
98+
Long size, String entityType, String entityUUID, Long vmId, boolean displayResource) {
99+
if (displayResource) {
100+
saveUsageEvent(usageType, accountId, zoneId, resourceId, offeringId, templateId, size, vmId, resourceName);
101+
}
102+
publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID);
103+
}
104+
97105
public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId,
98106
Long size, Long virtualSize, String entityType, String entityUUID, Map<String, String> details) {
99107
saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, size, virtualSize, details);
@@ -202,6 +210,10 @@ public static void saveUsageEvent(String usageType, long accountId, long zoneId,
202210
s_usageEventDao.persist(new UsageEventVO(usageType, accountId, zoneId, vmId, securityGroupId));
203211
}
204212

213+
public static void saveUsageEvent(String usageType, long accountId, long zoneId, long resourceId, Long offeringId, Long templateId, Long size, Long vmId, String resourceName) {
214+
s_usageEventDao.persist(new UsageEventVO(usageType, accountId, zoneId, resourceId, offeringId, templateId, size, vmId, resourceName));
215+
}
216+
205217
private static void publishUsageEvent(String usageEventType, Long accountId, Long zoneId, String resourceType, String resourceUUID) {
206218
String configKey = "publish.usage.events";
207219
String value = s_configDao.getValue(configKey);

engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offeri
871871
// Save usage event and update resource count for user vm volumes
872872
if (vm.getType() == VirtualMachine.Type.User) {
873873
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size,
874-
Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume());
874+
Volume.class.getName(), vol.getUuid(), vol.getInstanceId(), vol.isDisplayVolume());
875875
_resourceLimitMgr.incrementVolumeResourceCount(vm.getAccountId(), vol.isDisplayVolume(), vol.getSize(), offering);
876876
}
877877
DiskProfile diskProfile = toDiskProfile(vol, offering);
@@ -941,7 +941,7 @@ private DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering
941941
}
942942

943943
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offeringId, vol.getTemplateId(), size,
944-
Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume());
944+
Volume.class.getName(), vol.getUuid(), vol.getInstanceId(), vol.isDisplayVolume());
945945

946946
_resourceLimitMgr.incrementVolumeResourceCount(vm.getAccountId(), vol.isDisplayVolume(), vol.getSize(), offering);
947947
}

engine/schema/src/main/java/com/cloud/event/UsageEventVO.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ public enum DynamicParameters {
7575
@Column(name = "virtual_size")
7676
private Long virtualSize;
7777

78+
@Column(name = "vm_id")
79+
private Long vmId;
80+
7881
public UsageEventVO() {
7982
}
8083

@@ -143,6 +146,18 @@ public UsageEventVO(String usageType, long accountId, long zoneId, long vmId, lo
143146
this.offeringId = securityGroupId;
144147
}
145148

149+
public UsageEventVO(String usageType, long accountId, long zoneId, long resourceId, Long offeringId, Long templateId, Long size, Long vmId, String resourceName) {
150+
this.type = usageType;
151+
this.accountId = accountId;
152+
this.zoneId = zoneId;
153+
this.resourceId = resourceId;
154+
this.offeringId = offeringId;
155+
this.templateId = templateId;
156+
this.size = size;
157+
this.vmId = vmId;
158+
this.resourceName = resourceName;
159+
}
160+
146161
@Override
147162
public long getId() {
148163
return id;
@@ -248,4 +263,11 @@ public void setVirtualSize(Long virtualSize) {
248263
this.virtualSize = virtualSize;
249264
}
250265

266+
public Long getVmId() {
267+
return vmId;
268+
}
269+
270+
public void setVmId(Long vmId) {
271+
this.vmId = vmId;
272+
}
251273
}

engine/schema/src/main/java/com/cloud/event/dao/UsageEventDaoImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ public class UsageEventDaoImpl extends GenericDaoBase<UsageEventVO, Long> implem
4545
private final SearchBuilder<UsageEventVO> latestEventsSearch;
4646
private final SearchBuilder<UsageEventVO> IpeventsSearch;
4747
private static final String COPY_EVENTS =
48-
"INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size) "
49-
+ "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size FROM cloud.usage_event vmevt WHERE vmevt.id > ? and vmevt.id <= ? ";
48+
"INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size, vm_id) "
49+
+ "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size, vm_id FROM cloud.usage_event vmevt WHERE vmevt.id > ? and vmevt.id <= ? ";
5050
private static final String COPY_ALL_EVENTS =
51-
"INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size) "
52-
+ "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size FROM cloud.usage_event vmevt WHERE vmevt.id <= ?";
51+
"INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size, vm_id) "
52+
+ "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size, vm_id FROM cloud.usage_event vmevt WHERE vmevt.id <= ?";
5353
private static final String COPY_EVENT_DETAILS = "INSERT INTO cloud_usage.usage_event_details (id, usage_event_id, name, value) "
5454
+ "SELECT id, usage_event_id, name, value FROM cloud.usage_event_details vmevtDetails WHERE vmevtDetails.usage_event_id > ? and vmevtDetails.usage_event_id <= ? ";
5555
private static final String COPY_ALL_EVENT_DETAILS = "INSERT INTO cloud_usage.usage_event_details (id, usage_event_id, name, value) "
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.upgrade.dao;
18+
19+
import java.io.InputStream;
20+
import java.sql.Connection;
21+
22+
import com.cloud.utils.exception.CloudRuntimeException;
23+
24+
public class Upgrade41930to41940 implements DbUpgrade {
25+
26+
@Override
27+
public String[] getUpgradableVersionRange() {
28+
return new String[]{"4.19.3.0", "4.19.4.0"};
29+
}
30+
31+
@Override
32+
public String getUpgradedVersion() {
33+
return "4.19.4.0";
34+
}
35+
36+
@Override
37+
public boolean supportsRollingUpgrade() {
38+
return false;
39+
}
40+
41+
@Override
42+
public InputStream[] getPrepareScripts() {
43+
final String scriptFile = "META-INF/db/schema-41930to41940.sql";
44+
final InputStream script = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFile);
45+
if (script == null) {
46+
throw new CloudRuntimeException("Unable to find " + scriptFile);
47+
}
48+
49+
return new InputStream[]{script};
50+
}
51+
52+
@Override
53+
public void performDataMigration(Connection conn) {
54+
}
55+
56+
@Override
57+
public InputStream[] getCleanupScripts() {
58+
return new InputStream[0];
59+
}
60+
}

engine/schema/src/main/java/com/cloud/usage/UsageVolumeVO.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public class UsageVolumeVO implements InternalIdentity {
5959
@Column(name = "size")
6060
private long size;
6161

62+
@Column(name = "vm_id")
63+
private Long vmId;
64+
6265
@Column(name = "created")
6366
@Temporal(value = TemporalType.TIMESTAMP)
6467
private Date created = null;
@@ -70,13 +73,14 @@ public class UsageVolumeVO implements InternalIdentity {
7073
protected UsageVolumeVO() {
7174
}
7275

73-
public UsageVolumeVO(long id, long zoneId, long accountId, long domainId, Long diskOfferingId, Long templateId, long size, Date created, Date deleted) {
76+
public UsageVolumeVO(long id, long zoneId, long accountId, long domainId, Long diskOfferingId, Long templateId, Long vmId, long size, Date created, Date deleted) {
7477
this.volumeId = id;
7578
this.zoneId = zoneId;
7679
this.accountId = accountId;
7780
this.domainId = domainId;
7881
this.diskOfferingId = diskOfferingId;
7982
this.templateId = templateId;
83+
this.vmId = vmId;
8084
this.size = size;
8185
this.created = created;
8286
this.deleted = deleted;
@@ -126,4 +130,12 @@ public void setDeleted(Date deleted) {
126130
public long getVolumeId() {
127131
return volumeId;
128132
}
133+
134+
public Long getVmId() {
135+
return vmId;
136+
}
137+
138+
public void setVmId(Long vmId) {
139+
this.vmId = vmId;
140+
}
129141
}

engine/schema/src/main/java/com/cloud/usage/dao/UsageStorageDaoImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public UsageStorageDaoImpl() {
5757
IdSearch.and("accountId", IdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
5858
IdSearch.and("id", IdSearch.entity().getEntityId(), SearchCriteria.Op.EQ);
5959
IdSearch.and("type", IdSearch.entity().getStorageType(), SearchCriteria.Op.EQ);
60+
IdSearch.and("deleted", IdSearch.entity().getDeleted(), SearchCriteria.Op.NULL);
6061
IdSearch.done();
6162

6263
IdZoneSearch = createSearchBuilder();
@@ -74,6 +75,7 @@ public List<UsageStorageVO> listById(long accountId, long id, int type) {
7475
sc.setParameters("accountId", accountId);
7576
sc.setParameters("id", id);
7677
sc.setParameters("type", type);
78+
sc.setParameters("deleted", null);
7779
return listBy(sc, null);
7880
}
7981

engine/schema/src/main/java/com/cloud/usage/dao/UsageVolumeDao.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@
2323
import com.cloud.utils.db.GenericDao;
2424

2525
public interface UsageVolumeDao extends GenericDao<UsageVolumeVO, Long> {
26-
public void removeBy(long userId, long id);
27-
28-
public void update(UsageVolumeVO usage);
29-
3026
public List<UsageVolumeVO> getUsageRecords(Long accountId, Long domainId, Date startDate, Date endDate, boolean limit, int page);
27+
28+
List<UsageVolumeVO> listByVolumeId(long volumeId, long accountId);
3129
}

engine/schema/src/main/java/com/cloud/usage/dao/UsageVolumeDaoImpl.java

Lines changed: 33 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -18,81 +18,47 @@
1818

1919
import java.sql.PreparedStatement;
2020
import java.sql.ResultSet;
21-
import java.sql.SQLException;
2221
import java.util.ArrayList;
2322
import java.util.Date;
2423
import java.util.List;
2524
import java.util.TimeZone;
2625

2726

28-
import com.cloud.exception.CloudException;
27+
import javax.annotation.PostConstruct;
28+
29+
import org.apache.log4j.Logger;
2930
import org.springframework.stereotype.Component;
3031

3132
import com.cloud.usage.UsageVolumeVO;
3233
import com.cloud.utils.DateUtil;
3334
import com.cloud.utils.db.GenericDaoBase;
35+
import com.cloud.utils.db.SearchBuilder;
36+
import com.cloud.utils.db.SearchCriteria;
3437
import com.cloud.utils.db.TransactionLegacy;
3538

3639
@Component
3740
public class UsageVolumeDaoImpl extends GenericDaoBase<UsageVolumeVO, Long> implements UsageVolumeDao {
3841

39-
protected static final String REMOVE_BY_USERID_VOLID = "DELETE FROM usage_volume WHERE account_id = ? AND volume_id = ?";
40-
protected static final String UPDATE_DELETED = "UPDATE usage_volume SET deleted = ? WHERE account_id = ? AND volume_id = ? and deleted IS NULL";
41-
protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, size, created, deleted "
42+
protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, vm_id, size, created, deleted "
4243
+ "FROM usage_volume " + "WHERE account_id = ? AND ((deleted IS NULL) OR (created BETWEEN ? AND ?) OR "
4344
+ " (deleted BETWEEN ? AND ?) OR ((created <= ?) AND (deleted >= ?)))";
44-
protected static final String GET_USAGE_RECORDS_BY_DOMAIN = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, size, created, deleted "
45+
protected static final String GET_USAGE_RECORDS_BY_DOMAIN = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, vm_id, size, created, deleted "
4546
+ "FROM usage_volume " + "WHERE domain_id = ? AND ((deleted IS NULL) OR (created BETWEEN ? AND ?) OR "
4647
+ " (deleted BETWEEN ? AND ?) OR ((created <= ?) AND (deleted >= ?)))";
47-
protected static final String GET_ALL_USAGE_RECORDS = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, size, created, deleted "
48+
protected static final String GET_ALL_USAGE_RECORDS = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, vm_id, size, created, deleted "
4849
+ "FROM usage_volume " + "WHERE (deleted IS NULL) OR (created BETWEEN ? AND ?) OR " + " (deleted BETWEEN ? AND ?) OR ((created <= ?) AND (deleted >= ?))";
50+
private SearchBuilder<UsageVolumeVO> volumeSearch;
4951

5052
public UsageVolumeDaoImpl() {
5153
}
5254

53-
@Override
54-
public void removeBy(long accountId, long volId) {
55-
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
56-
try {
57-
txn.start();
58-
try(PreparedStatement pstmt = txn.prepareStatement(REMOVE_BY_USERID_VOLID);) {
59-
if (pstmt != null) {
60-
pstmt.setLong(1, accountId);
61-
pstmt.setLong(2, volId);
62-
pstmt.executeUpdate();
63-
}
64-
}catch (SQLException e) {
65-
throw new CloudException("Error removing usageVolumeVO:"+e.getMessage(), e);
66-
}
67-
txn.commit();
68-
} catch (Exception e) {
69-
txn.rollback();
70-
logger.warn("Error removing usageVolumeVO:"+e.getMessage(), e);
71-
} finally {
72-
txn.close();
73-
}
74-
}
75-
76-
@Override
77-
public void update(UsageVolumeVO usage) {
78-
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
79-
PreparedStatement pstmt = null;
80-
try {
81-
txn.start();
82-
if (usage.getDeleted() != null) {
83-
pstmt = txn.prepareAutoCloseStatement(UPDATE_DELETED);
84-
pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), usage.getDeleted()));
85-
pstmt.setLong(2, usage.getAccountId());
86-
pstmt.setLong(3, usage.getVolumeId());
87-
pstmt.executeUpdate();
88-
}
89-
txn.commit();
90-
} catch (Exception e) {
91-
txn.rollback();
92-
logger.warn("Error updating UsageVolumeVO", e);
93-
} finally {
94-
txn.close();
95-
}
55+
@PostConstruct
56+
protected void init() {
57+
volumeSearch = createSearchBuilder();
58+
volumeSearch.and("accountId", volumeSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
59+
volumeSearch.and("volumeId", volumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
60+
volumeSearch.and("deleted", volumeSearch.entity().getDeleted(), SearchCriteria.Op.NULL);
61+
volumeSearch.done();
9662
}
9763

9864
@Override
@@ -150,11 +116,15 @@ public List<UsageVolumeVO> getUsageRecords(Long accountId, Long domainId, Date s
150116
if (tId == 0) {
151117
tId = null;
152118
}
153-
long size = Long.valueOf(rs.getLong(7));
119+
Long vmId = Long.valueOf(rs.getLong(7));
120+
if (vmId == 0) {
121+
vmId = null;
122+
}
123+
long size = Long.valueOf(rs.getLong(8));
154124
Date createdDate = null;
155125
Date deletedDate = null;
156-
String createdTS = rs.getString(8);
157-
String deletedTS = rs.getString(9);
126+
String createdTS = rs.getString(9);
127+
String deletedTS = rs.getString(10);
158128

159129
if (createdTS != null) {
160130
createdDate = DateUtil.parseDateString(s_gmtTimeZone, createdTS);
@@ -163,7 +133,7 @@ public List<UsageVolumeVO> getUsageRecords(Long accountId, Long domainId, Date s
163133
deletedDate = DateUtil.parseDateString(s_gmtTimeZone, deletedTS);
164134
}
165135

166-
usageRecords.add(new UsageVolumeVO(vId, zoneId, acctId, dId, doId, tId, size, createdDate, deletedDate));
136+
usageRecords.add(new UsageVolumeVO(vId, zoneId, acctId, dId, doId, tId, vmId, size, createdDate, deletedDate));
167137
}
168138
} catch (Exception e) {
169139
txn.rollback();
@@ -174,4 +144,13 @@ public List<UsageVolumeVO> getUsageRecords(Long accountId, Long domainId, Date s
174144

175145
return usageRecords;
176146
}
147+
148+
@Override
149+
public List<UsageVolumeVO> listByVolumeId(long volumeId, long accountId) {
150+
SearchCriteria<UsageVolumeVO> sc = volumeSearch.create();
151+
sc.setParameters("accountId", accountId);
152+
sc.setParameters("volumeId", volumeId);
153+
sc.setParameters("deleted", null);
154+
return listBy(sc);
155+
}
177156
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-- Licensed to the Apache Software Foundation (ASF) under one
2+
-- or more contributor license agreements. See the NOTICE file
3+
-- distributed with this work for additional information
4+
-- regarding copyright ownership. The ASF licenses this file
5+
-- to you under the Apache License, Version 2.0 (the
6+
-- "License"); you may not use this file except in compliance
7+
-- with the License. You may obtain a copy of the License at
8+
--
9+
-- http://www.apache.org/licenses/LICENSE-2.0
10+
--
11+
-- Unless required by applicable law or agreed to in writing,
12+
-- software distributed under the License is distributed on an
13+
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
-- KIND, either express or implied. See the License for the
15+
-- specific language governing permissions and limitations
16+
-- under the License.
17+
18+
--;
19+
-- Schema upgrade from 4.19.3.0 to 4.19.4.0
20+
--;
21+
22+
-- Add vm_id column to usage_event table for volume usage events
23+
ALTER TABLE `cloud`.`usage_event` ADD COLUMN `vm_id` bigint unsigned NULL COMMENT 'VM ID associated with volume usage events';
24+
ALTER TABLE `cloud_usage`.`usage_event` ADD COLUMN `vm_id` bigint unsigned NULL COMMENT 'VM ID associated with volume usage events';
25+
26+
-- Add vm_id column to cloud_usage.usage_volume table
27+
ALTER TABLE `cloud_usage`.`usage_volume` ADD COLUMN `vm_id` bigint unsigned NULL COMMENT 'VM ID associated with the volume usage';

0 commit comments

Comments
 (0)