Commit bbcf7ad0 authored by Iustin Pop's avatar Iustin Pop
Browse files

Extend the hypervisor API with name-only shutdown



Currently the ShutdownInstance method of the hypervisors takes a full
instance object. However, when doing instance shutdowns from the node
only, we don't have a full object, just the name.

To handle this use case, we add a new ‘name’ argument to the method,
which makes the shutdown not use/rely on the ‘instance’ argument. The
KVM and fake hypervisors need a little bit of work, otherwise the change
is straightforward.
Signed-off-by: default avatarIustin Pop <iustin@google.com>
Reviewed-by: default avatarRené Nussbaumer <rn@google.com>
parent 4f7a6a10
......@@ -113,7 +113,7 @@ class BaseHypervisor(object):
"""Start an instance."""
raise NotImplementedError
def StopInstance(self, instance, force=False, retry=False):
def StopInstance(self, instance, force=False, retry=False, name=None):
"""Stop an instance
@type instance: L{objects.Instance}
......@@ -122,6 +122,10 @@ class BaseHypervisor(object):
@param force: whether to do a "hard" stop (destroy)
@type retry: boolean
@param retry: whether this is just a retry call
@type name: string or None
@param name: if this parameter is passed, the the instance object
should not be used (will be passed as None), and the shutdown
must be done by name only
"""
raise NotImplementedError
......
......@@ -177,7 +177,7 @@ class ChrootManager(hv_base.BaseHypervisor):
raise HypervisorError("Can't run the chroot start script: %s" %
result.output)
def StopInstance(self, instance, force=False, retry=False):
def StopInstance(self, instance, force=False, retry=False, name=None):
"""Stop an instance.
This method has complicated cleanup tests, as we must:
......@@ -186,7 +186,10 @@ class ChrootManager(hv_base.BaseHypervisor):
- finally unmount the instance dir
"""
root_dir = self._InstanceDir(instance.name)
if name is None:
name = instance.name
root_dir = self._InstanceDir(name)
if not os.path.exists(root_dir) or not self._IsDirLive(root_dir):
return
......
......@@ -136,13 +136,13 @@ class FakeHypervisor(hv_base.BaseHypervisor):
finally:
fh.close()
def _MarkDown(self, instance):
def _MarkDown(self, instance_name):
"""Mark the instance as running.
This does no checks, which should be done by its callers.
"""
file_name = self._InstanceFile(instance.name)
file_name = self._InstanceFile(instance_name)
utils.RemoveFile(file_name)
def StartInstance(self, instance, block_devices):
......@@ -162,17 +162,19 @@ class FakeHypervisor(hv_base.BaseHypervisor):
raise errors.HypervisorError("Failed to start instance %s: %s" %
(instance.name, err))
def StopInstance(self, instance, force=False, retry=False):
def StopInstance(self, instance, force=False, retry=False, name=None):
"""Stop an instance.
For the fake hypervisor, this just removes the file in the base
dir, if it exist, otherwise we raise an exception.
"""
if not self._IsAlive(instance.name):
if name is None:
name = instance.name
if not self._IsAlive(name):
raise errors.HypervisorError("Failed to stop instance %s: %s" %
(instance.name, "not running"))
self._MarkDown(instance)
(name, "not running"))
self._MarkDown(name)
def RebootInstance(self, instance):
"""Reboot an instance.
......@@ -252,7 +254,7 @@ class FakeHypervisor(hv_base.BaseHypervisor):
logging.debug("Fake hypervisor migrating %s to %s (live=%s)",
instance, target, live)
self._MarkDown(instance)
self._MarkDown(instance.name)
def FinalizeMigration(self, instance, info, success):
"""Finalize an instance migration.
......@@ -267,4 +269,4 @@ class FakeHypervisor(hv_base.BaseHypervisor):
self._MarkUp(instance)
else:
# ensure it's down
self._MarkDown(instance)
self._MarkDown(instance.name)
......@@ -613,19 +613,26 @@ class KVMHypervisor(hv_base.BaseHypervisor):
return result
def StopInstance(self, instance, force=False, retry=False):
def StopInstance(self, instance, force=False, retry=False, name=None):
"""Stop an instance.
"""
pidfile, pid, alive = self._InstancePidAlive(instance.name)
if name is not None and not force:
raise errors.HypervisorError("Cannot shutdown cleanly by name only")
if name is None:
name = instance.name
acpi = instance.hvparams[constants.HV_ACPI]
else:
acpi = False
pidfile, pid, alive = self._InstancePidAlive(name)
if pid > 0 and alive:
if force or not instance.hvparams[constants.HV_ACPI]:
if force or not acpi:
utils.KillProcess(pid)
else:
self._CallMonitorCommand(instance.name, 'system_powerdown')
self._CallMonitorCommand(name, 'system_powerdown')
if not self._InstancePidAlive(instance.name)[2]:
self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
if not self._InstancePidAlive(name)[2]:
self._RemoveInstanceRuntimeFiles(pidfile, name)
return True
else:
return False
......
......@@ -189,21 +189,22 @@ class XenHypervisor(hv_base.BaseHypervisor):
(instance.name, result.fail_reason,
result.output))
def StopInstance(self, instance, force=False, retry=False):
def StopInstance(self, instance, force=False, retry=False, name=None):
"""Stop an instance.
"""
self._RemoveConfigFile(instance.name)
if name is None:
name = instance.name
self._RemoveConfigFile(name)
if force:
command = ["xm", "destroy", instance.name]
command = ["xm", "destroy", name]
else:
command = ["xm", "shutdown", instance.name]
command = ["xm", "shutdown", name]
result = utils.RunCmd(command)
if result.failed:
raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
(instance.name, result.fail_reason,
result.output))
(name, result.fail_reason, result.output))
def RebootInstance(self, instance):
"""Reboot an instance.
......
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