From 87a7e80a2cbc4c8abcf4394242a02fcc5140e44b Mon Sep 17 00:00:00 2001 From: "Erlon R. Cruz" Date: Fri, 29 Nov 2019 16:08:43 -0300 Subject: [PATCH] Fix DriverFilter string evaluations When trying to compare two values that are non-numeric using the driver filter, the filter function will give an error. This is not desirable as it might be interesting to support comparatives with non-numeric values provided by the filter objects (volume, host, etc). For example, the following formula failed before the fix: filter_function = '(volume.project_id == "bb212f09317a4f4a8952ef3f729c2551")' Change-Id: Ifc9f2d7cf39c0e497e1ed6440d2be4cda6be12d9 --- cinder/scheduler/evaluator/evaluator.py | 20 ++++++++++---------- cinder/tests/unit/test_evaluator.py | 11 ++++++----- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/cinder/scheduler/evaluator/evaluator.py b/cinder/scheduler/evaluator/evaluator.py index 0e7974b480c..0d05bebdb5a 100644 --- a/cinder/scheduler/evaluator/evaluator.py +++ b/cinder/scheduler/evaluator/evaluator.py @@ -45,21 +45,21 @@ class EvalConstant(object): (which_dict, entry) = result.split('.') try: result = _vars[which_dict][entry] - except KeyError as e: + except KeyError: raise exception.EvaluatorParseException( - _("KeyError: %s") % e) - except TypeError as e: + _("KeyError evaluating string")) + except TypeError: raise exception.EvaluatorParseException( - _("TypeError: %s") % e) + _("TypeError evaluating string")) try: result = int(result) except ValueError: try: result = float(result) - except ValueError as e: - raise exception.EvaluatorParseException( - _("ValueError: %s") % e) + except ValueError: + if isinstance(result, str): + result = result.replace('"', '').replace('\'', '') return result @@ -232,8 +232,9 @@ def _def_parser(): alphas = pyparsing.alphas Combine = pyparsing.Combine - Forward = pyparsing.Forward nums = pyparsing.nums + quoted_string = pyparsing.quotedString + oneOf = pyparsing.oneOf opAssoc = pyparsing.opAssoc operatorPrecedence = pyparsing.operatorPrecedence @@ -243,9 +244,8 @@ def _def_parser(): real = Combine(Word(nums) + '.' + Word(nums)) variable = Word(alphas + '_' + '.') number = real | integer - expr = Forward() fn = Word(alphas + '_' + '.') - operand = number | variable | fn + operand = number | variable | fn | quoted_string signop = oneOf('+ -') addop = oneOf('+ -') diff --git a/cinder/tests/unit/test_evaluator.py b/cinder/tests/unit/test_evaluator.py index 4ff3384ee4d..bdc46a0894e 100644 --- a/cinder/tests/unit/test_evaluator.py +++ b/cinder/tests/unit/test_evaluator.py @@ -127,11 +127,12 @@ class EvaluatorTestCase(test.TestCase): def test_nonnumber_comparison(self): nonnumber = {'test': 'foo'} request = {'test': 'bar'} - self.assertRaises( - exception.EvaluatorParseException, - evaluator.evaluate, - "nonnumber.test != request.test", - nonnumber=nonnumber, request=request) + self.assertTrue( + evaluator.evaluate("nonnumber.test != request.test", + nonnumber=nonnumber, request=request)) + self.assertFalse( + evaluator.evaluate("nonnumber.test == request.test", + nonnumber=nonnumber, request=request)) def test_div_zero(self): self.assertRaises(exception.EvaluatorParseException,