You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ed...@apache.org on 2013/02/13 20:12:21 UTC
[3/3] git commit: refs/heads/storage_refactor - refactor snapshot,
move existing snapshot code into its own snapshotstrategy
Updated Branches:
refs/heads/storage_refactor b81db545a -> 9d98ece14
refactor snapshot, move existing snapshot code into its own snapshotstrategy
Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/9d98ece1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/9d98ece1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/9d98ece1
Branch: refs/heads/storage_refactor
Commit: 9d98ece14dc145f315805aa3bf5c8a970dc847d4
Parents: b81db54
Author: Edison Su <ed...@citrix.com>
Authored: Wed Feb 13 11:11:45 2013 -0800
Committer: Edison Su <ed...@citrix.com>
Committed: Wed Feb 13 11:11:45 2013 -0800
----------------------------------------------------------------------
api/src/com/cloud/storage/Snapshot.java | 18 +-
core/src/com/cloud/storage/SnapshotVO.java | 2 +-
.../subsystem/api/storage/CopyCommandResult.java | 10 +-
.../subsystem/api/storage/DataObjectInStore.java | 1 +
.../subsystem/api/storage/DataStoreDriver.java | 1 +
.../api/storage/ObjectInDataStoreStateMachine.java | 1 +
.../api/storage/PrimaryDataStoreDriver.java | 26 +
.../engine/subsystem/api/storage/SnapshotInfo.java | 6 +-
.../subsystem/api/storage/SnapshotStrategy.java | 10 +
.../engine/subsystem/api/storage/VolumeInfo.java | 3 +
.../subsystem/api/storage/VolumeService.java | 2 +
.../driver/AncientImageDataStoreDriverImpl.java | 69 ++-
.../driver/DefaultImageDataStoreDriverImpl.java | 7 +
.../image/motion/DefaultImageMotionStrategy.java | 6 +-
.../storage/test/MockStorageMotionStrategy.java | 2 +-
.../storage/snapshot/SnapshotDataFactoryImpl.java | 34 +-
.../storage/snapshot/SnapshotObject.java | 169 +++-
.../storage/snapshot/SnapshotServiceImpl.java | 6 +
.../snapshot/SnapshotStateMachineManager.java | 9 +
.../snapshot/SnapshotStateMachineManagerImpl.java | 37 +
.../snapshot/strategy/AncientSnasphotStrategy.java | 555 ++++++++++++
.../snapshot/strategy/HypervisorBasedSnapshot.java | 44 -
.../snapshot/strategy/StorageBasedSnapshot.java | 42 -
.../datastore/PrimaryDataStoreProviderManager.java | 2 +-
.../storage/motion/AncientDataMotionStrategy.java | 148 +++-
.../storage/snapshot/SnapshotEntityImpl.java | 13 +-
.../storage/snapshot/SnapshotStrategy.java | 25 -
.../storage/volume/PrimaryDataStoreDriver.java | 29 -
.../storage/datastore/DefaultPrimaryDataStore.java | 2 +-
.../driver/AncientPrimaryDataStoreDriverImpl.java | 490 ++++++-----
.../driver/DefaultPrimaryDataStoreDriverImpl.java | 23 +-
...DefaultPrimaryDataStoreProviderManagerImpl.java | 2 +-
.../AncientPrimaryDataStoreProviderImpl.java | 2 +-
.../DefaultPrimaryDatastoreProviderImpl.java | 2 +-
.../cloudstack/storage/volume/VolumeObject.java | 17 +
.../storage/volume/VolumeServiceImpl.java | 104 ++-
.../driver/SolidfirePrimaryDataStoreDriver.java | 22 +-
server/src/com/cloud/api/ApiDBUtils.java | 2 +-
server/src/com/cloud/api/ApiResponseHelper.java | 2 +-
server/src/com/cloud/configuration/Config.java | 3 +-
.../src/com/cloud/storage/ResizeVolumePayload.java | 14 +
server/src/com/cloud/storage/VolumeManager.java | 4 +-
.../src/com/cloud/storage/VolumeManagerImpl.java | 92 +--
server/src/com/cloud/storage/dao/SnapshotDao.java | 2 +-
.../src/com/cloud/storage/dao/SnapshotDaoImpl.java | 2 +-
.../storage/listener/SnapshotStateListener.java | 28 +-
.../cloud/storage/snapshot/SnapshotManager.java | 95 +--
.../storage/snapshot/SnapshotManagerImpl.java | 688 +++------------
48 files changed, 1649 insertions(+), 1224 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/api/src/com/cloud/storage/Snapshot.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/Snapshot.java b/api/src/com/cloud/storage/Snapshot.java
index 3f6b8f5..9c2217e 100644
--- a/api/src/com/cloud/storage/Snapshot.java
+++ b/api/src/com/cloud/storage/Snapshot.java
@@ -61,22 +61,6 @@ public interface Snapshot extends ControlledEntity, Identity, InternalIdentity,
BackedUp,
Error;
- private final static StateMachine2<State, Event, Snapshot> s_fsm = new StateMachine2<State, Event, Snapshot>();
-
- public static StateMachine2<State, Event, Snapshot> getStateMachine() {
- return s_fsm;
- }
-
- static {
- s_fsm.addTransition(null, Event.CreateRequested, Creating);
- s_fsm.addTransition(Creating, Event.OperationSucceeded, CreatedOnPrimary);
- s_fsm.addTransition(Creating, Event.OperationNotPerformed, BackedUp);
- s_fsm.addTransition(Creating, Event.OperationFailed, Error);
- s_fsm.addTransition(CreatedOnPrimary, Event.BackupToSecondary, BackingUp);
- s_fsm.addTransition(BackingUp, Event.OperationSucceeded, BackedUp);
- s_fsm.addTransition(BackingUp, Event.OperationFailed, Error);
- }
-
public String toString() {
return this.name();
}
@@ -107,7 +91,7 @@ public interface Snapshot extends ControlledEntity, Identity, InternalIdentity,
Date getCreated();
- Type getType();
+ Type getRecurringType();
State getState();
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/core/src/com/cloud/storage/SnapshotVO.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/SnapshotVO.java b/core/src/com/cloud/storage/SnapshotVO.java
index 0aa489b..504f6f8 100644
--- a/core/src/com/cloud/storage/SnapshotVO.java
+++ b/core/src/com/cloud/storage/SnapshotVO.java
@@ -175,7 +175,7 @@ public class SnapshotVO implements Snapshot {
}
@Override
- public Type getType() {
+ public Type getRecurringType() {
if (snapshotType < 0 || snapshotType >= Type.values().length) {
return null;
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java
index 100fd4e..571a77c 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java
@@ -18,14 +18,22 @@
*/
package org.apache.cloudstack.engine.subsystem.api.storage;
+import com.cloud.agent.api.Answer;
+
public class CopyCommandResult extends CommandResult {
private final String path;
- public CopyCommandResult(String path) {
+ private final Answer answer;
+ public CopyCommandResult(String path, Answer answer) {
super();
this.path = path;
+ this.answer = answer;
}
public String getPath() {
return this.path;
}
+
+ public Answer getAnswer() {
+ return this.answer;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java
index 60dfb9f..32ea996 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java
@@ -23,4 +23,5 @@ import com.cloud.utils.fsm.StateObject;
public interface DataObjectInStore extends StateObject<ObjectInDataStoreStateMachine.State> {
public String getInstallPath();
+ public void setInstallPath(String path);
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
index 4aba9bf..cf5759b 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
@@ -30,4 +30,5 @@ public interface DataStoreDriver {
public void deleteAsync(DataObject data, AsyncCompletionCallback<CommandResult> callback);
public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
public boolean canCopy(DataObject srcData, DataObject destData);
+ public void resize(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback);
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java
index af9974e..726ce08 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java
@@ -49,6 +49,7 @@ public interface ObjectInDataStoreStateMachine extends StateObject<ObjectInDataS
OperationSuccessed,
OperationFailed,
CopyingRequested,
+ ResizeRequested,
ExpungeRequested
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java
new file mode 100644
index 0000000..78a1014
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.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;
+
+import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+
+public interface PrimaryDataStoreDriver extends DataStoreDriver {
+ public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback);
+ public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CommandResult> callback);
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java
index 30cf182..b90404c 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java
@@ -16,9 +16,13 @@
// under the License.
package org.apache.cloudstack.engine.subsystem.api.storage;
+import com.cloud.storage.Snapshot;
-public interface SnapshotInfo extends DataObject {
+
+public interface SnapshotInfo extends DataObject, Snapshot {
public SnapshotInfo getParent();
public SnapshotInfo getChild();
public VolumeInfo getBaseVolume();
+ Long getDataCenterId();
+ public Long getPrevSnapshotId();
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/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
new file mode 100644
index 0000000..f854f6b
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java
@@ -0,0 +1,10 @@
+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/incubator-cloudstack/blob/9d98ece1/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
index f2a3d5e..349325a 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
@@ -18,10 +18,13 @@
*/
package org.apache.cloudstack.engine.subsystem.api.storage;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Volume;
public interface VolumeInfo extends DataObject, Volume {
public boolean isAttachedVM();
public void addPayload(Object data);
public Object getpayload();
+ public HypervisorType getHypervisorType();
+ public Long getLastPoolId();
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
index 58258eb..102c471 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
@@ -74,5 +74,7 @@ public interface VolumeService {
boolean destroyVolume(long volumeId) throws ConcurrentOperationException;
AsyncCallFuture<VolumeApiResult> registerVolume(VolumeInfo volume, DataStore store);
+
+ AsyncCallFuture<VolumeApiResult> resize(VolumeInfo volume);
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java
index 2c19c7f..97ea6c4 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java
@@ -38,22 +38,30 @@ import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.DeleteSnapshotBackupCommand;
import com.cloud.agent.api.storage.DeleteVolumeCommand;
+import com.cloud.agent.api.to.S3TO;
+import com.cloud.agent.api.to.SwiftTO;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.storage.RegisterVolumePayload;
import com.cloud.storage.Storage.ImageFormat;
+import com.cloud.storage.SnapshotVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.storage.VolumeHostVO;
import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VolumeHostDao;
import com.cloud.storage.download.DownloadMonitor;
+import com.cloud.storage.s3.S3Manager;
+import com.cloud.storage.snapshot.SnapshotManager;
+import com.cloud.storage.swift.SwiftManager;
import com.cloud.utils.exception.CloudRuntimeException;
public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver {
@@ -69,7 +77,13 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver {
@Inject VolumeDao volumeDao;
@Inject VolumeHostDao volumeHostDao;
@Inject HostDao hostDao;
+ @Inject SnapshotDao snapshotDao;
@Inject AgentManager agentMgr;
+ @Inject SnapshotManager snapshotMgr;
+ @Inject
+ private SwiftManager _swiftMgr;
+ @Inject
+ private S3Manager _s3Mgr;
@Override
public String grantAccess(DataObject data, EndPoint ep) {
// TODO Auto-generated method stub
@@ -158,6 +172,49 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver {
}
+ private void deleteSnapshot(DataObject data, AsyncCompletionCallback<CommandResult> callback) {
+ Long snapshotId = data.getId();
+ SnapshotVO snapshot = this.snapshotDao.findByIdIncludingRemoved(snapshotId);
+ CommandResult result = new CommandResult();
+ if (snapshot == null) {
+ s_logger.debug("Destroying snapshot " + snapshotId + " backup failed due to unable to find snapshot ");
+ result.setResult("Unable to find snapshot: " + snapshotId);
+ callback.complete(result);
+ return;
+ }
+
+ try {
+ String secondaryStoragePoolUrl = this.snapshotMgr.getSecondaryStorageURL(snapshot);
+ Long dcId = snapshot.getDataCenterId();
+ Long accountId = snapshot.getAccountId();
+ Long volumeId = snapshot.getVolumeId();
+
+ String backupOfSnapshot = snapshot.getBackupSnapshotId();
+ if (backupOfSnapshot == null) {
+ callback.complete(result);
+ return;
+ }
+ SwiftTO swift = _swiftMgr.getSwiftTO(snapshot.getSwiftId());
+ S3TO s3 = _s3Mgr.getS3TO();
+
+ DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand(
+ swift, s3, secondaryStoragePoolUrl, dcId, accountId, volumeId,
+ backupOfSnapshot, false);
+ Answer answer = agentMgr.sendToSSVM(dcId, cmd);
+
+ if ((answer != null) && answer.getResult()) {
+ snapshot.setBackupSnapshotId(null);
+ snapshotDao.update(snapshotId, snapshot);
+ } else if (answer != null) {
+ result.setResult(answer.getDetails());
+ }
+ } catch (Exception e) {
+ s_logger.debug("failed to delete snapshot: " + snapshotId + ": " + e.toString());
+ result.setResult(e.toString());
+ }
+ callback.complete(result);
+ }
+
@Override
public void deleteAsync(DataObject data,
AsyncCompletionCallback<CommandResult> callback) {
@@ -165,10 +222,9 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver {
deleteVolume(data, callback);
} else if (data.getType() == DataObjectType.TEMPLATE) {
deleteTemplate(data, callback);
+ } else if (data.getType() == DataObjectType.SNAPSHOT) {
+ deleteSnapshot(data, callback);
}
-
-
-
}
@Override
@@ -184,4 +240,11 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver {
return false;
}
+ @Override
+ public void resize(DataObject data,
+ AsyncCompletionCallback<CreateCmdResult> callback) {
+ // TODO Auto-generated method stub
+
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java
index 1a506fa..3d46c73 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java
@@ -116,4 +116,11 @@ public class DefaultImageDataStoreDriverImpl implements ImageDataStoreDriver {
// TODO Auto-generated method stub
}
+
+ @Override
+ public void resize(DataObject data,
+ AsyncCompletionCallback<CreateCmdResult> callback) {
+ // TODO Auto-generated method stub
+
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java
index 561c1cb..c49a521 100644
--- a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java
+++ b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java
@@ -101,7 +101,7 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy {
DataStore destStore = destData.getDataStore();
DataStore srcStore = srcData.getDataStore();
EndPoint ep = selector.select(srcData, destData);
- CopyCommandResult result = new CopyCommandResult("");
+ CopyCommandResult result = new CopyCommandResult("", null);
if (ep == null) {
result.setResult("can't find end point");
callback.complete(result);
@@ -125,12 +125,12 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy {
AsyncCompletionCallback<CopyCommandResult> parentCall = context.getParentCallback();
Answer answer = (Answer)callback.getResult();
if (!answer.getResult()) {
- CopyCommandResult result = new CopyCommandResult("");
+ CopyCommandResult result = new CopyCommandResult("", null);
result.setResult(answer.getDetails());
parentCall.complete(result);
} else {
CopyCmdAnswer ans = (CopyCmdAnswer)answer;
- CopyCommandResult result = new CopyCommandResult(ans.getPath());
+ CopyCommandResult result = new CopyCommandResult(ans.getPath(), null);
parentCall.complete(result);
}
return null;
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java
index e2e8f94..b619ee9 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java
@@ -34,7 +34,7 @@ public class MockStorageMotionStrategy implements DataMotionStrategy {
@Override
public Void copyAsync(DataObject srcData, DataObject destData,
AsyncCompletionCallback<CopyCommandResult> callback) {
- CopyCommandResult result = new CopyCommandResult("something");
+ CopyCommandResult result = new CopyCommandResult("something", null);
callback.complete(result);
return null;
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
index 0953209..5af5260 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
@@ -25,39 +25,55 @@ 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.DataStoreRole;
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.VolumeDataFactory;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
-import org.apache.cloudstack.storage.snapshot.db.SnapshotDao2;
-import org.apache.cloudstack.storage.snapshot.db.SnapshotVO;
import org.springframework.stereotype.Component;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+
@Component
public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
@Inject
- SnapshotDao2 snapshotDao;
+ SnapshotDao snapshotDao;
@Inject
ObjectInDataStoreManager objMap;
@Inject
DataStoreManager storeMgr;
+ @Inject
+ VolumeDataFactory volumeFactory;
@Override
public SnapshotInfo getSnapshot(long snapshotId, DataStore store) {
- SnapshotVO snapshot = snapshotDao.findById(snapshotId);
+ SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(snapshotId);
DataObjectInStore obj = objMap.findObject(snapshot.getUuid(), DataObjectType.SNAPSHOT, store.getUuid(), store.getRole());
if (obj == null) {
return null;
}
- SnapshotObject so = new SnapshotObject(snapshot, store);
+ SnapshotObject so = SnapshotObject.getSnapshotObject(snapshot, store);
return so;
}
@Override
public SnapshotInfo getSnapshot(long snapshotId) {
- // TODO Auto-generated method stub
- return null;
+ SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(snapshotId);
+ SnapshotObject so = null;
+ if (snapshot.getState() == Snapshot.State.BackedUp) {
+ DataStore store = objMap.findStore(snapshot.getUuid(), DataObjectType.SNAPSHOT, DataStoreRole.Image);
+ so = SnapshotObject.getSnapshotObject(snapshot, store);
+ } else {
+ VolumeInfo volume = this.volumeFactory.getVolume(snapshot.getVolumeId());
+ so = SnapshotObject.getSnapshotObject(snapshot, volume.getDataStore());
+ }
+ return so;
}
+
@Override
public SnapshotInfo getSnapshot(DataObject obj, DataStore store) {
- // TODO Auto-generated method stub
- return null;
+ throw new CloudRuntimeException("not implemented yet");
}
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
index d9fc8aa..a82be6d 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
@@ -18,21 +18,54 @@
*/
package org.apache.cloudstack.storage.snapshot;
+import java.util.Date;
+
+import javax.inject.Inject;
+
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.ObjectInDataStoreStateMachine.Event;
+import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
-import org.apache.cloudstack.storage.snapshot.db.SnapshotVO;
+import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
+import org.apache.log4j.Logger;
+
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.utils.component.ComponentContext;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.fsm.NoTransitionException;
public class SnapshotObject implements SnapshotInfo {
+ private static final Logger s_logger = Logger.getLogger(SnapshotObject.class);
private SnapshotVO snapshot;
private DataStore store;
-
- public SnapshotObject(SnapshotVO snapshot, DataStore store) {
- this.snapshot = snapshot;
- this.store = store;
+ @Inject
+ protected SnapshotDao snapshotDao;
+ @Inject
+ protected VolumeDao volumeDao;
+ @Inject protected VolumeDataFactory volFactory;
+ @Inject protected SnapshotStateMachineManager stateMachineMgr;
+ @Inject
+ ObjectInDataStoreManager ojbectInStoreMgr;
+ protected SnapshotObject() {
+
+ }
+
+ protected void configure(SnapshotVO snapshot, DataStore store) {
+ this.snapshot = snapshot;
+ this.store = store;
+ }
+
+ public static SnapshotObject getSnapshotObject(SnapshotVO snapshot, DataStore store) {
+ SnapshotObject snapObj = ComponentContext.inject(SnapshotObject.class);
+ snapObj.configure(snapshot, store);
+ return snapObj;
}
public DataStore getStore() {
@@ -53,56 +86,138 @@ public class SnapshotObject implements SnapshotInfo {
@Override
public VolumeInfo getBaseVolume() {
- // TODO Auto-generated method stub
- return null;
+ return volFactory.getVolume(this.snapshot.getVolumeId());
}
@Override
public long getId() {
- // TODO Auto-generated method stub
- return 0;
+ return this.snapshot.getId();
}
@Override
public String getUri() {
- // TODO Auto-generated method stub
- return null;
+ return this.snapshot.getUuid();
}
@Override
public DataStore getDataStore() {
- // TODO Auto-generated method stub
- return null;
+ return this.store;
}
@Override
public Long getSize() {
- // TODO Auto-generated method stub
- return 0L;
+ return this.getSize();
}
@Override
public DataObjectType getType() {
- // TODO Auto-generated method stub
- return null;
+ return DataObjectType.SNAPSHOT;
}
@Override
public DiskFormat getFormat() {
- // TODO Auto-generated method stub
return null;
}
@Override
public String getUuid() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void processEvent(Event event) {
- // TODO Auto-generated method stub
-
+ return this.snapshot.getUuid();
}
+ @Override
+ public void processEvent(
+ ObjectInDataStoreStateMachine.Event event) {
+ try {
+ ojbectInStoreMgr.update(this, event);
+ } catch (Exception e) {
+ s_logger.debug("Failed to update state:" + e.toString());
+ throw new CloudRuntimeException("Failed to update state: " + e.toString());
+ }
+ }
+
+ @Override
+ public long getAccountId() {
+ return this.snapshot.getAccountId();
+ }
+
+ @Override
+ public long getVolumeId() {
+ return this.snapshot.getVolumeId();
+ }
+
+ @Override
+ public String getPath() {
+ return this.snapshot.getPath();
+ }
+
+ public void setPath(String path) {
+ this.snapshot.setPath(path);
+ }
+
+ @Override
+ public String getName() {
+ return this.snapshot.getName();
+ }
+
+ @Override
+ public Date getCreated() {
+ return this.snapshot.getCreated();
+ }
+
+ @Override
+ public Type getRecurringType() {
+ return this.snapshot.getRecurringType();
+ }
+
+ @Override
+ public State getState() {
+ return this.snapshot.getState();
+ }
+
+ @Override
+ public HypervisorType getHypervisorType() {
+ return this.snapshot.getHypervisorType();
+ }
+
+ @Override
+ public boolean isRecursive() {
+ return this.snapshot.isRecursive();
+ }
+
+ @Override
+ public short getsnapshotType() {
+ return this.snapshot.getsnapshotType();
+ }
+
+ @Override
+ public long getDomainId() {
+ return this.snapshot.getDomainId();
+ }
+
+ public void setPrevSnapshotId(Long id) {
+ this.snapshot.setPrevSnapshotId(id);
+ }
+
+ @Override
+ public Long getDataCenterId() {
+ return this.snapshot.getDataCenterId();
+ }
+
+ public void processEvent(Snapshot.Event event)
+ throws NoTransitionException {
+ stateMachineMgr.processEvent(this.snapshot, event);
+ }
+
+ @Override
+ public Long getPrevSnapshotId() {
+ return this.snapshot.getPrevSnapshotId();
+ }
+
+ public void setBackupSnapshotId(String id) {
+ this.snapshot.setBackupSnapshotId(id);
+ }
+
+ public String getBackupSnapshotId() {
+ return this.snapshot.getBackupSnapshotId();
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/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 bd3caf4..1b64fd0 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
@@ -22,6 +22,10 @@ import org.springframework.stereotype.Component;
@Component
public class SnapshotServiceImpl implements SnapshotService {
+
+ public SnapshotServiceImpl() {
+
+ }
@Override
public SnapshotEntity getSnapshotEntity(long snapshotId) {
@@ -46,5 +50,7 @@ public class SnapshotServiceImpl implements SnapshotService {
// TODO Auto-generated method stub
return false;
}
+
+
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java
new file mode 100644
index 0000000..1c3ac28
--- /dev/null
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java
@@ -0,0 +1,9 @@
+package org.apache.cloudstack.storage.snapshot;
+
+import com.cloud.storage.Snapshot.Event;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.utils.fsm.NoTransitionException;
+
+public interface SnapshotStateMachineManager {
+ public void processEvent(SnapshotVO snapshot, Event event) throws NoTransitionException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java
new file mode 100644
index 0000000..a20a2c8
--- /dev/null
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java
@@ -0,0 +1,37 @@
+package org.apache.cloudstack.storage.snapshot;
+
+import javax.inject.Inject;
+
+import org.springframework.stereotype.Component;
+
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.Snapshot.Event;
+import com.cloud.storage.Snapshot.State;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.listener.SnapshotStateListener;
+import com.cloud.utils.fsm.NoTransitionException;
+import com.cloud.utils.fsm.StateMachine2;
+
+@Component
+public class SnapshotStateMachineManagerImpl implements
+SnapshotStateMachineManager {
+ private StateMachine2<State, Event, SnapshotVO> stateMachine = new StateMachine2<State, Event, SnapshotVO>();
+ @Inject
+ protected SnapshotDao snapshotDao;
+ public SnapshotStateMachineManagerImpl() {
+ stateMachine.addTransition(null, Event.CreateRequested, Snapshot.State.Creating);
+ stateMachine.addTransition(Snapshot.State.Creating, Event.OperationSucceeded, Snapshot.State.CreatedOnPrimary);
+ stateMachine.addTransition(Snapshot.State.Creating, Event.OperationNotPerformed, Snapshot.State.BackedUp);
+ stateMachine.addTransition(Snapshot.State.Creating, Event.OperationFailed, Snapshot.State.Error);
+ stateMachine.addTransition(Snapshot.State.CreatedOnPrimary, Event.BackupToSecondary, Snapshot.State.BackingUp);
+ stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationSucceeded, Snapshot.State.BackedUp);
+ stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationFailed, Snapshot.State.Error);
+
+ stateMachine.registerListener(new SnapshotStateListener());
+ }
+
+ public void processEvent(SnapshotVO snapshot, Event event) throws NoTransitionException {
+ stateMachine.transitTo(snapshot, event, null, snapshotDao);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnasphotStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnasphotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnasphotStrategy.java
new file mode 100644
index 0000000..704db6b
--- /dev/null
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnasphotStrategy.java
@@ -0,0 +1,555 @@
+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.DataObject;
+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.DataStoreRole;
+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.motion.DataMotionService;
+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.Answer;
+import com.cloud.agent.api.BackupSnapshotAnswer;
+import com.cloud.agent.api.DeleteSnapshotBackupCommand;
+import com.cloud.agent.api.to.S3TO;
+import com.cloud.agent.api.to.SwiftTO;
+import com.cloud.configuration.Resource.ResourceType;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.event.EventTypes;
+import com.cloud.event.UsageEventUtils;
+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.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.StoragePoolDao;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.storage.s3.S3Manager;
+import com.cloud.storage.snapshot.SnapshotManager;
+import com.cloud.storage.swift.SwiftManager;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.Transaction;
+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;
+
+@Component
+public class AncientSnasphotStrategy implements SnapshotStrategy {
+ private static final Logger s_logger = Logger.getLogger(AncientSnasphotStrategy.class);
+ @Inject
+ protected VolumeDao _volsDao;
+ @Inject
+ protected UserVmDao _vmDao;
+ @Inject
+ protected StoragePoolDao _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;
+
+
+ @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<AncientSnasphotStrategy, 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 = 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());
+ }
+
+ 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>();
+
+ CreateSnapshotContext<CommandResult> context = new CreateSnapshotContext<CommandResult>(
+ null, volume, snapshot, future);
+ AsyncCallbackDispatcher<AncientSnasphotStrategy, CreateCmdResult> caller = AsyncCallbackDispatcher
+ .create(this);
+ caller.setCallback(
+ caller.getTarget().createSnapshotAsyncCallback(null, null))
+ .setContext(context);
+ PrimaryDataStoreDriver primaryStore = (PrimaryDataStoreDriver)volume.getDataStore().getDriver();
+
+ primaryStore.takeSnapshot(snapshot, caller);
+ 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");
+ }
+ }
+ }
+
+ 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.getImageStores(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<AncientSnasphotStrategy, 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());
+ 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<AncientSnasphotStrategy, 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.getUuid(), 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<AncientSnasphotStrategy, 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<AncientSnasphotStrategy, 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/incubator-cloudstack/blob/9d98ece1/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/HypervisorBasedSnapshot.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/HypervisorBasedSnapshot.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/HypervisorBasedSnapshot.java
deleted file mode 100644
index 8ef0927..0000000
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/HypervisorBasedSnapshot.java
+++ /dev/null
@@ -1,44 +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 org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
-import org.apache.cloudstack.storage.snapshot.SnapshotStrategy;
-import org.springframework.stereotype.Component;
-
-@Component
-public class HypervisorBasedSnapshot implements SnapshotStrategy {
-
- @Override
- public boolean takeSnapshot(SnapshotInfo snapshot) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean revertSnapshot(SnapshotInfo snapshot) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean deleteSnapshot(SnapshotInfo snapshot) {
- // TODO Auto-generated method stub
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/StorageBasedSnapshot.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/StorageBasedSnapshot.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/StorageBasedSnapshot.java
deleted file mode 100644
index 7af395a..0000000
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/StorageBasedSnapshot.java
+++ /dev/null
@@ -1,42 +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 org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
-import org.apache.cloudstack.storage.snapshot.SnapshotStrategy;
-
-public class StorageBasedSnapshot implements SnapshotStrategy {
-
- @Override
- public boolean takeSnapshot(SnapshotInfo snapshot) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean revertSnapshot(SnapshotInfo snapshot) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean deleteSnapshot(SnapshotInfo snapshot) {
- // TODO Auto-generated method stub
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java
index 664c2d1..d1c26e1 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java
@@ -19,7 +19,7 @@
package org.apache.cloudstack.storage.datastore;
import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
-import org.apache.cloudstack.storage.volume.PrimaryDataStoreDriver;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
public interface PrimaryDataStoreProviderManager {
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index ed3ca6a..c067a1b 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -28,6 +28,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
@@ -36,6 +37,8 @@ import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.BackupSnapshotAnswer;
+import com.cloud.agent.api.BackupSnapshotCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
@@ -47,7 +50,9 @@ import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.CreateAnswer;
import com.cloud.agent.api.storage.CreateCommand;
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
+import com.cloud.agent.api.to.S3TO;
import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.agent.api.to.SwiftTO;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.exception.StorageUnavailableException;
@@ -72,7 +77,9 @@ import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VolumeHostDao;
+import com.cloud.storage.s3.S3Manager;
import com.cloud.storage.snapshot.SnapshotManager;
+import com.cloud.storage.swift.SwiftManager;
import com.cloud.template.TemplateManager;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.db.DB;
@@ -112,6 +119,10 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
@Inject VMTemplatePoolDao templatePoolDao;
@Inject
VolumeManager volumeMgr;
+ @Inject
+ private SwiftManager _swiftMgr;
+ @Inject
+ private S3Manager _s3Mgr;
@Override
public boolean canHandle(DataObject srcData, DataObject destData) {
@@ -120,7 +131,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
}
@DB
- protected String copyVolumeFromImage(DataObject srcData, DataObject destData) {
+ protected Answer copyVolumeFromImage(DataObject srcData, DataObject destData) {
String value = configDao.getValue(Config.RecreateSystemVmEnabled.key());
int _copyvolumewait = NumbersUtil.parseInt(value,
Integer.parseInt(Config.CopyVolumeWait.getDefaultValue()));
@@ -162,16 +173,17 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
this.volDao.update(vol.getId(), vol);
volumeHostDao.remove(volumeHostVO.getId());
txn.commit();
- return errMsg;
+ return cvAnswer;
}
- private void copyTemplate(DataObject srcData, DataObject destData) {
+ private Answer copyTemplate(DataObject srcData, DataObject destData) {
VMTemplateVO template = this.templateDao.findById(srcData.getId());
templateMgr.prepareTemplateForCreate(template,
(StoragePool) destData.getDataStore());
+ return null;
}
- protected String copyFromSnapshot(DataObject snapObj, DataObject volObj) {
+ protected Answer copyFromSnapshot(DataObject snapObj, DataObject volObj) {
SnapshotVO snapshot = this.snapshotDao.findById(snapObj.getId());
StoragePool pool = (StoragePool) volObj.getDataStore();
String vdiUUID = null;
@@ -227,8 +239,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
if ((answer != null) && answer.getResult()) {
snapshotDao.updateSnapshotVersion(volumeId, "2.1", "2.2");
} else {
- return "Unable to upgrade snapshot from 2.1 to 2.2 for "
- + snapshot.getId();
+ throw new CloudRuntimeException("Unable to upgrade snapshot from 2.1 to 2.2 for "
+ + snapshot.getId());
}
}
}
@@ -277,11 +289,10 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
snapshotMgr.deleteSnapshotsDirForVolume(
secondaryStoragePoolUrl, dcId, accountId, volumeId);
}
- snapshotDao.unlockFromLockTable(snapshotId.toString());
}
}
- protected String cloneVolume(DataObject template, DataObject volume) {
+ protected Answer cloneVolume(DataObject template, DataObject volume) {
VolumeInfo volInfo = (VolumeInfo)volume;
DiskOfferingVO offering = diskOfferingDao.findById(volInfo.getDiskOfferingId());
VMTemplateStoragePoolVO tmpltStoredOn = templatePoolDao.findByPoolTemplate(template.getDataStore().getId(), template.getId());
@@ -298,8 +309,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
answer = storagMgr.sendToPool(pool, null, cmd);
} catch (StorageUnavailableException e) {
s_logger.debug("Failed to send to storage pool", e);
- errMsg = e.toString();
- return errMsg;
+ throw new CloudRuntimeException("Failed to send to storage pool", e);
}
if (answer.getResult()) {
@@ -327,10 +337,10 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
errMsg = answer.getDetails();
}
- return errMsg;
+ return answer;
}
- protected String copyVolumeBetweenPools(DataObject srcData, DataObject destData) {
+ protected Answer copyVolumeBetweenPools(DataObject srcData, DataObject destData) {
VolumeInfo volume = (VolumeInfo)srcData;
VolumeInfo destVolume = (VolumeInfo)destData;
String secondaryStorageURL = this.templateMgr.getSecondaryStorageURL(volume
@@ -380,41 +390,45 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
VolumeVO destVol = this.volDao.findById(destVolume.getId());
destVol.setPath(cvAnswer.getVolumePath());
this.volDao.update(destVol.getId(), destVol);
- return null;
+ return cvAnswer;
}
@Override
public Void copyAsync(DataObject srcData, DataObject destData,
AsyncCompletionCallback<CopyCommandResult> callback) {
+ Answer answer = null;
String errMsg = null;
try {
if (destData.getType() == DataObjectType.VOLUME
&& srcData.getType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Image) {
- errMsg = copyVolumeFromImage(srcData, destData);
+ answer = copyVolumeFromImage(srcData, destData);
} else if (destData.getType() == DataObjectType.TEMPLATE
&& srcData.getType() == DataObjectType.TEMPLATE) {
- copyTemplate(srcData, destData);
+ answer = copyTemplate(srcData, destData);
} else if (srcData.getType() == DataObjectType.SNAPSHOT
&& destData.getType() == DataObjectType.VOLUME) {
- errMsg = copyFromSnapshot(srcData, destData);
+ answer = copyFromSnapshot(srcData, destData);
} else if (srcData.getType() == DataObjectType.SNAPSHOT
&& destData.getType() == DataObjectType.TEMPLATE) {
- errMsg = createTemplateFromSnashot(srcData, destData);
+ answer = createTemplateFromSnashot(srcData, destData);
} else if (srcData.getType() == DataObjectType.VOLUME
&& destData.getType() == DataObjectType.TEMPLATE) {
- errMsg = createTemplateFromVolume(srcData, destData);
+ answer = createTemplateFromVolume(srcData, destData);
} else if (srcData.getType() == DataObjectType.TEMPLATE
&& destData.getType() == DataObjectType.VOLUME) {
- errMsg = cloneVolume(srcData, destData);
+ answer = cloneVolume(srcData, destData);
} else if (destData.getType() == DataObjectType.VOLUME
&& srcData.getType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
- errMsg = copyVolumeBetweenPools(srcData, destData);
+ answer = copyVolumeBetweenPools(srcData, destData);
+ } else if (srcData.getType() == DataObjectType.SNAPSHOT &&
+ destData.getType() == DataObjectType.SNAPSHOT) {
+ answer = copySnapshot(srcData, destData);
}
} catch (Exception e) {
s_logger.debug("copy failed", e);
errMsg = e.toString();
}
- CopyCommandResult result = new CopyCommandResult(null);
+ CopyCommandResult result = new CopyCommandResult(null, answer);
result.setResult(errMsg);
callback.complete(result);
@@ -422,7 +436,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
}
@DB
- protected String createTemplateFromSnashot(DataObject srcData,
+ protected Answer createTemplateFromSnashot(DataObject srcData,
DataObject destData) {
long snapshotId = srcData.getId();
SnapshotVO snapshot = snapshotDao.findById(snapshotId);
@@ -538,7 +552,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
}
@DB
- protected String sendCommand(Command cmd, StoragePool pool,
+ protected Answer sendCommand(Command cmd, StoragePool pool,
long templateId, long zoneId, long hostId) {
CreatePrivateTemplateAnswer answer = null;
@@ -551,11 +565,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
e);
}
- if (answer == null) {
- return "Failed to execute CreatePrivateTemplateFromSnapshotCommand";
- } else if (!answer.getResult()) {
- return "Failed to execute CreatePrivateTemplateFromSnapshotCommand"
- + answer.getDetails();
+ if (answer == null || !answer.getResult()) {
+ return answer;
}
VMTemplateVO privateTemplate = templateDao.findById(templateId);
@@ -594,10 +605,10 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
templateHostVO.setPhysicalSize(answer.getphysicalSize());
templateHostDao.persist(templateHostVO);
txn.close();
- return null;
+ return answer;
}
- private String createTemplateFromVolume(DataObject srcObj,
+ private Answer createTemplateFromVolume(DataObject srcObj,
DataObject destObj) {
long volumeId = srcObj.getId();
VolumeVO volume = this.volDao.findById(volumeId);
@@ -633,5 +644,82 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
return sendCommand(cmd, pool, template.getId(), zoneId,
secondaryStorageHost.getId());
}
+
+ private HostVO getSecHost(long volumeId, long dcId) {
+ Long id = snapshotDao.getSecHostId(volumeId);
+ if ( id != null) {
+ return hostDao.findById(id);
+ }
+ return this.templateMgr.getSecondaryStorageHost(dcId);
+ }
+
+ protected Answer copySnapshot(DataObject srcObject, DataObject destObject) {
+ SnapshotInfo srcSnapshot = (SnapshotInfo)srcObject;
+ VolumeInfo baseVolume = srcSnapshot.getBaseVolume();
+ Long dcId = baseVolume.getDataCenterId();
+ Long accountId = baseVolume.getAccountId();
+
+ HostVO secHost = getSecHost(baseVolume.getId(), baseVolume.getDataCenterId());
+
+ String secondaryStoragePoolUrl = secHost.getStorageUrl();
+ String snapshotUuid = srcSnapshot.getPath();
+ // In order to verify that the snapshot is not empty,
+ // we check if the parent of the snapshot is not the same as the parent of the previous snapshot.
+ // We pass the uuid of the previous snapshot to the plugin to verify this.
+ SnapshotVO prevSnapshot = null;
+ String prevSnapshotUuid = null;
+ String prevBackupUuid = null;
+
+
+ SwiftTO swift = _swiftMgr.getSwiftTO();
+ S3TO s3 = _s3Mgr.getS3TO();
+
+ long prevSnapshotId = srcSnapshot.getPrevSnapshotId();
+ if (prevSnapshotId > 0) {
+ prevSnapshot = snapshotDao.findByIdIncludingRemoved(prevSnapshotId);
+ if ( prevSnapshot.getBackupSnapshotId() != null && swift == null) {
+ if (prevSnapshot.getVersion() != null && prevSnapshot.getVersion().equals("2.2")) {
+ prevBackupUuid = prevSnapshot.getBackupSnapshotId();
+ prevSnapshotUuid = prevSnapshot.getPath();
+ }
+ } else if ((prevSnapshot.getSwiftId() != null && swift != null)
+ || (prevSnapshot.getS3Id() != null && s3 != null)) {
+ prevBackupUuid = prevSnapshot.getBackupSnapshotId();
+ prevSnapshotUuid = prevSnapshot.getPath();
+ }
+ }
+ boolean isVolumeInactive = this.volumeMgr.volumeInactive(baseVolume);
+ String vmName = this.volumeMgr.getVmNameOnVolume(baseVolume);
+ StoragePool srcPool = (StoragePool)dataStoreMgr.getPrimaryDataStore(baseVolume.getPoolId());
+ String value = configDao.getValue(Config.BackupSnapshotWait.toString());
+ int _backupsnapshotwait = NumbersUtil.parseInt(value, Integer.parseInt(Config.BackupSnapshotWait.getDefaultValue()));
+ BackupSnapshotCommand backupSnapshotCommand = new BackupSnapshotCommand(secondaryStoragePoolUrl, dcId, accountId, baseVolume.getId(), srcSnapshot.getId(), baseVolume.getPath(), srcPool, snapshotUuid,
+ srcSnapshot.getName(), prevSnapshotUuid, prevBackupUuid, isVolumeInactive, vmName, _backupsnapshotwait);
+
+ if ( swift != null ) {
+ backupSnapshotCommand.setSwift(swift);
+ } else if (s3 != null) {
+ backupSnapshotCommand.setS3(s3);
+ }
+ BackupSnapshotAnswer answer = (BackupSnapshotAnswer) this.snapshotMgr.sendToPool(baseVolume, backupSnapshotCommand);
+ if (answer != null && answer.getResult()) {
+ SnapshotVO snapshotVO = this.snapshotDao.findById(srcSnapshot.getId());
+ if (backupSnapshotCommand.getSwift() != null ) {
+ snapshotVO.setSwiftId(swift.getId());
+ snapshotVO.setBackupSnapshotId(answer.getBackupSnapshotName());
+ } else if (backupSnapshotCommand.getS3() != null) {
+ snapshotVO.setS3Id(s3.getId());
+ snapshotVO.setBackupSnapshotId(answer.getBackupSnapshotName());
+ } else {
+ snapshotVO.setSecHostId(secHost.getId());
+ snapshotVO.setBackupSnapshotId(answer.getBackupSnapshotName());
+ }
+ if (answer.isFull()) {
+ snapshotVO.setPrevSnapshotId(0L);
+ }
+ this.snapshotDao.update(srcSnapshot.getId(), snapshotVO);
+ }
+ return answer;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
index 6a7d78a..0a91186 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
@@ -106,13 +106,6 @@ public class SnapshotEntityImpl implements SnapshotEntity {
}
@Override
- public Type getType() {
- // TODO Auto-generated method stub
- return null;
- }
-
-
- @Override
public HypervisorType getHypervisorType() {
// TODO Auto-generated method stub
return null;
@@ -190,4 +183,10 @@ public class SnapshotEntityImpl implements SnapshotEntity {
return null;
}
+ @Override
+ public Type getRecurringType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotStrategy.java b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotStrategy.java
deleted file mode 100644
index 8c4c815..0000000
--- a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotStrategy.java
+++ /dev/null
@@ -1,25 +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;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
-
-public interface SnapshotStrategy {
- public boolean takeSnapshot(SnapshotInfo snapshot);
- public boolean revertSnapshot(SnapshotInfo snapshot);
- public boolean deleteSnapshot(SnapshotInfo snapshot);
-}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9d98ece1/engine/storage/src/org/apache/cloudstack/storage/volume/PrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/PrimaryDataStoreDriver.java b/engine/storage/src/org/apache/cloudstack/storage/volume/PrimaryDataStoreDriver.java
deleted file mode 100644
index 2b49eee..0000000
--- a/engine/storage/src/org/apache/cloudstack/storage/volume/PrimaryDataStoreDriver.java
+++ /dev/null
@@ -1,29 +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.volume;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
-import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
-import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
-
-public interface PrimaryDataStoreDriver extends DataStoreDriver {
- public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CommandResult> callback);
- public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CommandResult> callback);
-}