Coverage for watcher/decision_engine/scoring/dummy_scoring_container.py: 84%

33 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-06-17 12:22 +0000

1# -*- encoding: utf-8 -*- 

2# Copyright (c) 2016 Intel 

3# 

4# Authors: Tomasz Kaczynski <tomasz.kaczynski@intel.com> 

5# 

6# Licensed under the Apache License, Version 2.0 (the "License"); 

7# you may not use this file except in compliance with the License. 

8# You may obtain a copy of the License at 

9# 

10# http://www.apache.org/licenses/LICENSE-2.0 

11# 

12# Unless required by applicable law or agreed to in writing, software 

13# distributed under the License is distributed on an "AS IS" BASIS, 

14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 

15# implied. 

16# See the License for the specific language governing permissions and 

17# limitations under the License. 

18# 

19 

20from oslo_log import log 

21from oslo_serialization import jsonutils 

22 

23from watcher._i18n import _ 

24from watcher.decision_engine.scoring import base 

25 

26LOG = log.getLogger(__name__) 

27 

28 

29class DummyScoringContainer(base.ScoringEngineContainer): 

30 """Sample Scoring Engine container returning a list of scoring engines. 

31 

32 Please note that it can be used in dynamic scenarios and the returned list 

33 might return instances based on some external configuration (e.g. in 

34 database). In order for these scoring engines to become discoverable in 

35 Watcher API and Watcher CLI, a database re-sync is required. It can be 

36 executed using watcher-sync tool for example. 

37 """ 

38 

39 @classmethod 

40 def get_scoring_engine_list(cls): 

41 return [ 

42 SimpleFunctionScorer( 

43 'dummy_min_scorer', 

44 'Dummy Scorer calculating the minimum value', 

45 min), 

46 SimpleFunctionScorer( 

47 'dummy_max_scorer', 

48 'Dummy Scorer calculating the maximum value', 

49 max), 

50 SimpleFunctionScorer( 

51 'dummy_avg_scorer', 

52 'Dummy Scorer calculating the average value', 

53 lambda x: float(sum(x)) / len(x)), 

54 ] 

55 

56 

57class SimpleFunctionScorer(base.ScoringEngine): 

58 """A simple generic scoring engine for demonstration purposes only. 

59 

60 A generic scoring engine implementation, which is expecting a JSON 

61 formatted array of numbers to be passed as an input for score calculation. 

62 It then executes the aggregate function on this array and returns an 

63 array with a single aggregated number (also JSON formatted). 

64 """ 

65 

66 def __init__(self, name, description, aggregate_function): 

67 super(SimpleFunctionScorer, self).__init__(config=None) 

68 self._name = name 

69 self._description = description 

70 self._aggregate_function = aggregate_function 

71 

72 def get_name(self): 

73 return self._name 

74 

75 def get_description(self): 

76 return self._description 

77 

78 def get_metainfo(self): 

79 return '' 

80 

81 def calculate_score(self, features): 

82 LOG.debug('Calculating score, features: %s', features) 

83 

84 # Basic input validation 

85 try: 

86 flist = jsonutils.loads(features) 

87 except Exception as e: 

88 raise ValueError(_('Unable to parse features: %s') % e) 

89 if type(flist) is not list: 89 ↛ 90line 89 didn't jump to line 90 because the condition on line 89 was never true

90 raise ValueError(_('JSON list expected in feature argument')) 

91 if len(flist) < 1: 91 ↛ 92line 91 didn't jump to line 92 because the condition on line 91 was never true

92 raise ValueError(_('At least one feature is required')) 

93 

94 # Calculate the result 

95 result = self._aggregate_function(flist) 

96 

97 # Return the aggregated result 

98 return jsonutils.dumps([result])