Merge "ci: verify generated rpms"
[barometer.git] / baro_tests / tests.py
1 # -*- coding: utf-8 -*-
2
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """Function for testing collectd plug-ins with different oup plug-ins"""
16
17 import time
18
19
20 def test_snmp_sends_data(
21         compute, interval, logger, client, mib_file=None,
22         mib_strings=None, in_command=None, conf=None):
23     """Check that SNMP deta are updated"""
24     logger.debug('Interval: {}'.format(interval))
25     if mib_file is not None:
26         logger.info(
27             'Getting SNMP metrics of MIB file {} and '.format(mib_file)
28             + 'following MIB strings: {}...'.format(', '.join(mib_strings)))
29     snmp_metrics = client.get_snmp_metrics(compute, mib_file, mib_strings)
30     if mib_file is None:
31         return len(snmp_metrics) > 1
32     if in_command is not None and conf is not None:
33         conf.execute_command(in_command, compute.get_ip())
34
35     attempt = 1
36     is_passed = False
37     while (attempt <= 10) and not is_passed:
38         is_passed = True
39         # wait Interval time + 2 sec for db update
40         sleep_time = interval + 2
41         if attempt > 1:
42             logger.info('Starting attempt {}'.format(attempt))
43         logger.info(
44             'Sleeping for {} seconds to get updated entries'.format(sleep_time)
45             + ' (interval is {} sec)...'.format(interval))
46         time.sleep(sleep_time)
47
48         logger.info(
49             'Getting SNMP metrics of MIB file {} and '.format(mib_file)
50             + 'following MIB strings: {}...'.format(', '.join(mib_strings)))
51         snmp_metrics2 = client.get_snmp_metrics(compute, mib_file, mib_strings)
52         unchanged_snmp_metrics = [
53             snmp_metric for snmp_metric in snmp_metrics
54             if snmp_metrics[snmp_metric] == snmp_metrics2[snmp_metric]]
55         if len(unchanged_snmp_metrics) > 0:
56             logger.error("Following SNMP metrics didn't change: {}".format(
57                 ', '.join(unchanged_snmp_metrics)))
58             is_passed = False
59         attempt += 1
60         if not is_passed:
61             logger.warning('After sleep new entries were not found.')
62     if not is_passed:
63         logger.error('This was the last attempt.')
64         return False
65     logger.info('All SNMP metrics are changed.')
66     return True
67
68
69 def test_ceilometer_node_sends_data(
70         node_id, interval, logger, client, criteria_list=[],
71         resource_id_substrings=['']):
72     """ Test that data reported by Ceilometer are updated in the given interval.
73
74     Keyword arguments:
75     node_id -- node ID
76     interval -- interval to check
77     logger -- logger instance
78     client -- CeilometerClient instance
79     criteria_list -- list of criteria used in ceilometer calls
80     resource_id_substrings -- list of substrings to search for in resource ID
81
82     Return boolean value indicating success or failure.
83     """
84
85     def _search_meterlist_latest_entry(meterlist, node_str, substr=''):
86         """Search for latest entry in meter list
87
88         Keyword arguments:
89         meterlist -- list of metrics
90         node_str -- name of node, which will be found in meter list
91         substr -- substring which will be found in meter list
92
93         Return latest entry from meter list which contains given node string
94         and (if defined) subsrting.
95         """
96         res = [
97             entry for entry in meterlist if node_str in entry['resource_id']
98             and substr in entry['resource_id']]
99         if res:
100             return res[0]
101         else:
102             return []
103
104     client.auth_token()
105     timestamps = {}
106     node_str = 'node-{}'.format(node_id) if node_id else ''
107
108     logger.info(
109         'Searching for timestamps of latest entries{0}{1}{2}...'.format(
110             '' if node_str == '' else ' for {}'.format(node_str),
111             '' if len(criteria_list) == 0 else (
112                 ' for criteria ' + ', '.join(criteria_list)),
113             '' if resource_id_substrings == [''] else
114             ' and resource ID substrings "{}"'.format(
115                 '", "'.join(resource_id_substrings))))
116     for criterion in criteria_list if len(criteria_list) > 0 else [None]:
117         meter_list = client.get_gnocchi_metrics(criterion)
118         for resource_id_substring in resource_id_substrings:
119             last_entry = _search_meterlist_latest_entry(
120                 meter_list, node_str, resource_id_substring)
121             if len(last_entry) == 0:
122                 logger.error('Entry{0}{1}{2} not found'.format(
123                     '' if node_str == '' else ' for {}'.format(node_str),
124                     '' if criterion is None else 'for criterion {}'.format(
125                         criterion),
126                     '' if resource_id_substring == '' else 'and resource '
127                     + 'ID substring "{}"'.format(resource_id_substring)))
128                 return False
129             timestamp = last_entry['timestamp']
130             logger.debug('Last entry found: {0} {1}'.format(
131                 timestamp, last_entry['resource_id']))
132             timestamps[(criterion, resource_id_substring)] = timestamp
133
134     attempt = 1
135     is_passed = False
136     while (attempt <= 10) and not is_passed:
137         is_passed = True
138         # wait Interval time + 2 sec for db update
139         sleep_time = interval + 2
140         if attempt > 1:
141             logger.info('Starting attempt {}'.format(attempt))
142         logger.info(
143             'Sleeping for {} seconds to get updated entries '.format(sleep_time)
144             + '(interval is {} sec)...'.format(interval))
145         time.sleep(sleep_time)
146
147         logger.info(
148             'Searching for timestamps of latest entries{}{}{}...' .format(
149                 '' if node_str == '' else ' for {}'.format(node_str),
150                 '' if len(criteria_list) == 0 else (
151                     ' for criteria ' + ', ' .join(criteria_list)),
152                 '' if resource_id_substrings == ['']
153                 else ' and resource ID substrings "{}"' .format(
154                     '", "'.join(resource_id_substrings))))
155         for criterion in criteria_list if len(criteria_list) > 0 else [None]:
156             meter_list = client.get_ceil_metrics(criterion)
157             for resource_id_substring in resource_id_substrings:
158                 last_entry = _search_meterlist_latest_entry(
159                     meter_list, node_str, resource_id_substring)
160                 if len(last_entry) == 0:
161                     logger.error('Entry{0}{1}{2} not found'.format(
162                         '' if node_str == '' else ' for {}'.format(node_str),
163                         '' if criterion is None else 'for criterion {}'.format(
164                             criterion),
165                         '' if resource_id_substring == '' else ' and resource'
166                         + 'ID substring "{}"'.format(resource_id_substring)))
167                     return False
168                 timestamp = last_entry['timestamp']
169                 logger.debug('Last entry found: {} {}'.format(
170                     timestamp, last_entry['resource_id']))
171                 if timestamp == timestamps[(criterion, resource_id_substring)]:
172                     logger.warning(
173                         'Last entry{0}{1}{2} has the same timestamp as '
174                         + 'before the sleep'.format(
175                             '' if node_str == '' else ' for {}'.format(
176                                 node_str),
177                             '' if resource_id_substring == ''
178                             else ', substring "{}"'.format(
179                                 resource_id_substring),
180                             '' if criterion is None else
181                             ' for criterion {}'.format(criterion)))
182                     is_passed = False
183         attempt += 1
184         if not is_passed:
185             logger.warning('After sleep new entries were not found.')
186     if not is_passed:
187         logger.error('This was the last attempt.')
188         return False
189     logger.info('All latest entries found.')
190     return True
191
192
193 def test_csv_handles_plugin_data(
194         compute, interval, plugin, plugin_subdirs, meter_categories,
195         logger, client):
196     """Check that CSV data are updated by the plugin.
197
198     Keyword arguments:
199     compute -- object compute node
200     interval -- interval to check
201     plugin -- plugin which will be tested
202     plugin_subdirs -- list subdirectories in csv folder
203     meter_categories -- list of meter categories which will be tested
204     logger -- logger instance
205     client -- CSVClient instance
206
207     Return boolean value indicating success or failure.
208     """
209     logger.info(
210         'Getting CSV metrics of plugin {} on compute node {}...' .format(
211             plugin, compute.get_id()))
212     logger.debug('Interval: {}'.format(interval))
213     logger.debug('Plugin subdirs: {}'.format(plugin_subdirs))
214     logger.debug('Plugin meter categories: {}'.format(meter_categories))
215     plugin_metrics = client.get_csv_metrics(
216         compute, plugin_subdirs, meter_categories)
217     if len(plugin_metrics) < len(plugin_subdirs) * len(meter_categories):
218         logger.error('Some plugin metrics not found')
219         return False
220
221     logger.info(
222         'Checking that last two entries in metrics are corresponding'
223         + 'to interval...')
224     for metric in plugin_metrics:
225         logger.debug('{0} {1} {2} ... '.format(metric[0], metric[1], metric[2]))
226         if metric[3] - metric[2] != interval:
227             logger.error(
228                 'Time of last two entries differ by '
229                 + '{}, but interval is {}'.format(
230                     metric[3] - metric[2], interval))
231             return False
232         else:
233             logger.debug('OK')
234     logger.info('OK')
235
236     # wait Interval time + 2 sec
237     sleep_time = interval + 2
238     logger.info(
239         'Sleeping for {} seconds to get updated entries '.format(sleep_time)
240         + '(interval is {} sec)...'.format(interval))
241     time.sleep(sleep_time)
242
243     logger.info('Getting new metrics of compute node {}...'.format(
244         compute.get_name()))
245     plugin_metrics2 = client.get_csv_metrics(
246         compute, plugin_subdirs, meter_categories)
247     if len(plugin_metrics2) < len(plugin_subdirs) * len(meter_categories):
248         logger.error('Some plugin metrics not found')
249         return False
250
251     logger.info('Comparing old and new metrics...')
252     logger.debug(plugin_metrics)
253     logger.debug(plugin_metrics2)
254     if len(plugin_metrics) != len(plugin_metrics2):
255         logger.error('Plugin metrics length before and after sleep differ')
256         return False
257     for i in range(len(plugin_metrics2)):
258         logger.debug('{0} {1} {2}  - {3} {4} {5} ... '.format(
259             plugin_metrics[i][0], plugin_metrics[i][1],
260             plugin_metrics[i][2], plugin_metrics2[i][0],
261             plugin_metrics2[i][1], plugin_metrics2[i][2]))
262         if plugin_metrics[i] == plugin_metrics2[i]:
263             logger.error('FAIL')
264             return False
265         else:
266             logger.debug('OK')
267     logger.info('OK')
268
269     return True