bug 6332: remove the new snapshot if it is empty

status 6332: resolved fixed
This commit is contained in:
anthony 2010-09-30 12:29:25 -07:00
parent 734e9c8a28
commit 25f7d46aed
9 changed files with 73 additions and 122 deletions

View File

@ -37,10 +37,11 @@ public class ManageSnapshotCommand extends Command {
public ManageSnapshotCommand() {}
public ManageSnapshotCommand(String commandSwitch, long snapshotId, String path, String snapshotName) {
public ManageSnapshotCommand(String commandSwitch, long snapshotId, String path, String preSnapshot, String snapshotName) {
_commandSwitch = commandSwitch;
if (commandSwitch.equals(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
_volumePath = path;
_snapshotPath = preSnapshot;
}
else if (commandSwitch.equals(ManageSnapshotCommand.DESTROY_SNAPSHOT)) {
_snapshotPath = path;

View File

@ -5079,6 +5079,20 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR
return new ValidateSnapshotAnswer(cmd, success, details, expectedSnapshotBackupUuid, actualSnapshotBackupUuid, actualSnapshotUuid);
}
protected String getVhdParent(String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) {
String parentUuid = callHostPlugin("vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid,
"snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString());
if (parentUuid == null || parentUuid.isEmpty()) {
s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid);
// errString is already logged.
return null;
}
return parentUuid;
}
protected ManageSnapshotAnswer execute(final ManageSnapshotCommand cmd) {
long snapshotId = cmd.getSnapshotId();
String snapshotName = cmd.getSnapshotName();
@ -5111,6 +5125,25 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR
}
// Determine the UUID of the snapshot
snapshotUUID = snapshot.getUuid(conn);
String preSnapshotUUID = cmd.getSnapshotPath();
//check if it is a empty snapshot
if( preSnapshotUUID != null) {
SR sr = volume.getSR(conn);
String srUUID = sr.getUuid(conn);
String type = sr.getType(conn);
Boolean isISCSI = SRType.LVMOISCSI.equals(type);
String snapshotParentUUID = getVhdParent(srUUID, snapshotUUID, isISCSI);
String preSnapshotParentUUID = getVhdParent(srUUID, preSnapshotUUID, isISCSI);
if( snapshotParentUUID != null && snapshotParentUUID.equals(preSnapshotParentUUID)) {
// this is empty snapshot, remove it
snapshot.destroy(conn);
snapshotUUID = preSnapshotUUID;
}
}
VDI.Record vdir = snapshot.getRecord(conn);
snapshotUUID = vdir.uuid;

View File

@ -1734,19 +1734,7 @@ public interface ManagementServer {
ResourceAllocationException,
InternalErrorException;
/**
* @param userId The Id of the user who invoked this operation.
* @param volumeId The volume for which this snapshot is being taken
* @return The properties of the snapshot taken
*/
SnapshotVO createTemplateSnapshot(Long userId, long volumeId);
/**
* Destroy a snapshot
* @param snapshotId the id of the snapshot to destroy
* @return true if snapshot successfully destroyed, false otherwise
*/
boolean destroyTemplateSnapshot(Long userId, long snapshotId);
long deleteSnapshotAsync(long userId, long snapshotId);
long createVolumeFromSnapshotAsync(long userId, long accountId, long snapshotId, String volumeName) throws InternalErrorException, ResourceAllocationException;

View File

@ -2103,8 +2103,20 @@ def network_rules(session, args):
except:
util.SMlog("Failed to network rule !")
def getVhdParent(session, args):
util.SMlog("getParent with " + str(args))
primaryStorageSRUuid = args['primaryStorageSRUuid']
snapshotUuid = args['snapshotUuid']
isISCSI = getIsTrueString(args['isISCSI'])
primarySRPath = getPrimarySRPath(primaryStorageSRUuid, isISCSI)
util.SMlog("primarySRPath: " + primarySRPath)
baseCopyUuid = getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI)
return baseCopyUuid
if __name__ == "__main__":
XenAPIPlugin.dispatch({"pingtest": pingtest, "create_secondary_storage_folder":create_secondary_storage_folder, "setup_iscsi":setup_iscsi, "delete_secondary_storage_folder":delete_secondary_storage_folder, "post_create_private_template": post_create_private_template, "gethostvmstats": gethostvmstats, "getvncport": getvncport, "getgateway": getgateway, "getnetwork": getnetwork, "preparemigration": preparemigration, "setIptables": setIptables, "patchdomr": patchdomr, "pingdomr": pingdomr, "pingxenserver": pingxenserver, "ipassoc": ipassoc, "vm_data": vm_data, "savePassword": savePassword, "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, "checkMount": checkMount, "checkIscsi": checkIscsi, "backupSnapshot": backupSnapshot, "deleteSnapshotBackup": deleteSnapshotBackup, "createVolumeFromSnapshot": createVolumeFromSnapshot, "networkUsage": networkUsage, "unmountSnapshotsDir": unmountSnapshotsDir, "deleteSnapshotsDir": deleteSnapshotsDir, "validatePreviousSnapshotBackup": validatePreviousSnapshotBackup, "validateSnapshot" : validateSnapshot, "network_rules":network_rules, "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, "destroy_network_rules_for_vm":destroy_network_rules_for_vm, "default_network_rules_systemvm":default_network_rules_systemvm, "get_rule_logs_for_vms":get_rule_logs_for_vms, "setLinkLocalIP":setLinkLocalIP})
XenAPIPlugin.dispatch({"getVhdParent":getVhdParent, "pingtest": pingtest, "create_secondary_storage_folder":create_secondary_storage_folder, "setup_iscsi":setup_iscsi, "delete_secondary_storage_folder":delete_secondary_storage_folder, "post_create_private_template": post_create_private_template, "gethostvmstats": gethostvmstats, "getvncport": getvncport, "getgateway": getgateway, "getnetwork": getnetwork, "preparemigration": preparemigration, "setIptables": setIptables, "patchdomr": patchdomr, "pingdomr": pingdomr, "pingxenserver": pingxenserver, "ipassoc": ipassoc, "vm_data": vm_data, "savePassword": savePassword, "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, "checkMount": checkMount, "checkIscsi": checkIscsi, "backupSnapshot": backupSnapshot, "deleteSnapshotBackup": deleteSnapshotBackup, "createVolumeFromSnapshot": createVolumeFromSnapshot, "networkUsage": networkUsage, "unmountSnapshotsDir": unmountSnapshotsDir, "deleteSnapshotsDir": deleteSnapshotsDir, "validatePreviousSnapshotBackup": validatePreviousSnapshotBackup, "validateSnapshot" : validateSnapshot, "network_rules":network_rules, "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, "destroy_network_rules_for_vm":destroy_network_rules_for_vm, "default_network_rules_systemvm":default_network_rules_systemvm, "get_rule_logs_for_vms":get_rule_logs_for_vms, "setLinkLocalIP":setLinkLocalIP})

View File

@ -40,6 +40,7 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.UserVmManager;
import com.google.gson.Gson;
@ -118,7 +119,8 @@ public class CreatePrivateTemplateExecutor extends VolumeOperationExecutor {
if (snapshotId == null) {
// We are create private template from volume. Create a snapshot, copy the vhd chain of the disk to secondary storage.
// For template snapshot, we use a separate snapshot method.
snapshot = vmMgr.createTemplateSnapshot(param.getUserId(), param.getVolumeId());
//snapshot = vmMgr.createTemplateSnapshot(param.getUserId(), param.getVolumeId());
throw new CloudRuntimeException("Do not support create template from volume at this moment");
}
else {
// We are creating a private template from an already present snapshot.
@ -145,13 +147,6 @@ public class CreatePrivateTemplateExecutor extends VolumeOperationExecutor {
resultObject = composeResultObject(template, templateHostRef, volume.getDataCenterId());
}
// Irrespective of whether the template was created or not,
// cleanup the snapshot taken for this template. (If this template is created from a volume and not a snapshot)
if(snapshotId == null) {
// Template was created from volume
// and snapshot is not null.
managerServer.destroyTemplateSnapshot(param.getUserId(), snapshot.getId());
}
}
}
}

View File

@ -6325,16 +6325,6 @@ public class ManagementServerImpl implements ManagementServer {
return jobId;
}
@Override
public SnapshotVO createTemplateSnapshot(Long userId, long volumeId) {
return _vmMgr.createTemplateSnapshot(userId, volumeId);
}
@Override
public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
return _vmMgr.destroyTemplateSnapshot(userId, snapshotId);
}
@Override
public long deleteSnapshotAsync(long userId, long snapshotId) {
Snapshot snapshot = findSnapshotById(snapshotId);

View File

@ -115,6 +115,7 @@ import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.UserVmDao;
import com.google.gson.Gson;
@ -362,9 +363,19 @@ public class SnapshotManagerImpl implements SnapshotManager {
}
txn.commit();
// get previous snapshot Path
long preId = _snapshotDao.getLastSnapshot(volumeId, id);
String preSnapshotPath = null;
SnapshotVO preSnapshotVO = null;
if( preId != 0) {
preSnapshotVO = _snapshotDao.findById(preId);
preSnapshotPath = preSnapshotVO.getPath();
}
// Send a ManageSnapshotCommand to the agent
ManageSnapshotCommand cmd = new ManageSnapshotCommand(ManageSnapshotCommand.CREATE_SNAPSHOT, id, volume.getPath(), snapshotName);
ManageSnapshotCommand cmd = new ManageSnapshotCommand(ManageSnapshotCommand.CREATE_SNAPSHOT, id, volume.getPath(), preSnapshotPath, snapshotName);
String basicErrMsg = "Failed to create snapshot for volume: " + volume.getId();
ManageSnapshotAnswer answer = (ManageSnapshotAnswer) _storageMgr.sendToHostsOnStoragePool(volume.getPoolId(), cmd, basicErrMsg, _totalRetries, _pauseInterval, _shouldBeSnapshotCapable);
@ -374,7 +385,16 @@ public class SnapshotManagerImpl implements SnapshotManager {
// Update the snapshot in the database
if ((answer != null) && answer.getResult()) {
// The snapshot was successfully created
createdSnapshot = updateDBOnCreate(id, answer.getSnapshotPath());
if( preSnapshotPath != null && preSnapshotPath == answer.getSnapshotPath() ){
//empty snapshot
s_logger.debug("CreateSnapshot: this is empty snapshot, remove it ");
// delete from the snapshots table
_snapshotDao.delete(id);
throw new CloudRuntimeException(" There is no change since last snapshot, please use last snapshot " + preSnapshotPath);
} else {
createdSnapshot = updateDBOnCreate(id, answer.getSnapshotPath());
}
} else {
if (answer != null) {
s_logger.error(answer.getDetails());

View File

@ -196,14 +196,6 @@ public interface UserVmManager extends Manager, VirtualMachineManager<UserVmVO>
*/
VMTemplateVO createPrivateTemplate(VMTemplateVO template, Long userId, long snapshotId, String name, String description);
/**
* @param userId The Id of the user who invoked this operation.
* @param volumeId The volume for which this snapshot is being taken
* @return The properties of the snapshot taken
*/
SnapshotVO createTemplateSnapshot(long userId, long volumeId);
boolean destroyTemplateSnapshot(Long userId, long snapshotId);
/**
* Clean the network rules for the given VM
* @param userId

View File

@ -2021,87 +2021,7 @@ public class UserVmManagerImpl implements UserVmManager {
}
}
@Override
public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
boolean success = false;
SnapshotVO snapshot = _snapshotDao.findById(Long.valueOf(snapshotId));
if (snapshot != null) {
VolumeVO volume = _volsDao.findById(snapshot.getVolumeId());
ManageSnapshotCommand cmd = new ManageSnapshotCommand(ManageSnapshotCommand.DESTROY_SNAPSHOT, snapshotId, snapshot.getPath(), snapshot.getName());
Answer answer = null;
String basicErrMsg = "Failed to destroy template snapshot: " + snapshot.getName();
Long storagePoolId = volume.getPoolId();
answer = _storageMgr.sendToHostsOnStoragePool(storagePoolId, cmd, basicErrMsg);
if ((answer != null) && answer.getResult()) {
// delete the snapshot from the database
_snapshotDao.delete(snapshotId);
success = true;
}
if (answer != null) {
s_logger.error(answer.getDetails());
}
}
return success;
}
@Override @DB
public SnapshotVO createTemplateSnapshot(long userId, long volumeId) {
SnapshotVO createdSnapshot = null;
VolumeVO volume = _volsDao.findById(volumeId);
Long id = null;
// Determine the name for this snapshot
String timeString = DateUtil.getDateDisplayString(DateUtil.GMT_TIMEZONE, new Date(), DateUtil.YYYYMMDD_FORMAT);
String snapshotName = volume.getName() + "_" + timeString;
// Create the Snapshot object and save it so we can return it to the user
SnapshotType snapshotType = SnapshotType.TEMPLATE;
SnapshotVO snapshot = new SnapshotVO(volume.getAccountId(), volume.getId(), null, snapshotName, (short)snapshotType.ordinal(), snapshotType.name());
snapshot = _snapshotDao.persist(snapshot);
id = snapshot.getId();
// Send a ManageSnapshotCommand to the agent
ManageSnapshotCommand cmd = new ManageSnapshotCommand(ManageSnapshotCommand.CREATE_SNAPSHOT, id, volume.getPath(), snapshotName);
String basicErrMsg = "Failed to create snapshot for volume: " + volume.getId();
// This can be sent to a KVM host too. We are only taking snapshots on primary storage, which doesn't require XenServer.
// So shouldBeSnapshotCapable is set to false.
ManageSnapshotAnswer answer = (ManageSnapshotAnswer) _storageMgr.sendToHostsOnStoragePool(volume.getPoolId(), cmd, basicErrMsg);
// Update the snapshot in the database
if ((answer != null) && answer.getResult()) {
// The snapshot was successfully created
Transaction txn = Transaction.currentTxn();
txn.start();
createdSnapshot = _snapshotDao.findById(id);
createdSnapshot.setPath(answer.getSnapshotPath());
createdSnapshot.setStatus(Snapshot.Status.CreatedOnPrimary);
_snapshotDao.update(id, createdSnapshot);
txn.commit();
// Don't Create an event for Template Snapshots for now.
} else {
if (answer != null) {
s_logger.error(answer.getDetails());
}
// The snapshot was not successfully created
Transaction txn = Transaction.currentTxn();
txn.start();
createdSnapshot = _snapshotDao.findById(id);
_snapshotDao.delete(id);
txn.commit();
createdSnapshot = null;
}
return createdSnapshot;
}
@Override
public void cleanNetworkRules(long userId, long instanceId) {
UserVmVO vm = _vmDao.findById(instanceId);