Merge "Fix docs for container deployment"
[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 += ' SKIP   |'
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 += ' SKIP   |'
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 += ' SKIP   |'
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 += ' SKIP   |'
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         # 'ipmi': ['ipmi'],
509         'mcelog': [
510             'mcelog-SOCKET_0_CHANNEL_0_DIMM_any',
511             'mcelog-SOCKET_0_CHANNEL_any_DIMM_any'],
512         'ovs_stats': [
513             'ovs_stats-br0.br0'],
514         'ovs_events': [
515             'ovs_events-br0']}
516     # csv_meter_categories_ipmi = get_csv_categories_for_ipmi(conf,
517     # compute_node)
518     csv_meter_categories = {
519         'intel_rdt': [
520             'bytes-llc', 'ipc'],
521         'hugepages': ['vmpage_number-free', 'vmpage_number-used'],
522         # 'ipmi': csv_meter_categories_ipmi,
523         'mcelog': [
524             'errors-corrected_memory_errors',
525             'errors-uncorrected_memory_errors'],
526         'ovs_stats': [
527             'if_dropped', 'if_errors', 'if_packets'],
528         'ovs_events': ['gauge-link_status']}
529
530     _print_plugin_label(
531         test_labels[name] if name in test_labels else name,
532         compute_node.get_name())
533     plugin_critical_errors = [
534         error for plugin, error, critical in error_plugins
535         if plugin == name and critical]
536     if plugin_critical_errors:
537         logger.error('Following critical errors occurred:'.format(name))
538         for error in plugin_critical_errors:
539             logger.error(' * ' + error)
540         _process_result(
541             compute_node.get_id(), out_plugin, test_labels[name], False,
542             results, compute_node.get_name())
543     else:
544         plugin_errors = [
545             error for plugin, error, critical in error_plugins
546             if plugin == name and not critical]
547         if plugin_errors:
548             logger.warning('Following non-critical errors occured:')
549             for error in plugin_errors:
550                 logger.warning(' * ' + error)
551         failed_prerequisites = []
552         if name in plugin_prerequisites:
553             failed_prerequisites = [
554                 prerequisite_name for prerequisite_passed,
555                 prerequisite_name in plugin_prerequisites[name]
556                 if not prerequisite_passed]
557         if failed_prerequisites:
558             logger.error(
559                 '{} test will not be executed, '.format(name)
560                 + 'following prerequisites failed:')
561             for prerequisite in failed_prerequisites:
562                 logger.error(' * {}'.format(prerequisite))
563         # optional plugin
564         elif "intel_rdt" == name and not conf.is_rdt_available(compute_node):
565             #TODO: print log message
566             logger.info("RDT is not available on virtual nodes, skipping test.")
567             res = True
568             print("Results for {}, pre-processing".format(str(test_labels[name])))
569             print(results)
570             _process_result(
571                 compute_node.get_id(), out_plugin, test_labels[name],
572                 res, results, compute_node.get_name())
573             print("Results for {}, post-processing".format(str(test_labels[name])))
574             print(results)
575         else:
576             plugin_interval = conf.get_plugin_interval(compute_node, name)
577             if out_plugin == 'Gnocchi':
578                 res = conf.test_plugins_with_gnocchi(
579                     compute_node.get_name(), plugin_interval,
580                     logger, criteria_list=gnocchi_criteria_lists[name])
581             if out_plugin == 'AODH':
582                 res = conf.test_plugins_with_aodh(
583                     compute_node.get_name(), plugin_interval,
584                     logger, criteria_list=aodh_criteria_lists[name])
585             if out_plugin == 'SNMP':
586                 res = \
587                     name in snmp_mib_files and name in snmp_mib_strings \
588                     and conf.test_plugins_with_snmp(
589                         compute_node.get_name(), plugin_interval, logger, name,
590                         snmp_mib_files[name], snmp_mib_strings[name],
591                         snmp_in_commands[name])
592             if out_plugin == 'CSV':
593                 res = tests.test_csv_handles_plugin_data(
594                     compute_node, conf.get_plugin_interval(compute_node, name),
595                     name, csv_subdirs[name], csv_meter_categories[name],
596                     logger, CSVClient(conf))
597
598             if res and plugin_errors:
599                 logger.info(
600                     'Test works, but will be reported as failure,'
601                     + 'because of non-critical errors.')
602                 res = False
603             print("Results for {}, pre-processing".format(str(test_labels[name])))
604             print(results)
605             _process_result(
606                 compute_node.get_id(), out_plugin, test_labels[name],
607                 res, results, compute_node.get_name())
608             print("Results for {}, post-processing".format(str(test_labels[name])))
609             print(results)
610
611
612 def get_results_for_ovs_events(
613         plugin_labels, plugin_name, gnocchi_running,
614         compute_node, conf, results, error_plugins):
615     """ Testing OVS Events with python plugin
616     """
617     plugin_label = 'OVS events'
618     res = conf.enable_ovs_events(
619         compute_node, plugin_label, error_plugins, create_backup=False)
620     _process_result(
621         compute_node.get_id(), plugin_label, res, results)
622     logger.info("Results for OVS Events = {}" .format(results))
623
624
625 def create_ovs_bridge():
626     """Create OVS brides on compute nodes"""
627     handler = factory.Factory.get_handler('apex',
628                                           APEX_IP,
629                                           APEX_USER_STACK,
630                                           APEX_PKEY)
631     nodes = handler.get_nodes()
632     logger.info("Creating OVS bridges on computes nodes")
633     for node in nodes:
634         if node.is_compute():
635             node.run_cmd('sudo ovs-vsctl add-br br0')
636             node.run_cmd('sudo ovs-vsctl set-manager ptcp:6640')
637     logger.info('OVS Bridges created on compute nodes')
638
639
640 def mcelog_install():
641     """Install mcelog on compute nodes."""
642     _print_label('Enabling mcelog and OVS bridges on compute nodes')
643     handler = factory.Factory.get_handler('apex',
644                                           APEX_IP,
645                                           APEX_USER_STACK,
646                                           APEX_PKEY)
647     nodes = handler.get_nodes()
648     mce_bin = os.path.dirname(os.path.realpath(__file__)) + '/mce-inject_ea'
649     for node in nodes:
650         if node.is_compute():
651             centos_release = node.run_cmd('uname -r')
652             if centos_release not in ('3.10.0-514.26.2.el7.x86_64', '3.10.0-693.17.1.el7.x86_64'):
653                 logger.info(
654                     'Mcelog will NOT be enabled on node-{}.'
655                     + ' Unsupported CentOS release found ({}).'.format(
656                         node.get_dict()['name'],centos_release))
657             else:
658                 logger.info(
659                     'Checking if mcelog is enabled'
660                     + ' on node-{}...'.format(node.get_dict()['name']))
661                 res = node.run_cmd('ls')
662                 if 'mce-inject_ea' and 'corrected' in res:
663                     logger.info(
664                         'Mcelog seems to be already installed '
665                         + 'on node-{}.'.format(node.get_dict()['name']))
666                     node.run_cmd('sudo modprobe mce-inject')
667                     node.run_cmd('sudo ./mce-inject_ea < corrected')
668                 else:
669                     logger.info(
670                         'Mcelog will be enabled '
671                         + 'on node-{}...'.format(node.get_dict()['name']))
672                     node.put_file(mce_bin, 'mce-inject_ea')
673                     node.run_cmd('chmod a+x mce-inject_ea')
674                     node.run_cmd('echo "CPU 0 BANK 0" > corrected')
675                     node.run_cmd(
676                         'echo "STATUS 0xcc00008000010090" >>'
677                         + ' corrected')
678                     node.run_cmd(
679                         'echo "ADDR 0x0010FFFFFFF" >> corrected')
680                     node.run_cmd('sudo modprobe mce-inject')
681                     node.run_cmd('sudo ./mce-inject_ea < corrected')
682                     logger.info(
683                         'Mcelog was installed '
684                         + 'on node-{}.'.format(node.get_dict()['name']))
685
686
687
688 def mcelog_delete():
689     """Uninstall mcelog from compute nodes."""
690     handler = factory.Factory.get_handler(
691             'apex', APEX_IP, APEX_USER, APEX_PKEY)
692     nodes = handler.get_nodes()
693     for node in nodes:
694         if node.is_compute():
695             output = node.run_cmd('ls')
696             if 'mce-inject_ea' in output:
697                 node.run_cmd('rm mce-inject_ea')
698             if 'corrected' in output:
699                 node.run_cmd('rm corrected')
700             node.run_cmd('sudo systemctl restart mcelog')
701     logger.info('Mcelog is deleted from all compute nodes')
702
703
704 def get_ssh_keys():
705     if not os.path.isdir(ID_RSA_DST_DIR):
706         os.makedirs(ID_RSA_DST_DIR)
707     if not os.path.isfile(ID_RSA_DST):
708         logger.info(
709             "RSA key file {} doesn't exist".format(ID_RSA_DST)
710             + ", it will be downloaded from installer node.")
711         handler = factory.Factory.get_handler(
712             'apex', APEX_IP, APEX_USER, APEX_PKEY)
713         apex = handler.get_installer_node()
714         apex.get_file(ID_RSA_SRC, ID_RSA_DST)
715     else:
716         logger.info("RSA key file {} exists.".format(ID_RSA_DST))
717
718
719 def _check_logger():
720     """Check whether there is global logger available and if not, define one."""
721     if 'logger' not in globals():
722         global logger
723         logger = logger.Logger("barometercollectd").getLogger()
724
725
726 def main(bt_logger=None):
727     """Check each compute node sends gnocchi metrics.
728
729     Keyword arguments:
730     bt_logger -- logger instance
731     """
732     logging.getLogger("paramiko").setLevel(logging.WARNING)
733     logging.getLogger("stevedore").setLevel(logging.WARNING)
734     logging.getLogger("opnfv.deployment.manager").setLevel(logging.WARNING)
735     if bt_logger is None:
736         _check_logger()
737     else:
738         global logger
739         logger = bt_logger
740     _print_label("Starting barometer tests suite")
741     get_ssh_keys()
742     conf = config_server.ConfigServer(APEX_IP, APEX_USER, logger)
743     controllers = conf.get_controllers()
744     if len(controllers) == 0:
745         logger.error('No controller nodes found!')
746         return 1
747     computes = conf.get_computes()
748     if len(computes) == 0:
749         logger.error('No compute nodes found!')
750         return 1
751
752     _print_label(
753         'Display of Control and Compute nodes available in the set up')
754     logger.info('controllers: {}'.format([('{0}: {1}'.format(
755         node.get_name(), node.get_ip())) for node in controllers]))
756     logger.info('computes: {}'.format([('{0}: {1}'.format(
757         node.get_name(), node.get_ip())) for node in computes]))
758
759     mcelog_install()
760     create_ovs_bridge()
761     gnocchi_running_on_con = False
762     aodh_running_on_con = False
763     # Disabling SNMP write plug-in
764     snmp_running = False
765     _print_label('Testing Gnocchi and AODH plugins on nodes')
766
767     for controller in controllers:
768         gnocchi_running = (
769             gnocchi_running_on_con or conf.is_gnocchi_running(controller))
770         aodh_running = (
771             aodh_running_on_con or conf.is_aodh_running(controller))
772
773     compute_ids = []
774     compute_node_names = []
775     results = []
776     plugin_labels = {
777         'intel_rdt': 'Intel RDT',
778         'hugepages': 'Hugepages',
779         # 'ipmi': 'IPMI',
780         'mcelog': 'Mcelog',
781         'ovs_stats': 'OVS stats',
782         'ovs_events': 'OVS events'}
783     aodh_plugin_labels = {
784         'mcelog': 'Mcelog',
785         'ovs_events': 'OVS events'}
786     out_plugins = {}
787     for compute_node in computes:
788         node_id = compute_node.get_id()
789         node_name = compute_node.get_name()
790         out_plugins[node_id] = []
791         compute_ids.append(node_id)
792         compute_node_names.append(node_name)
793         plugins_to_enable = []
794         error_plugins = []
795         gnocchi_running = (
796             gnocchi_running and conf.check_gnocchi_plugin_included(
797                 compute_node))
798         aodh_running = (
799             aodh_running and conf.check_aodh_plugin_included(compute_node))
800         # logger.info("SNMP enabled on {}" .format(node_name))
801         if gnocchi_running:
802             out_plugins[node_id].append("Gnocchi")
803         if aodh_running:
804             out_plugins[node_id].append("AODH")
805         if snmp_running:
806             out_plugins[node_id].append("SNMP")
807
808         if 'Gnocchi' in out_plugins[node_id]:
809             plugins_to_enable.append('csv')
810             out_plugins[node_id].append("CSV")
811             if plugins_to_enable:
812                 _print_label(
813                     'NODE {}: Enabling Test Plug-in '.format(node_name)
814                     + 'and Test case execution')
815             if plugins_to_enable and not conf.enable_plugins(
816                     compute_node, plugins_to_enable, error_plugins,
817                     create_backup=False):
818                 logger.error(
819                     'Failed to test plugins on node {}.'.format(node_id))
820                 logger.info(
821                     'Testcases on node {} will not be executed'.format(
822                         node_id))
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             elif i == 'CSV':
832                 _print_label("Node {}: Executing CSV Testcases".format(
833                     node_name))
834                 logger.info("Restarting collectd for CSV tests")
835                 collectd_restarted, collectd_warnings = \
836                     conf.restart_collectd(compute_node)
837                 sleep_time = 10
838                 logger.info(
839                     'Sleeping for {} seconds'.format(sleep_time)
840                     + ' after collectd restart...')
841                 time.sleep(sleep_time)
842                 if not collectd_restarted:
843                     for warning in collectd_warnings:
844                         logger.warning(warning)
845                     logger.error(
846                         'Restart of collectd on node {} failed'.format(
847                             compute_node))
848                     logger.info(
849                         'CSV Testcases on node {}'.format(compute_node)
850                         + ' will not be executed.')
851                 for plugin_name in sorted(plugin_labels.keys()):
852                     _exec_testcase(
853                         plugin_labels, plugin_name, i,
854                         controllers, compute_node, conf, results,
855                         error_plugins, out_plugins[node_id])
856
857             else:
858                 for plugin_name in sorted(plugin_labels.keys()):
859                     _exec_testcase(
860                         plugin_labels, plugin_name, i,
861                         controllers, compute_node, conf, results,
862                         error_plugins, out_plugins[node_id])
863
864     mcelog_delete()
865     print_overall_summary(
866         compute_ids, plugin_labels, aodh_plugin_labels, results, out_plugins)
867
868     for res in results:
869         if res[3] is 'False' or 'None':
870             logger.error('Some tests have failed or have not been executed')
871             logger.error('Overall Result is Fail')
872             return 1
873         else:
874             pass
875     return 0
876
877
878 if __name__ == '__main__':
879     sys.exit(main())