Commit 9d22cc90 authored by Jose A. Lopes's avatar Jose A. Lopes

Xen handle domain shutdown

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.
Signed-off-by: default avatarJose A. Lopes <jabolopes@google.com>
Reviewed-by: default avatarHrvoje Ribicic <riba@google.com>
parent 9158a1dd
...@@ -231,6 +231,7 @@ class BaseHypervisor(object): ...@@ -231,6 +231,7 @@ class BaseHypervisor(object):
@type hvparams: dict of strings @type hvparams: dict of strings
@param hvparams: hvparams to be used with this instance @param hvparams: hvparams to be used with this instance
@rtype: (string, string, int, int, HvInstanceState, int)
@return: tuple (name, id, memory, vcpus, state, times) @return: tuple (name, id, memory, vcpus, state, times)
""" """
...@@ -241,7 +242,9 @@ class BaseHypervisor(object): ...@@ -241,7 +242,9 @@ class BaseHypervisor(object):
@type hvparams: dict of strings @type hvparams: dict of strings
@param hvparams: hypervisor parameter @param hvparams: hypervisor parameter
@return: list of tuples (name, id, memory, vcpus, stat, times)
@rtype: (string, string, int, int, HvInstanceState, int)
@return: list of tuples (name, id, memory, vcpus, state, times)
""" """
raise NotImplementedError raise NotImplementedError
......
...@@ -84,8 +84,8 @@ def _CreateConfigCpus(cpu_mask): ...@@ -84,8 +84,8 @@ def _CreateConfigCpus(cpu_mask):
def _RunInstanceList(fn, instance_list_errors): def _RunInstanceList(fn, instance_list_errors):
"""Helper function for L{_GetInstanceList} to retrieve the list of instances """Helper function for L{_GetAllInstanceList} to retrieve the list
from xen. of instances from xen.
@type fn: callable @type fn: callable
@param fn: Function to query xen for the list of instances @param fn: Function to query xen for the list of instances
...@@ -131,6 +131,7 @@ def _ParseInstanceList(lines, include_node): ...@@ -131,6 +131,7 @@ def _ParseInstanceList(lines, include_node):
data[1] = int(data[1]) data[1] = int(data[1])
data[2] = int(data[2]) data[2] = int(data[2])
data[3] = int(data[3]) data[3] = int(data[3])
data[4] = _XenToHypervisorInstanceState(data[4])
data[5] = float(data[5]) data[5] = float(data[5])
except (TypeError, ValueError), err: except (TypeError, ValueError), err:
raise errors.HypervisorError("Can't parse instance list," raise errors.HypervisorError("Can't parse instance list,"
...@@ -143,8 +144,8 @@ def _ParseInstanceList(lines, include_node): ...@@ -143,8 +144,8 @@ def _ParseInstanceList(lines, include_node):
return result return result
def _GetInstanceList(fn, include_node, _timeout=5): def _GetAllInstanceList(fn, include_node, _timeout=5):
"""Return the list of running instances. """Return the list of instances including running and shutdown.
See L{_RunInstanceList} and L{_ParseInstanceList} for parameter details. See L{_RunInstanceList} and L{_ParseInstanceList} for parameter details.
...@@ -167,6 +168,46 @@ def _GetInstanceList(fn, include_node, _timeout=5): ...@@ -167,6 +168,46 @@ def _GetInstanceList(fn, include_node, _timeout=5):
return _ParseInstanceList(lines, include_node) return _ParseInstanceList(lines, include_node)
def _IsInstanceRunning(instance_info):
return instance_info == "r-----" \
or instance_info == "-b----"
def _IsInstanceShutdown(instance_info):
return instance_info == "---s--"
def _XenToHypervisorInstanceState(instance_info):
if _IsInstanceRunning(instance_info):
return hv_base.HvInstanceState.RUNNING
elif _IsInstanceShutdown(instance_info):
return hv_base.HvInstanceState.SHUTDOWN
else:
raise errors.HypervisorError("hv_xen._XenToHypervisorInstanceState:"
" unhandled Xen instance state '%s'" %
instance_info)
def _GetRunningInstanceList(fn, include_node, _timeout=5):
"""Return the list of running instances.
See L{_GetAllInstanceList} for parameter details.
"""
instances = _GetAllInstanceList(fn, include_node, _timeout)
return [i for i in instances if hv_base.HvInstanceState.IsRunning(i[4])]
def _GetShutdownInstanceList(fn, include_node, _timeout=5):
"""Return the list of shutdown instances.
See L{_GetAllInstanceList} for parameter details.
"""
instances = _GetAllInstanceList(fn, include_node, _timeout)
return [i for i in instances if hv_base.HvInstanceState.IsShutdown(i[4])]
def _ParseNodeInfo(info): def _ParseNodeInfo(info):
"""Return information about the node. """Return information about the node.
...@@ -514,14 +555,14 @@ class XenHypervisor(hv_base.BaseHypervisor): ...@@ -514,14 +555,14 @@ class XenHypervisor(hv_base.BaseHypervisor):
return new_filename return new_filename
def _GetInstanceList(self, include_node, hvparams): def _GetInstanceList(self, include_node, hvparams):
"""Wrapper around module level L{_GetInstanceList}. """Wrapper around module level L{_GetAllInstanceList}.
@type hvparams: dict of strings @type hvparams: dict of strings
@param hvparams: hypervisor parameters to be used on this node @param hvparams: hypervisor parameters to be used on this node
""" """
return _GetInstanceList(lambda: self._RunXen(["list"], hvparams), return _GetAllInstanceList(lambda: self._RunXen(["list"], hvparams),
include_node) include_node)
def ListInstances(self, hvparams=None): def ListInstances(self, hvparams=None):
"""Get the list of running instances. """Get the list of running instances.
...@@ -555,7 +596,9 @@ class XenHypervisor(hv_base.BaseHypervisor): ...@@ -555,7 +596,9 @@ class XenHypervisor(hv_base.BaseHypervisor):
@type hvparams: dict of strings @type hvparams: dict of strings
@param hvparams: hypervisor parameters @param hvparams: hypervisor parameters
@return: list of tuples (name, id, memory, vcpus, stat, times)
@rtype: (string, string, int, int, HypervisorInstanceState, int)
@return: list of tuples (name, id, memory, vcpus, state, times)
""" """
return self._GetInstanceList(False, hvparams) return self._GetInstanceList(False, hvparams)
...@@ -607,6 +650,28 @@ class XenHypervisor(hv_base.BaseHypervisor): ...@@ -607,6 +650,28 @@ class XenHypervisor(hv_base.BaseHypervisor):
return self._StopInstance(name, force, instance.hvparams) return self._StopInstance(name, force, instance.hvparams)
def _ShutdownInstance(self, name, hvparams, instance_info):
# The '-w' flag waits for shutdown to complete
#
# In the case of shutdown, we want to wait until the shutdown
# process is complete because then we want to also destroy the
# domain, and we do not want to destroy the domain while it is
# shutting down.
if hv_base.HvInstanceState.IsShutdown(instance_info):
logging.info("Instance '%s' is already shutdown, skipping shutdown"
" command", name)
else:
result = self._RunXen(["shutdown", "-w", name], hvparams)
if result.failed:
raise errors.HypervisorError("Failed to shutdown instance %s: %s, %s" %
(name, result.fail_reason, result.output))
def _DestroyInstance(self, name, hvparams):
result = self._RunXen(["destroy", name], hvparams)
if result.failed:
raise errors.HypervisorError("Failed to destroy instance %s: %s, %s" %
(name, result.fail_reason, result.output))
def _StopInstance(self, name, force, hvparams): def _StopInstance(self, name, force, hvparams):
"""Stop an instance. """Stop an instance.
...@@ -618,15 +683,17 @@ class XenHypervisor(hv_base.BaseHypervisor): ...@@ -618,15 +683,17 @@ class XenHypervisor(hv_base.BaseHypervisor):
@param hvparams: hypervisor parameters of the instance @param hvparams: hypervisor parameters of the instance
""" """
instance_info = self.GetInstanceInfo(name, hvparams=hvparams)
if instance_info is None:
raise errors.HypervisorError("Failed to shutdown instance %s,"
" not running" % name)
if force: if force:
action = "destroy" self._DestroyInstance(name, hvparams)
else: else:
action = "shutdown" self._ShutdownInstance(name, hvparams, instance_info[4])
self._DestroyInstance(name, hvparams)
result = self._RunXen([action, name], hvparams)
if result.failed:
raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
(name, result.fail_reason, result.output))
# Remove configuration file if stopping/starting instance was successful # Remove configuration file if stopping/starting instance was successful
self._RemoveConfigFile(name) self._RemoveConfigFile(name)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment