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 argv: 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") all_nodes, report_list = get_existing_nodes_names( utils.get_corosync_conf_facade() ) if report_list: utils.process_library_reports(report_list) unjoined_nodes = set(all_nodes) - set(utils.getCorosyncActiveNodes()) if not unjoined_nodes: utils.err("no unjoined nodes found") if not 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 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 argv: 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") all_nodes, report_list = get_existing_nodes_names( utils.get_corosync_conf_facade() ) if report_list: process_library_reports(report_list) unjoined_nodes = set(all_nodes) - set(utils.getCorosyncActiveNodes()) if not unjoined_nodes: utils.err("no unjoined nodes found") if not 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 is_service_running(service): """ Used in module pcs.config Commandline options: no options """ if utils.is_systemctl(): dummy_output, retval = utils.run(["systemctl", "status", service]) else: dummy_output, retval = utils.run(["service", service, "status"]) return retval == 0
def quorum_unblock_cmd(argv): if len(argv) > 0: usage.quorum(["unblock"]) sys.exit(1) if utils.is_rhel6(): utils.err("operation is not supported on CMAN clusters") 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.getNodesFromCorosyncConf()) - set(utils.getCorosyncActiveNodes()) ) if not unjoined_nodes: utils.err("no unjoined nodes found") if "--force" not in utils.pcs_options: 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: stonith.stonith_confirm([node], skip_question=True) 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 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 argv: raise CmdLineInputError() output, retval = utils.run( ["corosync-cmapctl", "-g", "runtime.votequorum.wait_for_all_status"]) if (retval == 1 and "Error CS_ERR_NOT_EXIST" in output) or ( retval == 0 and output.rsplit("=", maxsplit=1)[-1].strip() != "1"): utils.err("cluster is not waiting for nodes to establish quorum") if retval != 0: utils.err("unable to check quorum status") all_nodes, report_list = get_existing_nodes_names( utils.get_corosync_conf_facade()) if report_list: process_library_reports(report_list) unjoined_nodes = set(all_nodes) - set(utils.getCorosyncActiveNodes()) if not unjoined_nodes: utils.err("no unjoined nodes found") if not utils.get_continue_confirmation_or_force( f"If node(s) {format_list(unjoined_nodes)} are not powered off or they " "do have access to shared resources, data corruption and/or cluster " "failure may occur", modifiers.get("--force"), ): 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_to_stderr("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_to_stderr("Waiting for nodes canceled")
def pcs(testfile, args = ""): """Run pcs with -f on specified file Return tuple with: shell stdoutdata shell returncode """ if args == "": args = testfile testfile = temp_cib arg_split = args.split() arg_split_temp = [] in_quote = False for arg in arg_split: if in_quote: arg_split_temp[-1] = arg_split_temp[-1] + " " + arg.replace("'","") if arg.find("'") != -1: in_quote = False else: arg_split_temp.append(arg.replace("'","")) if arg.find("'") != -1 and not (arg[0] == "'" and arg[-1] == "'"): in_quote = True conf_opts = [] if "--corosync_conf" not in args: corosync_conf = rc("corosync.conf") conf_opts.append("--corosync_conf="+corosync_conf) if "--cluster_conf" not in args: cluster_conf = rc("cluster.conf") conf_opts.append("--cluster_conf="+cluster_conf) return utils.run([pcs_location, "-f", testfile] + conf_opts + arg_split_temp)
def cluster_status(lib, argv, modifiers): """ Options: * -f - CIB file * --request-timeout - HTTP timeout for checking status of pcsd, no effect if -f is specified """ modifiers.ensure_only_supported("-f", "--request-timeout") if argv: raise CmdLineInputError() (output, retval) = utils.run(["crm_mon", "-1", "-r"]) if retval != 0: utils.err("cluster is not currently running on this node") first_empty_line = False print("Cluster Status:") for line in output.splitlines(): if line == "": if first_empty_line: break first_empty_line = True continue print("", line) if not modifiers.is_specified("-f") and utils.hasCorosyncConf(): print() print_pcsd_daemon_status(lib, modifiers)
def full_status(): if "--hide-inactive" in utils.pcs_options and "--full" in utils.pcs_options: utils.err("you cannot specify both --hide-inactive and --full") monitor_command = ["crm_mon", "--one-shot"] if "--hide-inactive" not in utils.pcs_options: monitor_command.append('--inactive') if "--full" in utils.pcs_options: monitor_command.extend( ["--show-detail", "--show-node-attributes", "--failcounts"] ) output, retval = utils.run(monitor_command) if (retval != 0): utils.err("cluster is not currently running on this node") if not utils.usefile or "--corosync_conf" in utils.pcs_options: cluster_name = utils.getClusterName() print("Cluster name: %s" % cluster_name) if utils.stonithCheck(): print("WARNING: no stonith devices and stonith-enabled is not false") if not utils.is_rhel6() and utils.corosyncPacemakerNodeCheck(): print("WARNING: corosync and pacemaker node names do not match (IPs used in setup?)") print(output) if not utils.usefile: if "--full" in utils.pcs_options: print_pcsd_daemon_status() print() utils.serviceStatus(" ")
def fixture_attrs(self, nodes, attrs=None): attrs = dict() if attrs is None else attrs xml_lines = ["<nodes>"] for node_id, node_name in enumerate(nodes, 1): xml_lines.extend( [ '<node id="{0}" uname="{1}">'.format(node_id, node_name), '<instance_attributes id="nodes-{0}">'.format(node_id), ] ) nv = '<nvpair id="nodes-{id}-{name}" name="{name}" value="{val}"/>' for name, value in attrs.get(node_name, dict()).items(): xml_lines.append(nv.format(id=node_id, name=name, val=value)) xml_lines.extend(["</instance_attributes>", "</node>"]) xml_lines.append("</nodes>") utils_usefile_original = utils.usefile utils_filename_original = utils.filename utils.usefile = True utils.filename = self.temp_cib.name output, retval = utils.run( ["cibadmin", "--modify", "--xml-text", "\n".join(xml_lines)] ) utils.usefile = utils_usefile_original utils.filename = utils_filename_original assert output == "" assert retval == 0
def stonith_confirm(lib, argv, modifiers): """ Options: * --force - do not warn user """ del lib modifiers.ensure_only_supported("--force") if len(argv) != 1: utils.err("must specify one (and only one) node to confirm fenced") node = argv.pop(0) if not modifiers.get("--force"): answer = utils.get_terminal_input( ( "WARNING: If node {node} is not powered off or it does" + " have access to shared resources, data corruption and/or" + " cluster failure may occur. Are you sure you want to" + " continue? [y/N] " ).format(node=node) ) if answer.lower() not in ["y", "yes"]: print("Canceled") return args = ["stonith_admin", "-C", node] output, retval = utils.run(args) if retval != 0: utils.err("unable to confirm fencing of node '%s'\n" % node + output) else: print("Node: %s confirmed fenced" % node)
def stonith_confirm(lib, argv, modifiers): """ Options: * --force - do not warn user """ modifiers.ensure_only_supported("--force") if len(argv) != 1: utils.err("must specify one (and only one) node to confirm fenced") node = argv.pop(0) if not modifiers.get("--force"): answer = utils.get_terminal_input( ("WARNING: If node {node} is not powered off or it does" + " have access to shared resources, data corruption and/or" + " cluster failure may occur. Are you sure you want to" + " continue? [y/N] ").format(node=node)) if answer.lower() not in ["y", "yes"]: print("Canceled") return args = ["stonith_admin", "-C", node] output, retval = utils.run(args) if retval != 0: utils.err("unable to confirm fencing of node '%s'\n" % node + output) else: print("Node: %s confirmed fenced" % node)
def pcs(testfile, args): """ Run pcs with -f on specified file Return tuple with: shell stdoutdata shell returncode """ arg_split = args.split() arg_split_temp = [] in_quote = False for arg in arg_split: if in_quote: arg_split_temp[-1] = arg_split_temp[-1] + " " + arg.replace( "'", "") if arg.find("'") != -1: in_quote = False else: arg_split_temp.append(arg.replace("'", "")) if arg.find("'") != -1 and not (arg[0] == "'" and arg[-1] == "'"): in_quote = True conf_opts = [] if "--corosync_conf" not in args: corosync_conf = rc("corosync.conf") conf_opts.append("--corosync_conf=" + corosync_conf) if "--cluster_conf" not in args: cluster_conf = rc("cluster.conf") conf_opts.append("--cluster_conf=" + cluster_conf) return utils.run([__pcs_location, "-f", testfile] + conf_opts + arg_split_temp)
def fixture_attrs(self, nodes, attrs=None): attrs = dict() if attrs is None else attrs xml_lines = ['<nodes>'] for node_id, node_name in enumerate(nodes, 1): xml_lines.extend([ '<node id="{0}" uname="{1}">'.format(node_id, node_name), '<instance_attributes id="nodes-{0}">'.format(node_id), ]) nv = '<nvpair id="nodes-{id}-{name}" name="{name}" value="{val}"/>' for name, value in attrs.get(node_name, dict()).items(): xml_lines.append(nv.format(id=node_id, name=name, val=value)) xml_lines.extend([ '</instance_attributes>', '</node>' ]) xml_lines.append('</nodes>') utils_usefile_original = utils.usefile utils_filename_original = utils.filename utils.usefile = True utils.filename = temp_cib output, retval = utils.run([ "cibadmin", "--modify", '--xml-text', "\n".join(xml_lines) ]) utils.usefile = utils_usefile_original utils.filename = utils_filename_original assert output == "" assert retval == 0
def stop_cluster(argv): if len(argv) > 0: stop_cluster_nodes(argv) return if "--force" not in utils.pcs_options: output, dummy_retval = utils.run(["corosync-quorumtool", "-p", "-s"]) # retval is 0 on success if node is not in partition with quorum # retval is 1 on error OR on success if node has quorum try: if (corosync_live.QuorumStatus.from_string( output).stopping_local_node_cause_quorum_loss()): utils.err("Stopping the node will cause a loss of the quorum" + ", use --force to override") except corosync_live.QuorumStatusException: if not utils.is_node_offline_by_quorumtool_output(output): utils.err( "Unable to determine whether stopping the node will cause " + "a loss of the quorum, use --force to override") # else the node seems to be stopped already, proceed to be sure stop_all = ("--pacemaker" not in utils.pcs_options and "--corosync" not in utils.pcs_options) if stop_all or "--pacemaker" in utils.pcs_options: stop_cluster_pacemaker() if stop_all or "--corosync" in utils.pcs_options: stop_cluster_corosync()
def pcs(cib_file, args, corosync_conf_opt=None, mock_settings=None): """ Run pcs with -f on specified file Return tuple with: shell stdoutdata shell returncode """ if mock_settings is None: mock_settings = {} env_mock_settings_prefix = "PCS.SETTINGS." env = { "{}{}".format(env_mock_settings_prefix, option): value for option, value in mock_settings.items() } if test_installed: env["PCS_TEST.TEST_INSTALLED"] = "1" cmd = [__pcs_location] + args if cib_file: cmd.extend(["-f", cib_file]) if corosync_conf_opt: cmd.extend(["--corosync_conf", corosync_conf_opt]) return utils.run(cmd, env_extend=env)
def full_status(): if "--hide-inactive" in utils.pcs_options and "--full" in utils.pcs_options: utils.err("you cannot specify both --hide-inactive and --full") monitor_command = ["crm_mon", "--one-shot"] if "--hide-inactive" not in utils.pcs_options: monitor_command.append('--inactive') if "--full" in utils.pcs_options: monitor_command.extend( ["--show-detail", "--show-node-attributes", "--failcounts"]) output, retval = utils.run(monitor_command) if (retval != 0): utils.err("cluster is not currently running on this node") if not utils.usefile or "--corosync_conf" in utils.pcs_options: cluster_name = utils.getClusterName() print("Cluster name: %s" % cluster_name) status_stonith_check() if (not utils.usefile and not utils.is_rhel6() and utils.corosyncPacemakerNodeCheck()): print( "WARNING: corosync and pacemaker node names do not match (IPs used in setup?)" ) print(output) if not utils.usefile: if "--full" in utils.pcs_options and utils.hasCorosyncConf(): print_pcsd_daemon_status() print() utils.serviceStatus(" ")
def is_minimum_pacemaker_version(cmajor, cminor, crev): output, dummy_retval = utils.run(["crm_mon", "--version"]) pacemaker_version = output.split("\n")[0] r = re.compile(r"Pacemaker (\d+)\.(\d+)\.(\d+)") m = r.match(pacemaker_version) major = int(m.group(1)) minor = int(m.group(2)) rev = int(m.group(3)) return compare_version((major, minor, rev), (cmajor, cminor, crev)) > -1
def is_minimum_pacemaker_features(cmajor, cminor, crev): output, dummy_retval = utils.run(["pacemakerd", "--features"]) features_version = output.split("\n")[1] r = re.compile(r"Supporting v(\d+)\.(\d+)\.(\d+):") m = r.search(features_version) major = int(m.group(1)) minor = int(m.group(2)) rev = int(m.group(3)) return compare_version((major, minor, rev), (cmajor, cminor, crev)) > -1
def is_minimum_pacemaker_version(cmajor, cminor, crev): output, dummy_retval = utils.run(["crm_mon", "--version"]) pacemaker_version = output.split("\n")[0] r = re.compile(r"Pacemaker (\d+)\.(\d+)\.(\d+)") m = r.match(pacemaker_version) major = int(m.group(1)) minor = int(m.group(2)) rev = int(m.group(3)) return ( major > cmajor or (major == cmajor and minor > cminor) or (major == cmajor and minor == cminor and rev >= crev) )
def cluster_report(argv): if len(argv) != 1: usage.cluster(["report"]) sys.exit(1) outfile = argv[0] dest_outfile = outfile + ".tar.bz2" if os.path.exists(dest_outfile): if "--force" not in utils.pcs_options: utils.err(dest_outfile + " already exists, use --force to overwrite") else: try: os.remove(dest_outfile) except OSError as e: utils.err("Unable to remove " + dest_outfile + ": " + e.strerror) crm_report_opts = [] crm_report_opts.append("-f") if "--from" in utils.pcs_options: crm_report_opts.append(utils.pcs_options["--from"]) if "--to" in utils.pcs_options: crm_report_opts.append("-t") crm_report_opts.append(utils.pcs_options["--to"]) else: yesterday = datetime.datetime.now() - datetime.timedelta(1) crm_report_opts.append(yesterday.strftime("%Y-%m-%d %H:%M")) crm_report_opts.append(outfile) output, retval = utils.run([settings.crm_report] + crm_report_opts) if (retval != 0 and "ERROR: Cannot determine nodes; specify --nodes or --single-node" in output): utils.err("cluster is not configured on this node") newoutput = "" for line in output.split("\n"): if line.startswith("cat:") or line.startswith( "grep") or line.startswith("grep") or line.startswith("tail"): continue if "We will attempt to remove" in line: continue if "-p option" in line: continue if "However, doing" in line: continue if "to diagnose" in line: continue if "--dest" in line: line = line.replace("--dest", "<dest>") newoutput = newoutput + line + "\n" if retval != 0: utils.err(newoutput) print(newoutput)
def testNodeProperties(self): utils.usefile = True utils.filename = temp_cib o,r = utils.run(["cibadmin","-M", '--xml-text', '<nodes><node id="1" uname="rh7-1"><instance_attributes id="nodes-1"/></node><node id="2" uname="rh7-2"><instance_attributes id="nodes-2"/></node></nodes>']) ac(o,"") assert r == 0 o,r = pcs("property set --node=rh7-1 IP=192.168.1.1") ac(o,"") assert r==0 o,r = pcs("property set --node=rh7-2 IP=192.168.2.2") ac(o,"") assert r==0 o,r = pcs("property") ac(o,"Cluster Properties:\nNode Attributes:\n rh7-1: IP=192.168.1.1\n rh7-2: IP=192.168.2.2\n") assert r==0 o,r = pcs("property set --node=rh7-2 IP=") ac(o,"") assert r==0 o,r = pcs("property") ac(o,"Cluster Properties:\nNode Attributes:\n rh7-1: IP=192.168.1.1\n") assert r==0 o,r = pcs("property set --node=rh7-1 IP=192.168.1.1") ac(o,"") assert r==0 o,r = pcs("property set --node=rh7-2 IP=192.168.2.2") ac(o,"") assert r==0 o,r = pcs("property") ac(o,"Cluster Properties:\nNode Attributes:\n rh7-1: IP=192.168.1.1\n rh7-2: IP=192.168.2.2\n") assert r==0 o,r = pcs("property unset --node=rh7-1 IP") ac(o,"") assert r==0 o,r = pcs("property") ac(o,"Cluster Properties:\nNode Attributes:\n rh7-2: IP=192.168.2.2\n") assert r==0 o,r = pcs("property unset --node=rh7-1 IP") ac(o,"Error: attribute: 'IP' doesn't exist for node: 'rh7-1'\n") assert r==2 o,r = pcs("property unset --node=rh7-1 IP --force") ac(o,"") assert r==0
def corosync_status(dummy_lib, argv, modifiers): """ Options: no options """ modifiers.ensure_only_supported() if argv: raise CmdLineInputError() (output, retval) = utils.run(["corosync-quorumtool", "-l"]) if retval != 0: utils.err("corosync not running") else: print(output.rstrip())
def stonith_confirm(argv): if len(argv) != 1: utils.err("must specify one (and only one) node to confirm fenced") node = argv.pop(0) args = ["stonith_admin", "-C", node] output, retval = utils.run(args) if retval != 0: utils.err("unable to confirm fencing of node '%s'\n" % node + output) else: print("Node: %s confirmed fenced" % node)
def full_status(): if "--hide-inactive" in utils.pcs_options and "--full" in utils.pcs_options: utils.err("you cannot specify both --hide-inactive and --full") monitor_command = ["crm_mon", "--one-shot"] if "--hide-inactive" not in utils.pcs_options: monitor_command.append('--inactive') if "--full" in utils.pcs_options: monitor_command.extend( ["--show-detail", "--show-node-attributes", "--failcounts"]) output, retval = utils.run(monitor_command) if (retval != 0): utils.err("cluster is not currently running on this node") if not utils.usefile or "--corosync_conf" in utils.pcs_options: cluster_name = utils.getClusterName() print("Cluster name: %s" % cluster_name) status_stonith_check() print(output) if "--full" in utils.pcs_options: tickets, retval = utils.run(["crm_ticket", "-L"]) if retval != 0: print("WARNING: Unable to get information about tickets") print() elif tickets: print("Tickets:") print("\n".join(indent(tickets.split("\n")))) if not utils.usefile: if "--full" in utils.pcs_options and utils.hasCorosyncConf(): print_pcsd_daemon_status() print() utils.serviceStatus(" ")
def node_maintenance(argv, on=True): action = ["-v", "on"] if on else ["-D"] cluster_nodes = utils.getNodesFromPacemaker() nodes = [] failed_count = 0 if "--all" in utils.pcs_options: nodes = cluster_nodes elif argv: for node in argv: if node not in cluster_nodes: utils.err( "Node '{0}' does not appear to exist in " "configuration".format(node), False ) failed_count += 1 else: nodes.append(node) else: nodes.append("") if failed_count > 0: sys.exit(1) for node in nodes: node_attr = ["-N", node] if node else [] output, retval = utils.run( ["crm_attribute", "-t", "nodes", "-n", "maintenance"] + action + node_attr ) if retval != 0: node_name = ("node '{0}'".format(node)) if argv else "current node" failed_count += 1 if on: utils.err( "Unable to put {0} to maintenance mode: {1}".format( node_name, output ), False ) else: utils.err( "Unable to remove {0} from maintenance mode: {1}".format( node_name, output ), False ) if failed_count > 0: sys.exit(1)
def xml_status(dummy_lib, argv, modifiers): """ Options: * -f - CIB file """ 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 stonith_fence(argv): if len(argv) != 1: utils.err("must specify one (and only one) node to fence") node = argv.pop(0) if "--off" in utils.pcs_options: args = ["stonith_admin", "-F", node] else: args = ["stonith_admin", "-B", node] output, retval = utils.run(args) if retval != 0: utils.err("unable to fence '%s'\n" % node + output) else: print("Node: %s fenced" % node)
def kill_local_cluster_services(): all_cluster_daemons = [ # Daemons taken from cluster-clean script in pacemaker "pacemaker-attrd", "pacemaker-based", "pacemaker-controld", "pacemaker-execd", "pacemaker-fenced", "pacemaker-remoted", "pacemaker-schedulerd", "pacemakerd", "dlm_controld", "gfs_controld", # Corosync daemons "corosync-qdevice", "corosync", ] return utils.run(["killall", "-9"] + all_cluster_daemons)
def cluster_status(argv): (output, retval) = utils.run(["crm_mon", "-1", "-r"]) if (retval != 0): utils.err("cluster is not currently running on this node") first_empty_line = False print("Cluster Status:") for line in output.splitlines(): if line == "": if first_empty_line: break first_empty_line = True continue else: print("",line) if not utils.usefile and utils.hasCorosyncConf(): print() print_pcsd_daemon_status()
def stonith_fence(dummy_lib, argv, modifiers): """ Options: * --off - use off action of fence agent """ modifiers.ensure_only_supported("--off") if len(argv) != 1: utils.err("must specify one (and only one) node to fence") node = argv.pop(0) if modifiers.get("--off"): args = ["stonith_admin", "-F", node] else: args = ["stonith_admin", "-B", node] output, retval = utils.run(args) if retval != 0: utils.err("unable to fence '%s'\n" % node + output) else: print("Node: %s fenced" % node)
def cluster_status(argv): (output, retval) = utils.run(["crm_mon", "-1", "-r"]) if (retval != 0): utils.err("cluster is not currently running on this node") first_empty_line = False print("Cluster Status:") for line in output.splitlines(): if line == "": if first_empty_line: break first_empty_line = True continue else: print("", line) if not utils.usefile and utils.hasCorosyncConf(): print() print_pcsd_daemon_status()
def node_maintenance(argv, on=True): action = ["-v", "on"] if on else ["-D"] cluster_nodes = utils.getNodesFromPacemaker() nodes = [] failed_count = 0 if "--all" in utils.pcs_options: nodes = cluster_nodes elif argv: for node in argv: if node not in cluster_nodes: utils.err( "Node '{0}' does not appear to exist in " "configuration".format(node), False) failed_count += 1 else: nodes.append(node) else: nodes.append("") if failed_count > 0: sys.exit(1) for node in nodes: node_attr = ["-N", node] if node else [] output, retval = utils.run( ["crm_attribute", "-t", "nodes", "-n", "maintenance"] + action + node_attr) if retval != 0: node_name = ("node '{0}'".format(node)) if argv else "current node" failed_count += 1 if on: utils.err( "Unable to put {0} to maintenance mode: {1}".format( node_name, output), False) else: utils.err( "Unable to remove {0} from maintenance mode: {1}".format( node_name, output), False) if failed_count > 0: sys.exit(1)
def stonith_fence(lib, argv, modifiers): """ Options: * --off - use off action of fence agent """ del lib modifiers.ensure_only_supported("--off") if len(argv) != 1: utils.err("must specify one (and only one) node to fence") node = argv.pop(0) if modifiers.get("--off"): args = ["stonith_admin", "-F", node] else: args = ["stonith_admin", "-B", node] output, retval = utils.run(args) if retval != 0: utils.err("unable to fence '%s'\n" % node + output) else: print("Node: %s fenced" % node)
def stonith_confirm(argv, skip_question=False): if len(argv) != 1: utils.err("must specify one (and only one) node to confirm fenced") node = argv.pop(0) if not skip_question and "--force" not in utils.pcs_options: answer = utils.get_terminal_input( ("WARNING: If node {node} is not powered off or it does" + " have access to shared resources, data corruption and/or" + " cluster failure may occur. Are you sure you want to" + " continue? [y/N] ").format(node=node)) if answer.lower() not in ["y", "yes"]: print("Canceled") return args = ["stonith_admin", "-C", node] output, retval = utils.run(args) if retval != 0: utils.err("unable to confirm fencing of node '%s'\n" % node + output) else: print("Node: %s confirmed fenced" % node)
def pcs( cib_file, args, corosync_conf_opt=None, mock_settings=None ): """ Run pcs with -f on specified file Return tuple with: shell stdoutdata shell returncode """ if mock_settings is None: mock_settings = {} arg_split = args.split() arg_split_temp = [] in_quote = False for arg in arg_split: if in_quote: arg_split_temp[-1] = arg_split_temp[-1] + " " + arg.replace("'", "") if arg.find("'") != -1: in_quote = False else: arg_split_temp.append(arg.replace("'", "")) if arg.find("'") != -1 and not (arg[0] == "'" and arg[-1] == "'"): in_quote = True env_mock_settings_prefix = "PCS.SETTINGS." env = { "{}{}".format(env_mock_settings_prefix, option): value for option, value in mock_settings.items() } if test_installed: env["PCS_TEST.TEST_INSTALLED"] = "1" cmd = [__pcs_location] + arg_split_temp if cib_file: cmd.extend(["-f", cib_file]) if corosync_conf_opt: cmd.extend(["--corosync_conf", corosync_conf_opt]) return utils.run(cmd, env_extend=env)
def stonith_confirm(lib, argv, modifiers): """ Options: * --force - do not warn user """ del lib modifiers.ensure_only_supported("--force") if len(argv) != 1: utils.err("must specify one (and only one) node to confirm fenced") node = argv.pop(0) if not utils.get_continue_confirmation_or_force( f"If node '{node}' is not powered off or it does have access to shared " "resources, data corruption and/or cluster failure may occur", modifiers.get("--force"), ): return args = ["stonith_admin", "-C", node] output, retval = utils.run(args) if retval != 0: utils.err("unable to confirm fencing of node '%s'\n" % node + output) else: print("Node: %s confirmed fenced" % node)
def stonith_confirm(argv, skip_question=False): if len(argv) != 1: utils.err("must specify one (and only one) node to confirm fenced") node = argv.pop(0) if not skip_question and "--force" not in utils.pcs_options: answer = utils.get_terminal_input( ( "WARNING: If node {node} is not powered off or it does" + " have access to shared resources, data corruption and/or" + " cluster failure may occur. Are you sure you want to" + " continue? [y/N] " ).format(node=node) ) if answer.lower() not in ["y", "yes"]: print("Canceled") return args = ["stonith_admin", "-C", node] output, retval = utils.run(args) if retval != 0: utils.err("unable to confirm fencing of node '%s'\n" % node + output) else: print("Node: %s confirmed fenced" % node)
def skip_unless_pacemaker_supports_systemd(): output, dummy_retval = utils.run(["pacemakerd", "--features"]) return skipUnless( "systemd" in output, "Pacemaker does not support systemd resources" )
def skip_unless_pacemaker_supports_systemd(): output, dummy_retval = utils.run(["pacemakerd", "--features"]) return skipUnless("systemd" in output, "Pacemaker does not support systemd resources")
def is_corosyc_running(): if utils.is_systemctl(): dummy_output, retval = utils.run(["systemctl", "status", "corosync.service"]) else: dummy_output, retval = utils.run(["service", "corosync", "status"]) return retval == 0
def is_pacemaker_running(): if utils.is_systemctl(): dummy_output, retval = utils.run(["systemctl", "status", "pacemaker.service"]) else: dummy_output, retval = utils.run(["service", "pacemaker", "status"]) return retval == 0
def corosync_status(): (output, retval) = utils.run(["corosync-quorumtool", "-l"]) if retval != 0: utils.err("corosync not running") else: print(output, end="")
def xml_status(): (output, retval) = utils.run(["crm_mon", "-1", "-r", "-X"]) if (retval != 0): utils.err("running crm_mon, is pacemaker running?") print(output, end="")
def is_service_running(service): if utils.is_systemctl(): dummy_output, retval = utils.run(["systemctl", "status", service]) else: dummy_output, retval = utils.run(["service", service, "status"]) return retval == 0
def corosync_status(): (output, retval) = utils.run(["corosync-quorumtool", "-l"]) if retval != 0: utils.err("corosync not running") else: print(output.rstrip())
def xml_status(): (output, retval) = utils.run(["crm_mon", "-1", "-r", "-X"]) if (retval != 0): utils.err("running crm_mon, is pacemaker running?") print(output.rstrip())
def full_status(lib, argv, modifiers): """ Options: * --hide-inactive - hide inactive resources * --full - show full details, node attributes and failcount * -f - CIB file, crm_mon accepts CIB_file environment variable * --corosync_conf - file corocync.conf * --request-timeout - HTTP timeout for node authorization check """ modifiers.ensure_only_supported( "--hide-inactive", "--full", "-f", "--corosync_conf", "--request-timeout", ) if argv: raise CmdLineInputError() if (modifiers.is_specified("--hide-inactive") and modifiers.is_specified("--full")): utils.err("you cannot specify both --hide-inactive and --full") monitor_command = [ os.path.join(settings.pacemaker_binaries, "crm_mon"), "--one-shot" ] if not modifiers.get("--hide-inactive"): monitor_command.append('--inactive') if modifiers.get("--full"): monitor_command.extend( ["--show-detail", "--show-node-attributes", "--failcounts"]) # by default, pending and failed actions are displayed # with --full, we display the whole history if is_fence_history_supported(): monitor_command.append("--fence-history=3") stdout, stderr, retval = utils.cmd_runner().run(monitor_command) if retval != 0: utils.err("cluster is not currently running on this node") warnings = [] if stderr.strip(): for line in stderr.strip().splitlines(): if line.startswith("DEBUG: "): if modifiers.get("--full"): warnings.append(line) else: warnings.append(line) warnings.extend(status_stonith_check(modifiers)) print("Cluster name: %s" % utils.getClusterName()) if warnings: print() print("WARNINGS:") print("\n".join(warnings)) print() print(stdout) if modifiers.get("--full"): tickets, retval = utils.run(["crm_ticket", "-L"]) if retval != 0: print("WARNING: Unable to get information about tickets") print() elif tickets: print("Tickets:") print("\n".join(indent(tickets.split("\n")))) if not (modifiers.is_specified("-f") or modifiers.is_specified("--corosync_conf")): # do this only if in live environment if modifiers.get("--full"): print_pcsd_daemon_status(lib, modifiers) print() utils.serviceStatus(" ")