Hello community,
here is the log from the commit of package crmsh for openSUSE:Factory checked in at 2014-06-01 19:40:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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-23 07:51:35.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.crmsh.new/crmsh.changes 2014-06-01 19:40:23.000000000 +0200
@@ -1,0 +2,9 @@
+Tue May 27 18:13:25 UTC 2014 - kgronlund@suse.com
+
+- high: cibconfig: adjust attributes when adding operations (bnc#880052)
+- high: parse: Support id-ref in nvpairs (fate#316118)
+- low: ui_configure: Add --force flag to configure delete
+- low: ui_resource: Allow untrace without explicit interval
+- upstream: 2.0.0-93-g29c4073
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ crmsh.spec ++++++
--- /var/tmp/diff_new_pack.e9PSHG/_old 2014-06-01 19:40:25.000000000 +0200
+++ /var/tmp/diff_new_pack.e9PSHG/_new 2014-06-01 19:40:25.000000000 +0200
@@ -41,7 +41,7 @@
Summary: High Availability cluster command-line interface
License: GPL-2.0+
Group: %{pkg_group}
-Version: 2.0+git88
+Version: 2.0+git93
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-22 19:04:46.000000000 +0200
+++ new/crmsh/doc/crm.8.txt 2014-05-27 20:11:56.000000000 +0200
@@ -2146,6 +2146,79 @@
true, explicitly set `sequential` in a parenthesis set:
`A B ( C D sequential=true )`.
+==== References in attribute lists
+
+Attribute lists are used to set attributes and parameters for
+resources, constraints and property definitions. For example, to set
+the virtual IP used by an `IPAddr` resource the attribute `ip` can be
+set in an attribute list for that resource.
+
+Attribute lists can have identifiers that name them, and other
+resources can reuse the same attribute list by referring to that name
+using an `$id-ref`. For example, the following statement defines a
+simple dummy resource with an attribute list which sets the parameter
+`state to the value 1 and sets the identifier for the attribute list
+to `on-state`:
+
+..............
+primitive dummy-1 Dummy params $id=on-state state=1
+..............
+
+To refer to this attribute list from a different resource, refer to
+the `on-state` name using an id-ref:
+
+..............
+primitive dummy-2 Dummy params $id-ref=on-state
+..............
+
+The resource `dummy-2` will now also have the parameter `state` set to the value 1.
+
+===== Referencing individual attributes
+
+In some cases, referencing complete attribute lists is too
+coarse-grained, for example if two different parameters with different
+names should have the same value set. Instead of having to copy the
+value in multiple places, it is possible to create references to
+individual attributes in attribute lists.
+
+To name an attribute in order to be able to refer to it later, prefix
+the attribute name with a `$` character (as seen above with the
+special names `$id` and `$id-ref`:
+
+............
+primitive dummy-1 Dummy params $state=1
+............
+
+The identifier `state` can now be used to refer to this attribute from other
+primitives, using the `@<id>` syntax:
+
+............
+primitive dummy-2 Dummy params @state
+............
+
+In some cases, using the attribute name as the identifier doesn't work
+due to name clashes. In this case, the syntax `$<id>:<name>=<value>`
+can be used to give the attribute a different identifier:
+
+............
+primitive dummy-1 params $dummy-state-on:state=1
+primitive dummy-2 params @state
+............
+
+There is also the possibility that two resources both use the same
+attribute value but with different names. For example, a web server
+may have a parameter `server_ip` for setting the IP address where it
+listens for incoming requests, and a virtual IP resource may have a
+parameter called `ip` which sets the IP address it creates. To
+configure these two resources with an IP without repeating the value,
+the reference can be given a name using the syntax `@<id>:<name>`.
+
+Example:
+............
+primitive virtual-ip IPaddr2 params $vip:ip=192.168.1.100
+primitive webserver apache params @vip:server_ip
+............
+
[[cmdhelp_configure_node,define a cluster node]]
==== `node`
@@ -2861,9 +2934,12 @@
in that container, then the container is deleted as well. Any
related constraints are removed as well.
+If the object is a started resource, it will not be deleted unless the
+`--force` flag is passed to the command, or the `force` option is set.
+
Usage:
...............
-delete <id> [<id>...]
+delete [--force] <id> [<id>...]
...............
[[cmdhelp_configure_default-timeouts,set timeouts for operations to minimums from the meta-data]]
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-22 19:04:46.000000000 +0200
+++ new/crmsh/modules/cibconfig.py 2014-05-27 20:11:56.000000000 +0200
@@ -41,7 +41,7 @@
from utils import ext_cmd, safe_open_w, pipe_string, safe_close_w, crm_msec
from utils import ask, lines2cli, olist
from utils import page_string, cibadmin_can_patch, str2tmp
-from utils import run_ptest, is_id_valid, edit_file, get_boolean, filter_string, find_value
+from utils import run_ptest, is_id_valid, edit_file, get_boolean, filter_string
from ordereddict import odict
from xmlutil import is_child_rsc, rsc_constraint, sanitize_cib, rename_id, get_interesting_nodes
from xmlutil import is_pref_location, get_topnode, new_cib, get_rscop_defaults_meta_node
@@ -56,7 +56,7 @@
from xmlutil import get_rsc_operations, delete_rscref, xml_equals, lookup_node, RscState
from xmlutil import cibtext2elem
from cliformat import get_score, nvpairs2list, abs_pos_score, cli_acl_roleref, nvpair_format
-from cliformat import cli_acl_rule, rsc_set_constraint, get_kind, head_id_format
+from cliformat import cli_nvpair, cli_acl_rule, rsc_set_constraint, get_kind, head_id_format
from cliformat import cli_operations, simple_rsc_constraint, cli_rule, cli_format
@@ -197,21 +197,19 @@
tonode.append(copy.deepcopy(cnode))
def copy_nvpair(nvp):
+ if 'value' not in nvp:
+ tonode.append(copy.deepcopy(nvp))
+ return
n = nvp.get('name')
for nvp2 in tonode:
if nvp2.get('name') == n:
nvp2.set('value', nvp.get('value'))
break
else:
- m = etree.SubElement(tonode,
- 'nvpair',
- name=n,
- value=nvp.get('value'))
- if 'id' in nvp.attrib:
- m.set('id', nvp.get('id'))
- else:
- m.set('id', idmgmt.new(m, id_hint))
+ m = copy.deepcopy(nvp)
tonode.append(m)
+ if 'id' not in m.attrib:
+ m.set('id', idmgmt.new(m, id_hint))
def copy_id(node):
nid = node.get('id')
@@ -469,18 +467,19 @@
for a in r_node.iterchildren("instance_attributes"):
for p in a.iterchildren("nvpair"):
name = p.get("name")
+ value = p.get("value")
# don't fail if the meta-data doesn't contain the
# expected attributes
- try:
- if ra_params[name].get("unique") == "1":
- value = p.get("value")
- k = (ra_class, ra_provider, ra_type, name, value)
- try:
- clash_dict[k].append(ra_id)
- except KeyError:
- clash_dict[k] = [ra_id]
- except KeyError:
- pass
+ if value is not None:
+ try:
+ if ra_params[name].get("unique") == "1":
+ k = (ra_class, ra_provider, ra_type, name, value)
+ try:
+ clash_dict[k].append(ra_id)
+ except KeyError:
+ clash_dict[k] = [ra_id]
+ except KeyError:
+ pass
return
# we check the whole CIB for clashes as a clash may originate between
# an object already committed and a new one
@@ -764,12 +763,42 @@
recurse(node, oldnode, hint_map.get(node.tag, ''))
+def resolve_idref(node):
+ """
+ resolve id-ref references that refer
+ to object ids, not attribute lists
+ """
+ id_ref = node.get('id-ref')
+ attr_list_type = node.tag
+ obj = cib_factory.find_object(id_ref)
+ if obj:
+ nodes = obj.node.xpath(".//%s" % attr_list_type)
+ if len(nodes) > 1:
+ common_warn("%s contains more than one %s, using first" %
+ (obj.obj_id, attr_list_type))
+ if len(nodes) > 0:
+ node_id = nodes[0].get("id")
+ if node_id:
+ return node_id
+ target = cib_factory.get_cib().xpath('.//*[@id="%s"]' % (id_ref))
+ if len(target) == 0:
+ common_err("Reference not found: %s" % id_ref)
+ elif len(target) > 1:
+ common_err("Ambiguous reference to %s" % id_ref)
+ return id_ref
+
+
def resolve_references(node):
"""
In the output from parse(), there are
possible references to other nodes in
the CIB. This resolves those references.
"""
+ idrefnodes = node.xpath('.//*[@id-ref]')
+ if 'id-ref' in node.attrib:
+ idrefnodes += [node]
+ for ref in idrefnodes:
+ ref.set('id-ref', resolve_idref(ref))
for ref in node.iterchildren('crmsh-ref'):
child_id = ref.get('id')
obj = cib_factory.find_object(child_id)
@@ -1002,9 +1031,9 @@
for c in node.iterchildren():
if c.tag == "rule":
- ret += "%s %s " % (clidisplay.keyword("rule"), cli_rule(c, cib_factory.is_id_refd))
+ ret += "%s %s " % (clidisplay.keyword("rule"), cli_rule(c))
elif c.tag == "nvpair":
- ret += "%s " % (nvpair_format(c.get("name"), c.get("value")))
+ ret += "%s " % (cli_nvpair(c))
if ret[-1] == ' ':
ret = ret[:-1]
return ret
@@ -1338,7 +1367,8 @@
for p in self.node.xpath("instance_attributes/nvpair"):
n = p.get("name")
v = p.get("value")
- self.set_attr(n, v)
+ if n is not None and v is not None:
+ self.set_attr(n, v)
def mkxml(self):
# create an xml node
@@ -1348,8 +1378,9 @@
idmgmt.remove_xml(self.node)
self.node = etree.Element(self.elem_type)
inst_attr = {}
+ valid_attrs = olist(schema.get('attr', 'op', 'a'))
for n, v in self.attr_d.iteritems():
- if n in olist(schema.get('attr', 'op', 'a')):
+ if n in valid_attrs:
self.node.set(n, v)
else:
inst_attr[n] = v
@@ -1408,6 +1439,20 @@
# create an xml node
if 'id' not in node.attrib:
idmgmt.set(node, None, self.obj_id)
+ valid_attrs = olist(schema.get('attr', 'op', 'a'))
+ inst_attr = {}
+ for attr in node.attrib.keys():
+ if attr not in valid_attrs:
+ inst_attr[attr] = node.attrib[attr]
+ del node.attrib[attr]
+ if inst_attr:
+ attr_nodes = node.xpath('./instance_attributes')
+ if len(attr_nodes) == 1:
+ fill_nvpairs("instance_attributes", attr_nodes[0], inst_attr, node.get("id"))
+ else:
+ nia = mkxmlnvpairs("instance_attributes", inst_attr, node.get("id"))
+ node.append(nia)
+
self._append_op(node)
comments = find_comment_nodes(node)
for comment in comments:
@@ -1635,7 +1680,7 @@
def _repr_cli_child(self, c, format):
if c.tag == "rule":
return "%s %s" % \
- (clidisplay.keyword("rule"), cli_rule(c, cib_factory.is_id_refd))
+ (clidisplay.keyword("rule"), cli_rule(c))
def check_sanity(self):
'''
@@ -1836,9 +1881,9 @@
def _repr_cli_child(self, c, format):
if c.tag == "rule":
return ' '.join((clidisplay.keyword("rule"),
- cli_rule(c, cib_factory.is_id_refd)))
+ cli_rule(c)))
elif c.tag == "nvpair":
- return nvpair_format(c.get("name"), c.get("value"))
+ return cli_nvpair(c)
else:
return ''
@@ -2034,11 +2079,7 @@
def can_migrate(node):
- for c in node.iterchildren("meta_attributes"):
- pl = nvpairs2list(c)
- if find_value(pl, "allow-migrate") == "true":
- return True
- return False
+ return 'true' in node.xpath('.//nvpair[@name="allow-migrate"]/@value')
cib_upgrade = "cibadmin --upgrade --force"
@@ -2648,7 +2689,10 @@
return rc
def is_id_refd(self, attr_list_type, id):
- '''Is this ID referenced anywhere?'''
+ '''
+ Is this ID referenced anywhere?
+ Used from cliformat
+ '''
try:
return self.id_refs[id] == attr_list_type
except KeyError:
@@ -2661,36 +2705,32 @@
one, i.e. if the former is the case to find the right
id to reference.
'''
- obj = self.find_object(id_ref)
self.id_refs[id_ref] = attr_list_type
+ obj = self.find_object(id_ref)
if obj:
- node_l = obj.node.xpath(".//%s" % attr_list_type)
- if node_l:
- if len(node_l) > 1:
- common_warn("%s contains more than one %s, using first" %
- (obj.obj_id, attr_list_type))
- id = node_l[0].get("id")
- if not id:
- common_err("%s reference not found" % id_ref)
- return id_ref # hope that user will fix that
- return id
- # verify if id_ref exists
- node_l = self.cib_elem.xpath(".//%s" % attr_list_type)
- for node in node_l:
- if node.get("id") == id_ref:
- return id_ref
- common_err("%s reference not found" % id_ref)
- return id_ref # hope that user will fix that
+ nodes = obj.node.xpath(".//%s" % attr_list_type)
+ if len(nodes) > 1:
+ common_warn("%s contains more than one %s, using first" %
+ (obj.obj_id, attr_list_type))
+ if len(nodes) > 0:
+ node_id = nodes[0].get("id")
+ if node_id:
+ return node_id
+ target = self.cib_elem.xpath('.//*[@id="%s"]' % (id_ref))
+ if len(target) == 0:
+ common_err("Reference not found: %s" % id_ref)
+ elif len(target) > 1:
+ common_err("Ambiguous reference to %s" % id_ref)
+ return id_ref
def _get_attr_value(self, obj_type, attr):
if not self.is_cib_sane():
return None
for obj in self.cib_objects:
if obj.obj_type == obj_type and obj.node is not None:
- pl = nvpairs2list(obj.node)
- v = find_value(pl, attr)
- if v:
- return v
+ for n in nvpairs2list(obj.node):
+ if n.get('name') == attr:
+ return n.get('value')
return None
def get_property(self, property):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/cliformat.py new/crmsh/modules/cliformat.py
--- old/crmsh/modules/cliformat.py 2014-05-22 19:04:46.000000000 +0200
+++ new/crmsh/modules/cliformat.py 2014-05-27 20:11:56.000000000 +0200
@@ -17,7 +17,6 @@
import constants
import clidisplay
-from msg import common_err, node_debug
import utils
import xmlutil
@@ -68,61 +67,74 @@
return '%s="%s"' % (clidisplay.attr_name(n), clidisplay.attr_value(v))
-def cli_pairs(pl):
- 'Return a string of name="value" pairs (passed in a list of pairs).'
- l = []
- for n, v in pl:
- l.append(nvpair_format(n, v))
- return ' '.join(l)
+def cli_nvpair(nvp):
+ 'Converts an nvpair tag to CLI syntax'
+ from cibconfig import cib_factory
+ nodeid = nvp.get('id')
+ idref = nvp.get('id-ref')
+ name = nvp.get('name')
+ if idref is not None:
+ if name is not None:
+ return '@%s:%s' % (idref, name)
+ return '@%s' % (idref)
+ elif nodeid is not None and cib_factory.is_id_refd(nvp.tag, nodeid):
+ return '$%s:%s' % (nodeid, nvpair_format(name, nvp.get('value')))
+ return nvpair_format(name, nvp.get('value'))
+
+
+def cli_nvpairs(nvplist):
+ 'Return a string of name="value" pairs (passed in a list of nvpairs).'
+ return ' '.join([cli_nvpair(nvp) for nvp in nvplist])
def nvpairs2list(node, add_id=False):
'''
- Convert nvpairs to a list of pairs.
+ Convert an attribute node to a list of nvpairs.
+ Also converts an id-ref or id into plain nvpairs.
The id attribute is normally skipped, since they tend to be
long and therefore obscure the relevant content. For some
elements, however, they are included (e.g. properties).
'''
- pl = []
- # if there's id-ref, there can be then _only_ id-ref
- value = node.get("id-ref")
- if value:
- pl.append(["$id-ref", value])
- return pl
- if add_id or \
- (not len(node) and len(node.attrib) == 1):
- value = node.get("id")
- if value:
- pl.append(["$id", value])
- for c in node.iterchildren():
- if c.tag == "attributes":
- pl = nvpairs2list(c)
- elif c.tag == "rule" or xmlutil.is_comment(c):
- # skip rule expressions and comments
- continue
- elif c.tag != "nvpair":
- node_debug("expected nvpair got", c)
- continue
- pl.append([c.get("name"), c.get("value")])
- return pl
+ import xmlbuilder
+
+ ret = []
+ if 'id-ref' in node:
+ ret.append(xmlbuilder.nvpair('$id-ref', node.get('id-ref')))
+ nvpairs = node.xpath('./nvpair | ./attributes/nvpair')
+ if 'id' in node and (add_id or len(nvpairs) == 0):
+ ret.append(xmlbuilder.nvpair('$id', node.get('id')))
+ ret.extend(nvpairs)
+ return ret
+
+
+def cli_attributes(node, add_id=False):
+ '''
+ Convert an attribute tag to CLI syntax
+ Does not honor possible <rule> tags
+ '''
+ return ' '.join([cli_nvpair(nvp)
+ for nvp in nvpairs2list(node, add_id=add_id)])
def op_instattr(node):
+ """
+ Return nvpairs in <op>