"""
-# Allow wildcard import in pylint: disable-msg=W0401
+# Allow wildcard import in pylint: disable=W0401
import os
import re
import errno
import pwd
+import time
import itertools
import select
import logging
from ganeti import errors
from ganeti import constants
from ganeti import compat
+from ganeti import pathutils
from ganeti.utils.algo import *
from ganeti.utils.filelock import *
from ganeti.utils.hash import *
from ganeti.utils.io import *
from ganeti.utils.log import *
+from ganeti.utils.lvm import *
from ganeti.utils.mlock import *
from ganeti.utils.nodesetup import *
from ganeti.utils.process import *
_VALID_SERVICE_NAME_RE = re.compile("^[-_.a-zA-Z0-9]{1,128}$")
-UUID_RE = re.compile('^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-'
- '[a-f0-9]{4}-[a-f0-9]{12}$')
+UUID_RE = re.compile(constants.UUID_REGEX)
def ForceDictType(target, key_types, allowed_values=None):
pass
elif not isinstance(target[key], basestring):
if isinstance(target[key], bool) and not target[key]:
- target[key] = ''
+ target[key] = ""
else:
msg = "'%s' (value %s) is not a valid string" % (key, target[key])
raise errors.TypeEnforcementError(msg)
return name
+def _ComputeMissingKeys(key_path, options, defaults):
+ """Helper functions to compute which keys a invalid.
+
+ @param key_path: The current key path (if any)
+ @param options: The user provided options
+ @param defaults: The default dictionary
+ @return: A list of invalid keys
+
+ """
+ defaults_keys = frozenset(defaults.keys())
+ invalid = []
+ for key, value in options.items():
+ if key_path:
+ new_path = "%s/%s" % (key_path, key)
+ else:
+ new_path = key
+
+ if key not in defaults_keys:
+ invalid.append(new_path)
+ elif isinstance(value, dict):
+ invalid.extend(_ComputeMissingKeys(new_path, value, defaults[key]))
+
+ return invalid
+
+
+def VerifyDictOptions(options, defaults):
+ """Verify a dict has only keys set which also are in the defaults dict.
+
+ @param options: The user provided options
+ @param defaults: The default dictionary
+ @raise error.OpPrereqError: If one of the keys is not supported
+
+ """
+ invalid = _ComputeMissingKeys("", options, defaults)
+
+ if invalid:
+ raise errors.OpPrereqError("Provided option keys not supported: %s" %
+ CommaJoin(invalid), errors.ECODE_INVAL)
+
+
def ListVolumeGroups():
"""List volume groups and their size
return cpu_list
+def ParseMultiCpuMask(cpu_mask):
+ """Parse a multiple CPU mask definition and return the list of CPU IDs.
+
+ CPU mask format: colon-separated list of comma-separated list of CPU IDs
+ or dash-separated ID ranges, with optional "all" as CPU value
+ Example: "0-2,5:all:1,5,6:2" -> [ [ 0,1,2,5 ], [ -1 ], [ 1, 5, 6 ], [ 2 ] ]
+
+ @type cpu_mask: str
+ @param cpu_mask: multiple CPU mask definition
+ @rtype: list of lists of int
+ @return: list of lists of CPU IDs
+
+ """
+ if not cpu_mask:
+ return []
+ cpu_list = []
+ for range_def in cpu_mask.split(constants.CPU_PINNING_SEP):
+ if range_def == constants.CPU_PINNING_ALL:
+ cpu_list.append([constants.CPU_PINNING_ALL_VAL, ])
+ else:
+ # Uniquify and sort the list before adding
+ cpu_list.append(sorted(set(ParseCpuMask(range_def))))
+
+ return cpu_list
+
+
def GetHomeDir(user, default=None):
"""Try to get the homedir of the given user.
The user can be passed either as a string (denoting the name) or as
an integer (denoting the user id). If the user is not found, the
- 'default' argument is returned, which defaults to None.
+ C{default} argument is returned, which defaults to C{None}.
"""
try:
"""Check for and start daemon if not alive.
"""
- result = RunCmd([constants.DAEMON_UTIL, "check-and-start", name])
+ result = RunCmd([pathutils.DAEMON_UTIL, "check-and-start", name])
if result.failed:
logging.error("Can't start daemon '%s', failure %s, output: %s",
name, result.fail_reason, result.output)
"""Stop daemon
"""
- result = RunCmd([constants.DAEMON_UTIL, "stop", name])
+ result = RunCmd([pathutils.DAEMON_UTIL, "stop", name])
if result.failed:
logging.error("Can't stop daemon '%s', failure %s, output: %s",
name, result.fail_reason, result.output)
return True
-def CheckVolumeGroupSize(vglist, vgname, minsize):
- """Checks if the volume group list is valid.
-
- The function will check if a given volume group is in the list of
- volume groups and has a minimum size.
-
- @type vglist: dict
- @param vglist: dictionary of volume group names and their size
- @type vgname: str
- @param vgname: the volume group we should check
- @type minsize: int
- @param minsize: the minimum size we accept
- @rtype: None or str
- @return: None for success, otherwise the error message
-
- """
- vgsize = vglist.get(vgname, None)
- if vgsize is None:
- return "volume group '%s' missing" % vgname
- elif vgsize < minsize:
- return ("volume group '%s' too small (%s MiB required, %d MiB found)" %
- (vgname, minsize, vgsize))
- return None
-
-
def SplitTime(value):
"""Splits time as floating point number into a tuple.
"""
def wrap(fn):
def sig_function(*args, **kwargs):
- assert 'signal_handlers' not in kwargs or \
- kwargs['signal_handlers'] is None or \
- isinstance(kwargs['signal_handlers'], dict), \
+ assert "signal_handlers" not in kwargs or \
+ kwargs["signal_handlers"] is None or \
+ isinstance(kwargs["signal_handlers"], dict), \
"Wrong signal_handlers parameter in original function call"
- if 'signal_handlers' in kwargs and kwargs['signal_handlers'] is not None:
- signal_handlers = kwargs['signal_handlers']
+ if "signal_handlers" in kwargs and kwargs["signal_handlers"] is not None:
+ signal_handlers = kwargs["signal_handlers"]
else:
signal_handlers = {}
- kwargs['signal_handlers'] = signal_handlers
+ kwargs["signal_handlers"] = signal_handlers
sighandler = SignalHandler(signums)
try:
for sig in signums:
return wrap
+def TimeoutExpired(epoch, timeout, _time_fn=time.time):
+ """Checks whether a timeout has expired.
+
+ """
+ return _time_fn() > (epoch + timeout)
+
+
class SignalWakeupFd(object):
try:
# This is only supported in Python 2.5 and above (some distributions
_set_wakeup_fd_fn = signal.set_wakeup_fd
except AttributeError:
# Not supported
- def _SetWakeupFd(self, _): # pylint: disable-msg=R0201
+
+ def _SetWakeupFd(self, _): # pylint: disable=R0201
return -1
else:
+
def _SetWakeupFd(self, fd):
return self._set_wakeup_fd_fn(fd)