Modify threshold policy to support multiple constraints
[optf/has.git] / conductor / conductor / solver / optimizer / constraints / threshold.py
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