Xen handle domain shutdown
authorJose A. Lopes <jabolopes@google.com>
Mon, 2 Dec 2013 11:41:33 +0000 (12:41 +0100)
committerJose A. Lopes <jabolopes@google.com>
Thu, 5 Dec 2013 09:03:30 +0000 (10:03 +0100)
Update Xen backend to properly recognize when a domain has been
shutdown by the user and to properly cleanup a shutdown domain when
Ganeti requests Xen to stop this domain.

Partial cherry-pick from 9d22cc90609e3ee8f0f2b34b793a3daced3c0e61

Signed-off-by: Jose A. Lopes <jabolopes@google.com>
Reviewed-by: Michele Tartara <mtartara@google.com>

lib/hypervisor/hv_xen.py

index 909ef5f..af2f8fb 100644 (file)
@@ -165,6 +165,15 @@ def _GetXmList(fn, include_node, _timeout=5):
   return _ParseXmList(lines, include_node)
 
 
+def _IsInstanceRunning(instance_info):
+  return instance_info == "r-----" \
+      or instance_info == "-b----"
+
+
+def _IsInstanceShutdown(instance_info):
+  return instance_info == "---s--"
+
+
 def _ParseNodeInfo(info):
   """Return information about the node.
 
@@ -510,17 +519,58 @@ class XenHypervisor(hv_base.BaseHypervisor):
 
     return self._StopInstance(name, force)
 
+  def _ShutdownInstance(self, name):
+    """Shutdown an instance if the instance is running.
+
+    @type name: string
+    @param name: name of the instance to stop
+
+    The '-w' flag waits for shutdown to complete which avoids the need
+    to poll in the case where we want to destroy the domain
+    immediately after shutdown.
+
+    """
+    instance_info = self.GetInstanceInfo(name)
+
+    if instance_info is None or _IsInstanceShutdown(instance_info[4]):
+      logging.info("Failed to shutdown instance %s, not running", name)
+      return None
+
+    return self._RunXen(["shutdown", "-w", name])
+
+  def _DestroyInstance(self, name):
+    """Destroy an instance if the instance if the instance exists.
+
+    @type name: string
+    @param name: name of the instance to destroy
+
+    """
+    instance_info = self.GetInstanceInfo(name)
+
+    if instance_info is None:
+      logging.info("Failed to destroy instance %s, does not exist", name)
+      return None
+
+    return self._RunXen(["destroy", name])
+
   def _StopInstance(self, name, force):
     """Stop an instance.
 
+    @type name: string
+    @param name: name of the instance to destroy
+
+    @type force: boolean
+    @param force: whether to do a "hard" stop (destroy)
+
     """
     if force:
-      action = "destroy"
+      result = self._DestroyInstance(name)
     else:
-      action = "shutdown"
+      self._ShutdownInstance(name)
+      result = self._DestroyInstance(name)
 
-    result = self._RunXen([action, name])
-    if result.failed:
+    if result is not None and result.failed and \
+          self.GetInstanceInfo(name) is not None:
       raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
                                    (name, result.fail_reason, result.output))