CLOUDSTACK-2630: fix delta snashpt

This commit is contained in:
Edison Su 2013-07-20 18:21:03 -07:00 committed by Min Chen
parent fa358cf01f
commit d22bea6031
8 changed files with 95 additions and 55 deletions

View File

@ -334,18 +334,25 @@ public class SnapshotServiceImpl implements SnapshotService {
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, null);
future.complete(res);
return null;
SnapshotResult res = null;
try {
if (result.isFailed()) {
s_logger.debug("delete snapshot failed" + result.getResult());
snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
res = new SnapshotResult(context.snapshot, null);
res.setResult(result.getResult());
} else {
snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed);
res = new SnapshotResult(context.snapshot, null);
}
} catch (Exception e) {
s_logger.debug("Failed to in deleteSnapshotCallback", e);
res.setResult(e.toString());
}
snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed);
SnapshotResult res = new SnapshotResult(context.snapshot, null);
future.complete(res);
return null;
}

View File

@ -42,6 +42,7 @@ public class SnapshotStateMachineManagerImpl implements SnapshotStateMachineMana
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(State.CreatedOnPrimary, Event.OperationNotPerformed, State.BackedUp);
stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationSucceeded, Snapshot.State.BackedUp);
stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationFailed, Snapshot.State.CreatedOnPrimary);
stateMachine.addTransition(Snapshot.State.BackedUp, Event.DestroyRequested, Snapshot.State.Destroying);
@ -49,7 +50,7 @@ public class SnapshotStateMachineManagerImpl implements SnapshotStateMachineMana
stateMachine.addTransition(Snapshot.State.Copying, Event.OperationSucceeded, Snapshot.State.BackedUp);
stateMachine.addTransition(Snapshot.State.Copying, Event.OperationFailed, Snapshot.State.BackedUp);
stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationSucceeded, Snapshot.State.Destroyed);
stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationFailed, Snapshot.State.Error);
stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationFailed, State.BackedUp);
stateMachine.registerListener(new SnapshotStateListener());
}

View File

@ -127,21 +127,23 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
return this.snapshotSvr.backupSnapshot(snapshot);
}
protected void deleteSnapshotChain(SnapshotInfo snapshot) {
while (snapshot != null) {
protected boolean deleteSnapshotChain(SnapshotInfo snapshot) {
s_logger.debug("delete snapshot chain for snapshot: " + snapshot.getId());
boolean result = false;
while (snapshot != null && (snapshot.getState() == Snapshot.State.Destroying || snapshot.getState()
== Snapshot.State.Destroyed || snapshot.getState() == Snapshot.State.Error)) {
SnapshotInfo child = snapshot.getChild();
SnapshotInfo parent = snapshot.getParent();
if (child == null) {
if (parent == null || !parent.getPath().equalsIgnoreCase(snapshot.getPath())) {
this.snapshotSvr.deleteSnapshot(snapshot);
snapshot = parent;
continue;
}
break;
} else {
if (child != null) {
s_logger.debug("the snapshot has child, can't delete it on the storage");
break;
}
s_logger.debug("Snapshot: " + snapshot.getId() + " doesn't have children, so it's ok to delete it and its parents");
SnapshotInfo parent = snapshot.getParent();
result = this.snapshotSvr.deleteSnapshot(snapshot);
snapshot = parent;
}
return result;
}
@Override
@ -151,36 +153,47 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
return true;
}
if (snapshotVO.getState() == Snapshot.State.CreatedOnPrimary) {
s_logger.debug("delete snapshot on primary storage:");
snapshotVO.setState(Snapshot.State.Destroyed);
snapshotDao.update(snapshotId, snapshotVO);
return true;
}
if (!Snapshot.State.BackedUp.equals(snapshotVO.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);
}
// firt mark the snapshot as destroyed, so that ui can't see it, but we
// may not destroy the snapshot on the storage, as other snaphosts may
// depend on it.
SnapshotInfo snapshotOnPrimary = this.snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Primary);
SnapshotObject obj = (SnapshotObject) snapshotOnPrimary;
SnapshotInfo snapshotOnImage = this.snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Image);
if (snapshotOnImage == null) {
s_logger.debug("Can't find snapshot on backup storage, delete it in db");
snapshotDao.remove(snapshotId);
}
SnapshotObject obj = (SnapshotObject) snapshotOnImage;
try {
obj.processEvent(Snapshot.Event.DestroyRequested);
} catch (NoTransitionException e) {
s_logger.debug("Failed to destroy snapshot: " + e.toString());
s_logger.debug("Failed to set the state to destroying: ", e);
return false;
}
try {
SnapshotInfo snapshotOnImage = this.snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Image);
if (snapshotOnImage != null) {
deleteSnapshotChain(snapshotOnImage);
}
boolean result = deleteSnapshotChain(snapshotOnImage);
obj.processEvent(Snapshot.Event.OperationSucceeded);
if (result) {
//snapshot is deleted on backup storage, need to delete it on primary storage
SnapshotDataStoreVO snapshotOnPrimary = snapshotStoreDao.findBySnapshot(snapshotId, DataStoreRole.Primary);
snapshotOnPrimary.setState(State.Destroyed);
snapshotStoreDao.update(snapshotOnPrimary.getId(), snapshotOnPrimary);
}
} catch (Exception e) {
s_logger.debug("Failed to delete snapshot: " + e.toString());
s_logger.debug("Failed to delete snapshot: ", e);
try {
obj.processEvent(Snapshot.Event.OperationFailed);
} catch (NoTransitionException e1) {

View File

@ -219,10 +219,9 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
@Override
public void deleteAsync(DataStore dataStore, DataObject data, AsyncCompletionCallback<CommandResult> callback) {
DeleteCommand cmd = new DeleteCommand(data.getTO());
CommandResult result = new CommandResult();
try {
DeleteCommand cmd = new DeleteCommand(data.getTO());
EndPoint ep = _epSelector.select(data);
Answer answer = ep.sendMessage(cmd);
if (answer != null && !answer.getResult()) {

View File

@ -1160,7 +1160,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
String backupUuid = UUID.randomUUID().toString();
String results = hypervisorResource.callHostPluginAsync(conn, "vmopsSnapshot", "backupSnapshot", wait,
"primaryStorageSRUuid", primaryStorageSRUuid, "path", path, "secondaryStorageMountPath", secondaryStorageMountPath,
"snapshotUuid", snapshotUuid, "prevBackupUuid", prevBackupUuid, "backupUuid", backupUuid, "isISCSI", isISCSI.toString(), "localMountPath", localMountPoint);
"snapshotUuid", snapshotUuid, "prevBackupUuid", prevBackupUuid, "backupUuid", backupUuid, "isISCSI", isISCSI.toString(), "localMountPoint", localMountPoint);
String errMsg = null;
if (results == null || results.isEmpty()) {
errMsg = "Could not copy backupUuid: " + backupSnapshotUuid

View File

@ -504,7 +504,7 @@ def backupSnapshot(session, args):
# on it.
backupsDir = mountSnapshotsDir(secondaryStorageMountPath, localMountPoint, path)
util.SMlog("Backups dir " + backupsDir)
prevBackupUuid = prevBackupUuid.split("/")[-1]
# Check existence of snapshot on primary storage
isfile(baseCopyPath, isISCSI)
if prevBackupUuid:

View File

@ -1429,25 +1429,10 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return new Answer(cmd, false, errorMessage);
}
} else if (dstore instanceof SwiftTO) {
SwiftTO swiftTO = (SwiftTO)dstore;
String path = obj.getPath();
String filename = StringUtils.substringAfterLast(path, "/"); // assuming
// that
// the
// filename
// is
// the
// last
// section
// in
// the
// path
String volumeId = StringUtils.substringAfterLast(StringUtils.substringBeforeLast(path, "/"), "/");
String result = swiftDelete((SwiftTO) dstore, "V-" + volumeId, filename);
if (result != null) {
String errMsg = "failed to delete snapshot " + filename + " , err=" + result;
s_logger.warn(errMsg);
return new Answer(cmd, false, errMsg);
}
SwiftUtil.deleteObject(swiftTO, path);
return new Answer(cmd, true, "Deleted snapshot " + path + " from swift");
} else {
return new Answer(cmd, false, "Unsupported image data store: " + dstore);

View File

@ -203,4 +203,39 @@ public class SwiftUtil {
}
return null;
}
public static String[] splitSwiftPath(String path) {
int index = path.indexOf(File.separator);
if (index == -1) {
return null;
}
String[] paths = new String[2];
paths[0] = path.substring(0, index);
paths[1] = path.substring(index + 1);
return paths;
}
public static boolean deleteObject(SwiftClientCfg cfg, String path) {
Script command = new Script("/bin/bash", logger);
command.add("-c");
String[] paths = splitSwiftPath(path);
if (paths == null) {
return false;
}
String container = paths[0];
String objectName = paths[1];
StringBuilder swiftCmdBuilder = buildSwiftCmd(cfg);
swiftCmdBuilder.append(" delete ");
swiftCmdBuilder.append(container);
swiftCmdBuilder.append(" ");
swiftCmdBuilder.append(objectName);
command.add(swiftCmdBuilder.toString());
OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
String result = command.execute(parser);
return true;
}
}