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