#
#
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 Google Inc.
+# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2012, 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
# must be afile
_FILE_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
- os.path.isfile, "not found or not a file")
+ os.path.isfile, "not found or not a file")
# must be a directory
_DIR_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
- os.path.isdir, "not found or not a directory")
+ os.path.isdir, "not found or not a directory")
# CPU mask must be well-formed
# TODO: implement node level check for the CPU mask
_NET_PORT_CHECK = (lambda x: 0 < x < 65535, "invalid port number",
None, None)
+# Check that an integer is non negative
+_NONNEGATIVE_INT_CHECK = (lambda x: x >= 0, "cannot be negative", None, None)
+
# nice wrappers for users
REQ_FILE_CHECK = (True, ) + _FILE_CHECK
OPT_FILE_CHECK = (False, ) + _FILE_CHECK
OPT_CPU_MASK_CHECK = (False, ) + _CPU_MASK_CHECK
REQ_MULTI_CPU_MASK_CHECK = (True, ) + _MULTI_CPU_MASK_CHECK
OPT_MULTI_CPU_MASK_CHECK = (False, ) + _MULTI_CPU_MASK_CHECK
+REQ_NONNEGATIVE_INT_CHECK = (True, ) + _NONNEGATIVE_INT_CHECK
+OPT_NONNEGATIVE_INT_CHECK = (False, ) + _NONNEGATIVE_INT_CHECK
# no checks at all
NO_CHECK = (False, None, None, None, None)
"""
PARAMETERS = {}
ANCILLARY_FILES = []
+ ANCILLARY_FILES_OPT = []
CAN_MIGRATE = False
- def __init__(self):
- pass
-
def StartInstance(self, instance, block_devices, startup_paused):
"""Start an instance."""
raise NotImplementedError
"""Reboot an instance."""
raise NotImplementedError
- def ListInstances(self):
+ def ListInstances(self, hvparams=None):
"""Get the list of running instances."""
raise NotImplementedError
"""Return a list of ancillary files to be copied to all nodes as ancillary
configuration files.
- @rtype: list of strings
- @return: list of absolute paths of files to ship cluster-wide
+ @rtype: (list of absolute paths, list of absolute paths)
+ @return: (all files, optional files)
"""
# By default we return a member variable, so that if an hypervisor has just
# a static list of files it doesn't have to override this function.
- return cls.ANCILLARY_FILES
+ assert set(cls.ANCILLARY_FILES).issuperset(cls.ANCILLARY_FILES_OPT), \
+ "Optional ancillary files must be a subset of ancillary files"
- def Verify(self):
+ return (cls.ANCILLARY_FILES, cls.ANCILLARY_FILES_OPT)
+
+ def Verify(self, hvparams=None):
"""Verify the hypervisor.
+ @type hvparams: dict of strings
+ @param hvparams: hypervisor parameters to be verified against
+
+ @return: Problem description if something is wrong, C{None} otherwise
+
"""
raise NotImplementedError
"""
pass
+ 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
+
+ """
+ raise NotImplementedError
+
def FinalizeMigrationDst(self, instance, info, success):
"""Finalize the instance migration on the target node.
"""
raise NotImplementedError
+ def _InstanceStartupMemory(self, instance):
+ """Get the correct startup memory for an instance
+
+ This function calculates how much memory an instance should be started
+ with, making sure it's a value between the minimum and the maximum memory,
+ but also trying to use no more than the current free memory on the node.
+
+ @type instance: L{objects.Instance}
+ @param instance: the instance that is being started
+ @rtype: integer
+ @return: memory the instance should be started with
+
+ """
+ free_memory = self.GetNodeInfo()["memory_free"]
+ max_start_mem = min(instance.beparams[constants.BE_MAXMEM], free_memory)
+ start_mem = max(instance.beparams[constants.BE_MINMEM], max_start_mem)
+ return start_mem
+
@classmethod
def CheckParameterSyntax(cls, hvparams):
"""Check the given parameters for validity.
result = utils.RunCmd(["reboot", "-n", "-f"])
if not result:
logging.error("Can't run shutdown: %s", result.output)
+
+ @staticmethod
+ def _FormatVerifyResults(msgs):
+ """Formats the verification results, given a list of errors.
+
+ @param msgs: list of errors, possibly empty
+ @return: overall problem description if something is wrong,
+ C{None} otherwise
+
+ """
+ if msgs:
+ return "; ".join(msgs)
+ else:
+ return None