示例#1
0
 def _pathTestHelper(self, path, result):
   if result:
     self.assert_(utils.IsNormAbsPath(path),
         msg="Path %s should result absolute and normalized" % path)
   else:
     self.assertFalse(utils.IsNormAbsPath(path),
         msg="Path %s should not result absolute and normalized" % path)
示例#2
0
def validate_vnc_parameters(hvparams):
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
    if vnc_bind_address:
      bound_to_addr = (netutils.IP4Address.IsValid(vnc_bind_address) or
                       netutils.IP6Address.IsValid(vnc_bind_address))
      is_interface = netutils.IsValidInterface(vnc_bind_address)
      is_path = utils.IsNormAbsPath(vnc_bind_address)
      if not bound_to_addr and not is_interface and not is_path:
        raise errors.HypervisorError("VNC: The %s parameter must be either"
                                     " a valid IP address, an interface name,"
                                     " or an absolute path" %
                                     constants.HV_VNC_BIND_ADDRESS)
    return True
示例#3
0
    def Validate(self):
        """Validates loaded configuration data.

    """
        if not self.get("name"):
            raise qa_error.Error("Cluster name is required")

        if not self.get("nodes"):
            raise qa_error.Error("Need at least one node")

        if not self.get("instances"):
            raise qa_error.Error("Need at least one instance")

        disks = self.GetDiskOptions()
        if disks is None:
            raise qa_error.Error("Config option 'disks' must exist")
        else:
            for d in disks:
                if d.get("size") is None or d.get("growth") is None:
                    raise qa_error.Error(
                        "Config options `size` and `growth` must exist"
                        " for all `disks` items")
        check = self.GetInstanceCheckScript()
        if check:
            try:
                os.stat(check)
            except EnvironmentError as err:
                raise qa_error.Error(
                    "Can't find instance check script '%s': %s" % (check, err))

        enabled_hv = frozenset(self.GetEnabledHypervisors())
        if not enabled_hv:
            raise qa_error.Error("No hypervisor is enabled")

        difference = enabled_hv - constants.HYPER_TYPES
        if difference:
            raise qa_error.Error("Unknown hypervisor(s) enabled: %s" %
                                 utils.CommaJoin(difference))

        (vc_master, vc_basedir) = self.GetVclusterSettings()
        if bool(vc_master) != bool(vc_basedir):
            raise qa_error.Error(
                "All or none of the config options '%s' and '%s'"
                " must be set" % (_VCLUSTER_MASTER_KEY, _VCLUSTER_BASEDIR_KEY))

        if vc_basedir and not utils.IsNormAbsPath(vc_basedir):
            raise qa_error.Error(
                "Path given in option '%s' must be absolute and"
                " normalized" % _VCLUSTER_BASEDIR_KEY)
    def testEntryOrder(self):
        paths = [(path[0], path[1]) for path in ensure_dirs.GetPaths()]

        # Directories for which permissions have been set
        seen = set()

        # Current directory (changes when an entry of type C{DIR} or C{QUEUE_DIR}
        # is encountered)
        current_dir = None

        for (path, pathtype) in paths:
            self.assertTrue(pathtype in ensure_dirs.ALL_TYPES)
            self.assertTrue(
                utils.IsNormAbsPath(path),
                msg=("Path '%s' is not absolute and/or normalized" % path))

            dirname = os.path.dirname(path)

            if pathtype == ensure_dirs.DIR:
                self.assertFalse(path in seen,
                                 msg=("Directory '%s' was seen before" % path))
                current_dir = path
                seen.add(path)

            elif pathtype == ensure_dirs.QUEUE_DIR:
                self.assertTrue(
                    dirname in seen,
                    msg=("Queue directory '%s' was not seen before" % path))
                current_dir = path

            elif pathtype == ensure_dirs.FILE:
                self.assertFalse(current_dir is None)
                self.assertTrue(
                    dirname in seen,
                    msg=("Directory '%s' of path '%s' has not been seen"
                         " yet" % (dirname, path)))
                self.assertTrue(
                    (utils.IsBelowDir(current_dir, path)
                     and current_dir == dirname),
                    msg=("File '%s' not below current directory '%s'" %
                         (path, current_dir)))

            else:
                self.fail("Unknown path type '%s'" % (pathtype, ))
示例#5
0
        utils.ParseMultiCpuMask(cpu_mask)
    except errors.ParseError:
        return False

    return True


# Read the BaseHypervisor.PARAMETERS docstring for the syntax of the
# _CHECK values

# must be a file
_FILE_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
               os.path.isfile, "not found or not a file")

# must be a file or a URL
_FILE_OR_URL_CHECK = (lambda x: utils.IsNormAbsPath(x) or utils.IsUrl(x),
                      "must be an absolute normalized path or a URL",
                      lambda x: os.path.isfile(x) or utils.IsUrl(x),
                      "not found or not a file or URL")

# must be a directory
_DIR_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
              os.path.isdir, "not found or not a directory")

# CPU mask must be well-formed
# TODO: implement node level check for the CPU mask
_CPU_MASK_CHECK = (_IsCpuMaskWellFormed,
                   "CPU mask definition is not well-formed", None, None)

# Multiple CPU mask must be well-formed
_MULTI_CPU_MASK_CHECK = (_IsMultiCpuMaskWellFormed,
class _QaConfig(object):
  def __init__(self, data):
    """Initializes instances of this class.

    """
    self._data = data

    #: Cluster-wide run-time value of the exclusive storage flag
    self._exclusive_storage = None

  @staticmethod
  def LoadPatch(patch_dict, rel_path):
    """ Loads a single patch.

    @type patch_dict: dict of string to dict
    @param patch_dict: A dictionary storing patches by relative path.
    @type rel_path: string
    @param rel_path: The relative path to the patch, might or might not exist.

    """
    try:
      full_path = os.path.join(_QA_BASE_PATH, rel_path)
      patch = serializer.LoadJson(utils.ReadFile(full_path))
      patch_dict[rel_path] = patch
    except IOError:
      pass

  @staticmethod
  def LoadPatches():
    """ Finds and loads all patches supported by the QA.

    @rtype: dict of string to dict
    @return: A dictionary of relative path to patch content.

    """
    patches = {}
    _QaConfig.LoadPatch(patches, _QA_DEFAULT_PATCH)
    patch_dir_path = os.path.join(_QA_BASE_PATH, _QA_PATCH_DIR)
    if os.path.exists(patch_dir_path):
      for filename in os.listdir(patch_dir_path):
        if filename.endswith(".json"):
          _QaConfig.LoadPatch(patches, os.path.join(_QA_PATCH_DIR, filename))
    return patches

  @staticmethod
  def ApplyPatch(data, patch_module, patches, patch_path):
    """Applies a single patch.

    @type data: dict (deserialized json)
    @param data: The QA configuration to modify
    @type patch_module: module
    @param patch_module: The json patch module, loaded dynamically
    @type patches: dict of string to dict
    @param patches: The dictionary of patch path to content
    @type patch_path: string
    @param patch_path: The path to the patch, relative to the QA directory

    """
    patch_content = patches[patch_path]
    print qa_logging.FormatInfo("Applying patch %s" % patch_path)
    if not patch_content and patch_path != _QA_DEFAULT_PATCH:
      print qa_logging.FormatWarning("The patch %s added by the user is empty" %
                                     patch_path)
    patch_module.apply_patch(data, patch_content, in_place=True)

  @staticmethod
  def ApplyPatches(data, patch_module, patches):
    """Applies any patches present, and returns the modified QA configuration.

    First, patches from the patch directory are applied. They are ordered
    alphabetically, unless there is an ``order`` file present - any patches
    listed within are applied in that order, and any remaining ones in
    alphabetical order again. Finally, the default patch residing in the
    top-level QA directory is applied.

    @type data: dict (deserialized json)
    @param data: The QA configuration to modify
    @type patch_module: module
    @param patch_module: The json patch module, loaded dynamically
    @type patches: dict of string to dict
    @param patches: The dictionary of patch path to content

    """
    ordered_patches = []
    order_path = os.path.join(_QA_BASE_PATH, _QA_PATCH_DIR,
                              _QA_PATCH_ORDER_FILE)
    if os.path.exists(order_path):
      order_file = open(order_path, 'r')
      ordered_patches = order_file.read().splitlines()
      # Removes empty lines
      ordered_patches = filter(None, ordered_patches)

    # Add the patch dir
    ordered_patches = map(lambda x: os.path.join(_QA_PATCH_DIR, x),
                          ordered_patches)

    # First the ordered patches
    for patch in ordered_patches:
      if patch not in patches:
        raise qa_error.Error("Patch %s specified in the ordering file does not "
                             "exist" % patch)
      _QaConfig.ApplyPatch(data, patch_module, patches, patch)

    # Then the other non-default ones
    for patch in sorted(patches):
      if patch != _QA_DEFAULT_PATCH and patch not in ordered_patches:
        _QaConfig.ApplyPatch(data, patch_module, patches, patch)

    # Finally the default one
    if _QA_DEFAULT_PATCH in patches:
      _QaConfig.ApplyPatch(data, patch_module, patches, _QA_DEFAULT_PATCH)

  @classmethod
  def Load(cls, filename):
    """Loads a configuration file and produces a configuration object.

    @type filename: string
    @param filename: Path to configuration file
    @rtype: L{_QaConfig}

    """
    data = serializer.LoadJson(utils.ReadFile(filename))

    # Patch the document using JSON Patch (RFC6902) in file _PATCH_JSON, if
    # available
    try:
      patches = _QaConfig.LoadPatches()
      # Try to use the module only if there is a non-empty patch present
      if any(patches.values()):
        mod = __import__("jsonpatch", fromlist=[])
        _QaConfig.ApplyPatches(data, mod, patches)
    except IOError:
      pass
    except ImportError:
      raise qa_error.Error("For the QA JSON patching feature to work, you "
                           "need to install Python modules 'jsonpatch' and "
                           "'jsonpointer'.")

    result = cls(dict(map(_ConvertResources,
                          data.items()))) # pylint: disable=E1103
    result.Validate()

    return result

  def Validate(self):
    """Validates loaded configuration data.

    """
    if not self.get("name"):
      raise qa_error.Error("Cluster name is required")

    if not self.get("nodes"):
      raise qa_error.Error("Need at least one node")

    if not self.get("instances"):
      raise qa_error.Error("Need at least one instance")

    disks = self.GetDiskOptions()
    if disks is None:
      raise qa_error.Error("Config option 'disks' must exist")
    else:
      for d in disks:
        if d.get("size") is None or d.get("growth") is None:
          raise qa_error.Error("Config options `size` and `growth` must exist"
                               " for all `disks` items")
    check = self.GetInstanceCheckScript()
    if check:
      try:
        os.stat(check)
      except EnvironmentError, err:
        raise qa_error.Error("Can't find instance check script '%s': %s" %
                             (check, err))

    enabled_hv = frozenset(self.GetEnabledHypervisors())
    if not enabled_hv:
      raise qa_error.Error("No hypervisor is enabled")

    difference = enabled_hv - constants.HYPER_TYPES
    if difference:
      raise qa_error.Error("Unknown hypervisor(s) enabled: %s" %
                           utils.CommaJoin(difference))

    (vc_master, vc_basedir) = self.GetVclusterSettings()
    if bool(vc_master) != bool(vc_basedir):
      raise qa_error.Error("All or none of the config options '%s' and '%s'"
                           " must be set" %
                           (_VCLUSTER_MASTER_KEY, _VCLUSTER_BASEDIR_KEY))

    if vc_basedir and not utils.IsNormAbsPath(vc_basedir):
      raise qa_error.Error("Path given in option '%s' must be absolute and"
                           " normalized" % _VCLUSTER_BASEDIR_KEY)
示例#7
0
文件: qa_config.py 项目: badp/ganeti
class _QaConfig(object):
    def __init__(self, data):
        """Initializes instances of this class.

    """
        self._data = data

        #: Cluster-wide run-time value of the exclusive storage flag
        self._exclusive_storage = None

    @classmethod
    def Load(cls, filename):
        """Loads a configuration file and produces a configuration object.

    @type filename: string
    @param filename: Path to configuration file
    @rtype: L{_QaConfig}

    """
        data = serializer.LoadJson(utils.ReadFile(filename))

        # Patch the document using JSON Patch (RFC6902) in file _PATCH_JSON, if
        # available
        try:
            patch = serializer.LoadJson(utils.ReadFile(_PATCH_JSON))
            if patch:
                mod = __import__("jsonpatch", fromlist=[])
                data = mod.apply_patch(data, patch)
        except IOError:
            pass
        except ImportError:
            raise qa_error.Error(
                "If you want to use the QA JSON patching feature,"
                " you need to install Python modules"
                " 'jsonpatch' and 'jsonpointer'.")

        result = cls(dict(map(_ConvertResources, data.items())))  # pylint: disable=E1103
        result.Validate()

        return result

    def Validate(self):
        """Validates loaded configuration data.

    """
        if not self.get("name"):
            raise qa_error.Error("Cluster name is required")

        if not self.get("nodes"):
            raise qa_error.Error("Need at least one node")

        if not self.get("instances"):
            raise qa_error.Error("Need at least one instance")

        disks = self.GetDiskOptions()
        if disks is None:
            raise qa_error.Error("Config option 'disks' must exist")
        else:
            for d in disks:
                if d.get("size") is None or d.get("growth") is None:
                    raise qa_error.Error(
                        "Config options `size` and `growth` must exist"
                        " for all `disks` items")
        check = self.GetInstanceCheckScript()
        if check:
            try:
                os.stat(check)
            except EnvironmentError, err:
                raise qa_error.Error(
                    "Can't find instance check script '%s': %s" % (check, err))

        enabled_hv = frozenset(self.GetEnabledHypervisors())
        if not enabled_hv:
            raise qa_error.Error("No hypervisor is enabled")

        difference = enabled_hv - constants.HYPER_TYPES
        if difference:
            raise qa_error.Error("Unknown hypervisor(s) enabled: %s" %
                                 utils.CommaJoin(difference))

        (vc_master, vc_basedir) = self.GetVclusterSettings()
        if bool(vc_master) != bool(vc_basedir):
            raise qa_error.Error(
                "All or none of the config options '%s' and '%s'"
                " must be set" % (_VCLUSTER_MASTER_KEY, _VCLUSTER_BASEDIR_KEY))

        if vc_basedir and not utils.IsNormAbsPath(vc_basedir):
            raise qa_error.Error(
                "Path given in option '%s' must be absolute and"
                " normalized" % _VCLUSTER_BASEDIR_KEY)