Hello community,
here is the log from the commit of package crmsh for openSUSE:Factory checked in at 2015-10-12 10:02:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 2015-10-02 09:23:51.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.crmsh.new/crmsh.changes 2015-10-12 10:02:44.000000000 +0200
@@ -1,0 +2,25 @@
+Thu Oct 08 21:44:06 UTC 2015 - kgronlund@suse.com
+
+- Update to version 2.2.0~rc3+git.1444340345.59850ca:
+ + high: utils: Fix cluster_copy_file error when nodes provided (bsc#949603)
+ + low: xmlutil: More informative message when updating resource references after rename
+ + doc: fix some command syntax grammar in the man page
+ + doc: resource-discovery for location constraints
+
+-------------------------------------------------------------------
+Tue Oct 06 12:22:30 UTC 2015 - kgronlund@suse.com
+
+- Update to version 2.2.0~rc3+git.1444133917.3f7f79f:
+ + high: cibconfig: Fix bug in is_edit_valid (bsc#948547)
+ + high: cibconfig: Delete constraints before resources
+
+-------------------------------------------------------------------
+Tue Oct 06 09:14:24 UTC 2015 - kgronlund@suse.com
+
+- Update to version 2.2.0~rc3+git.1444122392.193bf69:
+ + high: cibconfig: Allow nodes and resources with the same ID (bsc#948547)
+ + high: cibconfig: Allow node/rsc id collision in _set_update (bsc#948547)
+ + medium: hb_report: Don't cat binary logs
+ + low: report: Silence tar warning on early stream close
+
+-------------------------------------------------------------------
Old:
----
crmsh-2.2.0~rc3+git.1443544100.aa2abda.tar.bz2
New:
----
crmsh-2.2.0~rc3+git.1444340345.59850ca.tar.bz2
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ crmsh.spec ++++++
--- /var/tmp/diff_new_pack.lYKxtr/_old 2015-10-12 10:02:44.000000000 +0200
+++ /var/tmp/diff_new_pack.lYKxtr/_new 2015-10-12 10:02:44.000000000 +0200
@@ -36,7 +36,7 @@
Summary: High Availability cluster command-line interface
License: GPL-2.0+
Group: %{pkg_group}
-Version: 2.2.0~rc3+git.1443544100.aa2abda
+Version: 2.2.0~rc3+git.1444340345.59850ca
Release: 0
Url: http://crmsh.github.io
Source0: %{name}-%{version}.tar.bz2
++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.lYKxtr/_old 2015-10-12 10:02:44.000000000 +0200
+++ /var/tmp/diff_new_pack.lYKxtr/_new 2015-10-12 10:02:44.000000000 +0200
@@ -1,4 +1,4 @@
<servicedata>
<service name="tar_scm">
<param name="url">git://github.com/ClusterLabs/crmsh.git</param>
- <param name="changesrevision">aa2abdad0c401d1cebf43e1a20da26b3de2992c5</param></service></servicedata>
\ No newline at end of file
+ <param name="changesrevision">59850ca9ed07b3e965170b1fb50712ea1bfa502f</param></service></servicedata>
\ No newline at end of file
++++++ crmsh-2.2.0~rc3+git.1443544100.aa2abda.tar.bz2 -> crmsh-2.2.0~rc3+git.1444340345.59850ca.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/doc/crm.8.adoc new/crmsh-2.2.0~rc3+git.1444340345.59850ca/doc/crm.8.adoc
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/doc/crm.8.adoc 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/doc/crm.8.adoc 2015-10-08 23:44:05.000000000 +0200
@@ -797,12 +797,12 @@
id_spec :: $id=<id> | $id-ref=<id>
score :: <number> | <attribute> | [-]inf
-expression :: [bool_op ...]
+expression :: [ ...]
bool_op :: or | and
simple_exp :: <attribute> [type:] <value>
| <attribute>
| date
-type :: string | version | number
+type :: <string> | <version> | <number>
binary_op :: lt | gt | lte | gte | eq | ne
unary_op :: defined | not_defined
@@ -2574,8 +2574,8 @@
...............
clone <name> <rsc>
[description=<description>]
- [meta attr_list]
- [params attr_list]
+ [meta ]
+ [params ]
attr_list :: [$id=<id>] <attr>=<val> [<attr>=<val>...] | $id-ref=<id>
...............
@@ -2622,13 +2622,13 @@
colocation <id> <score>: <rsc>[:<role>] <with-rsc>[:<role>]
[node-attribute=]
-colocation <id> <score>: resource_sets
+colocation <id> <score>:
[node-attribute=]
-resource_sets :: resource_set [resource_set ...]
+resource_sets :: [ ...]
resource_set :: ["("|"["] <rsc>[:<role>] [<rsc>[:<role>] ...] \
- [attributes] [")"|"]"]
+ [<attributes>] [")"|"]"]
attributes :: [require-all=(true|false)] [sequential=(true|false)]
@@ -2924,6 +2924,9 @@
* Tag containing resource ids: +location loc1 tag1 100: node1+
* Resource pattern: +location loc1 /web.*/ 100: node1+
+The +resource-discovery+ attribute allows probes to be selectively
+enabled or disabled per resource and node.
+
The syntax for resource sets is described in detail for
<>.
@@ -2935,12 +2938,14 @@
Usage:
...............
-location <id> rsc [role=<role>] {node_pref|rules}
+location <id> <rsc> [<attributes>] {|<rules>}
rsc :: /<rsc-pattern>/
| { resource_sets }
| <rsc>
+attributes :: role=<role> | resource-discovery=always|never|exclusive
+
node_pref :: <score>: <node>
rules ::
@@ -2949,7 +2954,7 @@
id_spec :: $id=<id> | $id-ref=<id>
score :: <number> | <attribute> | [-]inf
-expression :: [bool_op ...]
+expression :: [ ...]
bool_op :: or | and
simple_exp :: <attribute> [type:] <value>
| <attribute>
@@ -2984,6 +2989,9 @@
location conn_2 dummy_float \
rule -inf: not_defined pingd or pingd number:lte 0
+
+# never probe for rsc1 on node1
+location no-probe rsc1 resource-discovery=never -inf: node1
...............
[[cmdhelp_configure_modgroup,modify group]]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/hb_report/hb_report.in new/crmsh-2.2.0~rc3+git.1444340345.59850ca/hb_report/hb_report.in
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/hb_report/hb_report.in 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/hb_report/hb_report.in 2015-10-08 23:44:05.000000000 +0200
@@ -330,8 +330,10 @@
echo "gzip -dc"
elif echo $1 | grep -qs 'xz$'; then
echo "xz -dc"
- else
+ elif file $1 | grep -qs 'text'; then
echo "cat"
+ else
+ echo "echo"
fi
}
#
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/cibconfig.py new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/cibconfig.py
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/cibconfig.py 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/cibconfig.py 2015-10-08 23:44:05.000000000 +0200
@@ -494,28 +494,6 @@
rc |= obj.check_sanity()
return rc
- def is_edit_valid(self, id_set):
- '''
- 1. Cannot name any elements as those which exist but
- were not picked for editing.
- 2. Cannot remove running resources.
- '''
- rc = True
- not_allowed = id_set & self.locked_ids
- rscstat = RscState()
- if not_allowed:
- common_err("Elements %s already exist" %
- ', '.join(list(not_allowed)))
- rc = False
- delete_set = self.obj_ids - id_set
- cannot_delete = [x for x in delete_set
- if not rscstat.can_delete(x)]
- if cannot_delete:
- common_err("Cannot delete running resources: %s" %
- ', '.join(cannot_delete))
- rc = False
- return rc
-
class CibObjectSetCli(CibObjectSet):
'''
@@ -570,9 +548,7 @@
coming from edit). The original CIB is preserved and no
changes are made.
'''
- edit_d = {}
- id_set = oset()
- del_set = oset()
+ diff = CibDiff(self)
rc = True
err_buf.start_tmp_lineno()
cp = CliParser()
@@ -580,32 +556,17 @@
err_buf.incr_lineno()
node = cp.parse(cli_text)
if node not in (False, None):
- obj_id = id_for_node(node)
- if obj_id is None:
- common_err("element %s has no id!" %
- etree.tostring(node, pretty_print=True))
- rc = False
- elif obj_id in id_set:
- common_err("duplicate element %s" % obj_id)
- rc = False
- else:
- id_set.add(obj_id)
- edit_d[obj_id] = node
+ rc = diff.add(node)
elif node is False:
rc = False
err_buf.stop_tmp_lineno()
+
# we can't proceed if there was a syntax error, but we
# can ask the user to fix problems
- if not no_remove:
- rc &= self.is_edit_valid(id_set)
- del_set = self.obj_ids - id_set
if not rc:
return rc
- mk_set = id_set - self.obj_ids
- upd_set = id_set & self.obj_ids
- rc = cib_factory.set_update(edit_d, mk_set, upd_set, del_set,
- upd_type="cli", method=method)
+ rc = diff.apply(cib_factory, mode='cli', no_remove=no_remove, method=method)
if not rc:
self._initialize()
return rc
@@ -639,29 +600,12 @@
if not show_unrecognized_elems(cib_elem):
return False
rc = True
- id_set = oset()
- del_set = oset()
- edit_d = {}
+ diff = CibDiff(self)
for node in get_top_cib_nodes(cib_elem, []):
- id = self._get_id(node)
- if id is None:
- common_err("element %s has no id!" %
- etree.tostring(node, pretty_print=True))
- rc = False
- elif id in id_set:
- common_err("duplicate element %s" % id)
- rc = False
- else:
- id_set.add(id)
- edit_d[id] = node
- if not no_remove:
- rc &= self.is_edit_valid(id_set)
- del_set = self.obj_ids - id_set
+ rc = diff.add(node)
if not rc:
return rc
- mk_set = id_set - self.obj_ids
- upd_set = id_set & self.obj_ids
- rc = cib_factory.set_update(edit_d, mk_set, upd_set, del_set, "xml", method)
+ rc = diff.apply(cib_factory, mode='xml', no_remove=no_remove, method=method)
if not rc:
self._initialize()
return rc
@@ -1145,7 +1089,7 @@
Check if all operation attributes are supported by the
schema.
'''
- rc = True
+ rc = 0
op_id = op_node.get("name")
for name in op_node.keys():
vals = schema.rng_attr_values(op_node.tag, name)
@@ -1155,14 +1099,14 @@
if v not in vals:
common_warn("%s: op '%s' attribute '%s' value '%s' not recognized" %
(self.obj_id, op_id, name, v))
- rc = False
+ rc = 1
return rc
def _check_ops_attributes(self):
'''
Check if operation attributes settings are valid.
'''
- rc = True
+ rc = 0
if self.node is None:
return rc
for op_node in self.node.xpath("operations/op"):
@@ -2139,6 +2083,112 @@
cib_upgrade = "cibadmin --upgrade --force"
+class CibDiff(object):
+ '''
+ Represents a cib edit order.
+ Is complicated by the fact that
+ nodes and resources can have
+ colliding ids.
+
+ Can carry changes either as CLI objects
+ or as XML statements.
+ '''
+ def __init__(self, objset):
+ self.objset = objset
+ self._node_set = oset()
+ self._nodes = {}
+ self._rsc_set = oset()
+ self._resources = {}
+
+ def add(self, item):
+ obj_id = id_for_node(item)
+ is_node = item.tag == 'node'
+ if obj_id is None:
+ common_err("element %s has no id!" %
+ etree.tostring(item, pretty_print=True))
+ return False
+ elif is_node and obj_id in self._node_set:
+ common_err("Duplicate node: %s" % (obj_id))
+ return False
+ elif not is_node and obj_id in self._rsc_set:
+ common_err("Duplicate resource: %s" % (obj_id))
+ return False
+ elif is_node:
+ self._node_set.add(obj_id)
+ self._nodes[obj_id] = item
+ else:
+ self._rsc_set.add(obj_id)
+ self._resources[obj_id] = item
+ return True
+
+ def _obj_type(self, nid):
+ for obj in self.objset.all_set:
+ if obj.obj_id == nid:
+ return obj.obj_type
+ return None
+
+ def _obj_nodes(self):
+ return oset([n for n in self.objset.obj_ids
+ if self._obj_type(n) == 'node'])
+
+ def _obj_resources(self):
+ return oset([n for n in self.objset.obj_ids
+ if self._obj_type(n) != 'node'])
+
+ def _is_edit_valid(self, id_set, existing):
+ '''
+ 1. Cannot name any elements as those which exist but
+ were not picked for editing.
+ 2. Cannot remove running resources.
+ '''
+ rc = True
+ not_allowed = id_set & self.objset.locked_ids
+ rscstat = RscState()
+ if not_allowed:
+ common_err("Elements %s already exist" %
+ ', '.join(list(not_allowed)))
+ rc = False
+ delete_set = existing - id_set
+ cannot_delete = [x for x in delete_set
+ if not rscstat.can_delete(x)]
+ if cannot_delete:
+ common_err("Cannot delete running resources: %s" %
+ ', '.join(cannot_delete))
+ rc = False
+ return rc
+
+
+ def apply(self, factory, mode='cli', no_remove=False, method='replace'):
+ rc = True
+
+ edited_nodes = self._nodes.copy()
+ edited_resources = self._resources.copy()
+
+ def calc_sets(input_set, existing):
+ rc = True
+ if not no_remove:
+ rc = self._is_edit_valid(input_set, existing)
+ del_set = existing - (input_set)
+ else:
+ del_set = oset()
+ mk_set = (input_set) - existing
+ upd_set = (input_set) & existing
+ return rc, mk_set, upd_set, del_set
+
+ if not rc:
+ return rc
+
+ for e, s, existing in ((edited_nodes, self._node_set, self._obj_nodes()),
+ (edited_resources, self._rsc_set, self._obj_resources())):
+ rc, mk, upd, rm = calc_sets(s, existing)
+ if not rc:
+ return rc
+ rc = cib_factory.set_update(e, mk, upd, rm, upd_type=mode, method=method)
+ if not rc:
+ return rc
+ return rc
+
+
class CibFactory(object):
'''
Juggle with CIB objects.
@@ -2602,7 +2652,7 @@
# need to get addresses of all new objects created by
# deepcopy
for obj in self.cib_objects:
- obj.node = self.find_node(obj.xml_obj_type, obj.obj_id)
+ obj.node = self.find_xml_node(obj.xml_obj_type, obj.obj_id)
self._update_links(obj)
idmgmt.pop_state()
return self.check_structure()
@@ -2649,9 +2699,34 @@
if objs is None:
return None
if len(objs) > 0:
+ for obj in objs:
+ if obj.obj_type != 'node':
+ return obj
return objs[0]
return None
+ def find_resource(self, obj_id):
+ if not self.is_cib_sane():
+ return None
+ objs = self.find_objects(obj_id)
+ if objs is None:
+ return None
+ for obj in objs:
+ if obj.obj_type != 'node':
+ return obj
+ return None
+
+ def find_node(self, obj_id):
+ if not self.is_cib_sane():
+ return None
+ objs = self.find_objects(obj_id)
+ if objs is None:
+ return None
+ for obj in objs:
+ if obj.obj_type == 'node':
+ return obj
+ return None
+
#
# tab completion functions
#
@@ -2687,8 +2762,8 @@
def node_id_list(self):
"List of node ids."
- return [x.node.get("uname") for x in self.cib_objects
- if x.obj_type == "node"]
+ return sorted([x.node.get("uname") for x in self.cib_objects
+ if x.obj_type == "node"])
def f_prim_free_id_list(self):
"List of possible primitives ids (for group completion)."
@@ -2723,8 +2798,8 @@
return obj
return None
- def find_node(self, tag, id, strict=True):
- "Find a node of this type with this id."
+ def find_xml_node(self, tag, id, strict=True):
+ "Find a xml node of this type with this id."
try:
if tag in constants.defaults_tags:
expr = '//%s/meta_attributes[@id="%s"]' % (tag, id)
@@ -2754,7 +2829,7 @@
return False
rc = True
for obj_id in args:
- obj = self.find_object(obj_id)
+ obj = self.find_resource(obj_id)
if not obj:
no_object_err(obj_id)
rc = False
@@ -2834,7 +2909,7 @@
id to reference.
'''
self.id_refs[id_ref] = attr_list_type
- obj = self.find_object(id_ref)
+ obj = self.find_resource(id_ref)
if obj:
nodes = obj.node.xpath(".//%s" % attr_list_type)
if len(nodes) > 1:
@@ -2904,7 +2979,7 @@
matching_tags = [x for x in self.cib_objects if x.obj_type == 'tag' and x.obj_id == t]
ret = []
for mt in matching_tags:
- matches = [cib_factory.find_object(o) for o in mt.node.xpath('./obj_ref/@id')]
+ matches = [cib_factory.find_resource(o) for o in mt.node.xpath('./obj_ref/@id')]
ret += [m for m in matches if m is not None]
return ret
@@ -2955,7 +3030,7 @@
rc = True
constraint_id = node.get("id")
for obj_id in referenced_resources(node):
- if not self.find_object(obj_id):
+ if not self.find_resource(obj_id):
constraint_norefobj_err(constraint_id, obj_id)
rc = False
return rc
@@ -2993,7 +3068,7 @@
def _verify_child(self, child_id, parent_tag, obj_id):
'Check if child exists and obj_id is (or may become) its parent.'
- child = self.find_object(child_id)
+ child = self.find_resource(child_id)
if not child:
no_object_err(child_id)
return False
@@ -3062,7 +3137,7 @@
'''Add an op to a primitive.'''
# does the referenced primitive exist
rsc_id = node.get('rsc')
- rsc_obj = self.find_object(rsc_id)
+ rsc_obj = self.find_resource(rsc_id)
if not rsc_obj:
no_object_err(rsc_id)
return None
@@ -3095,7 +3170,7 @@
if obj_type == "op":
return self.add_op(elem)
if obj_type == "node":
- obj = self.find_object(obj_id)
+ obj = self.find_node(obj_id)
# make an exception and allow updating nodes
if obj:
self.merge_from_cli(obj, elem)
@@ -3166,17 +3241,32 @@
del_set is a set to be removed.
method is either replace or update.
'''
- common_debug("_cli_set_update: %s, %s, %s" % (mk_set, upd_set, del_set))
+ common_debug("_cli_set_update: mk=%s, upd=%s, del=%s" % (mk_set, upd_set, del_set))
test_l = []
def obj_is_container(x):
- obj = self.find_object(x)
+ obj = self.find_resource(x)
return obj and is_container(obj.node)
- del_containers = [x for x in del_set if obj_is_container(x)]
- del_objs = [x for x in del_set if not obj_is_container(x)]
+ def obj_is_constraint(x):
+ obj = self.find_resource(x)
+ return obj and is_constraint(obj.node)
+
+ del_constraints = []
+ del_containers = []
+ del_objs = []
+ for x in del_set:
+ if obj_is_constraint(x):
+ del_constraints.append(x)
+ elif obj_is_container(x):
+ del_containers.append(x)
+ else:
+ del_objs.append(x)
- # delete containers first in case objects are moved elsewhere
+ # delete constraints and containers first in case objects are moved elsewhere
+ if not self.delete(*del_constraints):
+ common_debug("delete %s failed" % (list(del_set)))
+ return False
if not self.delete(*del_containers):
common_debug("delete %s failed" % (list(del_set)))
return False
@@ -3190,7 +3280,10 @@
test_l.append(obj)
for id in upd_set:
- obj = self.find_object(id)
+ if edit_d[id].tag == 'node':
+ obj = self.find_node(id)
+ else:
+ obj = self.find_resource(id)
if not obj:
common_debug("%s not found!" % (id))
return False
@@ -3203,7 +3296,8 @@
(obj, etree.tostring(node), method))
return False
test_l.append(obj)
- if not self.delete(*del_objs):
+
+ if not self.delete(*reversed(del_objs)):
common_debug("delete %s failed" % (list(del_set)))
return False
rc = True
@@ -3229,7 +3323,10 @@
return False
test_l.append(obj)
for id in upd_set:
- obj = self.find_object(id)
+ if edit_d[id].tag == 'node':
+ obj = self.find_node(id)
+ else:
+ obj = self.find_resource(id)
if not obj:
return False
if not self.update_from_node(obj, edit_d[id]):
@@ -3272,7 +3369,7 @@
if not new_children_ids:
return True
old_children = [x for x in obj.children if x.parent == obj]
- new_children = [self.find_object(x) for x in new_children_ids]
+ new_children = [self.find_resource(x) for x in new_children_ids]
new_children = [c for c in new_children if c is not None]
obj.children = new_children
# relink orphans to top
@@ -3380,7 +3477,7 @@
for c in node.iterchildren('primitive'):
pid = c.get('id')
- child_obj = self.find_object(pid)
+ child_obj = self.find_resource(pid)
if child_obj is None:
child_obj = self.create_from_node(copy.deepcopy(c))
if not child_obj:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/parse.py new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/parse.py
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/parse.py 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/parse.py 2015-10-08 23:44:05.000000000 +0200
@@ -742,8 +742,8 @@
def parse_location(self):
"""
- location <id> rsc [[$]<attribute>=<value>] <score>: <node>
- location <id> rsc [[$]<attribute>=<value>] <rule> [<rule> ...]
+ location <id> <rsc> [[$]<attribute>=<value>] <score>: <node>
+ location <id> <rsc> [[$]<attribute>=<value>] <rule> [<rule> ...]
rsc :: /<rsc-pattern>/
| { <rsc-set> }
| <rsc>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/report.py new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/report.py
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/report.py 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/report.py 2015-10-08 23:44:05.000000000 +0200
@@ -751,7 +751,7 @@
self.error(msg)
return None
try:
- rc, tf_loc = get_stdout("tar -t%s < %s | head -1" % (tar_unpack_option, quote(bfname)))
+ rc, tf_loc = get_stdout("tar -t%s < %s 2> /dev/null | head -1" % (tar_unpack_option, quote(bfname)))
if os.path.abspath(tf_loc) != os.path.abspath(loc):
common_debug("top directory in tarball: %s, doesn't match the tarball name: %s" %
(tf_loc, loc))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/ui_assist.py new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/ui_assist.py
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/ui_assist.py 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/ui_assist.py 2015-10-08 23:44:05.000000000 +0200
@@ -39,7 +39,7 @@
'''
if len(primitives) < 1:
context.fatal_error("Expected at least one primitive argument")
- objs = [cib_factory.find_object(p) for p in primitives]
+ objs = [cib_factory.find_resource(p) for p in primitives]
for prim, obj in zip(primitives, objs):
if obj is None:
context.fatal_error("Primitive %s not found" % (prim))
@@ -100,7 +100,7 @@
context.fatal_error("Need at least two arguments")
for node in nodes:
- obj = cib_factory.find_object(node)
+ obj = cib_factory.find_resource(node)
if not obj:
context.fatal_error("Object not found: %s" % (node))
if not xmlutil.is_primitive(obj.node):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/ui_configure.py new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/ui_configure.py
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/ui_configure.py 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/ui_configure.py 2015-10-08 23:44:05.000000000 +0200
@@ -105,7 +105,7 @@
def ra_agent_for_template(tmpl):
'''@template -> ra.agent'''
- obj = cib_factory.find_object(tmpl[1:])
+ obj = cib_factory.find_resource(tmpl[1:])
if obj is None:
return None
return ra.get_ra(obj.node)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/utils.py new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/utils.py
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/utils.py 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/utils.py 2015-10-08 23:44:05.000000000 +0200
@@ -1438,7 +1438,7 @@
if not nodes:
nodes = list_cluster_nodes()
nodes.remove(this_node())
- opts = parallax.Options()
+ opts = parallax.Options()
opts.timeout = 60
opts.ssh_options += ['ControlPersist=no']
ok = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/xmlutil.py new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/xmlutil.py
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/modules/xmlutil.py 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/modules/xmlutil.py 2015-10-08 23:44:05.000000000 +0200
@@ -1021,7 +1021,7 @@
def rename_rscref(c_obj, old_id, new_id):
if rename_rscref_simple(c_obj, old_id, new_id) or \
rename_rscref_rset(c_obj, old_id, new_id):
- err_buf.info("resource references in %s updated" % str(c_obj))
+ err_buf.info("modified %s from %s to %s" % (str(c_obj), old_id, new_id))
def delete_rscref(c_obj, rsc_id):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/edit new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/edit
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/edit 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/edit 2015-10-08 23:44:05.000000000 +0200
@@ -12,7 +12,9 @@
op monitor interval=120m OCF_CHECK_LEVEL=10
filter "sed '$aprimitive p2 ocf:heartbeat:Dummy'"
filter "sed '$agroup g1 p1 p2'"
+show
filter "sed 's/p2/p3/;$aprimitive p3 ocf:heartbeat:Dummy'" g1
+show
filter "sed '$aclone c1 p2'"
filter "sed 's/p2/g1/'" c1
filter "sed '/clone/s/g1/p2/'" c1 g1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/edit.exp new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/edit.exp
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/edit.exp 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/edit.exp 2015-10-08 23:44:05.000000000 +0200
@@ -9,7 +9,38 @@
.INP: primitive p1 ocf:heartbeat:Dummy op monitor interval=60m op monitor interval=120m OCF_CHECK_LEVEL=10
.INP: filter "sed '$aprimitive p2 ocf:heartbeat:Dummy'"
.INP: filter "sed '$agroup g1 p1 p2'"
+.INP: show
+node node1 \
+ attributes mem=16G
+primitive p1 Dummy \
+ op monitor interval=60m \
+ op monitor interval=120m OCF_CHECK_LEVEL=10
+primitive p2 Dummy
+primitive st stonith:null \
+ params hostlist=node1 \
+ meta description="some description here" \
+ op start requires=nothing interval=0 \
+ op monitor interval=60m
+group g1 p1 p2
+property cib-bootstrap-options: \
+ default-action-timeout=2m
.INP: filter "sed 's/p2/p3/;$aprimitive p3 ocf:heartbeat:Dummy'" g1
+.INP: show
+node node1 \
+ attributes mem=16G
+primitive p1 Dummy \
+ op monitor interval=60m \
+ op monitor interval=120m OCF_CHECK_LEVEL=10
+primitive p2 Dummy
+primitive p3 Dummy
+primitive st stonith:null \
+ params hostlist=node1 \
+ meta description="some description here" \
+ op start requires=nothing interval=0 \
+ op monitor interval=60m
+group g1 p1 p3
+property cib-bootstrap-options: \
+ default-action-timeout=2m
.INP: filter "sed '$aclone c1 p2'"
.INP: filter "sed 's/p2/g1/'" c1
.INP: filter "sed '/clone/s/g1/p2/'" c1 g1
@@ -26,7 +57,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:g1: Child primitive:d1 already in group:g2
+ERROR: 29: Cannot create group:g1: Child primitive:d1 already in group:g2
.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
@@ -41,15 +72,15 @@
.INP: modgroup g1 add p1
ERROR: 1: syntax in group: child p1 listed more than once in group g1 parsing 'group g1 p1 p2 d3 p1'
.INP: modgroup g1 remove st
-ERROR: 40: configure.modgroup: st is not member of g1
+ERROR: 42: configure.modgroup: st is not member of g1
.INP: modgroup g1 remove c1
-ERROR: 41: configure.modgroup: c1 is not member of g1
+ERROR: 43: configure.modgroup: c1 is not member of g1
.INP: modgroup g1 remove nosuch
-ERROR: 42: configure.modgroup: nosuch is not member of g1
+ERROR: 44: configure.modgroup: nosuch is not member of g1
.INP: modgroup g1 add c1
-ERROR: 43: a group may contain only primitives; c1 is clone
+ERROR: 45: a group may contain only primitives; c1 is clone
.INP: modgroup g1 add nosuch
-ERROR: 44: g1 refers to missing object nosuch
+ERROR: 46: g1 refers to missing object nosuch
.INP: filter "sed 's/^/# this is a comment\n/'" loc-d1
.INP: rsc_defaults $id="rsc_options" failure-timeout=10m
.INP: filter "sed 's/2m/60s/'" cib-bootstrap-options
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/history.exp new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/history.exp
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/history.exp 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/history.exp 2015-10-08 23:44:05.000000000 +0200
@@ -2,6 +2,7 @@
.INP: history
.INP: source history-test.tar.bz2
.INP: info
+.EXT tar -tj < history-test.tar.bz2 2> /dev/null | head -1
.EXT tar -xj < history-test.tar.bz2
Source: history-test.tar.bz2
Created on: Fri 14 Dec 19:08:38 UTC 2012
@@ -278,6 +279,7 @@
.TRY History 2
.INP: history
.INP: session load _crmsh_regtest
+.EXT tar -tj < history-test.tar.bz2 2> /dev/null | head -1
.EXT tar -xj < history-test.tar.bz2
.INP: exclude
corosync|crmd|pengine|stonith-ng|cib|attrd|mgmtd|sshd
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/newfeatures new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/newfeatures
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/newfeatures 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/newfeatures 2015-10-08 23:44:05.000000000 +0200
@@ -19,6 +19,7 @@
tag tag1: p0 p1 p2
tag tag2 p0 p1 p2
location l1 { p0 p1 p2 } inf: node1
+primitive node1 Dummy
show
_test
verify
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/newfeatures.exp new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/newfeatures.exp
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/newfeatures.exp 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/newfeatures.exp 2015-10-08 23:44:05.000000000 +0200
@@ -13,8 +13,10 @@
.INP: tag tag1: p0 p1 p2
.INP: tag tag2 p0 p1 p2
.INP: location l1 { p0 p1 p2 } inf: node1
+.INP: primitive node1 Dummy
.INP: show
node node1
+primitive node1 Dummy
primitive p0 Dummy \
params state=1
primitive p1 Dummy \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/resource.exp new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/resource.exp
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/testcases/resource.exp 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/testcases/resource.exp 2015-10-08 23:44:05.000000000 +0200
@@ -87,7 +87,7 @@
.SETENV showobj=cli-prefer-p3
.TRY resource migrate p3 node1
-.EXT crm_resource --move -r 'p3' --node='node1'
+.EXT crm_resource --quiet --move -r 'p3' --node='node1'
.INP: configure
.INP: _regtest on
.INP: show xml cli-prefer-p3
@@ -105,10 +105,10 @@
.SETENV showobj=
.TRY resource unmigrate p3
-.EXT crm_resource --clear -r 'p3'
+.EXT crm_resource --quiet --clear -r 'p3'
.SETENV showobj=cli-prefer-p3
.TRY resource migrate p3 node1 force
-.EXT crm_resource --move -r 'p3' --node='node1' --force
+.EXT crm_resource --quiet --move -r 'p3' --node='node1' --force
.INP: configure
.INP: _regtest on
.INP: show xml cli-prefer-p3
@@ -126,7 +126,7 @@
.SETENV showobj=
.TRY resource unmigrate p3
-.EXT crm_resource --clear -r 'p3'
+.EXT crm_resource --quiet --clear -r 'p3'
.SETENV showobj=p0
.TRY resource param p0 set a0 "1 2 3"
.EXT crm_resource -r 'p0' -p 'a0' -v '1 2 3'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/unittests/__init__.py new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/unittests/__init__.py
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/unittests/__init__.py 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/unittests/__init__.py 2015-10-08 23:44:05.000000000 +0200
@@ -17,6 +17,8 @@
config.path.sharedir = os.path.join(_here, "../../doc")
config.path.crm_dtd_dir = os.path.join(_here, "schemas")
+os.environ["CIB_file"] = "test"
+
# install a basic CIB
from crmsh import cibconfig
@@ -35,9 +37,9 @@
<nodes>
- <node id="1" uname="ha-one"/>
- <node id="2" uname="ha-two"/>
- <node id="3" uname="ha-three"/>
+ <node id="ha-one" uname="ha-one"/>
+ <node id="ha-two" uname="ha-two"/>
+ <node id="ha-three" uname="ha-three"/>
</nodes>
<resources>
</resources>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/unittests/test_bugs.py new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/unittests/test_bugs.py
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/unittests/test_bugs.py 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/unittests/test_bugs.py 2015-10-08 23:44:05.000000000 +0200
@@ -531,3 +531,219 @@
factory.create_object('colocation', 'coloc-p1-p2-p3', 'inf:', 'p1', 'p2', 'p3')
c = factory.find_object('coloc-p1-p2-p3')
assert c and c.check_sanity() > 0
+
+
+@with_setup(setup_func, teardown_func)
+def test_existing_node_resource():
+ factory.create_object('primitive', 'ha-one', 'Dummy')
+
+ n = factory.find_node('ha-one')
+ assert factory.test_element(n)
+
+ r = factory.find_resource('ha-one')
+ assert factory.test_element(r)
+
+ assert n != r
+
+ assert factory.check_structure()
+ factory.cli_use_validate_all()
+
+ ok, s = factory.mkobj_set('ha-one')
+ assert ok
+
+
+@with_setup(setup_func, teardown_func)
+def test_existing_node_resource_2():
+ obj = cibconfig.mkset_obj()
+ assert obj is not None
+
+ from crmsh import clidisplay
+ with clidisplay.nopretty():
+ text = obj.repr()
+ text += "\nprimitive ha-one Dummy"
+ ok = obj.save(text)
+ assert ok
+
+ obj = cibconfig.mkset_obj()
+ assert obj is not None
+ with clidisplay.nopretty():
+ text2 = obj.repr()
+
+ assert sorted(text.split('\n')) == sorted(text2.split('\n'))
+
+
+@with_setup(setup_func, teardown_func)
+def test_id_collision_breakage_1():
+ from crmsh import clidisplay
+
+ obj = cibconfig.mkset_obj()
+ assert obj is not None
+ with clidisplay.nopretty():
+ original_cib = obj.repr()
+ print original_cib
+
+ obj = cibconfig.mkset_obj()
+ assert obj is not None
+
+ ok = obj.save("""node node1
+primitive p0 ocf:pacemaker:Dummy
+primitive p1 ocf:pacemaker:Dummy
+primitive p2 ocf:heartbeat:Delay \
+ params startdelay=2 mondelay=2 stopdelay=2
+primitive p3 ocf:pacemaker:Dummy
+primitive st stonith:null params hostlist=node1
+clone c1 p1
+ms m1 p2
+property default-action-timeout=60s
+""")
+ assert ok
+
+ obj = cibconfig.mkset_obj()
+ assert obj is not None
+ ok = obj.save("""property default-action-timeout=2m
+node node1 \
+ attributes mem=16G
+primitive st stonith:null \
+ params hostlist='node1' \
+ meta description="some description here" \
+ op start requires=nothing \
+ op monitor interval=60m
+primitive p1 ocf:heartbeat:Dummy \
+ op monitor interval=60m \
+ op monitor interval=120m OCF_CHECK_LEVEL=10
+""")
+ assert ok
+
+ obj = cibconfig.mkset_obj()
+ with clidisplay.nopretty():
+ text = obj.repr()
+ text = text + "\nprimitive p2 ocf:heartbeat:Dummy"
+ ok = obj.save(text)
+ assert ok
+
+ obj = cibconfig.mkset_obj()
+ with clidisplay.nopretty():
+ text = obj.repr()
+ text = text + "\ngroup g1 p1 p2"
+ ok = obj.save(text)
+ assert ok
+
+ obj = cibconfig.mkset_obj("g1")
+ with clidisplay.nopretty():
+ text = obj.repr()
+ text = text.replace("group g1 p1 p2", "group g1 p1 p3")
+ text = text + "\nprimitive p3 ocf:heartbeat:Dummy"
+ ok = obj.save(text)
+ assert ok
+
+ obj = cibconfig.mkset_obj("g1")
+ with clidisplay.nopretty():
+ print obj.repr().strip()
+ assert obj.repr().strip() == "group g1 p1 p3"
+
+ obj = cibconfig.mkset_obj()
+ assert obj is not None
+ ok = obj.save(original_cib)
+ assert ok
+ obj = cibconfig.mkset_obj()
+ with clidisplay.nopretty():
+ print "*** ORIGINAL"
+ print original_cib
+ print "*** NOW"
+ print obj.repr()
+ assert original_cib == obj.repr()
+
+
+@with_setup(setup_func, teardown_func)
+def test_id_collision_breakage_2():
+ from crmsh import clidisplay
+
+ obj = cibconfig.mkset_obj()
+ assert obj is not None
+ with clidisplay.nopretty():
+ original_cib = obj.repr()
+ print original_cib
+
+ obj = cibconfig.mkset_obj()
+ assert obj is not None
+
+ ok = obj.save("""node 168633610: webui
+node 168633611: node1
+rsc_template web-server apache \
+ params port=8000 \
+ op monitor interval=10s
+primitive d0 Dummy \
+ meta target-role=Started
+primitive d1 Dummy
+primitive d2 Dummy
+# Never use this STONITH agent in production!
+primitive development-stonith stonith:null \
+ params hostlist="webui node1 node2 node3"
+primitive proxy systemd:haproxy \
+ op monitor interval=10s
+primitive proxy-vip IPaddr2 \
+ params ip=10.13.37.20
+primitive srv1 @web-server
+primitive srv2 @web-server
+primitive vip1 IPaddr2 \
+ params ip=10.13.37.21 \
+ op monitor interval=20s
+primitive vip2 IPaddr2 \
+ params ip=10.13.37.22 \
+ op monitor interval=20s
+primitive virtual-ip IPaddr2 \
+ params ip=10.13.37.77 lvs_support=false \
+ op start timeout=20 interval=0 \
+ op stop timeout=20 interval=0 \
+ op monitor interval=10 timeout=20
+primitive yet-another-virtual-ip IPaddr2 \
+ params ip=10.13.37.72 cidr_netmask=24 \
+ op start interval=0 timeout=20 \
+ op stop interval=0 timeout=20 \
+ op monitor interval=10 timeout=20 \
+ meta target-role=Started
+group dovip d0 virtual-ip \
+ meta target-role=Stopped
+group g-proxy proxy-vip proxy
+group g-serv1 vip1 srv1
+group g-serv2 vip2 srv2
+clone d2-clone d2 \
+ meta target-role=Started
+tag dummytag d0 d1 d1-on-node1 d2 d2-clone
+# Never put the two web servers on the same node
+colocation co-serv -inf: g-serv1 g-serv2
+location d1-on-node1 d1 inf: node1
+# Never put any web server or haproxy on webui
+location l-avoid-webui { g-proxy g-serv1 g-serv2 } -inf: webui
+# Prever to spread groups across nodes
+location l-proxy g-proxy 200: node1
+location l-serv1 g-serv1 200: node2
+location l-serv2 g-serv2 200: node3
+property cib-bootstrap-options: \
+ have-watchdog=false \
+ dc-version="1.1.13+git20150917.20c2178-224.2-1.1.13+git20150917.20c2178" \
+ cluster-infrastructure=corosync \
+ cluster-name=hacluster \
+ stonith-enabled=true \
+ no-quorum-policy=ignore \
+ placement-strategy=balanced
+rsc_defaults rsc-options: \
+ resource-stickiness=1 \
+ migration-threshold=3
+op_defaults op-options: \
+ timeout=600 \
+ record-pending=true
+""")
+ assert ok
+
+ obj = cibconfig.mkset_obj()
+ assert obj is not None
+ ok = obj.save(original_cib)
+ assert ok
+ obj = cibconfig.mkset_obj()
+ with clidisplay.nopretty():
+ print "*** ORIGINAL"
+ print original_cib
+ print "*** NOW"
+ print obj.repr()
+ assert original_cib == obj.repr()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/unittests/test_objset.py new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/unittests/test_objset.py
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/unittests/test_objset.py 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/unittests/test_objset.py 2015-10-08 23:44:05.000000000 +0200
@@ -39,4 +39,4 @@
setobj = cibconfig.mkset_obj()
s = setobj.repr_nopretty()
sp = s.splitlines()
- assert_in("node 1: ha-one", sp[0:3])
+ assert_in("node ha-one", sp[0:3])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/unittests/test_parse.py new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/unittests/test_parse.py
--- old/crmsh-2.2.0~rc3+git.1443544100.aa2abda/test/unittests/test_parse.py 2015-09-30 17:21:36.000000000 +0200
+++ new/crmsh-2.2.0~rc3+git.1444340345.59850ca/test/unittests/test_parse.py 2015-10-08 23:44:05.000000000 +0200
@@ -434,7 +434,8 @@
# num test nodes are 3
out = self.parser.parse('fencing_topology poison-pill power')
- self.assertEqual("""<fencing-topology><fencing-level devices="poison-pill" index="1" target="ha-one"/><fencing-level devices="power" index="2" target="ha-one"/><fencing-level devices="poison-pill" index="1" target="ha-two"/><fencing-level devices="power" index="2" target="ha-two"/><fencing-level devices="poison-pill" index="1" target="ha-three"/><fencing-level devices="power" index="2" target="ha-three"/></fencing-topology>""", etree.tostring(out))
+ expect = '<fencing-topology><fencing-level devices="poison-pill" index="1" target="ha-one"/><fencing-level devices="power" index="2" target="ha-one"/><fencing-level devices="poison-pill" index="1" target="ha-three"/><fencing-level devices="power" index="2" target="ha-three"/><fencing-level devices="poison-pill" index="1" target="ha-two"/><fencing-level devices="power" index="2" target="ha-two"/></fencing-topology>'
+ self.assertEqual(expect, etree.tostring(out))
out = self.parser.parse('fencing_topology node-a: poison-pill power node-b: ipmi serial')
self.assertEqual(4, len(out))
@@ -661,7 +662,7 @@
'',
'',
'',
- '<fencing-topology><fencing-level devices="st" index="1" target="ha-one"/><fencing-level devices="st2" index="2" target="ha-one"/><fencing-level devices="st" index="1" target="ha-two"/><fencing-level devices="st2" index="2" target="ha-two"/><fencing-level devices="st" index="1" target="ha-three"/><fencing-level devices="st2" index="2" target="ha-three"/></fencing-topology>',
+ '<fencing-topology><fencing-level devices="st" index="1" target="ha-one"/><fencing-level devices="st2" index="2" target="ha-one"/><fencing-level devices="st" index="1" target="ha-three"/><fencing-level devices="st2" index="2" target="ha-three"/><fencing-level devices="st" index="1" target="ha-two"/><fencing-level devices="st2" index="2" target="ha-two"/></fencing-topology>',
'<nvpair name="stonith-enabled" value="true"/>',
'<nvpair name="maintenance-mode" value="true"/>',
'<nvpair name="failure-timeout" value="10m"/>',