Exemplo n.º 1
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()
Exemplo n.º 2
0
    def test_not_valid_rule(self):
        test_data = [
            ("resource", (1, 9, 8, "Expected <resource name>")),
            ("op", (1, 3, 2, "Expected <operation name>")),
            ("resource ::rA and", (1, 15, 14, "Expected end of text")),
            ("resource ::rA and op ", (1, 15, 14, "Expected end of text")),
            ("resource ::rA and (", (1, 15, 14, "Expected end of text")),
        ]

        for rule_string, exception_data in test_data:
            with self.subTest(rule_string=rule_string):
                with self.assertRaises(rule.RuleParseError) as cm:
                    rule.parse_rule(rule_string,
                                    allow_rsc_expr=True,
                                    allow_op_expr=True)
            e = cm.exception
            self.assertEqual(exception_data, (e.lineno, e.colno, e.pos, e.msg))
            self.assertEqual(rule_string, e.rule_string)
Exemplo n.º 3
0
    def validate(self, force_options: bool = False) -> reports.ReportItemList:
        report_list: reports.ReportItemList = []

        # Nvpair dict is intentionally not validated: it may contain any keys
        # and values. This can change in the future and then we add a
        # validation. Until then there is really nothing to validate there.

        # validate nvset options
        validators = [
            validate.NamesIn(
                ("id", "score"),
                severity=reports.item.get_severity(reports.codes.FORCE_OPTIONS,
                                                   force_options),
            ),
            # with id_provider it validates that the id is available as well
            validate.ValueId("id",
                             option_name_for_report="id",
                             id_provider=self._id_provider),
            validate.ValueScore("score"),
        ]
        report_list.extend(
            validate.ValidatorAll(validators).validate(self._nvset_options))

        # parse and validate rule
        # TODO write and call parsed rule validation and cleanup and tests
        if self._nvset_rule:
            try:
                # Allow flags are set to True always, the parsed rule tree is
                # checked in the validator instead. That gives us better error
                # messages, such as "op expression cannot be used in this
                # context" instead of a universal "parse error".
                self._nvset_rule_parsed = parse_rule(self._nvset_rule,
                                                     allow_rsc_expr=True,
                                                     allow_op_expr=True)
                report_list.extend(
                    RuleValidator(
                        self._nvset_rule_parsed,
                        allow_rsc_expr=self._allow_rsc_expr,
                        allow_op_expr=self._allow_op_expr,
                    ).get_reports())
            except RuleParseError as e:
                report_list.append(
                    reports.ReportItem.error(
                        reports.messages.RuleExpressionParseError(
                            e.rule_string,
                            e.msg,
                            e.rule_line,
                            e.lineno,
                            e.colno,
                            e.pos,
                        )))

        return report_list
Exemplo n.º 4
0
    def validate(self, force_options: bool = False) -> reports.ReportItemList:
        report_list: reports.ReportItemList = []

        # Nvpair dict is intentionally not validated: it may contain any keys
        # and values. This can change in the future and then we add a
        # validation. Until then there is really nothing to validate there.

        # validate nvset options
        validators = [
            validate.NamesIn(
                ("id", "score"),
                severity=reports.item.get_severity(reports.codes.FORCE,
                                                   force_options),
            ),
            # with id_provider it validates that the id is available as well
            validate.ValueId("id",
                             option_name_for_report="id",
                             id_provider=self._id_provider),
            validate.ValueScore("score"),
        ]
        report_list.extend(
            validate.ValidatorAll(validators).validate(self._nvset_options))

        # parse and validate rule
        if self._nvset_rule:
            try:
                self._nvset_rule_parsed = parse_rule(self._nvset_rule)
                report_list.extend(
                    RuleValidator(
                        self._nvset_rule_parsed,
                        allow_rsc_expr=self._allow_rsc_expr,
                        allow_op_expr=self._allow_op_expr,
                        allow_node_attr_expr=self._allow_node_attr_expr,
                    ).get_reports())
            except RuleParseError as e:
                report_list.append(
                    reports.ReportItem.error(
                        reports.messages.RuleExpressionParseError(
                            e.rule_string,
                            e.msg,
                            e.rule_line,
                            e.lineno,
                            e.colno,
                            e.pos,
                        )))

        return report_list
Exemplo n.º 5
0
 def test_success_parse_to_tree(self):
     test_data = [
         ("", "BoolExpr AND"),
         (
             "resource ::",
             dedent("""\
                 BoolExpr AND
                   RscExpr"""),
         ),
         (
             "resource ::dummy",
             dedent("""\
                 BoolExpr AND
                   RscExpr type=dummy"""),
         ),
         (
             "resource ocf::",
             dedent("""\
                 BoolExpr AND
                   RscExpr standard=ocf"""),
         ),
         (
             "resource :pacemaker:",
             dedent("""\
                 BoolExpr AND
                   RscExpr provider=pacemaker"""),
         ),
         (
             "resource systemd::Dummy",
             dedent("""\
                 BoolExpr AND
                   RscExpr standard=systemd type=Dummy"""),
         ),
         (
             "resource ocf:pacemaker:",
             dedent("""\
                 BoolExpr AND
                   RscExpr standard=ocf provider=pacemaker"""),
         ),
         (
             "resource :pacemaker:Dummy",
             dedent("""\
                 BoolExpr AND
                   RscExpr provider=pacemaker type=Dummy"""),
         ),
         (
             "resource ocf:pacemaker:Dummy",
             dedent("""\
                 BoolExpr AND
                   RscExpr standard=ocf provider=pacemaker type=Dummy"""),
         ),
         (
             "op monitor",
             dedent("""\
                 BoolExpr AND
                   OpExpr name=monitor"""),
         ),
         (
             "op monitor interval=10",
             dedent("""\
                 BoolExpr AND
                   OpExpr name=monitor interval=10"""),
         ),
         (
             "resource ::dummy and op monitor",
             dedent("""\
                 BoolExpr AND
                   RscExpr type=dummy
                   OpExpr name=monitor"""),
         ),
         (
             "resource ::dummy or op monitor interval=15s",
             dedent("""\
                 BoolExpr OR
                   RscExpr type=dummy
                   OpExpr name=monitor interval=15s"""),
         ),
         (
             "op monitor and resource ::dummy",
             dedent("""\
                 BoolExpr AND
                   OpExpr name=monitor
                   RscExpr type=dummy"""),
         ),
         (
             "op monitor interval=5min or resource ::dummy",
             dedent("""\
                 BoolExpr OR
                   OpExpr name=monitor interval=5min
                   RscExpr type=dummy"""),
         ),
         (
             "(resource ::dummy or resource ::delay) and op monitor",
             dedent("""\
                 BoolExpr AND
                   BoolExpr OR
                     RscExpr type=dummy
                     RscExpr type=delay
                   OpExpr name=monitor"""),
         ),
         (
             "(op start and op stop) or resource ::dummy",
             dedent("""\
                 BoolExpr OR
                   BoolExpr AND
                     OpExpr name=start
                     OpExpr name=stop
                   RscExpr type=dummy"""),
         ),
         (
             "op monitor or (resource ::dummy and resource ::delay)",
             dedent("""\
                 BoolExpr OR
                   OpExpr name=monitor
                   BoolExpr AND
                     RscExpr type=dummy
                     RscExpr type=delay"""),
         ),
         (
             "resource ::dummy and (op start or op stop)",
             dedent("""\
                 BoolExpr AND
                   RscExpr type=dummy
                   BoolExpr OR
                     OpExpr name=start
                     OpExpr name=stop"""),
         ),
         (
             "resource ::dummy and resource ::delay and op monitor",
             dedent("""\
                 BoolExpr AND
                   RscExpr type=dummy
                   RscExpr type=delay
                   OpExpr name=monitor"""),
         ),
         (
             "resource ::rA or resource ::rB or resource ::rC and op monitor",
             dedent("""\
                 BoolExpr AND
                   BoolExpr OR
                     RscExpr type=rA
                     RscExpr type=rB
                     RscExpr type=rC
                   OpExpr name=monitor"""),
         ),
         (
             "op start and op stop and op monitor or resource ::delay",
             dedent("""\
                 BoolExpr OR
                   BoolExpr AND
                     OpExpr name=start
                     OpExpr name=stop
                     OpExpr name=monitor
                   RscExpr type=delay"""),
         ),
         (
             "(resource ::rA or resource ::rB or resource ::rC) and (op oX or op oY or op oZ)",
             dedent("""\
                 BoolExpr AND
                   BoolExpr OR
                     RscExpr type=rA
                     RscExpr type=rB
                     RscExpr type=rC
                   BoolExpr OR
                     OpExpr name=oX
                     OpExpr name=oY
                     OpExpr name=oZ"""),
         ),
     ]
     for rule_string, rule_tree in test_data:
         with self.subTest(rule_string=rule_string):
             self.assertEqual(
                 rule_tree,
                 _parsed_to_str(
                     rule.parse_rule(rule_string,
                                     allow_rsc_expr=True,
                                     allow_op_expr=True)),
             )
Exemplo n.º 6
0
 def test_not_valid_rule(self):
     test_data = [
         # node attr misc
         ("#uname", (1, 7, 6, "Expected 'eq'")),
         ("string node1", (1, 8, 7, "Expected 'eq'")),
         # node attr unary
         ("defined", (1, 8, 7, "Expected <attribute name>")),
         ("not_defined", (1, 12, 11, "Expected <attribute name>")),
         ("defined string pingd", (1, 16, 15, "Expected end of text")),
         ("defined date-spec hours=1", (1, 19, 18, "Expected end of text")),
         ("defined duration hours=1", (1, 18, 17, "Expected end of text")),
         # node attr binary
         ("eq", (1, 3, 2, "Expected 'eq'")),
         ("#uname eq", (1, 10, 9, "Expected <attribute value>")),
         ("#uname node1", (1, 8, 7, "Expected 'eq'")),
         ("eq #uname", (1, 4, 3, "Expected 'eq'")),
         ("eq lt", (1, 6, 5, "Expected <attribute value>")),
         ("string #uname eq node1", (1, 8, 7, "Expected 'eq'")),
         ("date-spec hours=1 eq node1", (1, 19, 18,
                                         "Expected end of text")),
         (
             "#uname eq date-spec hours=1",
             (1, 21, 20, "Expected end of text"),
         ),
         ("duration hours=1 eq node1", (1, 10, 9, "Expected 'eq'")),
         ("#uname eq duration hours=1", (1, 20, 19,
                                         "Expected end of text")),
         # node attr binary with optional parts
         ("string", (1, 7, 6, "Expected 'eq'")),
         ("#uname eq string", (1, 17, 16, "Expected <attribute value>")),
         ("string #uname eq node1", (1, 8, 7, "Expected 'eq'")),
         # resource, op
         ("resource", (1, 9, 8, "Expected 'eq'")),
         ("op", (1, 3, 2, "Expected 'eq'")),
         ("resource ::rA and", (1, 15, 14, "Expected end of text")),
         ("resource ::rA and op ", (1, 15, 14, "Expected end of text")),
         ("resource ::rA and (", (1, 15, 14, "Expected end of text")),
         # and, or
         ("and", (1, 4, 3, "Expected 'eq'")),
         ("or", (1, 3, 2, "Expected 'eq'")),
         ("#uname and node1", (1, 8, 7, "Expected 'eq'")),
         ("#uname or node1", (1, 8, 7, "Expected 'eq'")),
         ("#uname or eq", (1, 8, 7, "Expected 'eq'")),
         ("#uname eq node1 and node2", (1, 17, 16, "Expected end of text")),
         ("#uname eq node1 and", (1, 17, 16, "Expected end of text")),
         (
             "#uname eq node1 and #uname eq",
             (1, 17, 16, "Expected end of text"),
         ),
         ("and #uname eq node1", (1, 5, 4, "Expected 'eq'")),
         (
             "#uname ne node1 and duration hours=1",
             (1, 17, 16, "Expected end of text"),
         ),
         (
             "duration monthdays=1 or #uname ne node1",
             (1, 10, 9, "Expected 'eq'"),
         ),
         # date
         ("date in_range", (1, 14, 13, "Expected 'to'")),
         ("date in_range 2014-06-26", (1, 15, 14, "Expected 'to'")),
         ("date in_range 2014-06-26 to", (1, 28, 27, "Expected <date>")),
         ("in_range 2014-06-26 to 2014-07-26", (1, 10, 9, "Expected 'eq'")),
         (
             "date in_range #uname eq node1 to 2014-07-26",
             (1, 15, 14, "Expected 'to'"),
         ),
         (
             "date in_range 2014-06-26 to #uname eq node1",
             (1, 36, 35, "Expected end of text"),
         ),
         (
             "date in_range defined pingd to 2014-07-26",
             (1, 15, 14, "Expected 'to'"),
         ),
         (
             "date in_range 2014-06-26 to defined pingd",
             (1, 37, 36, "Expected end of text"),
         ),
         (
             "string date in_range 2014-06-26 to 2014-07-26",
             (1, 8, 7, "Expected 'eq'"),
         ),
         (
             "date in_range string 2014-06-26 to 2014-07-26",
             (1, 15, 14, "Expected 'to'"),
         ),
         (
             "date in_range 2014-06-26 to string 2014-07-26",
             (1, 36, 35, "Expected end of text"),
         ),
         (
             "date in_range 2014-06-26 string to 2014-07-26",
             (1, 15, 14, "Expected 'to'"),
         ),
         (
             "#uname in_range 2014-06-26 to 2014-07-26",
             (1, 8, 7, "Expected 'eq'"),
         ),
         # braces
         ("(#uname)", (1, 8, 7, "Expected 'eq'")),
         ("(", (1, 2, 1, "Expected 'date'")),
         ("()", (1, 2, 1, "Expected 'date'")),
         ("(#uname", (1, 8, 7, "Expected 'eq'")),
         ("(#uname eq", (1, 11, 10, "Expected <attribute value>")),
         # pyparsing 2 uses double quotes, pyparsing 3 uses single quotes
         ("(#uname eq node1", (1, 17, 16, {"Expected ')'",
                                           'Expected ")"'})),
     ]
     for rule_string, exception_data in test_data:
         with self.subTest(rule_string=rule_string):
             with self.assertRaises(rule.RuleParseError) as cm:
                 rule.parse_rule(rule_string)
             e = cm.exception
             if isinstance(exception_data[3], set):
                 self.assertIn(e.msg, exception_data[3])
                 self.assertEqual(exception_data[0:3],
                                  (e.lineno, e.colno, e.pos))
             else:
                 self.assertEqual(exception_data,
                                  (e.lineno, e.colno, e.pos, e.msg))
             self.assertEqual(rule_string, e.rule_string)
Exemplo n.º 7
0
 def _assert_success(self, rule_string, rule_tree):
     self.assertEqual(
         rule_tree,
         _parsed_to_str(rule.parse_rule(rule_string)),
     )