Coverage for watcher/decision_engine/scoring/scoring_factory.py: 100%

29 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""" 

20A module providing helper methods to work with Scoring Engines. 

21""" 

22 

23from oslo_log import log 

24 

25from watcher._i18n import _ 

26from watcher.decision_engine.loading import default 

27 

28 

29LOG = log.getLogger(__name__) 

30 

31_scoring_engine_map = None 

32 

33 

34def get_scoring_engine(scoring_engine_name): 

35 """Returns a Scoring Engine by its name. 

36 

37 Method retrieves a Scoring Engine instance by its name. Scoring Engine 

38 instances are being cached in memory to avoid enumerating the Stevedore 

39 plugins on each call. 

40 

41 When called for the first time, it reloads the cache. 

42 

43 :return: A Scoring Engine instance with a given name 

44 :rtype: :class: 

45 `watcher.decision_engine.scoring.scoring_engine.ScoringEngine` 

46 """ 

47 global _scoring_engine_map 

48 

49 _reload_scoring_engines() 

50 scoring_engine = _scoring_engine_map.get(scoring_engine_name) 

51 if scoring_engine is None: 

52 raise KeyError(_('Scoring Engine with name=%s not found') 

53 % scoring_engine_name) 

54 

55 return scoring_engine 

56 

57 

58def get_scoring_engine_list(): 

59 """Returns a list of Scoring Engine instances. 

60 

61 The main use case for this method is discoverability, so the Scoring 

62 Engine list is always reloaded before returning any results. 

63 

64 Frequent calling of this method might have a negative performance impact. 

65 

66 :return: A list of all available Scoring Engine instances 

67 :rtype: List of :class: 

68 `watcher.decision_engine.scoring.scoring_engine.ScoringEngine` 

69 """ 

70 global _scoring_engine_map 

71 

72 _reload_scoring_engines(True) 

73 return _scoring_engine_map.values() 

74 

75 

76def _reload_scoring_engines(refresh=False): 

77 """Reloads Scoring Engines from Stevedore plugins to memory. 

78 

79 Please note that two Stevedore entry points are used: 

80 - watcher_scoring_engines: for simple plugin implementations 

81 - watcher_scoring_engine_containers: for container plugins, which enable 

82 the dynamic scenarios (its get_scoring_engine_list method might return 

83 different values on each call) 

84 """ 

85 global _scoring_engine_map 

86 

87 if _scoring_engine_map is None or refresh: 

88 LOG.debug("Reloading Scoring Engine plugins") 

89 engines = default.DefaultScoringLoader().list_available() 

90 _scoring_engine_map = dict() 

91 

92 for name in engines.keys(): 

93 se_impl = default.DefaultScoringLoader().load(name) 

94 LOG.debug("Found Scoring Engine plugin: %s", se_impl.get_name()) 

95 _scoring_engine_map[se_impl.get_name()] = se_impl 

96 

97 engine_containers = \ 

98 default.DefaultScoringContainerLoader().list_available() 

99 

100 for container_id, container_cls in engine_containers.items(): 

101 LOG.debug("Found Scoring Engine container plugin: %s", 

102 container_id) 

103 for se in container_cls.get_scoring_engine_list(): 

104 LOG.debug("Found Scoring Engine plugin: %s", 

105 se.get_name()) 

106 _scoring_engine_map[se.get_name()] = se