Hello community,

here is the log from the commit of package crmsh for openSUSE:Factory checked 
in at 2016-05-17 17:15:00
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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      2016-05-05 
12:12:22.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.crmsh.new/crmsh.changes 2016-05-17 
17:15:03.000000000 +0200
@@ -1,0 +2,10 @@
+Thu May 12 08:40:54 UTC 2016 - kgronl...@suse.com
+
+- Update to version 2.2.0+git.1462967444.169c554:
+  + high: parse: Support for event-driven alerts (fate#320855) (#136)
+  + high: utils: Avoid deadlock if DC changes during idle wait (bsc#978480)
+  + medium: ui_resource: Add force argument to resource cleanup (bsc#979420)
+  + medium: ui_resource: Show utilization in output from crm resource scores
+  + high: ui_resource: Improved resource move/clear/locate commands
+
+-------------------------------------------------------------------

Old:
----
  crmsh-2.2.0+git.1462285059.d79cd0d.tar.bz2

New:
----
  crmsh-2.2.0+git.1462967444.169c554.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ crmsh.spec ++++++
--- /var/tmp/diff_new_pack.qvK0Pp/_old  2016-05-17 17:15:04.000000000 +0200
+++ /var/tmp/diff_new_pack.qvK0Pp/_new  2016-05-17 17:15:04.000000000 +0200
@@ -32,13 +32,13 @@
 
 %{!?python_sitelib: %define python_sitelib %(python -c "from 
distutils.sysconfig import get_python_lib; print get_python_lib()")}
 
-%define version_unconverted 2.2.0+git.1462285059.d79cd0d
+%define version_unconverted 2.2.0+git.1462967444.169c554
 
 Name:           crmsh
 Summary:        High Availability cluster command-line interface
 License:        GPL-2.0+
 Group:          %{pkg_group}
-Version:        2.2.0+git.1462285059.d79cd0d
+Version:        2.2.0+git.1462967444.169c554
 Release:        0
 Url:            http://crmsh.github.io
 Source0:        %{name}-%{version}.tar.bz2

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.qvK0Pp/_old  2016-05-17 17:15:04.000000000 +0200
+++ /var/tmp/diff_new_pack.qvK0Pp/_new  2016-05-17 17:15:04.000000000 +0200
@@ -1,4 +1,4 @@
 <servicedata>
 <service name="tar_scm">
             <param name="url">git://github.com/ClusterLabs/crmsh.git</param>
-          <param 
name="changesrevision">d79cd0db97b99ccb6d4dbbe9797917c18a4982aa</param></service></servicedata>
\ No newline at end of file
+          <param 
name="changesrevision">169c5549accf42af8b89f6cc4d574c6c219768b1</param></service></servicedata>
\ No newline at end of file

++++++ crmsh-2.2.0+git.1462285059.d79cd0d.tar.bz2 -> 
crmsh-2.2.0+git.1462967444.169c554.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-2.2.0+git.1462285059.d79cd0d/.gitignore 
new/crmsh-2.2.0+git.1462967444.169c554/.gitignore
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/.gitignore   2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/.gitignore   1970-01-01 
01:00:00.000000000 +0100
@@ -1,19 +0,0 @@
-*.pyc
-*~
-#*.*#
-.#*
-doc/website-v1/gen
-Makefile.in
-autom4te.cache
-patches/*
-
-# Tool specific files
-.README.md.html
-.*.*~
-.project
-.settings
-.pydevproject
-
-contrib/build/
-contrib/dist/
-contrib/pygments_crmsh_lexers.egg-info/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-2.2.0+git.1462285059.d79cd0d/.hgignore 
new/crmsh-2.2.0+git.1462967444.169c554/.hgignore
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/.hgignore    2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/.hgignore    1970-01-01 
01:00:00.000000000 +0100
@@ -1,7 +0,0 @@
-syntax: glob
-
-*.pyc
-*~
-#*.*#
-doc/gen
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-2.2.0+git.1462285059.d79cd0d/Makefile.am 
new/crmsh-2.2.0+git.1462967444.169c554/Makefile.am
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/Makefile.am  2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/Makefile.am  2016-05-12 
10:40:53.000000000 +0200
@@ -73,11 +73,11 @@
 install-exec-local:
        -mkdir -p $(DESTDIR)$(pkgpythondir)
        $(PYTHON) $(srcdir)/setup.py install \
-               --root $(DESTDIR) \
+               --root $(DESTDIR)/// \
                $(python_prefix) \
                --record $(DESTDIR)$(pkgpythondir)/install_files.txt \
                --verbose
-       $(INSTALL) -d -m 770 $(DESTDIR)/$(CRM_CACHE_DIR)
+       $(INSTALL) -d -m 770 $(DESTDIR)$(CRM_CACHE_DIR)
 
 uninstall-local:
        cat $(DESTDIR)$(pkgpythondir)/install_files.txt | xargs rm -rf
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/cibconfig.py 
new/crmsh-2.2.0+git.1462967444.169c554/crmsh/cibconfig.py
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/cibconfig.py   2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/crmsh/cibconfig.py   2016-05-12 
10:40:53.000000000 +0200
@@ -47,7 +47,7 @@
 from .cliformat import get_score, nvpairs2list, abs_pos_score, 
cli_acl_roleref, nvpair_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
-from .cliformat import cli_acl_role, cli_acl_permission
+from .cliformat import cli_acl_role, cli_acl_permission, cli_path
 
 
 def show_unrecognized_elems(cib_elem):
@@ -657,6 +657,7 @@
         'rsc_location': 'location',
         'fencing-topology': 'fencing',
         'tags': 'tag',
+        'alerts': 'alert',
         }
 
     idless = set(['operations', 'fencing-topology'])
@@ -2018,6 +2019,53 @@
                          for c in self.node.iterchildren() if not 
is_comment(c)])
 
 
+class CibAlert(CibObject):
+    '''
+    Alert objects
+
+    TODO: check_sanity, repr_gv
+
+    FIXME: display instance / meta attributes, description
+
+    '''
+    set_names = {
+        "instance_attributes": "attributes",
+        "meta_attributes": "meta",
+    }
+
+    def _repr_cli_head(self, fmt):
+        ret = [clidisplay.keyword(self.obj_type),
+               clidisplay.ident(self.obj_id),
+               cli_path(self.node.get('path'))]
+        return ' '.join(ret)
+
+    def _repr_cli_child(self, c, format_mode):
+        if c.tag in self.set_names:
+            return self._attr_set_str(c)
+        elif c.tag == "recipient":
+            r = ["to"]
+            complex = self._is_complex()
+            if complex:
+                r.append('{')
+            r.append(cli_path(c.get('value')))
+            for subset in c.xpath('instance_attributes|meta_attributes'):
+                r.append(self._attr_set_str(subset))
+            if complex:
+                r.append('}')
+            return ' '.join(r)
+
+    def _is_complex(self):
+        '''
+        True if this alert is ambiguous wrt meta attributes in recipient tags
+        '''
+        children = [c.tag for c in 
self.node.xpath('recipient|instance_attributes|meta_attributes')]
+        ri = children.index('recipient')
+        if ri < 0:
+            return False
+        children = children[ri+1:]
+        return 'instance_attributes' in children or 'meta_attributes' in 
children
+
+
 #
 ################################################################
 
@@ -2062,6 +2110,7 @@
     "acl_target": ("acl_target", CibAcl, "acls"),
     "acl_group": ("acl_group", CibAcl, "acls"),
     "tag": ("tag", CibTag, "tags"),
+    "alert": ("alert", CibAlert, "alerts"),
 }
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/cliformat.py 
new/crmsh-2.2.0+git.1462967444.169c554/crmsh/cliformat.py
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/cliformat.py   2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/crmsh/cliformat.py   2016-05-12 
10:40:53.000000000 +0200
@@ -250,6 +250,10 @@
         return rsc
 
 
+def cli_path(p):
+    return clidisplay.attr_value(quote_wrap(p))
+
+
 def boolean_maybe(v):
     "returns True/False or None"
     if v is None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/cmd_status.py 
new/crmsh-2.2.0+git.1462967444.169c554/crmsh/cmd_status.py
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/cmd_status.py  2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/crmsh/cmd_status.py  2016-05-12 
10:40:53.000000000 +0200
@@ -3,7 +3,7 @@
 # See COPYING for license information.
 
 import re
-import clidisplay
+from . import clidisplay
 from . import utils
 
 _crm_mon = None
@@ -125,7 +125,6 @@
     Calls crm_verify -LV; ptest -L -VVVV
     '''
     from . import config
-    from . import clidisplay
     if "ptest" in config.core.ptest:
         cmd1 = "crm_verify -LV; %s -L -VVVV" % (config.core.ptest)
     else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/constants.py 
new/crmsh-2.2.0+git.1462967444.169c554/crmsh/constants.py
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/constants.py   2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/crmsh/constants.py   2016-05-12 
10:40:53.000000000 +0200
@@ -218,6 +218,9 @@
 ms_meta_attributes = (
     "master-max", "master-node-max", "description",
 )
+alert_meta_attributes = (
+    "timeout", "timestamp-format"
+)
 trace_ra_attr = "trace_ra"
 score_types = {'advisory': '0', 'mandatory': 'INFINITY'}
 boolean_ops = ('or', 'and')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/parse.py 
new/crmsh-2.2.0+git.1462967444.169c554/crmsh/parse.py
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/parse.py       2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/crmsh/parse.py       2016-05-12 
10:40:53.000000000 +0200
@@ -23,6 +23,7 @@
 _DISPATCH_RE = re.compile(r'[a-z0-9_]+$', re.IGNORECASE)
 _DESC_RE = re.compile(r'description=(.+)$', re.IGNORECASE)
 _ATTR_RE = re.compile(r'\$?([^=]+)=(.*)$')
+_ALERT_PATH_RE = re.compile(r'(.*)$')
 _RESOURCE_RE = re.compile(r'([a-z_#$][^=]*)$', re.IGNORECASE)
 _IDSPEC_RE = re.compile(r'(\$id-ref|\$id)=(.*)$', re.IGNORECASE)
 _ID_RE = re.compile(r'\$id=(.*)$', re.IGNORECASE)
@@ -393,7 +394,7 @@
             tokens.append(self.match_any())
         return tokens
 
-    def match_attr_list(self, name, tag, allow_empty=True):
+    def match_attr_list(self, name, tag, allow_empty=True, terminator=None):
         """
         matches [$id=<id>] [<score>:] <n>=<v> <n>=<v> ... | $id-ref=<id-ref>
         if matchname is False, matches:
@@ -414,12 +415,12 @@
         if self.try_match(_SCORE_RE):
             score = self.matched(1)
         rules = self.match_rules()
-        values = self.match_nvpairs(minpairs=0)
+        values = self.match_nvpairs(minpairs=0, terminator=terminator)
         if (allow_empty, xmlid, score, len(rules), len(values)) == (False, 
None, None, 0, 0):
             return None
         return xmlutil.attributes(tag, rules, values, xmlid=xmlid, score=score)
 
-    def match_attr_lists(self, name_map, implicit_initial=None):
+    def match_attr_lists(self, name_map, implicit_initial=None, 
terminator=None):
         """
         generator which matches attr_lists
         name_map: maps CLI name to XML name
@@ -427,16 +428,17 @@
         to_match = '|'.join(name_map.keys())
         if self.try_match(to_match):
             name = self.matched(0).lower()
-            yield self.match_attr_list(name, name_map[name])
+            yield self.match_attr_list(name, name_map[name], 
terminator=terminator)
         elif implicit_initial is not None:
             attrs = self.match_attr_list(implicit_initial,
                                          name_map[implicit_initial],
-                                         allow_empty=False)
+                                         allow_empty=False,
+                                         terminator=terminator)
             if attrs is not None:
                 yield attrs
         while self.try_match(to_match):
             name = self.matched(0).lower()
-            yield self.match_attr_list(name, name_map[name])
+            yield self.match_attr_list(name, name_map[name], 
terminator=terminator)
 
     def match_rules(self):
         '''parse rule definitions'''
@@ -585,7 +587,7 @@
         else:
             return ['score-attribute', score]
 
-    def match_arguments(self, out, name_map, implicit_initial=None):
+    def match_arguments(self, out, name_map, implicit_initial=None, 
terminator=None):
         """
         [<name> attr_list]
         [operations id_spec]
@@ -612,12 +614,13 @@
                 if t in oplist:
                     self.match_operations(out, t == 'operations')
                 else:
-                    for attr_list in self.match_attr_lists(name_map):
+                    for attr_list in self.match_attr_lists(name_map, 
terminator=terminator):
                         out.append(attr_list)
             elif initial:
                 initial = False
                 for attr_list in self.match_attr_lists(name_map,
-                                                       
implicit_initial=implicit_initial):
+                                                       
implicit_initial=implicit_initial,
+                                                       terminator=terminator):
                     out.append(attr_list)
             else:
                 break
@@ -1354,6 +1357,57 @@
     return e
 
 
+@parser_for('alert')
+def parse_alert(self, cmd):
+    """
+    <alerts>
+    <alert id=ID path=PATH>
+      <recipient id=RID value=VALUE/>
+      <meta_attributes ..>
+      <instance_attributes ..>
+      ...
+
+      meta attributes "timeout", "tstamp_format"
+    </tag>
+
+    alert ID PATH [attributes ...] [meta ...] [to [{] recipient [}] ...]
+    recipient :: PATH [attributes ...] [meta ...]
+    """
+    self.begin(cmd, min_args=2)
+    self.match('alert')
+    alertid = self.match_identifier()
+    path = self.match(_ALERT_PATH_RE, errmsg="Expected path")
+    out = xmlutil.new('alert', id=alertid, path=path)
+    desc = self.try_match_description()
+    if desc is not None:
+        out.attrib['description'] = desc
+    rcount = 1
+    while self.has_tokens():
+        if self.current_token() in ('attributes', 'meta'):
+            self.match_arguments(out, {'attributes': 'instance_attributes',
+                                       'meta': 'meta_attributes'},
+                                 terminator=['attributes', 'meta', 'to'])
+            continue
+        self.match('to')
+        rid = '%s-recipient-%s' % (alertid, rcount)
+        rcount += 1
+        bracer = self.try_match('{')
+        elem = xmlutil.new('recipient', id=rid, value=self.match_any())
+        desc = self.try_match_description()
+        terminators = ['attributes', 'meta', 'to']
+        if bracer:
+            terminators.append('}')
+        if desc is not None:
+            elem.attrib['description'] = desc
+        self.match_arguments(elem, {'attributes': 'instance_attributes',
+                                    'meta': 'meta_attributes'},
+                             terminator=terminators)
+        if bracer:
+            self.match('}')
+        out.append(elem)
+    return out
+
+
 class ResourceSet(object):
     '''
     Constraint resource set parser. Parses sth like:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/ui_configure.py 
new/crmsh-2.2.0+git.1462967444.169c554/crmsh/ui_configure.py
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/ui_configure.py        
2016-05-03 16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/crmsh/ui_configure.py        
2016-05-12 10:40:53.000000000 +0200
@@ -847,6 +847,10 @@
     def do_tag(self, context, *args):
         return self.__conf_object(context.get_command_name(), *args)
 
+    @command.skill_level('administrator')
+    def do_alert(self, context, *args):
+        return self.__conf_object(context.get_command_name(), *args)
+
     @command.skill_level('expert')
     @command.completers_repeating(_rsc_id_list)
     def do_rsctest(self, context, *args):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/ui_resource.py 
new/crmsh-2.2.0+git.1462967444.169c554/crmsh/ui_resource.py
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/ui_resource.py 2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/crmsh/ui_resource.py 2016-05-12 
10:40:53.000000000 +0200
@@ -150,13 +150,14 @@
     return True
 
 
-def cleanup_resource(rsc, node=''):
+def cleanup_resource(rsc, node='', force=False):
     if not utils.is_name_sane(rsc) or not utils.is_name_sane(node):
         return False
+    forces = " -f" if force else ""
     if not node:
-        rc = utils.ext_cmd(RscMgmt.rsc_cleanup_all % (rsc)) == 0
+        rc = utils.ext_cmd((RscMgmt.rsc_cleanup_all % (rsc)) + forces) == 0
     else:
-        rc = utils.ext_cmd(RscMgmt.rsc_cleanup % (rsc, node)) == 0
+        rc = utils.ext_cmd((RscMgmt.rsc_cleanup % (rsc, node)) + forces) == 0
     return rc
 
 
@@ -313,12 +314,20 @@
     def do_scores(self, context):
         "usage: scores"
         if utils.is_program('crm_simulate'):
-            utils.ext_cmd('crm_simulate -sL')
+            utils.ext_cmd('crm_simulate -sUL')
         elif utils.is_program('ptest'):
-            utils.ext_cmd('ptest -sL')
+            utils.ext_cmd('ptest -sUL')
         else:
             context.fatal_error("Need crm_simulate or ptest in path to display 
scores")
 
+    @command.completers(compl.resources)
+    def do_locate(self, context, *resources):
+        "usage: locate <rsc> [<rsc> ...]"
+        if len(resources) == 0:
+            context.error("Expected at least one resource as argument")
+        for rsc in resources:
+            utils.ext_cmd("crm_resource --resource '%s' --locate" % (rsc))
+
     @command.wait
     @command.completers(compl.resources)
     def do_demote(self, context, rsc):
@@ -340,23 +349,28 @@
         "usage: unmanage <rsc>"
         return self._commit_meta_attr(context, rsc, "is-managed", "false")
 
-    @command.alias('move')
+    @command.alias('migrate')
     @command.skill_level('administrator')
     @command.wait
     @command.completers_repeating(compl.resources, compl.nodes,
                                   compl.choice(['reboot', 'forever', 'force']))
-    def do_migrate(self, context, rsc, *args):
-        """usage: migrate <rsc> [<node>] [<lifetime>] [force]"""
+    def do_move(self, context, rsc, *args):
+        """usage: move <rsc> [<node>] [<lifetime>] [force]"""
         if not utils.is_name_sane(rsc):
             return False
         node = None
         argl = list(args)
-        force = "force" in utils.fetch_opts(argl, ["force"])
+        force = "force" in utils.fetch_opts(argl, ["force"]) or 
config.core.force
         lifetime = utils.fetch_lifetime_opt(argl)
         if len(argl) > 0:
             node = argl[0]
             if not xmlutil.is_our_node(node):
                 context.fatal_error("Not our node: " + node)
+
+        if context.get_command_name() == 'move':
+            if not node and not force:
+                context.fatal_error("No target node: Move requires either a 
target node or 'force'")
+
         opts = ''
         if node:
             opts = "--node='%s'" % node
@@ -364,7 +378,13 @@
             opts = "%s --lifetime='%s'" % (opts, lifetime)
         if force or config.core.force:
             opts = "%s --force" % opts
-        return utils.ext_cmd(self.rsc_migrate % (rsc, opts)) == 0
+        rc = utils.ext_cmd(self.rsc_migrate % (rsc, opts))
+        if rc == 0:
+            if node:
+                common_info("Move constraint created for %s to %s" % (rsc, 
node))
+            else:
+                common_info("Move constraint created for %s" % (rsc))
+        return rc == 0
 
     @command.skill_level('administrator')
     @command.wait
@@ -375,7 +395,7 @@
             return False
         node = None
         argl = list(args)
-        force = "force" in utils.fetch_opts(argl, ["force"])
+        force = "force" in utils.fetch_opts(argl, ["force"]) or 
config.core.force
         lifetime = utils.fetch_lifetime_opt(argl)
         if len(argl) > 0:
             node = argl[0]
@@ -386,28 +406,40 @@
             opts = "--node='%s'" % node
         if lifetime:
             opts = "%s --lifetime='%s'" % (opts, lifetime)
-        if force or config.core.force:
+        if force:
             opts = "%s --force" % opts
-        return utils.ext_cmd(self.rsc_ban % (rsc, opts)) == 0
+        rc = utils.ext_cmd(self.rsc_ban % (rsc, opts))
+        if rc == 0:
+            if node:
+                common_info("Ban constraint created for %s on %s" % (rsc, 
node))
+            else:
+                common_info("Ban constraint created for %s" % (rsc))
+        return rc == 0
 
-    @command.alias('unmove', 'unban')
+    @command.alias('unmove', 'unban', 'unmigrate')
     @command.skill_level('administrator')
     @command.wait
     @command.completers(compl.resources)
-    def do_unmigrate(self, context, rsc):
-        "usage: unmigrate <rsc>"
+    def do_clear(self, context, rsc):
+        "usage: clear <rsc>"
         if not utils.is_name_sane(rsc):
             return False
-        return utils.ext_cmd(self.rsc_unmigrate % rsc) == 0
+        rc = utils.ext_cmd(self.rsc_unmigrate % rsc)
+        if rc == 0:
+            common_info("Removed migration constraints for %s" % (rsc))
+        return rc == 0
 
     @command.skill_level('administrator')
     @command.wait
     @command.completers(compl.resources, compl.nodes)
-    def do_cleanup(self, context, resource, node=''):
-        "usage: cleanup <rsc> [<node>]"
+    def do_cleanup(self, context, resource, *args):
+        "usage: cleanup <rsc> [<node>] [force]"
         # Cleanup a resource on a node. Omit node to cleanup on
         # all live nodes.
-        return cleanup_resource(resource, node)
+        argl = list(args)
+        force = "force" in utils.fetch_opts(argl, ["force"]) or 
config.core.force
+        node = argl[0] if len(argl) > 0 else ''
+        return cleanup_resource(resource, node, force=force)
 
     @command.wait
     @command.completers(compl.resources, compl.nodes)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/utils.py 
new/crmsh-2.2.0+git.1462967444.169c554/crmsh/utils.py
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/utils.py       2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/crmsh/utils.py       2016-05-12 
10:40:53.000000000 +0200
@@ -619,13 +619,17 @@
         if 0 < delaymsec:
             common_info("The crmd-transition-delay is configured. Waiting %d 
msec before check DC status." % delaymsec)
             time.sleep(delaymsec / 1000)
-    cmd = "crmadmin -S %s" % dc
     cnt = 0
     output_started = 0
     init_sleep = 0.25
     max_sleep = 1.00
     sleep_time = init_sleep
     while True:
+        dc = get_dc()
+        if not dc:
+            common_warn("DC lost during wait")
+            return False
+        cmd = "crmadmin -S %s" % dc
         rc, s = get_stdout(add_sudo(cmd))
         if not s.startswith("Status"):
             common_warn("%s unexpected output: %s (exit code: %d)" %
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/xmlutil.py 
new/crmsh-2.2.0+git.1462967444.169c554/crmsh/xmlutil.py
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/crmsh/xmlutil.py     2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/crmsh/xmlutil.py     2016-05-12 
10:40:53.000000000 +0200
@@ -687,7 +687,9 @@
                           "op": ("name", "interval"),
                           "rule": ("score", "score-attribute", "role"),
                           "expression": ("attribute", "operation", "value"),
-                          "fencing-level": ("target", "devices")})
+                          "fencing-level": ("target", "devices"),
+                          "alert": ("path",),
+                          "recipient": ("value",)})
 
 
 def add_comment(e, s):
@@ -833,7 +835,8 @@
                                 ['rsc_location', 'rsc_colocation', 
'rsc_order'],
                                 ['rsc_ticket', 'fencing-topology'],
                                 'cluster_property_set', 'rsc_defaults', 
'op_defaults',
-                                'acl_role', ['acl_target', 'acl_group', 
'acl_user'])
+                                'acl_role', ['acl_target', 'acl_group', 
'acl_user'],
+                                'alert')
 
 _sort_cli_order = make_sort_map('node',
                                 'rsc_template', 'primitive', 'group',
@@ -842,7 +845,8 @@
                                 ['location', 'colocation', 'collocation', 
'order'],
                                 ['rsc_ticket', 'fencing_topology'],
                                 'property', 'rsc_defaults', 'op_defaults',
-                                'role', ['acl_target', 'acl_group', 'user'])
+                                'role', ['acl_target', 'acl_group', 'user'],
+                                'alert')
 
 _SORT_LAST = 1000
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-2.2.0+git.1462285059.d79cd0d/doc/crm.8.adoc 
new/crmsh-2.2.0+git.1462967444.169c554/doc/crm.8.adoc
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/doc/crm.8.adoc       2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/doc/crm.8.adoc       2016-05-12 
10:40:53.000000000 +0200
@@ -942,6 +942,43 @@
 add <node>
 ...............
 
+[[cmdhelp_cluster_copy,Copy file to other cluster nodes]]
+==== `copy`
+
+Copy file to other cluster nodes.
+
+Copies the given file to all other nodes unless given a
+list of nodes to copy to as argument.
+
+Usage:
+...............
+copy <filename> [nodes ...]
+...............
+
+Example:
+...............
+copy /etc/motd
+...............
+
+[[cmdhelp_cluster_diff,Diff file across cluster]]
+==== `diff`
+
+Displays the difference, if any, between a given file
+on different nodes. If the second argument is `--checksum`,
+a checksum of the file will be calculated and displayed for
+each node.
+
+Usage:
+...............
+diff <file> [--checksum] [nodes...]
+...............
+
+Example:
+...............
+diff /etc/crm/crm.conf node2
+diff /etc/resolv.conf --checksum
+...............
+
 [[cmdhelp_cluster_health,Cluster health check]]
 ==== `health`
 
@@ -991,24 +1028,6 @@
 run "cat /proc/uptime"
 ...............
 
-[[cmdhelp_cluster_copy,Copy file to other cluster nodes]]
-==== `copy`
-
-Copy file to other cluster nodes.
-
-Copies the given file to all other nodes unless given a
-list of nodes to copy to as argument.
-
-Usage:
-...............
-copy <filename> [nodes ...]
-...............
-
-Example:
-...............
-copy /etc/motd
-...............
-
 [[cmdhelp_cluster_start,Start cluster services]]
 ==== `start`
 
@@ -1054,25 +1073,6 @@
 wait_for_startup
 ........
 
-[[cmdhelp_cluster_diff,Diff file across cluster]]
-==== `diff`
-
-Displays the difference, if any, between a given file
-on different nodes. If the second argument is `--checksum`,
-a checksum of the file will be calculated and displayed for
-each node.
-
-Usage:
-...............
-diff <file> [--checksum] [nodes...]
-...............
-
-Example:
-...............
-diff /etc/crm/crm.conf node2
-diff /etc/resolv.conf --checksum
-...............
-
 [[cmdhelp_script,Cluster script management]]
 === `script` - Cluster script management
 
@@ -1093,6 +1093,45 @@
 function through the usual SSH channels used for system maintenance,
 requiring no additional software to be installed or maintained.
 
+[[cmdhelp_script_json,JSON API for cluster scripts]]
+==== `json`
+
+This command provides a JSON API for the cluster scripts, intended for
+use in user interface tools that want to interact with the cluster via
+scripts.
+
+The command takes a single argument, which should be a JSON array with
+the first member identifying the command to perform.
+
+The output is line-based: Commands that return multiple results will
+return them line-by-line, ending with a terminator value: "end".
+
+When providing parameter values to this command, they should be
+provided as nested objects, so +virtual-ip:ip=192.168.0.5+ on the
+command line becomes the JSON object
++{"virtual-ip":{"ip":"192.168.0.5"}}+.
+
+API:
+........
+["list"]
+=> [{name, shortdesc, category}]
+
+["show", <name>]
+=> [{name, shortdesc, longdesc, category, <<steps>>}]
+
+<<steps>> := [{name, shortdesc], longdesc, required, parameters, steps}]
+
+<<params>> := [{name, shortdesc, longdesc, required, unique, advanced,
+                type, value, example}]
+
+["verify", <name>, <<values>>]
+=> [{shortdesc, longdesc, text, nodes}]
+
+["run", <name>, <<values>>]
+=> [{shortdesc, rc, output|error}]
+........
+
+
 [[cmdhelp_script_list,List available scripts]]
 ==== `list`
 
@@ -1115,6 +1154,32 @@
 list all names
 ............
 
+[[cmdhelp_script_run,Run the script]]
+==== `run`
+
+Given a list of parameter values, this command will execute the
+actions specified by the cluster script. The format for the parameter
+values is the same as for the `verify` command.
+
+Can optionally take at least two parameters:
+* `nodes=<nodes>`: List of nodes that the script runs over
+* `dry_run=yes|no`: If set, the script will not perform any modifications.
+
+Additional parameters may be available depending on the script.
+
+Use the `show` command to see what parameters are available.
+
+Usage:
+.............
+run <script> [args...]
+.............
+
+Example:
+.............
+run apache install=true
+run sbd id=sbd-1 node=node1 sbd_device=/dev/disk/by-uuid/F00D-CAFE
+.............
+
 [[cmdhelp_script_show,Describe the script]]
 ==== `show`
 
@@ -1151,71 +1216,6 @@
 verify sbd id=sbd-1 node=node1 sbd_device=/dev/disk/by-uuid/F00D-CAFE
 ............
 
-[[cmdhelp_script_run,Run the script]]
-==== `run`
-
-Given a list of parameter values, this command will execute the
-actions specified by the cluster script. The format for the parameter
-values is the same as for the `verify` command.
-
-Can optionally take at least two parameters:
-* `nodes=<nodes>`: List of nodes that the script runs over
-* `dry_run=yes|no`: If set, the script will not perform any modifications.
-
-Additional parameters may be available depending on the script.
-
-Use the `show` command to see what parameters are available.
-
-Usage:
-.............
-run <script> [args...]
-.............
-
-Example:
-.............
-run apache install=true
-run sbd id=sbd-1 node=node1 sbd_device=/dev/disk/by-uuid/F00D-CAFE
-.............
-
-[[cmdhelp_script_json,JSON API for cluster scripts]]
-==== `json`
-
-This command provides a JSON API for the cluster scripts, intended for
-use in user interface tools that want to interact with the cluster via
-scripts.
-
-The command takes a single argument, which should be a JSON array with
-the first member identifying the command to perform.
-
-The output is line-based: Commands that return multiple results will
-return them line-by-line, ending with a terminator value: "end".
-
-When providing parameter values to this command, they should be
-provided as nested objects, so +virtual-ip:ip=192.168.0.5+ on the
-command line becomes the JSON object
-+{"virtual-ip":{"ip":"192.168.0.5"}}+.
-
-API:
-........
-["list"]
-=> [{name, shortdesc, category}]
-
-["show", <name>]
-=> [{name, shortdesc, longdesc, category, <<steps>>}]
-
-<<steps>> := [{name, shortdesc], longdesc, required, parameters, steps}]
-
-<<params>> := [{name, shortdesc, longdesc, required, unique, advanced,
-                type, value, example}]
-
-["verify", <name>, <<values>>]
-=> [{shortdesc, longdesc, text, nodes}]
-
-["run", <name>, <<values>>]
-=> [{shortdesc, rc, output|error}]
-........
-
-
 [[cmdhelp_corosync,Corosync management]]
 === `corosync` - Corosync management
 
@@ -1609,6 +1609,19 @@
 All (or almost all) commands are implemented with the CRM tools
 such as `crm_resource(8)`.
 
+[[cmdhelp_resource_ban,ban a resource from a node]]
+==== `ban`
+
+Ban a resource from running on a certain node. If no node is given
+as argument, the resource is banned from the current location.
+
+See `move` for details on other arguments.
+
+Usage:
+...............
+ban <rsc> [<node>] [<lifetime>] [force]
+...............
+
 [[cmdhelp_resource_cleanup,cleanup resource status]]
 ==== `cleanup`
 
@@ -1616,11 +1629,39 @@
 temporarily failed. If a node is omitted, cleanup on all nodes.
 If there are many nodes, the command may take a while.
 
++(Pacemaker 1.1.14)+ Pass force to cleanup the resource itself,
+otherwise the cleanup command will apply to the parent resource (if
+any).
+
+Usage:
+...............
+cleanup <rsc> [<node>] [force]
+...............
+
+[[cmdhelp_resource_clear,Clear any relocation constraint]]
+==== `clear` (`unmove`, `unmigrate`, `unban`)
+
+Remove any relocation constraint created by
+the `move`, `migrate` or `ban` command.
+
 Usage:
 ...............
-cleanup <rsc> [<node>]
+clear <rsc>
+unmigrate <rsc>
+unban <rsc>
 ...............
 
+[[cmdhelp_resource_constraints,Show constraints affecting a resource]]
+==== `constraints`
+
+Display the location and colocation constraints affecting the
+resource.
+
+Usage:
+................
+constraints <rsc>
+................
+
 [[cmdhelp_resource_demote,demote a master-slave resource]]
 ==== `demote`
 
@@ -1648,6 +1689,16 @@
 failcount fs_0 delete node2
 ...............
 
+[[cmdhelp_resource_locate,show the location of resources]]
+==== `locate`
+
+Show the current location of one or more resources.
+
+Usage:
+...............
+locate [<rsc> ...]
+...............
+
 [[cmdhelp_resource_maintenance,Enable/disable per-resource maintenance mode]]
 ==== `maintenance`
 
@@ -1698,33 +1749,33 @@
 meta ip_0 set target-role stopped
 ...............
 
-[[cmdhelp_resource_migrate,migrate a resource to another node]]
-==== `migrate` (`move`)
+[[cmdhelp_resource_move,Move a resource to another node]]
+==== `move` (`migrate`)
+
+Move a resource away from its current location.
 
-Migrate a resource to a different node. If node is left out, the
-resource is migrated by creating a constraint which prevents it from
-running on the current node. Additionally, you may specify a
-lifetime for the constraint---once it expires, the location
-constraint will no longer be active.
+If the destination node is left out, the resource is migrated by
+creating a constraint which prevents it from running on the current
+node. For this type of constraint to be created, the +force+ argument
+is required.
+
+A lifetime may be given for the constraint. Once it expires, the
+location constraint will no longer be active.
 
 Usage:
 ...............
-migrate <rsc> [<node>] [<lifetime>] [force]
+move <rsc> [<node>] [<lifetime>] [force]
 ...............
 
-[[cmdhelp_resource_ban,ban a resource from a node]]
-==== `ban`
-
-Ban a resource from running on a certain node. If no node is given
-as argument, the resource is banned from the current location.
+[[cmdhelp_resource_operations,Show active resource operations]]
+==== `operations`
 
-See `migrate` for details on other arguments.
+Show active operations, optionally filtered by resource and node.
 
 Usage:
-...............
-ban <rsc> [<node>] [<lifetime>] [force]
-...............
-
+................
+operations [<rsc>] [<node>]
+................
 
 [[cmdhelp_resource_param,manage a parameter of a resource]]
 ==== `param`
@@ -1811,27 +1862,6 @@
 #
 ...............
 
-[[cmdhelp_resource_constraints,Show constraints affecting a resource]]
-==== `constraints`
-
-Display the location and colocation constraints affecting the
-resource.
-
-Usage:
-................
-constraints <rsc>
-................
-
-[[cmdhelp_resource_operations,Show active resource operations]]
-==== `operations`
-
-Show active operations, optionally filtered by resource and node.
-
-Usage:
-................
-operations [<rsc>] [<node>]
-................
-
 [[cmdhelp_resource_scores,Display resource scores]]
 ==== `scores`
 
@@ -1957,16 +1987,6 @@
 unmanage <rsc>
 ...............
 
-[[cmdhelp_resource_unmigrate,unmigrate a resource to another node]]
-==== `unmigrate` (`unmove`)
-
-Remove the constraint generated by the previous migrate command.
-
-Usage:
-...............
-unmigrate <rsc>
-...............
-
 [[cmdhelp_resource_untrace,stop RA tracing]]
 ==== `untrace`
 
@@ -2619,6 +2639,59 @@
 acl_target joe resource_admin constraint_editor
 ................
 
+[[cmdhelp_configure_alert,Event-driven alerts]]
+==== `alert`
+
+.Version note
+****************************
+This feature is only available
+in Pacemaker 1.1.15+.
+****************************
+
+Event-driven alerts enables calling scripts whenever interesting
+events occur in the cluster (nodes joining or leaving, resources
+starting or stopping, etc.).
+
+The +path+ is an arbitrary file path to an alert script.  Existing
+external scripts used with ClusterMon resources can be used as alert
+scripts, since the interface is compatible.
+
+Each alert may have a number of receipients configured.  These will be
+passed to the script as arguments. The first recipient will also be
+passed as the +CRM_alert_recipient+ environment variable, for
+compatibility with existing scripts that only support one recipient.
+
+The available meta attributes are +timeout+ (default 30s) and
++timestamp-format+ (default `"%H:%M:%S.%06N"`).
+
+Some configurations may require each recipient to be delimited by
+brackets, to avoid ambiguity. In the example +alert-2+ below, the meta
+attribute for `timeout` is defined after the recipient, so the
+brackets are used to ensure that the meta attribute is set for the
+alert and not just the recipient. This can be avoided by setting any
+alert attributes before defining the recipients.
+
+Usage:
+...............
+alert <id> <path> \
+  [attributes <nvpair> ...] \
+  [meta <nvpair> ...] \
+  [to [{] <recipient>
+    [attributes <nvpair> ...] \
+    [meta <nvpair> ...] [}] \
+    ...]
+...............
+
+Example:
+...............
+alert alert-1 /srv/pacemaker/pcmk_alert_sample.sh \
+    to /var/log/cluster-alerts.log
+
+alert alert-2 /srv/pacemaker/example_alert.sh \
+    to { /var/log/cluster-alerts.log } \
+    meta timeout=60s
+...............
+
 [[cmdhelp_configure_cib,CIB shadow management]]
 ==== `cib`
 
@@ -2902,6 +2975,34 @@
 above.
 **************************
 
+[[cmdhelp_configure_get_property,Get property value]]
+==== `get-property`
+
+Show the value of the given property. If the value is not set, the
+command will print the default value for the property, if known.
+
+If no property name is passed to the command, the list of known
+cluster properties is printed.
+
+If the property is set multiple times, for example using multiple
+property sets with different rule expressions, the output of this
+command is undefined.
+
+Pass the argument +-t+ or +--true+ to `get-property` to translate
+the argument value into +true+ or +false+. If the value is not
+set, the command will print +false+.
+
+Usage:
+...............
+get-property [-t|--true] [<name>]
+...............
+
+Example:
+...............
+get-property stonith-enabled
+get-property -t maintenance-mode
+...............
+
 [[cmdhelp_configure_graph,generate a directed graph]]
 ==== `graph`
 
@@ -3728,34 +3829,6 @@
 show related:webapp
 ...............
 
-[[cmdhelp_configure_get_property,Get property value]]
-==== `get-property`
-
-Show the value of the given property. If the value is not set, the
-command will print the default value for the property, if known.
-
-If no property name is passed to the command, the list of known
-cluster properties is printed.
-
-If the property is set multiple times, for example using multiple
-property sets with different rule expressions, the output of this
-command is undefined.
-
-Pass the argument +-t+ or +--true+ to `get-property` to translate
-the argument value into +true+ or +false+. If the value is not
-set, the command will print +false+.
-
-Usage:
-...............
-get-property [-t|--true] [<name>]
-...............
-
-Example:
-...............
-get-property stonith-enabled
-get-property -t maintenance-mode
-...............
-
 [[cmdhelp_configure_tag,Define resource tags]]
 ==== `tag`
 
@@ -3775,7 +3848,6 @@
 tag ips server-vip admin-vip
 ...............
 
-
 [[cmdhelp_configure_template,edit and import a configuration from a template]]
 ==== `template`
 
@@ -4283,20 +4355,31 @@
 To ensure this, these commands require that maintenance mode is set
 either for the particular resource, or for the whole cluster.
 
-[[cmdhelp_maintenance_on,Enable maintenance mode]]
-==== `on`
+[[cmdhelp_maintenance_action,Invoke a resource action]]
+==== `action`
 
-Enables maintenances mode, either for the whole cluster
-or for the given resource.
+Invokes the given action for the resource. This is
+done directly via the resource agent, so the command must
+be issued while the cluster or the resource is in 
+maintenance mode.
+
+Unless the action is `start` or `monitor`, the action must be invoked
+on the same node as where the resource is running. If the resource is
+running on multiple nodes, the command will fail.
+
+To use SSH for executing resource actions on multiple nodes, append
+`ssh` after the action name. This requires SSH access to be configured
+between the nodes and the parallax python package to be installed.
 
 Usage:
 ...............
-on
-on <rsc>
+action <rsc> <action>
+action <rsc> <action> ssh
 ...............
 Example:
 ...............
-on rsc1
+action webserver reload
+action webserver monitor ssh
 ...............
 
 [[cmdhelp_maintenance_off,Disable maintenance mode]]
@@ -4315,31 +4398,20 @@
 off rsc1
 ...............
 
-[[cmdhelp_maintenance_action,Invoke a resource action]]
-==== `action`
-
-Invokes the given action for the resource. This is
-done directly via the resource agent, so the command must
-be issued while the cluster or the resource is in 
-maintenance mode.
-
-Unless the action is `start` or `monitor`, the action must be invoked
-on the same node as where the resource is running. If the resource is
-running on multiple nodes, the command will fail.
+[[cmdhelp_maintenance_on,Enable maintenance mode]]
+==== `on`
 
-To use SSH for executing resource actions on multiple nodes, append
-`ssh` after the action name. This requires SSH access to be configured
-between the nodes and the parallax python package to be installed.
+Enables maintenances mode, either for the whole cluster
+or for the given resource.
 
 Usage:
 ...............
-action <rsc> <action>
-action <rsc> <action> ssh
+on
+on <rsc>
 ...............
 Example:
 ...............
-action webserver reload
-action webserver monitor ssh
+on rsc1
 ...............
 
 [[cmdhelp_history,Cluster history]]
@@ -4437,6 +4509,27 @@
 diff pe-input-2080.bz2 live status
 ...............
 
+[[cmdhelp_history_events,Show events in log]]
+==== `events`
+
+By analysing the log output and looking for particular
+patterns, the `events` command helps sifting through
+the logs to find when particular events like resources
+changing state or node failure may have occurred.
+
+This can be used to generate a combined list of events
+from all nodes.
+
+Usage:
+...............
+events
+...............
+
+Example:
+...............
+events
+...............
+
 [[cmdhelp_history_exclude,exclude log messages]]
 ==== `exclude`
 
@@ -4573,27 +4666,6 @@
 log node-a
 ...............
 
-[[cmdhelp_history_events,Show events in log]]
-==== `events`
-
-By analysing the log output and looking for particular
-patterns, the `events` command helps sifting through
-the logs to find when particular events like resources
-changing state or node failure may have occurred.
-
-This can be used to generate a combined list of events
-from all nodes.
-
-Usage:
-...............
-events
-...............
-
-Example:
-...............
-events
-...............
-
 [[cmdhelp_history_node,node events]]
 ==== `node`
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/test/testcases/bugs 
new/crmsh-2.2.0+git.1462967444.169c554/test/testcases/bugs
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/test/testcases/bugs  2016-05-03 
16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/test/testcases/bugs  2016-05-12 
10:40:53.000000000 +0200
@@ -57,7 +57,7 @@
 property SAPHanaSR_2: \
     hana_ha1_site_iss_WDF1=cde \
     hana_ha1_site_bss_WDF1=abc
-show xml
+show
 commit
 _test
 verify
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/test/testcases/bugs.exp 
new/crmsh-2.2.0+git.1462967444.169c554/test/testcases/bugs.exp
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/test/testcases/bugs.exp      
2016-05-03 16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/test/testcases/bugs.exp      
2016-05-12 10:40:53.000000000 +0200
@@ -120,40 +120,18 @@
 .INP: _test
 .INP: verify
 .INP: property SAPHanaSR_2:     hana_ha1_site_iss_WDF1=cde     
hana_ha1_site_bss_WDF1=abc
-.INP: show xml
-<?xml version="1.0" ?>
-<cib>
-  <configuration>
-    <crm_config>
-      <cluster_property_set id="SAPHanaSR_2">
-        <nvpair name="hana_ha1_site_iss_WDF1" value="cde" 
id="SAPHanaSR_2-hana_ha1_site_iss_WDF1"/>
-        <nvpair name="hana_ha1_site_bss_WDF1" value="abc" 
id="SAPHanaSR_2-hana_ha1_site_bss_WDF1"/>
-      </cluster_property_set>
-      <cluster_property_set id="SAPHanaSR">
-        <nvpair name="hana_ha1_site_lss_WDF1" value="4" 
id="SAPHanaSR-hana_ha1_site_lss_WDF1"/>
-      </cluster_property_set>
-    </crm_config>
-    <nodes>
-      <node uname="node1" id="node1"/>
-    </nodes>
-    <resources>
-      <primitive id="st" class="stonith" type="null">
-        <instance_attributes id="st-instance_attributes">
-          <nvpair name="hostlist" value="node1" 
id="st-instance_attributes-hostlist"/>
-        </instance_attributes>
-        <meta_attributes id="st-meta_attributes">
-          <nvpair name="description" value="some description here" 
id="st-meta_attributes-description"/>
-        </meta_attributes>
-        <operations>
-          <op name="start" requires="nothing" interval="0" id="st-start-0"/>
-          <op name="monitor" interval="60m" id="st-monitor-60m"/>
-        </operations>
-      </primitive>
-    </resources>
-    <constraints/>
-  </configuration>
-</cib>
-
+.INP: show
+node node1
+primitive st stonith:null \
+       params hostlist=node1 \
+       meta description="some description here" \
+       op start requires=nothing interval=0 \
+       op monitor interval=60m
+property SAPHanaSR: \
+       hana_ha1_site_lss_WDF1=4
+property SAPHanaSR_2: \
+       hana_ha1_site_iss_WDF1=cde \
+       hana_ha1_site_bss_WDF1=abc
 .INP: commit
 .INP: _test
 .INP: verify
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/test/testcases/resource 
new/crmsh-2.2.0+git.1462967444.169c554/test/testcases/resource
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/test/testcases/resource      
2016-05-03 16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/test/testcases/resource      
2016-05-12 10:40:53.000000000 +0200
@@ -43,3 +43,7 @@
 configure rename p3 p4
 configure primitive p3 Dummy
 resource stop p3
+%setenv showobj=
+configure rm cg
+configure ms msg g
+resource scores
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/test/testcases/resource.exp 
new/crmsh-2.2.0+git.1462967444.169c554/test/testcases/resource.exp
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/test/testcases/resource.exp  
2016-05-03 16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/test/testcases/resource.exp  
2016-05-12 10:40:53.000000000 +0200
@@ -88,6 +88,7 @@
 .SETENV showobj=cli-prefer-p3
 .TRY resource migrate p3 node1
 .EXT crm_resource --quiet --move -r 'p3' --node='node1'
+INFO: Move constraint created for p3 to node1
 .INP: configure
 .INP: _regtest on
 .INP: show xml cli-prefer-p3
@@ -106,9 +107,11 @@
 .SETENV showobj=
 .TRY resource unmigrate p3
 .EXT crm_resource --quiet --clear -r 'p3'
+INFO: Removed migration constraints for p3
 .SETENV showobj=cli-prefer-p3
 .TRY resource migrate p3 node1 force
 .EXT crm_resource --quiet --move -r 'p3' --node='node1' --force
+INFO: Move constraint created for p3 to node1
 .INP: configure
 .INP: _regtest on
 .INP: show xml cli-prefer-p3
@@ -127,6 +130,7 @@
 .SETENV showobj=
 .TRY resource unmigrate p3
 .EXT crm_resource --quiet --clear -r 'p3'
+INFO: Removed migration constraints for p3
 .SETENV showobj=p0
 .TRY resource param p0 set a0 "1 2 3"
 .EXT crm_resource -r 'p0' -p 'a0' -v '1 2 3'
@@ -911,3 +915,46 @@
   </configuration>
 </cib>
 
+.SETENV showobj=
+.TRY configure rm cg
+.TRY configure ms msg g
+.TRY resource scores
+.EXT crm_simulate -sUL
+3 of 6 resources DISABLED and 0 BLOCKED from being started due to failures
+
+Current cluster status:
+Node node1: UNCLEAN (offline)
+
+ st    (stonith:null): Stopped 
+ Clone Set: c1 [p1] (unmanaged)
+     Stopped: [ node1 ]
+ Master/Slave Set: m1 [p2]
+     Stopped: [ node1 ]
+ p3    (ocf::heartbeat:Dummy): Stopped ( disabled ) 
+ Master/Slave Set: msg [g]
+     Stopped: [ node1 ]
+
+Allocation scores and utilization information:
+Original: node1 capacity:
+native_color: st allocation score on node1: 0
+clone_color: c1 allocation score on node1: 0
+clone_color: p1:0 allocation score on node1: 0
+native_color: p1:0 allocation score on node1: -INFINITY
+clone_color: m1 allocation score on node1: 0
+clone_color: p2:0 allocation score on node1: 0
+native_color: p2:0 allocation score on node1: -INFINITY
+p2:0 promotion score on none: 0
+native_color: p3 allocation score on node1: -INFINITY
+clone_color: msg allocation score on node1: 0
+clone_color: g:0 allocation score on node1: 0
+clone_color: p0:0 allocation score on node1: 0
+clone_color: p4:0 allocation score on node1: 0
+group_color: g:0 allocation score on node1: -INFINITY
+group_color: p0:0 allocation score on node1: -INFINITY
+group_color: p4:0 allocation score on node1: -INFINITY
+native_color: p0:0 allocation score on node1: -INFINITY
+native_color: p4:0 allocation score on node1: -INFINITY
+g:0 promotion score on none: 0
+Remaining: node1 capacity:
+
+Transition Summary:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/test/unittests/test_cliformat.py 
new/crmsh-2.2.0+git.1462967444.169c554/test/unittests/test_cliformat.py
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/test/unittests/test_cliformat.py     
2016-05-03 16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/test/unittests/test_cliformat.py     
2016-05-12 10:40:53.000000000 +0200
@@ -266,3 +266,24 @@
 @with_setup(setup_func, teardown_func)
 def test_is_value_sane_2():
     roundtrip('primitive p1 dummy params state="bo\\"o"')
+
+
+@with_setup(setup_func, teardown_func)
+def test_alerts_1():
+    roundtrip('alert alert1 "/tmp/foo.sh" to "/tmp/bar.log"')
+
+@with_setup(setup_func, teardown_func)
+def test_alerts_2():
+    roundtrip('alert alert2 "/tmp/foo.sh" attributes foo=bar to 
"/tmp/bar.log"')
+
+@with_setup(setup_func, teardown_func)
+def test_alerts_3():
+    roundtrip('alert alert3 "a path here" meta baby to "/tmp/bar.log"')
+
+@with_setup(setup_func, teardown_func)
+def test_alerts_4():
+    roundtrip('alert alert4 "/also/a/path"')
+
+@with_setup(setup_func, teardown_func)
+def test_alerts_5():
+    roundtrip('alert alert5 "/a/path" to { "/another/path" } meta timeout=30s')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-2.2.0+git.1462285059.d79cd0d/test/unittests/test_parse.py 
new/crmsh-2.2.0+git.1462967444.169c554/test/unittests/test_parse.py
--- old/crmsh-2.2.0+git.1462285059.d79cd0d/test/unittests/test_parse.py 
2016-05-03 16:17:39.000000000 +0200
+++ new/crmsh-2.2.0+git.1462967444.169c554/test/unittests/test_parse.py 
2016-05-12 10:40:53.000000000 +0200
@@ -474,6 +474,26 @@
         self.assertEqual(out.get('id'), 'tag1')
         self.assertEqual(['foo', 'bar'], out.xpath('/tag/obj_ref/@id'))
 
+    def test_alerts(self):
+        "Test alerts (1.1.15+)"
+        out = self._parse('alert alert1 /tmp/foo.sh to /tmp/bar.log')
+        self.assertEqual(out.get('id'), 'alert1')
+        self.assertEqual(['/tmp/foo.sh'],
+                         out.xpath('/alert/@path'))
+        self.assertEqual(['/tmp/bar.log'],
+                         out.xpath('/alert/recipient/@value'))
+
+    def test_alerts_brackets(self):
+        "Test alerts w/ brackets (1.1.15+)"
+        out = self._parse('alert alert2 /tmp/foo.sh to { /tmp/bar.log meta 
timeout=10s }')
+        self.assertEqual(out.get('id'), 'alert2')
+        self.assertEqual(['/tmp/foo.sh'],
+                         out.xpath('/alert/@path'))
+        self.assertEqual(['/tmp/bar.log'],
+                         out.xpath('/alert/recipient/@value'))
+        self.assertEqual(['10s'],
+                         
out.xpath('/alert/recipient/meta_attributes/nvpair[@name="timeout"]/@value'))
+
     def _parse_lines(self, lines):
         out = []
         for line in lines2cli(lines):


Reply via email to