Hello community, here is the log from the commit of package crmsh for openSUSE:Factory checked in at 2014-05-17 21:43:24 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/crmsh (Old) and /work/SRC/openSUSE:Factory/.crmsh.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "crmsh" Changes: -------- --- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes 2014-05-15 19:10:29.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.crmsh.new/crmsh.changes 2014-05-17 21:43:25.000000000 +0200 @@ -1,0 +2,9 @@ +Fri May 16 11:31:42 UTC 2014 - kgronl...@suse.com + +- high: xmlutil: Include remote nodes in nodelist (bnc#877962) +- high: cibconfig: Ban containers stealing children (bnc#878112) +- high: parse: Allow role in rule-based location constraints (bnc#878128) +- low: command: Add -h and --help as aliases to help +- upstream: 2.0.0-85-g5c9da05 + +------------------------------------------------------------------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ crmsh.spec ++++++ --- /var/tmp/diff_new_pack.faZxQZ/_old 2014-05-17 21:43:26.000000000 +0200 +++ /var/tmp/diff_new_pack.faZxQZ/_new 2014-05-17 21:43:26.000000000 +0200 @@ -41,7 +41,7 @@ Summary: High Availability cluster command-line interface License: GPL-2.0+ Group: %{pkg_group} -Version: 2.0+git73 +Version: 2.0+git85 Release: %{?crmsh_release}%{?dist} Url: http://crmsh.github.io Source0: crmsh.tar.bz2 ++++++ crmsh.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/doc/crm.8.txt new/crmsh/doc/crm.8.txt --- old/crmsh/doc/crm.8.txt 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/doc/crm.8.txt 2014-05-16 13:20:50.000000000 +0200 @@ -2406,9 +2406,9 @@ Usage: ............... -location <id> <rsc> {node_pref|rules} +location <id> <rsc> [role=<role>] {node_pref|rules} -node_pref :: <score>: <node> [role=<role>] +node_pref :: <score>: <node> rules :: rule [id_spec] [$role=<role>] <score>: <expression> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/cibconfig.py new/crmsh/modules/cibconfig.py --- old/crmsh/modules/cibconfig.py 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/modules/cibconfig.py 2014-05-16 13:20:50.000000000 +0200 @@ -1621,16 +1621,16 @@ s = clidisplay.keyword(self.obj_type) id = clidisplay.id(self.obj_id) s = "%s %s %s" % (s, id, rsc) + + role = self.node.get("role") + if role is not None: + s += " role=%s" % (role) + pref_node = self.node.get("node") score = clidisplay.score(get_score(self.node)) if pref_node is not None: - ret = "%s %s: %s" % (s, score, pref_node) - role = self.node.get("role") - if role is not None: - ret += " role=%s" % (role) - return ret - else: - return s + s = "%s %s: %s" % (s, score, pref_node) + return s def _repr_cli_child(self, c, format): if c.tag == "rule": @@ -2352,6 +2352,7 @@ properties and rsc/op_defaults hold stuff in a meta_attributes child. ''' + assert node is not None if pnode is None: pnode = node obj = cib_object_map[pnode.tag][1](pnode.tag) @@ -2954,7 +2955,8 @@ if oldnode.getparent() is not None: oldnode.getparent().replace(oldnode, newnode) obj.nocli = False # try again after update - self._adjust_children(obj) + if not self._adjust_children(obj): + return False if not obj.cli_use_validate(): common_debug("update_element: validation failed (%s, %s)" % (obj, etree.tostring(newnode))) obj.nocli_warn = True @@ -3070,33 +3072,56 @@ ''' new_children_ids = get_rsc_children_ids(obj.node) if not new_children_ids: - return + return True old_children = [x for x in obj.children if x.parent == obj] obj.children = [self.find_object(x) for x in new_children_ids] # relink orphans to top for child in set(old_children) - set(obj.children): common_debug("relink child %s to top" % str(child)) self._relink_child_to_top(child) - self._update_children(obj) + if not self._are_children_orphans(obj): + return False + return self._update_children(obj) def _relink_child_to_top(self, obj): 'Relink a child to the top node.' get_topnode(self.cib_elem, obj.parent_type).append(obj.node) obj.parent = None + def _are_children_orphans(self, obj): + """ + Check if we're adding a container containing objects + we've already added to a different container + """ + for child in obj.children: + if not child.parent: + continue + if child.parent == obj or child.parent.obj_id == obj.obj_id: + continue + if child.parent.obj_type in constants.container_tags: + common_err("Cannot create %s: Child %s already in %s" % (obj, child, child.parent)) + return False + return True + def _update_children(self, obj): '''For composite objects: update all children nodes. ''' # unlink all and find them in the new node for child in obj.children: oldnode = child.node - child.node = obj.find_child_in_node(child) + newnode = obj.find_child_in_node(child) + if newnode is None: + common_err("Child found in children list but not in node: %s, %s" % (obj, child)) + return False + child.node = newnode if child.children: # and children of children - self._update_children(child) + if not self._update_children(child): + return False rmnode(oldnode) - if child.parent and child.parent != obj: - child.parent.updated = True # the other parent updated + if child.parent: + child.parent.updated = True child.parent = obj + return True def test_element(self, obj): if not obj.xml_obj_type in constants.defaults_tags: @@ -3127,12 +3152,14 @@ child.node = c def _add_element(self, obj, node): + assert node is not None obj.node = node obj.set_id() pnode = get_topnode(self.cib_elem, obj.parent_type) common_debug("_add_element: append child %s to %s" % (obj.obj_id, pnode.tag)) + if not self._adjust_children(obj): + return None pnode.append(node) - self._adjust_children(obj) self._redirect_children_constraints(obj) if not obj.cli_use_validate(): self.nocli_warn = True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/command.py new/crmsh/modules/command.py --- old/crmsh/modules/command.py 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/modules/command.py 2014-05-16 13:20:50.000000000 +0200 @@ -322,7 +322,7 @@ def do_quit(self, context): context.quit() - @alias('?') + @alias('?', '-h', '--help') @help('''show help (help topics for list of topics) The help subsystem consists of the command reference and a list of topics. The former is what you need in order to get the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/idmgmt.py new/crmsh/modules/idmgmt.py --- old/crmsh/modules/idmgmt.py 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/modules/idmgmt.py 2014-05-16 13:20:50.000000000 +0200 @@ -59,7 +59,7 @@ ''' Create a unique id for the xml node. ''' - common_debug("idmgmt.new: node=%s, pfx=%s" % (etree.tostring(node), pfx)) + #common_debug("idmgmt.new: node=%s, pfx=%s" % (etree.tostring(node), pfx)) name = node.get("name") if node.tag == "nvpair": node_id = "%s-%s" % (pfx, name) @@ -151,7 +151,7 @@ def save(node_id): if not node_id: return - common_debug("id_store: saved %s" % node_id) + #common_debug("id_store: saved %s" % node_id) _id_store[node_id] = 1 @@ -171,7 +171,7 @@ return try: del _id_store[node_id] - common_debug("id_store: removed %s" % node_id) + #common_debug("id_store: removed %s" % node_id) except KeyError: pass @@ -194,10 +194,8 @@ ''' old_id = oldnode.get("id") if oldnode is not None else None new_id = node.get("id") or old_id or node.get("uname") - from msg import common_debug - from lxml import etree - common_debug("idmgmt.set: node=%s, new_id=%s, old_id=%s, id_hint=%s" % - (etree.tostring(node), new_id, old_id, id_hint)) + #common_debug("idmgmt.set: node=%s, new_id=%s, old_id=%s, id_hint=%s" % + # (etree.tostring(node), new_id, old_id, id_hint)) if new_id: save(new_id) elif id_required: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/parse.py new/crmsh/modules/parse.py --- old/crmsh/modules/parse.py 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/modules/parse.py 2014-05-16 13:20:50.000000000 +0200 @@ -698,7 +698,7 @@ def parse_location(self): """ location <id> rsc <score>: <node> [role=<role>] - location <id> rsc [rule ...] + location <id> rsc [role=<role>] [rule ...] rsc :: /<rsc-pattern>/ | { <rsc-set> } | <rsc> @@ -716,12 +716,20 @@ out.append(rscset) else: out.set('rsc', self.match_resource()) + + if self.try_match(self._ROLE_RE) or self.try_match(self._ROLE2_RE): + out.set('role', self.matched(1)) + + score = False if self.try_match(self._SCORE_RE): + score = True out.set(*self.validate_score(self.matched(1))) out.set('node', self.match_identifier()) - if self.try_match(self._ROLE_RE) or self.try_match(self._ROLE2_RE): - out.set('role', self.matched(1)) - else: + # backwards compatibility: role used to be read here + if 'role' not in out: + if self.try_match(self._ROLE_RE) or self.try_match(self._ROLE2_RE): + out.set('role', self.matched(1)) + if not score: for rule in self.match_rules(): out.append(rule) return out diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/ui_configure.py new/crmsh/modules/ui_configure.py --- old/crmsh/modules/ui_configure.py 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/modules/ui_configure.py 2014-05-16 13:20:50.000000000 +0200 @@ -550,8 +550,7 @@ not cib_factory.is_elem_supported(cmd): common_err("%s not supported by the RNG schema" % cmd) return False - f = lambda: cib_factory.create_object(cmd, *args) - return f() + return cib_factory.create_object(cmd, *args) @command.skill_level('administrator') @command.completers(_node_id_list, compl.choice(constants.node_attributes_keyw)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/xmlutil.py new/crmsh/modules/xmlutil.py --- old/crmsh/modules/xmlutil.py 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/modules/xmlutil.py 2014-05-16 13:20:50.000000000 +0200 @@ -332,17 +332,20 @@ def listnodes(): - nodes_elem = cibdump2elem("nodes") - if nodes_elem is None: + cib = cibdump2elem() + if cib is None: return [] - return [x.get("uname") for x in nodes_elem.iterchildren("node") - if is_normal_node(x)] + local_nodes = cib.xpath('/cib/configuration/nodes/node/@uname') + remote_nodes = cib.xpath('/cib/status/node_state[@remote_node="true"]/@uname') + return list(set([n for n in local_nodes + remote_nodes if n])) def is_our_node(s): ''' Check if s is in a list of our nodes (ignore case). This is not fast, perhaps should be cached. + + Includes remote nodes as well ''' for n in listnodes(): if n.lower() == s.lower(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/cibtests/003.exp.xml new/crmsh/test/cibtests/003.exp.xml --- old/crmsh/test/cibtests/003.exp.xml 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/test/cibtests/003.exp.xml 2014-05-16 13:20:50.000000000 +0200 @@ -1,4 +1,4 @@ -<cib epoch="3" num_updates="1" admin_epoch="0" validate-with="pacemaker-1.0" cib-last-written="Tue Mar 31 14:52:24 2009"> +<cib epoch="4" num_updates="1" admin_epoch="0" validate-with="pacemaker-1.0" cib-last-written="Tue Mar 31 14:52:24 2009"> <configuration> <crm_config> <cluster_property_set id="cib-bootstrap-options"> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/cibtests/004.exp.xml new/crmsh/test/cibtests/004.exp.xml --- old/crmsh/test/cibtests/004.exp.xml 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/test/cibtests/004.exp.xml 2014-05-16 13:20:50.000000000 +0200 @@ -1,4 +1,4 @@ -<cib epoch="3" num_updates="1" admin_epoch="0" validate-with="pacemaker-1.0" cib-last-written="Tue Mar 31 14:52:24 2009"> +<cib epoch="4" num_updates="1" admin_epoch="0" validate-with="pacemaker-1.0" cib-last-written="Tue Mar 31 14:52:24 2009"> <configuration> <crm_config> <cluster_property_set id="cib-bootstrap-options"> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/testcases/edit.exp new/crmsh/test/testcases/edit.exp --- old/crmsh/test/testcases/edit.exp 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/test/testcases/edit.exp 2014-05-16 13:20:50.000000000 +0200 @@ -29,6 +29,7 @@ .INP: primitive d3 ocf:heartbeat:Dummy .INP: group g2 d1 d2 .INP: filter "sed '/g2/s/d1/p1/;/g1/s/p1/d1/'" +ERROR: 27: Cannot create group:g2: Child primitive:p1 already in group:g1 .INP: filter "sed '/g1/s/d1/p1/;/g2/s/p1/d1/'" .INP: filter "sed '$alocation loc-d1 d1 rule $id=r1 -inf: not_defined webserver rule $id=r2 webserver: defined webserver'" .INP: filter "sed 's/not_defined webserver/& or mem number:lte 0/'" loc-d1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/unittests/test_bugs.py new/crmsh/test/unittests/test_bugs.py --- old/crmsh/test/unittests/test_bugs.py 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/test/unittests/test_bugs.py 2014-05-16 13:20:50.000000000 +0200 @@ -234,3 +234,39 @@ print "AFTER:", etree.tostring(elem) assert len(elem.xpath(".//meta_attributes/nvpair[@name='target-role']")) == 1 + + +def test_bnc878128(): + """ + L3: "crm configure show" displays XML information instead of typical crm output. + """ + xml = """<rsc_location id="cli-prefer-dummy-resource" rsc="dummy-resource" +role="Started"> + <rule id="cli-prefer-rule-dummy-resource" score="INFINITY"> + <expression id="cli-prefer-expr-dummy-resource" attribute="#uname" +operation="eq" value="x64-4"/> + <date_expression id="cli-prefer-lifetime-end-dummy-resource" operation="lt" +end="2014-05-17 17:56:11Z"/> + </rule> +</rsc_location>""" + data = etree.fromstring(xml) + obj = factory.create_from_node(data) + assert obj is not None + data = obj.repr_cli(format=-1) + print "OUTPUT:", data + exp = 'location cli-prefer-dummy-resource dummy-resource role=Started rule #uname eq x64-4 and date lt "2014-05-17 17:56:11Z"' + assert data == exp + assert obj.cli_use_validate() + + +def test_bnc878112(): + """ + crm configure group can hijack a cloned primitive (and then crash) + """ + obj1 = factory.create_object('primitive', 'p1', 'Dummy') + assert obj1 is not None + obj2 = factory.create_object('group', 'g1', 'p1') + assert obj2 is not None + obj3 = factory.create_object('group', 'g2', 'p1') + print obj3 + assert obj3 is False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/unittests/test_cliformat.py new/crmsh/test/unittests/test_cliformat.py --- old/crmsh/test/unittests/test_cliformat.py 2014-05-14 16:04:21.000000000 +0200 +++ new/crmsh/test/unittests/test_cliformat.py 2014-05-16 13:20:50.000000000 +0200 @@ -25,9 +25,7 @@ def assert_is_not_none(thing): - if thing is None: - message = "%s was None" % (thing) - raise AssertionError(message) + assert thing is not None, "Expected non-None value" def roundtrip(cli, debug=False): -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org