def test_catch_exactly_his_exception(self): report_missing = self.setup_patch("env_file.report_missing") next_in_line = mock.Mock(side_effect=LibraryEnvError( ReportItem.error(report_codes.FILE_DOES_NOT_EXIST, info={ "file_role": env_file_role_codes.BOOTH_CONFIG, }), ReportItem.error(report_codes.FILE_DOES_NOT_EXIST, info={ "file_role": env_file_role_codes.BOOTH_KEY, }), ReportItem.error("OTHER ERROR", info={}), )) mock_env = mock.MagicMock() self.read.return_value = {"content": None} booth_conf_middleware = env.middleware_config( "booth-name", "/local/file/path.conf", "/local/file/path.key", ) raised_exception = [] def run_middleware(): try: booth_conf_middleware(next_in_line, mock_env) except Exception as e: raised_exception.append(e) raise e self.assertRaises(LibraryEnvError, run_middleware) self.assertEqual(1, len(raised_exception[0].unprocessed)) self.assertEqual("OTHER ERROR", raised_exception[0].unprocessed[0].code) self.assertEqual(report_missing.mock_calls, [ mock.call('Booth config file', '/local/file/path.conf'), mock.call('Booth key file', '/local/file/path.key'), ])
def test_report_unprocessed_library_env_errors(self, mock_process_report): report1 = ReportItem.error("OTHER ERROR", info={}) report2 = ReportItem.error("OTHER ERROR", info={}) report3 = ReportItem.error("OTHER ERROR", info={}) e = LibraryEnvError(report1, report2, report3) e.sign_processed(report2) mock_middleware = mock.Mock(side_effect=e) binded = bind(cli_env=None, run_with_middleware=mock_middleware, run_library_command=None) self.assertRaises(SystemExit, lambda: binded(cli_env=None)) mock_process_report.assert_called_once_with([report1, report3])
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 validate_id(id_candidate, description="id"): """ Validate a pacemaker id, raise LibraryError on invalid id. id_candidate id's value description id's role description (default "id") """ # see NCName definition # http://www.w3.org/TR/REC-xml-names/#NT-NCName # http://www.w3.org/TR/REC-xml/#NT-Name if len(id_candidate) < 1: raise LibraryError(ReportItem.error( error_codes.INVALID_ID, "{description} cannot be empty", info={ "id": id_candidate, "description": description, "reason": "empty", } )) first_char_re = re.compile("[a-zA-Z_]") if not first_char_re.match(id_candidate[0]): raise LibraryError(ReportItem.error( error_codes.INVALID_ID, "invalid {description} '{id}', '{invalid_character}' is not " + "a valid first character for a {description}" , info={ "id": id_candidate, "description": description, "reason": "invalid first character", "invalid_character": id_candidate[0], } )) char_re = re.compile("[a-zA-Z0-9_.-]") for char in id_candidate[1:]: if not char_re.match(char): raise LibraryError(ReportItem.error( error_codes.INVALID_ID, "invalid {description} '{id}', '{invalid_character}' is not " + "a valid character for a {description}" , info={ "id": id_candidate, "description": description, "reason": "invalid character", "invalid_character": char, } ))
def resource_cleanup_error(retval, stdout, resource=None, node=None): """ an error occured when deleting resource history in pacemaker retval external process's return (exit) code stdout string external process's stdout resource string resource which has been cleaned up node string node which has been cleaned up """ if resource: text = "Unable to cleanup resource: {resource}\n{stdout}" else: text = ( "Unexpected error occured. 'crm_resource -C' err_code: " + "{return_value}\n{stdout}" ) return ReportItem.error( report_codes.RESOURCE_CLEANUP_ERROR, text, info={ "return_value": retval, "stdout": stdout, "resource": resource, "node": node, } )
def pacemaker_local_node_name_not_found(reason): """ we are unable to figure out pacemaker's local node's name reason string error message """ return ReportItem.error(report_codes.PACEMAKER_LOCAL_NODE_NAME_NOT_FOUND, info={"reason": reason})
def corosync_config_reload_error(reason): """ an error occured when reloading corosync configuration reason string an error message """ return ReportItem.error(report_codes.COROSYNC_CONFIG_RELOAD_ERROR, info={"reason": reason})
def corosync_running_on_node_fail(node): """ corosync is running on a node, which is not ok node string node address / name """ return ReportItem.error(report_codes.COROSYNC_RUNNING_ON_NODE, info={"node": node})
def live_environment_required(forbidden_options): return ReportItem.error( report_codes.LIVE_ENVIRONMENT_REQUIRED, info={ "forbidden_options": forbidden_options, } )
def corosync_config_parser_missing_closing_brace(): """ corosync config cannot be parsed due to missing closing brace """ return ReportItem.error( report_codes.PARSE_ERROR_COROSYNC_CONF_MISSING_CLOSING_BRACE, )
def agent_name_guess_found_none(agent): """ Specified agent doesn't exist string agent name of the agent which doesn't exist """ return ReportItem.error(report_codes.AGENT_NAME_GUESS_FOUND_NONE, info={"agent": agent})
def test_file_error(self, mock_config): self.mock_env.is_cman_cluster = False mock_config.side_effect = LibraryError( ReportItem.error(report_codes.UNABLE_TO_GET_SBD_CONFIG, )) assert_raise_library_error( lambda: cmd_sbd.get_local_sbd_config(self.mock_env), (Severities.ERROR, report_codes.UNABLE_TO_GET_SBD_CONFIG, {}))
def test_report_unprocessed_library_env_errors(self, mock_process_report): report1 = ReportItem.error("OTHER ERROR", "", info={}) report2 = ReportItem.error("OTHER ERROR", "", info={}) report3 = ReportItem.error("OTHER ERROR", "", info={}) e = LibraryEnvError(report1, report2, report3) e.sign_processed(report2) mock_middleware = mock.Mock(side_effect=e) binded = bind( cli_env=None, run_with_middleware=mock_middleware, run_library_command=None ) self.assertRaises(SystemExit, lambda: binded(cli_env=None)) mock_process_report.assert_called_once_with([report1, report3])
def cluster_state_invalid_format(): """ crm_mon xml output does not conform to the schema """ return ReportItem.error( report_codes.BAD_CLUSTER_STATE_FORMAT, )
def corosync_config_parser_unexpected_closing_brace(): """ corosync config cannot be parsed due to unexpected closing brace """ return ReportItem.error( report_codes.PARSE_ERROR_COROSYNC_CONF_UNEXPECTED_CLOSING_BRACE, )
def wait_for_idle_not_live_cluster(): """ cannot wait for the cluster if not running with a live cluster """ return ReportItem.error( report_codes.WAIT_FOR_IDLE_NOT_LIVE_CLUSTER, )
def empty_resource_set_list(): """ an empty resource set has been specified, which is not allowed by cib schema """ return ReportItem.error( report_codes.EMPTY_RESOURCE_SET_LIST, )
def qdevice_remove_or_cluster_stop_needed(): """ operation cannot be executed, qdevice removal or cluster stop is needed """ return ReportItem.error( report_codes.QDEVICE_REMOVE_OR_CLUSTER_STOP_NEEDED, )
def wait_for_idle_not_supported(): """ crm_resource does not support --wait """ return ReportItem.error( report_codes.WAIT_FOR_IDLE_NOT_SUPPORTED, )
def qdevice_already_defined(): """ qdevice is already set up in a cluster, when it was expected not to be """ return ReportItem.error( report_codes.QDEVICE_ALREADY_DEFINED, )
def qdevice_not_defined(): """ qdevice is not set up in a cluster, when it was expected to be """ return ReportItem.error( report_codes.QDEVICE_NOT_DEFINED, )
def rrp_addresses_transport_mismatch(): """ RRP defined by network addresses is not allowed when udp transport is used """ return ReportItem.error( report_codes.NON_UDP_TRANSPORT_ADDR_MISMATCH, )
def report_item_generator(i): if i == 1: raise NodeConnectionException("node", "command", "reason") elif i == 2: raise LibraryError( ReportItem.error(report_codes.COMMON_ERROR, ), ReportItem.info(report_codes.COMMON_INFO, ))
def cib_load_error_invalid_format(): """ cib does not conform to the schema """ return ReportItem.error( report_codes.CIB_LOAD_ERROR_BAD_FORMAT, )
def cman_unsupported_command(): """ requested library command is not available as local cluster is CMAN based """ return ReportItem.error( report_codes.CMAN_UNSUPPORTED_COMMAND, )
def invalid_timeout(timeout): """ specified timeout is not valid (number or other format e.g. 2min) timeout string specified invalid timeout """ return ReportItem.error(report_codes.INVALID_TIMEOUT_VALUE, info={"timeout": timeout})
def unable_to_determine_group_gid(group): return ReportItem.error( report_codes.UNABLE_TO_DETERMINE_GROUP_GID, info={ "group": group } )
def unable_to_determine_user_uid(user): return ReportItem.error( report_codes.UNABLE_TO_DETERMINE_USER_UID, info={ "user": user } )
def corosync_config_parser_other_error(): """ corosync config cannot be parsed, the cause is not specified It is better to use more specific error if possible. """ return ReportItem.error( report_codes.PARSE_ERROR_COROSYNC_CONF, )
def booth_tickets_status_error(reason=None): return ReportItem.error( report_codes.BOOTH_TICKET_STATUS_ERROR, "unable to get status of booth tickets", info={ "reason": reason, } )
def live_environment_required_for_local_node(): """ The operation cannot be performed on CIB in file (not live cluster) if no node name is specified i.e. working with the local node """ return ReportItem.error( report_codes.LIVE_ENVIRONMENT_REQUIRED_FOR_LOCAL_NODE, )
def file_does_not_exist(file_role, file_path=""): return ReportItem.error( report_codes.FILE_DOES_NOT_EXIST, info={ "file_role": file_role, "file_path": file_path, }, )
def multiple_score_options(): """ more than one of mutually exclusive score options has been set (score, score-attribute, score-attribute-mangle in rules or colocation sets) """ return ReportItem.error( report_codes.MULTIPLE_SCORE_OPTIONS, )
def resource_wait_not_supported(): """ crm_resource does not support --wait """ return ReportItem.error( report_codes.RESOURCE_WAIT_NOT_SUPPORTED, "crm_resource does not support --wait, please upgrade pacemaker" )
def test_regcognize_missing_report(self): self.assertTrue(env_file.is_missing_report( ReportItem.error( report_codes.FILE_DOES_NOT_EXIST, info={"file_role": "role"} ), "role" ))
def booth_peers_status_error(reason=None): return ReportItem.error( report_codes.BOOTH_PEERS_STATUS_ERROR, "unable to get status of booth peers", info={ "reason": reason, } )
def booth_cannot_determine_local_site_ip(): """ Some booth operations are performed on specific site and requires to specify site ip. When site specification omitted pcs can try determine local ip. But determine local site ip failed. """ return ReportItem.error(report_codes.BOOTH_CANNOT_DETERMINE_LOCAL_SITE_IP, info={})
def booth_daemon_status_error(reason): """ Unable to get status of booth daemon because of error. reason -- reason """ return ReportItem.error(report_codes.BOOTH_DAEMON_STATUS_ERROR, info={"reason": reason})
def corosync_running_on_node_fail(node): """ corosync is running on a node, which is not ok node string node address / name """ return ReportItem.error( report_codes.COROSYNC_RUNNING_ON_NODE, info={"node": node} )
def corosync_config_reload_error(reason): """ an error occured when reloading corosync configuration reason string an error message """ return ReportItem.error( report_codes.COROSYNC_CONFIG_RELOAD_ERROR, info={"reason": reason} )
def id_already_exists(id): """ specified id already exists in CIB and cannot be used for a new CIB object id string existing id """ return ReportItem.error( report_codes.ID_ALREADY_EXISTS, info={"id": id} )