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):
@type hvparams: dict of strings
@param hvparams: hvparams to be used with this instance
@rtype: (string, string, int, int, HvInstanceState, int)
@return: tuple (name, id, memory, vcpus, state, times)
"""
......@@ -241,7 +242,9 @@ class BaseHypervisor(object):
@type hvparams: dict of strings
@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
......
......@@ -84,8 +84,8 @@ def _CreateConfigCpus(cpu_mask):
def _RunInstanceList(fn, instance_list_errors):
"""Helper function for L{_GetInstanceList} to retrieve the list of instances
from xen.
"""Helper function for L{_GetAllInstanceList} to retrieve the list
of instances from xen.
@type fn: callable
@param fn: Function to query xen for the list of instances
......@@ -131,6 +131,7 @@ def _ParseInstanceList(lines, include_node):
data[1] = int(data[1])
data[2] = int(data[2])
data[3] = int(data[3])
data[4] = _XenToHypervisorInstanceState(data[4])
data[5] = float(data[5])
except (TypeError, ValueError), err:
raise errors.HypervisorError("Can't parse instance list,"
......@@ -143,8 +144,8 @@ def _ParseInstanceList(lines, include_node):
return result
def _GetInstanceList(fn, include_node, _timeout=5):
"""Return the list of running instances.
def _GetAllInstanceList(fn, include_node, _timeout=5):
"""Return the list of instances including running and shutdown.
See L{_RunInstanceList} and L{_ParseInstanceList} for parameter details.
......@@ -167,6 +168,46 @@ def _GetInstanceList(fn, include_node, _timeout=5):
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):
"""Return information about the node.
......@@ -514,14 +555,14 @@ class XenHypervisor(hv_base.BaseHypervisor):
return new_filename
def _GetInstanceList(self, include_node, hvparams):
"""Wrapper around module level L{_GetInstanceList}.
"""Wrapper around module level L{_GetAllInstanceList}.
@type hvparams: dict of strings
@param hvparams: hypervisor parameters to be used on this node
"""
return _GetInstanceList(lambda: self._RunXen(["list"], hvparams),
include_node)
return _GetAllInstanceList(lambda: self._RunXen(["list"], hvparams),
include_node)
def ListInstances(self, hvparams=None):
"""Get the list of running instances.
......@@ -555,7 +596,9 @@ class XenHypervisor(hv_base.BaseHypervisor):
@type hvparams: dict of strings
@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)
......@@ -607,6 +650,28 @@ class XenHypervisor(hv_base.BaseHypervisor):
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):
"""Stop an instance.
......@@ -618,15 +683,17 @@ class XenHypervisor(hv_base.BaseHypervisor):
@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:
action = "destroy"
self._DestroyInstance(name, hvparams)
else:
action = "shutdown"
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))
self._ShutdownInstance(name, hvparams, instance_info[4])
self._DestroyInstance(name, hvparams)
# Remove configuration file if stopping/starting instance was successful
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