From da6653e0886ea6e20b24324cb608adaf542c5b10 Mon Sep 17 00:00:00 2001 From: krishnaa96 Date: Tue, 28 Apr 2020 18:24:09 +0530 Subject: Modify threshold policy to support multiple constraints Issue-ID: OPTFRA-730 Signed-off-by: krishnaa96 Change-Id: I8f8b4a694048088fcb61b6dbe7428b73f52e65d2 --- conductor/conductor/controller/translator.py | 3 +- .../solver/optimizer/constraints/threshold.py | 35 ++++++++++------------ conductor/conductor/solver/utils/utils.py | 8 +++++ .../solver/optimizer/constraints/test_threshold.py | 26 +++++++--------- 4 files changed, 34 insertions(+), 38 deletions(-) diff --git a/conductor/conductor/controller/translator.py b/conductor/conductor/controller/translator.py index 9fa5b6b..7cafad0 100644 --- a/conductor/conductor/controller/translator.py +++ b/conductor/conductor/controller/translator.py @@ -70,8 +70,7 @@ CONSTRAINTS = { }, 'threshold': { 'split': True, - 'required': ['attribute', 'threshold', 'operator'], - 'optional': ['unit'] + 'required': ['evaluate'], }, 'distance_between_demands': { 'required': ['distance'], diff --git a/conductor/conductor/solver/optimizer/constraints/threshold.py b/conductor/conductor/solver/optimizer/constraints/threshold.py index a94c608..48ea2c7 100644 --- a/conductor/conductor/solver/optimizer/constraints/threshold.py +++ b/conductor/conductor/solver/optimizer/constraints/threshold.py @@ -19,6 +19,7 @@ from conductor.i18n import _LI from conductor.solver.optimizer.constraints import constraint +from conductor.solver.utils.utils import OPERATIONS from oslo_log import log LOG = log.getLogger(__name__) @@ -26,37 +27,31 @@ LOG = log.getLogger(__name__) class Threshold(constraint.Constraint): - OPERATIONS = {'gte': lambda x, y: x >= y, - 'lte': lambda x, y: x <= y, - 'gt': lambda x, y: x > y, - 'lt': lambda x, y: x < y, - 'eq': lambda x, y: x == y - } - def __init__(self, _name, _type, _demand_list, _priority=0, _properties=None): constraint.Constraint.__init__( self, _name, _type, _demand_list, _priority) - self.attribute = _properties.get('attribute') - self.operation = self.OPERATIONS.get(_properties.get('operator')) - self.threshold = _properties.get('threshold') + self.properties_list = _properties.get('evaluate') def solve(self, _decision_path, _candidate_list, _request): - filtered_candidates = list() + conflict_list = list() demand_name = _decision_path.current_demand.name - LOG.info(_LI("Solving constraint type '{}' for demand - [{}]").format( - self.constraint_type, demand_name)) + LOG.info(_LI("Solving constraint {} of type '{}' for demand - [{}]").format( + self.name, self.constraint_type, demand_name)) for candidate in _candidate_list: - attribute_value = candidate.get(self.attribute) - if self.operation(attribute_value, self.threshold): - filtered_candidates.append(candidate) - - return filtered_candidates - - + for prop in self.properties_list: + attribute = prop.get('attribute') + threshold = prop.get('threshold') + operation = OPERATIONS.get(prop.get('operator')) + attribute_value = candidate.get(attribute) + if not operation(attribute_value, threshold): + conflict_list.append(candidate) + continue + filtered_candidates = [c for c in _candidate_list if c not in conflict_list] + return filtered_candidates diff --git a/conductor/conductor/solver/utils/utils.py b/conductor/conductor/solver/utils/utils.py index 06de301..c995eec 100755 --- a/conductor/conductor/solver/utils/utils.py +++ b/conductor/conductor/solver/utils/utils.py @@ -24,6 +24,14 @@ from oslo_log import log LOG = log.getLogger(__name__) +OPERATIONS = {'gte': lambda x, y: x >= y, + 'lte': lambda x, y: x <= y, + 'gt': lambda x, y: x > y, + 'lt': lambda x, y: x < y, + 'eq': lambda x, y: x == y + } + + def compute_air_distance(_src, _dst): """Compute Air Distance diff --git a/conductor/conductor/tests/unit/solver/optimizer/constraints/test_threshold.py b/conductor/conductor/tests/unit/solver/optimizer/constraints/test_threshold.py index 34b8193..276701c 100644 --- a/conductor/conductor/tests/unit/solver/optimizer/constraints/test_threshold.py +++ b/conductor/conductor/tests/unit/solver/optimizer/constraints/test_threshold.py @@ -31,30 +31,24 @@ class TestThreshold(unittest.TestCase): candidates_file = './conductor/tests/unit/data/plugins/inventory_provider/nssi_candidate.json' candidates = json.loads(open(candidates_file).read()) - properties = {'attribute': 'latency', 'threshold': 30, 'operator': 'lte'} + properties = {'evaluate': + [{'attribute': 'latency', 'threshold': 30, 'operator': 'lte'}, + {'attribute': 'exp_data_rate_ul', 'threshold': 70, 'operator': 'gte'}]} - threshold_obj = Threshold('urllc_threshold', 'threshold', ['URLLC'], _priority=0, _properties=properties) + threshold_obj = Threshold('urllc_threshold', 'threshold', ['URLLC'], _priority=0, + _properties=properties) decision_path = DecisionPath() decision_path.current_demand = Demand('URLLC') self.assertEqual(candidates, threshold_obj.solve(decision_path, candidates, None)) - properties = {'attribute': 'latency', 'threshold': 10, 'operator': 'lte'} + properties = {'evaluate': + [{'attribute': 'latency', 'threshold': 10, 'operator': 'lte'}, + {'attribute': 'exp_data_rate_ul', 'threshold': 120, 'operator': 'gte'}]} - threshold_obj = Threshold('urllc_threshold', 'threshold', ['URLLC'], _priority=0, _properties=properties) - - self.assertEqual([], threshold_obj.solve(decision_path, candidates, None)) - - properties = {'attribute': 'exp_data_rate_ul', 'threshold': 70, 'operator': 'gte'} - - threshold_obj = Threshold('urllc_threshold', 'threshold', ['URLLC'], _priority=0, _properties=properties) - - self.assertEqual(candidates, threshold_obj.solve(decision_path, candidates, None)) - - properties = {'attribute': 'exp_data_rate_ul', 'threshold': 120, 'operator': 'gte'} - - threshold_obj = Threshold('urllc_threshold', 'threshold', ['URLLC'], _priority=0, _properties=properties) + threshold_obj = Threshold('urllc_threshold', 'threshold', ['URLLC'], _priority=0, + _properties=properties) self.assertEqual([], threshold_obj.solve(decision_path, candidates, None)) -- cgit 1.2.3-korg