#
#
-# 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
from ganeti import constants
from ganeti import errors
from ganeti import objects
+from ganeti import pathutils
from ganeti.hypervisor import hv_base
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)
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)
"""
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.
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()
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))
"""
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()
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.
"""
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()
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
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)