This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/master by this push:
new 391952d CLOUDSTACK-9867: VM snapshot on primary storage usage metrics
(#2035)
391952d is described below
commit 391952da5bd522e44e0a17723c6ec77254a76353
Author: Abhinandan Prateek <[email protected]>
AuthorDate: Thu Dec 28 14:57:10 2017 +0530
CLOUDSTACK-9867: VM snapshot on primary storage usage metrics (#2035)
VM snapshot on primary storage usage metrics.
---
api/src/com/cloud/event/EventTypes.java | 6 +
.../org/apache/cloudstack/usage/UsageTypes.java | 2 +
.../resources/META-INF/db/schema-41000to41100.sql | 17 +++
...apshotVO.java => UsageSnapshotOnPrimaryVO.java} | 66 +++++++----
.../src/com/cloud/usage/UsageVMSnapshotVO.java | 6 +
.../usage/dao/UsageVMSnapshotOnPrimaryDao.java | 31 +++++
.../usage/dao/UsageVMSnapshotOnPrimaryDaoImpl.java | 117 +++++++++++++++++++
.../storage/snapshot/SnapshotServiceImpl.java | 4 +
.../snapshot/StorageSystemSnapshotStrategy.java | 6 +
.../snapshot/XenserverSnapshotStrategy.java | 6 +-
.../vmsnapshot/DefaultVMSnapshotStrategy.java | 26 ++++-
.../storage/endpoint/DefaultEndPointSelector.java | 1 +
.../cloudstack/quota/constant/QuotaTypes.java | 1 +
usage/src/com/cloud/usage/UsageManagerImpl.java | 62 ++++++++++
.../usage/parser/VMSanpshotOnPrimaryParser.java | 129 +++++++++++++++++++++
15 files changed, 454 insertions(+), 26 deletions(-)
diff --git a/api/src/com/cloud/event/EventTypes.java
b/api/src/com/cloud/event/EventTypes.java
index ce410a6..26b6922 100644
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -241,6 +241,8 @@ public class EventTypes {
// Snapshots
public static final String EVENT_SNAPSHOT_CREATE = "SNAPSHOT.CREATE";
+ public static final String EVENT_SNAPSHOT_ON_PRIMARY =
"SNAPSHOT.ON_PRIMARY";
+ public static final String EVENT_SNAPSHOT_OFF_PRIMARY =
"SNAPSHOT.OFF_PRIMARY";
public static final String EVENT_SNAPSHOT_DELETE = "SNAPSHOT.DELETE";
public static final String EVENT_SNAPSHOT_REVERT = "SNAPSHOT.REVERT";
public static final String EVENT_SNAPSHOT_POLICY_CREATE =
"SNAPSHOTPOLICY.CREATE";
@@ -462,6 +464,8 @@ public class EventTypes {
// vm snapshot events
public static final String EVENT_VM_SNAPSHOT_CREATE = "VMSNAPSHOT.CREATE";
public static final String EVENT_VM_SNAPSHOT_DELETE = "VMSNAPSHOT.DELETE";
+ public static final String EVENT_VM_SNAPSHOT_ON_PRIMARY =
"VMSNAPSHOT.ON_PRIMARY";
+ public static final String EVENT_VM_SNAPSHOT_OFF_PRIMARY =
"VMSNAPSHOT.OFF_PRIMARY";
public static final String EVENT_VM_SNAPSHOT_REVERT =
"VMSNAPSHOT.REVERTTO";
// external network device events
@@ -711,6 +715,8 @@ public class EventTypes {
// Snapshots
entityEventDetails.put(EVENT_SNAPSHOT_CREATE, Snapshot.class);
entityEventDetails.put(EVENT_SNAPSHOT_DELETE, Snapshot.class);
+ entityEventDetails.put(EVENT_SNAPSHOT_ON_PRIMARY, Snapshot.class);
+ entityEventDetails.put(EVENT_SNAPSHOT_OFF_PRIMARY, Snapshot.class);
entityEventDetails.put(EVENT_SNAPSHOT_POLICY_CREATE,
SnapshotPolicy.class);
entityEventDetails.put(EVENT_SNAPSHOT_POLICY_UPDATE,
SnapshotPolicy.class);
entityEventDetails.put(EVENT_SNAPSHOT_POLICY_DELETE,
SnapshotPolicy.class);
diff --git a/api/src/org/apache/cloudstack/usage/UsageTypes.java
b/api/src/org/apache/cloudstack/usage/UsageTypes.java
index 08cd7dd..f03d9a9 100644
--- a/api/src/org/apache/cloudstack/usage/UsageTypes.java
+++ b/api/src/org/apache/cloudstack/usage/UsageTypes.java
@@ -43,6 +43,7 @@ public class UsageTypes {
public static final int VM_DISK_BYTES_WRITE = 24;
public static final int VM_SNAPSHOT = 25;
public static final int VOLUME_SECONDARY = 26;
+ public static final int VM_SNAPSHOT_ON_PRIMARY = 27;
public static List<UsageTypeResponse> listUsageTypes() {
List<UsageTypeResponse> responseList = new
ArrayList<UsageTypeResponse>();
@@ -65,6 +66,7 @@ public class UsageTypes {
responseList.add(new UsageTypeResponse(VM_DISK_BYTES_READ, "VM Disk
usage(Bytes Read)"));
responseList.add(new UsageTypeResponse(VM_DISK_BYTES_WRITE, "VM Disk
usage(Bytes Write)"));
responseList.add(new UsageTypeResponse(VM_SNAPSHOT, "VM Snapshot
storage usage"));
+ responseList.add(new UsageTypeResponse(VM_SNAPSHOT_ON_PRIMARY, "VM
Snapshot on primary storage usage"));
return responseList;
}
}
diff --git a/engine/schema/resources/META-INF/db/schema-41000to41100.sql
b/engine/schema/resources/META-INF/db/schema-41000to41100.sql
index 19c9039..5d51b47 100644
--- a/engine/schema/resources/META-INF/db/schema-41000to41100.sql
+++ b/engine/schema/resources/META-INF/db/schema-41000to41100.sql
@@ -490,6 +490,23 @@ INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,
hypervisor_type, hypervi
INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type,
hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined)
SELECT UUID(),'Xenserver', '7.2.0', guest_os_name, guest_os_id,
utc_timestamp(), 0 FROM `cloud`.`guest_os_hypervisor` WHERE
hypervisor_type='Xenserver' AND hypervisor_version='7.1.0' AND guest_os_id not
in
(1,2,3,4,56,101,56,58,93,94,50,51,87,88,89,90,91,92,26,27,28,29,40,41,42,43,44,45,96,97,107,108,109,110,151,152,153);
+-- Add table to track primary storage in use for snapshots
+DROP TABLE IF EXISTS `cloud_usage`.`usage_snapshot_on_primary`;
+CREATE TABLE `cloud_usage`.`usage_snapshot_on_primary` (
+ `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,
+ `vm_id` bigint(20) unsigned NOT NULL,
+ `name` varchar(128),
+ `type` int(1) unsigned NOT NULL,
+ `physicalsize` bigint(20),
+ `virtualsize` bigint(20),
+ `created` datetime NOT NULL,
+ `deleted` datetime,
+ INDEX `i_usage_snapshot_on_primary` (`account_id`,`id`,`vm_id`,`created`)
+) ENGINE=InnoDB CHARSET=utf8;
+
-- Change monitor patch for apache2 in systemvm
UPDATE `cloud`.`monitoring_services` SET
pidfile="/var/run/apache2/apache2.pid" WHERE process_name="apache2" AND
service_name="apache2";
diff --git a/engine/schema/src/com/cloud/usage/UsageVMSnapshotVO.java
b/engine/schema/src/com/cloud/usage/UsageSnapshotOnPrimaryVO.java
similarity index 58%
copy from engine/schema/src/com/cloud/usage/UsageVMSnapshotVO.java
copy to engine/schema/src/com/cloud/usage/UsageSnapshotOnPrimaryVO.java
index 1266d63..74f944b 100644
--- a/engine/schema/src/com/cloud/usage/UsageVMSnapshotVO.java
+++ b/engine/schema/src/com/cloud/usage/UsageSnapshotOnPrimaryVO.java
@@ -27,8 +27,8 @@ import javax.persistence.TemporalType;
import org.apache.cloudstack.api.InternalIdentity;
@Entity
-@Table(name = "usage_vmsnapshot")
-public class UsageVMSnapshotVO implements InternalIdentity {
+@Table(name = "usage_snapshot_on_primary")
+public class UsageSnapshotOnPrimaryVO implements InternalIdentity {
@Column(name = "id")
// volumeId
@@ -46,33 +46,41 @@ public class UsageVMSnapshotVO implements InternalIdentity {
@Column(name = "vm_id")
private long vmId;
- @Column(name = "disk_offering_id")
- private Long diskOfferingId;
+ @Column(name = "name")
+ private String name;
- @Column(name = "size")
- private long size;
+ @Column(name = "type")
+ private int snapshotType;
+
+ @Column(name = "physicalsize")
+ private long physicalSize;
@Column(name = "created")
@Temporal(value = TemporalType.TIMESTAMP)
private Date created = null;
- @Column(name = "processed")
+ @Column(name = "deleted")
@Temporal(value = TemporalType.TIMESTAMP)
- private Date processed;
+ private Date deleted;
+
+ @Column(name = "virtualsize")
+ private Long virtualSize;
- protected UsageVMSnapshotVO() {
+ protected UsageSnapshotOnPrimaryVO() {
}
- public UsageVMSnapshotVO(long id, long zoneId, long accountId, long
domainId, long vmId, Long diskOfferingId, long size, Date created, Date
processed) {
+ public UsageSnapshotOnPrimaryVO(long id, long zoneId, long accountId, long
domainId, long vmId, String name, int type, long virtualSize, long
physicalSize, Date created, Date deleted) {
+ this.id = id;
this.zoneId = zoneId;
this.accountId = accountId;
this.domainId = domainId;
- this.diskOfferingId = diskOfferingId;
- this.id = id;
- this.size = size;
+ this.snapshotType = type;
+ this.physicalSize = physicalSize;
+ this.virtualSize = virtualSize;
this.created = created;
this.vmId = vmId;
- this.processed = processed;
+ this.name = name;
+ this.deleted = deleted;
}
public long getZoneId() {
@@ -87,20 +95,24 @@ public class UsageVMSnapshotVO implements InternalIdentity {
return domainId;
}
- public Long getDiskOfferingId() {
- return diskOfferingId;
+ public int getSnapshotType() {
+ return snapshotType;
+ }
+
+ public long getPhysicalSize() {
+ return physicalSize;
}
- public long getSize() {
- return size;
+ public Long getVirtualSize() {
+ return virtualSize;
}
- public Date getProcessed() {
- return processed;
+ public Date getDeleted() {
+ return deleted;
}
- public void setProcessed(Date processed) {
- this.processed = processed;
+ public void setDeleted(Date deleted) {
+ this.deleted = deleted;
}
public Date getCreated() {
@@ -115,9 +127,19 @@ public class UsageVMSnapshotVO implements InternalIdentity
{
return vmId;
}
+ public String getName() {
+ return name;
+ }
+
@Override
public long getId() {
return this.id;
}
+ @Override
+ public String toString() {
+ return "UsageSnapshotOnPrimaryVO [id=" + id + ", zoneId=" + zoneId +
", accountId=" + accountId + ", domainId=" + domainId + ", vmId=" + vmId + ",
name=" + name
+ + ", snapshotType=" + snapshotType + ", physicalSize=" +
physicalSize + ", created=" + created + ", deleted=" + deleted + ",
virtualSize=" + virtualSize + "]";
+ }
+
}
diff --git a/engine/schema/src/com/cloud/usage/UsageVMSnapshotVO.java
b/engine/schema/src/com/cloud/usage/UsageVMSnapshotVO.java
index 1266d63..05a1b29 100644
--- a/engine/schema/src/com/cloud/usage/UsageVMSnapshotVO.java
+++ b/engine/schema/src/com/cloud/usage/UsageVMSnapshotVO.java
@@ -120,4 +120,10 @@ public class UsageVMSnapshotVO implements InternalIdentity
{
return this.id;
}
+ @Override
+ public String toString() {
+ return "UsageVMSnapshotVO [id=" + id + ", zoneId=" + zoneId + ",
accountId=" + accountId + ", domainId=" + domainId + ", vmId=" + vmId + ",
diskOfferingId="
+ + diskOfferingId + ", size=" + size + ", created=" + created +
", processed=" + processed + "]";
+ }
+
}
diff --git
a/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotOnPrimaryDao.java
b/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotOnPrimaryDao.java
new file mode 100644
index 0000000..09d6e00
--- /dev/null
+++ b/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotOnPrimaryDao.java
@@ -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 com.cloud.usage.dao;
+
+import java.util.Date;
+import java.util.List;
+
+import com.cloud.usage.UsageSnapshotOnPrimaryVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface UsageVMSnapshotOnPrimaryDao extends
GenericDao<UsageSnapshotOnPrimaryVO, Long> {
+
+ public void updateDeleted(UsageSnapshotOnPrimaryVO usage);
+
+ public List<UsageSnapshotOnPrimaryVO> getUsageRecords(Long accountId, Long
domainId, Date startDate, Date endDate);
+
+}
diff --git
a/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotOnPrimaryDaoImpl.java
b/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotOnPrimaryDaoImpl.java
new file mode 100644
index 0000000..5926938
--- /dev/null
+++ b/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotOnPrimaryDaoImpl.java
@@ -0,0 +1,117 @@
+// 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 java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.usage.UsageSnapshotOnPrimaryVO;
+import com.cloud.utils.DateUtil;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.TransactionLegacy;
+
+@Component
+public class UsageVMSnapshotOnPrimaryDaoImpl extends
GenericDaoBase<UsageSnapshotOnPrimaryVO, Long> implements
UsageVMSnapshotOnPrimaryDao {
+ public static final Logger s_logger =
Logger.getLogger(UsageVMSnapshotOnPrimaryDaoImpl.class.getName());
+ protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = "SELECT id,
zone_id, account_id, domain_id, vm_id, name, type, physicalsize, virtualsize,
created, deleted "
+ + " FROM usage_snapshot_on_primary" + " WHERE account_id = ? " + " AND
( (created < ? AND deleted is NULL)"
+ + " OR ( deleted BETWEEN ? AND ?)) ORDER BY created asc";
+ protected static final String UPDATE_DELETED = "UPDATE
usage_snapshot_on_primary SET deleted = ? WHERE account_id = ? AND id = ? and
vm_id = ? and created = ?";
+
+ @Override
+ public void updateDeleted(UsageSnapshotOnPrimaryVO usage) {
+ TransactionLegacy txn =
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
+ PreparedStatement pstmt = null;
+ try {
+ txn.start();
+ pstmt = txn.prepareAutoCloseStatement(UPDATE_DELETED);
+ pstmt.setString(1,
DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), usage.getDeleted()));
+ pstmt.setLong(2, usage.getAccountId());
+ pstmt.setLong(3, usage.getId());
+ pstmt.setLong(4, usage.getVmId());
+ pstmt.setString(5,
DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), usage.getCreated()));
+ pstmt.executeUpdate();
+ txn.commit();
+ } catch (Exception e) {
+ txn.rollback();
+ s_logger.warn("Error updating UsageSnapshotOnPrimaryVO", e);
+ } finally {
+ txn.close();
+ }
+ }
+
+ @Override
+ public List<UsageSnapshotOnPrimaryVO> getUsageRecords(Long accountId, Long
domainId, Date startDate, Date endDate) {
+ List<UsageSnapshotOnPrimaryVO> usageRecords = new
ArrayList<UsageSnapshotOnPrimaryVO>();
+
+ String sql = GET_USAGE_RECORDS_BY_ACCOUNT;
+ TransactionLegacy txn =
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
+ PreparedStatement pstmt = null;
+
+ try {
+ int i = 1;
+ pstmt = txn.prepareAutoCloseStatement(sql);
+ 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));
+ s_logger.debug("GET_USAGE_RECORDS_BY_ACCOUNT " + pstmt);
+ ResultSet rs = pstmt.executeQuery();
+ while (rs.next()) {
+ //id, zone_id, account_id, domain_iVMSnapshotVOd, vm_id,
disk_offering_id, size, created, deleted
+ Long vId = Long.valueOf(rs.getLong(1));
+ Long zoneId = Long.valueOf(rs.getLong(2));
+ Long acctId = Long.valueOf(rs.getLong(3));
+ Long dId = Long.valueOf(rs.getLong(4));
+ Long vmId = Long.valueOf(rs.getLong(5));
+ String name = String.valueOf(rs.getString(6));
+ Integer type = Integer.valueOf(rs.getInt(7));
+ Long physicalSize = Long.valueOf(rs.getLong(8));
+ Long virtaulSize = Long.valueOf(rs.getLong(9));
+ Date createdDate = null;
+ Date deleteDate = null;
+ String createdTS = rs.getString(10);
+ String deleted = rs.getString(11);
+
+ if (createdTS != null) {
+ createdDate = DateUtil.parseDateString(s_gmtTimeZone,
createdTS);
+ }
+ if (deleted != null) {
+ deleteDate = DateUtil.parseDateString(s_gmtTimeZone,
deleted);
+ }
+ usageRecords.add(new UsageSnapshotOnPrimaryVO(vId, zoneId,
acctId, dId, vmId, name, type, virtaulSize, physicalSize, createdDate,
deleteDate));
+ }
+ } catch (Exception e) {
+ txn.rollback();
+ s_logger.warn("Error getting usage records", e);
+ } finally {
+ txn.close();
+ }
+
+ return usageRecords;
+ }
+
+}
diff --git
a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
index b7bc447..601959b 100644
---
a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
+++
b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
@@ -49,6 +49,8 @@ import
org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
import org.apache.log4j.Logger;
import com.cloud.storage.CreateSnapshotPayload;
+import com.cloud.event.EventTypes;
+import com.cloud.event.UsageEventUtils;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Snapshot;
import com.cloud.storage.SnapshotVO;
@@ -216,6 +218,8 @@ public class SnapshotServiceImpl implements SnapshotService
{
try {
result = future.get();
+
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_ON_PRIMARY,
snap.getAccountId(), snap.getDataCenterId(), snap.getId(),
+ snap.getName(), null, null, snapshotOnPrimary.getSize(),
snapshotOnPrimary.getSize(), snap.getClass().getName(), snap.getUuid());
return result;
} catch (InterruptedException e) {
s_logger.debug("Failed to create snapshot", e);
diff --git
a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java
b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java
index 185cf56..7aa5388 100644
---
a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java
+++
b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java
@@ -19,6 +19,9 @@ package org.apache.cloudstack.storage.snapshot;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.dc.dao.ClusterDao;
+import com.cloud.event.ActionEvent;
+import com.cloud.event.EventTypes;
+import com.cloud.event.UsageEventUtils;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
@@ -147,6 +150,7 @@ public class StorageSystemSnapshotStrategy extends
SnapshotStrategyBase {
* @return true if snapshot is removed, false otherwise
*/
+ @ActionEvent(eventType = EventTypes.EVENT_SNAPSHOT_OFF_PRIMARY,
eventDescription = "deleting snapshot", async = true)
private boolean cleanupSnapshotOnPrimaryStore(long snapshotId) {
SnapshotObject snapshotObj =
(SnapshotObject)snapshotDataFactory.getSnapshot(snapshotId,
DataStoreRole.Primary);
@@ -176,6 +180,8 @@ public class StorageSystemSnapshotStrategy extends
SnapshotStrategyBase {
snapshotSvr.deleteSnapshot(snapshotObj);
snapshotObj.processEvent(Snapshot.Event.OperationSucceeded);
+
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_OFF_PRIMARY,
snapshotObj.getAccountId(), snapshotObj.getDataCenterId(), snapshotId,
+ snapshotObj.getName(), null, null, 0L,
snapshotObj.getClass().getName(), snapshotObj.getUuid());
}
catch (Exception e) {
s_logger.debug("Failed to delete snapshot: ", e);
diff --git
a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
index a673a462..837b201 100644
---
a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
+++
b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
@@ -42,6 +42,8 @@ import
org.apache.cloudstack.storage.datastore.PrimaryDataStoreImpl;
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
+import com.cloud.event.EventTypes;
+import com.cloud.event.UsageEventUtils;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -97,7 +99,6 @@ public class XenserverSnapshotStrategy extends
SnapshotStrategyBase {
SnapshotInfo parentSnapshot = snapshot.getParent();
if (parentSnapshot != null &&
snapshot.getPath().equalsIgnoreCase(parentSnapshot.getPath())) {
- s_logger.debug("backup an empty snapshot");
// don't need to backup this snapshot
SnapshotDataStoreVO parentSnapshotOnBackupStore =
snapshotStoreDao.findBySnapshot(parentSnapshot.getId(), DataStoreRole.Image);
if (parentSnapshotOnBackupStore != null &&
parentSnapshotOnBackupStore.getState() == State.Ready) {
@@ -254,7 +255,6 @@ public class XenserverSnapshotStrategy extends
SnapshotStrategyBase {
}
if (snapshotVO.getState() == Snapshot.State.CreatedOnPrimary) {
- s_logger.debug("delete snapshot on primary storage:");
snapshotVO.setState(Snapshot.State.Destroyed);
snapshotDao.update(snapshotId, snapshotVO);
return true;
@@ -428,6 +428,8 @@ public class XenserverSnapshotStrategy extends
SnapshotStrategyBase {
SnapshotDataStoreVO snapshotDataStoreVO =
snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(),
primaryStore.getId(), parentSnapshotId);
if (snapshotDataStoreVO != null) {
parentSnapshotId =
snapshotDataStoreVO.getParentSnapshotId();
+
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_OFF_PRIMARY,
parent.getAccountId(), parent.getDataCenterId(), parent.getId(),
+ parent.getName(), null, null, 0L,
0L, parent.getClass().getName(), parent.getUuid());
snapshotStoreDao.remove(snapshotDataStoreVO.getId());
} else {
parentSnapshotId = null;
diff --git
a/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java
b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java
index 71a5e10..ebe8b27 100644
---
a/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java
+++
b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java
@@ -119,6 +119,14 @@ public class DefaultVMSnapshotStrategy extends ManagerBase
implements VMSnapshot
List<VolumeObjectTO> volumeTOs =
vmSnapshotHelper.getVolumeTOList(userVm.getId());
+ long prev_chain_size = 0;
+ long virtual_size=0;
+ for (VolumeObjectTO volume : volumeTOs) {
+ virtual_size += volume.getSize();
+ VolumeVO volumeVO = volumeDao.findById(volume.getId());
+ prev_chain_size += volumeVO.getVmSnapshotChainSize() == null ?
0 : volumeVO.getVmSnapshotChainSize();
+ }
+
VMSnapshotTO current = null;
VMSnapshotVO currentSnapshot =
vmSnapshotDao.findCurrentSnapshotByVmId(userVm.getId());
if (currentSnapshot != null)
@@ -150,10 +158,12 @@ public class DefaultVMSnapshotStrategy extends
ManagerBase implements VMSnapshot
processAnswer(vmSnapshotVO, userVm, answer, hostId);
s_logger.debug("Create vm snapshot " + vmSnapshot.getName() +
" succeeded for vm: " + userVm.getInstanceName());
result = true;
-
+ long new_chain_size=0;
for (VolumeObjectTO volumeTo : answer.getVolumeTOs()) {
publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_CREATE,
vmSnapshot, userVm, volumeTo);
+ new_chain_size += volumeTo.getSize();
}
+ publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_ON_PRIMARY,
vmSnapshot, userVm, new_chain_size - prev_chain_size, virtual_size);
return vmSnapshot;
} else {
String errMsg = "Creating VM snapshot: " +
vmSnapshot.getName() + " failed";
@@ -208,9 +218,12 @@ public class DefaultVMSnapshotStrategy extends ManagerBase
implements VMSnapshot
if (answer != null && answer.getResult()) {
DeleteVMSnapshotAnswer deleteVMSnapshotAnswer =
(DeleteVMSnapshotAnswer)answer;
processAnswer(vmSnapshotVO, userVm, answer, hostId);
+ long full_chain_size=0;
for (VolumeObjectTO volumeTo :
deleteVMSnapshotAnswer.getVolumeTOs()) {
publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_DELETE,
vmSnapshot, userVm, volumeTo);
+ full_chain_size += volumeTo.getSize();
}
+ publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_OFF_PRIMARY,
vmSnapshot, userVm, full_chain_size, 0L);
return true;
} else {
String errMsg = (answer == null) ? null : answer.getDetails();
@@ -325,7 +338,16 @@ public class DefaultVMSnapshotStrategy extends ManagerBase
implements VMSnapshot
}
}
UsageEventUtils.publishUsageEvent(type, vmSnapshot.getAccountId(),
userVm.getDataCenterId(), userVm.getId(), vmSnapshot.getName(), offeringId,
volume.getId(), // save volume's id into templateId field
- volumeTo.getSize(), VMSnapshot.class.getName(),
vmSnapshot.getUuid());
+ volumeTo.getSize(), VMSnapshot.class.getName(),
vmSnapshot.getUuid());
+ }
+
+ private void publishUsageEvent(String type, VMSnapshot vmSnapshot, UserVm
userVm, Long vmSnapSize, Long virtualSize) {
+ try {
+ UsageEventUtils.publishUsageEvent(type, vmSnapshot.getAccountId(),
userVm.getDataCenterId(), userVm.getId(), vmSnapshot.getName(), 0L, 0L,
vmSnapSize, virtualSize,
+ VMSnapshot.class.getName(), vmSnapshot.getUuid());
+ } catch (Exception e) {
+ s_logger.error("Failed to publis usage event " + type, e);
+ }
}
@Override
diff --git
a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
index c25c1ad..158ee18 100644
---
a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
+++
b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
@@ -209,6 +209,7 @@ public class DefaultEndPointSelector implements
EndPointSelector {
@Override
public EndPoint select(DataObject srcData, DataObject destData,
StorageAction action) {
+ s_logger.error("IR24 select BACKUPSNAPSHOT from primary to secondary "
+ srcData.getId() + " dest=" + destData.getId());
if (action == StorageAction.BACKUPSNAPSHOT &&
srcData.getDataStore().getRole() == DataStoreRole.Primary) {
SnapshotInfo srcSnapshot = (SnapshotInfo)srcData;
VolumeInfo volumeInfo = srcSnapshot.getBaseVolume();
diff --git
a/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java
b/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java
index 6e1432d..97e22da 100644
--- a/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java
+++ b/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java
@@ -55,6 +55,7 @@ public class QuotaTypes extends UsageTypes {
quotaTypeList.put(VM_DISK_BYTES_READ, new
QuotaTypes(VM_DISK_BYTES_READ, "VM_DISK_BYTES_READ", "GB", "VM Disk usage(Bytes
Read)"));
quotaTypeList.put(VM_DISK_BYTES_WRITE, new
QuotaTypes(VM_DISK_BYTES_WRITE, "VPN_USERS", "GB", "VM Disk usage(Bytes
Write)"));
quotaTypeList.put(VM_SNAPSHOT, new QuotaTypes(VM_SNAPSHOT,
"VM_SNAPSHOT", "GB-Month", "VM Snapshot storage usage"));
+ quotaTypeList.put(VM_SNAPSHOT_ON_PRIMARY, new
QuotaTypes(VM_SNAPSHOT_ON_PRIMARY, "VM_SNAPSHOT_ON_PRIMARY", "GB-Month", "VM
Snapshot primary storage usage"));
quotaTypeList.put(CPU_CLOCK_RATE, new QuotaTypes(CPU_CLOCK_RATE,
"CPU_CLOCK_RATE", "Compute-Month", "Quota tariff for using 1 CPU of clock rate
100MHz"));
quotaTypeList.put(CPU_NUMBER, new QuotaTypes(CPU_NUMBER, "CPU_NUMBER",
"Compute-Month", "Quota tariff for running VM that has 1vCPU"));
quotaTypeList.put(MEMORY, new QuotaTypes(MEMORY, "MEMORY",
"Compute-Month", "Quota tariff for using 1MB of RAM"));
diff --git a/usage/src/com/cloud/usage/UsageManagerImpl.java
b/usage/src/com/cloud/usage/UsageManagerImpl.java
index 4a60b24..d709102 100644
--- a/usage/src/com/cloud/usage/UsageManagerImpl.java
+++ b/usage/src/com/cloud/usage/UsageManagerImpl.java
@@ -57,6 +57,7 @@ import com.cloud.usage.dao.UsageNetworkDao;
import com.cloud.usage.dao.UsageNetworkOfferingDao;
import com.cloud.usage.dao.UsagePortForwardingRuleDao;
import com.cloud.usage.dao.UsageSecurityGroupDao;
+import com.cloud.usage.dao.UsageVMSnapshotOnPrimaryDao;
import com.cloud.usage.dao.UsageStorageDao;
import com.cloud.usage.dao.UsageVMInstanceDao;
import com.cloud.usage.dao.UsageVMSnapshotDao;
@@ -75,6 +76,7 @@ import com.cloud.usage.parser.VMSnapshotUsageParser;
import com.cloud.usage.parser.VPNUserUsageParser;
import com.cloud.usage.parser.VmDiskUsageParser;
import com.cloud.usage.parser.VolumeUsageParser;
+import com.cloud.usage.parser.VMSanpshotOnPrimaryParser;
import com.cloud.user.Account;
import com.cloud.user.AccountVO;
import com.cloud.user.UserStatisticsVO;
@@ -87,6 +89,7 @@ import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GlobalLock;
+import com.cloud.utils.db.QueryBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
@@ -145,6 +148,8 @@ public class UsageManagerImpl extends ManagerBase
implements UsageManager, Runna
@Inject
private UsageVMSnapshotDao _usageVMSnapshotDao;
@Inject
+ private UsageVMSnapshotOnPrimaryDao _usageSnapshotOnPrimaryDao;
+ @Inject
private QuotaManager _quotaManager;
@Inject
private QuotaAlertManager _alertManager;
@@ -939,6 +944,18 @@ public class UsageManagerImpl extends ManagerBase
implements UsageManager, Runna
s_logger.debug("VM Snapshot usage successfully parsed? " +
parsed + " (for account: " + account.getAccountName() + ", id: " +
account.getId() + ")");
}
}
+ parsed = VMSnapshotUsageParser.parse(account, currentStartDate,
currentEndDate);
+ if (s_logger.isDebugEnabled()) {
+ if (!parsed) {
+ s_logger.debug("VM Snapshot usage successfully parsed? " +
parsed + " (for account: " + account.getAccountName() + ", id: " +
account.getId() + ")");
+ }
+ }
+ parsed = VMSanpshotOnPrimaryParser.parse(account, currentStartDate,
currentEndDate);
+ if (s_logger.isDebugEnabled()) {
+ if (!parsed) {
+ s_logger.debug("VM Snapshot on primary usage successfully
parsed? " + parsed + " (for account: " + account.getAccountName() + ", id: " +
account.getId() + ")");
+ }
+ }
return parsed;
}
@@ -968,6 +985,8 @@ public class UsageManagerImpl extends ManagerBase
implements UsageManager, Runna
createSecurityGroupEvent(event);
} else if (isVmSnapshotEvent(eventType)) {
createVMSnapshotEvent(event);
+ } else if (isVmSnapshotOnPrimaryEvent(eventType)) {
+ createVmSnapshotOnPrimaryEvent(event);
}
}
@@ -1043,6 +1062,12 @@ public class UsageManagerImpl extends ManagerBase
implements UsageManager, Runna
return (eventType.equals(EventTypes.EVENT_VM_SNAPSHOT_CREATE) ||
eventType.equals(EventTypes.EVENT_VM_SNAPSHOT_DELETE));
}
+ private boolean isVmSnapshotOnPrimaryEvent(String eventType) {
+ if (eventType == null)
+ return false;
+ return (eventType.equals(EventTypes.EVENT_VM_SNAPSHOT_ON_PRIMARY) ||
eventType.equals(EventTypes.EVENT_VM_SNAPSHOT_OFF_PRIMARY));
+ }
+
private void createVMHelperEvent(UsageEventVO event) {
// One record for handling VM.START and VM.STOP
@@ -1806,6 +1831,43 @@ public class UsageManagerImpl extends ManagerBase
implements UsageManager, Runna
_usageVMSnapshotDao.persist(vsVO);
}
+ private void createVmSnapshotOnPrimaryEvent(UsageEventVO event) {
+ Long vmId = event.getResourceId();
+ String name = event.getResourceName();
+ if (EventTypes.EVENT_VM_SNAPSHOT_ON_PRIMARY.equals(event.getType())) {
+ Long zoneId = event.getZoneId();
+ Long accountId = event.getAccountId();
+ long physicalsize = (event.getSize() == null) ? 0 :
event.getSize();
+ long virtualsize = (event.getVirtualSize() == null) ? 0 :
event.getVirtualSize();
+ Date created = event.getCreateDate();
+ Account acct =
_accountDao.findByIdIncludingRemoved(event.getAccountId());
+ Long domainId = acct.getDomainId();
+ UsageSnapshotOnPrimaryVO vsVO = new UsageSnapshotOnPrimaryVO(vmId,
zoneId, accountId, domainId, vmId, name, 0, virtualsize, physicalsize, created,
null);
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("createSnapshotOnPrimaryEvent
UsageSnapshotOnPrimaryVO " + vsVO);
+ }
+ _usageSnapshotOnPrimaryDao.persist(vsVO);
+ } else if
(EventTypes.EVENT_VM_SNAPSHOT_OFF_PRIMARY.equals(event.getType())) {
+ QueryBuilder<UsageSnapshotOnPrimaryVO> sc =
QueryBuilder.create(UsageSnapshotOnPrimaryVO.class);
+ sc.and(sc.entity().getAccountId(), SearchCriteria.Op.EQ,
event.getAccountId());
+ sc.and(sc.entity().getId(), SearchCriteria.Op.EQ, vmId);
+ sc.and(sc.entity().getName(), SearchCriteria.Op.EQ, name);
+ sc.and(sc.entity().getDeleted(), SearchCriteria.Op.NULL);
+ List<UsageSnapshotOnPrimaryVO> vmsnaps = sc.list();
+ if (vmsnaps.size() > 1) {
+ s_logger.warn("More that one usage entry for vm snapshot: " +
name + " for vm id:" + vmId + " assigned to account: " + event.getAccountId()
+ + "; marking them all as deleted...");
+ }
+ for (UsageSnapshotOnPrimaryVO vmsnap : vmsnaps) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("deleting vm snapshot name: " +
vmsnap.getName() + " from account: " + vmsnap.getAccountId());
+ }
+ vmsnap.setDeleted(event.getCreateDate()); // there really
shouldn't be more than one
+ _usageSnapshotOnPrimaryDao.updateDeleted(vmsnap);
+ }
+ }
+ }
+
private class Heartbeat extends ManagedContextRunnable {
@Override
protected void runInContext() {
diff --git a/usage/src/com/cloud/usage/parser/VMSanpshotOnPrimaryParser.java
b/usage/src/com/cloud/usage/parser/VMSanpshotOnPrimaryParser.java
new file mode 100644
index 0000000..8519295
--- /dev/null
+++ b/usage/src/com/cloud/usage/parser/VMSanpshotOnPrimaryParser.java
@@ -0,0 +1,129 @@
+// 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
+// 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 java.text.DecimalFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import org.apache.cloudstack.usage.UsageTypes;
+
+import com.cloud.usage.UsageSnapshotOnPrimaryVO;
+import com.cloud.usage.UsageVO;
+import com.cloud.usage.dao.UsageDao;
+import com.cloud.usage.dao.UsageVMSnapshotOnPrimaryDao;
+import com.cloud.user.AccountVO;
+
+@Component
+public class VMSanpshotOnPrimaryParser {
+ public static final Logger s_logger =
Logger.getLogger(VMSanpshotOnPrimaryParser.class.getName());
+
+ private static UsageDao s_usageDao;
+ private static UsageVMSnapshotOnPrimaryDao s_usageSnapshotOnPrimaryDao;
+
+ @Inject
+ private UsageDao _usageDao;
+ @Inject
+ private UsageVMSnapshotOnPrimaryDao _usageSnapshotOnPrimaryDao;
+
+ @PostConstruct
+ void init() {
+ s_usageDao = _usageDao;
+ s_usageSnapshotOnPrimaryDao = _usageSnapshotOnPrimaryDao;
+ }
+
+ public static boolean parse(AccountVO account, Date startDate, Date
endDate) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Parsing all VmSnapshot on primary usage events for
account: " + account.getId());
+ }
+ if ((endDate == null) || endDate.after(new Date())) {
+ endDate = new Date();
+ }
+
+ List<UsageSnapshotOnPrimaryVO> usageUsageVMSnapshots =
s_usageSnapshotOnPrimaryDao.getUsageRecords(account.getId(),
account.getDomainId(), startDate, endDate);
+
+ if (usageUsageVMSnapshots.isEmpty()) {
+ s_logger.debug("No VM snapshot on primary usage events for this
period");
+ return true;
+ }
+
+ Map<String, UsageSnapshotOnPrimaryVO> unprocessedUsage = new
HashMap<String, UsageSnapshotOnPrimaryVO>();
+ for (UsageSnapshotOnPrimaryVO usageRec : usageUsageVMSnapshots) {
+ s_logger.debug("usageRec for VMsnap on primary " +
usageRec.toString());
+ String key = usageRec.getName();
+ if (usageRec.getPhysicalSize() == 0) {
+ usageRec.setDeleted(new Date());
+ s_usageSnapshotOnPrimaryDao.updateDeleted(usageRec);
+ } else {
+ unprocessedUsage.put(key, usageRec);
+ }
+ }
+
+ for (String key : unprocessedUsage.keySet()) {
+ UsageSnapshotOnPrimaryVO usageRec = unprocessedUsage.get(key);
+ Date created = usageRec.getCreated();
+ if (created.before(startDate)) {
+ created = startDate;
+ }
+ Date endDateEffective = endDate;
+ if (usageRec.getDeleted() != null &&
usageRec.getDeleted().before(endDate)){
+ endDateEffective = usageRec.getDeleted();
+ s_logger.debug("Remoevd vm snapshot found endDateEffective " +
endDateEffective + " period end data " + endDate);
+ }
+ long duration = (endDateEffective.getTime() - created.getTime()) +
1;
+ createUsageRecord(UsageTypes.VM_SNAPSHOT_ON_PRIMARY, duration,
created, endDateEffective, account, usageRec.getId(), usageRec.getName(),
usageRec.getZoneId(),
+ usageRec.getVirtualSize(), usageRec.getPhysicalSize());
+ }
+
+ return true;
+ }
+
+ private static void createUsageRecord(int usageType, long runningTime,
Date startDate, Date endDate, AccountVO account, long vmId, String name, long
zoneId, long virtualSize,
+ long physicalSize) {
+ // Our smallest increment is hourly for now
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Total running time " + runningTime + "ms");
+ }
+
+ float usage = runningTime / 1000f / 60f / 60f;
+
+ DecimalFormat dFormat = new DecimalFormat("#.######");
+ String usageDisplay = dFormat.format(usage);
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Creating VMSnapshot On Primary usage record for
vm: " + vmId + ", usage: " + usageDisplay + ", startDate: " + startDate + ",
endDate: " + endDate
+ + ", for account: " + account.getId());
+ }
+
+ // Create the usage record
+ String usageDesc = "VMSnapshot On Primary Usage: " + "VM Id: " + vmId;
+ usageDesc += " Size: " + virtualSize;
+
+ UsageVO usageRecord = new UsageVO(zoneId, account.getId(),
account.getDomainId(), usageDesc, usageDisplay + " Hrs", usageType, new
Double(usage), vmId, name, null, null,
+ vmId, physicalSize, virtualSize, startDate, endDate);
+ s_usageDao.persist(usageRecord);
+ }
+
+}
--
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].