Coverage for watcher/decision_engine/solution/efficacy.py: 89%
40 statements
« prev ^ index » next coverage.py v7.8.2, created at 2025-06-17 12:22 +0000
« prev ^ index » next coverage.py v7.8.2, created at 2025-06-17 12:22 +0000
1# -*- encoding: utf-8 -*-
2# Copyright (c) 2016 b<>com
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13# implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
17import numbers
19from oslo_log import log
21from watcher._i18n import _
22from watcher.common import exception
23from watcher.common import utils
25LOG = log.getLogger(__name__)
28class IndicatorsMap(utils.Struct):
29 pass
32class Indicator(utils.Struct):
34 def __init__(self, name, description, unit, value):
35 super(Indicator, self).__init__()
36 self.name = name
37 self.description = description
38 self.unit = unit
39 if not isinstance(value, numbers.Number): 39 ↛ 40line 39 didn't jump to line 40 because the condition on line 39 was never true
40 raise exception.InvalidIndicatorValue(
41 _("An indicator value should be a number"))
42 self.value = value
45class Efficacy(object):
46 """Solution efficacy"""
48 def __init__(self, goal, strategy):
49 """Solution efficacy
51 :param goal: Goal associated to this solution
52 :type goal: :py:class:`~.base.Goal` instance
53 :param strategy: Strategy associated to this solution
54 :type strategy: :py:class:`~.BaseStrategy` instance
55 """
56 self.goal = goal
57 self.strategy = strategy
59 self._efficacy_spec = self.goal.efficacy_specification
61 # Used to store in DB the info related to the efficacy indicators
62 self.indicators = []
63 # Used to compute the global efficacy
64 self._indicators_mapping = IndicatorsMap()
65 self.global_efficacy = []
67 def set_efficacy_indicators(self, **indicators_map):
68 """Set the efficacy indicators
70 :param indicators_map: kwargs where the key is the name of the efficacy
71 indicator as defined in the associated
72 :py:class:`~.IndicatorSpecification` and the
73 value is a number.
74 :type indicators_map: dict {str: numerical value}
75 """
76 self._indicators_mapping.update(indicators_map)
78 def compute_global_efficacy(self):
79 self._efficacy_spec.validate_efficacy_indicators(
80 self._indicators_mapping)
81 try:
82 self.global_efficacy = (
83 self._efficacy_spec.get_global_efficacy_indicator(
84 self._indicators_mapping))
86 indicators_specs_map = {
87 indicator_spec.name: indicator_spec
88 for indicator_spec in self._efficacy_spec.indicators_specs}
90 indicators = []
91 for indicator_name, value in self._indicators_mapping.items():
92 related_indicator_spec = indicators_specs_map[indicator_name]
93 indicators.append(
94 Indicator(
95 name=related_indicator_spec.name,
96 description=related_indicator_spec.description,
97 unit=related_indicator_spec.unit,
98 value=value))
100 self.indicators = indicators
101 except Exception as exc:
102 LOG.exception(exc)
103 raise exception.GlobalEfficacyComputationError(
104 goal=self.goal.name,
105 strategy=self.strategy.name)