def test_nonexisting_id(self): self.fixture_add_primitive_with_id("myId") self.assertFalse(lib.does_id_exist(self.cib.tree, "otherId")) self.assertFalse(lib.does_id_exist(self.cib.tree, "myid")) self.assertFalse(lib.does_id_exist(self.cib.tree, " myId")) self.assertFalse(lib.does_id_exist(self.cib.tree, "myId ")) self.assertFalse(lib.does_id_exist(self.cib.tree, "my Id"))
def test_ignore_acl_role_references(self): self.cib.append_to_first_tag_name( "configuration", """ <acls> <acl_target id="target1"> <role id="role1"/> <role id="role2"/> </acl_target> </acls> """) self.assertFalse(lib.does_id_exist(self.cib.tree, "role1")) self.assertFalse(lib.does_id_exist(self.cib.tree, "role2"))
def test_ignore_acl_role_references(self): self.cib.append_to_first_tag_name( "configuration", """ <acls> <acl_target id="target1"> <role id="role1"/> <role id="role2"/> </acl_target> </acls> """ ) self.assertFalse(lib.does_id_exist(self.cib.tree, "role1")) self.assertFalse(lib.does_id_exist(self.cib.tree, "role2"))
def validate_permissions(tree, permission_info_list): """ Validate given permission list. Raise LibraryError if any of permission is not valid. tree -- cib tree permission_info_list -- list of tuples like this: ("read|write|deny", "xpath|id", <id-or-xpath-string>) """ report_items = [] allowed_permissions = ["read", "write", "deny"] allowed_scopes = ["xpath", "id"] for permission, scope_type, scope in permission_info_list: if not permission in allowed_permissions: report_items.append(reports.invalid_option_value( "permission", permission, allowed_permissions )) if not scope_type in allowed_scopes: report_items.append(reports.invalid_option_value( "scope type", scope_type, allowed_scopes )) if scope_type == 'id' and not does_id_exist(tree, scope): report_items.append(reports.id_not_found(scope, "id")) if report_items: raise LibraryError(*report_items)
def validate_permissions(tree, permission_info_list): """ Validate given permission list. Raise LibraryError if any of permission is not valid. tree -- cib tree permission_info_list -- list of tuples like this: ("read|write|deny", "xpath|id", <id-or-xpath-string>) """ report_items = [] allowed_permissions = ["read", "write", "deny"] allowed_scopes = ["xpath", "id"] for permission, scope_type, scope in permission_info_list: if not permission in allowed_permissions: report_items.append( reports.invalid_option_value("permission", permission, allowed_permissions)) if not scope_type in allowed_scopes: report_items.append( reports.invalid_option_value("scope type", scope_type, allowed_scopes)) if scope_type == 'id' and not does_id_exist(tree, scope): report_items.append(reports.id_not_found(scope, ["id"])) if report_items: raise LibraryError(*report_items)
def append_new_operation(operations_element, options): """ Create op element and apend it to operations_element. etree operations_element is the context element dict options are attributes of operation """ attribute_map = dict((key, value) for key, value in options.items() if key not in OPERATION_NVPAIR_ATTRIBUTES) if "id" in attribute_map: if does_id_exist(operations_element, attribute_map["id"]): raise LibraryError(reports.id_already_exists(attribute_map["id"])) else: attribute_map.update({ "id": create_id(operations_element.getparent(), options["name"], options["interval"]) }) op_element = etree.SubElement( operations_element, "op", attribute_map, ) nvpair_attribute_map = dict((key, value) for key, value in options.items() if key in OPERATION_NVPAIR_ATTRIBUTES) if nvpair_attribute_map: append_new_instance_attributes(op_element, nvpair_attribute_map) return op_element
def test_ignore_acl_target(self): self.cib.append_to_first_tag_name( "configuration", """ <acls> <acl_target id="target1"/> </acls> """) self.assertFalse(lib.does_id_exist(self.cib.tree, "target1"))
def test_ignore_acl_target(self): self.cib.append_to_first_tag_name( "configuration", """ <acls> <acl_target id="target1"/> </acls> """ ) self.assertFalse(lib.does_id_exist(self.cib.tree, "target1"))
def validate_conflicts(tree, existing_nodes_names, existing_nodes_addrs, node_name, options): report_list = [] if (does_id_exist(tree, node_name) or node_name in existing_nodes_names or ("remote-addr" not in options and node_name in existing_nodes_addrs)): report_list.append(reports.id_already_exists(node_name)) if ("remote-addr" in options and options["remote-addr"] in existing_nodes_addrs): report_list.append(reports.id_already_exists(options["remote-addr"])) return report_list
def validate_conflicts(tree, nodes, node_name, options): report_list = [] if (does_id_exist(tree, node_name) or node_addresses_contain_name(nodes, node_name) or ("remote-addr" not in options and node_addresses_contain_host(nodes, node_name))): report_list.append(reports.id_already_exists(node_name)) if ("remote-addr" in options and node_addresses_contain_host(nodes, options["remote-addr"])): report_list.append(reports.id_already_exists(options["remote-addr"])) return report_list
def __validate_role_id_for_create(tree, role_id): validate_id(role_id, 'ACL role') if tree.find('.//acl_role[@id="{0}"]'.format(role_id)) is not None: raise LibraryError(ReportItem.error( error_codes.ACL_ROLE_ALREADY_EXISTS, 'role {id} already exists', info={'id': role_id} )) if does_id_exist(tree, role_id): raise LibraryError(ReportItem.error( error_codes.ID_ALREADY_EXISTS, '{id} already exists', info={'id': role_id} ))
def test_find_remote_node_pacemaker_internal_id(self): tree = etree.fromstring(""" <cib> <configuration> <resources> <primitive id="b"> <meta_attributes> <nvpair name="remote-node" value="a"/> </meta_attributes> </primitive> </resources> </configuration> </cib> """) self.assertTrue(lib.does_id_exist(tree, "a"))
def test_ignore_status_section(self): self.cib.append_to_first_tag_name("status", """ <elem1 id="status-1"> <elem1a id="status-1a"> <elem1aa id="status-1aa"/> <elem1ab id="status-1ab"/> </elem1a> <elem1b id="status-1b"> <elem1ba id="status-1ba"/> <elem1bb id="status-1bb"/> </elem1b> </elem1> """) self.assertFalse(lib.does_id_exist(self.cib.tree, "status-1")) self.assertFalse(lib.does_id_exist(self.cib.tree, "status-1a")) self.assertFalse(lib.does_id_exist(self.cib.tree, "status-1aa")) self.assertFalse(lib.does_id_exist(self.cib.tree, "status-1ab")) self.assertFalse(lib.does_id_exist(self.cib.tree, "status-1b")) self.assertFalse(lib.does_id_exist(self.cib.tree, "status-1ba")) self.assertFalse(lib.does_id_exist(self.cib.tree, "status-1bb"))
def __validate_permissions(tree, permission_info_list): report = [] allowed_permissions = ["read", "write", "deny"] allowed_scopes = ["xpath", "id"] for permission, scope_type, scope in permission_info_list: if not permission in allowed_permissions: report.append(ReportItem.error( error_codes.BAD_ACL_PERMISSION, 'bad permission "{permission}, expected {allowed_values}', info={ 'permission': permission, 'allowed_values_raw': allowed_permissions, 'allowed_values': ' or '.join(allowed_permissions) }, )) if not scope_type in allowed_scopes: report.append(ReportItem.error( error_codes.BAD_ACL_SCOPE_TYPE, 'bad scope type "{scope_type}, expected {allowed_values}', info={ 'scope_type': scope_type, 'allowed_values_raw': allowed_scopes, 'allowed_values': ' or '.join(allowed_scopes) }, )) if scope_type == 'id' and not does_id_exist(tree, scope): report.append(ReportItem.error( error_codes.ID_NOT_FOUND, 'id "{id}" does not exist.', info={'id': scope }, )) if report: raise LibraryError(*report)
def __validate_permissions(tree, permission_info_list): report_items = [] allowed_permissions = ["read", "write", "deny"] allowed_scopes = ["xpath", "id"] for permission, scope_type, scope in permission_info_list: if not permission in allowed_permissions: report_items.append(reports.invalid_option_value( "permission", permission, allowed_permissions )) if not scope_type in allowed_scopes: report_items.append(reports.invalid_option_value( "scope type", scope_type, allowed_scopes )) if scope_type == 'id' and not does_id_exist(tree, scope): report_items.append(reports.id_not_found(scope, "id")) if report_items: raise LibraryError(*report_items)
def create( report_processor, resources_section, resource_id, resource_agent, raw_operation_list=None, meta_attributes=None, instance_attributes=None, allow_invalid_operation=False, allow_invalid_instance_attributes=False, use_default_operations=True, resource_type="resource" ): """ Prepare all parts of primitive resource and append it into cib. report_processor is a tool for warning/info/error reporting etree.Element resources_section is place where new element will be appended string resource_id is id of new resource lib.resource_agent.CrmAgent resource_agent list of dict raw_operation_list specifies operations of resource dict meta_attributes specifies meta attributes of resource dict instance_attributes specifies instance attributes of resource bool allow_invalid_operation is flag for skipping validation of operations bool allow_invalid_instance_attributes is flag for skipping validation of instance_attributes bool use_default_operations is flag for completion operations with default actions specified in resource agent string resource_type -- describes the resource for reports """ if raw_operation_list is None: raw_operation_list = [] if meta_attributes is None: meta_attributes = {} if instance_attributes is None: instance_attributes = {} if does_id_exist(resources_section, resource_id): raise LibraryError(reports.id_already_exists(resource_id)) validate_id(resource_id, "{0} name".format(resource_type)) operation_list = prepare_operations( report_processor, raw_operation_list, resource_agent.get_cib_default_actions( necessary_only=not use_default_operations ), [operation["name"] for operation in resource_agent.get_actions()], allow_invalid=allow_invalid_operation, ) report_processor.process_list( resource_agent.validate_parameters( instance_attributes, parameters_type=resource_type, allow_invalid=allow_invalid_instance_attributes, ) ) return append_new( resources_section, resource_id, resource_agent.get_standard(), resource_agent.get_provider(), resource_agent.get_type(), instance_attributes=instance_attributes, meta_attributes=meta_attributes, operation_list=operation_list )
def create( report_processor: ReportProcessor, resources_section, id_provider, resource_id, resource_agent, raw_operation_list=None, meta_attributes=None, instance_attributes=None, allow_invalid_operation=False, allow_invalid_instance_attributes=False, use_default_operations=True, resource_type="resource", do_not_report_instance_attribute_server_exists=False # TODO remove this arg ): # pylint: disable=too-many-arguments """ Prepare all parts of primitive resource and append it into cib. report_processor is a tool for warning/info/error reporting etree.Element resources_section is place where new element will be appended IdProvider id_provider -- elements' ids generator string resource_id is id of new resource lib.resource_agent.CrmAgent resource_agent list of dict raw_operation_list specifies operations of resource dict meta_attributes specifies meta attributes of resource dict instance_attributes specifies instance attributes of resource bool allow_invalid_operation is flag for skipping validation of operations bool allow_invalid_instance_attributes is flag for skipping validation of instance_attributes bool use_default_operations is flag for completion operations with default actions specified in resource agent string resource_type -- describes the resource for reports bool do_not_report_instance_attribute_server_exists -- dirty fix due to suboptimal architecture, TODO: fix the architecture and remove the param """ if raw_operation_list is None: raw_operation_list = [] if meta_attributes is None: meta_attributes = {} if instance_attributes is None: instance_attributes = {} if does_id_exist(resources_section, resource_id): raise LibraryError(reports.id_already_exists(resource_id)) validate_id(resource_id, "{0} name".format(resource_type)) operation_list = prepare_operations( report_processor, raw_operation_list, resource_agent.get_cib_default_actions( necessary_only=not use_default_operations ), [operation["name"] for operation in resource_agent.get_actions()], allow_invalid=allow_invalid_operation, ) if report_processor.report_list( validate_resource_instance_attributes_create( resource_agent, instance_attributes, resources_section, force=allow_invalid_instance_attributes, do_not_report_instance_attribute_server_exists=( do_not_report_instance_attribute_server_exists ) ) ).has_errors: raise LibraryError() return append_new( resources_section, id_provider, resource_id, resource_agent.get_standard(), resource_agent.get_provider(), resource_agent.get_type(), instance_attributes=instance_attributes, meta_attributes=meta_attributes, operation_list=operation_list )
def test_existing_id(self): self.fixture_add_primitive_with_id("myId") self.assertTrue(lib.does_id_exist(self.cib.tree, "myId"))
def test_ignore_sections_directly_under_cib(self): #this is side effect of current implementation but is not problem since #id attribute is not allowed for elements directly under cib tree = etree.fromstring('<cib><direct id="a"/></cib>') self.assertFalse(lib.does_id_exist(tree, "a"))
def test_find_id_when_cib_is_not_root_element(self): #for example we have only part of xml tree = etree.fromstring('<root><direct id="a"/></root>') self.assertTrue(lib.does_id_exist(tree, "a"))
def create( report_processor: reports.ReportProcessor, resources_section: _Element, id_provider: IdProvider, resource_id: str, resource_agent_facade: ResourceAgentFacade, raw_operation_list: Optional[Iterable[ResourceOperationIn]] = None, meta_attributes: Optional[Mapping[str, str]] = None, instance_attributes: Optional[Mapping[str, str]] = None, allow_invalid_operation: bool = False, allow_invalid_instance_attributes: bool = False, use_default_operations: bool = True, resource_type: str = "resource", # TODO remove this arg do_not_report_instance_attribute_server_exists: bool = False, ): # pylint: disable=too-many-arguments # pylint: disable=too-many-locals """ Prepare all parts of primitive resource and append it into cib. report_processor -- a tool for warning/info/error reporting resources_section -- a place where the new resource will be appended id_provider -- elements' ids generator resource_id -- id of the new resource resource_agent_facade -- resource agent raw_operation_list -- specifies operations of the resource meta_attributes -- specifies meta attributes of the resource instance_attributes -- specifies instance attributes of the resource allow_invalid_operation -- flag for skipping validation of operations allow_invalid_instance_attributes -- flag for skipping validation of instance_attributes use_default_operations -- flag for completion operations with default actions specified in resource agent resource_type -- describes the resource for reports do_not_report_instance_attribute_server_exists -- dirty fix due to suboptimal architecture, TODO: fix the architecture and remove the param """ if raw_operation_list is None: raw_operation_list = [] if meta_attributes is None: meta_attributes = {} if instance_attributes is None: instance_attributes = {} filtered_raw_operation_list = [] for op in raw_operation_list: filtered_raw_operation_list.append( {name: "" if value is None else value for name, value in op.items()} ) if does_id_exist(resources_section, resource_id): raise LibraryError( reports.ReportItem.error( reports.messages.IdAlreadyExists(resource_id) ) ) validate_id(resource_id, "{0} name".format(resource_type)) agent_metadata = resource_agent_facade.metadata operation_list = prepare_operations( report_processor, filtered_raw_operation_list, get_default_operations( agent_metadata, necessary_only=not use_default_operations ), [operation.name for operation in agent_metadata.actions], are_new_role_names_supported(resources_section), allow_invalid=allow_invalid_operation, ) report_items = validate_resource_instance_attributes_create( resource_agent_facade, instance_attributes, resources_section, force=allow_invalid_instance_attributes, ) # TODO remove this "if", see pcs.lib.cib.remote_node.create for details if do_not_report_instance_attribute_server_exists: for report_item in report_items: if isinstance(report_item.message, reports.messages.InvalidOptions): report_msg = cast( reports.messages.InvalidOptions, report_item.message ) report_item.message = reports.messages.InvalidOptions( report_msg.option_names, sorted( [ value for value in report_msg.allowed if value != "server" ] ), report_msg.option_type, report_msg.allowed_patterns, ) report_processor.report_list(report_items) if report_processor.has_errors: raise LibraryError() return append_new( resources_section, id_provider, resource_id, agent_metadata.name.standard, agent_metadata.name.provider, agent_metadata.name.type, instance_attributes=instance_attributes, meta_attributes=meta_attributes, operation_list=operation_list, )
def create( report_processor, resources_section, resource_id, resource_agent, raw_operation_list=None, meta_attributes=None, instance_attributes=None, allow_invalid_operation=False, allow_invalid_instance_attributes=False, use_default_operations=True, ensure_disabled=False, ): """ Prepare all parts of primitive resource and append it into cib. report_processor is a tool for warning/info/error reporting etree.Element resources_section is place where new element will be appended string resource_id is id of new resource lib.resource_agent.CrmAgent resource_agent list of dict raw_operation_list specifies operations of resource dict meta_attributes specifies meta attributes of resource dict instance_attributes specifies instance attributes of resource bool allow_invalid_operation is flag for skipping validation of operations bool allow_invalid_instance_attributes is flag for skipping validation of instance_attributes bool use_default_operations is flag for completion operations with default actions specified in resource agent bool ensure_disabled is flag for completion meta_attributes with attribute causing disabling resource """ if raw_operation_list is None: raw_operation_list = [] if meta_attributes is None: meta_attributes = {} if instance_attributes is None: instance_attributes = {} if does_id_exist(resources_section, resource_id): raise LibraryError(reports.id_already_exists(resource_id)) validate_id(resource_id, "resource name") operation_list = prepare_operations( report_processor, raw_operation_list, resource_agent.get_cib_default_actions( necessary_only=not use_default_operations ), [operation["name"] for operation in resource_agent.get_actions()], allow_invalid=allow_invalid_operation, ) if ensure_disabled: meta_attributes = disable_meta(meta_attributes) report_processor.process_list( resource_agent.validate_parameters( instance_attributes, parameters_type="resource", allow_invalid=allow_invalid_instance_attributes, ) ) return append_new( resources_section, resource_id, resource_agent.get_standard(), resource_agent.get_provider(), resource_agent.get_type(), instance_attributes=instance_attributes, meta_attributes=meta_attributes, operation_list=operation_list )