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 - kgronlund@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>