From bbcf7ad022e5b0e8fd247175ef9cb98f1f6ca78f Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Mon, 22 Mar 2010 15:49:23 +0100 Subject: [PATCH] Extend the hypervisor API with name-only shutdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: Iustin Pop <iustin@google.com> Reviewed-by: RenΓ© Nussbaumer <rn@google.com> --- lib/hypervisor/hv_base.py | 6 +++++- lib/hypervisor/hv_chroot.py | 7 +++++-- lib/hypervisor/hv_fake.py | 18 ++++++++++-------- lib/hypervisor/hv_kvm.py | 19 +++++++++++++------ lib/hypervisor/hv_xen.py | 13 +++++++------ 5 files changed, 40 insertions(+), 23 deletions(-) diff --git a/lib/hypervisor/hv_base.py b/lib/hypervisor/hv_base.py index db8bcb49a..af7aa9575 100644 --- a/lib/hypervisor/hv_base.py +++ b/lib/hypervisor/hv_base.py @@ -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 diff --git a/lib/hypervisor/hv_chroot.py b/lib/hypervisor/hv_chroot.py index cf40c5936..36b37a8eb 100644 --- a/lib/hypervisor/hv_chroot.py +++ b/lib/hypervisor/hv_chroot.py @@ -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 diff --git a/lib/hypervisor/hv_fake.py b/lib/hypervisor/hv_fake.py index d607d0de8..cea05d61e 100644 --- a/lib/hypervisor/hv_fake.py +++ b/lib/hypervisor/hv_fake.py @@ -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) diff --git a/lib/hypervisor/hv_kvm.py b/lib/hypervisor/hv_kvm.py index 2035e2d6a..b9f20f3dd 100644 --- a/lib/hypervisor/hv_kvm.py +++ b/lib/hypervisor/hv_kvm.py @@ -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 diff --git a/lib/hypervisor/hv_xen.py b/lib/hypervisor/hv_xen.py index e16c03080..575e3b940 100644 --- a/lib/hypervisor/hv_xen.py +++ b/lib/hypervisor/hv_xen.py @@ -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. -- GitLab