def _parse_bundle_groups(arg_list): repeatable_keyword_list = ["port-map", "storage-map"] keyword_list = ["meta", "container", "network"] + repeatable_keyword_list groups = group_by_keywords( arg_list, set(keyword_list), group_repeated_keywords=repeatable_keyword_list, only_found_keywords=True, ) for keyword in keyword_list: if keyword not in groups: continue if keyword in repeatable_keyword_list: for repeated_section in groups[keyword]: if len(repeated_section) == 0: raise CmdLineInputError( "No {0} options specified".format(keyword) ) else: if len(groups[keyword]) == 0: raise CmdLineInputError( "No {0} options specified".format(keyword) ) return groups
def config_destroy(lib, arg_list, modifiers): """ destroy booth config Options: --force - ignore config load issues --name - name of a booth instance """ modifiers.ensure_only_supported("--force", "--name") if arg_list: raise CmdLineInputError() lib.booth.config_destroy( instance_name=modifiers.get("--name"), ignore_config_load_problems=modifiers.get("--force"), )
def sbd_cmd(lib, argv, modifiers): if len(argv) == 0: raise CmdLineInputError() cmd = argv.pop(0) try: if cmd == "enable": sbd_enable(lib, argv, modifiers) elif cmd == "disable": sbd_disable(lib, argv, modifiers) elif cmd == "status": sbd_status(lib, argv, modifiers) elif cmd == "config": sbd_config(lib, argv, modifiers) elif cmd == "local_config_in_json": local_sbd_config(lib, argv, modifiers) elif cmd == "device": sbd_device_cmd(lib, argv, modifiers) elif cmd == "watchdog": sbd_watchdog_cmd(lib, argv, modifiers) else: cmd = "" raise CmdLineInputError() except CmdLineInputError as e: utils.exit_on_cmdline_input_errror(e, "stonith", "sbd {0}".format(cmd))
def unset_property(lib, argv, modifiers): """ Options: * --force - no error when removing not existing properties * -f - CIB file """ del lib modifiers.ensure_only_supported("--force", "-f") if not argv: raise CmdLineInputError() cib_dom = utils.get_cib_dom() for arg in argv: utils.set_cib_property(arg, "", cib_dom) utils.replace_cib_configuration(cib_dom)
def sbd_watchdog_test(lib, argv, modifiers): """ Options: no options """ modifiers.ensure_only_supported() if len(argv) > 1: raise CmdLineInputError() print("Warning: This operation is expected to force-reboot this system " "without following any shutdown procedures.") if utils.get_terminal_input("Proceed? [no/yes]: ") != "yes": return watchdog = None if len(argv) == 1: watchdog = argv[0] lib.sbd.test_local_watchdog(watchdog)
def qdevice_status_cmd(lib, argv, modifiers): """ Options: * --full - get more detailed output """ modifiers.ensure_only_supported("--full") if not argv or len(argv) > 2: raise CmdLineInputError() model = argv[0] cluster = None if len(argv) < 2 else argv[1] print( lib.qdevice.status( model, verbose=modifiers.get("--full"), cluster=cluster, ) )
def node_utilization_cmd(lib, argv, modifiers): """ Options: * -f - CIB file (in lib wrapper) * --name - specify attribute name to filter out """ modifiers.ensure_only_supported("-f", "--name") if modifiers.get("--name") and len(argv) > 1: raise CmdLineInputError() if len(argv) == 0: print_node_utilization(filter_name=modifiers.get("--name")) elif len(argv) == 1: print_node_utilization(argv.pop(0), filter_name=modifiers.get("--name")) else: set_node_utilization(argv.pop(0), argv)
def _sbd_parse_watchdogs(watchdog_list): """ Commandline options: no options """ ( default_watchdog_list, node_specific_watchdog_dict, ) = _sbd_parse_node_specific_options(watchdog_list) if not default_watchdog_list: default_watchdog = None elif len(default_watchdog_list) == 1: default_watchdog = default_watchdog_list[0] else: raise CmdLineInputError("Multiple watchdog definitions.") watchdog_dict = {} for node, node_watchdog_list in node_specific_watchdog_dict.items(): if len(node_watchdog_list) > 1: raise CmdLineInputError( "Multiple watchdog definitions for node '{node}'".format( node=node)) watchdog_dict[node] = node_watchdog_list[0] return default_watchdog, watchdog_dict
def acl_user(lib, argv, modifiers): if len(argv) < 1: raise CmdLineInputError() sub_cmd, argv_next = argv[0], argv[1:] try: if sub_cmd == "create": user_create(lib, argv_next, modifiers) elif sub_cmd in {"delete", "remove"}: user_delete(lib, argv_next, modifiers) else: usage.show("acl", ["user"]) sys.exit(1) except CmdLineInputError as e: utils.exit_on_cmdline_input_errror(e, "acl", "user {0}".format(sub_cmd))
def alert_add(lib, argv, modifiers): if not argv: raise CmdLineInputError() sections = parse_cmd_sections(argv, set(["options", "meta"])) main_args = prepare_options(sections["main"]) ensure_only_allowed_options(main_args, ["id", "description", "path"]) lib.alert.create_alert( main_args.get("id", None), main_args.get("path", None), prepare_options(sections["options"]), prepare_options(sections["meta"]), main_args.get("description", None) )
def quorum_device_remove_cmd(lib, argv, modifiers): """ Options: * --skip-offline - skip offline nodes * --corosync_conf - mocked corosync configuration file * --request-timeout - HTTP timeout, has effect only if --corosync_conf is not specified """ modifiers.ensure_only_supported("--skip-offline", "--request-timeout", "--corosync_conf") if argv: raise CmdLineInputError() lib.quorum.remove_device( skip_offline_nodes=modifiers.get("--skip-offline"))
def parse_add(arg_list): info, option_candidates = separate_tail_option_candidates(arg_list) if not info: raise CmdLineInputError("Ticket not specified") ticket, resource_specification = info[0], info[1:] if len(resource_specification) not in (1, 2): raise CmdLineInputError("invalid resource specification: '{0}'".format( " ".join(resource_specification))) if len(resource_specification) == 2: resource_role, resource_id = resource_specification else: resource_role = "" resource_id = resource_specification[0] return ( ticket, resource_id, resource_role, parse_args.prepare_options(option_candidates), )
def _parse_quorum_device_groups(arg_list): keyword_list = ["model", "heuristics"] groups = parse_args.group_by_keywords( arg_list, set(keyword_list), implicit_first_group_key="generic", keyword_repeat_allowed=False, only_found_keywords=True, ) for keyword in keyword_list: if keyword not in groups: continue if not groups[keyword]: raise CmdLineInputError("No {0} options specified".format(keyword)) return groups
def get_output_format(self, supported_formats: Set[str] = _OUTPUT_FORMAT_VALUES ) -> str: output_format = self.get(_OUTPUT_FORMAT_OPTION) if output_format in supported_formats: return cast(str, output_format) raise CmdLineInputError( ("Unknown value '{value}' for '{option}' option. Supported " "{value_pl} {is_pl}: {supported}").format( value=output_format, option=_OUTPUT_FORMAT_OPTION, value_pl=format_plural(supported_formats, "value"), is_pl=format_plural(supported_formats, "is"), supported=format_list(list(supported_formats)), ))
def create_in_cluster(lib, arg_list, modifiers): """ Options: * --force - allows to create booth resource even if its agent is not installed * -f - CIB file * --name - name of a booth instance """ modifiers.ensure_only_supported("--force", "-f", "--name") if len(arg_list) != 2 or arg_list[0] != "ip": raise CmdLineInputError() lib.booth.create_in_cluster( arg_list[1], instance_name=modifiers.get("--name"), allow_absent_resource_agent=modifiers.get("--force"))
def xml_status(lib, argv, modifiers): """ Options: * -f - CIB file """ del lib modifiers.ensure_only_supported("-f") if argv: raise CmdLineInputError() (output, retval) = utils.run(["crm_mon", "-1", "-r", "-X"], ignore_stderr=True) if retval != 0: utils.err("running crm_mon, is pacemaker running?") print(output.rstrip())
def restart(lib, arg_list, modifiers): """ Options: * --force - allow multiple * -f - CIB file * --name - name of a booth instance """ modifiers.ensure_only_supported("--force", "-f", "--name") if arg_list: raise CmdLineInputError() lib.booth.restart( resource_restart, allow_multiple=modifiers.get("--force"), )
def stonith_level_remove_cmd(lib, argv, modifiers): """ Options: * -f - CIB file """ modifiers.ensure_only_supported("-f") if not argv: raise CmdLineInputError() target_type, target_value, devices = None, None, None level = argv[0] if len(argv) > 1: target_type, target_value = stonith_level_parse_node(argv[1]) if len(argv) > 2: devices = stonith_level_normalize_devices(argv[2:]) try: lib.fencing_topology.remove_levels_by_params(level, target_type, target_value, devices) except LibraryError as e: # backward compatibility mode # Command parameters are: level, node, stonith, stonith... # Both the node and the stonith list are optional. If the node is # ommited and the stonith list is present, there is no way to figure it # out, since there is no specification of what the parameter is. Hence # the pre-lib code tried both. First it assumed the first parameter is # a node. If that fence level didn't exist, it assumed the first # parameter is a device. Since it was only possible to specify node as # a target back then, this is enabled only in that case. if target_type != TARGET_TYPE_NODE: raise e level_not_found = False for report_item in e.args: if ( # pylint: disable=no-member report_item.code == report_codes.CIB_FENCING_LEVEL_DOES_NOT_EXIST): level_not_found = True break if not level_not_found: raise e target_and_devices = [target_value] if devices: target_and_devices.extend(devices) try: lib.fencing_topology.remove_levels_by_params( level, None, None, target_and_devices) except LibraryError as e_second: raise LibraryError(*(e.args + e_second.args))
def set_property(lib, argv, modifiers): """ Options: * --force - allow unknown options * -f - CIB file """ del lib modifiers.ensure_only_supported("--force", "-f") if not argv: raise CmdLineInputError() prop_def_dict = utils.get_cluster_properties_definition() failed = False forced = modifiers.get("--force") properties = {} for arg in argv: args = arg.split('=') if len(args) != 2: utils.err("invalid property format: '{0}'".format(arg), False) failed = True elif not args[0]: utils.err("empty property name: '{0}'".format(arg), False) failed = True elif forced or args[1].strip() == "": properties[args[0]] = args[1] else: try: if utils.is_valid_cluster_property(prop_def_dict, args[0], args[1]): properties[args[0]] = args[1] else: utils.err( "invalid value of property: '{0}', (use --force to " "override)".format(arg), False) failed = True except utils.UnknownPropertyException: utils.err( "unknown cluster property: '{0}', (use --force to " "override)".format(args[0]), False) failed = True if failed: sys.exit(1) cib_dom = utils.get_cib_dom() for prop, value in properties.items(): utils.set_cib_property(prop, value, cib_dom) utils.replace_cib_configuration(cib_dom)
def stonith_level_clear_cmd(lib, argv, modifiers): """ Options: * -f - CIB file """ modifiers.ensure_only_supported("-f") if len(argv) > 1: raise CmdLineInputError() if not argv: lib.fencing_topology.remove_all_levels() return target_type, target_value = stonith_level_parse_node(argv[0]) # backward compatibility mode # Command parameters are: node, stonith-list # Both the node and the stonith list are optional. If the node is ommited # and the stonith list is present, there is no way to figure it out, since # there is no specification of what the parameter is. Hence the pre-lib # code tried both. It deleted all levels having the first parameter as # either a node or a device list. Since it was only possible to specify # node as a target back then, this is enabled only in that case. report_item_list = [] try: lib.fencing_topology.remove_levels_by_params( None, target_type, target_value, None, # pre-lib code didn't return any error when no level was found ignore_if_missing=True ) except LibraryError as e: report_item_list.extend(e.args) if target_type == TARGET_TYPE_NODE: try: lib.fencing_topology.remove_levels_by_params( None, None, None, argv[0].split(","), # pre-lib code didn't return any error when no level was found ignore_if_missing=True ) except LibraryError as e: report_item_list.extend(e.args) if report_item_list: raise LibraryError(*report_item_list)
def sbd_watchdog_list(lib, argv, modifiers): """ Options: no options """ modifiers.ensure_only_supported() if argv: raise CmdLineInputError() available_watchdogs = lib.sbd.get_local_available_watchdogs() if available_watchdogs: print("Available watchdog(s):") for watchdog in sorted(available_watchdogs.keys()): print(" {}".format(watchdog)) else: print("No available watchdog")
def recipient_update(lib, argv, modifiers): if len(argv) < 1: raise CmdLineInputError() recipient_id = argv[0] sections = parse_cmd_sections(argv[1:], set(["options", "meta"])) main_args = prepare_options(sections["main"]) ensure_only_allowed_options(main_args, ["description", "value"]) lib.alert.update_recipient(recipient_id, prepare_options(sections["options"]), prepare_options(sections["meta"]), recipient_value=main_args.get("value", None), description=main_args.get("description", None), allow_same_value=modifiers["force"])
def acl_permission(lib, argv, modifiers): if len(argv) < 1: raise CmdLineInputError() sub_cmd, argv_next = argv[0], argv[1:] try: if sub_cmd == "add": permission_add(lib, argv_next, modifiers) elif sub_cmd == "delete": run_permission_delete(lib, argv_next, modifiers) else: usage.show("acl", ["permission"]) sys.exit(1) except CmdLineInputError as e: utils.exit_on_cmdline_input_errror(e, "acl", "permission {0}".format(sub_cmd))
def acl_group(lib, argv, modifiers): if len(argv) < 1: raise CmdLineInputError() sub_cmd, argv_next = argv[0], argv[1:] try: if sub_cmd == "create": group_create(lib, argv_next, modifiers) elif sub_cmd == "delete": group_delete(lib, argv_next, modifiers) else: usage.show("acl", ["group"]) sys.exit(1) except CmdLineInputError as e: utils.exit_on_cmdline_input_errror(e, "acl", "group {0}".format(sub_cmd))
def config_show(lib, arg_list, modifiers): """ print booth config Options: * --name - name of a booth instace * --request-timeout - HTTP timeout for getting config from remote host """ modifiers.ensure_only_supported("--name", "--request-timeout") if len(arg_list) > 1: raise CmdLineInputError() node = None if not arg_list else arg_list[0] print( lib.booth.config_text(instance_name=modifiers.get("--name"), node_name=node).decode("utf-8").rstrip())
def stonith_list_options(lib, argv, modifiers): """ Options: * --full - show advanced options """ modifiers.ensure_only_supported("--full") if len(argv) != 1: raise CmdLineInputError() agent_name = argv[0] print( resource._format_agent_description( lib.stonith_agent.describe_agent(agent_name), stonith=True, show_all=modifiers.get("--full"), ))
def print_alert_config(lib, argv, modifiers): """ Options: * -f - CIB file (in lib wrapper) """ modifiers.ensure_only_supported("-f") if argv: raise CmdLineInputError() print("Alerts:") alert_list = lib.alert.get_all_alerts() if alert_list: for alert in alert_list: print("\n".join(indent(_alert_to_str(alert), 1))) else: print(" No alerts defined")
def quorum_unblock_cmd(lib, argv, modifiers): """ Options: * --force - no error when removing non existing property and no warning about this action """ modifiers.ensure_only_supported("--force") if len(argv) > 0: raise CmdLineInputError() output, retval = utils.run( ["corosync-cmapctl", "-g", "runtime.votequorum.wait_for_all_status"]) if retval != 0: utils.err("unable to check quorum status") if output.split("=")[-1].strip() != "1": utils.err("cluster is not waiting for nodes to establish quorum") unjoined_nodes = (set(utils.get_corosync_conf_facade().get_nodes_names()) - set(utils.getCorosyncActiveNodes())) if not unjoined_nodes: utils.err("no unjoined nodes found") if modifiers.get("--force"): answer = utils.get_terminal_input( ("WARNING: If node(s) {nodes} are not powered off or they do" + " have access to shared resources, data corruption and/or" + " cluster failure may occur. Are you sure you want to" + " continue? [y/N] ").format(nodes=", ".join(unjoined_nodes))) if answer.lower() not in ["y", "yes"]: print("Canceled") return for node in unjoined_nodes: # pass --force so no warning will be displayed stonith.stonith_confirm(lib, [node], parse_args.InputModifiers({"--force": ""})) output, retval = utils.run( ["corosync-cmapctl", "-s", "quorum.cancel_wait_for_all", "u8", "1"]) if retval != 0: utils.err("unable to cancel waiting for nodes") print("Quorum unblocked") startup_fencing = utils.get_set_properties().get("startup-fencing", "") utils.set_cib_property( "startup-fencing", "false" if startup_fencing.lower() != "false" else "true") utils.set_cib_property("startup-fencing", startup_fencing) print("Waiting for nodes canceled")
def prepare_options(cmdline_args, allowed_repeatable_options=()): """return dictionary of options from commandline key=value args""" options = dict() for arg in cmdline_args: name, value = split_option(arg) if name not in options: if name in allowed_repeatable_options: options[name] = [value] else: options[name] = value elif name in allowed_repeatable_options: options[name].append(value) elif options[name] != value: raise CmdLineInputError( "duplicate option '{0}' with different values '{1}' and '{2}'". format(name, options[name], value)) return options
def role_create(lib, argv, modifiers): """ Options: * -f - CIB file """ modifiers.ensure_only_supported("-f") if not argv: raise CmdLineInputError() role_id = argv.pop(0) description = "" desc_key = "description=" if argv and argv[0].startswith(desc_key) and len(argv[0]) > len(desc_key): description = argv.pop(0)[len(desc_key) :] permission_info_list = argv_to_permission_info_list(argv) lib.acl.create_role(role_id, permission_info_list, description)