X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/d0c8c01d4fd36ed2f6870fcd3512022b11a3cd7c..4f2f98f170abda39b7075eaf61755bcec663f47a:/lib/hypervisor/hv_fake.py diff --git a/lib/hypervisor/hv_fake.py b/lib/hypervisor/hv_fake.py index 441e44b..b5abf7f 100644 --- a/lib/hypervisor/hv_fake.py +++ b/lib/hypervisor/hv_fake.py @@ -1,7 +1,7 @@ # # -# Copyright (C) 2006, 2007, 2008 Google Inc. +# Copyright (C) 2006, 2007, 2008, 2013 Google Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -31,6 +31,7 @@ from ganeti import utils from ganeti import constants from ganeti import errors from ganeti import objects +from ganeti import pathutils from ganeti.hypervisor import hv_base @@ -41,24 +42,31 @@ class FakeHypervisor(hv_base.BaseHypervisor): a real virtualisation software installed. """ + PARAMETERS = { + constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK, + } + CAN_MIGRATE = True - _ROOT_DIR = constants.RUN_GANETI_DIR + "/fake-hypervisor" + _ROOT_DIR = pathutils.RUN_DIR + "/fake-hypervisor" def __init__(self): hv_base.BaseHypervisor.__init__(self) utils.EnsureDirs([(self._ROOT_DIR, constants.RUN_DIRS_MODE)]) - def ListInstances(self): + def ListInstances(self, hvparams=None): """Get the list of running instances. """ return os.listdir(self._ROOT_DIR) - def GetInstanceInfo(self, instance_name): + def GetInstanceInfo(self, instance_name, hvparams=None): """Get instance properties. + @type instance_name: string @param instance_name: the instance name + @type hvparams: dict of strings + @param hvparams: hvparams to be used with this instance @return: tuple of (name, id, memory, vcpus, stat, times) @@ -81,9 +89,11 @@ class FakeHypervisor(hv_base.BaseHypervisor): raise errors.HypervisorError("Failed to list instance %s: %s" % (instance_name, err)) - def GetAllInstancesInfo(self): + def GetAllInstancesInfo(self, hvparams=None): """Get properties of all instances. + @type hvparams: dict of strings + @param hvparams: hypervisor parameter @return: list of tuples (name, id, memory, vcpus, stat, times) """ @@ -123,7 +133,7 @@ class FakeHypervisor(hv_base.BaseHypervisor): file_name = self._InstanceFile(instance_name) return os.path.exists(file_name) - def _MarkUp(self, instance): + def _MarkUp(self, instance, memory): """Mark the instance as running. This does no checks, which should be done by its callers. @@ -133,7 +143,7 @@ class FakeHypervisor(hv_base.BaseHypervisor): fh = file(file_name, "w") try: fh.write("0\n%d\n%d\n" % - (instance.beparams[constants.BE_MEMORY], + (memory, instance.beparams[constants.BE_VCPUS])) finally: fh.close() @@ -159,7 +169,7 @@ class FakeHypervisor(hv_base.BaseHypervisor): raise errors.HypervisorError("Failed to start instance %s: %s" % (instance.name, "already running")) try: - self._MarkUp(instance) + self._MarkUp(instance, self._InstanceStartupMemory(instance)) except IOError, err: raise errors.HypervisorError("Failed to start instance %s: %s" % (instance.name, err)) @@ -186,15 +196,28 @@ class FakeHypervisor(hv_base.BaseHypervisor): """ return - def GetNodeInfo(self): - """Return information about the node. + def BalloonInstanceMemory(self, instance, mem): + """Balloon an instance memory to a certain value. + + @type instance: L{objects.Instance} + @param instance: instance to be accepted + @type mem: int + @param mem: actual memory size to use for instance runtime - This is just a wrapper over the base GetLinuxNodeInfo method. + """ + if not self._IsAlive(instance.name): + raise errors.HypervisorError("Failed to balloon memory for %s: %s" % + (instance.name, "not running")) + try: + self._MarkUp(instance, mem) + except EnvironmentError, err: + raise errors.HypervisorError("Failed to balloon memory for %s: %s" % + (instance.name, utils.ErrnoOrStr(err))) + + def GetNodeInfo(self, hvparams=None): + """Return information about the node. - @return: a dict with the following keys (values in MiB): - - memory_total: the total memory size on the node - - memory_free: the available memory on the node for instances - - memory_dom0: the memory used by the node itself, if available + See L{BaseHypervisor.GetLinuxNodeInfo}. """ result = self.GetLinuxNodeInfo() @@ -205,7 +228,7 @@ class FakeHypervisor(hv_base.BaseHypervisor): return result @classmethod - def GetInstanceConsole(cls, instance, hvparams, beparams): + def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams): """Return information for connecting to the console of an instance. """ @@ -214,20 +237,31 @@ class FakeHypervisor(hv_base.BaseHypervisor): message=("Console not available for fake" " hypervisor")) - def Verify(self): + def Verify(self, hvparams=None): """Verify the hypervisor. For the fake hypervisor, it just checks the existence of the base dir. + @type hvparams: dict of strings + @param hvparams: hypervisor parameters to be verified against; not used + for fake hypervisors + + @return: Problem description if something is wrong, C{None} otherwise + """ - if not os.path.exists(self._ROOT_DIR): - return "The required directory '%s' does not exist." % self._ROOT_DIR + if os.path.exists(self._ROOT_DIR): + return None + else: + return "The required directory '%s' does not exist" % self._ROOT_DIR @classmethod - def PowercycleNode(cls): + def PowercycleNode(cls, hvparams=None): """Fake hypervisor powercycle, just a wrapper over Linux powercycle. + @type hvparams: dict of strings + @param hvparams: hypervisor params to be used on this node + """ cls.LinuxPowercycle() @@ -245,9 +279,11 @@ class FakeHypervisor(hv_base.BaseHypervisor): if self._IsAlive(instance.name): raise errors.HypervisorError("Can't accept instance, already running") - def MigrateInstance(self, instance, target, live): + def MigrateInstance(self, cluster_name, instance, target, live): """Migrate an instance. + @type cluster_name: string + @param cluster_name: name of the cluster @type instance: L{objects.Instance} @param instance: the instance to be migrated @type target: string @@ -259,19 +295,62 @@ class FakeHypervisor(hv_base.BaseHypervisor): logging.debug("Fake hypervisor migrating %s to %s (live=%s)", instance, target, live) - self._MarkDown(instance.name) - - def FinalizeMigration(self, instance, info, success): - """Finalize an instance migration. + def FinalizeMigrationDst(self, instance, info, success): + """Finalize the instance migration on the target node. For the fake hv, this just marks the instance up. @type instance: L{objects.Instance} @param instance: instance whose migration is being finalized + @type info: string/data (opaque) + @param info: migration information, from the source node + @type success: boolean + @param success: whether the migration was a success or a failure """ if success: - self._MarkUp(instance) + self._MarkUp(instance, self._InstanceStartupMemory(instance)) else: # ensure it's down self._MarkDown(instance.name) + + def PostMigrationCleanup(self, instance): + """Clean-up after a migration. + + To be executed on the source node. + + @type instance: L{objects.Instance} + @param instance: the instance that was migrated + + """ + pass + + def FinalizeMigrationSource(self, instance, success, live): + """Finalize the instance migration on the source node. + + @type instance: L{objects.Instance} + @param instance: the instance that was migrated + @type success: bool + @param success: whether the migration succeeded or not + @type live: bool + @param live: whether the user requested a live migration or not + + """ + # pylint: disable=W0613 + if success: + self._MarkDown(instance.name) + + def GetMigrationStatus(self, instance): + """Get the migration status + + The fake hypervisor migration always succeeds. + + @type instance: L{objects.Instance} + @param instance: the instance that is being migrated + @rtype: L{objects.MigrationStatus} + @return: the status of the current migration (one of + L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional + progress info that can be retrieved from the hypervisor + + """ + return objects.MigrationStatus(status=constants.HV_MIGRATION_COMPLETED)