Coverage for watcher/decision_engine/datasources/grafana_translator/base.py: 85%

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) 2019 European Organization for Nuclear Research (CERN) 

3# 

4# Authors: Corne Lukken <info@dantalion.nl> 

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 

19import abc 

20 

21from watcher._i18n import _ 

22from watcher.common import exception 

23from watcher.decision_engine.datasources import base 

24 

25 

26class BaseGrafanaTranslator(object): 

27 """Grafana translator baseclass to use with grafana for different databases 

28 

29 Specific databasses that are proxied through grafana require some 

30 alterations depending on the database. 

31 """ 

32 

33 """ 

34 data { 

35 metric: name of the metric as found in DataSourceBase.METRIC_MAP, 

36 db: database specified for this metric in grafana_client config 

37 options, 

38 attribute: the piece of information that will be selected from the 

39 resource object to build the query. 

40 query: the unformatted query from the configuration for this metric, 

41 resource: the object from the OpenStackClient 

42 resource_type: the type of the resource 

43 ['compute_node','instance', 'bare_metal', 'storage'], 

44 period: the period of time to collect metrics for in seconds, 

45 aggregate: the aggregation can be any from ['mean', 'max', 'min', 

46 'count'], 

47 granularity: interval between datapoints in seconds (optional), 

48 } 

49 """ 

50 

51 """Every grafana translator should have a uniquely identifying name""" 

52 NAME = '' 

53 

54 RESOURCE_TYPES = base.DataSourceBase.RESOURCE_TYPES 

55 

56 AGGREGATES = base.DataSourceBase.AGGREGATES 

57 

58 def __init__(self, data): 

59 self._data = data 

60 self._validate_data() 

61 

62 def _validate_data(self): 

63 """iterate through the supplied data and verify attributes""" 

64 

65 optionals = ['granularity'] 

66 

67 reference_data = { 

68 'metric': None, 

69 'db': None, 

70 'attribute': None, 

71 'query': None, 

72 'resource': None, 

73 'resource_type': None, 

74 'period': None, 

75 'aggregate': None, 

76 'granularity': None 

77 } 

78 reference_data.update(self._data) 

79 

80 for key, value in reference_data.items(): 

81 if value is None and key not in optionals: 

82 raise exception.InvalidParameter( 

83 message=(_("The value %(value)s for parameter " 

84 "%(parameter)s is invalid") % {'value': None, 

85 'parameter': key} 

86 ) 

87 ) 

88 

89 if reference_data['resource_type'] not in self.RESOURCE_TYPES: 89 ↛ 90line 89 didn't jump to line 90 because the condition on line 89 was never true

90 raise exception.InvalidParameter(parameter='resource_type', 

91 parameter_type='RESOURCE_TYPES') 

92 

93 if reference_data['aggregate'] not in self.AGGREGATES: 93 ↛ 94line 93 didn't jump to line 94 because the condition on line 93 was never true

94 raise exception.InvalidParameter(parameter='aggregate', 

95 parameter_type='AGGREGATES') 

96 

97 @staticmethod 

98 def _extract_attribute(resource, attribute): 

99 """Retrieve the desired attribute from the resource 

100 

101 :param resource: The resource object to extract the attribute from. 

102 :param attribute: The name of the attribute to subtract as string. 

103 :return: The extracted attribute or None 

104 """ 

105 

106 try: 

107 return getattr(resource, attribute) 

108 except AttributeError: 

109 raise 

110 

111 @staticmethod 

112 def _query_format(query, aggregate, resource, period, 

113 granularity, translator_specific): 

114 return query.format(aggregate, resource, period, granularity, 

115 translator_specific) 

116 

117 @abc.abstractmethod 

118 def build_params(self): 

119 """Build the set of parameters to send with the request""" 

120 raise NotImplementedError() 

121 

122 @abc.abstractmethod 

123 def extract_result(self, raw_results): 

124 """Extrapolate the metric from the raw results of the request""" 

125 raise NotImplementedError()