bug 9663: do account permission check against the volume when create snapshot

status 9663: resolved fixed
This commit is contained in:
alena 2011-05-03 11:32:35 -07:00
parent 64a7f72dc0
commit 6502171f39
4 changed files with 143 additions and 138 deletions

View File

@ -34,30 +34,30 @@ import com.cloud.storage.Snapshot;
import com.cloud.storage.Volume;
import com.cloud.user.Account;
@Implementation(description="Creates an instant snapshot of a volume.", responseObject=SnapshotResponse.class)
@Implementation(description = "Creates an instant snapshot of a volume.", responseObject = SnapshotResponse.class)
public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
public static final Logger s_logger = Logger.getLogger(CreateSnapshotCmd.class.getName());
private static final String s_name = "createsnapshotresponse";
public static final Logger s_logger = Logger.getLogger(CreateSnapshotCmd.class.getName());
private static final String s_name = "createsnapshotresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="The account of the snapshot. The account parameter must be used with the domainId parameter.")
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "The account of the snapshot. The account parameter must be used with the domainId parameter.")
private String accountName;
@Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="The domain ID of the snapshot. If used with the account parameter, specifies a domain for the account associated with the disk volume.")
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.LONG, description = "The domain ID of the snapshot. If used with the account parameter, specifies a domain for the account associated with the disk volume.")
private Long domainId;
@Parameter(name=ApiConstants.VOLUME_ID, type=CommandType.LONG, required=true, description="The ID of the disk volume")
@Parameter(name = ApiConstants.VOLUME_ID, type = CommandType.LONG, required = true, description = "The ID of the disk volume")
private Long volumeId;
@Parameter(name=ApiConstants.POLICY_ID, type=CommandType.LONG, description="policy id of the snapshot, if this is null, then use MANUAL_POLICY.")
@Parameter(name = ApiConstants.POLICY_ID, type = CommandType.LONG, description = "policy id of the snapshot, if this is null, then use MANUAL_POLICY.")
private Long policyId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
public String getAccountName() {
return accountName;
@ -70,26 +70,26 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
public Long getVolumeId() {
return volumeId;
}
public Long getPolicyId() {
if( policyId != null) {
return policyId;
} else {
return Snapshot.MANUAL_POLICY_ID;
}
if (policyId != null) {
return policyId;
} else {
return Snapshot.MANUAL_POLICY_ID;
}
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
public static String getResultObjectName() {
return "snapshot";
return "snapshot";
}
@Override
@ -110,27 +110,27 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
@Override
public String getEventDescription() {
return "creating snapshot for volume: " + getVolumeId();
return "creating snapshot for volume: " + getVolumeId();
}
@Override
public AsyncJob.Type getInstanceType() {
return AsyncJob.Type.Snapshot;
return AsyncJob.Type.Snapshot;
}
@Override
public void create() throws ResourceAllocationException{
Snapshot snapshot = _snapshotService.allocSnapshot(this);
public void create() throws ResourceAllocationException {
Snapshot snapshot = _snapshotService.allocSnapshot(getVolumeId(), getPolicyId());
if (snapshot != null) {
this.setEntityId(snapshot.getId());
} else {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create snapshot");
}
}
@Override
public void execute() {
Snapshot snapshot = _snapshotService.createSnapshot(this);
public void execute() {
Snapshot snapshot = _snapshotService.createSnapshot(getVolumeId(), getPolicyId(), getEntityId());
if (snapshot != null) {
SnapshotResponse response = _responseGenerator.createSnapshotResponse(snapshot);
response.setResponseName(getCommandName());

View File

@ -19,7 +19,6 @@ package com.cloud.storage.snapshot;
import java.util.List;
import com.cloud.api.commands.CreateSnapshotCmd;
import com.cloud.api.commands.CreateSnapshotPolicyCmd;
import com.cloud.api.commands.DeleteSnapshotCmd;
import com.cloud.api.commands.DeleteSnapshotPoliciesCmd;
@ -32,16 +31,12 @@ import com.cloud.exception.ResourceAllocationException;
import com.cloud.storage.Snapshot;
public interface SnapshotService {
/**
* Create a snapshot of a volume
* @param cmd the API command wrapping the parameters for creating the snapshot (mainly volumeId)
* @return the Snapshot that was created
*/
Snapshot createSnapshot(CreateSnapshotCmd cmd) throws InvalidParameterValueException;
/**
* List all snapshots of a disk volume. Optionally lists snapshots created by specified interval
* @param cmd the command containing the search criteria (order by, limit, etc.)
*
* @param cmd
* the command containing the search criteria (order by, limit, etc.)
* @return list of snapshots
* @throws InvalidParameterValueException
* @throws PermissionDeniedException
@ -49,36 +44,51 @@ public interface SnapshotService {
List<? extends Snapshot> listSnapshots(ListSnapshotsCmd cmd);
/**
* Delete specified snapshot from the specified.
* If no other policies are assigned it calls destroy snapshot.
* This will be used for manual snapshots too.
* Delete specified snapshot from the specified. If no other policies are assigned it calls destroy snapshot. This will be
* used for manual snapshots too.
*/
boolean deleteSnapshot(DeleteSnapshotCmd cmd);
boolean deleteSnapshot(DeleteSnapshotCmd cmd);
/**
* Creates a policy with specified schedule. maxSnaps specifies the number of most recent snapshots that are to be retained.
* If the number of snapshots go beyond maxSnaps the oldest snapshot is deleted
* @param cmd the command that
* If the number of snapshots go beyond maxSnaps the oldest snapshot is deleted
*
* @param cmd
* the command that
* @return the newly created snapshot policy if success, null otherwise
*/
SnapshotPolicy createPolicy(CreateSnapshotPolicyCmd cmd);
/**
* Get the recurring snapshots scheduled for this volume currently along with the time at which they are scheduled
* @param cmd the command wrapping the volumeId (volume for which the snapshots are required) and policyId (to show snapshots for only this policy).
* Get the recurring snapshots scheduled for this volume currently along with the time at which they are scheduled
*
* @param cmd
* the command wrapping the volumeId (volume for which the snapshots are required) and policyId (to show
* snapshots for only this policy).
* @return The list of snapshot schedules.
*/
public List<? extends SnapshotSchedule> findRecurringSnapshotSchedule(ListRecurringSnapshotScheduleCmd cmd);
/**
* list all snapshot policies assigned to the specified volume
* @param cmd the command that specifies the volume criteria
*
* @param cmd
* the command that specifies the volume criteria
* @return list of snapshot policies
*/
List<? extends SnapshotPolicy> listPoliciesforVolume(ListSnapshotPoliciesCmd cmd);
boolean deleteSnapshotPolicies(DeleteSnapshotPoliciesCmd cmd);
Snapshot allocSnapshot(CreateSnapshotCmd cmd) throws ResourceAllocationException;
Snapshot allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException;
/**
* Create a snapshot of a volume
*
* @param cmd
* the API command wrapping the parameters for creating the snapshot (mainly volumeId)
* @return the Snapshot that was created
*/
Snapshot createSnapshot(Long volumeId, Long policyId, Long snapshotId);
}

View File

@ -22,52 +22,49 @@ import java.util.List;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.VolumeVO;
import com.cloud.utils.db.Filter;
/**
*
* SnapshotManager contains all of the code to work with volume snapshots.
*
*/
*
* SnapshotManager contains all of the code to work with volume snapshots.
*
*/
public interface SnapshotManager {
public static final int HOURLYMAX = 8;
public static final int DAILYMAX = 8;
public static final int WEEKLYMAX = 8;
public static final int MONTHLYMAX = 12;
public static final int DELTAMAX = 16;
/**
* Create a snapshot of a volume
* @param cmd the API command wrapping the parameters for creating the snapshot (mainly volumeId)
* @return the Snapshot that was created
*/
SnapshotVO createSnapshotImpl(Long volumeId, Long policyId, Long snapshotId);
public static final int HOURLYMAX = 8;
public static final int DAILYMAX = 8;
public static final int WEEKLYMAX = 8;
public static final int MONTHLYMAX = 12;
public static final int DELTAMAX = 16;
/**
* After successfully creating a snapshot of a volume, copy the snapshot to the secondary storage for
* 1) reliability
* 2) So that storage space on Primary is conserved.
* @param snapshot Info about the created snapshot on primary storage.
* @param startEventId event id of the scheduled event for this snapshot
* @return True if the snapshot was successfully backed up.
* After successfully creating a snapshot of a volume, copy the snapshot to the secondary storage for 1) reliability 2) So
* that storage space on Primary is conserved.
*
* @param snapshot
* Info about the created snapshot on primary storage.
* @param startEventId
* event id of the scheduled event for this snapshot
* @return True if the snapshot was successfully backed up.
*/
public boolean backupSnapshotToSecondaryStorage(SnapshotVO snapshot);
/**
* Once a snapshot has completed,
* 1) If success, update the database entries
* 2) If success and there are excess snapshots for any of the policies given, delete the oldest one.
* 3) Schedule the next recurring snapshot.
* @param volumeId The volume for which the snapshot is being taken
* @param snapshotId The snapshot which has just completed
* @param policyIds The list of policyIds to which this snapshot belongs to
* @param backedUp If true, the snapshot has been successfully created.
* Once a snapshot has completed, 1) If success, update the database entries 2) If success and there are excess snapshots
* for any of the policies given, delete the oldest one. 3) Schedule the next recurring snapshot.
*
* @param volumeId
* The volume for which the snapshot is being taken
* @param snapshotId
* The snapshot which has just completed
* @param policyIds
* The list of policyIds to which this snapshot belongs to
* @param backedUp
* If true, the snapshot has been successfully created.
*/
void postCreateSnapshot(Long volumeId, Long snapshotId, Long policyId, boolean backedUp);
/**
* Destroys the specified snapshot from secondary storage
*/
@ -77,41 +74,41 @@ public interface SnapshotManager {
* Deletes snapshot scheduling policy. Delete will fail if this policy is assigned to one or more volumes
*/
boolean deletePolicy(long userId, Long policyId);
/**
* Lists all snapshots for the volume which are created using schedule of the specified policy
*/
/*
List<SnapshotVO> listSnapsforPolicy(long policyId, Filter filter);
*/
* List<SnapshotVO> listSnapsforPolicy(long policyId, Filter filter);
*/
/**
* List all policies which are assigned to the specified volume
*/
List<SnapshotPolicyVO> listPoliciesforVolume(long volumeId);
/**
* List all policies to which a specified snapshot belongs. For ex: A snapshot
* may belong to a hourly snapshot and a daily snapshot run at the same time
* List all policies to which a specified snapshot belongs. For ex: A snapshot may belong to a hourly snapshot and a daily
* snapshot run at the same time
*/
/*
List<SnapshotPolicyVO> listPoliciesforSnapshot(long snapshotId);
*/
* List<SnapshotPolicyVO> listPoliciesforSnapshot(long snapshotId);
*/
/**
* List all snapshots for a specified volume irrespective of the policy which
* created the snapshot
* List all snapshots for a specified volume irrespective of the policy which created the snapshot
*/
List<SnapshotVO> listSnapsforVolume(long volumeId);
void deletePoliciesForVolume(Long volumeId);
void deletePoliciesForVolume(Long volumeId);
/**
* For each of the volumes in the account,
* (which can span across multiple zones and multiple secondary storages),
* delete the dir on the secondary storage which contains the backed up snapshots for that volume.
* This is called during deleteAccount.
* @param accountId The account which is to be deleted.
* For each of the volumes in the account, (which can span across multiple zones and multiple secondary storages), delete
* the dir on the secondary storage which contains the backed up snapshots for that volume. This is called during
* deleteAccount.
*
* @param accountId
* The account which is to be deleted.
*/
boolean deleteSnapshotDirsForAccount(long accountId);
boolean deleteSnapshotDirsForAccount(long accountId);
void validateSnapshot(Long userId, SnapshotVO snapshot);
@ -121,10 +118,12 @@ public interface SnapshotManager {
/**
* Create a snapshot of a volume
* @param cmd the API command wrapping the parameters for creating the snapshot (mainly volumeId)
*
* @param cmd
* the API command wrapping the parameters for creating the snapshot (mainly volumeId)
* @return the Snapshot that was created
*/
SnapshotVO createSnapshotOnPrimary(VolumeVO volume, Long polocyId, Long snapshotId) throws ResourceAllocationException;
SnapshotVO createSnapshotOnPrimary(VolumeVO volume, Long polocyId, Long snapshotId) throws ResourceAllocationException;
List<SnapshotPolicyVO> listPoliciesforSnapshot(long snapshotId);

View File

@ -38,7 +38,6 @@ import com.cloud.agent.api.DeleteSnapshotBackupCommand;
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
import com.cloud.agent.api.ManageSnapshotAnswer;
import com.cloud.agent.api.ManageSnapshotCommand;
import com.cloud.api.commands.CreateSnapshotCmd;
import com.cloud.api.commands.CreateSnapshotPolicyCmd;
import com.cloud.api.commands.DeleteSnapshotCmd;
import com.cloud.api.commands.DeleteSnapshotPoliciesCmd;
@ -229,10 +228,10 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
Thread.sleep(_pauseInterval * 1000);
} catch (InterruptedException e) {
}
s_logger.debug("Retrying...");
}
s_logger.warn("After " + _totalRetries + " retries, the command " + cmd.getClass().getName() + " did not succeed.");
return null;
@ -327,7 +326,8 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
@Override
@DB
public SnapshotVO createSnapshotImpl(Long volumeId, Long policyId, Long snapshotId) {
@ActionEvent(eventType = EventTypes.EVENT_SNAPSHOT_CREATE, eventDescription = "creating snapshot", async = true)
public SnapshotVO createSnapshot(Long volumeId, Long policyId, Long snapshotId) {
VolumeVO v = _volsDao.findById(volumeId);
Account owner = _accountMgr.getAccount(v.getAccountId());
SnapshotVO snapshot = null;
@ -368,7 +368,8 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
if (userVm != null) {
if (userVm.getState().equals(State.Destroyed) || userVm.getState().equals(State.Expunging)) {
_snapshotDao.expunge(snapshotId);
throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volumeId + " is associated with vm:" + userVm.getInstanceName() + " is in " + userVm.getState().toString() + " state");
throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volumeId + " is associated with vm:" + userVm.getInstanceName() + " is in "
+ userVm.getState().toString() + " state");
}
}
}
@ -389,7 +390,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
if (snapshot.getStatus() == Snapshot.Status.CreatedOnPrimary) {
backedUp = backupSnapshotToSecondaryStorage(snapshot);
} else if (snapshot.getStatus() == Snapshot.Status.BackedUp) {
//For empty snapshot we set status to BackedUp in createSnapshotOnPrimary
// For empty snapshot we set status to BackedUp in createSnapshotOnPrimary
backedUp = true;
}
if (!backedUp) {
@ -404,7 +405,8 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
postCreateSnapshot(volumeId, snapshot.getId(), policyId, backedUp);
_volsDao.releaseFromLockTable(volumeId);
if (backedUp) {
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(), snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null, v.getSize());
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(), snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
v.getSize());
_usageEventDao.persist(usageEvent);
}
} else if (snapshot == null || !backedUp) {
@ -416,15 +418,6 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
return snapshot;
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_SNAPSHOT_CREATE, eventDescription = "creating snapshot", async = true)
public SnapshotVO createSnapshot(CreateSnapshotCmd cmd) {
Long volumeId = cmd.getVolumeId();
Long policyId = cmd.getPolicyId();
Long snapshotId = cmd.getEntityId();
return createSnapshotImpl(volumeId, policyId, snapshotId);
}
private SnapshotVO updateDBOnCreate(Long id, String snapshotPath, long preSnapshotId) {
SnapshotVO createdSnapshot = _snapshotDao.findByIdIncludingRemoved(id);
createdSnapshot.setPath(snapshotPath);
@ -494,7 +487,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
long prevSnapshotId = snapshot.getPrevSnapshotId();
if (prevSnapshotId > 0) {
prevSnapshot = _snapshotDao.findByIdIncludingRemoved(prevSnapshotId);
if (prevSnapshot.getVersion() != null && prevSnapshot.getVersion().equals("2.2") ) {
if (prevSnapshot.getVersion() != null && prevSnapshot.getVersion().equals("2.2")) {
prevBackupUuid = prevSnapshot.getBackupSnapshotId();
if (prevBackupUuid != null) {
prevSnapshotUuid = prevSnapshot.getPath();
@ -504,8 +497,8 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
boolean isVolumeInactive = _storageMgr.volumeInactive(volume);
String vmName = _storageMgr.getVmNameOnVolume(volume);
BackupSnapshotCommand backupSnapshotCommand = new BackupSnapshotCommand(primaryStoragePoolNameLabel, secondaryStoragePoolUrl, dcId, accountId, volumeId, volume.getPath(), snapshotUuid, snapshot.getName(), prevSnapshotUuid, prevBackupUuid,
isVolumeInactive, vmName);
BackupSnapshotCommand backupSnapshotCommand = new BackupSnapshotCommand(primaryStoragePoolNameLabel, secondaryStoragePoolUrl, dcId, accountId, volumeId, volume.getPath(), snapshotUuid,
snapshot.getName(), prevSnapshotUuid, prevBackupUuid, isVolumeInactive, vmName);
String backedUpSnapshotUuid = null;
// By default, assume failed.
@ -641,7 +634,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
return status;
}
@DB
private boolean deleteSnapshotInternal(Long snapshotId) {
if (s_logger.isDebugEnabled()) {
@ -656,7 +649,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
_snapshotDao.update(snapshot.getId(), snapshot);
}
}
Transaction txn = Transaction.currentTxn();
txn.start();
_snapshotDao.remove(snapshotId);
@ -664,7 +657,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
_usageEventDao.persist(usageEvent);
_accountMgr.decrementResourceCount(snapshot.getAccountId(), ResourceType.snapshot);
txn.commit();
long lastId = snapshotId;
boolean destroy = false;
while (true) {
@ -942,7 +935,8 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
}
// Log event after successful deletion
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SNAPSHOT_DELETE, snapshot.getAccountId(), volume.getDataCenterId(), snapshot.getId(), snapshot.getName(), null, null, volume.getSize());
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_SNAPSHOT_DELETE, snapshot.getAccountId(), volume.getDataCenterId(), snapshot.getId(), snapshot.getName(), null, null,
volume.getSize());
_usageEventDao.persist(usageEvent);
}
}
@ -1019,7 +1013,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
policy = _snapshotPolicyDao.acquireInLockTable(policy.getId());
policy.setSchedule(cmd.getSchedule());
policy.setTimezone(timezoneId);
policy.setInterval((short)intvType.ordinal());
policy.setInterval((short) intvType.ordinal());
policy.setMaxSnaps(cmd.getMaxSnaps());
policy.setActive(true);
_snapshotPolicyDao.update(policy.getId(), policy);
@ -1164,21 +1158,23 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
}
@Override
public SnapshotVO allocSnapshot(CreateSnapshotCmd cmd) throws ResourceAllocationException {
Long volumeId = cmd.getVolumeId();
Long policyId = cmd.getPolicyId();
public SnapshotVO allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException {
Account caller = UserContext.current().getCaller();
VolumeVO volume = _volsDao.findById(volumeId);
if (volume == null) {
throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volumeId + " doesn't exist");
throw new InvalidParameterValueException("Creating snapshot failed due to volume:" + volumeId + " doesn't exist");
}
if (volume.getState() != Volume.State.Ready) {
throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in Created state but " + volume.getState() + ". Cannot take snapshot.");
throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot.");
}
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");
}
// Verify permissions
_accountMgr.checkAccess(caller, volume);
Account owner = _accountMgr.getAccount(volume.getAccountId());
if (_accountMgr.resourceLimitExceeded(owner, ResourceType.snapshot)) {
ResourceAllocationException rae = new ResourceAllocationException("Maximum number of snapshots for account: " + owner.getAccountName() + " has been exceeded.");
@ -1201,8 +1197,8 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
// user
Type snapshotType = getSnapshotType(policyId);
HypervisorType hypervisorType = this._volsDao.getHypervisorType(volumeId);
SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(), volume.getDomainId(), volume.getId(), volume.getDiskOfferingId(), null, snapshotName, (short) snapshotType.ordinal(), snapshotType.name(), volume.getSize(),
hypervisorType);
SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(), volume.getDomainId(), volume.getId(), volume.getDiskOfferingId(), null, snapshotName,
(short) snapshotType.ordinal(), snapshotType.name(), volume.getSize(), hypervisorType);
SnapshotVO snapshot = _snapshotDao.persist(snapshotVO);
if (snapshot != null) {