def get_cib(argv): if len(argv) > 2: usage.cluster(["cib"]) sys.exit(1) filename = None scope = None for arg in argv: if "=" not in arg: filename = arg else: arg_name, arg_value = arg.split("=", 1) if arg_name == "scope" and "--config" not in utils.pcs_options: if not utils.is_valid_cib_scope(arg_value): utils.err("invalid CIB scope '%s'" % arg_value) else: scope = arg_value else: usage.cluster(["cib"]) sys.exit(1) if "--config" in utils.pcs_options: scope = "configuration" if not filename: print(utils.get_cib(scope).rstrip()) else: try: f = open(filename, 'w') output = utils.get_cib(scope) if output != "": f.write(output) else: utils.err("No data in the CIB") except IOError as e: utils.err("Unable to write to file '%s', %s" % (filename, e.strerror))
def cluster_edit(argv): if 'EDITOR' in os.environ: if len(argv) > 1: usage.cluster(["edit"]) sys.exit(1) scope = None scope_arg = "" for arg in argv: if "=" not in arg: usage.cluster(["edit"]) sys.exit(1) else: arg_name, arg_value = arg.split("=", 1) if arg_name == "scope" and "--config" not in utils.pcs_options: if not utils.is_valid_cib_scope(arg_value): utils.err("invalid CIB scope '%s'" % arg_value) else: scope_arg = arg scope = arg_value else: usage.cluster(["edit"]) sys.exit(1) if "--config" in utils.pcs_options: scope = "configuration" # Leave scope_arg empty as cluster_push will pick up a --config # option from utils.pcs_options scope_arg = "" editor = os.environ['EDITOR'] tempcib = tempfile.NamedTemporaryFile(mode="w+", suffix=".pcs") cib = utils.get_cib(scope) tempcib.write(cib) tempcib.flush() try: subprocess.call([editor, tempcib.name]) except OSError: utils.err("unable to open file with $EDITOR: " + editor) tempcib.seek(0) newcib = "".join(tempcib.readlines()) if newcib == cib: print("CIB not updated, no changes detected") else: cluster_push([arg for arg in [tempcib.name, scope_arg] if arg]) else: utils.err("$EDITOR environment variable is not set")
def config_export_pcs_commands(lib, argv, modifiers, verbose=False): """ Options: * --force - skip checks, overwrite files * --interactive - interactive issue resolving * -f - CIB file * --corosync_conf """ del lib modifiers.ensure_only_supported("--force", "--interactive", "-f", "--corosync_conf") if no_clufter: utils.err( "Unable to perform export due to missing python-clufter package") # parse options debug = modifiers.get("--debug") force = modifiers.get("--force") interactive = modifiers.get("--interactive") invalid_args = False output_file = None dist = None for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "output": output_file = value elif name == "dist": dist = value else: invalid_args = True else: invalid_args = True # check options if invalid_args: usage.config(["export pcs-commands"]) sys.exit(1) # complete optional options if dist is None: dist = _get_linux_dist() # prepare convertor options clufter_args = { "nocheck": force, "batch": True, "sys": "linux", "dist": dist, "coro": settings.corosync_conf_file, "start_wait": "60", "tmp_cib": "tmp-cib.xml", "force": force, "text_width": "80", "silent": True, "noguidance": True, } if output_file: clufter_args["output"] = {"passin": "bytestring"} else: clufter_args["output"] = "-" if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if utils.usefile: clufter_args["cib"] = os.path.abspath(utils.filename) else: clufter_args["cib"] = ("bytestring", utils.get_cib()) if verbose: clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) cmd_name = "pcs2pcscmd-camelback" # run convertor run_clufter( cmd_name, clufter_args_obj, debug, force, "Error: unable to export cluster configuration", ) # save commands if not printed to stdout by clufter if output_file: # pylint: disable=no-member ok, message = utils.write_file( output_file, clufter_args_obj.output["passout"].decode()) if not ok: utils.err(message)
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, constraints_reports.order_plain, modifiers.get_subset("-f", "--full"), )) all_lines.extend( constraint_command.show( "Colocation Constraints:", lib.constraint_colocation.show, constraints_reports.colocation_plain, modifiers.get_subset("-f", "--full"), )) all_lines.extend( constraint_command.show( "Ticket Constraints:", lib.constraint_ticket.show, constraints_reports.ticket_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, )) all_lines.append("") all_lines.append("Tags:") tags = lib.tag.config([]) if not tags: all_lines.append(" No tags defined") tag_lines = [] for tag in tags: tag_lines.append(tag["tag_id"]) tag_lines.extend(indent(tag["idref_list"])) all_lines.extend(indent(tag_lines, indent_step=1)) return all_lines
def config_export_pcs_commands(argv, verbose=False): if no_clufter: utils.err( "Unable to perform export due to missing python-clufter package") # parse options debug = "--debug" in utils.pcs_options force = "--force" in utils.pcs_options interactive = "--interactive" in utils.pcs_options invalid_args = False output_file = None dist = None for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "output": output_file = value elif name == "dist": dist = value else: invalid_args = True else: invalid_args = True # check options if invalid_args: usage.config(["export", "pcs-commands"]) sys.exit(1) # complete optional options if dist is None: dist = ",".join(platform.linux_distribution(full_distribution_name=0)) # prepare convertor options clufter_args = { "nocheck": force, "batch": True, "sys": "linux", "dist": dist, "coro": settings.corosync_conf_file, "ccs": settings.cluster_conf_file, "start_wait": "60", "tmp_cib": "tmp-cib.xml", "force": force, "text_width": "80", "silent": True, "noguidance": True, } if output_file: clufter_args["output"] = {"passin": "bytestring"} else: clufter_args["output"] = "-" if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if utils.usefile: clufter_args["cib"] = os.path.abspath(utils.filename) else: clufter_args["cib"] = ("bytestring", utils.get_cib()) if verbose: clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) cmd_name = "pcs2pcscmd-flatiron" if utils.is_rhel6( ) else "pcs2pcscmd-needle" # run convertor run_clufter(cmd_name, clufter_args_obj, debug, force, "Error: unable to export cluster configuration") # save commands if not printed to stdout by clufter if output_file: ok, message = utils.write_file( output_file, clufter_args_obj.output["passout"].decode()) if not ok: utils.err(message)
def config_export_pcs_commands(argv, verbose=False): if no_clufter: utils.err( "Unable to perform export due to missing python-clufter package" ) # parse options debug = "--debug" in utils.pcs_options force = "--force" in utils.pcs_options interactive = "--interactive" in utils.pcs_options invalid_args = False output_file = None dist = None for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "output": output_file = value elif name == "dist": dist = value else: invalid_args = True else: invalid_args = True # check options if invalid_args: usage.config(["export", "pcs-commands"]) sys.exit(1) # complete optional options if dist is None: dist = ",".join(platform.linux_distribution(full_distribution_name=0)) # prepare convertor options clufter_args = { "nocheck": force, "batch": True, "sys": "linux", "dist": dist, # Make it work on RHEL6 as well for sure "color": "always" if sys.stdout.isatty() else "never", "coro": settings.corosync_conf_file, "ccs": settings.cluster_conf_file, "start_wait": "60", "tmp_cib": "tmp-cib.xml", "force": force, "text_width": "80", "silent": True, "noguidance": True, } if output_file: clufter_args["output"] = {"passin": "bytestring"} else: clufter_args["output"] = "-" if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if utils.usefile: clufter_args["cib"] = os.path.abspath(utils.filename) else: clufter_args["cib"] = ("bytestring", utils.get_cib()) if verbose: clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) cmd_name = "pcs2pcscmd-flatiron" if utils.is_rhel6() else "pcs2pcscmd-needle" # run convertor run_clufter( cmd_name, clufter_args_obj, debug, force, "Error: unable to export cluster configuration" ) # save commands if not printed to stdout by clufter if output_file: ok, message = utils.write_file( output_file, clufter_args_obj.output["passout"] ) if not ok: utils.err(message)
def location_lines(constraintsElement, showDetail=False, byNode=False, valid_noderes=None, show_expired=False, verify_expiration=True): """ Commandline options: no options """ all_lines = [] nodehashon = {} nodehashoff = {} rschashon = {} rschashoff = {} ruleshash = defaultdict(list) all_loc_constraints = constraintsElement.getElementsByTagName( 'rsc_location') cib = utils.get_cib() if not isfile(settings.crm_rule): if verify_expiration: sys.stderr.write(CRM_RULE_MISSING_MSG) verify_expiration = False all_lines.append("Location Constraints:") for rsc_loc in all_loc_constraints: if rsc_loc.hasAttribute("rsc-pattern"): lc_rsc_type = RESOURCE_TYPE_REGEXP lc_rsc_value = rsc_loc.getAttribute("rsc-pattern") lc_name = "Resource pattern: {0}".format(lc_rsc_value) else: lc_rsc_type = RESOURCE_TYPE_RESOURCE lc_rsc_value = rsc_loc.getAttribute("rsc") lc_name = "Resource: {0}".format(lc_rsc_value) lc_rsc = lc_rsc_type, lc_rsc_value, lc_name lc_id = rsc_loc.getAttribute("id") lc_node = rsc_loc.getAttribute("node") lc_score = rsc_loc.getAttribute("score") lc_role = rsc_loc.getAttribute("role") lc_resource_discovery = rsc_loc.getAttribute("resource-discovery") for child in rsc_loc.childNodes: if child.nodeType == child.ELEMENT_NODE and child.tagName == "rule": ruleshash[lc_rsc].append(child) # NEED TO FIX FOR GROUP LOCATION CONSTRAINTS (where there are children of # rsc_location) if lc_score == "": lc_score = "0" if lc_score == "INFINITY": positive = True elif lc_score == "-INFINITY": positive = False elif int(lc_score) >= 0: positive = True else: positive = False if positive: nodeshash = nodehashon rschash = rschashon else: nodeshash = nodehashoff rschash = rschashoff hash_element = { "id": lc_id, "rsc_type": lc_rsc_type, "rsc_value": lc_rsc_value, "rsc_label": lc_name, "node": lc_node, "score": lc_score, "role": lc_role, "resource-discovery": lc_resource_discovery, } if lc_node in nodeshash: nodeshash[lc_node].append(hash_element) else: nodeshash[lc_node] = [hash_element] if lc_rsc in rschash: rschash[lc_rsc].append(hash_element) else: rschash[lc_rsc] = [hash_element] nodelist = sorted(set(list(nodehashon.keys()) + list(nodehashoff.keys()))) rsclist = sorted(set(list(rschashon.keys()) + list(rschashoff.keys())), key=lambda item: ({ RESOURCE_TYPE_RESOURCE: 1, RESOURCE_TYPE_REGEXP: 0, }[item[0]], item[1])) if byNode: for node in nodelist: if valid_noderes: if node not in valid_noderes: continue all_lines.append(" Node: " + node) nodehash_label = ((nodehashon, " Allowed to run:"), (nodehashoff, " Not allowed to run:")) all_lines += _hashtable_to_lines(nodehash_label, "rsc_label", node, showDetail) all_lines += _show_location_rules(ruleshash, cib, show_detail=showDetail, show_expired=show_expired, verify_expiration=verify_expiration) else: for rsc in rsclist: rsc_lines = [] if valid_noderes: if rsc[0:2] not in valid_noderes: continue rsc_lines.append(" {0}".format(rsc[2])) rschash_label = ( (rschashon, " Enabled on:"), (rschashoff, " Disabled on:"), ) rsc_lines += _hashtable_to_lines(rschash_label, "node", rsc, showDetail) miniruleshash = {} miniruleshash[rsc] = ruleshash[rsc] rsc_lines += _show_location_rules( miniruleshash, cib, show_detail=showDetail, show_expired=show_expired, verify_expiration=verify_expiration, noheader=True, ) # Append to all_lines only if the resource has any constraints if len(rsc_lines) > 2: all_lines += rsc_lines return all_lines
def config_export_pcs_commands(lib, argv, modifiers, verbose=False): """ Options: * --force - skip checks, overwrite files * --interactive - interactive issue resolving * -f - CIB file * --corosync_conf """ del lib modifiers.ensure_only_supported( "--force", "--interactive", "-f", "--corosync_conf" ) if no_clufter: utils.err( "Unable to perform export due to missing python-clufter package" ) # parse options debug = modifiers.get("--debug") force = modifiers.get("--force") interactive = modifiers.get("--interactive") invalid_args = False output_file = None dist = None for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "output": output_file = value elif name == "dist": dist = value else: invalid_args = True else: invalid_args = True # check options if invalid_args: usage.config(["export pcs-commands"]) sys.exit(1) # complete optional options if dist is None: dist = _get_linux_dist() # prepare convertor options clufter_args = { "nocheck": force, "batch": True, "sys": "linux", "dist": dist, "coro": settings.corosync_conf_file, "start_wait": "60", "tmp_cib": "tmp-cib.xml", "force": force, "text_width": "80", "silent": True, "noguidance": True, } if output_file: clufter_args["output"] = {"passin": "bytestring"} else: clufter_args["output"] = "-" if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if utils.usefile: clufter_args["cib"] = os.path.abspath(utils.filename) else: clufter_args["cib"] = ("bytestring", utils.get_cib()) if verbose: clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) cmd_name = "pcs2pcscmd-camelback" # run convertor run_clufter( cmd_name, clufter_args_obj, debug, force, "Error: unable to export cluster configuration" ) # save commands if not printed to stdout by clufter if output_file: # pylint: disable=no-member ok, message = utils.write_file( output_file, clufter_args_obj.output["passout"].decode() ) if not ok: utils.err(message)
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) ) 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