You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2013/04/23 01:16:56 UTC
[1/2] Rename SnapshotStrategy to SnapshotService to have consistent
naming convention for Template, Snapshot,
Volume. Also rename CopyCmd to CopyCommand to follow internal command naming
convention.
Updated Branches:
refs/heads/object_store 5f90aa971 -> 29687663e
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/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 3a453d5..88bcc6a 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -34,7 +34,7 @@ import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
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.SnapshotStrategy;
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
@@ -126,8 +126,8 @@ import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
@Component
-@Local(value = { SnapshotManager.class, SnapshotService.class })
-public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, SnapshotService {
+@Local(value = { SnapshotManager.class, SnapshotApiService.class })
+public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, SnapshotApiService {
private static final Logger s_logger = Logger.getLogger(SnapshotManagerImpl.class);
@Inject
protected VMTemplateDao _templateDao;
@@ -171,9 +171,9 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
private ResourceLimitService _resourceLimitMgr;
@Inject
private SwiftManager _swiftMgr;
- @Inject
+ @Inject
private S3Manager _s3Mgr;
- @Inject
+ @Inject
private SecondaryStorageVmManager _ssvmMgr;
@Inject
private DomainManager _domainMgr;
@@ -182,17 +182,17 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
@Inject
private ConfigurationDao _configDao;
- @Inject
+ @Inject
private VMSnapshotDao _vmSnapshotDao;
String _name;
@Inject TemplateManager templateMgr;
@Inject VolumeManager volumeMgr;
@Inject DataStoreManager dataStoreMgr;
- @Inject List<SnapshotStrategy> snapshotStrategies;
+ @Inject SnapshotService snapshotSrv;
@Inject VolumeDataFactory volFactory;
@Inject SnapshotDataFactory snapshotFactory;
-
+
private int _totalRetries;
private int _pauseInterval;
@@ -201,14 +201,14 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
protected SearchBuilder<SnapshotVO> PolicySnapshotSearch;
protected SearchBuilder<SnapshotPolicyVO> PoliciesForSnapSearch;
-
+
@Override
public Answer sendToPool(Volume vol, Command cmd) {
StoragePool pool = (StoragePool)dataStoreMgr.getPrimaryDataStore(vol.getPoolId());
long[] hostIdsToTryFirst = null;
-
+
Long vmHostId = getHostIdForSnapshotOperation(vol);
-
+
if (vmHostId != null) {
hostIdsToTryFirst = new long[] { vmHostId };
}
@@ -263,29 +263,22 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
if (volume == null) {
throw new InvalidParameterValueException("No such volume exist");
}
-
+
if (volume.getState() != Volume.State.Ready) {
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);
- SnapshotStrategy strategy = null;
- for (SnapshotStrategy st : snapshotStrategies) {
- if (st.canHandle(snap)) {
- strategy = st;
- break;
- }
- }
try {
- snapshot = strategy.takeSnapshot(volume, snapshotId);
+ 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
@@ -344,20 +337,13 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
if (snapshot == null) {
throw new CloudRuntimeException("Can't find snapshot:" + snapshotId);
}
-
+
if (snapshot.getState() == Snapshot.State.BackedUp) {
return snapshot;
}
-
- SnapshotStrategy strategy = null;
- for (SnapshotStrategy st : snapshotStrategies) {
- if (st.canHandle(snapshot)) {
- strategy = st;
- break;
- }
- }
-
- return strategy.backupSnapshot(snapshot);
+
+
+ return this.snapshotSrv.backupSnapshot(snapshot);
}
@Override
@@ -394,7 +380,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
} catch (Exception e) {
throw new CloudRuntimeException("downloadSnapshotsFromSwift failed due to " + e.toString());
}
-
+
}
private List<String> determineBackupUuids(final SnapshotVO snapshot) {
@@ -445,7 +431,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
}
}
-
+
@Override
public SnapshotVO getParentSnapshot(VolumeInfo volume, Snapshot snapshot) {
long preId = _snapshotDao.getLastSnapshot(volume.getId(), snapshot.getId());
@@ -454,7 +440,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
if (preId != 0 && !(volume.getLastPoolId() != null && !volume.getLastPoolId().equals(volume.getPoolId()))) {
preSnapshotVO = _snapshotDao.findByIdIncludingRemoved(preId);
}
-
+
return preSnapshotVO;
}
@@ -475,7 +461,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
snapshotSchedule.setSnapshotId(snapshotId);
_snapshotScheduleDao.update(snapshotSchedule.getId(), snapshotSchedule);
}
-
+
if (snapshot != null && snapshot.isRecursive()) {
postCreateRecurringSnapshotForPolicy(userId, volumeId, snapshotId, policyId);
}
@@ -515,18 +501,11 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
if (snapshotCheck == null) {
throw new InvalidParameterValueException("unable to find a snapshot with id " + snapshotId);
}
-
+
_accountMgr.checkAccess(caller, null, true, snapshotCheck);
-
- SnapshotStrategy strategy = null;
- for (SnapshotStrategy st : snapshotStrategies) {
- if (st.canHandle(snapshotCheck)) {
- strategy = st;
- break;
- }
- }
+
try {
- boolean result = strategy.deleteSnapshot(snapshotCheck);
+ boolean result = this.snapshotSrv.deleteSnapshot(snapshotCheck);
if (result) {
if (snapshotCheck.getState() == Snapshot.State.BackedUp) {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_DELETE, snapshotCheck.getAccountId(),
@@ -573,7 +552,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
String snapshotTypeStr = cmd.getSnapshotType();
String intervalTypeStr = cmd.getIntervalType();
Map<String, String> tags = cmd.getTags();
-
+
Account caller = UserContext.current().getCaller();
List<Long> permittedAccounts = new ArrayList<Long>();
@@ -589,8 +568,8 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
_accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false);
Long domainId = domainIdRecursiveListProject.first();
Boolean isRecursive = domainIdRecursiveListProject.second();
- ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
-
+ ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
+
Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchBuilder<SnapshotVO> sb = _snapshotDao.createSearchBuilder();
_accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
@@ -601,7 +580,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("snapshotTypeEQ", sb.entity().getsnapshotType(), SearchCriteria.Op.IN);
sb.and("snapshotTypeNEQ", sb.entity().getsnapshotType(), SearchCriteria.Op.NEQ);
-
+
if (tags != null && !tags.isEmpty()) {
SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
for (int count=0; count < tags.size(); count++) {
@@ -620,7 +599,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
if (volumeId != null) {
sc.setParameters("volumeId", volumeId);
}
-
+
if (tags != null && !tags.isEmpty()) {
int count = 0;
sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.Snapshot.toString());
@@ -765,9 +744,9 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
if (volume == null) {
throw new InvalidParameterValueException("Failed to create snapshot policy, unable to find a volume with id " + volumeId);
}
-
+
_accountMgr.checkAccess(UserContext.current().getCaller(), null, true, volume);
-
+
if (volume.getState() != Volume.State.Ready) {
throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot.");
}
@@ -823,7 +802,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
if (owner.getType() == Account.ACCOUNT_TYPE_PROJECT) {
message = "domain/project";
}
-
+
throw new InvalidParameterValueException("Max number of snapshots shouldn't exceed the " + message + " level snapshot limit");
}
@@ -869,11 +848,11 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
return new Pair<List<? extends SnapshotPolicy>, Integer>(result.first(), result.second());
}
-
+
private List<SnapshotPolicyVO> listPoliciesforVolume(long volumeId) {
return _snapshotPolicyDao.listByVolumeId(volumeId);
}
-
+
private List<SnapshotVO> listSnapsforVolume(long volumeId) {
return _snapshotDao.listByVolumeId(volumeId);
}
@@ -961,7 +940,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
@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");
@@ -970,11 +949,11 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
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.");
}
@@ -985,7 +964,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
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");
@@ -1030,7 +1009,7 @@ 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
+ // user
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);
@@ -1050,7 +1029,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
-
+
String value = _configDao.getValue(Config.BackupSnapshotWait.toString());
_backupsnapshotwait = NumbersUtil.parseInt(value, Integer.parseInt(Config.BackupSnapshotWait.getDefaultValue()));
backup = Boolean.parseBoolean(this._configDao.getValue(Config.BackupSnapshotAferTakingSnapshot.toString()));
@@ -1124,7 +1103,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
return success;
}
-
+
@Override
public boolean canOperateOnVolume(Volume volume) {
List<SnapshotVO> snapshots = _snapshotDao.listByStatus(volume.getId(), Snapshot.State.Creating,
[2/2] git commit: updated refs/heads/object_store to 2968766
Posted by mc...@apache.org.
Rename SnapshotStrategy to SnapshotService to have consistent naming
convention for Template, Snapshot, Volume. Also rename CopyCmd to
CopyCommand to follow internal command naming convention.
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/29687663
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/29687663
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/29687663
Branch: refs/heads/object_store
Commit: 29687663e84c06067e8433b4598629aaedebceb4
Parents: 5f90aa9
Author: Min Chen <mi...@citrix.com>
Authored: Mon Apr 22 16:15:57 2013 -0700
Committer: Min Chen <mi...@citrix.com>
Committed: Mon Apr 22 16:15:57 2013 -0700
----------------------------------------------------------------------
.../cloud/storage/snapshot/SnapshotApiService.java | 109 +++
.../cloud/storage/snapshot/SnapshotService.java | 109 ---
api/src/org/apache/cloudstack/api/BaseCmd.java | 4 +-
.../resource/NfsSecondaryStorageResource.java | 12 +-
.../subsystem/api/storage/SnapshotService.java | 26 +
.../subsystem/api/storage/SnapshotStrategy.java | 27 -
.../apache/cloudstack/storage/command/CopyCmd.java | 62 --
.../cloudstack/storage/command/CopyCommand.java | 62 ++
.../storage/motion/AncientDataMotionStrategy.java | 6 +-
.../storage/test/DirectAgentManagerSimpleImpl.java | 13 -
.../storage/snapshot/SnapshotServiceImpl.java | 566 +++++++++++++-
.../snapshot/strategy/AncientSnapshotStrategy.java | 597 ---------------
.../cloudstack/storage/LocalHostEndpoint.java | 4 +-
.../xen/resource/XenServerStorageResource.java | 10 +-
.../storage/snapshot/SnapshotManagerImpl.java | 109 ++--
15 files changed, 809 insertions(+), 907 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/api/src/com/cloud/storage/snapshot/SnapshotApiService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/snapshot/SnapshotApiService.java b/api/src/com/cloud/storage/snapshot/SnapshotApiService.java
new file mode 100644
index 0000000..23e6522
--- /dev/null
+++ b/api/src/com/cloud/storage/snapshot/SnapshotApiService.java
@@ -0,0 +1,109 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.storage.snapshot;
+
+import java.util.List;
+
+import org.apache.cloudstack.api.command.user.snapshot.CreateSnapshotPolicyCmd;
+import org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotPoliciesCmd;
+import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotPoliciesCmd;
+import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd;
+
+import com.cloud.api.commands.ListRecurringSnapshotScheduleCmd;
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.Volume;
+import com.cloud.user.Account;
+import com.cloud.utils.Pair;
+
+public interface SnapshotApiService {
+
+ /**
+ * 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.)
+ * @return list of snapshots
+ * @throws PermissionDeniedException
+ */
+ Pair<List<? extends Snapshot>, Integer> 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.
+ *
+ * @param snapshotId
+ * TODO
+ */
+ boolean deleteSnapshot(long snapshotId);
+
+ /**
+ * 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
+ * @param policyOwner
+ * TODO
+ * @return the newly created snapshot policy if success, null otherwise
+ */
+ SnapshotPolicy createPolicy(CreateSnapshotPolicyCmd cmd, Account policyOwner);
+
+ /**
+ * 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
+ * @return list of snapshot policies
+ */
+ Pair<List<? extends SnapshotPolicy>, Integer> listPoliciesforVolume(ListSnapshotPoliciesCmd cmd);
+
+ boolean deleteSnapshotPolicies(DeleteSnapshotPoliciesCmd cmd);
+
+ Snapshot allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException;
+
+ /**
+ * Create a snapshot of a volume
+ *
+ * @param snapshotOwner
+ * TODO
+ * @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, Account snapshotOwner);
+
+ /**
+ * @param vol
+ * @return
+ */
+ Long getHostIdForSnapshotOperation(Volume vol);
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/api/src/com/cloud/storage/snapshot/SnapshotService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/snapshot/SnapshotService.java b/api/src/com/cloud/storage/snapshot/SnapshotService.java
deleted file mode 100644
index b5325f5..0000000
--- a/api/src/com/cloud/storage/snapshot/SnapshotService.java
+++ /dev/null
@@ -1,109 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.storage.snapshot;
-
-import java.util.List;
-
-import org.apache.cloudstack.api.command.user.snapshot.CreateSnapshotPolicyCmd;
-import org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotPoliciesCmd;
-import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotPoliciesCmd;
-import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd;
-
-import com.cloud.api.commands.ListRecurringSnapshotScheduleCmd;
-import com.cloud.exception.PermissionDeniedException;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.storage.Snapshot;
-import com.cloud.storage.Volume;
-import com.cloud.user.Account;
-import com.cloud.utils.Pair;
-
-public interface SnapshotService {
-
- /**
- * 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.)
- * @return list of snapshots
- * @throws PermissionDeniedException
- */
- Pair<List<? extends Snapshot>, Integer> 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.
- *
- * @param snapshotId
- * TODO
- */
- boolean deleteSnapshot(long snapshotId);
-
- /**
- * 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
- * @param policyOwner
- * TODO
- * @return the newly created snapshot policy if success, null otherwise
- */
- SnapshotPolicy createPolicy(CreateSnapshotPolicyCmd cmd, Account policyOwner);
-
- /**
- * 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
- * @return list of snapshot policies
- */
- Pair<List<? extends SnapshotPolicy>, Integer> listPoliciesforVolume(ListSnapshotPoliciesCmd cmd);
-
- boolean deleteSnapshotPolicies(DeleteSnapshotPoliciesCmd cmd);
-
- Snapshot allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException;
-
- /**
- * Create a snapshot of a volume
- *
- * @param snapshotOwner
- * TODO
- * @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, Account snapshotOwner);
-
- /**
- * @param vol
- * @return
- */
- Long getHostIdForSnapshotOperation(Volume vol);
-}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/api/src/org/apache/cloudstack/api/BaseCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java
index b845053..46a9dfc 100644
--- a/api/src/org/apache/cloudstack/api/BaseCmd.java
+++ b/api/src/org/apache/cloudstack/api/BaseCmd.java
@@ -64,7 +64,7 @@ import com.cloud.server.TaggedResourceService;
import com.cloud.storage.DataStoreProviderApiService;
import com.cloud.storage.StorageService;
import com.cloud.storage.VolumeApiService;
-import com.cloud.storage.snapshot.SnapshotService;
+import com.cloud.storage.snapshot.SnapshotApiService;
import com.cloud.template.TemplateApiService;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
@@ -108,7 +108,7 @@ public abstract class BaseCmd {
@Inject public NetworkService _networkService;
@Inject public TemplateApiService _templateService;
@Inject public SecurityGroupService _securityGroupService;
- @Inject public SnapshotService _snapshotService;
+ @Inject public SnapshotApiService _snapshotService;
@Inject public ConsoleProxyService _consoleProxyService;
@Inject public VpcVirtualNetworkApplianceService _routerService;
@Inject public ResponseGenerator _responseGenerator;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
index e8abcbf..3be9ced 100755
--- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
+++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
@@ -48,7 +48,7 @@ import java.util.concurrent.Callable;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
-import org.apache.cloudstack.storage.command.CopyCmd;
+import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
@@ -215,14 +215,14 @@ SecondaryStorageResource {
return execute((DeleteTemplateFromS3Command) cmd);
} else if (cmd instanceof CleanupSnapshotBackupCommand){
return execute((CleanupSnapshotBackupCommand)cmd);
- } else if (cmd instanceof CopyCmd) {
- return execute((CopyCmd)cmd);
+ } else if (cmd instanceof CopyCommand) {
+ return execute((CopyCommand)cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
- protected Answer downloadFromS3ToNfs(CopyCmd cmd, DataTO srcData, S3TO s3,
+ protected Answer downloadFromS3ToNfs(CopyCommand cmd, DataTO srcData, S3TO s3,
DataTO destData, NfsTO destImageStore) {
final String storagePath = destImageStore.getUrl();
final String destPath = destData.getPath();
@@ -265,12 +265,12 @@ SecondaryStorageResource {
}
}
- protected Answer downloadFromSwiftToNfs(CopyCmd cmd, DataTO srcData, SwiftTO srcImageStore,
+ protected Answer downloadFromSwiftToNfs(CopyCommand cmd, DataTO srcData, SwiftTO srcImageStore,
DataTO destData, NfsTO destImageStore) {
return Answer.createUnsupportedCommandAnswer(cmd);
}
- protected Answer execute(CopyCmd cmd) {
+ protected Answer execute(CopyCommand cmd) {
DataTO srcData = cmd.getSrcTO();
DataTO destData = cmd.getDestTO();
DataStoreTO srcDataStore = srcData.getDataStore();
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java
new file mode 100644
index 0000000..68dc55f
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.engine.subsystem.api.storage;
+
+
+public interface SnapshotService {
+ public SnapshotInfo takeSnapshot(VolumeInfo volume, Long snapshotId);
+ public SnapshotInfo backupSnapshot(SnapshotInfo snapshot);
+ public boolean deleteSnapshot(SnapshotInfo snapshot);
+ public boolean revertSnapshot(SnapshotInfo snapshot);
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java
deleted file mode 100644
index e9492c4..0000000
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.cloudstack.engine.subsystem.api.storage;
-
-
-public interface SnapshotStrategy {
- public boolean canHandle(SnapshotInfo snapshot);
- public SnapshotInfo takeSnapshot(VolumeInfo volume, Long snapshotId);
- public SnapshotInfo backupSnapshot(SnapshotInfo snapshot);
- public boolean deleteSnapshot(SnapshotInfo snapshot);
- public boolean revertSnapshot(SnapshotInfo snapshot);
-}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/engine/api/src/org/apache/cloudstack/storage/command/CopyCmd.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/command/CopyCmd.java b/engine/api/src/org/apache/cloudstack/storage/command/CopyCmd.java
deleted file mode 100644
index 9cb225b..0000000
--- a/engine/api/src/org/apache/cloudstack/storage/command/CopyCmd.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package org.apache.cloudstack.storage.command;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
-
-import com.cloud.agent.api.Command;
-
-public class CopyCmd extends Command implements StorageSubSystemCommand {
- private DataTO srcTO;
- private DataTO destTO;
- private int timeout;
-
- /**
- * @return the timeout
- */
- public int getTimeout() {
- return timeout;
- }
-
- /**
- * @param timeout the timeout to set
- */
- public void setTimeout(int timeout) {
- this.timeout = timeout;
- }
-
- public CopyCmd(DataTO srcUri, DataTO destUri, int timeout) {
- super();
- this.srcTO = srcUri;
- this.destTO = destUri;
- this.timeout = timeout;
- }
-
- public DataTO getDestTO() {
- return this.destTO;
- }
-
- public DataTO getSrcTO() {
- return this.srcTO;
- }
-
- @Override
- public boolean executeInSequence() {
- return true;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java b/engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java
new file mode 100644
index 0000000..fb28034
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java
@@ -0,0 +1,62 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.storage.command;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
+
+import com.cloud.agent.api.Command;
+
+public class CopyCommand extends Command implements StorageSubSystemCommand {
+ private DataTO srcTO;
+ private DataTO destTO;
+ private int timeout;
+
+ /**
+ * @return the timeout
+ */
+ public int getTimeout() {
+ return timeout;
+ }
+
+ /**
+ * @param timeout the timeout to set
+ */
+ public void setTimeout(int timeout) {
+ this.timeout = timeout;
+ }
+
+ public CopyCommand(DataTO srcUri, DataTO destUri, int timeout) {
+ super();
+ this.srcTO = srcUri;
+ this.destTO = destUri;
+ this.timeout = timeout;
+ }
+
+ public DataTO getDestTO() {
+ return this.destTO;
+ }
+
+ public DataTO getSrcTO() {
+ return this.srcTO;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index e72bb54..8274fd7 100644
--- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -35,7 +35,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
-import org.apache.cloudstack.storage.command.CopyCmd;
+import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.log4j.Logger;
@@ -194,13 +194,13 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
if (srcData.getDataStore().getRole() != DataStoreRole.ImageCache && destData.getDataStore().getRole() != DataStoreRole.ImageCache) {
//need to copy it to image cache store
DataObject cacheData = cacheMgr.createCacheObject(srcData, destData.getDataStore().getScope());
- CopyCmd cmd = new CopyCmd(cacheData.getTO(), destData.getTO(), _primaryStorageDownloadWait);
+ CopyCommand cmd = new CopyCommand(cacheData.getTO(), destData.getTO(), _primaryStorageDownloadWait);
EndPoint ep = selector.select(cacheData, destData);
Answer answer = ep.sendMessage(cmd);
return answer;
} else {
//handle copy it to cache store
- CopyCmd cmd = new CopyCmd(srcData.getTO(), destData.getTO(), _primaryStorageDownloadWait);
+ CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _primaryStorageDownloadWait);
EndPoint ep = selector.select(srcData, destData);
Answer answer = ep.sendMessage(cmd);
return answer;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java
index 0725971..c5b5883 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java
@@ -187,19 +187,6 @@ public class DirectAgentManagerSimpleImpl extends ManagerBase implements AgentMa
return null;
}
-
- @Override
- public void sendToSecStorage(DataStore ssStore, Command cmd, Listener listener) throws AgentUnavailableException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public Answer sendToSecStorage(DataStore ssStore, Command cmd) {
- // TODO Auto-generated method stub
- return null;
- }
-
@Override
public boolean tapLoadingAgents(Long hostId, TapAgentsAction action) {
// TODO Auto-generated method stub
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
index 1b64fd0..7eee772 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
@@ -14,43 +14,577 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
+
package org.apache.cloudstack.storage.snapshot;
-import org.apache.cloudstack.engine.cloud.entity.api.SnapshotEntity;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
+import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
+import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
+import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
+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.VolumeInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
+import org.apache.cloudstack.framework.async.AsyncCallFuture;
+import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
+import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+import org.apache.cloudstack.framework.async.AsyncRpcConext;
+import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
+import com.cloud.agent.api.BackupSnapshotAnswer;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.host.HostVO;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.resource.ResourceManager;
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.VolumeManager;
+import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.storage.snapshot.SnapshotManager;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.fsm.NoTransitionException;
+import com.cloud.vm.UserVmVO;
+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
public class SnapshotServiceImpl implements SnapshotService {
-
- public SnapshotServiceImpl() {
-
+ private static final Logger s_logger = Logger.getLogger(SnapshotServiceImpl.class);
+ @Inject
+ protected VolumeDao _volsDao;
+ @Inject
+ protected UserVmDao _vmDao;
+ @Inject
+ protected PrimaryDataStoreDao _storagePoolDao;
+ @Inject
+ protected ClusterDao _clusterDao;
+ @Inject
+ protected SnapshotDao _snapshotDao;
+ @Inject
+ private ResourceManager _resourceMgr;
+ @Inject
+ protected SnapshotManager snapshotMgr;
+ @Inject
+ protected VolumeManager volumeMgr;
+ @Inject
+ private ConfigurationDao _configDao;
+ @Inject
+ protected SnapshotStateMachineManager stateMachineManager;
+ @Inject
+ private VolumeDao volumeDao;
+ @Inject
+ SnapshotDataFactory snapshotfactory;
+ @Inject
+ DataStoreManager dataStoreMgr;
+ @Inject
+ DataMotionService motionSrv;
+ @Inject
+ ObjectInDataStoreManager objInStoreMgr;
+ @Inject
+ VMSnapshotDao _vmSnapshotDao;
+
+
+
+
+ static private class CreateSnapshotContext<T> extends AsyncRpcConext<T> {
+ final VolumeInfo volume;
+ final SnapshotInfo snapshot;
+ final AsyncCallFuture<SnapshotResult> future;
+ public CreateSnapshotContext(AsyncCompletionCallback<T> callback, VolumeInfo volume,
+ SnapshotInfo snapshot,
+ AsyncCallFuture<SnapshotResult> future) {
+ super(callback);
+ this.volume = volume;
+ this.snapshot = snapshot;
+ this.future = future;
+ }
}
- @Override
- public SnapshotEntity getSnapshotEntity(long snapshotId) {
- // TODO Auto-generated method stub
+ static private class DeleteSnapshotContext<T> extends AsyncRpcConext<T> {
+ final SnapshotInfo snapshot;
+ final AsyncCallFuture<SnapshotResult> future;
+ public DeleteSnapshotContext(AsyncCompletionCallback<T> callback, SnapshotInfo snapshot,
+ AsyncCallFuture<SnapshotResult> future) {
+ super(callback);
+ this.snapshot = snapshot;
+ this.future = future;
+ }
+
+ }
+
+ static private class CopySnapshotContext<T> extends AsyncRpcConext<T> {
+ final SnapshotInfo srcSnapshot;
+ final SnapshotInfo destSnapshot;
+ final AsyncCallFuture<SnapshotResult> future;
+ public CopySnapshotContext(AsyncCompletionCallback<T> callback,
+ SnapshotInfo srcSnapshot,
+ SnapshotInfo destSnapshot,
+ AsyncCallFuture<SnapshotResult> future) {
+ super(callback);
+ this.srcSnapshot = srcSnapshot;
+ this.destSnapshot = destSnapshot;
+ this.future = future;
+ }
+
+ }
+
+ protected Void createSnapshotAsyncCallback(AsyncCallbackDispatcher<SnapshotServiceImpl, CreateCmdResult> callback,
+ CreateSnapshotContext<CreateCmdResult> context) {
+ CreateCmdResult result = callback.getResult();
+ SnapshotObject snapshot = (SnapshotObject)context.snapshot;
+ VolumeInfo volume = context.volume;
+ AsyncCallFuture<SnapshotResult> future = context.future;
+ SnapshotResult snapResult = new SnapshotResult(snapshot);
+ if (result.isFailed()) {
+ s_logger.debug("create snapshot " + context.snapshot.getName() + " failed: " + result.getResult());
+ try {
+ snapshot.processEvent(Snapshot.Event.OperationFailed);
+ } catch (NoTransitionException nte) {
+ s_logger.debug("Failed to update snapshot state due to " + nte.getMessage());
+ }
+
+
+ snapResult.setResult(result.getResult());
+ future.complete(snapResult);
+ return null;
+ }
+
+ try {
+ SnapshotVO preSnapshotVO = this.snapshotMgr.getParentSnapshot(volume, snapshot);
+ String preSnapshotPath = null;
+ if (preSnapshotVO != null) {
+ preSnapshotPath = preSnapshotVO.getPath();
+ }
+ SnapshotVO snapshotVO = this._snapshotDao.findById(snapshot.getId());
+ // The snapshot was successfully created
+ if (preSnapshotPath != null && preSnapshotPath.equals(result.getPath())) {
+ // empty snapshot
+ s_logger.debug("CreateSnapshot: this is empty snapshot ");
+
+ snapshotVO.setPath(preSnapshotPath);
+ snapshotVO.setBackupSnapshotId(preSnapshotVO.getBackupSnapshotId());
+ snapshotVO.setSwiftId(preSnapshotVO.getSwiftId());
+ snapshotVO.setPrevSnapshotId(preSnapshotVO.getId());
+ snapshotVO.setSecHostId(preSnapshotVO.getSecHostId());
+ snapshot.processEvent(Snapshot.Event.OperationNotPerformed);
+ } else {
+ long preSnapshotId = 0;
+
+ if (preSnapshotVO != null && preSnapshotVO.getBackupSnapshotId() != null) {
+ preSnapshotId = preSnapshotVO.getId();
+ int _deltaSnapshotMax = NumbersUtil.parseInt(_configDao.getValue("snapshot.delta.max"), SnapshotManager.DELTAMAX);
+ int deltaSnap = _deltaSnapshotMax;
+
+ int i;
+ for (i = 1; i < deltaSnap; i++) {
+ String prevBackupUuid = preSnapshotVO.getBackupSnapshotId();
+ // previous snapshot doesn't have backup, create a full snapshot
+ if (prevBackupUuid == null) {
+ preSnapshotId = 0;
+ break;
+ }
+ long preSSId = preSnapshotVO.getPrevSnapshotId();
+ if (preSSId == 0) {
+ break;
+ }
+ preSnapshotVO = _snapshotDao.findByIdIncludingRemoved(preSSId);
+ }
+ if (i >= deltaSnap) {
+ preSnapshotId = 0;
+ }
+ }
+
+ //If the volume is moved around, backup a full snapshot to secondary storage
+ if (volume.getLastPoolId() != null && !volume.getLastPoolId().equals(volume.getPoolId())) {
+ preSnapshotId = 0;
+ //TODO: fix this hack
+ VolumeVO volumeVO = this.volumeDao.findById(volume.getId());
+ volumeVO.setLastPoolId(volume.getPoolId());
+ this.volumeDao.update(volume.getId(), volumeVO);
+ }
+
+ snapshot.setPath(result.getPath());
+ snapshot.setPrevSnapshotId(preSnapshotId);
+
+ snapshot.processEvent(Snapshot.Event.OperationSucceeded);
+ snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(snapshot.getId()));
+ }
+ } catch (Exception e) {
+ s_logger.debug("Failed to create snapshot: ", e);
+ snapResult.setResult(e.toString());
+ try {
+ snapshot.processEvent(Snapshot.Event.OperationFailed);
+ } catch (NoTransitionException e1) {
+ s_logger.debug("Failed to change snapshot state: " + e1.toString());
+ }
+ }
+
+ future.complete(snapResult);
return null;
}
- @Override
- public boolean takeSnapshot(SnapshotInfo snapshot) {
- // TODO Auto-generated method stub
+ class SnapshotResult extends CommandResult {
+ SnapshotInfo snashot;
+ public SnapshotResult(SnapshotInfo snapshot) {
+ this.snashot = snapshot;
+ }
+ }
+
+ protected SnapshotInfo createSnapshotOnPrimary(VolumeInfo volume, Long snapshotId) {
+ SnapshotObject snapshot = (SnapshotObject)this.snapshotfactory.getSnapshot(snapshotId);
+ if (snapshot == null) {
+ throw new CloudRuntimeException("Can not find snapshot " + snapshotId);
+ }
+
+ try {
+ snapshot.processEvent(Snapshot.Event.CreateRequested);
+ } catch (NoTransitionException nte) {
+ s_logger.debug("Failed to update snapshot state due to " + nte.getMessage());
+ throw new CloudRuntimeException("Failed to update snapshot state due to " + nte.getMessage());
+ }
+
+ AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
+ try {
+ CreateSnapshotContext<CommandResult> context = new CreateSnapshotContext<CommandResult>(
+ null, volume, snapshot, future);
+ AsyncCallbackDispatcher<SnapshotServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher
+ .create(this);
+ caller.setCallback(
+ caller.getTarget().createSnapshotAsyncCallback(null, null))
+ .setContext(context);
+ PrimaryDataStoreDriver primaryStore = (PrimaryDataStoreDriver)volume.getDataStore().getDriver();
+ primaryStore.takeSnapshot(snapshot, caller);
+ } catch (Exception e) {
+ s_logger.debug("Failed to take snapshot: " + snapshot.getId(), e);
+ try {
+ snapshot.processEvent(Snapshot.Event.OperationFailed);
+ } catch (NoTransitionException e1) {
+ s_logger.debug("Failed to change state for event: OperationFailed" , e);
+ }
+ throw new CloudRuntimeException("Failed to take snapshot" + snapshot.getId());
+ }
+
+ SnapshotResult result;
+
+ try {
+ result = future.get();
+ if (result.isFailed()) {
+ s_logger.debug("Failed to create snapshot:" + result.getResult());
+ throw new CloudRuntimeException(result.getResult());
+ }
+ return result.snashot;
+ } catch (InterruptedException e) {
+ s_logger.debug("Failed to create snapshot", e);
+ throw new CloudRuntimeException("Failed to create snapshot", e);
+ } catch (ExecutionException e) {
+ s_logger.debug("Failed to create snapshot", e);
+ throw new CloudRuntimeException("Failed to create snapshot", e);
+ }
+
+ }
+
+ 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;
}
+ protected boolean supportedByHypervisor(VolumeInfo volume) {
+ if (volume.getHypervisorType().equals(HypervisorType.KVM)) {
+ StoragePool storagePool = (StoragePool)volume.getDataStore();
+ ClusterVO cluster = _clusterDao.findById(storagePool.getClusterId());
+ 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 boolean revertSnapshot(SnapshotInfo snapshot) {
- // TODO Auto-generated method stub
- return false;
+ public SnapshotInfo takeSnapshot(VolumeInfo volume, Long snapshotId) {
+
+ supportedByHypervisor(volume);
+
+ SnapshotInfo snapshot = createSnapshotOnPrimary(volume, snapshotId);
+ return snapshot;
}
@Override
- public boolean deleteSnapshot(SnapshotInfo snapshot) {
+ public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) {
+ SnapshotObject snapObj = (SnapshotObject)snapshot;
+ AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
+ SnapshotResult result = new SnapshotResult(snapshot);
+ try {
+
+ snapObj.processEvent(Snapshot.Event.BackupToSecondary);
+
+ ZoneScope scope = new ZoneScope(snapshot.getDataCenterId());
+ List<DataStore> stores = this.dataStoreMgr.getImageStoresByScope(scope);
+ if (stores.size() != 1) {
+ throw new CloudRuntimeException("find out more than one image stores");
+ }
+
+ DataStore imageStore = stores.get(0);
+ SnapshotInfo snapshotOnImageStore = (SnapshotInfo)imageStore.create(snapshot);
+
+ snapshotOnImageStore.processEvent(Event.CreateOnlyRequested);
+ CopySnapshotContext<CommandResult> context = new CopySnapshotContext<CommandResult>(null, snapshot,
+ snapshotOnImageStore, future);
+ AsyncCallbackDispatcher<SnapshotServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher
+ .create(this);
+ caller.setCallback(
+ caller.getTarget().copySnapshotAsyncCallback(null, null))
+ .setContext(context);
+ this.motionSrv.copyAsync(snapshot, snapshotOnImageStore, caller);
+ } catch (Exception e) {
+ s_logger.debug("Failed to copy snapshot", e);
+ result.setResult("Failed to copy snapshot:" +e.toString());
+ try {
+ snapObj.processEvent(Snapshot.Event.OperationFailed);
+ } catch (NoTransitionException e1) {
+ s_logger.debug("Failed to change state: " + e1.toString());
+ }
+ future.complete(result);
+ }
+
+ try {
+ SnapshotResult res = future.get();
+ SnapshotInfo destSnapshot = res.snashot;
+ return destSnapshot;
+ } catch (InterruptedException e) {
+ s_logger.debug("failed copy snapshot", e);
+ throw new CloudRuntimeException("Failed to copy snapshot" , e);
+ } catch (ExecutionException e) {
+ s_logger.debug("Failed to copy snapshot", e);
+ throw new CloudRuntimeException("Failed to copy snapshot" , e);
+ }
+
+ }
+
+ protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher<SnapshotServiceImpl, CopyCommandResult> callback,
+ CopySnapshotContext<CommandResult> context) {
+ CopyCommandResult result = callback.getResult();
+ SnapshotInfo destSnapshot = context.destSnapshot;
+ SnapshotObject srcSnapshot = (SnapshotObject)context.srcSnapshot;
+ AsyncCallFuture<SnapshotResult> future = context.future;
+ SnapshotResult snapResult = new SnapshotResult(destSnapshot);
+ if (result.isFailed()) {
+ snapResult.setResult(result.getResult());
+ future.complete(snapResult);
+ return null;
+ }
+
+ try {
+ BackupSnapshotAnswer answer = (BackupSnapshotAnswer)result.getAnswer();
+
+ DataObjectInStore dataInStore = objInStoreMgr.findObject(destSnapshot, destSnapshot.getDataStore());
+ dataInStore.setInstallPath(answer.getBackupSnapshotName());
+ objInStoreMgr.update(destSnapshot, Event.OperationSuccessed);
+
+ srcSnapshot.processEvent(Snapshot.Event.OperationSucceeded);
+ snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(destSnapshot.getId()));
+ future.complete(snapResult);
+ } catch (Exception e) {
+ s_logger.debug("Failed to update snapshot state", e);
+ snapResult.setResult(e.toString());
+ future.complete(snapResult);
+ }
+ return null;
+ }
+
+ @DB
+ protected boolean destroySnapshotBackUp(SnapshotVO snapshot) {
+ DataStore store = objInStoreMgr.findStore(snapshot.getId(), DataObjectType.SNAPSHOT, DataStoreRole.Image);
+ if (store == null) {
+ s_logger.debug("Can't find snapshot" + snapshot.getId() + " backed up into image store");
+ return false;
+ }
+
+ try {
+ SnapshotInfo snapshotInfo = this.snapshotfactory.getSnapshot(snapshot.getId(), store);
+ snapshotInfo.processEvent(ObjectInDataStoreStateMachine.Event.DestroyRequested);
+
+ AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
+ DeleteSnapshotContext<CommandResult> context = new DeleteSnapshotContext<CommandResult>(null,
+ snapshotInfo, future);
+ AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> caller = AsyncCallbackDispatcher
+ .create(this);
+ caller.setCallback(
+ caller.getTarget().deleteSnapshotCallback(null, null))
+ .setContext(context);
+
+ store.getDriver().deleteAsync(snapshotInfo, caller);
+
+ SnapshotResult result = future.get();
+ if (result.isFailed()) {
+ s_logger.debug("Failed to delete snapsoht: " + result.getResult());
+ }
+ return result.isSuccess();
+ } catch (Exception e) {
+ s_logger.debug("Failed to delete snapshot", e);
+ return false;
+ }
+ }
+
+ protected Void deleteSnapshotCallback(AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> callback,
+ DeleteSnapshotContext<CommandResult> context) {
+ CommandResult result = callback.getResult();
+ AsyncCallFuture<SnapshotResult> future = context.future;
+ SnapshotInfo snapshot = context.snapshot;
+ if (result.isFailed()) {
+ s_logger.debug("delete snapshot failed" + result.getResult());
+ snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
+ SnapshotResult res = new SnapshotResult(context.snapshot);
+ future.complete(res);
+ return null;
+ }
+ snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed);
+ SnapshotResult res = new SnapshotResult(context.snapshot);
+ future.complete(res);
+ return null;
+ }
+
+ @Override
+ public boolean deleteSnapshot(SnapshotInfo snapInfo) {
+ Long snapshotId = snapInfo.getId();
+ SnapshotObject snapshot = (SnapshotObject)snapInfo;
+
+ if (!Snapshot.State.BackedUp.equals(snapshot.getState())) {
+ throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId + " due to it is not in BackedUp Status");
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Calling deleteSnapshot for snapshotId: " + snapshotId);
+ }
+ SnapshotVO lastSnapshot = null;
+ if (snapshot.getBackupSnapshotId() != null) {
+ List<SnapshotVO> snaps = _snapshotDao.listByBackupUuid(snapshot.getVolumeId(), snapshot.getBackupSnapshotId());
+ if (snaps != null && snaps.size() > 1) {
+ snapshot.setBackupSnapshotId(null);
+ SnapshotVO snapshotVO = this._snapshotDao.findById(snapshotId);
+ _snapshotDao.update(snapshot.getId(), snapshotVO);
+ }
+ }
+
+ _snapshotDao.remove(snapshotId);
+
+ long lastId = snapshotId;
+ boolean destroy = false;
+ while (true) {
+ lastSnapshot = _snapshotDao.findNextSnapshot(lastId);
+ if (lastSnapshot == null) {
+ // if all snapshots after this snapshot in this chain are removed, remove those snapshots.
+ destroy = true;
+ break;
+ }
+ if (lastSnapshot.getRemoved() == null) {
+ // if there is one child not removed, then can not remove back up snapshot.
+ break;
+ }
+ lastId = lastSnapshot.getId();
+ }
+ if (destroy) {
+ lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId);
+ while (lastSnapshot.getRemoved() != null) {
+ String BackupSnapshotId = lastSnapshot.getBackupSnapshotId();
+ if (BackupSnapshotId != null) {
+ List<SnapshotVO> snaps = _snapshotDao.listByBackupUuid(lastSnapshot.getVolumeId(), BackupSnapshotId);
+ if (snaps != null && snaps.size() > 1) {
+ lastSnapshot.setBackupSnapshotId(null);
+ _snapshotDao.update(lastSnapshot.getId(), lastSnapshot);
+ } else {
+ if (destroySnapshotBackUp(lastSnapshot)) {
+
+ } else {
+ s_logger.debug("Destroying snapshot backup failed " + lastSnapshot);
+ break;
+ }
+ }
+ }
+ lastId = lastSnapshot.getPrevSnapshotId();
+ if (lastId == 0) {
+ break;
+ }
+ lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId);
+ }
+ }
+ return true;
+
+ }
+
+ @Override
+ public boolean revertSnapshot(SnapshotInfo snapshot) {
// TODO Auto-generated method stub
return false;
}
-
-
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnapshotStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnapshotStrategy.java
deleted file mode 100644
index 944c477..0000000
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnapshotStrategy.java
+++ /dev/null
@@ -1,597 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.cloudstack.storage.snapshot.strategy;
-
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
-import javax.inject.Inject;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
-import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
-import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
-import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
-import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
-import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
-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.SnapshotStrategy;
-import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
-import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
-import org.apache.cloudstack.framework.async.AsyncCallFuture;
-import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
-import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
-import org.apache.cloudstack.framework.async.AsyncRpcConext;
-import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
-import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
-import org.apache.cloudstack.storage.snapshot.SnapshotObject;
-import org.apache.cloudstack.storage.snapshot.SnapshotStateMachineManager;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import com.cloud.agent.api.BackupSnapshotAnswer;
-import com.cloud.configuration.dao.ConfigurationDao;
-import com.cloud.dc.ClusterVO;
-import com.cloud.dc.dao.ClusterDao;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.host.HostVO;
-import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.resource.ResourceManager;
-import com.cloud.storage.DataStoreRole;
-import com.cloud.storage.Snapshot;
-import com.cloud.storage.SnapshotVO;
-import com.cloud.storage.StoragePool;
-import com.cloud.storage.VolumeManager;
-import com.cloud.storage.VolumeVO;
-import com.cloud.storage.dao.SnapshotDao;
-import com.cloud.storage.dao.VolumeDao;
-import com.cloud.storage.snapshot.SnapshotManager;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.utils.fsm.NoTransitionException;
-import com.cloud.vm.UserVmVO;
-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
-public class AncientSnapshotStrategy implements SnapshotStrategy {
- private static final Logger s_logger = Logger.getLogger(AncientSnapshotStrategy.class);
- @Inject
- protected VolumeDao _volsDao;
- @Inject
- protected UserVmDao _vmDao;
- @Inject
- protected PrimaryDataStoreDao _storagePoolDao;
- @Inject
- protected ClusterDao _clusterDao;
- @Inject
- protected SnapshotDao snapshotDao;
- @Inject
- private ResourceManager _resourceMgr;
- @Inject
- protected SnapshotDao _snapshotDao;
- @Inject
- protected SnapshotManager snapshotMgr;
- @Inject
- protected VolumeManager volumeMgr;
- @Inject
- private ConfigurationDao _configDao;
- @Inject
- protected SnapshotStateMachineManager stateMachineManager;
- @Inject
- private VolumeDao volumeDao;
- @Inject
- SnapshotDataFactory snapshotfactory;
- @Inject
- DataStoreManager dataStoreMgr;
- @Inject
- DataMotionService motionSrv;
- @Inject
- ObjectInDataStoreManager objInStoreMgr;
- @Inject
- VMSnapshotDao _vmSnapshotDao;
-
-
- @Override
- public boolean canHandle(SnapshotInfo snapshot) {
- return true;
- }
-
- static private class CreateSnapshotContext<T> extends AsyncRpcConext<T> {
- final VolumeInfo volume;
- final SnapshotInfo snapshot;
- final AsyncCallFuture<SnapshotResult> future;
- public CreateSnapshotContext(AsyncCompletionCallback<T> callback, VolumeInfo volume,
- SnapshotInfo snapshot,
- AsyncCallFuture<SnapshotResult> future) {
- super(callback);
- this.volume = volume;
- this.snapshot = snapshot;
- this.future = future;
- }
- }
-
- static private class DeleteSnapshotContext<T> extends AsyncRpcConext<T> {
- final SnapshotInfo snapshot;
- final AsyncCallFuture<SnapshotResult> future;
- public DeleteSnapshotContext(AsyncCompletionCallback<T> callback, SnapshotInfo snapshot,
- AsyncCallFuture<SnapshotResult> future) {
- super(callback);
- this.snapshot = snapshot;
- this.future = future;
- }
-
- }
-
- static private class CopySnapshotContext<T> extends AsyncRpcConext<T> {
- final SnapshotInfo srcSnapshot;
- final SnapshotInfo destSnapshot;
- final AsyncCallFuture<SnapshotResult> future;
- public CopySnapshotContext(AsyncCompletionCallback<T> callback,
- SnapshotInfo srcSnapshot,
- SnapshotInfo destSnapshot,
- AsyncCallFuture<SnapshotResult> future) {
- super(callback);
- this.srcSnapshot = srcSnapshot;
- this.destSnapshot = destSnapshot;
- this.future = future;
- }
-
- }
-
- protected Void createSnapshotAsyncCallback(AsyncCallbackDispatcher<AncientSnapshotStrategy, CreateCmdResult> callback,
- CreateSnapshotContext<CreateCmdResult> context) {
- CreateCmdResult result = callback.getResult();
- SnapshotObject snapshot = (SnapshotObject)context.snapshot;
- VolumeInfo volume = context.volume;
- AsyncCallFuture<SnapshotResult> future = context.future;
- SnapshotResult snapResult = new SnapshotResult(snapshot);
- if (result.isFailed()) {
- s_logger.debug("create snapshot " + context.snapshot.getName() + " failed: " + result.getResult());
- try {
- snapshot.processEvent(Snapshot.Event.OperationFailed);
- } catch (NoTransitionException nte) {
- s_logger.debug("Failed to update snapshot state due to " + nte.getMessage());
- }
-
-
- snapResult.setResult(result.getResult());
- future.complete(snapResult);
- return null;
- }
-
- try {
- SnapshotVO preSnapshotVO = this.snapshotMgr.getParentSnapshot(volume, snapshot);
- String preSnapshotPath = null;
- if (preSnapshotVO != null) {
- preSnapshotPath = preSnapshotVO.getPath();
- }
- SnapshotVO snapshotVO = this.snapshotDao.findById(snapshot.getId());
- // The snapshot was successfully created
- if (preSnapshotPath != null && preSnapshotPath.equals(result.getPath())) {
- // empty snapshot
- s_logger.debug("CreateSnapshot: this is empty snapshot ");
-
- snapshotVO.setPath(preSnapshotPath);
- snapshotVO.setBackupSnapshotId(preSnapshotVO.getBackupSnapshotId());
- snapshotVO.setSwiftId(preSnapshotVO.getSwiftId());
- snapshotVO.setPrevSnapshotId(preSnapshotVO.getId());
- snapshotVO.setSecHostId(preSnapshotVO.getSecHostId());
- snapshot.processEvent(Snapshot.Event.OperationNotPerformed);
- } else {
- long preSnapshotId = 0;
-
- if (preSnapshotVO != null && preSnapshotVO.getBackupSnapshotId() != null) {
- preSnapshotId = preSnapshotVO.getId();
- int _deltaSnapshotMax = NumbersUtil.parseInt(_configDao.getValue("snapshot.delta.max"), SnapshotManager.DELTAMAX);
- int deltaSnap = _deltaSnapshotMax;
-
- int i;
- for (i = 1; i < deltaSnap; i++) {
- String prevBackupUuid = preSnapshotVO.getBackupSnapshotId();
- // previous snapshot doesn't have backup, create a full snapshot
- if (prevBackupUuid == null) {
- preSnapshotId = 0;
- break;
- }
- long preSSId = preSnapshotVO.getPrevSnapshotId();
- if (preSSId == 0) {
- break;
- }
- preSnapshotVO = _snapshotDao.findByIdIncludingRemoved(preSSId);
- }
- if (i >= deltaSnap) {
- preSnapshotId = 0;
- }
- }
-
- //If the volume is moved around, backup a full snapshot to secondary storage
- if (volume.getLastPoolId() != null && !volume.getLastPoolId().equals(volume.getPoolId())) {
- preSnapshotId = 0;
- //TODO: fix this hack
- VolumeVO volumeVO = this.volumeDao.findById(volume.getId());
- volumeVO.setLastPoolId(volume.getPoolId());
- this.volumeDao.update(volume.getId(), volumeVO);
- }
-
- snapshot.setPath(result.getPath());
- snapshot.setPrevSnapshotId(preSnapshotId);
-
- snapshot.processEvent(Snapshot.Event.OperationSucceeded);
- snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(snapshot.getId()));
- }
- } catch (Exception e) {
- s_logger.debug("Failed to create snapshot: ", e);
- snapResult.setResult(e.toString());
- try {
- snapshot.processEvent(Snapshot.Event.OperationFailed);
- } catch (NoTransitionException e1) {
- s_logger.debug("Failed to change snapshot state: " + e1.toString());
- }
- }
-
- future.complete(snapResult);
- return null;
- }
-
- class SnapshotResult extends CommandResult {
- SnapshotInfo snashot;
- public SnapshotResult(SnapshotInfo snapshot) {
- this.snashot = snapshot;
- }
- }
-
- protected SnapshotInfo createSnapshotOnPrimary(VolumeInfo volume, Long snapshotId) {
- SnapshotObject snapshot = (SnapshotObject)this.snapshotfactory.getSnapshot(snapshotId);
- if (snapshot == null) {
- throw new CloudRuntimeException("Can not find snapshot " + snapshotId);
- }
-
- try {
- snapshot.processEvent(Snapshot.Event.CreateRequested);
- } catch (NoTransitionException nte) {
- s_logger.debug("Failed to update snapshot state due to " + nte.getMessage());
- throw new CloudRuntimeException("Failed to update snapshot state due to " + nte.getMessage());
- }
-
- AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
- try {
- CreateSnapshotContext<CommandResult> context = new CreateSnapshotContext<CommandResult>(
- null, volume, snapshot, future);
- AsyncCallbackDispatcher<AncientSnapshotStrategy, CreateCmdResult> caller = AsyncCallbackDispatcher
- .create(this);
- caller.setCallback(
- caller.getTarget().createSnapshotAsyncCallback(null, null))
- .setContext(context);
- PrimaryDataStoreDriver primaryStore = (PrimaryDataStoreDriver)volume.getDataStore().getDriver();
- primaryStore.takeSnapshot(snapshot, caller);
- } catch (Exception e) {
- s_logger.debug("Failed to take snapshot: " + snapshot.getId(), e);
- try {
- snapshot.processEvent(Snapshot.Event.OperationFailed);
- } catch (NoTransitionException e1) {
- s_logger.debug("Failed to change state for event: OperationFailed" , e);
- }
- throw new CloudRuntimeException("Failed to take snapshot" + snapshot.getId());
- }
-
- SnapshotResult result;
-
- try {
- result = future.get();
- if (result.isFailed()) {
- s_logger.debug("Failed to create snapshot:" + result.getResult());
- throw new CloudRuntimeException(result.getResult());
- }
- return result.snashot;
- } catch (InterruptedException e) {
- s_logger.debug("Failed to create snapshot", e);
- throw new CloudRuntimeException("Failed to create snapshot", e);
- } catch (ExecutionException e) {
- s_logger.debug("Failed to create snapshot", e);
- throw new CloudRuntimeException("Failed to create snapshot", e);
- }
-
- }
-
- 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;
- }
-
- protected boolean supportedByHypervisor(VolumeInfo volume) {
- if (volume.getHypervisorType().equals(HypervisorType.KVM)) {
- StoragePool storagePool = (StoragePool)volume.getDataStore();
- ClusterVO cluster = _clusterDao.findById(storagePool.getClusterId());
- 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, Long snapshotId) {
-
- supportedByHypervisor(volume);
-
- SnapshotInfo snapshot = createSnapshotOnPrimary(volume, snapshotId);
- return snapshot;
- }
-
- @Override
- public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) {
- SnapshotObject snapObj = (SnapshotObject)snapshot;
- AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
- SnapshotResult result = new SnapshotResult(snapshot);
- try {
-
- snapObj.processEvent(Snapshot.Event.BackupToSecondary);
-
- ZoneScope scope = new ZoneScope(snapshot.getDataCenterId());
- List<DataStore> stores = this.dataStoreMgr.getImageStoresByScope(scope);
- if (stores.size() != 1) {
- throw new CloudRuntimeException("find out more than one image stores");
- }
-
- DataStore imageStore = stores.get(0);
- SnapshotInfo snapshotOnImageStore = (SnapshotInfo)imageStore.create(snapshot);
-
- snapshotOnImageStore.processEvent(Event.CreateOnlyRequested);
- CopySnapshotContext<CommandResult> context = new CopySnapshotContext<CommandResult>(null, snapshot,
- snapshotOnImageStore, future);
- AsyncCallbackDispatcher<AncientSnapshotStrategy, CopyCommandResult> caller = AsyncCallbackDispatcher
- .create(this);
- caller.setCallback(
- caller.getTarget().copySnapshotAsyncCallback(null, null))
- .setContext(context);
- this.motionSrv.copyAsync(snapshot, snapshotOnImageStore, caller);
- } catch (Exception e) {
- s_logger.debug("Failed to copy snapshot", e);
- result.setResult("Failed to copy snapshot:" +e.toString());
- try {
- snapObj.processEvent(Snapshot.Event.OperationFailed);
- } catch (NoTransitionException e1) {
- s_logger.debug("Failed to change state: " + e1.toString());
- }
- future.complete(result);
- }
-
- try {
- SnapshotResult res = future.get();
- SnapshotInfo destSnapshot = res.snashot;
- return destSnapshot;
- } catch (InterruptedException e) {
- s_logger.debug("failed copy snapshot", e);
- throw new CloudRuntimeException("Failed to copy snapshot" , e);
- } catch (ExecutionException e) {
- s_logger.debug("Failed to copy snapshot", e);
- throw new CloudRuntimeException("Failed to copy snapshot" , e);
- }
-
- }
-
- protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher<AncientSnapshotStrategy, CopyCommandResult> callback,
- CopySnapshotContext<CommandResult> context) {
- CopyCommandResult result = callback.getResult();
- SnapshotInfo destSnapshot = context.destSnapshot;
- SnapshotObject srcSnapshot = (SnapshotObject)context.srcSnapshot;
- AsyncCallFuture<SnapshotResult> future = context.future;
- SnapshotResult snapResult = new SnapshotResult(destSnapshot);
- if (result.isFailed()) {
- snapResult.setResult(result.getResult());
- future.complete(snapResult);
- return null;
- }
-
- try {
- BackupSnapshotAnswer answer = (BackupSnapshotAnswer)result.getAnswer();
-
- DataObjectInStore dataInStore = objInStoreMgr.findObject(destSnapshot, destSnapshot.getDataStore());
- dataInStore.setInstallPath(answer.getBackupSnapshotName());
- objInStoreMgr.update(destSnapshot, Event.OperationSuccessed);
-
- srcSnapshot.processEvent(Snapshot.Event.OperationSucceeded);
- snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(destSnapshot.getId()));
- future.complete(snapResult);
- } catch (Exception e) {
- s_logger.debug("Failed to update snapshot state", e);
- snapResult.setResult(e.toString());
- future.complete(snapResult);
- }
- return null;
- }
-
- @DB
- protected boolean destroySnapshotBackUp(SnapshotVO snapshot) {
- DataStore store = objInStoreMgr.findStore(snapshot.getId(), DataObjectType.SNAPSHOT, DataStoreRole.Image);
- if (store == null) {
- s_logger.debug("Can't find snapshot" + snapshot.getId() + " backed up into image store");
- return false;
- }
-
- try {
- SnapshotInfo snapshotInfo = this.snapshotfactory.getSnapshot(snapshot.getId(), store);
- snapshotInfo.processEvent(ObjectInDataStoreStateMachine.Event.DestroyRequested);
-
- AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
- DeleteSnapshotContext<CommandResult> context = new DeleteSnapshotContext<CommandResult>(null,
- snapshotInfo, future);
- AsyncCallbackDispatcher<AncientSnapshotStrategy, CommandResult> caller = AsyncCallbackDispatcher
- .create(this);
- caller.setCallback(
- caller.getTarget().deleteSnapshotCallback(null, null))
- .setContext(context);
-
- store.getDriver().deleteAsync(snapshotInfo, caller);
-
- SnapshotResult result = future.get();
- if (result.isFailed()) {
- s_logger.debug("Failed to delete snapsoht: " + result.getResult());
- }
- return result.isSuccess();
- } catch (Exception e) {
- s_logger.debug("Failed to delete snapshot", e);
- return false;
- }
- }
-
- protected Void deleteSnapshotCallback(AsyncCallbackDispatcher<AncientSnapshotStrategy, CommandResult> callback,
- DeleteSnapshotContext<CommandResult> context) {
- CommandResult result = callback.getResult();
- AsyncCallFuture<SnapshotResult> future = context.future;
- SnapshotInfo snapshot = context.snapshot;
- if (result.isFailed()) {
- s_logger.debug("delete snapshot failed" + result.getResult());
- snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
- SnapshotResult res = new SnapshotResult(context.snapshot);
- future.complete(res);
- return null;
- }
- snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed);
- SnapshotResult res = new SnapshotResult(context.snapshot);
- future.complete(res);
- return null;
- }
-
- @Override
- public boolean deleteSnapshot(SnapshotInfo snapInfo) {
- Long snapshotId = snapInfo.getId();
- SnapshotObject snapshot = (SnapshotObject)snapInfo;
-
- if (!Snapshot.State.BackedUp.equals(snapshot.getState())) {
- throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId + " due to it is not in BackedUp Status");
- }
-
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Calling deleteSnapshot for snapshotId: " + snapshotId);
- }
- SnapshotVO lastSnapshot = null;
- if (snapshot.getBackupSnapshotId() != null) {
- List<SnapshotVO> snaps = _snapshotDao.listByBackupUuid(snapshot.getVolumeId(), snapshot.getBackupSnapshotId());
- if (snaps != null && snaps.size() > 1) {
- snapshot.setBackupSnapshotId(null);
- SnapshotVO snapshotVO = this._snapshotDao.findById(snapshotId);
- _snapshotDao.update(snapshot.getId(), snapshotVO);
- }
- }
-
- _snapshotDao.remove(snapshotId);
-
- long lastId = snapshotId;
- boolean destroy = false;
- while (true) {
- lastSnapshot = _snapshotDao.findNextSnapshot(lastId);
- if (lastSnapshot == null) {
- // if all snapshots after this snapshot in this chain are removed, remove those snapshots.
- destroy = true;
- break;
- }
- if (lastSnapshot.getRemoved() == null) {
- // if there is one child not removed, then can not remove back up snapshot.
- break;
- }
- lastId = lastSnapshot.getId();
- }
- if (destroy) {
- lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId);
- while (lastSnapshot.getRemoved() != null) {
- String BackupSnapshotId = lastSnapshot.getBackupSnapshotId();
- if (BackupSnapshotId != null) {
- List<SnapshotVO> snaps = _snapshotDao.listByBackupUuid(lastSnapshot.getVolumeId(), BackupSnapshotId);
- if (snaps != null && snaps.size() > 1) {
- lastSnapshot.setBackupSnapshotId(null);
- _snapshotDao.update(lastSnapshot.getId(), lastSnapshot);
- } else {
- if (destroySnapshotBackUp(lastSnapshot)) {
-
- } else {
- s_logger.debug("Destroying snapshot backup failed " + lastSnapshot);
- break;
- }
- }
- }
- lastId = lastSnapshot.getPrevSnapshotId();
- if (lastId == 0) {
- break;
- }
- lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId);
- }
- }
- return true;
-
- }
-
- @Override
- public boolean revertSnapshot(SnapshotInfo snapshot) {
- // TODO Auto-generated method stub
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java
index f08a597..9fe0c55 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java
@@ -6,7 +6,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
-import org.apache.cloudstack.storage.command.CopyCmd;
+import org.apache.cloudstack.storage.command.CopyCommand;
import com.cloud.agent.Listener;
import com.cloud.agent.api.Answer;
@@ -32,7 +32,7 @@ public class LocalHostEndpoint implements EndPoint {
@Override
public Answer sendMessage(Command cmd) {
- if (cmd instanceof CopyCmd) {
+ if (cmd instanceof CopyCommand) {
return resource.executeRequest(cmd);
}
// TODO Auto-generated method stub
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/29687663/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 e7c009b..300daa5 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
@@ -34,7 +34,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer;
import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
-import org.apache.cloudstack.storage.command.CopyCmd;
+import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
import org.apache.cloudstack.storage.command.CreateObjectCommand;
@@ -84,8 +84,8 @@ public class XenServerStorageResource {
}
public Answer handleStorageCommands(StorageSubSystemCommand command) {
- if (command instanceof CopyCmd) {
- return this.execute((CopyCmd)command);
+ if (command instanceof CopyCommand) {
+ return this.execute((CopyCommand)command);
} else if (command instanceof AttachPrimaryDataStoreCmd) {
return this.execute((AttachPrimaryDataStoreCmd)command);
} else if (command instanceof CreatePrimaryDataStoreCmd) {
@@ -505,7 +505,7 @@ public class XenServerStorageResource {
}
- protected Answer directDownloadHttpTemplate(CopyCmd cmd, DecodedDataObject srcObj, DecodedDataObject destObj) {
+ protected Answer directDownloadHttpTemplate(CopyCommand cmd, DecodedDataObject srcObj, DecodedDataObject destObj) {
Connection conn = hypervisorResource.getConnection();
SR poolsr = null;
VDI vdi = null;
@@ -724,7 +724,7 @@ public class XenServerStorageResource {
}
- protected Answer execute(CopyCmd cmd) {
+ protected Answer execute(CopyCommand cmd) {
DataTO srcData = cmd.getSrcTO();
DataTO destData = cmd.getDestTO();