cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From m...@apache.org
Subject [2/2] git commit: updated refs/heads/master to 51e4f59
Date Thu, 01 Aug 2013 02:42:11 GMT
fix CLOUDSTACK-3591 add usage recording for VM snapshots

Conflicts:

	plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
	server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
	setup/db/db/schema-410to420.sql


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/51e4f597
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/51e4f597
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/51e4f597

Branch: refs/heads/master
Commit: 51e4f597e0600bbcd39b9ba650c2d7e81fc785b4
Parents: 7e9e804
Author: Mice Xia <mice_xia@tcloudcomputing.com>
Authored: Mon Jul 29 17:05:44 2013 +0800
Committer: Mice Xia <mice_xia@tcloudcomputing.com>
Committed: Thu Aug 1 10:47:36 2013 +0800

----------------------------------------------------------------------
 api/src/com/cloud/agent/api/to/VolumeTO.java    |   9 +
 api/src/com/cloud/storage/Volume.java           |   1 +
 .../org/apache/cloudstack/usage/UsageTypes.java |   2 +
 .../schema/src/com/cloud/storage/VolumeVO.java  |  11 +
 .../src/com/cloud/usage/UsageVMSnapshotVO.java  | 122 +++
 .../com/cloud/usage/dao/UsageVMSnapshotDao.java |  29 +
 .../cloud/usage/dao/UsageVMSnapshotDaoImpl.java | 182 ++++
 .../cloudstack/storage/volume/VolumeObject.java |   5 +
 .../manager/VmwareStorageManagerImpl.java       | 102 ++-
 .../xen/resource/CitrixResourceBase.java        |  76 ++
 server/src/com/cloud/api/ApiResponseHelper.java |   7 +
 .../com/cloud/capacity/CapacityManagerImpl.java |  21 +-
 .../vm/snapshot/VMSnapshotManagerImpl.java      |  55 +-
 .../vm/snapshot/VMSnapshotManagerImpl.java.orig | 913 +++++++++++++++++++
 setup/db/db/schema-410to420.sql                 |  18 +
 usage/src/com/cloud/usage/UsageManagerImpl.java |  39 +-
 .../usage/parser/VMSnapshotUsageParser.java     | 153 ++++
 17 files changed, 1699 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/api/src/com/cloud/agent/api/to/VolumeTO.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/to/VolumeTO.java b/api/src/com/cloud/agent/api/to/VolumeTO.java
index cc0e818..a5681a0 100644
--- a/api/src/com/cloud/agent/api/to/VolumeTO.java
+++ b/api/src/com/cloud/agent/api/to/VolumeTO.java
@@ -41,6 +41,7 @@ public class VolumeTO implements InternalIdentity {
     private Long bytesWriteRate;
     private Long iopsReadRate;
     private Long iopsWriteRate;
+    private Long chainSize;
 
     public VolumeTO(long id, Volume.Type type, StoragePoolType poolType, String poolUuid,
String name, String mountPoint, String path, long size, String chainInfo) {
         this.id = id;
@@ -77,6 +78,7 @@ public class VolumeTO implements InternalIdentity {
         this.storagePoolUuid = pool.getUuid();
         this.mountPoint = volume.getFolder();
         this.chainInfo = volume.getChainInfo();
+        this.chainSize = volume.getVmSnapshotChainSize();
         if (volume.getDeviceId() != null)
             this.deviceId = volume.getDeviceId();
     }
@@ -170,4 +172,11 @@ public class VolumeTO implements InternalIdentity {
         return iopsWriteRate;
     }
 
+    public Long getChainSize() {
+        return chainSize;
+    }
+
+    public void setChainSize(Long chainSize) {
+        this.chainSize = chainSize;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/api/src/com/cloud/storage/Volume.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/Volume.java b/api/src/com/cloud/storage/Volume.java
index 9319da9..57e0494 100755
--- a/api/src/com/cloud/storage/Volume.java
+++ b/api/src/com/cloud/storage/Volume.java
@@ -184,4 +184,5 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity,
Ba
 	 */
 	void setReservationId(String reserv);
 	Storage.ImageFormat getFormat();
+	Long getVmSnapshotChainSize();
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/api/src/org/apache/cloudstack/usage/UsageTypes.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/usage/UsageTypes.java b/api/src/org/apache/cloudstack/usage/UsageTypes.java
index ddf1097..52d2644 100644
--- a/api/src/org/apache/cloudstack/usage/UsageTypes.java
+++ b/api/src/org/apache/cloudstack/usage/UsageTypes.java
@@ -40,6 +40,7 @@ public class UsageTypes {
     public static final int VM_DISK_IO_WRITE = 22;
     public static final int VM_DISK_BYTES_READ = 23;
     public static final int VM_DISK_BYTES_WRITE = 24;
+    public static final int VM_SNAPSHOT = 25;
     
     public static List<UsageTypeResponse> listUsageTypes(){
     	List<UsageTypeResponse> responseList = new ArrayList<UsageTypeResponse>();
@@ -61,6 +62,7 @@ public class UsageTypes {
         responseList.add(new UsageTypeResponse(VM_DISK_IO_WRITE, "VM Disk usage(I/O Write)"));
         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"));
     	return responseList;
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/engine/schema/src/com/cloud/storage/VolumeVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/storage/VolumeVO.java b/engine/schema/src/com/cloud/storage/VolumeVO.java
index 3463029..1445e99 100755
--- a/engine/schema/src/com/cloud/storage/VolumeVO.java
+++ b/engine/schema/src/com/cloud/storage/VolumeVO.java
@@ -150,6 +150,9 @@ public class VolumeVO implements Volume {
     @Column(name = "iscsi_name")
     private String _iScsiName;
 
+    @Column(name = "vm_snapshot_chain_size")
+    private Long vmSnapshotChainSize;
+    
     @Transient
     // @Column(name="reservation")
     String reservationId;
@@ -550,4 +553,12 @@ public class VolumeVO implements Volume {
     public void setFormat(Storage.ImageFormat format) {
         this.format = format;
     }
+    
+    public void setVmSnapshotChainSize(Long vmSnapshotChainSize){
+        this.vmSnapshotChainSize = vmSnapshotChainSize;
+    }
+
+    public Long getVmSnapshotChainSize(){
+        return this.vmSnapshotChainSize;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/engine/schema/src/com/cloud/usage/UsageVMSnapshotVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/usage/UsageVMSnapshotVO.java b/engine/schema/src/com/cloud/usage/UsageVMSnapshotVO.java
new file mode 100644
index 0000000..e1f3743
--- /dev/null
+++ b/engine/schema/src/com/cloud/usage/UsageVMSnapshotVO.java
@@ -0,0 +1,122 @@
+// 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_vmsnapshot")
+public class UsageVMSnapshotVO 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="disk_offering_id")
+    private Long diskOfferingId;
+    
+    @Column(name="size")
+    private long size;
+
+    @Column(name="created")
+    @Temporal(value=TemporalType.TIMESTAMP)
+    private Date created = null;
+    
+    @Column(name="processed")
+    @Temporal(value=TemporalType.TIMESTAMP)
+    private Date processed;
+
+    protected UsageVMSnapshotVO() {
+    }
+
+    public UsageVMSnapshotVO(long id, long zoneId, long accountId, long domainId, 
+            long vmId, Long diskOfferingId, long size, Date created, Date processed) {
+        this.zoneId = zoneId;
+        this.accountId = accountId;
+        this.domainId = domainId;
+        this.diskOfferingId = diskOfferingId;
+        this.id = id;
+        this.size = size;
+        this.created = created;
+        this.vmId = vmId;
+        this.processed = processed;
+    }
+
+    public long getZoneId() {
+        return zoneId;
+    }
+    
+    public long getAccountId() {
+        return accountId;
+    }
+
+    public long getDomainId() {
+        return domainId;
+    }
+
+    public Long getDiskOfferingId() {
+        return diskOfferingId;
+    }
+    
+    public long getSize() {
+        return size;
+    }
+
+    public Date getProcessed() {
+        return processed;
+    }
+
+    public void setProcessed(Date processed) {
+        this.processed = processed;
+    }
+
+    public Date getCreated() {
+        return created;
+    }
+
+    public void setCreated(Date created) {
+        this.created = created;
+    }
+
+    public long getVmId() {
+        return vmId;
+    }
+    
+    public long getId(){
+        return this.id;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotDao.java b/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotDao.java
new file mode 100644
index 0000000..ed8f932
--- /dev/null
+++ b/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotDao.java
@@ -0,0 +1,29 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.usage.dao;
+
+import java.util.Date;
+import java.util.List;
+
+import com.cloud.usage.UsageVMSnapshotVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface UsageVMSnapshotDao extends GenericDao<UsageVMSnapshotVO, Long> {
+    public void update(UsageVMSnapshotVO usage);
+    public List<UsageVMSnapshotVO> getUsageRecords(Long accountId, Long domainId, Date
startDate, Date endDate);
+    UsageVMSnapshotVO getPreviousUsageRecord(UsageVMSnapshotVO rec);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotDaoImpl.java b/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotDaoImpl.java
new file mode 100644
index 0000000..9f98bbf
--- /dev/null
+++ b/engine/schema/src/com/cloud/usage/dao/UsageVMSnapshotDaoImpl.java
@@ -0,0 +1,182 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.usage.dao;
+
+import com.cloud.usage.UsageVMSnapshotVO;
+import com.cloud.utils.DateUtil;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.Transaction;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import javax.ejb.Local;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+@Component
+@Local(value={UsageVMSnapshotDao.class})
+public class UsageVMSnapshotDaoImpl extends GenericDaoBase<UsageVMSnapshotVO, Long>
implements UsageVMSnapshotDao{
+    public static final Logger s_logger = Logger.getLogger(UsageVMSnapshotDaoImpl.class.getName());
+    protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = 
+            "SELECT id, zone_id, account_id, domain_id, vm_id, disk_offering_id, size, created,
processed " +
+            " FROM usage_vmsnapshot" +
+            " WHERE account_id = ? " +
+            " AND ( (created BETWEEN ? AND ?) OR " +
+            "      (created < ? AND processed is NULL) ) ORDER BY created asc";
+    protected static final String UPDATE_DELETED = 
+            "UPDATE usage_vmsnapshot SET processed = ? WHERE account_id = ? AND id = ? and
vm_id = ?  and created = ?";
+    
+    protected static final String PREVIOUS_QUERY = 
+            "SELECT id, zone_id, account_id, domain_id, vm_id, disk_offering_id,size, created,
processed " +
+            "FROM usage_vmsnapshot " +
+            "WHERE account_id = ? AND id = ? AND vm_id = ? AND created < ? AND processed
IS NULL " +
+            "ORDER BY created desc limit 1";
+    
+    public void update(UsageVMSnapshotVO usage) {
+        Transaction txn = Transaction.open(Transaction.USAGE_DB);
+        PreparedStatement pstmt = null;
+        try {
+            txn.start();
+            pstmt = txn.prepareAutoCloseStatement(UPDATE_DELETED);
+            pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"),
usage.getProcessed()));
+            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 UsageVMSnapshotVO", e);
+        } finally {
+            txn.close();
+        }
+    }
+    
+    public List<UsageVMSnapshotVO> getUsageRecords(Long accountId, Long domainId, 
+            Date startDate, Date endDate) {
+        List<UsageVMSnapshotVO> usageRecords = new ArrayList<UsageVMSnapshotVO>();
+
+        String sql = GET_USAGE_RECORDS_BY_ACCOUNT;
+        Transaction txn = Transaction.open(Transaction.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"),
startDate));
+            pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"),
endDate));
+            pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"),
startDate));
+
+            ResultSet rs = pstmt.executeQuery();
+            while (rs.next()) {
+                //id, zone_id, account_id, domain_iVMSnapshotVOd, vm_id, disk_offering_id,
size, created, processed
+                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));
+                Long doId = Long.valueOf(rs.getLong(6));
+                if(doId == 0){
+                    doId = null;
+                }
+                Long size = Long.valueOf(rs.getLong(7));
+                Date createdDate = null;
+                Date processDate = null;
+                String createdTS = rs.getString(8);
+                String processed = rs.getString(9);
+                
+
+                if (createdTS != null) {
+                    createdDate = DateUtil.parseDateString(s_gmtTimeZone, createdTS);
+                }
+                if (processed != null) {
+                    processDate = DateUtil.parseDateString(s_gmtTimeZone, processed);
+                }
+                usageRecords.add(new UsageVMSnapshotVO(vId, zoneId, acctId, dId, vmId, 
+                        doId, size, createdDate, processDate));
+            }
+        } catch (Exception e) {
+            txn.rollback();
+            s_logger.warn("Error getting usage records", e);
+        } finally {
+            txn.close();
+        }
+
+        return usageRecords;
+    }
+
+    @Override
+    public UsageVMSnapshotVO getPreviousUsageRecord(UsageVMSnapshotVO rec) {
+        List<UsageVMSnapshotVO> usageRecords = new ArrayList<UsageVMSnapshotVO>();
+
+        String sql = PREVIOUS_QUERY;
+        Transaction txn = Transaction.open(Transaction.USAGE_DB);
+        PreparedStatement pstmt = null;
+        try {
+            int i = 1;
+            pstmt = txn.prepareAutoCloseStatement(sql);
+            pstmt.setLong(i++, rec.getAccountId());
+            pstmt.setLong(i++, rec.getId());
+            pstmt.setLong(i++, rec.getVmId());
+            pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"),
rec.getCreated()));
+
+            ResultSet rs = pstmt.executeQuery();
+            while (rs.next()) {
+                //id, zone_id, account_id, domain_iVMSnapshotVOd, vm_id, disk_offering_id,
size, created, processed
+                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));
+                Long doId = Long.valueOf(rs.getLong(6));
+                if(doId == 0){
+                    doId = null;
+                }
+                Long size = Long.valueOf(rs.getLong(7));
+                Date createdDate = null;
+                Date processDate = null;
+                String createdTS = rs.getString(8);
+                String processed = rs.getString(9);
+                
+
+                if (createdTS != null) {
+                    createdDate = DateUtil.parseDateString(s_gmtTimeZone, createdTS);
+                }
+                if (processed != null) {
+                    processDate = DateUtil.parseDateString(s_gmtTimeZone, processed);
+                }
+                usageRecords.add(new UsageVMSnapshotVO(vId, zoneId, acctId, dId, vmId, 
+                        doId, size, createdDate, processDate));
+            }
+        } catch (Exception e) {
+            txn.rollback();
+            s_logger.warn("Error getting usage records", e);
+        } finally {
+            txn.close();
+        }
+
+        if(usageRecords.size() > 0)
+            return usageRecords.get(0);
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
----------------------------------------------------------------------
diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
index c247f18..b5968b6 100644
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
@@ -613,4 +613,9 @@ public class VolumeObject implements VolumeInfo {
         }
         return true;
     }
+
+    @Override
+    public Long getVmSnapshotChainSize() {
+        return this.volumeVO.getVmSnapshotChainSize();
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
index f6f0cc1..72fb65b 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
@@ -51,14 +51,18 @@ import com.cloud.agent.api.RevertToVMSnapshotCommand;
 import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
 import com.cloud.hypervisor.vmware.mo.DatacenterMO;
 import com.cloud.hypervisor.vmware.mo.DatastoreMO;
+import com.cloud.hypervisor.vmware.mo.HostDatastoreBrowserMO;
 import com.cloud.hypervisor.vmware.mo.HostMO;
 import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
+import com.cloud.hypervisor.vmware.mo.SnapshotDescriptor;
+import com.cloud.hypervisor.vmware.mo.SnapshotDescriptor.SnapshotInfo;
 import com.cloud.hypervisor.vmware.mo.TaskMO;
 import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
 import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
 import com.cloud.hypervisor.vmware.util.VmwareContext;
 import com.cloud.hypervisor.vmware.util.VmwareHelper;
 import com.cloud.storage.JavaStorageLayer;
+import com.cloud.storage.Volume;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.StorageLayer;
 import com.cloud.storage.template.VmdkProcessor;
@@ -70,6 +74,10 @@ import com.cloud.utils.script.Script;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.snapshot.VMSnapshot;
+import com.vmware.vim25.FileInfo;
+import com.vmware.vim25.FileQueryFlags;
+import com.vmware.vim25.HostDatastoreBrowserSearchResults;
+import com.vmware.vim25.HostDatastoreBrowserSearchSpec;
 import com.vmware.vim25.ManagedObjectReference;
 import com.vmware.vim25.TaskEvent;
 import com.vmware.vim25.TaskInfo;
@@ -1209,6 +1217,55 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager
{
         return "snapshots/" + accountId + "/" + volumeId;
     }
 
+    private long getVMSnapshotChainSize(VmwareContext context, VmwareHypervisorHost hyperHost,

+            String fileName, String poolUuid, String exceptFileName) 
+            throws Exception{
+        long size = 0;
+        ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost,
poolUuid);
+        DatastoreMO dsMo = new DatastoreMO(context, morDs);
+        HostDatastoreBrowserMO browserMo = dsMo.getHostDatastoreBrowserMO();
+        String datastorePath = "[" + dsMo.getName() + "]";
+        HostDatastoreBrowserSearchSpec searchSpec = new HostDatastoreBrowserSearchSpec();
+        FileQueryFlags fqf = new FileQueryFlags();
+        fqf.setFileSize(true);
+        fqf.setFileOwner(true);
+        fqf.setModification(true);
+        searchSpec.setDetails(fqf);
+        searchSpec.setSearchCaseInsensitive(false);
+        searchSpec.getMatchPattern().add(fileName);
+        ArrayList<HostDatastoreBrowserSearchResults> results = browserMo.
+                searchDatastoreSubFolders(datastorePath, searchSpec);
+        for(HostDatastoreBrowserSearchResults result : results){
+            if (result != null) {
+                List<FileInfo> info = result.getFile();
+                for (FileInfo fi : info) {
+                    if(exceptFileName != null && fi.getPath().contains(exceptFileName))
+                        continue;
+                    else
+                        size = size + fi.getFileSize();
+                }
+            }
+        }
+        return size;
+    }
+
+    private String extractSnapshotBaseFileName(String input) {
+        if(input == null)
+            return null;
+        String result  = input;
+        if (result.endsWith(".vmdk")){ // get rid of vmdk file extension
+            result = result.substring(0, result.length() - (".vmdk").length());
+        }
+        if(result.split("-").length == 1) // e.g 4da6dcbd412c47b59f96c7ff6dbd7216.vmdk
+            return result;
+        if(result.split("-").length > 2) // e.g ROOT-5-4.vmdk, ROOT-5-4-000001.vmdk
+            return result.split("-")[0] + "-" + result.split("-")[1];
+        if(result.split("-").length == 2) // e.g 4da6dcbd412c47b59f96c7ff6dbd7216-000001.vmdk
+            return result.split("-")[0];
+        else
+            return result;
+    }
+    
     @Override
     public CreateVMSnapshotAnswer execute(VmwareHostService hostService, CreateVMSnapshotCommand
cmd) {
         List<VolumeTO> volumeTOs = cmd.getVolumeTOs();
@@ -1250,24 +1307,30 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager
{
                 // find VM disk file path after creating snapshot
                 VirtualDisk[] vdisks = vmMo.getAllDiskDevice();
                 for (int i = 0; i < vdisks.length; i ++){
-                    @SuppressWarnings("deprecation")
                     List<Pair<String, ManagedObjectReference>> vmdkFiles = vmMo.getDiskDatastorePathChain(vdisks[i],
false);
                     for(Pair<String, ManagedObjectReference> fileItem : vmdkFiles)
{
                         String vmdkName = fileItem.first().split(" ")[1];
-                        if ( vmdkName.endsWith(".vmdk")){
+                        if (vmdkName.endsWith(".vmdk")){
                             vmdkName = vmdkName.substring(0, vmdkName.length() - (".vmdk").length());
                         }
-                        String[] s = vmdkName.split("-");
-                        mapNewDisk.put(s[0], vmdkName);
+                        String baseName = extractSnapshotBaseFileName(vmdkName);
+                        mapNewDisk.put(baseName, vmdkName);
                     }
                 }
-
-                // update volume path using maps
                 for (VolumeTO volumeTO : volumeTOs) {
-                    String parentUUID = volumeTO.getPath();
-                    String[] s = parentUUID.split("-");
-                    String key = s[0];
-                    volumeTO.setPath(mapNewDisk.get(key));
+                    String baseName = extractSnapshotBaseFileName(volumeTO.getPath());
+                    String newPath = mapNewDisk.get(baseName);
+                    // get volume's chain size for this VM snapshot, exclude current volume
vdisk
+                    long size = getVMSnapshotChainSize(context,hyperHost,baseName + "*.vmdk",
+                            volumeTO.getPoolUuid(), newPath);
+                    
+                    if(volumeTO.getType()== Volume.Type.ROOT){
+                        // add memory snapshot size
+                        size = size + getVMSnapshotChainSize(context,hyperHost,cmd.getVmName()+"*.vmsn",volumeTO.getPoolUuid(),null);
+                    }
+                    
+                    volumeTO.setChainSize(size);
+                    volumeTO.setPath(newPath);
                 }
                 return new CreateVMSnapshotAnswer(cmd, cmd.getTarget(), volumeTOs);
             }
@@ -1322,16 +1385,21 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager
{
                         if (vmdkName.endsWith(".vmdk")) {
                             vmdkName = vmdkName.substring(0, vmdkName.length() - (".vmdk").length());
                         }
-                        String[] s = vmdkName.split("-");
-                        mapNewDisk.put(s[0], vmdkName);
+                        String baseName = extractSnapshotBaseFileName(vmdkName);
+                        mapNewDisk.put(baseName, vmdkName);
                     }
                 }
                 for (VolumeTO volumeTo : listVolumeTo) {
-                    String key = null;
-                    String parentUUID = volumeTo.getPath();
-                    String[] s = parentUUID.split("-");
-                    key = s[0];
-                    volumeTo.setPath(mapNewDisk.get(key));
+                    String baseName = extractSnapshotBaseFileName(volumeTo.getPath());
+                    String newPath = mapNewDisk.get(baseName);
+                    long size = getVMSnapshotChainSize(context,hyperHost,
+                            baseName + "*.vmdk", volumeTo.getPoolUuid(), newPath);
+                    if(volumeTo.getType()== Volume.Type.ROOT){
+                        // add memory snapshot size
+                        size = size + getVMSnapshotChainSize(context,hyperHost,cmd.getVmName()+"*.vmsn",volumeTo.getPoolUuid(),null);
+                    }                    
+                    volumeTo.setChainSize(size);
+                    volumeTo.setPath(newPath);
                 }
                 return new DeleteVMSnapshotAnswer(cmd, listVolumeTo);
             }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
index 735eeda..e0dcbae 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
@@ -6668,6 +6668,60 @@ public abstract class CitrixResourceBase implements ServerResource,
HypervisorRe
 
     }
 
+    private long getVMSnapshotChainSize(Connection conn, VolumeTO volumeTo, String vmName)

+            throws BadServerResponse, XenAPIException, XmlRpcException {
+        Set<VDI> allvolumeVDIs = VDI.getByNameLabel(conn, volumeTo.getName());
+        long size = 0;
+        for (VDI vdi : allvolumeVDIs) {
+            try {
+                if (vdi.getIsASnapshot(conn)
+                        && vdi.getSmConfig(conn).get("vhd-parent") != null) {
+                    String parentUuid = vdi.getSmConfig(conn).get("vhd-parent");
+                    VDI parentVDI = VDI.getByUuid(conn, parentUuid);
+                    // add size of snapshot vdi node, usually this only contains meta data
+                    size = size + vdi.getPhysicalUtilisation(conn);
+                    // add size of snapshot vdi parent, this contains data
+                    if (parentVDI != null)
+                        size = size
+                                + parentVDI.getPhysicalUtilisation(conn)
+                                        .longValue();
+                }
+            } catch (Exception e) {
+                s_logger.debug("Exception occurs when calculate "
+                        + "snapshot capacity for volumes: " + e.getMessage());
+                continue;
+            }
+        }
+        if (volumeTo.getType() == Volume.Type.ROOT) {
+            Map<VM, VM.Record> allVMs = VM.getAllRecords(conn);
+            // add size of memory snapshot vdi
+            if (allVMs.size() > 0) {
+                for (VM vmr : allVMs.keySet()) {
+                    try {
+                        String vName = vmr.getNameLabel(conn);
+                        if (vName != null && vName.contains(vmName)
+                                && vmr.getIsASnapshot(conn)) {
+
+                            VDI memoryVDI = vmr.getSuspendVDI(conn);
+                            size = size
+                                    + memoryVDI.getParent(conn)
+                                            .getPhysicalUtilisation(conn);
+                            size = size
+                                    + memoryVDI.getPhysicalUtilisation(conn);
+                        }
+                    } catch (Exception e) {
+                        s_logger.debug("Exception occurs when calculate "
+                                + "snapshot capacity for memory: "
+                                + e.getMessage());
+                        continue;
+                    }
+                }
+            }
+        }
+        return size;
+    }
+    
+
     protected Answer execute(final CreateVMSnapshotCommand cmd) {
         String vmName = cmd.getVmName();
         String vmSnapshotName = cmd.getTarget().getSnapshotName();
@@ -6745,7 +6799,17 @@ public abstract class CitrixResourceBase implements ServerResource,
HypervisorRe
             // extract VM snapshot ref from result
             String ref = result.substring("<value>".length(), result.length() - "</value>".length());
             vmSnapshot = Types.toVM(ref);
+            try {
+                Thread.sleep(5000);
+            } catch (final InterruptedException ex) {
 
+            }
+            // calculate used capacity for this VM snapshot
+            for (VolumeTO volumeTo : cmd.getVolumeTOs()){
+                long size = getVMSnapshotChainSize(conn,volumeTo,cmd.getVmName());
+                volumeTo.setChainSize(size);
+            }
+            
             success = true;
             return new CreateVMSnapshotAnswer(cmd, cmd.getTarget(), cmd.getVolumeTOs());
         } catch (Exception e) {
@@ -6862,6 +6926,18 @@ public abstract class CitrixResourceBase implements ServerResource,
HypervisorRe
             for (VDI vdi : vdiList) {
                 vdi.destroy(conn);
             }
+
+            try {
+                Thread.sleep(5000);
+            } catch (final InterruptedException ex) {
+
+            }
+            // re-calculate used capacify for this VM snapshot
+            for (VolumeTO volumeTo : cmd.getVolumeTOs()){
+                long size = getVMSnapshotChainSize(conn,volumeTo,cmd.getVmName());
+                volumeTo.setChainSize(size);
+            }
+            
             return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs());
         } catch (Exception e) {
             s_logger.warn("Catch Exception: " + e.getClass().toString()

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/server/src/com/cloud/api/ApiResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index a7ddbf1..4a0635a 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -3413,6 +3413,13 @@ public class ApiResponseHelper implements ResponseGenerator {
 			//Security Group Id
             SecurityGroupVO sg = _entityMgr.findById(SecurityGroupVO.class, usageRecord.getUsageId().toString());
 			usageRecResponse.setUsageId(sg.getUuid());
+		} else if(usageRecord.getUsageType() == UsageTypes.VM_SNAPSHOT){
+		    VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, usageRecord.getVmInstanceId().toString());
+		    usageRecResponse.setVmName(vm.getInstanceName());
+		    usageRecResponse.setUsageId(vm.getUuid());
+	        usageRecResponse.setSize(usageRecord.getSize());
+	        if(usageRecord.getOfferingId() != null)
+	            usageRecResponse.setOfferingId(usageRecord.getOfferingId().toString());
 		}
 
 		if (usageRecord.getRawUsage() != null) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/server/src/com/cloud/capacity/CapacityManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java
index 5486a48..4c97a9f 100755
--- a/server/src/com/cloud/capacity/CapacityManagerImpl.java
+++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java
@@ -479,24 +479,9 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
         for (VolumeVO volume : volumes) {
             if(volume.getInstanceId() == null)
                 continue;
-            Long vmId = volume.getInstanceId();
-            UserVm vm = _userVMDao.findById(vmId);
-            if(vm == null)
-                continue;
-            ServiceOffering offering = _offeringsDao.findById(vm.getServiceOfferingId());
-            List<VMSnapshotVO> vmSnapshots =  _vmSnapshotDao.findByVm(vmId);
-            long pathCount = 0;
-            long memorySnapshotSize = 0;
-            for (VMSnapshotVO vmSnapshotVO : vmSnapshots) {
-                if(_vmSnapshotDao.listByParent(vmSnapshotVO.getId()).size() == 0)
-                    pathCount++;
-                if(vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory)
-                    memorySnapshotSize += (offering.getRamSize() * 1024L * 1024L);
-            }
-            if(pathCount <= 1)
-                totalSize = totalSize + memorySnapshotSize;
-            else
-                totalSize = totalSize + volume.getSize() * (pathCount - 1) + memorySnapshotSize;
+            Long chainSize = volume.getVmSnapshotChainSize();
+            if(chainSize != null)
+                totalSize += chainSize;
         }
         return totalSize;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/51e4f597/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
index 5fea480..734ddf1 100644
--- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
+++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
@@ -50,6 +50,7 @@ import com.cloud.agent.api.to.VolumeTO;
 import com.cloud.configuration.dao.ConfigurationDao;
 import com.cloud.event.ActionEvent;
 import com.cloud.event.EventTypes;
+import com.cloud.event.UsageEventUtils;
 import com.cloud.exception.AgentUnavailableException;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.InsufficientCapacityException;
@@ -64,11 +65,14 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.hypervisor.HypervisorGuruManager;
 import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
 import com.cloud.projects.Project.ListProjectResourcesCriteria;
+import com.cloud.service.dao.ServiceOfferingDao;
+import com.cloud.storage.DiskOfferingVO;
 import com.cloud.storage.GuestOSVO;
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.SnapshotVO;
 import com.cloud.storage.StoragePool;
 import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.DiskOfferingDao;
 import com.cloud.storage.dao.GuestOSDao;
 import com.cloud.storage.dao.SnapshotDao;
 import com.cloud.storage.dao.VolumeDao;
@@ -121,6 +125,8 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
     @Inject DataStoreManager dataStoreMgr;
     @Inject ConfigurationDao _configDao;
     @Inject HypervisorCapabilitiesDao _hypervisorCapabilitiesDao;
+    @Inject DiskOfferingDao _diskOfferingDao;
+    @Inject ServiceOfferingDao _serviceOfferingDao;
     int _vmSnapshotMax;
     int _wait;
     StateMachine2<VMSnapshot.State, VMSnapshot.Event, VMSnapshot> _vmSnapshottateMachine
;
@@ -249,7 +255,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
         // check hypervisor capabilities
         if(!_hypervisorCapabilitiesDao.isVmSnapshotEnabled(userVmVo.getHypervisorType(),
"default"))
-        	throw new InvalidParameterValueException("VM snapshot is not enabled for hypervisor
type: " + userVmVo.getHypervisorType());
+            throw new InvalidParameterValueException("VM snapshot is not enabled for hypervisor
type: " + userVmVo.getHypervisorType());
 
         // parameter length check
         if(vsDisplayName != null && vsDisplayName.length()>255)
@@ -351,8 +357,8 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
     }
 
     protected VMSnapshot createVmSnapshotInternal(UserVmVO userVm, VMSnapshotVO vmSnapshot,
Long hostId) {
+        CreateVMSnapshotAnswer answer = null;
         try {
-            CreateVMSnapshotAnswer answer = null;
             GuestOSVO guestOS = _guestOSDao.findById(userVm.getGuestOSId());
             
             // prepare snapshotVolumeTos
@@ -403,9 +409,37 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
                 s_logger.warn("Create vm snapshot " + vmSnapshot.getName() + " failed for
vm: " + userVm.getInstanceName());
                 _vmSnapshotDao.remove(vmSnapshot.getId());
             }
+            if(vmSnapshot.getState() == VMSnapshot.State.Ready && answer != null){
+                for (VolumeTO volumeTo : answer.getVolumeTOs()){
+                    publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_CREATE,vmSnapshot,userVm,volumeTo);
+                }
+            }
         }
     }
 
+    private void publishUsageEvent(String type, VMSnapshot vmSnapshot, UserVm userVm, VolumeTO
volumeTo){
+        VolumeVO volume = _volumeDao.findById(volumeTo.getId());
+        Long diskOfferingId = volume.getDiskOfferingId();
+        Long offeringId = null;
+        if (diskOfferingId != null) {
+            DiskOfferingVO offering = _diskOfferingDao.findById(diskOfferingId);
+            if (offering != null
+                    && (offering.getType() == DiskOfferingVO.Type.Disk)) {
+                offeringId = offering.getId();
+            }
+        }
+        UsageEventUtils.publishUsageEvent(
+                type,
+                vmSnapshot.getAccountId(),
+                userVm.getDataCenterId(),
+                userVm.getId(),
+                vmSnapshot.getName(),
+                offeringId,     
+                volume.getId(), // save volume's id into templateId field
+                volumeTo.getChainSize(),
+                VMSnapshot.class.getName(), vmSnapshot.getUuid());       
+    }
+    
     protected List<VolumeTO> getVolumeTOList(Long vmId) {
         List<VolumeTO> volumeTOs = new ArrayList<VolumeTO>();
         List<VolumeVO> volumeVos = _volumeDao.findByInstance(vmId);
@@ -532,6 +566,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
             if (volume.getPath() != null) {
                 VolumeVO volumeVO = _volumeDao.findById(volume.getId());
                 volumeVO.setPath(volume.getPath());
+                volumeVO.setVmSnapshotChainSize(volume.getChainSize());
                 _volumeDao.persist(volumeVO);
             }
         }
@@ -590,7 +625,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
     @DB
     protected boolean deleteSnapshotInternal(VMSnapshotVO vmSnapshot) {
         UserVmVO userVm = _userVMDao.findById(vmSnapshot.getVmId());
-        
+        DeleteVMSnapshotAnswer answer = null;
         try {
             vmSnapshotStateTransitTo(vmSnapshot,VMSnapshot.Event.ExpungeRequested);
             Long hostId = pickRunningHost(vmSnapshot.getVmId());
@@ -606,7 +641,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
             GuestOSVO guestOS = _guestOSDao.findById(userVm.getGuestOSId());
             DeleteVMSnapshotCommand deleteSnapshotCommand = new DeleteVMSnapshotCommand(vmInstanceName,
vmSnapshotTO, volumeTOs,guestOS.getDisplayName());
             
-            DeleteVMSnapshotAnswer answer = (DeleteVMSnapshotAnswer) sendToPool(hostId, deleteSnapshotCommand);
+            answer = (DeleteVMSnapshotAnswer) sendToPool(hostId, deleteSnapshotCommand);
            
             if (answer != null && answer.getResult()) {
                 processAnswer(vmSnapshot, userVm, answer, hostId);
@@ -620,6 +655,12 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
             String msg = "Delete vm snapshot " + vmSnapshot.getName() + " of vm " + userVm.getInstanceName()
+ " failed due to " + e.getMessage();
             s_logger.error(msg , e);
             throw new CloudRuntimeException(e.getMessage());
+        } finally{
+            if(answer != null && answer.getResult()){
+                for (VolumeTO volumeTo : answer.getVolumeTOs()){
+                    publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_DELETE,vmSnapshot,userVm,volumeTo);
+                }
+            }
         }
     }
 
@@ -682,7 +723,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
                     _itMgr.advanceStop(userVm.getUuid(), true);
                 } catch (Exception e) {
                     s_logger.error("Stop VM " + userVm.getInstanceName() + " before reverting
failed due to " + e.getMessage());
-    			    throw new CloudRuntimeException(e.getMessage());
+                    throw new CloudRuntimeException(e.getMessage());
                 }
             }
             hostId = pickRunningHost(userVm.getId());
@@ -712,8 +753,8 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
             List<VolumeTO> volumeTOs = getVolumeTOList(userVm.getId());
             String vmInstanceName = userVm.getInstanceName();
             VMSnapshotTO parent = getSnapshotWithParents(snapshot).getParent();
-            VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(snapshot.getId(), snapshot.getName(),
snapshot.getType(),
-            		snapshot.getCreated().getTime(), snapshot.getDescription(), snapshot.getCurrent(),
parent);
+            VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(snapshot.getId(), snapshot.getName(),
snapshot.getType(), 
+                    snapshot.getCreated().getTime(), snapshot.getDescription(), snapshot.getCurrent(),
parent);
             
             GuestOSVO guestOS = _guestOSDao.findById(userVm.getGuestOSId());
             RevertToVMSnapshotCommand revertToSnapshotCommand = new RevertToVMSnapshotCommand(vmInstanceName,
vmSnapshotTO, volumeTOs, guestOS.getDisplayName());


Mime
View raw message