diff --git a/sonic_platform_base/sonic_thermal_control/thermal_json_object.py b/sonic_platform_base/sonic_thermal_control/thermal_json_object.py index 3060d8665..243d337ed 100644 --- a/sonic_platform_base/sonic_thermal_control/thermal_json_object.py +++ b/sonic_platform_base/sonic_thermal_control/thermal_json_object.py @@ -17,6 +17,15 @@ def load_from_json(self, json_obj): """ pass + def __eq__(self, other): + """ + Compare input object with this object, return True if equal. Subclass should override this + if necessary. + :param other: Object to compare with. + :return: True if equal else False + """ + return self.__class__ == other.__class__ + @classmethod def register_concrete_type(cls, type_name, object_type): """ diff --git a/sonic_platform_base/sonic_thermal_control/thermal_manager_base.py b/sonic_platform_base/sonic_thermal_control/thermal_manager_base.py index 8ffe5d6ed..3b380bad3 100644 --- a/sonic_platform_base/sonic_thermal_control/thermal_manager_base.py +++ b/sonic_platform_base/sonic_thermal_control/thermal_manager_base.py @@ -151,6 +151,7 @@ def _load_policy(cls, json_policy): policy = ThermalPolicy() policy.load_from_json(json_policy) + policy.validate_duplicate_policy(cls._policy_dict.values()) cls._policy_dict[name] = policy else: raise Exception('{} not found in policy'.format(cls.JSON_FIELD_POLICY_NAME)) diff --git a/sonic_platform_base/sonic_thermal_control/thermal_policy.py b/sonic_platform_base/sonic_thermal_control/thermal_policy.py index 56e619bff..eeb1962ab 100644 --- a/sonic_platform_base/sonic_thermal_control/thermal_policy.py +++ b/sonic_platform_base/sonic_thermal_control/thermal_policy.py @@ -1,4 +1,5 @@ from .thermal_json_object import ThermalJsonObject +from collections import OrderedDict class ThermalPolicy(object): @@ -15,10 +16,10 @@ def __init__(self): self.name = None # Conditions load from JSON policy file - self.conditions = [] + self.conditions = OrderedDict() # Actions load from JSON policy file - self.actions = [] + self.actions = OrderedDict() def load_from_json(self, json_obj): """ @@ -32,16 +33,23 @@ def load_from_json(self, json_obj): if self.JSON_FIELD_CONDITIONS in json_obj: for json_condition in json_obj[self.JSON_FIELD_CONDITIONS]: cond_type = ThermalJsonObject.get_type(json_condition) + if cond_type in self.conditions: + raise Exception('Duplicate thermal condition type detected in policy [{}]!'.format(self.name)) cond_obj = cond_type() cond_obj.load_from_json(json_condition) - self.conditions.append(cond_obj) + self.conditions[cond_type] = cond_obj if self.JSON_FIELD_ACTIONS in json_obj: for json_action in json_obj[self.JSON_FIELD_ACTIONS]: action_type = ThermalJsonObject.get_type(json_action) + if action_type in self.actions: + raise Exception('Duplicate thermal action type detected in policy [{}]!'.format(self.name)) action_obj = action_type() action_obj.load_from_json(json_action) - self.actions.append(action_obj) + self.actions[action_type] = action_obj + + if not len(self.conditions) or not len(self.actions): + raise Exception('A policy requires at least 1 action and 1 condition') else: raise Exception('name field not found in policy') @@ -51,7 +59,7 @@ def is_match(self, thermal_info_dict): :param thermal_info_dict: A dictionary stores all thermal information. :return: True if all conditions matches else False. """ - for condition in self.conditions: + for condition in self.conditions.values(): if not condition.is_match(thermal_info_dict): return False @@ -63,5 +71,19 @@ def do_action(self, thermal_info_dict): :param thermal_info_dict: A dictionary stores all thermal information. :return: """ - for action in self.actions: + for action in self.actions.values(): action.execute(thermal_info_dict) + + def validate_duplicate_policy(self, policies): + """ + Detect this policy with existing policies, if a policy with same conditions exists, raise Exception. + :param policies: existing policies. + :return: + """ + for policy in policies: + if len(policy.conditions) != len(self.conditions): + continue + + for cond_type, value in policy.conditions.items(): + if cond_type in self.conditions and policy.conditions[cond_type] == self.conditions[cond_type]: + raise Exception('Policy [{}] and policy [{}] have duplicate conditions'.format(policy.name, self.name))