def test_nvpairs(self): context_element = etree.fromstring("""<context id="a" />""") id_provider = IdProvider(context_element) nvpair_multi.nvset_append_new( context_element, id_provider, Version(3, 5, 0), nvpair_multi.NVSET_META, {"attr1": "value1", "attr-empty": "", "attr2": "value2"}, {}, ) assert_xml_equal( """ <context id="a"> <meta_attributes id="a-meta_attributes"> <nvpair id="a-meta_attributes-attr1" name="attr1" value="value1" /> <nvpair id="a-meta_attributes-attr2" name="attr2" value="value2" /> </meta_attributes> </context> """, etree_to_str(context_element), )
def test_rule(self): context_element = etree.fromstring("""<context id="a" />""") id_provider = IdProvider(context_element) nvpair_multi.nvset_append_new( context_element, id_provider, nvpair_multi.NVSET_META, {}, {}, nvset_rule=BoolExpr( BOOL_AND, [RscExpr("ocf", "pacemaker", "Dummy"), OpExpr("start", None)], ), ) assert_xml_equal( """ <context id="a"> <meta_attributes id="a-meta_attributes"> <rule id="a-meta_attributes-rule" boolean-op="and" score="INFINITY" > <rsc_expression id="a-meta_attributes-rule-rsc-ocf-pacemaker-Dummy" class="ocf" provider="pacemaker" type="Dummy" /> <op_expression id="a-meta_attributes-rule-op-start" name="start" /> </rule> </meta_attributes> </context> """, etree_to_str(context_element), )
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()
def test_minimal(self): context_element = etree.fromstring("""<context id="a" />""") id_provider = IdProvider(context_element) nvpair_multi.nvset_append_new(context_element, id_provider, nvpair_multi.NVSET_META, {}, {}) assert_xml_equal( """ <context id="a"> <meta_attributes id="a-meta_attributes" /> </context> """, etree_to_str(context_element), )
def test_everything(self): context_element = etree.fromstring("""<context id="a" />""") id_provider = IdProvider(context_element) nvpair_multi.nvset_append_new( context_element, id_provider, Version(3, 5, 0), nvpair_multi.NVSET_META, { "attr1": "value1", "attr-empty": "", "attr2": "value2" }, { "id": "custom-id", "score": "INFINITY", "empty-attr": "" }, nvset_rule=BoolExpr( BOOL_AND, [RscExpr("ocf", "pacemaker", "Dummy"), OpExpr("start", None)], ), ) assert_xml_equal( """ <context id="a"> <meta_attributes id="custom-id" score="INFINITY"> <rule id="custom-id-rule" boolean-op="and" score="INFINITY" > <rsc_expression id="custom-id-rule-rsc-ocf-pacemaker-Dummy" class="ocf" provider="pacemaker" type="Dummy" /> <op_expression id="custom-id-rule-op-start" name="start" /> </rule> <nvpair id="custom-id-attr1" name="attr1" value="value1" /> <nvpair id="custom-id-attr2" name="attr2" value="value2" /> </meta_attributes> </context> """, etree_to_str(context_element), )
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 if nvset_rule: required_cib_version = Version(3, 4, 0) cib = env.get_cib(required_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, 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()
def test_options(self): context_element = etree.fromstring("""<context id="a" />""") id_provider = IdProvider(context_element) nvpair_multi.nvset_append_new( context_element, id_provider, Version(3, 5, 0), nvpair_multi.NVSET_META, {}, {"score": "INFINITY", "empty-attr": ""}, ) assert_xml_equal( """ <context id="a"> <meta_attributes id="a-meta_attributes" score="INFINITY" /> </context> """, etree_to_str(context_element), )
def test_custom_id(self): context_element = etree.fromstring("""<context id="a" />""") id_provider = IdProvider(context_element) nvpair_multi.nvset_append_new( context_element, id_provider, Version(3, 5, 0), nvpair_multi.NVSET_META, {}, {"id": "custom-id"}, ) assert_xml_equal( """ <context id="a"> <meta_attributes id="custom-id" /> </context> """, etree_to_str(context_element), )
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, 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()
def test_rule(self): context_element = etree.fromstring("""<context id="a" />""") id_provider = IdProvider(context_element) nvpair_multi.nvset_append_new( context_element, id_provider, Version(3, 5, 0), nvpair_multi.NVSET_META, {}, {}, nvset_rule=BoolExpr( BOOL_AND, [ RscExpr("ocf", "pacemaker", "Dummy"), OpExpr("start", None), BoolExpr( BOOL_OR, [ NodeAttrExpr( NODE_ATTR_OP_DEFINED, "attr1", None, None ), NodeAttrExpr( NODE_ATTR_OP_GT, "attr2", "5", NODE_ATTR_TYPE_NUMBER, ), ], ), ], ), ) assert_xml_equal( """ <context id="a"> <meta_attributes id="a-meta_attributes"> <rule id="a-meta_attributes-rule" boolean-op="and" score="INFINITY" > <rsc_expression id="a-meta_attributes-rule-rsc-ocf-pacemaker-Dummy" class="ocf" provider="pacemaker" type="Dummy" /> <op_expression id="a-meta_attributes-rule-op-start" name="start" /> <rule id="a-meta_attributes-rule-rule" boolean-op="or" score="0" > <expression id="a-meta_attributes-rule-rule-expr" operation="defined" attribute="attr1" /> <expression id="a-meta_attributes-rule-rule-expr-1" attribute="attr2" operation="gt" type="number" value="5" /> </rule> </rule> </meta_attributes> </context> """, etree_to_str(context_element), )