mirror of https://github.com/apache/cloudstack.git
bug 7144: return snapshotId with jobid
1. manual and recursive snapshot use the same command 2. upgrade from 2.2 beta1 to beta need to execute schema-22beta1to22beta2.sql and data-22beta1to22beta2.sql 3. upgrade from 2.1GA to 2.2GA need to execute schema-21to22.sql and data-21to22.sql status 7144: resolved fixed
This commit is contained in:
parent
d184c56ef3
commit
6f1eb4bf44
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -31,5 +31,6 @@ public interface SnapshotDao extends GenericDao<SnapshotVO, Long> {
|
|||
SnapshotVO findNextSnapshot(long parentSnapId);
|
||||
long getLastSnapshot(long volumeId, long snapId);
|
||||
List<SnapshotVO> listByVolumeIdType(long volumeId, String type);
|
||||
List<SnapshotVO> listByVolumeIdIncludingRemoved(long volumeId);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<SnapshotVO, Long> 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<SnapshotVO> VolumeIdSearch;
|
||||
private final SearchBuilder<SnapshotVO> VolumeIdTypeSearch;
|
||||
private final SearchBuilder<SnapshotVO> ParentIdSearch;
|
||||
private final GenericSearchBuilder<SnapshotVO, Long> lastSnapSearch;
|
||||
|
||||
@Override
|
||||
public SnapshotVO findNextSnapshot(long snapshotId) {
|
||||
|
|
@ -62,6 +66,12 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
|
|||
return listBy(sc, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SnapshotVO> listByVolumeIdIncludingRemoved(long volumeId) {
|
||||
SearchCriteria<SnapshotVO> sc = VolumeIdSearch.create();
|
||||
sc.setParameters("volumeId", volumeId);
|
||||
return listIncludingRemovedBy(sc, null);
|
||||
}
|
||||
|
||||
public List<SnapshotVO> listByVolumeIdType(Filter filter, long volumeId, String type ) {
|
||||
SearchCriteria<SnapshotVO> sc = VolumeIdTypeSearch.create();
|
||||
|
|
@ -83,24 +93,28 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> 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<Long> sc = lastSnapSearch.create();
|
||||
sc.setParameters("volumeId", volumeId);
|
||||
sc.setParameters("snapId", snapId);
|
||||
List<Long> prevSnapshots = searchIncludingRemoved(sc, null);
|
||||
if(prevSnapshots != null && prevSnapshots.size() > 0 && prevSnapshots.get(0) != null) {
|
||||
return prevSnapshots.get(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<String, Object> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
INSERT INTO sequence (name, value)
|
||||
VALUES ('snapshots_seq', '1')
|
||||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE `cloud`.`snapshots` MODIFY COLUMN `id` bigint unsigned UNIQUE NOT NULL
|
||||
Loading…
Reference in New Issue