Hello community,

here is the log from the commit of package crmsh for openSUSE:Factory checked 
in at 2018-01-10 23:36:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/crmsh (Old)
 and      /work/SRC/openSUSE:Factory/.crmsh.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "crmsh"

Wed Jan 10 23:36:04 2018 rev:136 rq:563058 version:4.0.0+git.1515511613.5ee0eb23

Changes:
--------
--- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes      2017-12-14 
11:03:29.958189541 +0100
+++ /work/SRC/openSUSE:Factory/.crmsh.new/crmsh.changes 2018-01-10 
23:36:06.349383198 +0100
@@ -1,0 +2,10 @@
+Tue Jan 09 15:31:11 UTC 2018 - kgronl...@suse.com
+
+- Update to version 4.0.0+git.1515511613.5ee0eb23:
+  * high: scripts: Enable complex expressions in when: (bsc#1074835)
+  * medium: hb_report: Support new pacemaker.log location (fate#324508)
+  * low: ui_configure: Complete rsc template correctly
+  * fix: ra: Convert bytes to str
+  * fix: ui_resource: Using crm_failcount instead of crm_attribute(bsc#1074127)
+
+-------------------------------------------------------------------

Old:
----
  crmsh-4.0.0+git.1513179435.e1d17d7b.tar.bz2

New:
----
  crmsh-4.0.0+git.1515511613.5ee0eb23.tar.bz2

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

Other differences:
------------------
++++++ crmsh.spec ++++++
--- /var/tmp/diff_new_pack.hIQEt8/_old  2018-01-10 23:36:06.909356924 +0100
+++ /var/tmp/diff_new_pack.hIQEt8/_new  2018-01-10 23:36:06.913356736 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package crmsh
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -36,7 +36,7 @@
 Summary:        High Availability cluster command-line interface
 License:        GPL-2.0+
 Group:          %{pkg_group}
-Version:        4.0.0+git.1513179435.e1d17d7b
+Version:        4.0.0+git.1515511613.5ee0eb23
 Release:        0
 Url:            http://crmsh.github.io
 Source0:        %{name}-%{version}.tar.bz2

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.hIQEt8/_old  2018-01-10 23:36:06.949355047 +0100
+++ /var/tmp/diff_new_pack.hIQEt8/_new  2018-01-10 23:36:06.953354859 +0100
@@ -1,4 +1,4 @@
 <servicedata>
 <service name="tar_scm">
             <param name="url">git://github.com/ClusterLabs/crmsh.git</param>
-          <param 
name="changesrevision">e1d17d7b1a3b6b4a3ca0211d72d8102b150c0c65</param></service></servicedata>
\ No newline at end of file
+          <param 
name="changesrevision">5ee0eb231d19e543bcba9a5dd9f43327096ff1b3</param></service></servicedata>
\ No newline at end of file

++++++ crmsh-4.0.0+git.1513179435.e1d17d7b.tar.bz2 -> 
crmsh-4.0.0+git.1515511613.5ee0eb23.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/config.py 
new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/config.py
--- old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/config.py     2017-12-13 
16:37:15.000000000 +0100
+++ new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/config.py     2018-01-09 
16:26:53.000000000 +0100
@@ -260,7 +260,7 @@
         'from_time': opt_string('-12H'),
         'compress': opt_boolean('yes'),
         'speed_up': opt_boolean('no'),
-        'collect_extra_logs': opt_string('/var/log/messages 
/var/log/pacemaker.log /var/log/ha-cluster-bootstrap.log'),
+        'collect_extra_logs': opt_string('/var/log/messages 
/var/log/pacemaker/pacemaker.log /var/log/pacemaker.log 
/var/log/ha-cluster-bootstrap.log'),
         'remove_exist_dest': opt_boolean('no'),
         'single_node': opt_boolean('no')
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/minieval.py 
new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/minieval.py
--- old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/minieval.py   1970-01-01 
01:00:00.000000000 +0100
+++ new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/minieval.py   2018-01-09 
16:26:53.000000000 +0100
@@ -0,0 +1,360 @@
+# Copyright (C) 2013-2017 Daniel Fairhead
+# Copyright (C) 2017 Kristoffer Gronlund <kgronl...@suse.com>
+# See COPYING for license information.
+
+"""
+Based on simpleeval:
+
+SimpleEval - (C) 2013-2017 Daniel Fairhead
+-------------------------------------
+
+An short, easy to use, safe and reasonably extensible expression evaluator.
+Designed for things like in a website where you want to allow the user to
+generate a string, or a number from some other input, without allowing full
+eval() or other unsafe or needlessly complex linguistics.
+
+-------------------------------------
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+-------------------------------------
+
+Initial idea copied from J.F. Sebastian on Stack Overflow
+( http://stackoverflow.com/a/9558001/1973500 ) with
+modifications and many improvments.
+
+-------------------------------------
+Contributors:
+- corro (Robin Baumgartner) (py3k)
+- dratchkov (David R) (nested dicts)
+- marky1991 (Mark Young) (slicing)
+- T045T (Nils Berg) (!=, py3kstr, obj.
+- perkinslr (Logan Perkins) (.__globals__ or .func_ breakouts)
+- impala2 (Kirill Stepanov) (massive _eval refactor)
+- gk (ugik) (Other iterables than str can DOS too, and can be made)
+- daveisfera (Dave Johansen) 'not' Boolean op, Pycharm and pep8 fixes.
+
+-------------------------------------
+Usage:
+
+>>> s = SimpleEval()
+>>> s.eval("20 + 30")
+50
+
+You can add your own functions easily too:
+
+if file.txt contents is "11"
+
+>>> def get_file():
+        with open("file.txt",'r') as f:
+            return f.read()
+
+    s.functions["get_file"] = get_file
+    s.eval("int(get_file()) + 31")
+42
+
+For more information, see the full package documentation on pypi, or the github
+repo.
+
+-----------
+
+If you don't need to re-use the evaluator (with it's names, functions, etc),
+then you can use the simple_eval() function:
+
+>>> simple_eval("21 + 19")
+40
+
+You can pass names, operators and functions to the simple_eval function as
+well:
+
+>>> simple_eval("40 + two", names={"two": 2})
+42
+
+"""
+
+import ast
+import sys
+import operator as op
+
+########################################
+# Module wide 'globals'
+
+MAX_STRING_LENGTH = 100000
+DISALLOW_PREFIXES = ['_', 'func_']
+DISALLOW_METHODS = ['format']
+
+PYTHON3 = sys.version_info[0] == 3
+
+########################################
+# Exceptions:
+
+
+class InvalidExpression(Exception):
+    """ Generic Exception """
+    pass
+
+
+class NameNotDefined(InvalidExpression):
+    """ a name isn't defined. """
+    def __init__(self, name, expression):
+        self.name = name
+        self.message = "'{0}' is not defined for expression '{1}'".format(
+            name, expression)
+        self.expression = expression
+
+        # pylint: disable=bad-super-call
+        super(InvalidExpression, self).__init__(self.message)
+
+
+class AttributeDoesNotExist(InvalidExpression):
+    """attribute does not exist"""
+    def __init__(self, attr, expression):
+        self.message = \
+            "Attribute '{0}' does not exist in expression '{1}'".format(
+                attr, expression)
+        self.attr = attr
+        self.expression = expression
+
+
+class FeatureNotAvailable(InvalidExpression):
+    """ What you're trying to do is not allowed. """
+    pass
+
+
+class IterableTooLong(InvalidExpression):
+    """ That iterable is **way** too long, baby. """
+    pass
+
+
+########################################
+# Defaults for the evaluator:
+
+DEFAULT_OPERATORS = {ast.Eq: op.eq, ast.NotEq: op.ne,
+                     ast.Gt: op.gt, ast.Lt: op.lt,
+                     ast.GtE: op.ge, ast.LtE: op.le,
+                     ast.Not: op.not_,
+                     ast.USub: op.neg, ast.UAdd: op.pos,
+                     ast.In: lambda x, y: op.contains(y, x),
+                     ast.NotIn: lambda x, y: not op.contains(y, x),
+                     ast.Is: lambda x, y: x is y,
+                     ast.IsNot: lambda x, y: x is not y,
+                     }
+
+DEFAULT_NAMES = {"True": True, "False": False}
+
+########################################
+# And the actual evaluator:
+
+
+class SimpleEval(object):  # pylint: disable=too-few-public-methods
+    """ A very simple expression parser.
+        >>> s = SimpleEval()
+        >>> s.eval("20 + 30 - ( 10 * 5)")
+        0
+        """
+    expr = ""
+
+    def __init__(self, names):
+        """
+            Create the evaluator instance.  Set up valid operators (+,-, etc)
+            functions (add, random, get_val, whatever) and names. """
+
+        operators = DEFAULT_OPERATORS
+        names = names.copy()
+        names.update(DEFAULT_NAMES)
+
+        self.operators = operators
+        self.names = names
+
+        self.nodes = {
+            ast.Num: self._eval_num,
+            ast.Str: self._eval_str,
+            ast.Name: self._eval_name,
+            ast.UnaryOp: self._eval_unaryop,
+            ast.BinOp: self._eval_binop,
+            ast.BoolOp: self._eval_boolop,
+            ast.Compare: self._eval_compare,
+            ast.IfExp: self._eval_ifexp,
+            ast.keyword: self._eval_keyword,
+            ast.Subscript: self._eval_subscript,
+            ast.Attribute: self._eval_attribute,
+            ast.Index: self._eval_index,
+            ast.Slice: self._eval_slice,
+        }
+
+        # py3k stuff:
+        if hasattr(ast, 'NameConstant'):
+            self.nodes[ast.NameConstant] = self._eval_nameconstant
+        elif isinstance(self.names, dict) and "None" not in self.names:
+            self.names["None"] = None
+
+    def evaluate(self, expr):
+        """ evaluate an expresssion, using the operators, functions and
+            names previously set up. """
+
+        # set a copy of the expression aside, so we can give nice errors...
+
+        self.expr = expr
+
+        # and evaluate:
+        return self._eval(ast.parse(expr.strip()).body[0].value)
+
+    def _eval(self, node):
+        """ The internal evaluator used on each node in the parsed tree. """
+
+        try:
+            handler = self.nodes[type(node)]
+        except KeyError:
+            raise FeatureNotAvailable("Sorry, {0} is not available in this "
+                                      "evaluator".format(type(node).__name__))
+
+        return handler(node)
+
+    @staticmethod
+    def _eval_num(node):
+        return node.n
+
+    @staticmethod
+    def _eval_str(node):
+        if len(node.s) > MAX_STRING_LENGTH:
+            raise IterableTooLong("String Literal in statement is too long!"
+                                  " ({0}, when {1} is max)".format(
+                                      len(node.s), MAX_STRING_LENGTH))
+        return node.s
+
+    @staticmethod
+    def _eval_nameconstant(node):
+        return node.value
+
+    def _eval_unaryop(self, node):
+        return self.operators[type(node.op)](self._eval(node.operand))
+
+    def _eval_binop(self, node):
+        return self.operators[type(node.op)](self._eval(node.left),
+                                             self._eval(node.right))
+
+    def _eval_boolop(self, node):
+        if isinstance(node.op, ast.And):
+            vout = False
+            for value in node.values:
+                vout = self._eval(value)
+                if not vout:
+                    return False
+            return vout
+        elif isinstance(node.op, ast.Or):
+            for value in node.values:
+                vout = self._eval(value)
+                if vout:
+                    return vout
+            return False
+
+    def _eval_compare(self, node):
+        left = self._eval(node.left)
+        for operation, comp in zip(node.ops, node.comparators):
+            right = self._eval(comp)
+            if self.operators[type(operation)](left, right):
+                left = right  # Hi Dr. Seuss...
+            else:
+                return False
+        return True
+
+    def _eval_ifexp(self, node):
+        return self._eval(node.body) if self._eval(node.test) \
+                                         else self._eval(node.orelse)
+
+    def _eval_keyword(self, node):
+        return node.arg, self._eval(node.value)
+
+    def _eval_name(self, node):
+        try:
+            # This happens at least for slicing
+            # This is a safe thing to do because it is impossible
+            # that there is a true exression assigning to none
+            # (the compiler rejects it, so you can't even
+            # pass that to ast.parse)
+            if isinstance(self.names, dict):
+                return self.names[node.id]
+            elif callable(self.names):
+                return self.names(node)
+            else:
+                raise InvalidExpression('Trying to use name (variable) "{0}"'
+                                        ' when no "names" defined for'
+                                        ' evaluator'.format(node.id))
+
+        except KeyError:
+            if node.id in self.functions:
+                return self.functions[node.id]
+
+            raise NameNotDefined(node.id, self.expr)
+
+    def _eval_subscript(self, node):
+
+        container = self._eval(node.value)
+        key = self._eval(node.slice)
+        try:
+            return container[key]
+        except KeyError:
+            raise
+
+    def _eval_attribute(self, node):
+        for prefix in DISALLOW_PREFIXES:
+            if node.attr.startswith(prefix):
+                raise FeatureNotAvailable(
+                    "Sorry, access to __attributes "
+                    " or func_ attributes is not available. "
+                    "({0})".format(node.attr))
+        if node.attr in DISALLOW_METHODS:
+            raise FeatureNotAvailable(
+                    "Sorry, this method is not available. "
+                    "({0})".format(node.attr))
+
+        try:
+            return self._eval(node.value)[node.attr]
+        except (KeyError, TypeError):
+            pass
+
+        # Maybe the base object is an actual object, not just a dict
+        try:
+            return getattr(self._eval(node.value), node.attr)
+        except (AttributeError, TypeError):
+            pass
+
+        # If it is neither, raise an exception
+        raise AttributeDoesNotExist(node.attr, self.expr)
+
+    def _eval_index(self, node):
+        return self._eval(node.value)
+
+    def _eval_slice(self, node):
+        lower = upper = step = None
+        if node.lower is not None:
+            lower = self._eval(node.lower)
+        if node.upper is not None:
+            upper = self._eval(node.upper)
+        if node.step is not None:
+            step = self._eval(node.step)
+        return slice(lower, upper, step)
+
+
+def minieval(expr, env):
+    """
+    Given a dict of variable -> value mapping in env,
+    parse and evaluate the expression in expr
+    """
+    return SimpleEval(env).evaluate(expr)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/ra.py 
new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/ra.py
--- old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/ra.py 2017-12-13 
16:37:15.000000000 +0100
+++ new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/ra.py 2018-01-09 
16:26:53.000000000 +0100
@@ -13,7 +13,7 @@
 from . import options
 from . import userdir
 from . import utils
-from .utils import stdout2list, is_program, is_process
+from .utils import stdout2list, is_program, is_process, to_ascii
 from .utils import os_types_list, get_stdout, find_value
 from .utils import crm_msec, crm_time_cmp
 from .msg import common_debug, common_err, common_warn, common_info
@@ -836,7 +836,8 @@
     if options.regression_tests:
         print(".EXT", " ".join(cmd))
     p = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
stderr=subprocess.STDOUT, env=my_env)
-    out, _ = p.communicate()
+    _out, _ = p.communicate()
+    out = to_ascii(_out)
     p.wait()
 
     if log is True:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/scripts.py 
new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/scripts.py
--- old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/scripts.py    2017-12-13 
16:37:15.000000000 +0100
+++ new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/scripts.py    2018-01-09 
16:26:53.000000000 +0100
@@ -118,6 +118,24 @@
         return str(self) == str(obj)
 
 
+class WhenExpr(object):
+    def __init__(self, script, prog):
+        self.script = script
+        self.prog = prog
+
+    def __repr__(self):
+        return repr(self.prog)
+
+    def __str__(self):
+        lenv = self.script.get('__values__', {})
+        inp = handles.parse(self.prog, lenv).strip()
+        try:
+            from .minieval import minieval, InvalidExpression
+            return str(minieval(inp, lenv)).lower()
+        except InvalidExpression as err:
+            raise ValueError(str(err))
+
+
 def _strip(desc):
     if desc is None:
         return None
@@ -206,13 +224,14 @@
             action['longdesc'] = Text.desc(script, action['longdesc'])
 
         hre = handles.headmatcher
+        ident_re = re.compile(r'([a-z_-][a-z0-9_-]*)$', re.IGNORECASE)
 
         if 'when' in action:
             when = action['when']
-            if hre.search(when):
-                action['when'] = Text(script, when)
-            elif when:
+            if ident_re.match(when):
                 action['when'] = Text(script, '{{%s}}' % (when))
+            elif when:
+                action['when'] = WhenExpr(script, when)
             else:
                 del action['when']
         for k, v in action.items():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/ui_configure.py 
new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/ui_configure.py
--- old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/ui_configure.py       
2017-12-13 16:37:15.000000000 +0100
+++ new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/ui_configure.py       
2018-01-09 16:26:53.000000000 +0100
@@ -109,9 +109,8 @@
 
 
 def ra_classes_or_tmpl(args):
-    if args[-1].startswith('@'):
-        return cib_factory.rsc_template_list()
-    return ui_ra.complete_class_provider_type(args)
+    return ui_ra.complete_class_provider_type(args) + \
+           ['@'+x for x in cib_factory.rsc_template_list()]
 
 
 def op_attr_list(args):
@@ -142,7 +141,8 @@
 def get_prim_token(words, n):
     for key in ("primitive", "rsc_template"):
         try:
-            return words[words.index(key) + n - 1]
+            if key in words:
+                return words[words.index(key) + n - 1]
         except IndexError:
             pass
     return ''
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/ui_resource.py 
new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/ui_resource.py
--- old/crmsh-4.0.0+git.1513179435.e1d17d7b/crmsh/ui_resource.py        
2017-12-13 16:37:15.000000000 +0100
+++ new/crmsh-4.0.0+git.1515511613.5ee0eb23/crmsh/ui_resource.py        
2018-01-09 16:26:53.000000000 +0100
@@ -195,9 +195,9 @@
     }
     rsc_failcount = {
         'set': "crm_attribute -t status -n 'fail-count-%s' -N '%s' -v '%s' -d 
0",
-        'delete': "crm_attribute -t status -n 'fail-count-%s' -N '%s' -D -d 0",
-        'show': "crm_attribute -t status -n 'fail-count-%s' -N '%s' -G -d 0",
-        'get': "crm_attribute -t status -n 'fail-count-%s' -N '%s' -G -d 0",
+        'delete': "crm_failcount -D -r %s -N %s",
+        'show': "crm_failcount -G -r %s -N %s",
+        'get': "crm_failcount -G -r %s -N %s",
     }
     rsc_utilization = {
         'set': "crm_resource -z -r '%s' -p '%s' -v '%s'",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.0.0+git.1513179435.e1d17d7b/doc/website-v1/scripts.adoc 
new/crmsh-4.0.0+git.1515511613.5ee0eb23/doc/website-v1/scripts.adoc
--- old/crmsh-4.0.0+git.1513179435.e1d17d7b/doc/website-v1/scripts.adoc 
2017-12-13 16:37:15.000000000 +0100
+++ new/crmsh-4.0.0+git.1515511613.5ee0eb23/doc/website-v1/scripts.adoc 
2018-01-09 16:26:53.000000000 +0100
@@ -301,6 +301,22 @@
     to be passed to the next action. Instead, the output is printed to
     the screen.
 
+==== When expressions ====
+
+Actions can be made conditional on the value of script parameters using
+the +when:+ expression. This expression has two basic forms.
+
+The first form is in the form of the name of a script parameter. For
+example, given a boolean script parameter named +install+, an action
+can be made conditional on that parameter being true using the syntax
++when: install+.
+
+The second form is a more complex expression. All parameters are
+interpreted as either a string value or None if no value was provided.
+These can be compared to string literals using python-style
+comparators. For example, an action can be conditional on the string
+parameter +mode+ having the value +"advanced"+ using the following
+syntax: +when: mode == "advanced"+.
 
 === Basic structure ===
 
@@ -641,3 +657,4 @@
 {{^name}} ... {{/name}} = Inserts the text between the mustasches when
                           name is falsy.
 ............
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.0.0+git.1513179435.e1d17d7b/hb_report/constants.py 
new/crmsh-4.0.0+git.1515511613.5ee0eb23/hb_report/constants.py
--- old/crmsh-4.0.0+git.1513179435.e1d17d7b/hb_report/constants.py      
2017-12-13 16:37:15.000000000 +0100
+++ new/crmsh-4.0.0+git.1515511613.5ee0eb23/hb_report/constants.py      
2018-01-09 16:26:53.000000000 +0100
@@ -36,7 +36,7 @@
 OCF_DIR = None
 PACKAGES = None
 PCMK_LIB = None
-PCMK_LOG = "/var/log/pacemaker.log"
+PCMK_LOG = "/var/log/pacemaker/pacemaker.log /var/log/pacemaker.log"
 PE_STATE_DIR = None
 PTEST = "crm_simulate"
 SANITIZE = "passw.*"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.0.0+git.1513179435.e1d17d7b/hb_report/utillib.py 
new/crmsh-4.0.0+git.1515511613.5ee0eb23/hb_report/utillib.py
--- old/crmsh-4.0.0+git.1513179435.e1d17d7b/hb_report/utillib.py        
2017-12-13 16:37:15.000000000 +0100
+++ new/crmsh-4.0.0+git.1515511613.5ee0eb23/hb_report/utillib.py        
2018-01-09 16:26:53.000000000 +0100
@@ -638,15 +638,16 @@
     """
     if constants.EXTRA_LOGS:
         for l in constants.EXTRA_LOGS.split():
-            if os.path.isfile(l) and l != constants.PCMK_LOG:
+            if os.path.isfile(l) and l not in constants.PCMK_LOG.split():
                 return l
 
         tmp_f = os.path.join(constants.WORKDIR, constants.JOURNAL_F)
         if os.path.isfile(tmp_f):
             return tmp_f
 
-        if os.path.isfile(constants.PCMK_LOG):
-            return constants.PCMK_LOG
+        for l in constants.PCMK_LOG.split():
+            if os.path.isfile(l):
+                return l
 
     if constants.HA_DEBUGFILE:
         log_debug("will try with %s" % constants.HA_DEBUGFILE)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/crmsh-4.0.0+git.1513179435.e1d17d7b/test/unittests/test_scripts.py 
new/crmsh-4.0.0+git.1515511613.5ee0eb23/test/unittests/test_scripts.py
--- old/crmsh-4.0.0+git.1513179435.e1d17d7b/test/unittests/test_scripts.py      
2017-12-13 16:37:15.000000000 +0100
+++ new/crmsh-4.0.0+git.1515511613.5ee0eb23/test/unittests/test_scripts.py      
2018-01-09 16:26:53.000000000 +0100
@@ -879,3 +879,48 @@
         print(action, args)
         if action == 'finish':
             assert args[0]['value'] == '#!/bin/sh\necho "hello world"'
+
+
+@with_setup(setup_func, teardown_func)
+def test_when_expression():
+    """
+    Test when expressions
+    """
+    def runtest(when, val):
+        the_script = '''version: 2.2
+shortdesc: Test when expressions
+longdesc: See if more complicated expressions work
+parameters:
+  - name: stringtest
+    type: string
+    shortdesc: A test string
+actions:
+  - call: "echo '{{stringtest}}'"
+    when: %s
+'''
+        scrpt = scripts.load_script_string('{}_{}'.format(when, val), 
the_script % when)
+        assert scrpt is not None
+
+        a1 = scripts.verify(scrpt,
+                            {"stringtest": val},
+                            external_check=False)
+        pprint(a1)
+        return a1
+
+    a1 = runtest('stringtest == "balloon"', "balloon")
+    assert len(a1) == 1 and a1[0]['value'] == "echo 'balloon'"
+
+    a1 = runtest('stringtest == "balloon"', "not a balloon")
+    assert len(a1) == 0
+
+    a1 = runtest('stringtest != "balloon"', "not a balloon")
+    assert len(a1) == 1
+
+    a1 = runtest('stringtest != "balloon"', "balloon")
+    assert len(a1) == 0
+
+    a1 = runtest('stringtest == "{{dry_run}}"', "no")
+    assert len(a1) == 1
+
+    a1 = runtest('stringtest == "yes" or stringtest == "no"', "yes")
+    assert len(a1) == 1


Reply via email to