mirror of https://github.com/apache/cloudstack.git
CLOUDSTACK-9867: VM snapshot on primary storage usage metrics (#2035)
VM snapshot on primary storage usage metrics.
This commit is contained in:
parent
26759d1d13
commit
391952da5b
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
// 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 java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
@Entity
|
||||
@Table(name = "usage_snapshot_on_primary")
|
||||
public class UsageSnapshotOnPrimaryVO implements InternalIdentity {
|
||||
|
||||
@Column(name = "id")
|
||||
// volumeId
|
||||
private long id;
|
||||
|
||||
@Column(name = "zone_id")
|
||||
private long zoneId;
|
||||
|
||||
@Column(name = "account_id")
|
||||
private long accountId;
|
||||
|
||||
@Column(name = "domain_id")
|
||||
private long domainId;
|
||||
|
||||
@Column(name = "vm_id")
|
||||
private long vmId;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@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 = "deleted")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date deleted;
|
||||
|
||||
@Column(name = "virtualsize")
|
||||
private Long virtualSize;
|
||||
|
||||
protected UsageSnapshotOnPrimaryVO() {
|
||||
}
|
||||
|
||||
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.snapshotType = type;
|
||||
this.physicalSize = physicalSize;
|
||||
this.virtualSize = virtualSize;
|
||||
this.created = created;
|
||||
this.vmId = vmId;
|
||||
this.name = name;
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
public long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public int getSnapshotType() {
|
||||
return snapshotType;
|
||||
}
|
||||
|
||||
public long getPhysicalSize() {
|
||||
return physicalSize;
|
||||
}
|
||||
|
||||
public Long getVirtualSize() {
|
||||
return virtualSize;
|
||||
}
|
||||
|
||||
public Date getDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public void setDeleted(Date deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public long getVmId() {
|
||||
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 + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue