Modyfying method to get env variables in Barometer
[barometer.git] / baro_tests / collectd.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 """Executing test of plugins"""
16
17 import requests
18 from keystoneclient.v3 import client
19 import os
20 import sys
21 import time
22 import logging
23 import config_server
24 import tests
25 from opnfv.deployment import factory
26
27 AODH_NAME = 'aodh'
28 GNOCCHI_NAME = 'gnocchi'
29 ID_RSA_SRC = '/root/.ssh/id_rsa'
30 ID_RSA_DST_DIR = '/root/.ssh'
31 ID_RSA_DST = ID_RSA_DST_DIR + '/id_rsa'
32 APEX_IP = os.getenv("INSTALLER_IP").rstrip('\n')
33 APEX_USER = 'root'
34 APEX_USER_STACK = 'stack'
35 APEX_PKEY = '/root/.ssh/id_rsa'
36 PATH = os.path.dirname(os.path.realpath(__file__))
37
38
39 class KeystoneException(Exception):
40     """Keystone exception class"""
41     def __init__(self, message, exc=None, response=None):
42         """
43         Keyword arguments:
44         message -- error message
45         exc -- exception
46         response -- response
47         """
48         if exc:
49             message += "\nReason: %s" % exc
50         super(KeystoneException, self).__init__(message)
51
52         self.response = response
53         self.exception = exc
54
55
56 class InvalidResponse(KeystoneException):
57     """Invalid Keystone exception class"""
58     def __init__(self, exc, response):
59         """
60         Keyword arguments:
61         exc -- exception
62         response -- response
63         """
64         super(InvalidResponse, self).__init__(
65             "Invalid response", exc, response)
66
67
68 def get_apex_nodes():
69     handler = factory.Factory.get_handler('apex',
70                                           APEX_IP,
71                                           APEX_USER_STACK,
72                                           APEX_PKEY)
73     nodes = handler.get_nodes()
74     return nodes
75
76
77 class GnocchiClient(object):
78     # Gnocchi Client to authenticate and request meters
79     def __init__(self):
80         self._auth_token = None
81         self._gnocchi_url = None
82         self._meter_list = None
83
84     def auth_token(self):
85         # Get auth token
86         self._auth_server()
87         return self._auth_token
88
89     def get_gnocchi_url(self):
90         # Get Gnocchi  URL
91         return self._gnocchi_url
92
93     def get_gnocchi_metrics(self, criteria=None):
94         # Subject to change if metric gathering is different for gnocchi
95         self._request_meters(criteria)
96         return self._meter_list
97
98     def _auth_server(self):
99         # Request token in authentication server
100         logger.debug('Connecting to the auth server {}'.format(
101             os.environ['OS_AUTH_URL']))
102         keystone = client.Client(username=os.environ['OS_USERNAME'],
103                                  password=os.environ['OS_PASSWORD'],
104                                  tenant_name=os.environ['OS_USERNAME'],
105                                  auth_url=os.environ['OS_AUTH_URL'])
106         self._auth_token = keystone.auth_token
107         for service in keystone.service_catalog.get_data():
108             if service['name'] == GNOCCHI_NAME:
109                 for service_type in service['endpoints']:
110                     if service_type['interface'] == 'internal':
111                         self._gnocchi_url = service_type['url']
112
113         if self._gnocchi_url is None:
114             logger.warning('Gnocchi is not registered in service catalog')
115
116     def _request_meters(self, criteria):
117         """Request meter list values from ceilometer
118
119         Keyword arguments:
120         criteria -- criteria for ceilometer meter list
121         """
122         if criteria is None:
123             url = self._gnocchi_url + ('/v2/metric?limit=400')
124         else:
125             url = self._gnocchi_url \
126                 + ('/v3/metric/%s?q.field=metric&limit=400' % criteria)
127         headers = {'X-Auth-Token': self._auth_token}
128         resp = requests.get(url, headers=headers)
129         try:
130             resp.raise_for_status()
131             self._meter_list = resp.json()
132         except (KeyError, ValueError, requests.exceptions.HTTPError) as err:
133             raise InvalidResponse(err, resp)
134
135
136 class AodhClient(object):
137     # Gnocchi Client to authenticate and request meters
138     def __init__(self):
139         self._auth_token = None
140         self._aodh_url = None
141         self._meter_list = None
142
143     def auth_token(self):
144         # Get auth token
145         self._auth_server()
146         return self._auth_token
147
148     def get_aodh_url(self):
149         # Get Gnocchi  URL
150         return self._gnocchi_url
151
152     def get_aodh_metrics(self, criteria=None):
153         # Subject to change if metric gathering is different for gnocchi
154         self._request_meters(criteria)
155         return self._meter_list
156
157     def _auth_server(self):
158         # Request token in authentication server
159         logger.debug('Connecting to the AODH auth server {}'.format(
160             os.environ['OS_AUTH_URL']))
161         keystone = client.Client(username=os.environ['OS_USERNAME'],
162                                  password=os.environ['OS_PASSWORD'],
163                                  tenant_name=os.environ['OS_USERNAME'],
164                                  auth_url=os.environ['OS_AUTH_URL'])
165         self._auth_token = keystone.auth_token
166         for service in keystone.service_catalog.get_data():
167             if service['name'] == AODH_NAME:
168                 for service_type in service['endpoints']:
169                     if service_type['interface'] == 'internal':
170                         self._gnocchi_url = service_type['url']
171
172         if self._aodh_url is None:
173             logger.warning('Aodh is not registered in service catalog')
174
175
176 class CSVClient(object):
177     """Client to request CSV meters"""
178     def __init__(self, conf):
179         """
180         Keyword arguments:
181         conf -- ConfigServer instance
182         """
183         self.conf = conf
184
185     def get_csv_metrics(
186             self, compute_node, plugin_subdirectories, meter_categories):
187         """Get CSV metrics.
188
189         Keyword arguments:
190         compute_node -- compute node instance
191         plugin_subdirectories -- list of subdirectories of plug-in
192         meter_categories -- categories which will be tested
193
194         Return list of metrics.
195         """
196         compute_name = compute_node.get_name()
197         nodes = get_apex_nodes()
198         for node in nodes:
199             if compute_name == node.get_dict()['name']:
200                 date = node.run_cmd(
201                     "date '+%Y-%m-%d'")
202                 hostname = node.run_cmd('hostname -A')
203                 hostname = hostname.split()[0]
204                 metrics = []
205                 for plugin_subdir in plugin_subdirectories:
206                     for meter_category in meter_categories:
207                         stdout1 = node.run_cmd(
208                             "tail -2 /var/lib/collectd/csv/"
209                             + "{0}/{1}/{2}-{3}".format(
210                                 hostname, plugin_subdir,
211                                 meter_category, date))
212                         stdout2 = node.run_cmd(
213                             "tail -1 /var/lib/collectd/csv/"
214                             + "{0}.jf.intel.com/{1}/{2}-{3}".format(
215                                 compute_node.get_name(), plugin_subdir,
216                                 meter_category, date))
217                         # Storing last two values
218                         values = stdout1
219                         if values is None:
220                             logger.error(
221                                 'Getting last two CSV entries of meter category'
222                                 + ' {0} in {1} subdir failed'.format(
223                                     meter_category, plugin_subdir))
224                         else:
225                             values = values.split(',')
226                             old_value = float(values[0])
227                             stdout2 = stdout2.split(',')
228                             new_value = float(stdout2[0])
229                             metrics.append((
230                                 plugin_subdir, meter_category, old_value,
231                                 new_value))
232         return metrics
233
234
235 def get_csv_categories_for_ipmi(conf, compute_node):
236     """Get CSV metrics.
237
238     Keyword arguments:
239     compute_node -- compute node instance
240
241     Return list of categories.
242     """
243     stdout = conf.execute_command(
244         "date '+%Y-%m-%d'", compute_node.get_ip())
245     date = stdout[0].strip()
246     categories = conf.execute_command(
247         "ls /var/lib/collectd/csv/{0}.jf.intel.com/ipmi | grep {1}".format(
248             compute_node.get_name(), date), compute_node.get_ip())
249     return [category.strip()[:-11] for category in categories]
250
251
252 def _process_result(compute_node, out_plugin, test, result, results_list):
253     """Print test result and append it to results list.
254
255     Keyword arguments:
256     test -- testcase name
257     result -- boolean test result
258     results_list -- results list
259     """
260     if result:
261         logger.info(
262             'Test case {0} PASSED with {1}.'.format(
263                 test, out_plugin))
264     else:
265         logger.error(
266             'Test case {0} FAILED with {1}.'.format(
267                 test, out_plugin))
268     results_list.append((compute_node, out_plugin, test, result))
269
270
271 def _print_label(label):
272     """Print label on the screen
273
274     Keyword arguments:
275     label -- label string
276     """
277     label = label.strip()
278     length = 70
279     if label != '':
280         label = ' ' + label + ' '
281     length_label = len(label)
282     length1 = (length - length_label) / 2
283     length2 = length - length_label - length1
284     length1 = max(3, length1)
285     length2 = max(3, length2)
286     logger.info(('=' * length1) + label + ('=' * length2))
287
288
289 def _print_plugin_label(plugin, node_name):
290     """Print plug-in label.
291
292     Keyword arguments:
293     plugin -- plug-in name
294     node_id -- node ID
295     """
296     _print_label(
297         'Node {0}: Plug-in {1} Test case execution'.format(node_name, plugin))
298
299
300 def _print_final_result_of_plugin(
301         plugin, compute_ids, results, out_plugins, out_plugin):
302     """Print final results of plug-in.
303
304     Keyword arguments:
305     plugin -- plug-in name
306     compute_ids -- list of compute node IDs
307     results -- results list
308     out_plugins -- list of out plug-ins
309     out_plugin -- used out plug-in
310     """
311     print_line = ''
312     for id in compute_ids:
313         if out_plugin == 'Gnocchi':
314             if (id, out_plugin, plugin, True) in results:
315                 print_line += ' PASS   |'
316             elif (id, out_plugin, plugin, False) in results:
317                 print_line += ' FAIL   |'
318             else:
319                 print_line += ' NOT EX |'
320         elif out_plugin == 'AODH':
321             if (id, out_plugin, plugin, True) in results:
322                 print_line += ' PASS   |'
323             elif (id, out_plugin, plugin, False) in results:
324                 print_line += ' FAIL   |'
325             else:
326                 print_line += ' FAIL   |'
327         elif out_plugin == 'SNMP':
328             if (id, out_plugin, plugin, True) in results:
329                 print_line += ' PASS   |'
330             elif (id, out_plugin, plugin, False) in results:
331                 print_line += ' FAIL   |'
332             else:
333                 print_line += ' FAIL   |'
334         elif out_plugin == 'CSV':
335             if (id, out_plugin, plugin, True) in results:
336                 print_line += ' PASS   |'
337             elif (id, out_plugin, plugin, False) in results:
338                 print_line += ' FAIL   |'
339             else:
340                 print_line += ' NOT EX |'
341         else:
342             print_line += ' SKIP   |'
343     return print_line
344
345
346 def print_overall_summary(
347         compute_ids, tested_plugins, aodh_plugins, results, out_plugins):
348     """Print overall summary table.
349
350     Keyword arguments:
351     compute_ids -- list of compute IDs
352     tested_plugins -- list of plug-ins
353     results -- results list
354     out_plugins --  list of used out plug-ins
355     """
356     compute_node_names = ['Node-{}'.format(i) for i in range(
357         len((compute_ids)))]
358     all_computes_in_line = ''
359     for compute in compute_node_names:
360         all_computes_in_line += '| ' + compute + (' ' * (7 - len(compute)))
361     line_of_nodes = '| Test           ' + all_computes_in_line + '|'
362     logger.info('=' * 70)
363     logger.info('+' + ('-' * ((9 * len(compute_node_names))+16)) + '+')
364     logger.info(
365         '|' + ' ' * ((9*len(compute_node_names))/2)
366         + ' OVERALL SUMMARY'
367         + ' ' * (
368             9*len(compute_node_names) - (9*len(compute_node_names))/2)
369         + '|')
370     logger.info(
371         '+' + ('-' * 16) + '+' + (('-' * 8) + '+') * len(compute_node_names))
372     logger.info(line_of_nodes)
373     logger.info(
374         '+' + ('-' * 16) + '+' + (('-' * 8) + '+') * len(compute_node_names))
375     out_plugins_print = []
376     out_plugins_print1 = []
377     for key in out_plugins.keys():
378         if 'Gnocchi' in out_plugins[key]:
379             out_plugins_print1.append('Gnocchi')
380         if 'AODH' in out_plugins[key]:
381             out_plugins_print1.append('AODH')
382         if 'SNMP' in out_plugins[key]:
383             out_plugins_print1.append('SNMP')
384         if 'CSV' in out_plugins[key]:
385             out_plugins_print1.append('CSV')
386     for i in out_plugins_print1:
387         if i not in out_plugins_print:
388             out_plugins_print.append(i)
389     for out_plugin in out_plugins_print:
390         output_plugins_line = ''
391         for id in compute_ids:
392             out_plugin_result = '----'
393             if out_plugin == 'Gnocchi':
394                 out_plugin_result = \
395                     'PASS'
396             elif out_plugin == 'AODH':
397                 out_plugin_result = \
398                     'PASS'
399             elif out_plugin == 'SNMP':
400                 out_plugin_result = \
401                     'PASS'
402             elif out_plugin == 'CSV':
403                 out_plugin_result = \
404                     'PASS' if [
405                         plugin for comp_id, out_pl, plugin, res in results
406                         if comp_id == id and res] else 'FAIL'
407             else:
408                 out_plugin_result = \
409                     'FAIL'
410             output_plugins_line += '| ' + out_plugin_result + '   '
411         logger.info(
412             '| OUT:{}'.format(out_plugin) + (' ' * (11 - len(out_plugin)))
413             + output_plugins_line + '|')
414
415         if out_plugin == 'AODH':
416             for plugin in sorted(aodh_plugins.values()):
417                 line_plugin = _print_final_result_of_plugin(
418                     plugin, compute_ids, results, out_plugins, out_plugin)
419                 logger.info(
420                     '|  IN:{}'.format(plugin) + (' ' * (11-len(plugin)))
421                     + '|' + line_plugin)
422         else:
423             for plugin in sorted(tested_plugins.values()):
424                 line_plugin = _print_final_result_of_plugin(
425                     plugin, compute_ids, results, out_plugins, out_plugin)
426                 logger.info(
427                     '|  IN:{}'.format(plugin) + (' ' * (11-len(plugin)))
428                     + '|' + line_plugin)
429         logger.info(
430             '+' + ('-' * 16) + '+'
431             + (('-' * 8) + '+') * len(compute_node_names))
432     logger.info('=' * 70)
433
434
435 def _exec_testcase(
436         test_labels, name, out_plugin, controllers, compute_node,
437         conf, results, error_plugins, out_plugins):
438     """Execute the testcase.
439
440     Keyword arguments:
441     test_labels -- dictionary of plug-in IDs and their display names
442     name -- plug-in ID, key of test_labels dictionary
443     ceilometer_running -- boolean indicating whether Ceilometer is running
444     compute_node -- compute node ID
445     conf -- ConfigServer instance
446     results -- results list
447     error_plugins -- list of tuples with plug-in errors
448         (plugin, error_description, is_critical):
449         plugin -- plug-in ID, key of test_labels dictionary
450         error_decription -- description of the error
451         is_critical -- boolean value indicating whether error is critical
452     """
453     ovs_interfaces = conf.get_ovs_interfaces(compute_node)
454     ovs_configured_interfaces = conf.get_plugin_config_values(
455         compute_node, 'ovs_events', 'Interfaces')
456     ovs_configured_bridges = conf.get_plugin_config_values(
457          compute_node, 'ovs_stats', 'Bridges')
458     ovs_existing_configured_int = [
459         interface for interface in ovs_interfaces
460         if interface in ovs_configured_interfaces]
461     ovs_existing_configured_bridges = [
462         bridge for bridge in ovs_interfaces
463         if bridge in ovs_configured_bridges]
464     plugin_prerequisites = {
465         'mcelog': [(
466             conf.is_mcelog_installed(compute_node, 'mcelog'),
467             'mcelog must be installed.')],
468         'ovs_events': [(
469             len(ovs_existing_configured_int) > 0 or len(ovs_interfaces) > 0,
470             'Interfaces must be configured.')],
471         'ovs_stats': [(
472             len(ovs_existing_configured_bridges) > 0,
473             'Bridges must be configured.')]}
474     gnocchi_criteria_lists = {
475         'hugepages': 'hugepages',
476         'intel_rdt': 'rdt',
477         'mcelog': 'mcelog',
478         'ovs_events': 'interface-ovs-system',
479         'ovs_stats': 'ovs_stats-br0.br0'}
480     aodh_criteria_lists = {
481         'mcelog': 'mcelog',
482         'ovs_events': 'ovs_events'}
483     snmp_mib_files = {
484         'intel_rdt': '/usr/share/snmp/mibs/Intel-Rdt.txt',
485         'hugepages': '/usr/share/snmp/mibs/Intel-Hugepages.txt',
486         'mcelog': '/usr/share/snmp/mibs/Intel-Mcelog.txt'}
487     snmp_mib_strings = {
488         'intel_rdt': 'INTEL-RDT-MIB::rdtLlc.1',
489         'hugepages': 'INTEL-HUGEPAGES-MIB::hugepagesPageFree',
490         'mcelog': 'INTEL-MCELOG-MIB::memoryCorrectedErrors.1'}
491     nr_hugepages = int(time.time()) % 10000
492     snmp_in_commands = {
493         'intel_rdt': None,
494         'hugepages': 'echo {} > /sys/kernel/'.format(nr_hugepages)
495                      + 'mm/hugepages/hugepages-2048kB/nr_hugepages',
496         'mcelog': '/root/mce-inject_df < /root/corrected'}
497     csv_subdirs = {
498         'intel_rdt': [
499             'intel_rdt-0-2'],
500         'hugepages': [
501             'hugepages-mm-2048Kb', 'hugepages-node0-2048Kb',
502             'hugepages-node1-2048Kb'],
503         # 'ipmi': ['ipmi'],
504         'mcelog': [
505             'mcelog-SOCKET_0_CHANNEL_0_DIMM_any',
506             'mcelog-SOCKET_0_CHANNEL_any_DIMM_any'],
507         'ovs_stats': [
508             'ovs_stats-br0.br0'],
509         'ovs_events': [
510             'ovs_events-br0']}
511     # csv_meter_categories_ipmi = get_csv_categories_for_ipmi(conf,
512     # compute_node)
513     csv_meter_categories = {
514         'intel_rdt': [
515             'bytes-llc', 'ipc'],
516         'hugepages': ['vmpage_number-free', 'vmpage_number-used'],
517         # 'ipmi': csv_meter_categories_ipmi,
518         'mcelog': [
519             'errors-corrected_memory_errors',
520             'errors-uncorrected_memory_errors'],
521         'ovs_stats': [
522             'if_dropped', 'if_errors', 'if_packets'],
523         'ovs_events': ['gauge-link_status']}
524
525     _print_plugin_label(
526         test_labels[name] if name in test_labels else name,
527         compute_node.get_name())
528     plugin_critical_errors = [
529         error for plugin, error, critical in error_plugins
530         if plugin == name and critical]
531     if plugin_critical_errors:
532         logger.error('Following critical errors occurred:'.format(name))
533         for error in plugin_critical_errors:
534             logger.error(' * ' + error)
535         _process_result(
536             compute_node.get_id(), out_plugin, test_labels[name], False,
537             results)
538     else:
539         plugin_errors = [
540             error for plugin, error, critical in error_plugins
541             if plugin == name and not critical]
542         if plugin_errors:
543             logger.warning('Following non-critical errors occured:')
544             for error in plugin_errors:
545                 logger.warning(' * ' + error)
546         failed_prerequisites = []
547         if name in plugin_prerequisites:
548             failed_prerequisites = [
549                 prerequisite_name for prerequisite_passed,
550                 prerequisite_name in plugin_prerequisites[name]
551                 if not prerequisite_passed]
552         if failed_prerequisites:
553             logger.error(
554                 '{} test will not be executed, '.format(name)
555                 + 'following prerequisites failed:')
556             for prerequisite in failed_prerequisites:
557                 logger.error(' * {}'.format(prerequisite))
558         else:
559             plugin_interval = conf.get_plugin_interval(compute_node, name)
560             if out_plugin == 'Gnocchi':
561                 res = conf.test_plugins_with_gnocchi(
562                     compute_node.get_name(), plugin_interval,
563                     logger, criteria_list=gnocchi_criteria_lists[name])
564             if out_plugin == 'AODH':
565                 res = conf.test_plugins_with_aodh(
566                     compute_node.get_name(), plugin_interval,
567                     logger, criteria_list=aodh_criteria_lists[name])
568             if out_plugin == 'SNMP':
569                 res = \
570                     name in snmp_mib_files and name in snmp_mib_strings \
571                     and conf.test_plugins_with_snmp(
572                         compute_node.get_name(), plugin_interval, logger, name,
573                         snmp_mib_files[name], snmp_mib_strings[name],
574                         snmp_in_commands[name])
575             if out_plugin == 'CSV':
576                 res = tests.test_csv_handles_plugin_data(
577                     compute_node, conf.get_plugin_interval(compute_node, name),
578                     name, csv_subdirs[name], csv_meter_categories[name],
579                     logger, CSVClient(conf))
580
581             if res and plugin_errors:
582                 logger.info(
583                     'Test works, but will be reported as failure,'
584                     + 'because of non-critical errors.')
585                 res = False
586             _process_result(
587                 compute_node.get_id(), out_plugin, test_labels[name],
588                 res, results)
589
590
591 def get_results_for_ovs_events(
592         plugin_labels, plugin_name, gnocchi_running,
593         compute_node, conf, results, error_plugins):
594     """ Testing OVS Events with python plugin
595     """
596     plugin_label = 'OVS events'
597     res = conf.enable_ovs_events(
598         compute_node, plugin_label, error_plugins, create_backup=False)
599     _process_result(
600         compute_node.get_id(), plugin_label, res, results)
601     logger.info("Results for OVS Events = {}" .format(results))
602
603
604 def create_ovs_bridge():
605     """Create OVS brides on compute nodes"""
606     handler = factory.Factory.get_handler('apex',
607                                           APEX_IP,
608                                           APEX_USER_STACK,
609                                           APEX_PKEY)
610     nodes = handler.get_nodes()
611     logger.info("Creating OVS bridges on computes nodes")
612     for node in nodes:
613         if node.is_compute():
614             node.run_cmd('sudo ovs-vsctl add-br br0')
615             node.run_cmd('sudo ovs-vsctl set-manager ptcp:6640')
616     logger.info('OVS Bridges created on compute nodes')
617
618
619 def mcelog_install():
620     """Install mcelog on compute nodes."""
621     _print_label('Enabling mcelog and OVS bridges on compute nodes')
622     handler = factory.Factory.get_handler('apex',
623                                           APEX_IP,
624                                           APEX_USER_STACK,
625                                           APEX_PKEY)
626     nodes = handler.get_nodes()
627     for node in nodes:
628         if node.is_compute():
629             centos_release = node.run_cmd('uname -r')
630             if '3.10.0-514.26.2.el7.x86_64' not in centos_release:
631                 logger.info(
632                     'Mcelog will not be enabled '
633                     + 'on node-{0}, '.format(node.get_dict()['name'])
634                     + 'unsupported CentOS release found ({1}).'.format(
635                         centos_release))
636             else:
637                 logger.info(
638                     'Checking if  mcelog is enabled'
639                     + ' on node-{}...'.format(node.get_dict()['name']))
640                 res = node.run_cmd('ls')
641             if 'mce-inject_ea' and 'corrected' in res:
642                 logger.info(
643                     'Mcelog seems to be already installed '
644                     + 'on node-{}.'.format(node.get_dict()['name']))
645                 node.run_cmd('sudo modprobe mce-inject')
646                 node.run_cmd('sudo ./mce-inject_ea < corrected')
647             else:
648                 logger.info(
649                     'Mcelog will be enabled on node-{}...'.format(
650                         node.get_dict()['id']))
651                 node.put_file(
652                     'PATH/'
653                     + 'mce-inject_ea', 'mce-inject_ea')
654                 node.run_cmd('chmod a+x mce-inject_ea')
655                 node.run_cmd('echo "CPU 0 BANK 0" > corrected')
656                 node.run_cmd(
657                     'echo "STATUS 0xcc00008000010090" >>'
658                     + ' corrected')
659                 node.run_cmd(
660                     'echo "ADDR 0x0010FFFFFFF" >> corrected')
661                 node.run_cmd('sudo modprobe mce-inject')
662                 node.run_cmd('sudo ./mce-inject_ea < corrected')
663     logger.info('Mcelog is installed on all compute nodes')
664
665
666 def mcelog_delete():
667     """Uninstall mcelog from compute nodes."""
668     handler = factory.Factory.get_handler(
669             'apex', APEX_IP, APEX_USER, APEX_PKEY)
670     nodes = handler.get_nodes()
671     for node in nodes:
672         if node.is_compute():
673             output = node.run_cmd('ls')
674             if 'mce-inject_ea' in output:
675                 node.run_cmd('rm mce-inject_ea')
676             if 'corrected' in output:
677                 node.run_cmd('rm corrected')
678             node.run_cmd('sudo systemctl restart mcelog')
679     logger.info('Mcelog is deleted from all compute nodes')
680
681
682 def get_ssh_keys():
683     if not os.path.isdir(ID_RSA_DST_DIR):
684         os.makedirs(ID_RSA_DST_DIR)
685     if not os.path.isfile(ID_RSA_DST):
686         logger.info(
687             "RSA key file {} doesn't exist".format(ID_RSA_DST)
688             + ", it will be downloaded from installer node.")
689         handler = factory.Factory.get_handler(
690             'apex', APEX_IP, APEX_USER, APEX_PKEY)
691         apex = handler.get_installer_node()
692         apex.get_file(ID_RSA_SRC, ID_RSA_DST)
693     else:
694         logger.info("RSA key file {} exists.".format(ID_RSA_DST))
695
696
697 def _check_logger():
698     """Check whether there is global logger available and if not, define one."""
699     if 'logger' not in globals():
700         global logger
701         logger = logger.Logger("barometercollectd").getLogger()
702
703
704 def main(bt_logger=None):
705     """Check each compute node sends gnocchi metrics.
706
707     Keyword arguments:
708     bt_logger -- logger instance
709     """
710     logging.getLogger("paramiko").setLevel(logging.WARNING)
711     logging.getLogger("stevedore").setLevel(logging.WARNING)
712     logging.getLogger("opnfv.deployment.manager").setLevel(logging.WARNING)
713     if bt_logger is None:
714         _check_logger()
715     else:
716         global logger
717         logger = bt_logger
718     _print_label("Starting barometer tests suite")
719     get_ssh_keys()
720     conf = config_server.ConfigServer(APEX_IP, APEX_USER, logger)
721     controllers = conf.get_controllers()
722     if len(controllers) == 0:
723         logger.error('No controller nodes found!')
724         return 1
725     computes = conf.get_computes()
726     if len(computes) == 0:
727         logger.error('No compute nodes found!')
728         return 1
729
730     _print_label(
731         'Display of Control and Compute nodes available in the set up')
732     logger.info('controllers: {}'.format([('{0}: {1}'.format(
733         node.get_name(), node.get_ip())) for node in controllers]))
734     logger.info('computes: {}'.format([('{0}: {1}'.format(
735         node.get_name(), node.get_ip())) for node in computes]))
736
737     mcelog_install()
738     create_ovs_bridge()
739     gnocchi_running_on_con = False
740     aodh_running_on_con = False
741     snmp_running = True
742     _print_label('Testing Gnocchi, AODH and SNMP on nodes')
743
744     for controller in controllers:
745         gnocchi_running = (
746             gnocchi_running_on_con or conf.is_gnocchi_running(controller))
747         aodh_running = (
748             aodh_running_on_con or conf.is_aodh_running(controller))
749
750     compute_ids = []
751     compute_node_names = []
752     results = []
753     plugin_labels = {
754         'intel_rdt': 'Intel RDT',
755         'hugepages': 'Hugepages',
756         # 'ipmi': 'IPMI',
757         'mcelog': 'Mcelog',
758         'ovs_stats': 'OVS stats',
759         'ovs_events': 'OVS events'}
760     aodh_plugin_labels = {
761         'mcelog': 'Mcelog',
762         'ovs_events': 'OVS events'}
763     out_plugins = {}
764     for compute_node in computes:
765         node_id = compute_node.get_id()
766         node_name = compute_node.get_name()
767         out_plugins[node_id] = []
768         compute_ids.append(node_id)
769         compute_node_names.append(node_name)
770         plugins_to_enable = []
771         error_plugins = []
772         gnocchi_running = (
773             gnocchi_running and conf.check_gnocchi_plugin_included(
774                 compute_node))
775         aodh_running = (
776             aodh_running and conf.check_aodh_plugin_included(compute_node))
777         logger.info("SNMP enabled on {}" .format(node_name))
778         if gnocchi_running:
779             out_plugins[node_id].append("Gnocchi")
780         if aodh_running:
781             out_plugins[node_id].append("AODH")
782         if snmp_running:
783             out_plugins[node_id].append("SNMP")
784
785         if 'Gnocchi' in out_plugins[node_id]:
786             logger.info("CSV will be enabled for verification")
787             plugins_to_enable.append('csv')
788             out_plugins[node_id].append("CSV")
789             if plugins_to_enable:
790                 _print_label(
791                     'NODE {}: Enabling Test Plug-in '.format(node_name)
792                     + 'and Test case execution')
793             if plugins_to_enable and not conf.enable_plugins(
794                     compute_node, plugins_to_enable, error_plugins,
795                     create_backup=False):
796                 logger.error(
797                     'Failed to test plugins on node {}.'.format(node_id))
798                 logger.info(
799                     'Testcases on node {} will not be executed'.format(
800                         node_id))
801             else:
802                 if plugins_to_enable:
803                     collectd_restarted, collectd_warnings = \
804                         conf.restart_collectd(compute_node)
805                     sleep_time = 10
806                     logger.info(
807                         'Sleeping for {} seconds'.format(sleep_time)
808                         + ' after collectd restart...')
809                     time.sleep(sleep_time)
810                 if plugins_to_enable and not collectd_restarted:
811                     for warning in collectd_warnings:
812                         logger.warning(warning)
813                     logger.error(
814                         'Restart of collectd on node {} failed'.format(
815                             node_id))
816                     logger.info(
817                         'Testcases on node {}'.format(node_id)
818                         + ' will not be executed.')
819                 else:
820                     if collectd_warnings:
821                         for warning in collectd_warnings:
822                             logger.warning(warning)
823
824         for i in out_plugins[node_id]:
825             if i == 'AODH':
826                 for plugin_name in sorted(aodh_plugin_labels.keys()):
827                     _exec_testcase(
828                         aodh_plugin_labels, plugin_name, i,
829                         controllers, compute_node, conf, results,
830                         error_plugins, out_plugins[node_id])
831             else:
832                 for plugin_name in sorted(plugin_labels.keys()):
833                     _exec_testcase(
834                         plugin_labels, plugin_name, i,
835                         controllers, compute_node, conf, results,
836                         error_plugins, out_plugins[node_id])
837
838     mcelog_delete()
839     print_overall_summary(
840         compute_ids, plugin_labels, aodh_plugin_labels, results, out_plugins)
841
842     if ((len([res for res in results if not res[2]]) > 0)
843             or (len(results) < len(computes) * len(plugin_labels))):
844         logger.error('Some tests have failed or have not been executed')
845         return 1
846     return 0
847
848
849 if __name__ == '__main__':
850     sys.exit(main())