Modify threshold policy to support multiple constraints 44/106744/1
authorkrishnaa96 <krishna.moorthy6@wipro.com>
Tue, 28 Apr 2020 12:54:09 +0000 (18:24 +0530)
committerkrishnaa96 <krishna.moorthy6@wipro.com>
Tue, 28 Apr 2020 12:56:56 +0000 (18:26 +0530)
Issue-ID: OPTFRA-730
Signed-off-by: krishnaa96 <krishna.moorthy6@wipro.com>
Change-Id: I8f8b4a694048088fcb61b6dbe7428b73f52e65d2

conductor/conductor/controller/translator.py
conductor/conductor/solver/optimizer/constraints/threshold.py
conductor/conductor/solver/utils/utils.py
conductor/conductor/tests/unit/solver/optimizer/constraints/test_threshold.py

index 9fa5b6b..7cafad0 100644 (file)
@@ -70,8 +70,7 @@ CONSTRAINTS = {
     },
     'threshold': {
         'split': True,
-        'required': ['attribute', 'threshold', 'operator'],
-        'optional': ['unit']
+        'required': ['evaluate'],
     },
     'distance_between_demands': {
         'required': ['distance'],
index a94c608..48ea2c7 100644 (file)
@@ -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
index 06de301..c995eec 100755 (executable)
@@ -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
 
index 34b8193..276701c 100644 (file)
@@ -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))