diff --git a/api/src/com/cloud/api/commands/CreateSnapshotCmd.java b/api/src/com/cloud/api/commands/CreateSnapshotCmd.java
index 94fddf93d17..5e54db27421 100644
--- a/api/src/com/cloud/api/commands/CreateSnapshotCmd.java
+++ b/api/src/com/cloud/api/commands/CreateSnapshotCmd.java
@@ -21,11 +21,12 @@ package com.cloud.api.commands;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
-import com.cloud.api.BaseAsyncCmd;
+import com.cloud.api.BaseAsyncCreateCmd;
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
+import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.response.SnapshotResponse;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
@@ -35,7 +36,7 @@ import com.cloud.storage.Volume;
import com.cloud.user.Account;
@Implementation(description="Creates an instant snapshot of a volume.", responseObject=SnapshotResponse.class)
-public class CreateSnapshotCmd extends BaseAsyncCmd {
+public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
public static final Logger s_logger = Logger.getLogger(CreateSnapshotCmd.class.getName());
private static final String s_name = "createsnapshotresponse";
@@ -52,6 +53,9 @@ public class CreateSnapshotCmd extends BaseAsyncCmd {
@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="polocy id of the snapshot, if this is null, then use MANUAL_POLICY.")
+ private Long policyId;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -67,6 +71,14 @@ public class CreateSnapshotCmd extends BaseAsyncCmd {
public Long getVolumeId() {
return volumeId;
}
+
+ public Long getPolicyId() {
+ if( policyId != null) {
+ return policyId;
+ } else {
+ return Snapshot.MANUAL_POLICY_ID;
+ }
+ }
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
@@ -106,6 +118,12 @@ public class CreateSnapshotCmd extends BaseAsyncCmd {
return AsyncJob.Type.Snapshot;
}
+ @Override
+ public void callCreate(){
+ long id = _snapshotMgr.getNextInSequence(this);
+ this.setId(id);
+ }
+
@Override
public void execute(){
try {
diff --git a/api/src/com/cloud/api/commands/CreateSnapshotInternalCmd.java b/api/src/com/cloud/api/commands/CreateSnapshotInternalCmd.java
deleted file mode 100644
index ff43ecd4966..00000000000
--- a/api/src/com/cloud/api/commands/CreateSnapshotInternalCmd.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
- * Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
- *
- * This software is licensed under the GNU General Public License v3 or later.
- *
- * It is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-package com.cloud.api.commands;
-
-import org.apache.log4j.Logger;
-
-import com.cloud.api.ApiConstants;
-import com.cloud.api.BaseAsyncCmd;
-import com.cloud.api.BaseCmd;
-import com.cloud.api.Implementation;
-import com.cloud.api.Parameter;
-import com.cloud.api.ServerApiException;
-import com.cloud.api.response.SnapshotResponse;
-import com.cloud.domain.Domain;
-import com.cloud.event.EventTypes;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.storage.Snapshot;
-import com.cloud.storage.Snapshot.Type;
-import com.cloud.storage.Volume;
-import com.cloud.user.Account;
-
-@Implementation(description="Creates an instant snapshot of a volume.", responseObject=SnapshotResponse.class)
-public class CreateSnapshotInternalCmd extends BaseAsyncCmd {
- public static final Logger s_logger = Logger.getLogger(CreateSnapshotInternalCmd.class.getName());
- private static final String s_name = "createsnapshotresponse";
-
- /////////////////////////////////////////////////////
- //////////////// API parameters /////////////////////
- /////////////////////////////////////////////////////
-
- @Parameter(name=ApiConstants.POLICY_ID, type=CommandType.LONG)
- private Long policyId;
-
- @Parameter(name=ApiConstants.VOLUME_ID, type=CommandType.LONG, required=true)
- private Long volumeId;
-
- /////////////////////////////////////////////////////
- /////////////////// Accessors ///////////////////////
- /////////////////////////////////////////////////////
-
- public Long getPolicyId() {
- return policyId;
- }
-
- public Long getVolumeId() {
- return volumeId;
- }
-
- /////////////////////////////////////////////////////
- /////////////// API Implementation///////////////////
- /////////////////////////////////////////////////////
-
- @Override
- public String getName() {
- return s_name;
- }
-
- public static String getResultObjectName() {
- return "snapshot";
- }
-
- @Override
- public long getAccountId() {
- Volume volume = _entityMgr.findById(Volume.class, getVolumeId());
- if (volume != null) {
- return volume.getAccountId();
- }
-
- // bad id given, parent this command to SYSTEM so ERROR events are tracked
- return Account.ACCOUNT_ID_SYSTEM;
- }
-
- @Override
- public String getEventType() {
- return EventTypes.EVENT_SNAPSHOT_CREATE;
- }
-
- @Override
- public String getEventDescription() {
- return "creating snapshot for volume: " + getVolumeId();
- }
-
- @Override
- public void execute(){
- try {
- Snapshot snapshot = _snapshotMgr.createSnapshotInternal(this);
- if (snapshot != null) {
- SnapshotResponse response = new SnapshotResponse();
- response.setId(snapshot.getId());
-
- Account account = _entityMgr.findById(Account.class, snapshot.getAccountId());
- if (account != null) {
- response.setAccountName(account.getAccountName());
- response.setDomainId(account.getDomainId());
- response.setDomainName(_entityMgr.findById(Domain.class, account.getDomainId()).getName());
- }
-
- Volume volume = _entityMgr.findById(Volume.class, snapshot.getVolumeId());
- String snapshotTypeStr = Type.values()[snapshot.getSnapshotType()].name();
- response.setSnapshotType(snapshotTypeStr);
- response.setVolumeId(snapshot.getVolumeId());
- response.setVolumeName(volume.getName());
- response.setVolumeType(volume.getVolumeType().toString());
- response.setCreated(snapshot.getCreated());
- response.setName(snapshot.getName());
- response.setObjectName("snapshot");
- response.setResponseName(getName());
- this.setResponseObject(response);
- } else {
- throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create snapshot");
- }
- } catch (ResourceAllocationException ex) {
- throw new ServerApiException(BaseCmd.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
- }
- }
-}
diff --git a/api/src/com/cloud/storage/snapshot/SnapshotService.java b/api/src/com/cloud/storage/snapshot/SnapshotService.java
index dcf51fc4602..004da20bff9 100644
--- a/api/src/com/cloud/storage/snapshot/SnapshotService.java
+++ b/api/src/com/cloud/storage/snapshot/SnapshotService.java
@@ -20,7 +20,6 @@ package com.cloud.storage.snapshot;
import java.util.List;
import com.cloud.api.commands.CreateSnapshotCmd;
-import com.cloud.api.commands.CreateSnapshotInternalCmd;
import com.cloud.api.commands.CreateSnapshotPolicyCmd;
import com.cloud.api.commands.DeleteSnapshotCmd;
import com.cloud.api.commands.DeleteSnapshotPoliciesCmd;
@@ -40,14 +39,6 @@ public interface SnapshotService {
*/
Snapshot createSnapshot(CreateSnapshotCmd cmd) throws InvalidParameterValueException, ResourceAllocationException;
- /**
- * An internal method for creating recurring snapshots. The command is not exposed through the API but is used to hook into the async framework.
- * @param cmd the command specifying volumeId and policyId
- * @return the created snapshot
- * @throws ResourceAllocationException
- */
- Snapshot createSnapshotInternal(CreateSnapshotInternalCmd cmd) throws ResourceAllocationException;
-
/**
* 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.)
@@ -87,5 +78,7 @@ public interface SnapshotService {
List extends SnapshotPolicy> listPoliciesforVolume(ListSnapshotPoliciesCmd cmd);
boolean deleteSnapshotPolicies(DeleteSnapshotPoliciesCmd cmd);
+
+ long getNextInSequence(CreateSnapshotCmd cmd);
}
diff --git a/core/src/com/cloud/agent/api/DeleteSnapshotsDirCommand.java b/core/src/com/cloud/agent/api/DeleteSnapshotsDirCommand.java
index 2073019e61e..c9694d35c43 100644
--- a/core/src/com/cloud/agent/api/DeleteSnapshotsDirCommand.java
+++ b/core/src/com/cloud/agent/api/DeleteSnapshotsDirCommand.java
@@ -57,10 +57,10 @@ public class DeleteSnapshotsDirCommand extends SnapshotCommand {
Long dcId,
Long accountId,
Long volumeId,
- String snapshotUUID,
- String snapshotName)
+ String volumePath)
{
- super(primaryStoragePoolNameLabel, secondaryStoragePoolURL, snapshotUUID, snapshotName, dcId, accountId, volumeId);
+ super(primaryStoragePoolNameLabel, secondaryStoragePoolURL, null, null, dcId, accountId, volumeId);
+ this.setVolumePath(volumePath);
}
}
\ No newline at end of file
diff --git a/core/src/com/cloud/storage/SnapshotVO.java b/core/src/com/cloud/storage/SnapshotVO.java
index 20c68d18957..4b4c3b4dbac 100644
--- a/core/src/com/cloud/storage/SnapshotVO.java
+++ b/core/src/com/cloud/storage/SnapshotVO.java
@@ -29,6 +29,7 @@ import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
+import javax.persistence.TableGenerator;
import com.cloud.utils.db.GenericDao;
import com.google.gson.annotations.Expose;
@@ -38,8 +39,8 @@ import com.google.gson.annotations.Expose;
public class SnapshotVO implements Snapshot {
@Id
- @GeneratedValue(strategy=GenerationType.IDENTITY)
- @Column(name="id")
+ @TableGenerator(name="snapshots_sq", table="sequence", pkColumnName="name", valueColumnName="value", pkColumnValue="snapshots_seq", allocationSize=1)
+ @Column(name="id", updatable=false, nullable = false)
Long id;
@Column(name="account_id")
@@ -81,7 +82,8 @@ public class SnapshotVO implements Snapshot {
public SnapshotVO() { }
- public SnapshotVO(long accountId, long volumeId, String path, String name, short snapshotType, String typeDescription) {
+ public SnapshotVO(long id, long accountId, long volumeId, String path, String name, short snapshotType, String typeDescription) {
+ this.id = id;
this.accountId = accountId;
this.volumeId = volumeId;
this.path = path;
diff --git a/server/src/com/cloud/storage/dao/SnapshotDao.java b/server/src/com/cloud/storage/dao/SnapshotDao.java
index 4391add9a82..fcd6d6dd064 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDao.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDao.java
@@ -31,5 +31,6 @@ public interface SnapshotDao extends GenericDao {
SnapshotVO findNextSnapshot(long parentSnapId);
long getLastSnapshot(long volumeId, long snapId);
List listByVolumeIdType(long volumeId, String type);
+ List listByVolumeIdIncludingRemoved(long volumeId);
}
diff --git a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
index d50f5fc43ec..fe7f44dc68b 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
@@ -18,25 +18,29 @@
package com.cloud.storage.dao;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
import java.util.List;
import javax.ejb.Local;
-import com.cloud.storage.Snapshot;
+import org.apache.log4j.Logger;
+
import com.cloud.storage.SnapshotVO;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
-import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.Transaction;
@Local (value={SnapshotDao.class})
public class SnapshotDaoImpl extends GenericDaoBase implements SnapshotDao {
+ public static final Logger s_logger = Logger.getLogger(SnapshotDaoImpl.class.getName());
+ private static final String GET_LAST_SNAPSHOT = "SELECT id FROM snapshots where volume_id = ? AND id != ? ORDER BY created DESC";
private final SearchBuilder VolumeIdSearch;
private final SearchBuilder VolumeIdTypeSearch;
private final SearchBuilder ParentIdSearch;
- private final GenericSearchBuilder lastSnapSearch;
@Override
public SnapshotVO findNextSnapshot(long snapshotId) {
@@ -62,6 +66,12 @@ public class SnapshotDaoImpl extends GenericDaoBase implements
return listBy(sc, filter);
}
+ @Override
+ public List listByVolumeIdIncludingRemoved(long volumeId) {
+ SearchCriteria sc = VolumeIdSearch.create();
+ sc.setParameters("volumeId", volumeId);
+ return listIncludingRemovedBy(sc, null);
+ }
public List listByVolumeIdType(Filter filter, long volumeId, String type ) {
SearchCriteria sc = VolumeIdTypeSearch.create();
@@ -83,24 +93,28 @@ public class SnapshotDaoImpl extends GenericDaoBase implements
ParentIdSearch = createSearchBuilder();
ParentIdSearch.and("prevSnapshotId", ParentIdSearch.entity().getPrevSnapshotId(), SearchCriteria.Op.EQ);
ParentIdSearch.done();
-
- lastSnapSearch = createSearchBuilder(Long.class);
- lastSnapSearch.select(null, SearchCriteria.Func.MAX, lastSnapSearch.entity().getId());
- lastSnapSearch.and("volumeId", lastSnapSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
- lastSnapSearch.and("snapId", lastSnapSearch.entity().getId(), SearchCriteria.Op.NEQ);
- lastSnapSearch.done();
+
+ }
+
+ @Override
+ public long getLastSnapshot(long volumeId, long snapId) {
+ 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);
+ ResultSet rs = pstmt.executeQuery();
+ if (rs.next()) {
+ return rs.getLong(1);
+ }
+ } catch (Exception ex) {
+ s_logger.error("error getting last snapshot", ex);
+ }
+ return 0;
}
- @Override
- public long getLastSnapshot(long volumeId, long snapId) {
- SearchCriteria sc = lastSnapSearch.create();
- sc.setParameters("volumeId", volumeId);
- sc.setParameters("snapId", snapId);
- List prevSnapshots = searchIncludingRemoved(sc, null);
- if(prevSnapshots != null && prevSnapshots.size() > 0 && prevSnapshots.get(0) != null) {
- return prevSnapshots.get(0);
- }
- return 0;
- }
+
}
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManager.java b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
index 24eb041c038..02e5e573e60 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManager.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
@@ -19,9 +19,6 @@ package com.cloud.storage.snapshot;
import java.util.List;
-import com.cloud.api.commands.ListSnapshotsCmd;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotVO;
@@ -46,7 +43,7 @@ public interface SnapshotManager {
* @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 startEventId) throws ResourceAllocationException;
+ SnapshotVO createSnapshotImpl(Long volumeId, Long policyId, Long startEventId, Long snapshotId) throws ResourceAllocationException;
/**
* After successfully creating a snapshot of a volume, copy the snapshot to the secondary storage for
@@ -130,5 +127,5 @@ public interface SnapshotManager {
* @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) throws ResourceAllocationException;
+ SnapshotVO createSnapshotOnPrimary(VolumeVO volume, Long polocyId, Long snapshotId) throws ResourceAllocationException;
}
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index 77ebdfdf437..f53174ec99b 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -18,6 +18,8 @@
package com.cloud.storage.snapshot;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -41,7 +43,6 @@ import com.cloud.agent.api.ManageSnapshotCommand;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.CreateSnapshotCmd;
-import com.cloud.api.commands.CreateSnapshotInternalCmd;
import com.cloud.api.commands.CreateSnapshotPolicyCmd;
import com.cloud.api.commands.DeleteSnapshotCmd;
import com.cloud.api.commands.DeleteSnapshotPoliciesCmd;
@@ -62,6 +63,7 @@ import com.cloud.event.dao.EventDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.UsageServerException;
import com.cloud.host.dao.DetailsDao;
import com.cloud.host.dao.HostDao;
import com.cloud.storage.Snapshot;
@@ -110,6 +112,8 @@ import com.cloud.vm.dao.UserVmDao;
@Local(value={SnapshotManager.class, SnapshotService.class})
public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Manager {
private static final Logger s_logger = Logger.getLogger(SnapshotManagerImpl.class);
+ private static final String GET_LAST_ID = "SELECT id FROM cloud.snapshots ORDER BY id DESC LIMIT 1";
+ private static final String UPDATE_SNAPSHOT_SEQ = "UPDATE cloud.sequence SET value=? WHERE name='snapshots_seq'";
@Inject protected HostDao _hostDao;
@Inject protected UserVmDao _vmDao;
@@ -193,7 +197,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
}
@Override
- public SnapshotVO createSnapshotOnPrimary(VolumeVO volume, Long policyId) throws ResourceAllocationException {
+ public SnapshotVO createSnapshotOnPrimary(VolumeVO volume, Long policyId, Long snapshotId) throws ResourceAllocationException {
SnapshotVO createdSnapshot = null;
Long volumeId = volume.getId();
if (volume.getStatus() != AsyncInstanceCreateStatus.Created) {
@@ -227,7 +231,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
// Create the Snapshot object and save it so we can return it to the
// user
Type snapshotType = SnapshotVO.getSnapshotType(policyId);
- SnapshotVO snapshotVO = new SnapshotVO(volume.getAccountId(), volume.getId(), null, snapshotName,
+ SnapshotVO snapshotVO = new SnapshotVO(snapshotId, volume.getAccountId(), volume.getId(), null, snapshotName,
(short) snapshotType.ordinal(), snapshotType.name());
snapshotVO = _snapshotDao.persist(snapshotVO);
id = snapshotVO.getId();
@@ -321,7 +325,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
}
@Override @DB
- public SnapshotVO createSnapshotImpl(Long volumeId, Long policyId, Long startEventId) throws ResourceAllocationException {
+ public SnapshotVO createSnapshotImpl(Long volumeId, Long policyId, Long snapshotId, Long startEventId) throws ResourceAllocationException {
VolumeVO volume = _volsDao.acquireInLockTable(volumeId, 10);
if( volume == null ) {
volume = _volsDao.findById(volumeId);
@@ -333,9 +337,8 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
}
SnapshotVO snapshot = null;
boolean backedUp = false;
- Long snapshotId = null;
try {
- snapshot = createSnapshotOnPrimary(volume, policyId);
+ snapshot = createSnapshotOnPrimary(volume, policyId, snapshotId);
if (snapshot != null && snapshot.getStatus() == Snapshot.Status.CreatedOnPrimary ) {
snapshotId = snapshot.getId();
backedUp = backupSnapshotToSecondaryStorage(snapshot, startEventId);
@@ -356,19 +359,12 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
@Override
public SnapshotVO createSnapshot(CreateSnapshotCmd cmd) throws ResourceAllocationException {
- Long volumeId = cmd.getVolumeId();
- Long policyId = Snapshot.MANUAL_POLICY_ID ;
- Long startEventId = cmd.getStartEventId();
- return createSnapshotImpl(volumeId, policyId, startEventId);
- }
-
- @Override
- public SnapshotVO createSnapshotInternal(CreateSnapshotInternalCmd cmd) throws ResourceAllocationException {
Long volumeId = cmd.getVolumeId();
Long policyId = cmd.getPolicyId();
+ Long snapshotId = cmd.getId();
Long startEventId = cmd.getStartEventId();
- return createSnapshotImpl(volumeId, policyId, startEventId);
- }
+ return createSnapshotImpl(volumeId, policyId, snapshotId, startEventId);
+ }
private SnapshotVO updateDBOnCreate(Long id, String snapshotPath, long preSnapshotId) {
SnapshotVO createdSnapshot = _snapshotDao.findByIdIncludingRemoved(id);
@@ -887,20 +883,11 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
Long dcId = volume.getDataCenterId();
String secondaryStoragePoolURL = _storageMgr.getSecondaryStorageURL(dcId);
String primaryStoragePoolNameLabel = _storageMgr.getPrimaryStorageNameLabel(volume);
- long mostRecentSnapshotId = _snapshotDao.getLastSnapshot(volumeId, -1L);
- if (mostRecentSnapshotId == 0L) {
+ if (_snapshotDao.listByVolumeIdIncludingRemoved(volumeId).isEmpty() ) {
// This volume doesn't have any snapshots. Nothing do delete.
continue;
}
- SnapshotVO mostRecentSnapshot = _snapshotDao.findByIdIncludingRemoved(mostRecentSnapshotId);
- if (mostRecentSnapshot == null) {
- // Huh. The code should never reach here.
- s_logger.error("Volume Id's mostRecentSnapshot with id: " + mostRecentSnapshotId + " turns out to be null");
- }
- // even if mostRecentSnapshot.removed() != null, we still have to explicitly remove it from the primary storage.
- // Then deleting the volume VDI will GC the base copy and nothing will be left on primary storage.
- String mostRecentSnapshotUuid = mostRecentSnapshot.getPath();
- DeleteSnapshotsDirCommand cmd = new DeleteSnapshotsDirCommand(primaryStoragePoolNameLabel, secondaryStoragePoolURL, dcId, accountId, volumeId, mostRecentSnapshotUuid, mostRecentSnapshot.getName());
+ DeleteSnapshotsDirCommand cmd = new DeleteSnapshotsDirCommand(primaryStoragePoolNameLabel, secondaryStoragePoolURL, dcId, accountId, volumeId, volume.getPath());
String basicErrMsg = "Failed to destroy snapshotsDir for: " + volume.getId() + " under account: " + accountId;
Answer answer = null;
Long poolId = volume.getPoolId();
@@ -1161,6 +1148,45 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
return _snapshotPolicyDao.findOneByVolume(volumeId);
}
+ @Override
+ public long getNextInSequence(CreateSnapshotCmd cmd) {
+ return _snapshotDao.getNextInSequence(Long.class, "id");
+ }
+
+ private Long _getLastId() {
+ Transaction txn = Transaction.open(Transaction.CLOUD_DB);
+ PreparedStatement pstmt = null;
+ String sql = GET_LAST_ID;
+ try {
+ pstmt = txn.prepareAutoCloseStatement(sql);
+ ResultSet rs = pstmt.executeQuery();
+ if (rs.next()) {
+ return Long.valueOf(rs.getLong(1));
+ }
+ } catch (Exception ex) {
+ s_logger.error("error getting last id", ex);
+ }
+ return null;
+ }
+
+ private void _updateSnapshotSeq(Long seq) {
+ Transaction txn = Transaction.open(Transaction.CLOUD_DB);
+ try {
+ txn.start();
+ String sql = UPDATE_SNAPSHOT_SEQ;
+ PreparedStatement pstmt = null;
+ pstmt = txn.prepareAutoCloseStatement(sql);
+ pstmt.setLong(1, seq.longValue());
+ pstmt.execute();
+ txn.commit();
+ } catch (Exception ex) {
+ txn.rollback();
+ String msg = "error seting snapshots_seq to " + seq;
+ s_logger.error(msg, ex);
+ throw new CloudRuntimeException(msg, ex);
+ }
+ }
+
@Override
public boolean configure(String name, Map params) throws ConfigurationException {
_name = name;
@@ -1179,7 +1205,15 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
_deltaSnapshotMax = NumbersUtil.parseInt(configDao.getValue("snapshot.delta.max"), DELTAMAX);
_totalRetries = NumbersUtil.parseInt(configDao.getValue("total.retries"), 4);
_pauseInterval = 2*NumbersUtil.parseInt(configDao.getValue("ping.interval"), 60);
-
+
+ Long lastId = _getLastId();
+ if ( lastId == null ) {
+ String msg = "Can not get last id of snapshots";
+ s_logger.error(msg);
+ throw new CloudRuntimeException(msg);
+ }
+ s_logger.info("Set shapshot sequence to " + (lastId + 1));
+ _updateSnapshotSeq( lastId + 1 );
s_logger.info("Snapshot Manager is configured.");
return true;
@@ -1249,4 +1283,5 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
return success;
}
+
}
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
index be91e3ea66d..d6f7bf7410d 100644
--- a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
@@ -30,7 +30,7 @@ import javax.persistence.EntityExistsException;
import org.apache.log4j.Logger;
-import com.cloud.api.commands.CreateSnapshotInternalCmd;
+import com.cloud.api.commands.CreateSnapshotCmd;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobResult;
import com.cloud.async.AsyncJobVO;
@@ -228,7 +228,7 @@ public class SnapshotSchedulerImpl implements SnapshotScheduler {
// Just have SYSTEM own the job for now. Users won't be able to see this job, but
// it's an internal job so probably not a huge deal.
job.setAccountId(1L);
- job.setCmd(CreateSnapshotInternalCmd.class.getName());
+ job.setCmd(CreateSnapshotCmd.class.getName());
job.setCmdInfo(GsonHelper.getBuilder().create().toJson(params));
long jobId = _asyncMgr.submitAsyncJob(job);
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index 551f34d441d..1742d7c66b6 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -277,6 +277,7 @@ INSERT INTO `cloud`.`sequence` (name, value) VALUES ('private_mac_address_seq',
INSERT INTO `cloud`.`sequence` (name, value) VALUES ('storage_pool_seq', 200);
INSERT INTO `cloud`.`sequence` (name, value) VALUES ('volume_seq', 1);
INSERT INTO `cloud`.`sequence` (name, value) VALUES ('networks_seq', 1);
+INSERT INTO `cloud`.`sequence` (name, value) VALUES ('snapshots_seq', 1);
CREATE TABLE `cloud`.`volumes` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
@@ -315,7 +316,7 @@ CREATE TABLE `cloud`.`volumes` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`snapshots` (
- `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
+ `id` bigint unsigned UNIQUE NOT NULL 'Primary Key',
`account_id` bigint unsigned NOT NULL COMMENT 'owner. foreign key to account table',
`volume_id` bigint unsigned NOT NULL COMMENT 'volume it belongs to. foreign key to volume table',
`status` varchar(32) COMMENT 'snapshot creation status',
diff --git a/setup/db/data-21to22.sql b/setup/db/data-21to22.sql
index a13fa0a9946..7fcc35e36a8 100644
--- a/setup/db/data-21to22.sql
+++ b/setup/db/data-21to22.sql
@@ -15,5 +15,7 @@ UPDATE vm_template set unique_name='routing_old' where id=1;
INSERT INTO vm_template (id, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones)
VALUES (10, 'routing', 'SystemVM Template', 0, now(), 'ext3', 0, 64, 1, 'http://download.cloud.com/releases/2.2/systemvm.vhd.bz2', 'bcc7f290f4c27ab4d0fe95d1012829ea', 0, 'SystemVM Template', 'VHD', 15, 0, 1);
Update configuration set name='storage.max.volume.size' where name='max.volume.size.mb';
+INSERT INTO sequence (name, value)
+ VALUES ('snapshots_seq', '1')
COMMIT;
diff --git a/setup/db/data-22beta1to22beta2.sql b/setup/db/data-22beta1to22beta2.sql
new file mode 100644
index 00000000000..f52a94b3651
--- /dev/null
+++ b/setup/db/data-22beta1to22beta2.sql
@@ -0,0 +1,2 @@
+INSERT INTO sequence (name, value)
+ VALUES ('snapshots_seq', '1')
diff --git a/setup/db/schema-21to22.sql b/setup/db/schema-21to22.sql
index ebfb3a35d3e..3e3d8f0ea5c 100644
--- a/setup/db/schema-21to22.sql
+++ b/setup/db/schema-21to22.sql
@@ -3,5 +3,6 @@ SET foreign_key_checks = 0;
--
-- Schema upgrade from 2.1 to 2.2
--
-ALTER TABLE `cloud`.`template_host_ref` ADD COLUMN `physical_size` bigint unsigned NOT NULL DEFAULT 0;
+ALTER TABLE `cloud`.`template_host_ref` ADD COLUMN `physical_size` bigint unsigned NOT NULL DEFAULT 0
+ALTER TABLE `cloud`.`snapshots` MODIFY COLUMN `id` bigint unsigned UNIQUE NOT NULL
ALTER TABLE `vm_instance` DROP COLUMN `group`
diff --git a/setup/db/schema-22beta1to22beta2.sql b/setup/db/schema-22beta1to22beta2.sql
new file mode 100644
index 00000000000..efb631a2deb
--- /dev/null
+++ b/setup/db/schema-22beta1to22beta2.sql
@@ -0,0 +1 @@
+ALTER TABLE `cloud`.`snapshots` MODIFY COLUMN `id` bigint unsigned UNIQUE NOT NULL