Exemple #1
0
def ensure_cib_version(runner, cib, version):
    """
    This method ensures that specified cib is verified by pacemaker with
    version 'version' or newer. If cib doesn't correspond to this version,
    method will try to upgrade cib.
    Returns cib which was verified by pacemaker version 'version' or later.
    Raises LibraryError on any failure.

    CommandRunner runner
    etree cib cib tree
    tuple version tuple of integers (<major>, <minor>, <revision>)
    """
    current_version = get_pacemaker_version_by_which_cib_was_validated(cib)
    if current_version >= version:
        return None

    _upgrade_cib(runner)
    new_cib_xml = get_cib_xml(runner)

    try:
        new_cib = parse_cib_xml(new_cib_xml)
    except (etree.XMLSyntaxError, etree.DocumentInvalid) as e:
        raise LibraryError(reports.cib_upgrade_failed(str(e)))

    current_version = get_pacemaker_version_by_which_cib_was_validated(new_cib)
    if current_version >= version:
        return new_cib

    raise LibraryError(
        reports.unable_to_upgrade_cib_to_required_version(
            current_version, version))
Exemple #2
0
def ensure_cib_version(runner, cib, version):
    """
    This method ensures that specified cib is verified by pacemaker with
    version 'version' or newer. If cib doesn't correspond to this version,
    method will try to upgrade cib.
    Returns cib which was verified by pacemaker version 'version' or later.
    Raises LibraryError on any failure.

    CommandRunner runner -- runner
    etree cib -- cib tree
    pcs.common.tools.Version version -- required cib version
    """
    current_version = get_pacemaker_version_by_which_cib_was_validated(cib)
    if current_version >= version:
        return None

    _upgrade_cib(runner)
    new_cib_xml = get_cib_xml(runner)

    try:
        new_cib = parse_cib_xml(new_cib_xml)
    except (etree.XMLSyntaxError, etree.DocumentInvalid) as e:
        raise LibraryError(
            ReportItem.error(reports.messages.CibUpgradeFailed(str(e))))

    current_version = get_pacemaker_version_by_which_cib_was_validated(new_cib)
    if current_version >= version:
        return new_cib

    raise LibraryError(
        ReportItem.error(
            reports.messages.CibUpgradeFailedToMinimalRequiredVersion(
                str(current_version), str(version))))
Exemple #3
0
def ensure_cib_version(runner, cib, version):
    """
    This method ensures that specified cib is verified by pacemaker with
    version 'version' or newer. If cib doesn't correspond to this version,
    method will try to upgrade cib.
    Returns cib which was verified by pacemaker version 'version' or later.
    Raises LibraryError on any failure.

    CommandRunner runner
    etree cib cib tree
    tuple version tuple of integers (<major>, <minor>, <revision>)
    """
    current_version = get_pacemaker_version_by_which_cib_was_validated(cib)
    if current_version >= version:
        return None

    _upgrade_cib(runner)
    new_cib_xml = get_cib_xml(runner)

    try:
        new_cib = parse_cib_xml(new_cib_xml)
    except (etree.XMLSyntaxError, etree.DocumentInvalid) as e:
        raise LibraryError(reports.cib_upgrade_failed(str(e)))

    current_version = get_pacemaker_version_by_which_cib_was_validated(new_cib)
    if current_version >= version:
        return new_cib

    raise LibraryError(reports.unable_to_upgrade_cib_to_required_version(
        current_version, version
    ))
Exemple #4
0
def ensure_cib_version(
    runner: CommandRunner,
    cib: _Element,
    version: Version,
    fail_if_version_not_met: bool = True,
) -> Tuple[_Element, bool]:
    """
    Make sure CIB complies to specified schema version (or newer), upgrade CIB
    if necessary. Raise on error. Raise if CIB cannot be upgraded enough to
    meet the required version unless fail_if_version_not_met is set to False.
    Return tuple(upgraded_cib, was_upgraded)

    This method ensures that specified cib is verified by pacemaker with
    version 'version' or newer. If cib doesn't correspond to this version,
    method will try to upgrade cib.
    Returns cib which was verified by pacemaker version 'version' or later.
    Raises LibraryError on any failure.

    runner -- runner
    cib -- cib tree
    version -- required cib version
    fail_if_version_not_met -- allows a 'nice to have' cib upgrade
    """
    version_pre_upgrade = get_pacemaker_version_by_which_cib_was_validated(cib)
    if version_pre_upgrade >= version:
        return cib, False

    _upgrade_cib(runner)
    new_cib_xml = get_cib_xml(runner)

    try:
        new_cib = parse_cib_xml(new_cib_xml)
    except (etree.XMLSyntaxError, etree.DocumentInvalid) as e:
        raise LibraryError(
            ReportItem.error(reports.messages.CibUpgradeFailed(str(e)))
        ) from e

    version_post_upgrade = get_pacemaker_version_by_which_cib_was_validated(
        new_cib
    )
    if version_post_upgrade >= version or not fail_if_version_not_met:
        return new_cib, version_post_upgrade > version_pre_upgrade

    raise LibraryError(
        ReportItem.error(
            reports.messages.CibUpgradeFailedToMinimalRequiredVersion(
                str(version_post_upgrade), str(version)
            )
        )
    )
Exemple #5
0
 def test_with_revision(self):
     self.assertEqual(
         (1, 2, 3),
         lib.get_pacemaker_version_by_which_cib_was_validated(
             etree.XML('<cib validate-with="pacemaker-1.2.3"/>')
         )
     )
Exemple #6
0
 def test_with_revision(self):
     self.assertEqual(
         Version(1, 2, 3),
         lib.get_pacemaker_version_by_which_cib_was_validated(
             etree.XML('<cib validate-with="pacemaker-1.2.3"/>')
         )
     )
Exemple #7
0
def _defaults_create(
    env: LibraryEnvironment,
    cib_section_name: str,
    validator_options: Mapping[str, Any],
    nvpairs: Mapping[str, str],
    nvset_options: Mapping[str, str],
    nvset_rule: Optional[str] = None,
    force_flags: Optional[Container] = None,
) -> None:
    if force_flags is None:
        force_flags = set()
    force = (reports.codes.FORCE
             in force_flags) or (reports.codes.FORCE_OPTIONS in force_flags)

    required_cib_version = None
    nice_to_have_cib_version = None
    if nvset_rule:
        # Parse the rule to see if we need to upgrade CIB schema. All errors
        # would be properly reported by a validator called bellow, so we can
        # safely ignore them here.
        try:
            rule_tree = parse_rule(nvset_rule)
            if has_rsc_or_op_expression(rule_tree):
                required_cib_version = Version(3, 4, 0)
            if has_node_attr_expr_with_type_integer(rule_tree):
                nice_to_have_cib_version = Version(3, 5, 0)
        except RuleParseError:
            pass

    cib = env.get_cib(
        minimal_version=required_cib_version,
        nice_to_have_version=nice_to_have_cib_version,
    )
    id_provider = IdProvider(cib)

    validator = nvpair_multi.ValidateNvsetAppendNew(
        id_provider,
        nvpairs,
        nvset_options,
        nvset_rule=nvset_rule,
        **validator_options,
    )
    if env.report_processor.report_list(
            validator.validate(force_options=force)).has_errors:
        raise LibraryError()

    nvpair_multi.nvset_append_new(
        sections.get(cib, cib_section_name),
        id_provider,
        get_pacemaker_version_by_which_cib_was_validated(cib),
        nvpair_multi.NVSET_META,
        nvpairs,
        nvset_options,
        nvset_rule=validator.get_parsed_rule(),
    )

    env.report_processor.report(
        ReportItem.warning(reports.messages.DefaultsCanBeOverriden()))
    env.push_cib()
Exemple #8
0
 def test_invalid_version_at_end(self):
     assert_raise_library_error(
         lambda: lib.get_pacemaker_version_by_which_cib_was_validated(
             etree.XML('<cib validate-with="pacemaker-1.2.3x"/>')),
         (severities.ERROR, report_codes.CIB_LOAD_ERROR_BAD_FORMAT, {
             "reason":
             "the attribute 'validate-with' of the element"
             " 'cib' has an invalid value: 'pacemaker-1.2.3x'"
         }))
Exemple #9
0
 def test_missing_attribute(self):
     assert_raise_library_error(
         lambda: lib.get_pacemaker_version_by_which_cib_was_validated(
             etree.XML("<cib/>")),
         (severities.ERROR, report_codes.CIB_LOAD_ERROR_BAD_FORMAT, {
             "reason":
             "the attribute 'validate-with' of the element"
             " 'cib' is missing"
         }))
Exemple #10
0
 def test_invalid_version(self):
     assert_raise_library_error(
         lambda: lib.get_pacemaker_version_by_which_cib_was_validated(
             etree.XML('<cib validate-with="something-1.2.3"/>')
         ),
         (
             severities.ERROR,
             report_codes.CIB_LOAD_ERROR_BAD_FORMAT,
             {}
         )
     )
Exemple #11
0
 def test_missing_attribute(self):
     assert_raise_library_error(
         lambda: lib.get_pacemaker_version_by_which_cib_was_validated(
             etree.XML("<cib/>")
         ),
         (
             severities.ERROR,
             report_codes.CIB_LOAD_ERROR_BAD_FORMAT,
             {}
         )
     )
Exemple #12
0
 def test_invalid_version(self):
     assert_raise_library_error(
         lambda: lib.get_pacemaker_version_by_which_cib_was_validated(
             etree.XML('<cib validate-with="something-1.2.3"/>')
         ),
         (
             severities.ERROR,
             report_codes.CIB_LOAD_ERROR_BAD_FORMAT,
             {}
         )
     )
Exemple #13
0
 def test_missing_attribute(self):
     assert_raise_library_error(
         lambda: lib.get_pacemaker_version_by_which_cib_was_validated(
             etree.XML("<cib/>")
         ),
         (
             severities.ERROR,
             report_codes.CIB_LOAD_ERROR_BAD_FORMAT,
             {}
         )
     )
Exemple #14
0
 def test_invalid_version_at_end(self):
     assert_raise_library_error(
         lambda: lib.get_pacemaker_version_by_which_cib_was_validated(
             etree.XML('<cib validate-with="pacemaker-1.2.3x"/>')
         ),
         (
             severities.ERROR,
             report_codes.CIB_LOAD_ERROR_BAD_FORMAT,
             {
                 "reason": "the attribute 'validate-with' of the element"
                     " 'cib' has an invalid value: 'pacemaker-1.2.3x'"
             }
         )
     )
Exemple #15
0
 def test_missing_attribute(self):
     assert_raise_library_error(
         lambda: lib.get_pacemaker_version_by_which_cib_was_validated(
             etree.XML("<cib/>")
         ),
         (
             severities.ERROR,
             report_codes.CIB_LOAD_ERROR_BAD_FORMAT,
             {
                 "reason": "the attribute 'validate-with' of the element"
                     " 'cib' is missing"
             }
         )
     )
Exemple #16
0
def _defaults_update(
    env: LibraryEnvironment,
    cib_section_name: str,
    nvset_id: Optional[str],
    nvpairs: Mapping[str, str],
    pcs_command: reports.types.PcsCommand,
) -> None:
    cib = env.get_cib()
    id_provider = IdProvider(cib)

    if nvset_id is None:
        # Backward compatibility code to support an old use case where no id
        # was requested and provided and the first meta_attributes nvset was
        # created / updated. However, we check that there is only one nvset
        # present in the CIB to prevent breaking the configuration with
        # multiple nvsets in place.

        # This is to be supported as it provides means of easily managing
        # defaults if only one set of defaults is needed.

        # TODO move this to a separate lib command.

        if not nvpairs:
            return

        # Do not create new defaults element if we are only removing values
        # from it.
        only_removing = True
        for value in nvpairs.values():
            if value != "":
                only_removing = False
                break
        if only_removing and not sections.exists(cib, cib_section_name):
            env.report_processor.report(
                ReportItem.warning(reports.messages.DefaultsCanBeOverriden()))
            return

        nvset_elements = nvpair_multi.find_nvsets(
            sections.get(cib, cib_section_name))
        if len(nvset_elements) > 1:
            env.report_processor.report(
                reports.item.ReportItem.error(
                    reports.messages.CibNvsetAmbiguousProvideNvsetId(
                        pcs_command)))
            raise LibraryError()
        env.report_processor.report(
            ReportItem.warning(reports.messages.DefaultsCanBeOverriden()))
        if len(nvset_elements) == 1:
            nvpair_multi.nvset_update(nvset_elements[0], id_provider, nvpairs)
        elif only_removing:
            # do not create new nvset if there is none and we are only removing
            # nvpairs
            return
        else:
            nvpair_multi.nvset_append_new(
                sections.get(cib, cib_section_name),
                id_provider,
                get_pacemaker_version_by_which_cib_was_validated(cib),
                nvpair_multi.NVSET_META,
                nvpairs,
                {},
            )
        env.push_cib()
        return

    nvset_elements, report_list = nvpair_multi.find_nvsets_by_ids(
        sections.get(cib, cib_section_name), [nvset_id])
    if env.report_processor.report_list(report_list).has_errors:
        raise LibraryError()

    nvpair_multi.nvset_update(nvset_elements[0], id_provider, nvpairs)
    env.report_processor.report(
        ReportItem.warning(reports.messages.DefaultsCanBeOverriden()))
    env.push_cib()