cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From edi...@apache.org
Subject [1/5] refactor snapshot
Date Tue, 30 Apr 2013 02:38:10 GMT
Updated Branches:
  refs/heads/object_store 35264f708 -> 99dcb23b1


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/37cbe889/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
index 9f47e06..98527a9 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
@@ -141,58 +141,22 @@ public class XenServerStorageResource {
     }
     
     protected CreateObjectAnswer getTemplateSize(CreateObjectCommand cmd, String templateUrl)
{
-        Connection conn = hypervisorResource.getConnection();
+        /*Connection conn = hypervisorResource.getConnection();
         long size = this.getTemplateSize(conn, templateUrl);
-        return new CreateObjectAnswer(cmd, templateUrl, size);
+        return new CreateObjectAnswer(cmd, templateUrl, size);*/
+        return null;
     }
     protected CreateObjectAnswer execute(CreateObjectCommand cmd) {
-        String uriString = cmd.getObjectUri();
-        DecodedDataObject obj = null;
-
-        Connection conn = hypervisorResource.getConnection();
-        VDI vdi = null;
-        boolean result = false;
-        String errorMsg = null;
-        
-        try {
-            obj = Decoder.decode(uriString);
-
-            DecodedDataStore store = obj.getStore(); 
-            if (obj.getObjType().equalsIgnoreCase("template") && store.getRole().equalsIgnoreCase("image"))
{
-                return getTemplateSize(cmd, obj.getPath());
-            }
-            
-            long size = obj.getSize();
-            String name = obj.getName();
-            String storeUuid = store.getUuid();
-            SR primaryDataStoreSR = getSRByNameLabel(conn, storeUuid);
-            vdi = createVdi(conn, name, primaryDataStoreSR, size);
-            VDI.Record record = vdi.getRecord(conn);
-            result = true;
-            return new CreateObjectAnswer(cmd, record.uuid, record.virtualSize);
-        } catch (BadServerResponse e) {
-            s_logger.debug("Failed to create volume", e);
-            errorMsg = e.toString();
-        } catch (XenAPIException e) {
-            s_logger.debug("Failed to create volume", e);
-            errorMsg = e.toString();
-        } catch (XmlRpcException e) {
-            s_logger.debug("Failed to create volume", e);
-            errorMsg = e.toString();
-        } catch (URISyntaxException e) {
-            s_logger.debug("Failed to create volume", e);
-            errorMsg = e.toString();
-        } finally {
-            if (!result && vdi != null) {
-                try {
-                    deleteVDI(conn, vdi);
-                } catch (Exception e) {
-                    s_logger.debug("Faled to delete vdi: " + vdi.toString());
-                }
-            }
-        }
-        
-        return new CreateObjectAnswer(cmd, false, errorMsg);
+       DataTO data = cmd.getData();
+       try {
+           if (data.getObjectType() == DataObjectType.VOLUME) {
+               return createVolume(data);
+           } 
+           return new CreateObjectAnswer("not supported type");
+       } catch (Exception e) {
+           s_logger.debug("Failed to create object: " + data.getObjectType() + ": " + e.toString());
+           return new CreateObjectAnswer(e.toString());
+       }
     }
     
     protected Answer execute(DeleteVolumeCommand cmd) {
@@ -735,20 +699,30 @@ public class XenServerStorageResource {
         return new CopyCmdAnswer("not implemented yet");
     }
     
-    protected CreateObjectAnswer createVolume(DataTO data) {
-        /*
+    protected CreateObjectAnswer createVolume(DataTO data) throws BadServerResponse, XenAPIException,
XmlRpcException {
+        VolumeObjectTO volume = (VolumeObjectTO)data;
+
+        Connection conn = hypervisorResource.getConnection();
+        PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)data.getDataStore();
+        SR poolSr = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
         VDI.Record vdir = new VDI.Record();
-        vdir.nameLabel = dskch.getName();
+        vdir.nameLabel = volume.getName();
         vdir.SR = poolSr;
         vdir.type = Types.VdiType.USER;
 
-        vdir.virtualSize = dskch.getSize();
+        vdir.virtualSize = volume.getSize();
+        VDI vdi;
+
         vdi = VDI.create(conn, vdir);
-        VDI.Record vdir;
         vdir = vdi.getRecord(conn);
-        s_logger.debug("Succesfully created VDI for " + cmd + ".  Uuid = " + vdir.uuid);*/
-        return null;
+        VolumeObjectTO newVol = new VolumeObjectTO();
+        newVol.setName(vdir.nameLabel);
+        newVol.setSize(vdir.virtualSize);
+        newVol.setPath(vdir.uuid);
+
+        return new CreateObjectAnswer(newVol);
     }
+    
     protected CopyCmdAnswer cloneVolumeFromBaseTemplate(DataTO srcData, DataTO destData)
{
         Connection conn = hypervisorResource.getConnection();
         PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/37cbe889/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
index 91f9cd0..e477b57 100644
--- a/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
+++ b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
@@ -96,12 +96,12 @@ public class SampleImageStoreDriverImpl implements ImageStoreDriver {
                 callback.complete(result);
                 return;
             }
-            CreateObjectCommand createCmd = new CreateObjectCommand(data.getUri());
+            CreateObjectCommand createCmd = new CreateObjectCommand(data.getTO());
             CreateObjectAnswer answer = (CreateObjectAnswer)ep.sendMessage(createCmd);
             if (answer.getResult()) {
                 //update imagestorevo
 
-                result = new CreateCmdResult(answer.getPath(), null);
+                result = new CreateCmdResult(null, null);
             } else {
                 result.setResult(answer.getDetails());
             }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/37cbe889/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
index ea4c561..5e82a7e 100644
--- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
+++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
@@ -34,6 +34,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+import org.apache.cloudstack.storage.command.CreateObjectCommand;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.volume.VolumeObject;
 import org.apache.log4j.Logger;
@@ -108,46 +109,15 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
 		return null;
 	}
 
-	public boolean createVolume(
+	public Answer createVolume(
 			VolumeInfo volume) throws StorageUnavailableException {
 		if (s_logger.isDebugEnabled()) {
 			s_logger.debug("Creating volume: " + volume);
 		}
-
-		DiskOfferingVO offering = diskOfferingDao.findById(volume.getDiskOfferingId());
-		DiskProfile diskProfile = new DiskProfile(volume, offering,
-				null);
-
-		StoragePool pool = (StoragePool)volume.getDataStore();
-		VolumeVO vol = volumeDao.findById(volume.getId());
-		if (pool != null) {
-			if (s_logger.isDebugEnabled()) {
-				s_logger.debug("Trying to create in " + pool);
-			}
-			vol.setPoolId(pool.getId());
-
-			CreateCommand cmd = new CreateCommand(diskProfile, new StorageFilerTO(
-					pool));
-
-			Answer answer = storageMgr.sendToPool(pool, null, cmd);
-			if (answer.getResult()) {
-				CreateAnswer createAnswer = (CreateAnswer) answer;
-				vol.setFolder(pool.getPath());
-				vol.setPath(createAnswer.getVolume().getPath());
-				vol.setSize(createAnswer.getVolume().getSize());
-				vol.setPoolType(pool.getPoolType());
-				vol.setPoolId(pool.getId());
-				vol.setPodId(pool.getPodId());
-				this.volumeDao.update(vol.getId(), vol);
-				return true;
-			} 
-
-		}
-
-		if (s_logger.isDebugEnabled()) {
-			s_logger.debug("Unable to create volume " + volume.getId());
-		}
-		return false;
+		
+		CreateObjectCommand cmd = new CreateObjectCommand(volume.getTO());
+		Answer answer = storageMgr.sendToPool((StoragePool)volume.getDataStore(), null, cmd);
+		return answer;
 	}
 
 	@Override
@@ -155,9 +125,10 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
 			AsyncCompletionCallback<CreateCmdResult> callback) {
 		// TODO Auto-generated method stub
 		String errMsg = null;
+		Answer answer = null;
 		if (data.getType() == DataObjectType.VOLUME) {
 			try {
-				createVolume((VolumeInfo)data);
+				answer = createVolume((VolumeInfo)data);
 			} catch (StorageUnavailableException e) {
 				s_logger.debug("failed to create volume", e);
 				errMsg = e.toString();
@@ -166,13 +137,12 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
 				errMsg = e.toString();
 			}
 		}
-		CreateCmdResult result = new CreateCmdResult(null, null);
+		CreateCmdResult result = new CreateCmdResult(null, answer);
 		if (errMsg != null) {
 			result.setResult(errMsg);
 		}
 
 		callback.complete(result);
-
 	}
 
 	@Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/37cbe889/server/src/com/cloud/storage/CreateSnapshotPayload.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/CreateSnapshotPayload.java b/server/src/com/cloud/storage/CreateSnapshotPayload.java
new file mode 100644
index 0000000..cafe46c
--- /dev/null
+++ b/server/src/com/cloud/storage/CreateSnapshotPayload.java
@@ -0,0 +1,14 @@
+package com.cloud.storage;
+
+public class CreateSnapshotPayload {
+	private Long snapshotPolicyId;
+
+	public Long getSnapshotPolicyId() {
+		return snapshotPolicyId;
+	}
+
+	public void setSnapshotPolicyId(Long snapshotPolicyId) {
+		this.snapshotPolicyId = snapshotPolicyId;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/37cbe889/server/src/com/cloud/storage/StorageManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java
index e615967..05b2257 100755
--- a/server/src/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/com/cloud/storage/StorageManagerImpl.java
@@ -1931,7 +1931,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager,
C
         _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), store.getDataCenterId());
 
         // Verify that there are no live snapshot, template, volume on the image store to
be deleted
-        List<SnapshotDataStoreVO> snapshots = _snapshotStoreDao.listByStoreId(storeId);
+        List<SnapshotDataStoreVO> snapshots = _snapshotStoreDao.listByStoreId(storeId,
DataStoreRole.Image);
         if ( snapshots != null && snapshots.size() > 0 ){
             throw new CloudRuntimeException("Cannot delete image store with active snapshots
backup!");
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/37cbe889/server/src/com/cloud/storage/VolumeManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java
index 57241b1..3177a59 100644
--- a/server/src/com/cloud/storage/VolumeManagerImpl.java
+++ b/server/src/com/cloud/storage/VolumeManagerImpl.java
@@ -85,6 +85,7 @@ import com.cloud.configuration.Resource.ResourceType;
 import com.cloud.configuration.dao.ConfigurationDao;
 import com.cloud.consoleproxy.ConsoleProxyManager;
 import com.cloud.dc.ClusterVO;
+import com.cloud.dc.DataCenter;
 import com.cloud.dc.DataCenterVO;
 import com.cloud.dc.HostPodVO;
 import com.cloud.dc.dao.ClusterDao;
@@ -166,6 +167,7 @@ import com.cloud.vm.dao.DomainRouterDao;
 import com.cloud.vm.dao.SecondaryStorageVmDao;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.VMInstanceDao;
+import com.cloud.vm.snapshot.VMSnapshot;
 import com.cloud.vm.snapshot.VMSnapshotVO;
 import com.cloud.vm.snapshot.dao.VMSnapshotDao;
 
@@ -2463,5 +2465,47 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager
{
             throw new CloudRuntimeException("Failed to destroy volume" + volume.getId(),
e);
         }
     }
+    
+    
+    
+    
+    @Override
+    public Snapshot takeSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException
{
+    	Account caller = UserContext.current().getCaller();
+
+        VolumeInfo volume = this.volFactory.getVolume(volumeId);
+        if (volume == null) {
+            throw new InvalidParameterValueException("Creating snapshot failed due to volume:"
+ volumeId + " doesn't exist");
+        }
+        DataCenter zone = _dcDao.findById(volume.getDataCenterId());
+        if (zone == null) {
+            throw new InvalidParameterValueException("Can't find zone by id " + volume.getDataCenterId());
+        }
+
+        if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType()))
{
+            throw new PermissionDeniedException("Cannot perform this operation, Zone is currently
disabled: " + zone.getName());
+        }
+
+        if (volume.getState() != Volume.State.Ready) {
+            throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in
" + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot.");
+        }
+
+        if ( volume.getTemplateId() != null ) {
+            VMTemplateVO  template = _templateDao.findById(volume.getTemplateId());
+            if( template != null && template.getTemplateType() == Storage.TemplateType.SYSTEM
) {
+                throw new InvalidParameterValueException("VolumeId: " + volumeId + " is for
System VM , Creating snapshot against System VM volumes is not supported");
+            }
+        }
+
+        StoragePool storagePool = (StoragePool)volume.getDataStore();
+        if (storagePool == null) {
+            throw new InvalidParameterValueException("VolumeId: " + volumeId + " please attach
this volume to a VM before create snapshot for it");
+        }
+        
+        CreateSnapshotPayload payload = new CreateSnapshotPayload();
+        payload.setSnapshotPolicyId(policyId);
+        return this.volService.takeSnapshot(volume);
+
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/37cbe889/server/src/com/cloud/storage/dao/SnapshotDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/SnapshotDao.java b/server/src/com/cloud/storage/dao/SnapshotDao.java
index e6aecc7..46f2fa9 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDao.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDao.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.storage.dao;
 
+import com.cloud.storage.DataStoreRole;
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.Snapshot.Type;
 import com.cloud.storage.SnapshotVO;
@@ -29,7 +30,7 @@ public interface SnapshotDao extends GenericDao<SnapshotVO, Long>,
StateDao<Snap
 	List<SnapshotVO> listByVolumeId(long volumeId);
 	List<SnapshotVO> listByVolumeId(Filter filter, long volumeId);
 	SnapshotVO findNextSnapshot(long parentSnapId);
-	long getLastSnapshot(long volumeId, long snapId);
+	long getLastSnapshot(long volumeId, DataStoreRole role);
     List<SnapshotVO> listByVolumeIdType(long volumeId, Type type);
     List<SnapshotVO> listByVolumeIdIncludingRemoved(long volumeId);
     List<SnapshotVO> listByBackupUuid(long volumeId, String backupUuid);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/37cbe889/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
index 2dd5da1..24d4c65 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
@@ -28,6 +28,7 @@ import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
 import com.cloud.server.ResourceTag.TaggedResourceType;
+import com.cloud.storage.DataStoreRole;
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.Snapshot.Event;
 import com.cloud.storage.Snapshot.State;
@@ -55,7 +56,7 @@ import com.cloud.vm.dao.VMInstanceDao;
 public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements SnapshotDao
{
     public static final Logger s_logger = Logger.getLogger(SnapshotDaoImpl.class.getName());
     //TODO: we should remove these direct sqls
-    private static final String GET_LAST_SNAPSHOT = "SELECT id FROM snapshots where volume_id
= ? AND id != ? AND path IS NOT NULL ORDER BY created DESC";
+    private static final String GET_LAST_SNAPSHOT = "SELECT snapshots.id FROM snapshot_store_ref,
snapshots where snapshots.id = snapshot_store_ref.snapshot_id AND snapshosts.volume_id = ?
AND snapshot_store_ref.role = ? ORDER BY created DESC";
     private static final String UPDATE_SNAPSHOT_VERSION = "UPDATE snapshots SET version =
? WHERE volume_id = ? AND version = ?";
     private static final String GET_SECHOST_ID = "SELECT store_id FROM snapshots, snapshot_store_ref
where snapshots.id = snapshot_store_ref.snapshot_id AND volume_id = ? AND backup_snap_id IS
NOT NULL AND sechost_id IS NOT NULL LIMIT 1";
     private static final String UPDATE_SECHOST_ID = "UPDATE snapshots SET sechost_id = ?
WHERE data_center_id = ?";
@@ -212,14 +213,14 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long>
implements
         return null;
     }
     @Override
-    public long getLastSnapshot(long volumeId, long snapId) {
+    public long getLastSnapshot(long volumeId, DataStoreRole role) {
         Transaction txn = Transaction.currentTxn();
         PreparedStatement pstmt = null;
         String sql = GET_LAST_SNAPSHOT;
         try {
             pstmt = txn.prepareAutoCloseStatement(sql);
             pstmt.setLong(1, volumeId);
-            pstmt.setLong(2, snapId);
+            pstmt.setString(2, role.toString());
             ResultSet rs = pstmt.executeQuery();
             if (rs.next()) {
                 return rs.getLong(1);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/37cbe889/server/src/com/cloud/storage/snapshot/SnapshotManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManager.java b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
index 8181330..983b50c 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManager.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
@@ -18,6 +18,7 @@ package com.cloud.storage.snapshot;
 
 import java.util.List;
 
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 
 import com.cloud.agent.api.Answer;
@@ -68,7 +69,10 @@ public interface SnapshotManager {
 
 	Answer sendToPool(Volume vol, Command cmd);
 
-	SnapshotVO getParentSnapshot(VolumeInfo volume, Snapshot snapshot);
+	SnapshotVO getParentSnapshot(VolumeInfo volume);
 
 	Snapshot backupSnapshot(Long snapshotId);
+
+	SnapshotInfo takeSnapshot(VolumeInfo volume)
+			throws ResourceAllocationException;
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/37cbe889/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index 11408f9..c18ffa8 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -38,6 +38,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
@@ -82,7 +83,9 @@ import com.cloud.host.dao.HostDao;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.org.Grouping;
 import com.cloud.projects.Project.ListProjectResourcesCriteria;
+import com.cloud.resource.ResourceManager;
 import com.cloud.server.ResourceTag.TaggedResourceType;
+import com.cloud.storage.CreateSnapshotPayload;
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.Snapshot.Type;
 import com.cloud.storage.DataStoreRole;
@@ -128,8 +131,12 @@ import com.cloud.utils.db.JoinBuilder;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.UserVmVO;
 import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.VirtualMachine.State;
 import com.cloud.vm.dao.UserVmDao;
+import com.cloud.vm.snapshot.VMSnapshot;
+import com.cloud.vm.snapshot.VMSnapshotVO;
 import com.cloud.vm.snapshot.dao.VMSnapshotDao;
 
 @Component
@@ -202,6 +209,10 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
     @Inject VolumeDataFactory volFactory;
     @Inject SnapshotDataFactory snapshotFactory;
     @Inject EndPointSelector _epSelector;
+	@Inject
+	private ResourceManager _resourceMgr;
+	@Inject
+	protected List<SnapshotStrategy> snapshotStrategies;
 
 
     private int _totalRetries;
@@ -278,32 +289,25 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
         	throw new InvalidParameterValueException("Volume is not in ready state");
         }
 
-        SnapshotInfo snapshot = null;
-
+    
         boolean backedUp = false;
         // does the caller have the authority to act on this volume
         _accountMgr.checkAccess(UserContext.current().getCaller(), null, true, volume);
 
-
-        SnapshotInfo snap = this.snapshotFactory.getSnapshot(snapshotId);
+        SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Primary);
 
         try {
-        	snapshot = this.snapshotSrv.takeSnapshot(volume, snapshotId);
-        	if (snapshot != null) {
-        		postCreateSnapshot(volumeId, snapshot.getId(), policyId);
-        		//Check if the snapshot was removed while backingUp. If yes, do not log snapshot
create usage event
-        		SnapshotVO freshSnapshot = _snapshotDao.findById(snapshot.getId());
-        		if ((freshSnapshot != null) && backedUp) {
-        			UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(),
-        					snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
-        					volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
-        		}
-
-                _resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
-        	}
-        	if (backup) {
-        		this.backupSnapshot(snapshotId);
+        	postCreateSnapshot(volumeId, snapshot.getId(), policyId);
+        	//Check if the snapshot was removed while backingUp. If yes, do not log snapshot
create usage event
+        	SnapshotVO freshSnapshot = _snapshotDao.findById(snapshot.getId());
+        	if ((freshSnapshot != null) && backedUp) {
+        		UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(),
+        				snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
+        				volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
         	}
+
+        	_resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
+
         } catch(Exception e) {
             s_logger.debug("Failed to create snapshot", e);
             if (backup) {
@@ -337,16 +341,11 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
 
     @Override
     public Snapshot backupSnapshot(Long snapshotId) {
-    	 SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotId);
-    	 if (snapshot == null) {
-    		 throw new CloudRuntimeException("Can't find snapshot:" + snapshotId);
-    	 }
-
-    	 if (snapshot.getState() == Snapshot.State.BackedUp) {
-    	     return snapshot;
+    	 SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Image);
+    	 if (snapshot != null) {
+    		 throw new CloudRuntimeException("Already in the backup snapshot:" + snapshotId);
     	 }
 
-
          return this.snapshotSrv.backupSnapshot(snapshot);
     }
 
@@ -436,8 +435,8 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
     }
 
     @Override
-    public SnapshotVO getParentSnapshot(VolumeInfo volume, Snapshot snapshot) {
-    	 long preId = _snapshotDao.getLastSnapshot(volume.getId(), snapshot.getId());
+    public SnapshotVO getParentSnapshot(VolumeInfo volume) {
+    	 long preId = _snapshotDao.getLastSnapshot(volume.getId(), DataStoreRole.Primary);
 
          SnapshotVO preSnapshotVO = null;
          if (preId != 0 && !(volume.getLastPoolId() != null && !volume.getLastPoolId().equals(volume.getPoolId())))
{
@@ -500,15 +499,21 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
         Account caller = UserContext.current().getCaller();
 
         // Verify parameters
-        SnapshotInfo snapshotCheck = this.snapshotFactory.getSnapshot(snapshotId);
+        SnapshotVO snapshotCheck = this._snapshotDao.findById(snapshotId);
         if (snapshotCheck == null) {
             throw new InvalidParameterValueException("unable to find a snapshot with id "
+ snapshotId);
         }
 
         _accountMgr.checkAccess(caller, null, true, snapshotCheck);
-
+        SnapshotStrategy snapshotStrategy = null;
+        for (SnapshotStrategy strategy : this.snapshotStrategies) {
+        	if (strategy.canHandle(snapshotCheck)) {
+        		snapshotStrategy = strategy;
+        		break;
+        	}
+        }
         try {
-        	boolean result = this.snapshotSrv.deleteSnapshot(snapshotCheck);
+        	boolean result = snapshotStrategy.deleteSnapshot(snapshotId);
         	if (result) {
         		if (snapshotCheck.getState() == Snapshot.State.BackedUp) {
         			UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_DELETE, snapshotCheck.getAccountId(),
@@ -529,7 +534,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
 
     @Override
     public String getSecondaryStorageURL(SnapshotVO snapshot) {
-        SnapshotDataStoreVO snapshotStore = this._snapshotStoreDao.findBySnapshot(snapshot.getId());
+        SnapshotDataStoreVO snapshotStore = this._snapshotStoreDao.findBySnapshot(snapshot.getId(),
DataStoreRole.Image);
         if (snapshotStore != null){
             DataStore store = this.dataStoreMgr.getDataStore(snapshotStore.getDataStoreId(),
DataStoreRole.Image);
             if ( store != null ){
@@ -904,44 +909,76 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
         return null;
     }
 
-    @Override
-    public SnapshotVO allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException
{
-        Account caller = UserContext.current().getCaller();
-
-        VolumeVO volume = _volsDao.findById(volumeId);
-        if (volume == null) {
-            throw new InvalidParameterValueException("Creating snapshot failed due to volume:"
+ volumeId + " doesn't exist");
-        }
-        DataCenter zone = _dcDao.findById(volume.getDataCenterId());
-        if (zone == null) {
-            throw new InvalidParameterValueException("Can't find zone by id " + volume.getDataCenterId());
-        }
-
-        if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType()))
{
-            throw new PermissionDeniedException("Cannot perform this operation, Zone is currently
disabled: " + zone.getName());
-        }
-
-        if (volume.getState() != Volume.State.Ready) {
-            throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in
" + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot.");
-        }
-
-        if ( volume.getTemplateId() != null ) {
-            VMTemplateVO  template = _templateDao.findById(volume.getTemplateId());
-            if( template != null && template.getTemplateType() == Storage.TemplateType.SYSTEM
) {
-                throw new InvalidParameterValueException("VolumeId: " + volumeId + " is for
System VM , Creating snapshot against System VM volumes is not supported");
-            }
-        }
-
-        StoragePoolVO storagePoolVO = _storagePoolDao.findById(volume.getPoolId());
-        if (storagePoolVO == null) {
-            throw new InvalidParameterValueException("VolumeId: " + volumeId + " please attach
this volume to a VM before create snapshot for it");
-        }
-
-        ClusterVO cluster = _clusterDao.findById(storagePoolVO.getClusterId());
+    
+    
+    private boolean hostSupportSnapsthot(HostVO host) {
+		if (host.getHypervisorType() != HypervisorType.KVM) {
+			return true;
+		}
+		// Determine host capabilities
+		String caps = host.getCapabilities();
+
+		if (caps != null) {
+			String[] tokens = caps.split(",");
+			for (String token : tokens) {
+				if (token.contains("snapshot")) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+    
+    private boolean supportedByHypervisor(VolumeInfo volume) {
+    	StoragePool storagePool = (StoragePool)volume.getDataStore();
+        ClusterVO cluster = _clusterDao.findById(storagePool.getClusterId());
         if (cluster != null && cluster.getHypervisorType() == HypervisorType.Ovm)
{
             throw new InvalidParameterValueException("Ovm won't support taking snapshot");
         }
-
+        
+		if (volume.getHypervisorType().equals(HypervisorType.KVM)) {
+			List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(cluster.getId());
+			if (hosts != null && !hosts.isEmpty()) {
+				HostVO host = hosts.get(0);
+				if (!hostSupportSnapsthot(host)) {
+					throw new CloudRuntimeException("KVM Snapshot is not supported on cluster: " + host.getId());
+				}
+			}
+		}
+
+		// if volume is attached to a vm in destroyed or expunging state; disallow
+		if (volume.getInstanceId() != null) {
+			UserVmVO userVm = _vmDao.findById(volume.getInstanceId());
+			if (userVm != null) {
+				if (userVm.getState().equals(State.Destroyed) || userVm.getState().equals(State.Expunging))
{
+					throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volume.getId()
+ " is associated with vm:" + userVm.getInstanceName() + " is in "
+							+ userVm.getState().toString() + " state");
+				}
+
+				if(userVm.getHypervisorType() == HypervisorType.VMware || userVm.getHypervisorType()
== HypervisorType.KVM) {
+					List<SnapshotVO> activeSnapshots = _snapshotDao.listByInstanceId(volume.getInstanceId(),
Snapshot.State.Creating,  Snapshot.State.CreatedOnPrimary,  Snapshot.State.BackingUp);
+					if(activeSnapshots.size() > 1)
+						throw new CloudRuntimeException("There is other active snapshot tasks on the instance
to which the volume is attached, please try again later");
+				}
+
+				  List<VMSnapshotVO> activeVMSnapshots = _vmSnapshotDao.listByInstanceId(userVm.getId(),
+			                VMSnapshot.State.Creating, VMSnapshot.State.Reverting, VMSnapshot.State.Expunging);
+			        if (activeVMSnapshots.size() > 0) {
+			            throw new CloudRuntimeException(
+			                    "There is other active vm snapshot tasks on the instance to which
the volume is attached, please try again later");
+			        }
+			}
+		}
+
+		return true;
+	}
+    @Override
+    public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationException
{
+        Account caller = UserContext.current().getCaller();
+        
+        supportedByHypervisor(volume);
+        CreateSnapshotPayload snapInfo = (CreateSnapshotPayload)volume.getpayload();
+        Long policyId = snapInfo.getSnapshotPolicyId();
         // Verify permissions
         _accountMgr.checkAccess(caller, null, true, volume);
         Type snapshotType = getSnapshotType(policyId);
@@ -975,14 +1012,13 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
         }
         String snapshotName = vmDisplayName + "_" + volume.getName() + "_" + timeString;
 
-        // Create the Snapshot object and save it so we can return it to the
-        // user
-        HypervisorType hypervisorType = this._volsDao.getHypervisorType(volumeId);
-        SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(),
volume.getDomainId(), volume.getId(), volume.getDiskOfferingId(), null, snapshotName,
+        HypervisorType hypervisorType = volume.getHypervisorType();
+        SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(),
volume.getDomainId(), volume.getId(), volume.getDiskOfferingId(), snapshotName,
                 (short) snapshotType.ordinal(), snapshotType.name(), volume.getSize(), hypervisorType);
+        
         SnapshotVO snapshot = _snapshotDao.persist(snapshotVO);
         if (snapshot == null) {
-            throw new CloudRuntimeException("Failed to create snapshot for volume: "+volumeId);
+            throw new CloudRuntimeException("Failed to create snapshot for volume: " + volume.getId());
         }
         if (backup) {
             _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.secondary_storage,
@@ -991,7 +1027,19 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
             _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.primary_storage,
                     new Long(volume.getSize()));
         }
-        return snapshot;
+        SnapshotInfo snap = this.snapshotFactory.getSnapshot(snapshot.getId(), volume.getDataStore());
+        boolean processed = false;
+        for (SnapshotStrategy strategy : snapshotStrategies) {
+        	if (strategy.canHandle(snap)) {
+        		processed = true;
+        		snap = strategy.takeSnapshot(snap);
+        		break;
+        	}
+        }
+        if (!processed) {
+        	throw new CloudRuntimeException("Can't find snapshot strategy to deal with snapshot:"
+ snapshot.getId());
+        }
+        return snap;
     }
 
     @Override


Mime
View raw message