Adding improvements to the log messages
[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 # Patch on October 10 2017
15
16 """Executing test of plugins"""
17
18 import requests
19 from keystoneclient.v3 import client
20 import os
21 import sys
22 import time
23 import logging
24 import config_server
25 import tests
26 from opnfv.deployment import factory
27
28 AODH_NAME = 'aodh'
29 GNOCCHI_NAME = 'gnocchi'
30 ID_RSA_SRC = '/root/.ssh/id_rsa'
31 ID_RSA_DST_DIR = '/root/.ssh'
32 ID_RSA_DST = ID_RSA_DST_DIR + '/id_rsa'
33 APEX_IP = os.getenv("INSTALLER_IP").rstrip('\n')
34 APEX_USER = 'root'
35 APEX_USER_STACK = 'stack'
36 APEX_PKEY = '/root/.ssh/id_rsa'
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}/{1}/{2}-{3}".format(
215                                 hostname, plugin_subdir,
216                                 meter_category, date))
217                         # Storing last two values
218                         values = stdout1
219                         values2 = stdout2
220                         if values is None:
221                             logger.error(
222                                 'Getting last two CSV entries of meter category'
223                                 + ' {0} in {1} subdir failed'.format(
224                                     meter_category, plugin_subdir))
225                         elif values2 is None:
226                             logger.error(
227                                 'Getting last CSV entries of meter category'
228                                 + ' {0} in {1} subdir failed'.format(
229                                     meter_category, plugin_subdir))
230                         else:
231                             values = values.split(',')
232                             old_value = float(values[0])
233                             values2 = values2.split(',')
234                             new_value = float(values2[0])
235                             metrics.append((
236                                 plugin_subdir, meter_category, old_value,
237                                 new_value))
238         return metrics
239
240
241 def get_csv_categories_for_ipmi(conf, compute_node):
242     """Get CSV metrics.
243
244     Keyword arguments:
245     compute_node -- compute node instance
246
247     Return list of categories.
248     """
249     stdout = conf.execute_command(
250         "date '+%Y-%m-%d'", compute_node.get_ip())
251     date = stdout[0].strip()
252     categories = conf.execute_command(
253         "ls /var/lib/collectd/csv/{0}.jf.intel.com/ipmi | grep {1}".format(
254             compute_node.get_name(), date), compute_node.get_ip())
255     return [category.strip()[:-11] for category in categories]
256
257
258 def _process_result(compute_node, out_plugin, test, result, results_list, node):
259     """Print test result and append it to results list.
260
261     Keyword arguments:
262     test -- testcase name
263     result -- boolean test result
264     results_list -- results list
265     """
266     if result:
267         logger.info(
268             'Test case for {0} with {1} PASSED on {2}.'.format(
269                 node, out_plugin, test))
270     else:
271         logger.error(
272             'Test case for {0} with {1} FAILED on {2}.'.format(
273                 node, out_plugin, test))
274     results_list.append((compute_node, out_plugin, test, result))
275
276
277 def _print_label(label):
278     """Print label on the screen
279
280     Keyword arguments:
281     label -- label string
282     """
283     label = label.strip()
284     length = 70
285     if label != '':
286         label = ' ' + label + ' '
287     length_label = len(label)
288     length1 = (length - length_label) / 2
289     length2 = length - length_label - length1
290     length1 = max(3, length1)
291     length2 = max(3, length2)
292     logger.info(('=' * length1) + label + ('=' * length2))
293
294
295 def _print_plugin_label(plugin, node_name):
296     """Print plug-in label.
297
298     Keyword arguments:
299     plugin -- plug-in name
300     node_id -- node ID
301     """
302     _print_label(
303         'Node {0}: Plug-in {1} Test case execution'.format(node_name, plugin))
304
305
306 def _print_final_result_of_plugin(
307         plugin, compute_ids, results, out_plugins, out_plugin):
308     """Print final results of plug-in.
309
310     Keyword arguments:
311     plugin -- plug-in name
312     compute_ids -- list of compute node IDs
313     results -- results list
314     out_plugins -- list of out plug-ins
315     out_plugin -- used out plug-in
316     """
317     print_line = ''
318     for id in compute_ids:
319         if out_plugin == 'Gnocchi':
320             if (id, out_plugin, plugin, True) in results:
321                 print_line += ' PASS   |'
322             elif (id, out_plugin, plugin, False) in results:
323                 print_line += ' FAIL   |'
324             else:
325                 print_line += ' NOT EX |'
326         elif out_plugin == 'AODH':
327             if (id, out_plugin, plugin, True) in results:
328                 print_line += ' PASS   |'
329             elif (id, out_plugin, plugin, False) in results:
330                 print_line += ' FAIL   |'
331             else:
332                 print_line += ' FAIL   |'
333         elif out_plugin == 'SNMP':
334             if (id, out_plugin, plugin, True) in results:
335                 print_line += ' PASS   |'
336             elif (id, out_plugin, plugin, False) in results:
337                 print_line += ' FAIL   |'
338             else:
339                 print_line += ' FAIL   |'
340         elif out_plugin == 'CSV':
341             if (id, out_plugin, plugin, True) in results:
342                 print_line += ' PASS   |'
343             elif (id, out_plugin, plugin, False) in results:
344                 print_line += ' FAIL   |'
345             else:
346                 print_line += ' NOT EX |'
347         else:
348             print_line += ' SKIP   |'
349     return print_line
350
351
352 def print_overall_summary(
353         compute_ids, tested_plugins, aodh_plugins, results, out_plugins):
354     """Print overall summary table.
355
356     Keyword arguments:
357     compute_ids -- list of compute IDs
358     tested_plugins -- list of plug-ins
359     results -- results list
360     out_plugins --  list of used out plug-ins
361     """
362     compute_node_names = ['Node-{}'.format(i) for i in range(
363         len((compute_ids)))]
364     all_computes_in_line = ''
365     for compute in compute_node_names:
366         all_computes_in_line += '| ' + compute + (' ' * (7 - len(compute)))
367     line_of_nodes = '| Test           ' + all_computes_in_line + '|'
368     logger.info('=' * 70)
369     logger.info('+' + ('-' * ((9 * len(compute_node_names))+16)) + '+')
370     logger.info(
371         '|' + ' ' * ((9*len(compute_node_names))/2)
372         + ' OVERALL SUMMARY'
373         + ' ' * (
374             9*len(compute_node_names) - (9*len(compute_node_names))/2)
375         + '|')
376     logger.info(
377         '+' + ('-' * 16) + '+' + (('-' * 8) + '+') * len(compute_node_names))
378     logger.info(line_of_nodes)
379     logger.info(
380         '+' + ('-' * 16) + '+' + (('-' * 8) + '+') * len(compute_node_names))
381     out_plugins_print = []
382     out_plugins_print1 = []
383     for key in out_plugins.keys():
384         if 'Gnocchi' in out_plugins[key]:
385             out_plugins_print1.append('Gnocchi')
386         if 'AODH' in out_plugins[key]:
387             out_plugins_print1.append('AODH')
388         if 'SNMP' in out_plugins[key]:
389             out_plugins_print1.append('SNMP')
390         if 'CSV' in out_plugins[key]:
391             out_plugins_print1.append('CSV')
392     for i in out_plugins_print1:
393         if i not in out_plugins_print:
394             out_plugins_print.append(i)
395     for out_plugin in out_plugins_print:
396         output_plugins_line = ''
397         for id in compute_ids:
398             out_plugin_result = '----'
399             if out_plugin == 'Gnocchi':
400                 out_plugin_result = \
401                     'PASS'
402             elif out_plugin == 'AODH':
403                 out_plugin_result = \
404                     'PASS'
405             elif out_plugin == 'SNMP':
406                 out_plugin_result = \
407                     'PASS'
408             elif out_plugin == 'CSV':
409                 out_plugin_result = \
410                     'PASS' if [
411                         plugin for comp_id, out_pl, plugin, res in results
412                         if comp_id == id and res] else 'FAIL'
413             else:
414                 out_plugin_result = \
415                     'FAIL'
416             output_plugins_line += '| ' + out_plugin_result + '   '
417         logger.info(
418             '| OUT:{}'.format(out_plugin) + (' ' * (11 - len(out_plugin)))
419             + output_plugins_line + '|')
420
421         if out_plugin == 'AODH':
422             for plugin in sorted(aodh_plugins.values()):
423                 line_plugin = _print_final_result_of_plugin(
424                     plugin, compute_ids, results, out_plugins, out_plugin)
425                 logger.info(
426                     '|  IN:{}'.format(plugin) + (' ' * (11-len(plugin)))
427                     + '|' + line_plugin)
428         else:
429             for plugin in sorted(tested_plugins.values()):
430                 line_plugin = _print_final_result_of_plugin(
431                     plugin, compute_ids, results, out_plugins, out_plugin)
432                 logger.info(
433                     '|  IN:{}'.format(plugin) + (' ' * (11-len(plugin)))
434                     + '|' + line_plugin)
435         logger.info(
436             '+' + ('-' * 16) + '+'
437             + (('-' * 8) + '+') * len(compute_node_names))
438     logger.info('=' * 70)
439
440
441 def _exec_testcase(
442         test_labels, name, out_plugin, controllers, compute_node,
443         conf, results, error_plugins, out_plugins):
444     """Execute the testcase.
445
446     Keyword arguments:
447     test_labels -- dictionary of plug-in IDs and their display names
448     name -- plug-in ID, key of test_labels dictionary
449     ceilometer_running -- boolean indicating whether Ceilometer is running
450     compute_node -- compute node ID
451     conf -- ConfigServer instance
452     results -- results list
453     error_plugins -- list of tuples with plug-in errors
454         (plugin, error_description, is_critical):
455         plugin -- plug-in ID, key of test_labels dictionary
456         error_decription -- description of the error
457         is_critical -- boolean value indicating whether error is critical
458     """
459     ovs_interfaces = conf.get_ovs_interfaces(compute_node)
460     ovs_configured_interfaces = conf.get_plugin_config_values(
461         compute_node, 'ovs_events', 'Interfaces')
462     ovs_configured_bridges = conf.get_plugin_config_values(
463          compute_node, 'ovs_stats', 'Bridges')
464     ovs_existing_configured_int = [
465         interface for interface in ovs_interfaces
466         if interface in ovs_configured_interfaces]
467     ovs_existing_configured_bridges = [
468         bridge for bridge in ovs_interfaces
469         if bridge in ovs_configured_bridges]
470     plugin_prerequisites = {
471         'mcelog': [(
472             conf.is_mcelog_installed(compute_node, 'mcelog'),
473             'mcelog must be installed.')],
474         'ovs_events': [(
475             len(ovs_existing_configured_int) > 0 or len(ovs_interfaces) > 0,
476             'Interfaces must be configured.')],
477         'ovs_stats': [(
478             len(ovs_existing_configured_bridges) > 0,
479             'Bridges must be configured.')]}
480     gnocchi_criteria_lists = {
481         'hugepages': 'hugepages',
482         'intel_rdt': 'rdt',
483         'mcelog': 'mcelog',
484         'ovs_events': 'interface-ovs-system',
485         'ovs_stats': 'ovs_stats-br0.br0'}
486     aodh_criteria_lists = {
487         'mcelog': 'mcelog',
488         'ovs_events': 'ovs_events'}
489     snmp_mib_files = {
490         'intel_rdt': '/usr/share/snmp/mibs/Intel-Rdt.txt',
491         'hugepages': '/usr/share/snmp/mibs/Intel-Hugepages.txt',
492         'mcelog': '/usr/share/snmp/mibs/Intel-Mcelog.txt'}
493     snmp_mib_strings = {
494         'intel_rdt': 'INTEL-RDT-MIB::rdtLlc.1',
495         'hugepages': 'INTEL-HUGEPAGES-MIB::hugepagesPageFree',
496         'mcelog': 'INTEL-MCELOG-MIB::memoryCorrectedErrors.1'}
497     nr_hugepages = int(time.time()) % 10000
498     snmp_in_commands = {
499         'intel_rdt': None,
500         'hugepages': 'echo {} > /sys/kernel/'.format(nr_hugepages)
501                      + 'mm/hugepages/hugepages-2048kB/nr_hugepages',
502         'mcelog': '/root/mce-inject_df < /root/corrected'}
503     csv_subdirs = {
504         'intel_rdt': [
505             'intel_rdt-0-2'],
506         'hugepages': [
507             'hugepages-mm-2048Kb', 'hugepages-node0-2048Kb',
508             'hugepages-node1-2048Kb'],
509         # 'ipmi': ['ipmi'],
510         'mcelog': [
511             'mcelog-SOCKET_0_CHANNEL_0_DIMM_any',
512             'mcelog-SOCKET_0_CHANNEL_any_DIMM_any'],
513         'ovs_stats': [
514             'ovs_stats-br0.br0'],
515         'ovs_events': [
516             'ovs_events-br0']}
517     # csv_meter_categories_ipmi = get_csv_categories_for_ipmi(conf,
518     # compute_node)
519     csv_meter_categories = {
520         'intel_rdt': [
521             'bytes-llc', 'ipc'],
522         'hugepages': ['vmpage_number-free', 'vmpage_number-used'],
523         # 'ipmi': csv_meter_categories_ipmi,
524         'mcelog': [
525             'errors-corrected_memory_errors',
526             'errors-uncorrected_memory_errors'],
527         'ovs_stats': [
528             'if_dropped', 'if_errors', 'if_packets'],
529         'ovs_events': ['gauge-link_status']}
530
531     _print_plugin_label(
532         test_labels[name] if name in test_labels else name,
533         compute_node.get_name())
534     plugin_critical_errors = [
535         error for plugin, error, critical in error_plugins
536         if plugin == name and critical]
537     if plugin_critical_errors:
538         logger.error('Following critical errors occurred:'.format(name))
539         for error in plugin_critical_errors:
540             logger.error(' * ' + error)
541         _process_result(
542             compute_node.get_id(), out_plugin, test_labels[name], False,
543             results, compute_node.get_name())
544     else:
545         plugin_errors = [
546             error for plugin, error, critical in error_plugins
547             if plugin == name and not critical]
548         if plugin_errors:
549             logger.warning('Following non-critical errors occured:')
550             for error in plugin_errors:
551                 logger.warning(' * ' + error)
552         failed_prerequisites = []
553         if name in plugin_prerequisites:
554             failed_prerequisites = [
555                 prerequisite_name for prerequisite_passed,
556                 prerequisite_name in plugin_prerequisites[name]
557                 if not prerequisite_passed]
558         if failed_prerequisites:
559             logger.error(
560                 '{} test will not be executed, '.format(name)
561                 + 'following prerequisites failed:')
562             for prerequisite in failed_prerequisites:
563                 logger.error(' * {}'.format(prerequisite))
564         else:
565             plugin_interval = conf.get_plugin_interval(compute_node, name)
566             if out_plugin == 'Gnocchi':
567                 res = conf.test_plugins_with_gnocchi(
568                     compute_node.get_name(), plugin_interval,
569                     logger, criteria_list=gnocchi_criteria_lists[name])
570             if out_plugin == 'AODH':
571                 res = conf.test_plugins_with_aodh(
572                     compute_node.get_name(), plugin_interval,
573                     logger, criteria_list=aodh_criteria_lists[name])
574             if out_plugin == 'SNMP':
575                 res = \
576                     name in snmp_mib_files and name in snmp_mib_strings \
577                     and conf.test_plugins_with_snmp(
578                         compute_node.get_name(), plugin_interval, logger, name,
579                         snmp_mib_files[name], snmp_mib_strings[name],
580                         snmp_in_commands[name])
581             if out_plugin == 'CSV':
582                 res = tests.test_csv_handles_plugin_data(
583                     compute_node, conf.get_plugin_interval(compute_node, name),
584                     name, csv_subdirs[name], csv_meter_categories[name],
585                     logger, CSVClient(conf))
586
587             if res and plugin_errors:
588                 logger.info(
589                     'Test works, but will be reported as failure,'
590                     + 'because of non-critical errors.')
591                 res = False
592             _process_result(
593                 compute_node.get_id(), out_plugin, test_labels[name],
594                 res, results, compute_node.get_name())
595
596
597 def get_results_for_ovs_events(
598         plugin_labels, plugin_name, gnocchi_running,
599         compute_node, conf, results, error_plugins):
600     """ Testing OVS Events with python plugin
601     """
602     plugin_label = 'OVS events'
603     res = conf.enable_ovs_events(
604         compute_node, plugin_label, error_plugins, create_backup=False)
605     _process_result(
606         compute_node.get_id(), plugin_label, res, results)
607     logger.info("Results for OVS Events = {}" .format(results))
608
609
610 def create_ovs_bridge():
611     """Create OVS brides on compute nodes"""
612     handler = factory.Factory.get_handler('apex',
613                                           APEX_IP,
614                                           APEX_USER_STACK,
615                                           APEX_PKEY)
616     nodes = handler.get_nodes()
617     logger.info("Creating OVS bridges on computes nodes")
618     for node in nodes:
619         if node.is_compute():
620             node.run_cmd('sudo ovs-vsctl add-br br0')
621             node.run_cmd('sudo ovs-vsctl set-manager ptcp:6640')
622     logger.info('OVS Bridges created on compute nodes')
623
624
625 def mcelog_install():
626     """Install mcelog on compute nodes."""
627     _print_label('Enabling mcelog and OVS bridges on compute nodes')
628     handler = factory.Factory.get_handler('apex',
629                                           APEX_IP,
630                                           APEX_USER_STACK,
631                                           APEX_PKEY)
632     nodes = handler.get_nodes()
633     mce_bin = os.path.dirname(os.path.realpath(__file__)) + '/mce-inject_ea'
634     for node in nodes:
635         if node.is_compute():
636             centos_release = node.run_cmd('uname -r')
637             if '3.10.0-514.26.2.el7.x86_64' not in centos_release:
638                 logger.info(
639                     'Mcelog will not be enabled '
640                     + 'on node-{0}, '.format(node.get_dict()['name'])
641                     + 'unsupported CentOS release found ({1}).'.format(
642                         centos_release))
643             else:
644                 logger.info(
645                     'Checking if  mcelog is enabled'
646                     + ' on node-{}...'.format(node.get_dict()['name']))
647                 res = node.run_cmd('ls')
648             if 'mce-inject_ea' and 'corrected' in res:
649                 logger.info(
650                     'Mcelog seems to be already installed '
651                     + 'on node-{}.'.format(node.get_dict()['name']))
652                 node.run_cmd('sudo modprobe mce-inject')
653                 node.run_cmd('sudo ./mce-inject_ea < corrected')
654             else:
655                 logger.info(
656                     'Mcelog will be enabled on node-{}...'.format(
657                         node.get_dict()['id']))
658                 node.put_file(mce_bin, 'mce-inject_ea')
659                 node.run_cmd('chmod a+x mce-inject_ea')
660                 node.run_cmd('echo "CPU 0 BANK 0" > corrected')
661                 node.run_cmd(
662                     'echo "STATUS 0xcc00008000010090" >>'
663                     + ' corrected')
664                 node.run_cmd(
665                     'echo "ADDR 0x0010FFFFFFF" >> corrected')
666                 node.run_cmd('sudo modprobe mce-inject')
667                 node.run_cmd('sudo ./mce-inject_ea < corrected')
668     logger.info('Mcelog is installed on all compute nodes')
669
670
671 def mcelog_delete():
672     """Uninstall mcelog from compute nodes."""
673     handler = factory.Factory.get_handler(
674             'apex', APEX_IP, APEX_USER, APEX_PKEY)
675     nodes = handler.get_nodes()
676     for node in nodes:
677         if node.is_compute():
678             output = node.run_cmd('ls')
679             if 'mce-inject_ea' in output:
680                 node.run_cmd('rm mce-inject_ea')
681             if 'corrected' in output:
682                 node.run_cmd('rm corrected')
683             node.run_cmd('sudo systemctl restart mcelog')
684     logger.info('Mcelog is deleted from all compute nodes')
685
686
687 def get_ssh_keys():
688     if not os.path.isdir(ID_RSA_DST_DIR):
689         os.makedirs(ID_RSA_DST_DIR)
690     if not os.path.isfile(ID_RSA_DST):
691         logger.info(
692             "RSA key file {} doesn't exist".format(ID_RSA_DST)
693             + ", it will be downloaded from installer node.")
694         handler = factory.Factory.get_handler(
695             'apex', APEX_IP, APEX_USER, APEX_PKEY)
696         apex = handler.get_installer_node()
697         apex.get_file(ID_RSA_SRC, ID_RSA_DST)
698     else:
699         logger.info("RSA key file {} exists.".format(ID_RSA_DST))
700
701
702 def _check_logger():
703     """Check whether there is global logger available and if not, define one."""
704     if 'logger' not in globals():
705         global logger
706         logger = logger.Logger("barometercollectd").getLogger()
707
708
709 def main(bt_logger=None):
710     """Check each compute node sends gnocchi metrics.
711
712     Keyword arguments:
713     bt_logger -- logger instance
714     """
715     logging.getLogger("paramiko").setLevel(logging.WARNING)
716     logging.getLogger("stevedore").setLevel(logging.WARNING)
717     logging.getLogger("opnfv.deployment.manager").setLevel(logging.WARNING)
718     if bt_logger is None:
719         _check_logger()
720     else:
721         global logger
722         logger = bt_logger
723     _print_label("Starting barometer tests suite")
724     get_ssh_keys()
725     conf = config_server.ConfigServer(APEX_IP, APEX_USER, logger)
726     controllers = conf.get_controllers()
727     if len(controllers) == 0:
728         logger.error('No controller nodes found!')
729         return 1
730     computes = conf.get_computes()
731     if len(computes) == 0:
732         logger.error('No compute nodes found!')
733         return 1
734
735     _print_label(
736         'Display of Control and Compute nodes available in the set up')
737     logger.info('controllers: {}'.format([('{0}: {1}'.format(
738         node.get_name(), node.get_ip())) for node in controllers]))
739     logger.info('computes: {}'.format([('{0}: {1}'.format(
740         node.get_name(), node.get_ip())) for node in computes]))
741
742     mcelog_install()
743     create_ovs_bridge()
744     gnocchi_running_on_con = False
745     aodh_running_on_con = False
746     # Disabling SNMP write plug-in
747     snmp_running = False
748     _print_label('Testing Gnocchi and AODH plugins on nodes')
749
750     for controller in controllers:
751         gnocchi_running = (
752             gnocchi_running_on_con or conf.is_gnocchi_running(controller))
753         aodh_running = (
754             aodh_running_on_con or conf.is_aodh_running(controller))
755
756     compute_ids = []
757     compute_node_names = []
758     results = []
759     plugin_labels = {
760         'intel_rdt': 'Intel RDT',
761         'hugepages': 'Hugepages',
762         # 'ipmi': 'IPMI',
763         'mcelog': 'Mcelog',
764         'ovs_stats': 'OVS stats',
765         'ovs_events': 'OVS events'}
766     aodh_plugin_labels = {
767         'mcelog': 'Mcelog',
768         'ovs_events': 'OVS events'}
769     out_plugins = {}
770     for compute_node in computes:
771         node_id = compute_node.get_id()
772         node_name = compute_node.get_name()
773         out_plugins[node_id] = []
774         compute_ids.append(node_id)
775         compute_node_names.append(node_name)
776         plugins_to_enable = []
777         error_plugins = []
778         gnocchi_running = (
779             gnocchi_running and conf.check_gnocchi_plugin_included(
780                 compute_node))
781         aodh_running = (
782             aodh_running and conf.check_aodh_plugin_included(compute_node))
783         # logger.info("SNMP enabled on {}" .format(node_name))
784         if gnocchi_running:
785             out_plugins[node_id].append("Gnocchi")
786         if aodh_running:
787             out_plugins[node_id].append("AODH")
788         if snmp_running:
789             out_plugins[node_id].append("SNMP")
790
791         if 'Gnocchi' in out_plugins[node_id]:
792             plugins_to_enable.append('csv')
793             out_plugins[node_id].append("CSV")
794             if plugins_to_enable:
795                 _print_label(
796                     'NODE {}: Enabling Test Plug-in '.format(node_name)
797                     + 'and Test case execution')
798             if plugins_to_enable and not conf.enable_plugins(
799                     compute_node, plugins_to_enable, error_plugins,
800                     create_backup=False):
801                 logger.error(
802                     'Failed to test plugins on node {}.'.format(node_id))
803                 logger.info(
804                     'Testcases on node {} will not be executed'.format(
805                         node_id))
806
807         for i in out_plugins[node_id]:
808             if i == 'AODH':
809                 for plugin_name in sorted(aodh_plugin_labels.keys()):
810                     _exec_testcase(
811                         aodh_plugin_labels, plugin_name, i,
812                         controllers, compute_node, conf, results,
813                         error_plugins, out_plugins[node_id])
814             elif i == 'CSV':
815                 _print_label("Node {}: Executing CSV Testcases".format(
816                     node_name))
817                 logger.info("Restarting collectd for CSV tests")
818                 collectd_restarted, collectd_warnings = \
819                     conf.restart_collectd(compute_node)
820                 sleep_time = 10
821                 logger.info(
822                     'Sleeping for {} seconds'.format(sleep_time)
823                     + ' after collectd restart...')
824                 time.sleep(sleep_time)
825                 if not collectd_restarted:
826                     for warning in collectd_warnings:
827                         logger.warning(warning)
828                     logger.error(
829                         'Restart of collectd on node {} failed'.format(
830                             compute_node))
831                     logger.info(
832                         'CSV Testcases on node {}'.format(compute_node)
833                         + ' will not be executed.')
834                 for plugin_name in sorted(plugin_labels.keys()):
835                     _exec_testcase(
836                         plugin_labels, plugin_name, i,
837                         controllers, compute_node, conf, results,
838                         error_plugins, out_plugins[node_id])
839
840             else:
841                 for plugin_name in sorted(plugin_labels.keys()):
842                     _exec_testcase(
843                         plugin_labels, plugin_name, i,
844                         controllers, compute_node, conf, results,
845                         error_plugins, out_plugins[node_id])
846
847     mcelog_delete()
848     print_overall_summary(
849         compute_ids, plugin_labels, aodh_plugin_labels, results, out_plugins)
850
851     for res in results:
852         if res[3] is 'False' or 'None':
853             logger.error('Some tests have failed or have not been executed')
854             logger.error('Overall Result is Fail')
855             return 1
856         else:
857             pass
858     return 0
859
860
861 if __name__ == '__main__':
862     sys.exit(main())