bug 11380: taking VM snapshot is moved to do it at the same time when backup it to secondary storage, wait snapshot MOR really appears in vCenter until we continue.

This commit is contained in:
Kelven Yang 2011-09-13 17:21:59 -07:00
parent 45c595d558
commit 6b33d114e8
3 changed files with 31 additions and 55 deletions

View File

@ -9,7 +9,6 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.rmi.RemoteException; import java.rmi.RemoteException;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -34,8 +33,6 @@ import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.hypervisor.vmware.mo.CustomFieldConstants; import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
import com.cloud.hypervisor.vmware.mo.DatacenterMO; import com.cloud.hypervisor.vmware.mo.DatacenterMO;
import com.cloud.hypervisor.vmware.mo.DatastoreMO; import com.cloud.hypervisor.vmware.mo.DatastoreMO;
import com.cloud.hypervisor.vmware.mo.HostMO;
import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
import com.cloud.hypervisor.vmware.mo.VirtualMachineMO; import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost; import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
import com.vmware.vim25.VirtualDeviceConfigSpec; import com.vmware.vim25.VirtualDeviceConfigSpec;
@ -177,10 +174,10 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
vmMo = hyperHost.findVmOnPeerHyperHost(cmd.getVmName()); vmMo = hyperHost.findVmOnPeerHyperHost(cmd.getVmName());
if(vmMo == null) { if(vmMo == null) {
dsMo = new DatastoreMO(hyperHost.getContext(), morDs); dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
//restrict VM name to 32 chars, (else snapshot descriptor file name will be truncated to 32 chars of vm name) // restrict VM name to 32 chars, (else snapshot descriptor file name will be truncated to 32 chars of vm name)
workerVMName = UUID.randomUUID().toString().replaceAll("-", ""); workerVMName = UUID.randomUUID().toString().replaceAll("-", "");
//attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup // attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup
if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, 0, VirtualMachineGuestOsIdentifier._otherGuest.toString(), morDs, false)) { if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, 0, VirtualMachineGuestOsIdentifier._otherGuest.toString(), morDs, false)) {
String msg = "Unable to create worker VM to execute BackupSnapshotCommand"; String msg = "Unable to create worker VM to execute BackupSnapshotCommand";
s_logger.error(msg); s_logger.error(msg);
@ -189,10 +186,10 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
vmMo = hyperHost.findVmOnHyperHost(workerVMName); vmMo = hyperHost.findVmOnHyperHost(workerVMName);
if (vmMo == null) { if (vmMo == null) {
throw new Exception("Failed to find the newly create or relocated VM. vmName: " + workerVMName); throw new Exception("Failed to find the newly create or relocated VM. vmName: " + workerVMName);
} }
workerVm = vmMo; workerVm = vmMo;
//attach volume to worker VM // attach volume to worker VM
String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath); String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath);
vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs); vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
snapshotUUID = UUID.randomUUID().toString(); snapshotUUID = UUID.randomUUID().toString();
@ -200,6 +197,10 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
throw new Exception("Failed to take snapshot " + cmd.getSnapshotName() + " on vm: " + cmd.getVmName()); throw new Exception("Failed to take snapshot " + cmd.getSnapshotName() + " on vm: " + cmd.getVmName());
} }
} }
} else {
if (!vmMo.createSnapshot(snapshotUuid, "Snapshot taken for " + cmd.getSnapshotName(), false, false)) {
throw new Exception("Failed to take snapshot " + cmd.getSnapshotName() + " on vm: " + cmd.getVmName());
}
} }
snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, accountId, snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, accountId,
@ -226,7 +227,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
} finally { } finally {
try { try {
if (workerVm != null) { if (workerVm != null) {
//detach volume and destroy worker vm // detach volume and destroy worker vm
workerVm.moveAllVmDiskFiles(dsMo, "", false); workerVm.moveAllVmDiskFiles(dsMo, "", false);
workerVm.detachAllDisks(); workerVm.detachAllDisks();
workerVm.destroy(); workerVm.destroy();

View File

@ -2225,53 +2225,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
String details = "ManageSnapshotCommand operation: " + snapshotOp + " Failed for snapshotId: " + snapshotId; String details = "ManageSnapshotCommand operation: " + snapshotOp + " Failed for snapshotId: " + snapshotId;
String snapshotUUID = null; String snapshotUUID = null;
try {
VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext());
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(cmd.getVmName());
if (vmMo == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to find the owner VM for ManageSnapshotCommand on host " + hyperHost.getHyperHostName() + ", try within datacenter");
}
vmMo = hyperHost.findVmOnPeerHyperHost(cmd.getVmName());
}
if (vmMo == null) {
// when no vm instance attached fake as if snapshot is taken, and handle actual taking snapshot as part of BackupSnapshotCommand
snapshotUUID = UUID.randomUUID().toString();
success = true;
details = null;
} else {
if (cmdSwitch.equals(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
snapshotUUID = UUID.randomUUID().toString();
if (!vmMo.createSnapshot(snapshotUUID, "Snapshot taken for " + cmd.getSnapshotName(), false, false)) {
throw new Exception("Failed to take snapshot " + cmd.getSnapshotName() + " on vm: " + cmd.getVmName());
}
success = true; // snapshot operation (create or destroy) is handled inside BackupSnapshotCommand(), we just fake
details = null; // a success return here
} else if (cmd.getCommandSwitch().equals(ManageSnapshotCommand.DESTROY_SNAPSHOT)) { snapshotUUID = UUID.randomUUID().toString();
snapshotUUID = cmd.getSnapshotPath(); success = true;
details = null;
if (!vmMo.removeSnapshot(snapshotUUID, false)) {
throw new Exception("Failed to destroy snapshot: " + cmd.getSnapshotName());
}
success = true;
details = null;
}
}
} catch (Throwable e) {
if (e instanceof RemoteException) {
s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
invalidateServiceContext();
}
details = "ManageSnapshotCommand failed due to " + VmwareHelper.getExceptionMessage(e);
s_logger.error(details);
return new ManageSnapshotAnswer(cmd, snapshotId, snapshotUUID, false, details);
}
return new ManageSnapshotAnswer(cmd, snapshotId, snapshotUUID, success, details); return new ManageSnapshotAnswer(cmd, snapshotId, snapshotUUID, success, details);
} }

View File

@ -325,7 +325,23 @@ public class VirtualMachineMO extends BaseMO {
String result = _context.getServiceUtil().waitForTask(morTask); String result = _context.getServiceUtil().waitForTask(morTask);
if(result.equals("sucess")) { if(result.equals("sucess")) {
_context.waitForTaskProgressDone(morTask); _context.waitForTaskProgressDone(morTask);
ManagedObjectReference morSnapshot = null;
// We still need to wait until the object appear in vCenter
long startTick = System.currentTimeMillis();
while(System.currentTimeMillis() - startTick < 10000) {
morSnapshot = getSnapshotMor(snapshotName);
if(morSnapshot != null) {
break;
}
try { Thread.sleep(1000); } catch(InterruptedException e) {}
}
if(morSnapshot == null)
s_logger.error("We've been waiting for over 10 seconds for snapshot MOR to be appearing in vCenter after CreateSnapshot task is done, but it is still not there?!");
return true; return true;
} else { } else {
s_logger.error("VMware createSnapshot_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask)); s_logger.error("VMware createSnapshot_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));