def dom_rule_add(dom_element, argv): options = {"id": None, "role": None, "score": None, "score-attribute": None} # parse options while argv: found = False option = argv.pop(0) for name in options: if option.startswith(name + "="): options[name] = option.split("=", 1)[1] found = True break if not found: argv.insert(0, option) break # validate options if options["score"] and options["score-attribute"]: utils.err("can not specify both score and score-attribute") if options["score"] and not utils.is_score(options["score"]): # preserving legacy behaviour print("Warning: invalid score '%s', setting score-attribute=pingd instead" % options["score"]) options["score-attribute"] = "pingd" options["score"] = None if options["role"] and options["role"] not in ["master", "slave"]: utils.err("invalid role '%s', use 'master' or 'slave'" % options["role"]) if options["id"]: id_valid, id_error = utils.validate_xml_id(options["id"], "rule id") if not id_valid: utils.err(id_error) if utils.does_id_exist(dom_element.ownerDocument, options["id"]): utils.err("id '%s' is already in use, please specify another one" % options["id"]) # parse rule if not argv: utils.err("no rule expression was specified") try: dom_rule = CibBuilder().build(dom_element, RuleParser().parse(TokenPreprocessor().run(argv)), options["id"]) except SyntaxError as e: utils.err("'%s' is not a valid rule expression: %s" % (" ".join(argv), e)) except UnexpectedEndOfInput as e: utils.err("'%s' is not a valid rule expression: unexpected end of rule" % " ".join(argv)) except (ParserException, CibBuilderException) as e: utils.err("'%s' is not a valid rule expression" % " ".join(argv)) # add options into rule xml if not options["score"] and not options["score-attribute"]: options["score"] = "INFINITY" for name, value in options.iteritems(): if name != "id" and value is not None: dom_rule.setAttribute(name, value) # score or score-attribute is required for the nested rules in order to have # valid CIB, pacemaker does not use the score of the nested rules for rule in dom_rule.getElementsByTagName("rule"): rule.setAttribute("score", "0") if dom_element.hasAttribute("score"): dom_element.removeAttribute("score") if dom_element.hasAttribute("node"): dom_element.removeAttribute("node") return dom_element
def location_prefer(argv): rsc = argv.pop(0) prefer_option = argv.pop(0) if prefer_option == "prefers": prefer = True elif prefer_option == "avoids": prefer = False else: usage.constraint() sys.exit(1) for nodeconf in argv: nodeconf_a = nodeconf.split("=",1) if len(nodeconf_a) == 1: node = nodeconf_a[0] if prefer: score = "INFINITY" else: score = "-INFINITY" else: score = nodeconf_a[1] if not utils.is_score(score): utils.err("invalid score '%s', use integer or INFINITY or -INFINITY" % score) if not prefer: if score[0] == "-": score = score[1:] else: score = "-" + score node = nodeconf_a[0] location_add(["location-" +rsc+"-"+node+"-"+score,rsc,node,score])
def location_add(argv, rm=False): if len(argv) != 4 and (rm == False or len(argv) < 1): usage.constraint() sys.exit(1) constraint_id = argv.pop(0) # If we're removing, we only care about the id if (rm == True): resource_name = "" node = "" score = "" else: id_valid, id_error = utils.validate_xml_id(constraint_id, 'constraint id') if not id_valid: utils.err(id_error) resource_name = argv.pop(0) node = argv.pop(0) score = argv.pop(0) resource_valid, resource_error = utils.validate_constraint_resource( utils.get_cib_dom(), resource_name) if not resource_valid: utils.err(resource_error) if not utils.is_score(score): utils.err( "invalid score '%s', use integer or INFINITY or -INFINITY" % score) # Verify current constraint doesn't already exist # If it does we replace it with the new constraint (dom, constraintsElement) = getCurrentConstraints() elementsToRemove = [] # If the id matches, or the rsc & node match, then we replace/remove for rsc_loc in constraintsElement.getElementsByTagName('rsc_location'): if (constraint_id == rsc_loc.getAttribute("id")) or \ (rsc_loc.getAttribute("rsc") == resource_name and \ rsc_loc.getAttribute("node") == node and not rm): elementsToRemove.append(rsc_loc) for etr in elementsToRemove: constraintsElement.removeChild(etr) if (rm == True and len(elementsToRemove) == 0): utils.err("resource location id: " + constraint_id + " not found.") if (not rm): element = dom.createElement("rsc_location") element.setAttribute("id", constraint_id) element.setAttribute("rsc", resource_name) element.setAttribute("node", node) element.setAttribute("score", score) constraintsElement.appendChild(element) utils.replace_cib_configuration(dom)
def dom_rule_add(dom_element, options, rule_argv): # validate options if options.get("score") and options.get("score-attribute"): utils.err("can not specify both score and score-attribute") if options.get("score") and not utils.is_score(options["score"]): # preserving legacy behaviour print( "Warning: invalid score '%s', setting score-attribute=pingd instead" % options["score"]) options["score-attribute"] = "pingd" options["score"] = None if options.get("role") and options["role"] not in ["master", "slave"]: utils.err("invalid role '%s', use 'master' or 'slave'" % options["role"]) if options.get("id"): id_valid, id_error = utils.validate_xml_id(options["id"], 'rule id') if not id_valid: utils.err(id_error) if utils.does_id_exist(dom_element.ownerDocument, options["id"]): utils.err("id '%s' is already in use, please specify another one" % options["id"]) # parse rule if not rule_argv: utils.err("no rule expression was specified") try: dom_rule = CibBuilder().build( dom_element, RuleParser().parse(TokenPreprocessor().run(rule_argv)), options.get("id")) except SyntaxError as e: utils.err("'%s' is not a valid rule expression: %s" % (" ".join(rule_argv), e)) except UnexpectedEndOfInput as e: utils.err( "'%s' is not a valid rule expression: unexpected end of rule" % " ".join(rule_argv)) except (ParserException, CibBuilderException) as e: utils.err("'%s' is not a valid rule expression" % " ".join(rule_argv)) # add options into rule xml if not options.get("score") and not options.get("score-attribute"): options["score"] = "INFINITY" for name, value in options.iteritems(): if name != "id" and value is not None: dom_rule.setAttribute(name, value) # score or score-attribute is required for the nested rules in order to have # valid CIB, pacemaker does not use the score of the nested rules for rule in dom_rule.getElementsByTagName("rule"): rule.setAttribute("score", "0") if dom_element.hasAttribute("score"): dom_element.removeAttribute("score") if dom_element.hasAttribute("node"): dom_element.removeAttribute("node") return dom_element
def location_add(argv,rm=False): if len(argv) != 4 and (rm == False or len(argv) < 1): usage.constraint() sys.exit(1) constraint_id = argv.pop(0) # If we're removing, we only care about the id if (rm == True): resource_name = "" node = "" score = "" else: id_valid, id_error = utils.validate_xml_id(constraint_id, 'constraint id') if not id_valid: utils.err(id_error) resource_name = argv.pop(0) node = argv.pop(0) score = argv.pop(0) resource_valid, resource_error = utils.validate_constraint_resource( utils.get_cib_dom(), resource_name ) if not resource_valid: utils.err(resource_error) if not utils.is_score(score): utils.err("invalid score '%s', use integer or INFINITY or -INFINITY" % score) # Verify current constraint doesn't already exist # If it does we replace it with the new constraint (dom,constraintsElement) = getCurrentConstraints() elementsToRemove = [] # If the id matches, or the rsc & node match, then we replace/remove for rsc_loc in constraintsElement.getElementsByTagName('rsc_location'): if (constraint_id == rsc_loc.getAttribute("id")) or \ (rsc_loc.getAttribute("rsc") == resource_name and \ rsc_loc.getAttribute("node") == node and not rm): elementsToRemove.append(rsc_loc) for etr in elementsToRemove: constraintsElement.removeChild(etr) if (rm == True and len(elementsToRemove) == 0): utils.err("resource location id: " + constraint_id + " not found.") if (not rm): element = dom.createElement("rsc_location") element.setAttribute("id",constraint_id) element.setAttribute("rsc",resource_name) element.setAttribute("node",node) element.setAttribute("score",score) constraintsElement.appendChild(element) utils.replace_cib_configuration(dom)
def colocation_set(argv): setoptions = [] for i in range(len(argv)): if argv[i] == "setoptions": setoptions = argv[i+1:] argv[i:] = [] break current_set = set_args_into_array(argv) colocation_id = "pcs_rsc_colocation" for a in argv: if a.find('=') == -1: colocation_id = colocation_id + "_" + a cib = utils.get_cib_etree() constraints = cib.find(".//constraints") if constraints == None: constraints = ET.SubElement(cib, "constraints") rsc_colocation = ET.SubElement(constraints,"rsc_colocation") rsc_colocation.set("id", utils.find_unique_id(cib,colocation_id)) rsc_colocation.set("score","INFINITY") score_options = ("score", "score-attribute", "score-attribute-mangle") score_specified = False for opt in setoptions: if opt.find("=") != -1: name,value = opt.split("=") if name not in score_options: utils.err( "invalid option '%s', allowed options are: %s" % (name, ", ".join(score_options)) ) if score_specified: utils.err("you cannot specify multiple score options") score_specified = True if name == "score" and not utils.is_score(value): utils.err( "invalid score '%s', use integer or INFINITY or -INFINITY" % value ) rsc_colocation.set(name,value) set_add_resource_sets(rsc_colocation, current_set, cib) utils.replace_cib_configuration(cib)
def test_is_score(self): self.assertTrue(utils.is_score("INFINITY")) self.assertTrue(utils.is_score("+INFINITY")) self.assertTrue(utils.is_score("-INFINITY")) self.assertTrue(utils.is_score("0")) self.assertTrue(utils.is_score("+0")) self.assertTrue(utils.is_score("-0")) self.assertTrue(utils.is_score("123")) self.assertTrue(utils.is_score("-123")) self.assertTrue(utils.is_score("+123")) self.assertFalse(utils.is_score("")) self.assertFalse(utils.is_score("abc")) self.assertFalse(utils.is_score("+abc")) self.assertFalse(utils.is_score("-abc")) self.assertFalse(utils.is_score("10a")) self.assertFalse(utils.is_score("+10a")) self.assertFalse(utils.is_score("-10a")) self.assertFalse(utils.is_score("a10")) self.assertFalse(utils.is_score("+a10")) self.assertFalse(utils.is_score("a-10")) self.assertFalse(utils.is_score("infinity")) self.assertFalse(utils.is_score("+infinity")) self.assertFalse(utils.is_score("-infinity")) self.assertFalse(utils.is_score("+InFiNiTy")) self.assertFalse(utils.is_score("INFINITY10")) self.assertFalse(utils.is_score("INFINITY+10")) self.assertFalse(utils.is_score("-INFINITY10")) self.assertFalse(utils.is_score("+INFINITY+10")) self.assertFalse(utils.is_score("10INFINITY")) self.assertFalse(utils.is_score("+10+INFINITY"))
def location_add(argv,rm=False): if len(argv) < 4 and (rm == False or len(argv) < 1): usage.constraint() sys.exit(1) constraint_id = argv.pop(0) # If we're removing, we only care about the id if (rm == True): resource_name = "" node = "" score = "" else: id_valid, id_error = utils.validate_xml_id(constraint_id, 'constraint id') if not id_valid: utils.err(id_error) resource_name = argv.pop(0) node = argv.pop(0) score = argv.pop(0) options = [] # For now we only allow setting resource-discovery if len(argv) > 0: for arg in argv: if '=' in arg: options.append(arg.split('=',1)) else: print("Error: bad option '%s'" % arg) usage.constraint(["location add"]) sys.exit(1) if options[-1][0] != "resource-discovery" and "--force" not in utils.pcs_options: utils.err("bad option '%s', use --force to override" % options[-1][0]) resource_valid, resource_error, correct_id \ = utils.validate_constraint_resource( utils.get_cib_dom(), resource_name ) if "--autocorrect" in utils.pcs_options and correct_id: resource_name = correct_id elif not resource_valid: utils.err(resource_error) if not utils.is_score(score): utils.err("invalid score '%s', use integer or INFINITY or -INFINITY" % score) # Verify current constraint doesn't already exist # If it does we replace it with the new constraint (dom,constraintsElement) = getCurrentConstraints() elementsToRemove = [] # If the id matches, or the rsc & node match, then we replace/remove for rsc_loc in constraintsElement.getElementsByTagName('rsc_location'): if (constraint_id == rsc_loc.getAttribute("id")) or \ (rsc_loc.getAttribute("rsc") == resource_name and \ rsc_loc.getAttribute("node") == node and not rm): elementsToRemove.append(rsc_loc) for etr in elementsToRemove: constraintsElement.removeChild(etr) if (rm == True and len(elementsToRemove) == 0): utils.err("resource location id: " + constraint_id + " not found.") if (not rm): element = dom.createElement("rsc_location") element.setAttribute("id",constraint_id) element.setAttribute("rsc",resource_name) element.setAttribute("node",node) element.setAttribute("score",score) for option in options: element.setAttribute(option[0], option[1]) constraintsElement.appendChild(element) utils.replace_cib_configuration(dom)
def colocation_set(argv): setoptions = [] for i in range(len(argv)): if argv[i] == "setoptions": setoptions = argv[i+1:] argv[i:] = [] break argv.insert(0, "set") resource_sets = set_args_into_array(argv) if not check_empty_resource_sets(resource_sets): usage.constraint(["colocation set"]) sys.exit(1) cib, constraints = getCurrentConstraints(utils.get_cib_dom()) attributes = [] score_options = ("score", "score-attribute", "score-attribute-mangle") score_specified = False id_specified = False for opt in setoptions: if "=" not in opt: utils.err("missing value of '%s' option" % opt) name, value = opt.split("=", 1) if name == "id": id_valid, id_error = utils.validate_xml_id(value, 'constraint id') if not id_valid: utils.err(id_error) if utils.does_id_exist(cib, value): utils.err( "id '%s' is already in use, please specify another one" % value ) id_specified = True attributes.append((name, value)) elif name in score_options: if score_specified: utils.err("you cannot specify multiple score options") if name == "score" and not utils.is_score(value): utils.err( "invalid score '%s', use integer or INFINITY or -INFINITY" % value ) score_specified = True attributes.append((name, value)) else: utils.err( "invalid option '%s', allowed options are: %s" % (name, ", ".join(score_options + ("id",))) ) if not score_specified: attributes.append(("score", "INFINITY")) if not id_specified: colocation_id = "pcs_rsc_colocation" for a in argv: if "=" not in a: colocation_id += "_" + a attributes.append(("id", utils.find_unique_id(cib, colocation_id))) rsc_colocation = cib.createElement("rsc_colocation") for name, value in attributes: rsc_colocation.setAttribute(name, value) set_add_resource_sets(rsc_colocation, resource_sets, cib) constraints.appendChild(rsc_colocation) utils.replace_cib_configuration(cib)
def location_add(argv, rm=False): if len(argv) < 4 and (rm == False or len(argv) < 1): usage.constraint() sys.exit(1) constraint_id = argv.pop(0) # If we're removing, we only care about the id if (rm == True): resource_name = "" node = "" score = "" else: id_valid, id_error = utils.validate_xml_id(constraint_id, 'constraint id') if not id_valid: utils.err(id_error) resource_name = argv.pop(0) node = argv.pop(0) score = argv.pop(0) options = [] # For now we only allow setting resource-discovery if len(argv) > 0: for arg in argv: if '=' in arg: options.append(arg.split('=', 1)) else: print("Error: bad option '%s'" % arg) usage.constraint(["location add"]) sys.exit(1) if options[-1][ 0] != "resource-discovery" and "--force" not in utils.pcs_options: utils.err("bad option '%s', use --force to override" % options[-1][0]) resource_valid, resource_error, correct_id \ = utils.validate_constraint_resource( utils.get_cib_dom(), resource_name ) if "--autocorrect" in utils.pcs_options and correct_id: resource_name = correct_id elif not resource_valid: utils.err(resource_error) if not utils.is_score(score): utils.err( "invalid score '%s', use integer or INFINITY or -INFINITY" % score) # Verify current constraint doesn't already exist # If it does we replace it with the new constraint (dom, constraintsElement) = getCurrentConstraints() elementsToRemove = [] # If the id matches, or the rsc & node match, then we replace/remove for rsc_loc in constraintsElement.getElementsByTagName('rsc_location'): if (constraint_id == rsc_loc.getAttribute("id")) or \ (rsc_loc.getAttribute("rsc") == resource_name and \ rsc_loc.getAttribute("node") == node and not rm): elementsToRemove.append(rsc_loc) for etr in elementsToRemove: constraintsElement.removeChild(etr) if (rm == True and len(elementsToRemove) == 0): utils.err("resource location id: " + constraint_id + " not found.") if (not rm): element = dom.createElement("rsc_location") element.setAttribute("id", constraint_id) element.setAttribute("rsc", resource_name) element.setAttribute("node", node) element.setAttribute("score", score) for option in options: element.setAttribute(option[0], option[1]) constraintsElement.appendChild(element) utils.replace_cib_configuration(dom)
def colocation_set(argv): setoptions = [] for i in range(len(argv)): if argv[i] == "setoptions": setoptions = argv[i + 1:] argv[i:] = [] break argv.insert(0, "set") resource_sets = set_args_into_array(argv) if not check_empty_resource_sets(resource_sets): usage.constraint(["colocation set"]) sys.exit(1) cib, constraints = getCurrentConstraints(utils.get_cib_dom()) attributes = [] score_options = ("score", "score-attribute", "score-attribute-mangle") score_specified = False id_specified = False for opt in setoptions: if "=" not in opt: utils.err("missing value of '%s' option" % opt) name, value = opt.split("=", 1) if name == "id": id_valid, id_error = utils.validate_xml_id(value, 'constraint id') if not id_valid: utils.err(id_error) if utils.does_id_exist(cib, value): utils.err( "id '%s' is already in use, please specify another one" % value) id_specified = True attributes.append((name, value)) elif name in score_options: if score_specified: utils.err("you cannot specify multiple score options") if name == "score" and not utils.is_score(value): utils.err( "invalid score '%s', use integer or INFINITY or -INFINITY" % value) score_specified = True attributes.append((name, value)) else: utils.err("invalid option '%s', allowed options are: %s" % (name, ", ".join(score_options + ("id", )))) if not score_specified: attributes.append(("score", "INFINITY")) if not id_specified: colocation_id = "pcs_rsc_colocation" for a in argv: if "=" not in a: colocation_id += "_" + a attributes.append(("id", utils.find_unique_id(cib, colocation_id))) rsc_colocation = cib.createElement("rsc_colocation") for name, value in attributes: rsc_colocation.setAttribute(name, value) set_add_resource_sets(rsc_colocation, resource_sets, cib) constraints.appendChild(rsc_colocation) utils.replace_cib_configuration(cib)