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 10:15:07 UTC

git commit: updated refs/heads/master to a70bbdb

Updated Branches:
  refs/heads/master 951336c3e -> a70bbdb13


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 programmatically 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/a70bbdb1
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/a70bbdb1
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/a70bbdb1

Branch: refs/heads/master
Commit: a70bbdb139b4b1b1c8dd8f9a258b4b37b5698290
Parents: 951336c
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 09:11:54 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/a70bbdb1/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 784c031..a4469f0 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 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 {
@@ -2041,7 +2126,7 @@ public class VirtualMachineMO extends BaseMO {
 			}
 	    }
 	    	
-	    return detachedDiskFiles; 
+	    return detachedDiskFiles;
 	}
 	
 	public List<VirtualDevice> getAllDeviceList() throws Exception {
@@ -2066,7 +2151,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;
 			}
@@ -2294,8 +2379,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();