def stonith_level_config_to_str(config): """ Commandline option: no options """ config_data = dict() for level in config: if level["target_type"] not in config_data: config_data[level["target_type"]] = dict() if level["target_value"] not in config_data[level["target_type"]]: config_data[level["target_type"]][level["target_value"]] = [] config_data[level["target_type"]][level["target_value"]].append(level) lines = [] for target_type in [ TARGET_TYPE_NODE, TARGET_TYPE_REGEXP, TARGET_TYPE_ATTRIBUTE ]: if not target_type in config_data: continue for target_value in sorted(config_data[target_type].keys()): lines.append( "Target: {0}".format("=".join(target_value) if target_type == TARGET_TYPE_ATTRIBUTE else target_value)) level_lines = [] for target_level in sorted(config_data[target_type][target_value], key=lambda level: level["level"]): level_lines.append("Level {level} - {devices}".format( level=target_level["level"], devices=",".join(target_level["devices"]))) lines.extend(indent(level_lines)) return lines
def show(caption, load_constraints, format_options, modifiers): """ load constraints and return console lines list with info about constraints string caption for example "Ticket Constraints:" callable load_constraints which returns desired constraints as dictionary like {"plain": [], "with_resource_sets": []} callable format_options takes dict of options and show_detail flag (bool) and returns string with constraint formated for commandline modifiers dict like object with command modifiers Commandline options: * -f - CIB file * --full - print more details """ show_detail = modifiers.get("--full") constraints = load_constraints() line_list = [caption] line_list.extend([ " " + format_options(constraint_options_dict, show_detail) for constraint_options_dict in constraints["plain"] ]) if constraints["with_resource_sets"]: line_list.extend( indent(show_constraints_with_set( constraints["with_resource_sets"], show_detail )) ) return line_list
def _alert_to_str(alert): content = [] content.extend(__description_attributes_to_str(alert)) recipients = [] for recipient in alert.get("recipient_list", []): recipients.extend(_recipient_to_str(recipient)) if recipients: content.append("Recipients:") content.extend(indent(recipients, 1)) return [ "Alert: {alert_id} (path={path})".format(alert_id=alert["id"], path=alert["path"]) ] + indent(content, 1)
def config_show(lib, argv, modifiers): """ Options: * -f - CIB file, when getting cluster name on remote node (corosync.conf doesn't exist) * --corosync_conf - corosync.conf file """ modifiers.ensure_only_supported("-f", "--corosync_conf") if argv: raise CmdLineInputError() print("Cluster Name: %s" % utils.getClusterName()) status.nodes_status(lib, ["config"], modifiers.get_subset("-f")) print() print("\n".join(_config_show_cib_lines(lib))) if (utils.hasCorosyncConf() and not modifiers.is_specified("-f") and not modifiers.is_specified("--corosync_conf")): cluster.cluster_uidgid(lib, [], modifiers.get_subset(), silent_list=True) if (modifiers.is_specified("--corosync_conf") or utils.hasCorosyncConf()): print() print("Quorum:") try: config = lib_quorum.get_config(utils.get_lib_env()) print("\n".join(indent(quorum.quorum_config_to_str(config)))) except LibraryError as e: process_library_reports(e.args)
def _config_site_lines(site_dto: DrConfigSiteDto) -> List[str]: lines = [f"Role: {site_dto.site_role.capitalize()}"] if site_dto.node_list: lines.append("Nodes:") lines.extend(indent(sorted([node.name for node in site_dto.node_list]))) return lines
def alert_config_lines(lib): lines = ["Alerts:"] alert_list = lib.alert.get_all_alerts() if alert_list: for alert in alert_list: lines.extend(indent(_alert_to_str(alert), 1)) else: lines.append(" No alerts defined") return lines
def config( lib: Any, argv: Sequence[str], modifiers: InputModifiers, ) -> None: """ Options: None """ modifiers.ensure_only_supported() if argv: raise CmdLineInputError() config_raw = lib.dr.get_config() try: config_dto = dto.from_dict(DrConfigDto, config_raw) except (KeyError, TypeError, ValueError): raise error("Unable to communicate with pcsd, received response:\n" f"{config_raw}") lines = ["Local site:"] lines.extend(indent(_config_site_lines(config_dto.local_site))) for site_dto in config_dto.remote_site_list: lines.append("Remote site:") lines.extend(indent(_config_site_lines(site_dto))) print("\n".join(lines))
def show_constraints_with_set(constraint_list, show_detail, indent_step=2): """ return list of console lines with info about constraints list of dict constraint_list see constraint in pcs/lib/exchange_formats.md bool with_id have to show id with options int indent_step is count of spaces for indenting Commandline options: no options """ return ["Resource Sets:"] + indent( [ console_report.constraint_with_sets(constraint, with_id=show_detail) for constraint in constraint_list ], indent_step=indent_step )
def quorum_config_to_str(config): """ Commandline options: no options """ lines = [] lines.append("Options:") if "options" in config and config["options"]: lines.extend(indent([ "{n}: {v}".format(n=name, v=value) for name, value in sorted(config["options"].items()) ])) if "device" in config and config["device"]: lines.append("Device:") lines.extend(indent([ "{n}: {v}".format(n=name, v=value) for name, value in sorted( config["device"].get("generic_options", {}).items() ) ])) model_settings = [ "Model: {m}".format(m=config["device"].get("model", "")) ] model_settings.extend(indent([ "{n}: {v}".format(n=name, v=value) for name, value in sorted( config["device"].get("model_options", {}).items() ) ])) lines.extend(indent(model_settings)) heuristics_options = config["device"].get("heuristics_options", {}) if heuristics_options: heuristics_settings = ["Heuristics:"] heuristics_settings.extend(indent([ "{n}: {v}".format(n=name, v=value) for name, value in sorted(heuristics_options.items()) ])) lines.extend(indent(heuristics_settings)) return lines
def print_stonith_levels(lib): levels = stonith_level_config_to_str(lib.fencing_topology.get_config()) if levels: print("\n".join(indent(levels, 1)))
def full_cluster_status_plaintext( env: LibraryEnvironment, hide_inactive_resources: bool = False, verbose: bool = False, ) -> str: """ Return full cluster status as plaintext env -- LibraryEnvironment hide_inactive_resources -- if True, do not display non-running resources verbose -- if True, display more info """ # pylint: disable=too-many-branches # pylint: disable=too-many-locals # validation if not env.is_cib_live and env.is_corosync_conf_live: raise LibraryError( reports.live_environment_not_consistent( [file_type_codes.CIB], [file_type_codes.COROSYNC_CONF], )) if env.is_cib_live and not env.is_corosync_conf_live: raise LibraryError( reports.live_environment_not_consistent( [file_type_codes.COROSYNC_CONF], [file_type_codes.CIB], )) # initialization runner = env.cmd_runner() report_processor = SimpleReportProcessor(env.report_processor) live = env.is_cib_live and env.is_corosync_conf_live is_sbd_running = False # load status, cib, corosync.conf status_text, warning_list = get_cluster_status_text( runner, hide_inactive_resources, verbose) corosync_conf = env.get_corosync_conf() cib = env.get_cib() if verbose: ticket_status_text, ticket_status_stderr, ticket_status_retval = ( get_ticket_status_text(runner)) # get extra info if live if live: try: is_sbd_running = is_service_running(runner, get_sbd_service_name()) except LibraryError: pass local_services_status = _get_local_services_status(runner) if verbose: node_name_list, node_names_report_list = get_existing_nodes_names( corosync_conf) report_processor.report_list(node_names_report_list) node_reachability = _get_node_reachability( env.get_node_target_factory(), env.get_node_communicator(), report_processor, node_name_list, ) # check stonith configuration warning_list = list(warning_list) warning_list.extend(_stonith_warnings(cib, is_sbd_running)) # put it all together if report_processor.has_errors: raise LibraryError() parts = [] parts.append(f"Cluster name: {corosync_conf.get_cluster_name()}") if warning_list: parts.extend(["", "WARNINGS:"] + warning_list + [""]) parts.append(status_text) if verbose: parts.extend(["", "Tickets:"]) if ticket_status_retval != 0: ticket_warning_parts = [ "WARNING: Unable to get information about tickets" ] if ticket_status_stderr: ticket_warning_parts.extend( indent(ticket_status_stderr.splitlines())) parts.extend(indent(ticket_warning_parts)) else: parts.extend(indent(ticket_status_text.splitlines())) if live: if verbose: parts.extend(["", "PCSD Status:"]) parts.extend( indent( _format_node_reachability(node_name_list, node_reachability))) parts.extend(["", "Daemon Status:"]) parts.extend( indent(_format_local_services_status(local_services_status))) return "\n".join(parts)
def _recipient_to_str(recipient): return [ "Recipient: {id} (value={value})".format(value=recipient["value"], id=recipient["id"]) ] + indent(__description_attributes_to_str(recipient), 1)
def _config_show_cib_lines(lib): """ Commandline options: * -f - CIB file """ # update of pcs_options will change output of constraint show utils.pcs_options["--full"] = 1 # get latest modifiers object after updating pcs_options modifiers = utils.get_input_modifiers() cib_xml = utils.get_cib() cib_etree = utils.get_cib_etree(cib_xml=cib_xml) cib_dom = utils.get_cib_dom(cib_xml=cib_xml) resource_lines = [] stonith_lines = [] for resource_el in cib_etree.find(".//resources"): is_stonith = ("class" in resource_el.attrib and resource_el.attrib["class"] == "stonith") resource_el_lines = resource.resource_node_lines(resource_el) if is_stonith: stonith_lines += resource_el_lines else: resource_lines += resource_el_lines all_lines = [] all_lines.append("Resources:") all_lines.extend(indent(resource_lines, indent_step=1)) all_lines.append("") all_lines.append("Stonith Devices:") all_lines.extend(indent(stonith_lines, indent_step=1)) all_lines.append("Fencing Levels:") levels_lines = stonith.stonith_level_config_to_str( lib.fencing_topology.get_config()) if levels_lines: all_lines.extend(indent(levels_lines, indent_step=2)) all_lines.append("") constraints_element = cib_dom.getElementsByTagName('constraints')[0] all_lines.extend( constraint.location_lines(constraints_element, showDetail=True, show_expired=True, verify_expiration=False)) all_lines.extend( constraint_command.show( "Ordering Constraints:", lib.constraint_order.show, order_console_report.constraint_plain, modifiers.get_subset("-f", "--full"), )) all_lines.extend( constraint_command.show( "Colocation Constraints:", lib.constraint_colocation.show, colocation_console_report.constraint_plain, modifiers.get_subset("-f", "--full"), )) all_lines.extend( constraint_command.show( "Ticket Constraints:", lib.constraint_ticket.show, ticket_console_report.constraint_plain, modifiers.get_subset("-f", "--full"), )) all_lines.append("") all_lines.extend(alert.alert_config_lines(lib)) all_lines.append("") all_lines.append("Resources Defaults:") all_lines.extend( indent(resource.show_defaults(cib_dom, "rsc_defaults"), indent_step=1)) all_lines.append("Operations Defaults:") all_lines.extend( indent(resource.show_defaults(cib_dom, "op_defaults"), indent_step=1)) all_lines.append("") all_lines.append("Cluster Properties:") properties = utils.get_set_properties() all_lines.extend( indent([ "{0}: {1}".format(prop, val) for prop, val in sorted(properties.items()) ], indent_step=1)) return all_lines
def role_to_str(role): out = [] if role.get("description"): out.append("Description: {0}".format(role.get("description"))) out += map(_permission_to_str, role.get("permission_list", [])) return ["Role: {0}".format(role.get("id"))] + indent(out)
def _target_group_to_str(type_name, obj): return ["{0}: {1}".format(type_name.title(), obj.get("id"))] + indent( [" ".join(["Roles:"] + obj.get("role_list", []))])