You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by sa...@apache.org on 2013/11/11 09:58:07 UTC

git commit: updated refs/heads/4.2 to 8f53bb2

Updated Branches:
  refs/heads/4.2 6a92f7546 -> 8f53bb273


CLOUDSTACK-4993 [VMware] When issuing detach ISO to Vcenter, MS should prevent Vcenter from posting Virtual Machine question dialog waiting for user response

During ISO detach operation, answer question from vCenter by pragrmatically answering for VM question in detaching process.

Signed-off-by: Sateesh Chodapuneedi <sa...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/8f53bb27
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8f53bb27
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8f53bb27

Branch: refs/heads/4.2
Commit: 8f53bb2731c04487a6c0c0cd5062eb957f0636f4
Parents: 6a92f75
Author: Sateesh Chodapuneedi <sa...@apache.org>
Authored: Mon Nov 11 08:48:12 2013 +0530
Committer: Sateesh Chodapuneedi <sa...@apache.org>
Committed: Mon Nov 11 08:48:12 2013 +0530

----------------------------------------------------------------------
 .../hypervisor/vmware/mo/VirtualMachineMO.java  | 194 +++++++++++++++++--
 1 file changed, 179 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f53bb27/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
----------------------------------------------------------------------
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
index 55cc8de..126b67d 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
@@ -29,14 +29,19 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
 import org.apache.log4j.Logger;
 
 import com.google.gson.Gson;
 import com.vmware.vim25.ArrayOfManagedObjectReference;
+import com.vmware.vim25.ChoiceOption;
 import com.vmware.vim25.CustomFieldStringValue;
 import com.vmware.vim25.DistributedVirtualSwitchPortConnection;
 import com.vmware.vim25.DynamicProperty;
+import com.vmware.vim25.ElementDescription;
 import com.vmware.vim25.GuestInfo;
 import com.vmware.vim25.GuestOsDescriptor;
 import com.vmware.vim25.HttpNfcLeaseDeviceUrl;
@@ -80,8 +85,10 @@ import com.vmware.vim25.VirtualMachineConfigOption;
 import com.vmware.vim25.VirtualMachineConfigSpec;
 import com.vmware.vim25.VirtualMachineConfigSummary;
 import com.vmware.vim25.VirtualMachineFileInfo;
+import com.vmware.vim25.VirtualMachineMessage;
 import com.vmware.vim25.VirtualMachineMovePriority;
 import com.vmware.vim25.VirtualMachinePowerState;
+import com.vmware.vim25.VirtualMachineQuestionInfo;
 import com.vmware.vim25.VirtualMachineRelocateDiskMoveOptions;
 import com.vmware.vim25.VirtualMachineRelocateSpec;
 import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator;
@@ -98,12 +105,14 @@ import com.cloud.hypervisor.vmware.util.VmwareHelper;
 import com.cloud.utils.ActionDelegate;
 import com.cloud.utils.Pair;
 import com.cloud.utils.Ternary;
+import com.cloud.utils.concurrency.NamedThreadFactory;
 import com.cloud.utils.script.Script;
 
 import edu.emory.mathcs.backport.java.util.Arrays;
 
 public class VirtualMachineMO extends BaseMO {
     private static final Logger s_logger = Logger.getLogger(VirtualMachineMO.class);
+    private static final ExecutorService _monitorServiceExecutor = Executors.newCachedThreadPool(new NamedThreadFactory("VM-Question-Monitor"));
     private ManagedObjectReference _vmEnvironmentBrowser = null;
 
 	public VirtualMachineMO(VmwareContext context, ManagedObjectReference morVm) {
@@ -170,6 +179,10 @@ public class VirtualMachineMO extends BaseMO {
 		return (GuestInfo)getContext().getVimClient().getDynamicProperty(_mor, "guest");
 	}
 
+    public void answerVM(String questionId, String choice) throws Exception {
+        getContext().getService().answerVM(_mor, questionId, choice);
+    }
+
 	public boolean isVMwareToolsRunning() throws Exception {
 		GuestInfo guestInfo = getVmGuestInfo();
 		if(guestInfo != null) {
@@ -1157,7 +1170,7 @@ public class VirtualMachineMO extends BaseMO {
 		boolean connect, boolean connectAtBoot) throws Exception {
 
 		if(s_logger.isTraceEnabled())
-			s_logger.trace("vCenter API trace - detachIso(). target MOR: " + _mor.getValue() + ", isoDatastorePath: "
+            s_logger.trace("vCenter API trace - attachIso(). target MOR: " + _mor.getValue() + ", isoDatastorePath: "
 				+ isoDatastorePath + ", datastore: " + morDs.getValue() + ", connect: " + connect + ", connectAtBoot: " + connectAtBoot);
 
 		assert(isoDatastorePath != null);
@@ -1240,18 +1253,90 @@ public class VirtualMachineMO extends BaseMO {
 	    //deviceConfigSpecArray[0] = deviceConfigSpec;
 	    reConfigSpec.getDeviceChange().add(deviceConfigSpec);
 
-	    ManagedObjectReference morTask = _context.getService().reconfigVMTask(_mor, reConfigSpec);
-		boolean result = _context.getVimClient().waitForTask(morTask);
+        ManagedObjectReference morTask = _context.getService().reconfigVMTask(_mor, reConfigSpec);
+
+        // Monitor VM questions
+        final Boolean[] flags = { false };
+        final VirtualMachineMO vmMo = this;
+        Future<?> future = _monitorServiceExecutor.submit(new Runnable() {
+            @Override
+            public void run() {
+                s_logger.info("VM Question monitor started...");
+
+                while(!flags[0]) {
+                    try {
+                        VirtualMachineRuntimeInfo runtimeInfo = vmMo.getRuntimeInfo();
+                        VirtualMachineQuestionInfo question = runtimeInfo.getQuestion();
+                        if(question != null) {
+                            if(s_logger.isTraceEnabled()) {
+                                s_logger.trace("Question id: " + question.getId());
+                                s_logger.trace("Question text: " + question.getText());
+                            }
+                            if(question.getMessage() != null) {
+                                for(VirtualMachineMessage msg : question.getMessage()) {
+                                    if(s_logger.isTraceEnabled()) {
+                                        s_logger.trace("msg id: " + msg.getId());
+                                        s_logger.trace("msg text: " + msg.getText());
+                                    }
+                                    if("msg.cdromdisconnect.locked".equalsIgnoreCase(msg.getId())) {
+                                        s_logger.info("Found that VM has a pending question that we need to answer programmatically, question id: " + msg.getId()
+                                                + ", for safe operation we will automatically decline it");
+                                        vmMo.answerVM(question.getId(), "1");
+                                        break;
+                                    }
+                                }
+                            } else if (question.getText() != null) {
+                                String text = question.getText();
+                                String msgId;
+                                String msgText;
+                                if (s_logger.isDebugEnabled()) {
+                                    s_logger.debug("question text : " + text);
+                                }
+                                String[] tokens = text.split(":");
+                                msgId = tokens[0];
+                                msgText = tokens[1];
+                                if ("msg.cdromdisconnect.locked".equalsIgnoreCase(msgId)) {
+                                    s_logger.info("Found that VM has a pending question that we need to answer programmatically, question id: " + question.getId()
+                                            + ". Message id : " + msgId + ". Message text : " + msgText
+                                            + ", for safe operation we will automatically decline it.");
+                                    vmMo.answerVM(question.getId(), "1");
+                                }
+                            }
 
-		if(!result) {
-			if(s_logger.isTraceEnabled())
-				s_logger.trace("vCenter API trace - detachIso() done(failed)");
-            throw new Exception("Failed to detachIso due to " + TaskMO.getTaskFailureInfo(_context, morTask));
+                            ChoiceOption choice = question.getChoice();
+                            if(choice != null) {
+                                for(ElementDescription info : choice.getChoiceInfo()) {
+                                    if(s_logger.isTraceEnabled()) {
+                                        s_logger.trace("Choice option key: " + info.getKey());
+                                        s_logger.trace("Choice option label: " + info.getLabel());
+                                    }
+                                }
+                            }
+                        }
+                    } catch(Throwable e) {
+                        s_logger.error("Unexpected exception: ", e);
+                    }
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException e) {
+                    }
+                }
+                s_logger.info("VM Question monitor stopped");
+            }
+        });
+        try {
+            boolean result = _context.getVimClient().waitForTask(morTask);
+            if (!result) {
+                if(s_logger.isDebugEnabled())
+                    s_logger.trace("vCenter API trace - detachIso() done(failed)");
+                throw new Exception("Failed to detachIso due to " + TaskMO.getTaskFailureInfo(_context, morTask));
+            }
+            _context.waitForTaskProgressDone(morTask);
+            s_logger.trace("vCenter API trace - detachIso() done(successfully)");
+        } finally {
+            flags[0] = true;
+            future.cancel(true);
         }
-		_context.waitForTaskProgressDone(morTask);
-
-		if(s_logger.isTraceEnabled())
-			s_logger.trace("vCenter API trace - detachIso() done(successfully)");
 	}
 
 	public Pair<VmdkFileDescriptor, byte[]> getVmdkFileInfo(String vmdkDatastorePath) throws Exception {
@@ -2027,7 +2112,7 @@ public class VirtualMachineMO extends BaseMO {
 			}
 	    }
 	    	
-	    return detachedDiskFiles; 
+	    return detachedDiskFiles;
 	}
 	
 	public List<VirtualDevice> getAllDeviceList() throws Exception {
@@ -2052,7 +2137,7 @@ public class VirtualMachineMO extends BaseMO {
 		for(VirtualDevice device : allDevices ) {
 			if(device instanceof VirtualDisk) {
 				VirtualDisk disk = (VirtualDisk)device;
-				String diskBusName = getDeviceBusName(allDevices, (VirtualDevice)disk);
+				String diskBusName = getDeviceBusName(allDevices, disk);
 				if(busName.equalsIgnoreCase(diskBusName))
 					return disk;
 			}
@@ -2280,8 +2365,87 @@ public class VirtualMachineMO extends BaseMO {
 	}
 
 	public void unmountToolsInstaller() throws Exception {
-		_context.getService().unmountToolsInstaller(_mor);
-	}
+        int i = 1;
+        // Monitor VM questions
+        final Boolean[] flags = {false};
+        final VirtualMachineMO vmMo = this;
+        Future<?> future = _monitorServiceExecutor.submit(new Runnable() {
+            @Override
+            public void run() {
+                s_logger.info("VM Question monitor started...");
+
+                while (!flags[0]) {
+                    try {
+                        VirtualMachineRuntimeInfo runtimeInfo = vmMo.getRuntimeInfo();
+                        VirtualMachineQuestionInfo question = runtimeInfo.getQuestion();
+                        if (question != null) {
+                            if (s_logger.isTraceEnabled()) {
+                                s_logger.trace("Question id: " + question.getId());
+                                s_logger.trace("Question text: " + question.getText());
+                            }
+
+                            if (question.getMessage() != null) {
+                                for (VirtualMachineMessage msg : question.getMessage()) {
+                                    if (s_logger.isTraceEnabled()) {
+                                        s_logger.trace("msg id: " + msg.getId());
+                                        s_logger.trace("msg text: " + msg.getText());
+                                    }
+                                    if ("msg.cdromdisconnect.locked".equalsIgnoreCase(msg.getId())) {
+                                        s_logger.info("Found that VM has a pending question that we need to answer programmatically, question id: " + msg.getId()
+                                                + ", for safe operation we will automatically decline it");
+                                        vmMo.answerVM(question.getId(), "1");
+                                        break;
+                                    }
+                                }
+                            } else if (question.getText() != null) {
+                                String text = question.getText();
+                                String msgId;
+                                String msgText;
+                                if (s_logger.isDebugEnabled()) {
+                                    s_logger.debug("question text : " + text);
+                                }
+                                String[] tokens = text.split(":");
+                                msgId = tokens[0];
+                                msgText = tokens[1];
+                                if ("msg.cdromdisconnect.locked".equalsIgnoreCase(msgId)) {
+                                    s_logger.info("Found that VM has a pending question that we need to answer programmatically, question id: " + question.getId()
+                                            + ". Message id : " + msgId + ". Message text : " + msgText
+                                            + ", for safe operation we will automatically decline it.");
+                                    vmMo.answerVM(question.getId(), "1");
+                                }
+                            }
+
+                            ChoiceOption choice = question.getChoice();
+                            if (choice != null) {
+                                for (ElementDescription info : choice.getChoiceInfo()) {
+                                    if (s_logger.isTraceEnabled()) {
+                                        s_logger.trace("Choice option key: " + info.getKey());
+                                        s_logger.trace("Choice option label: " + info.getLabel());
+                                    }
+                                }
+                            }
+                        }
+                    } catch (Throwable e) {
+                        s_logger.error("Unexpected exception: ", e);
+                    }
+
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException e) {
+                    }
+                }
+
+                s_logger.info("VM Question monitor stopped");
+            }
+        });
+
+        try {
+            _context.getService().unmountToolsInstaller(_mor);
+        } finally {
+            flags[0] = true;
+            future.cancel(true);
+        }
+    }
 
 	public void redoRegistration(ManagedObjectReference morHost) throws Exception {
 		String vmName = getVmName();