Adding different method to access compute and controllers
[barometer.git] / baro_tests / collectd.py
1 # -*- coding: utf-8 -*-
2
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """Executing test of plugins"""
16
17 import requests
18 from keystoneclient.v3 import client
19 import os
20 import sys
21 import time
22 import logging
23 import config_server
24 import tests
25 import subprocess
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 = subprocess.check_output("echo $INSTALLER_IP", shell=True)
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 SNMPClient(object):
177     """Client to request SNMP meters"""
178     def __init__(self, conf, compute_node):
179         """
180         Keyword arguments:
181         conf -- ConfigServer instance
182         compute_node -- Compute node object
183         """
184         self.conf = conf
185         self.compute_node = compute_node
186
187     def get_snmp_metrics(self, compute_node, mib_file, mib_strings):
188         snmp_output = {}
189         if mib_file is None:
190             cmd = "snmpwalk -v 2c -c public localhost IF-MIB::interfaces"
191             ip = compute_node.get_ip()
192             snmp_output = self.conf.execute_command(cmd, ip)
193         else:
194             for mib_string in mib_strings:
195                 snmp_output[mib_string] = self.conf.execute_command(
196                     "snmpwalk -v2c -m {} -c public localhost {}".format(
197                         mib_file, mib_string), compute_node.get_ip())
198         return snmp_output
199
200
201 class CSVClient(object):
202     """Client to request CSV meters"""
203     def __init__(self, conf):
204         """
205         Keyword arguments:
206         conf -- ConfigServer instance
207         """
208         self.conf = conf
209
210     def get_csv_metrics(
211             self, compute_node, plugin_subdirectories, meter_categories):
212         """Get CSV metrics.
213
214         Keyword arguments:
215         compute_node -- compute node instance
216         plugin_subdirectories -- list of subdirectories of plug-in
217         meter_categories -- categories which will be tested
218
219         Return list of metrics.
220         """
221         compute_name = compute_node.get_name()
222         nodes = get_apex_nodes()
223         for node in nodes:
224             if compute_name == node.get_dict()['name']:
225                 date = node.run_cmd(
226                     "date '+%Y-%m-%d'")
227                 metrics = []
228                 for plugin_subdir in plugin_subdirectories:
229                     for meter_category in meter_categories:
230                         stdout1 = node.run_cmd(
231                             "tail -2 /var/lib/collectd/csv/"
232                             + "{0}.jf.intel.com/{1}/{2}-{3}".format(
233                                 compute_node.get_name(), plugin_subdir,
234                                 meter_category, date))
235                         stdout2 = node.run_cmd(
236                             "tail -1 /var/lib/collectd/csv/"
237                             + "{0}.jf.intel.com/{1}/{2}-{3}".format(
238                                 compute_node.get_name(), plugin_subdir,
239                                 meter_category, date))
240                 # Storing last two values
241                         values = stdout1
242                         if values is None:
243                             logger.error(
244                                 'Getting last two CSV entries of meter category'
245                                 + ' {0} in {1} subdir failed'.format(
246                                     meter_category, plugin_subdir))
247                         else:
248                             values = values.split(',')
249                             old_value = float(values[0])
250                             stdout2 = stdout2.split(',')
251                             new_value = float(stdout2[0])
252                             metrics.append((
253                                 plugin_subdir, meter_category, old_value,
254                                 new_value))
255         return metrics
256
257
258 def get_csv_categories_for_ipmi(conf, compute_node):
259     """Get CSV metrics.
260
261     Keyword arguments:
262     compute_node -- compute node instance
263
264     Return list of categories.
265     """
266     stdout = conf.execute_command(
267         "date '+%Y-%m-%d'", compute_node.get_ip())
268     date = stdout[0].strip()
269     categories = conf.execute_command(
270         "ls /var/lib/collectd/csv/{0}.jf.intel.com/ipmi | grep {1}".format(
271             compute_node.get_name(), date), compute_node.get_ip())
272     return [category.strip()[:-11] for category in categories]
273
274
275 def _process_result(compute_node, test, result, results_list):
276     """Print test result and append it to results list.
277
278     Keyword arguments:
279     test -- testcase name
280     result -- boolean test result
281     results_list -- results list
282     """
283     if result:
284         logger.info(
285             'Compute node {0} test case {1} PASSED.'.format(
286                 compute_node, test))
287     else:
288         logger.error(
289             'Compute node {0} test case {1} FAILED.'.format(
290                 compute_node, test))
291     results_list.append((compute_node, test, result))
292
293
294 def _print_label(label):
295     """Print label on the screen
296
297     Keyword arguments:
298     label -- label string
299     """
300     label = label.strip()
301     length = 70
302     if label != '':
303         label = ' ' + label + ' '
304     length_label = len(label)
305     length1 = (length - length_label) / 2
306     length2 = length - length_label - length1
307     length1 = max(3, length1)
308     length2 = max(3, length2)
309     logger.info(('=' * length1) + label + ('=' * length2))
310
311
312 def _print_plugin_label(plugin, node_name):
313     """Print plug-in label.
314
315     Keyword arguments:
316     plugin -- plug-in name
317     node_id -- node ID
318     """
319     _print_label(
320         'Node {0}: Plug-in {1} Test case execution'.format(node_name, plugin))
321
322
323 def _print_final_result_of_plugin(
324         plugin, compute_ids, results, out_plugins, out_plugin):
325     """Print final results of plug-in.
326
327     Keyword arguments:
328     plugin -- plug-in name
329     compute_ids -- list of compute node IDs
330     results -- results list
331     out_plugins -- list of out plug-ins
332     out_plugin -- used out plug-in
333     """
334     print_line = ''
335     for id in compute_ids:
336         if out_plugins[id] == out_plugin:
337             if (id, plugin, True) in results:
338                 print_line += ' PASS   |'
339             elif (id, plugin, False) in results \
340                     and out_plugins[id] == out_plugin:
341                 print_line += ' FAIL   |'
342             else:
343                 print_line += ' NOT EX |'
344         elif out_plugin == 'Gnocchi':
345             print_line += ' NOT EX |'
346         else:
347             print_line += ' NOT EX |'
348     return print_line
349
350
351 def print_overall_summary(compute_ids, tested_plugins, results, out_plugins):
352     """Print overall summary table.
353
354     Keyword arguments:
355     compute_ids -- list of compute IDs
356     tested_plugins -- list of plug-ins
357     results -- results list
358     out_plugins --  list of used out plug-ins
359     """
360     compute_node_names = ['Node-{}'.format(i) for i in range(
361         len((compute_ids)))]
362     # compute_node_names = ['Node-{}'.format(id) for id in compute_ids]
363     all_computes_in_line = ''
364     for compute in compute_node_names:
365         all_computes_in_line += '| ' + compute + (' ' * (7 - len(compute)))
366     line_of_nodes = '| Test           ' + all_computes_in_line + '|'
367     logger.info('=' * 70)
368     logger.info('+' + ('-' * ((9 * len(compute_node_names))+16)) + '+')
369     logger.info(
370         '|' + ' ' * ((9*len(compute_node_names))/2)
371         + ' OVERALL SUMMARY'
372         + ' ' * (
373             9*len(compute_node_names) - (9*len(compute_node_names))/2)
374         + '|')
375     logger.info(
376         '+' + ('-' * 16) + '+' + (('-' * 8) + '+') * len(compute_node_names))
377     logger.info(line_of_nodes)
378     logger.info(
379         '+' + ('-' * 16) + '+' + (('-' * 8) + '+') * len(compute_node_names))
380     out_plugins_print = ['Gnocchi']
381     if 'SNMP' in out_plugins.values():
382         out_plugins_print.append('SNMP')
383     if 'AODH' in out_plugins.values():
384         out_plugins_print.append('AODH')
385     if 'CSV' in out_plugins.values():
386         out_plugins_print.append('CSV')
387     for out_plugin in out_plugins_print:
388         output_plugins_line = ''
389         for id in compute_ids:
390             out_plugin_result = 'FAIL'
391             if out_plugin == 'Gnocchi':
392                 out_plugin_result = \
393                     'PASS' if out_plugins[id] == out_plugin else 'FAIL'
394             if out_plugin == 'AODH':
395                 if out_plugins[id] == out_plugin:
396                     out_plugin_result = \
397                         'PASS' if out_plugins[id] == out_plugin else 'FAIL'
398             if out_plugin == 'SNMP':
399                 if out_plugins[id] == out_plugin:
400                     out_plugin_result = \
401                         'PASS' if out_plugins[id] == out_plugin else 'FAIL'
402             if out_plugin == 'CSV':
403                 if out_plugins[id] == out_plugin:
404                     out_plugin_result = \
405                         'PASS' if [
406                             plugin for comp_id, plugin, res in results
407                             if comp_id == id and res] else 'FAIL'
408                 else:
409                     out_plugin_result = 'SKIP'
410             output_plugins_line += '| ' + out_plugin_result + '   '
411         logger.info(
412             '| OUT:{}'.format(out_plugin) + (' ' * (11 - len(out_plugin)))
413             + output_plugins_line + '|')
414         for plugin in sorted(tested_plugins.values()):
415             line_plugin = _print_final_result_of_plugin(
416                 plugin, compute_ids, results, out_plugins, out_plugin)
417             logger.info(
418                 '|  IN:{}'.format(plugin) + (' ' * (11-len(plugin)))
419                 + '|' + line_plugin)
420         logger.info(
421             '+' + ('-' * 16) + '+'
422             + (('-' * 8) + '+') * len(compute_node_names))
423     logger.info('=' * 70)
424
425
426 def _exec_testcase(
427         test_labels, name, gnocchi_running, aodh_running, snmp_running,
428         controllers, compute_node, conf, results, error_plugins, out_plugins):
429     """Execute the testcase.
430
431     Keyword arguments:
432     test_labels -- dictionary of plug-in IDs and their display names
433     name -- plug-in ID, key of test_labels dictionary
434     ceilometer_running -- boolean indicating whether Ceilometer is running
435     compute_node -- compute node ID
436     conf -- ConfigServer instance
437     results -- results list
438     error_plugins -- list of tuples with plug-in errors
439         (plugin, error_description, is_critical):
440         plugin -- plug-in ID, key of test_labels dictionary
441         error_decription -- description of the error
442         is_critical -- boolean value indicating whether error is critical
443     """
444     ovs_interfaces = conf.get_ovs_interfaces(compute_node)
445     ovs_configured_interfaces = conf.get_plugin_config_values(
446         compute_node, 'ovs_events', 'Interfaces')
447     ovs_configured_bridges = conf.get_plugin_config_values(
448          compute_node, 'ovs_stats', 'Bridges')
449     ovs_existing_configured_int = [
450         interface for interface in ovs_interfaces
451         if interface in ovs_configured_interfaces]
452     ovs_existing_configured_bridges = [
453         bridge for bridge in ovs_interfaces
454         if bridge in ovs_configured_bridges]
455     plugin_prerequisites = {
456         'intel_rdt': [(
457             conf.is_libpqos_on_node(compute_node),
458             'libpqos must be installed.')],
459         'mcelog': [(
460             conf.is_installed(compute_node, 'mcelog'),
461             'mcelog must be installed.')],
462         'ovs_events': [(
463             len(ovs_existing_configured_int) > 0 or len(ovs_interfaces) > 0,
464             'Interfaces must be configured.')],
465         'ovs_stats': [(
466             len(ovs_existing_configured_bridges) > 0,
467             'Bridges must be configured.')]}
468     gnocchi_criteria_lists = {
469         'hugepages': ['hugepages'],
470         'mcelog': ['mcelog'],
471         'ovs_events': ['interface-ovs-system'],
472         'ovs_stats': ['ovs_stats-br0.br0']}
473     aodh_criteria_lists = {
474         'mcelog': ['mcelog.errors'],
475         'ovs_events': ['ovs_events.gauge']}
476     snmp_mib_files = {
477         'intel_rdt': '/usr/share/snmp/mibs/Intel-Rdt.txt',
478         'hugepages': '/usr/share/snmp/mibs/Intel-Hugepages.txt',
479         'mcelog': '/usr/share/snmp/mibs/Intel-Mcelog.txt'}
480     snmp_mib_strings = {
481         'intel_rdt': [
482             'INTEL-RDT-MIB::rdtLlc.1',
483             'INTEL-RDT-MIB::rdtIpc.1',
484             'INTEL-RDT-MIB::rdtMbmRemote.1',
485             'INTEL-RDT-MIB::rdtMbmLocal.1'],
486         'hugepages': [
487             'INTEL-HUGEPAGES-MIB::hugepagesPageFree'],
488         'mcelog': [
489             'INTEL-MCELOG-MIB::memoryCorrectedErrors.1',
490             'INTEL-MCELOG-MIB::memoryCorrectedErrors.2']}
491     nr_hugepages = int(time.time()) % 10000
492     snmp_in_commands = {
493         'intel_rdt': None,
494         'hugepages': 'echo {} > /sys/kernel/'.format(nr_hugepages)
495                      + 'mm/hugepages/hugepages-2048kB/nr_hugepages',
496         'mcelog': '/root/mce-inject_df < /root/corrected'}
497     csv_subdirs = {
498         'intel_rdt': [
499             'intel_rdt-{}'.format(core)
500             for core in conf.get_plugin_config_values(
501                 compute_node, 'intel_rdt', 'Cores')],
502         'hugepages': [
503             'hugepages-mm-2048Kb', 'hugepages-node0-2048Kb',
504             'hugepages-node1-2048Kb', 'hugepages-mm-1048576Kb',
505             'hugepages-node0-1048576Kb', 'hugepages-node1-1048576Kb'],
506         # 'ipmi': ['ipmi'],
507         'mcelog': [
508             'mcelog-SOCKET_0_CHANNEL_0_DIMM_any',
509             'mcelog-SOCKET_0_CHANNEL_any_DIMM_any'],
510         'ovs_stats': [
511             'ovs_stats-br0.br0'],
512         'ovs_events': [
513             'ovs_events-br0']}
514     # csv_meter_categories_ipmi = get_csv_categories_for_ipmi(conf,
515     # compute_node)
516     csv_meter_categories = {
517         'intel_rdt': [
518             'bytes-llc', 'ipc', 'memory_bandwidth-local',
519             'memory_bandwidth-remote'],
520         'hugepages': ['vmpage_number-free', 'vmpage_number-used'],
521         # 'ipmi': csv_meter_categories_ipmi,
522         'mcelog': [
523             'errors-corrected_memory_errors',
524             'errors-uncorrected_memory_errors',
525             'errors-corrected_memory_errors_in_24h',
526             'errors-uncorrected_memory_errors_in_24h'],
527         'ovs_stats': [
528             'if_collisions', 'if_dropped', 'if_errors', 'if_packets',
529             'if_rx_errors-crc', 'if_rx_errors-frame', 'if_rx_errors-over',
530             'if_rx_octets', 'if_tx_octets'],
531         'ovs_events': ['gauge-link_status']}
532
533     _print_plugin_label(
534         test_labels[name] if name in test_labels else name,
535         compute_node.get_name())
536     plugin_critical_errors = [
537         error for plugin, error, critical in error_plugins
538         if plugin == name and critical]
539     if plugin_critical_errors:
540         logger.error('Following critical errors occurred:'.format(name))
541         for error in plugin_critical_errors:
542             logger.error(' * ' + error)
543         _process_result(
544             compute_node.get_id(), test_labels[name], False, results)
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         else:
566             if gnocchi_running:
567                 plugin_interval = conf.get_plugin_interval(compute_node, name)
568                 res = conf.test_plugins_with_gnocchi(
569                     compute_node.get_id(), plugin_interval, logger,
570                     criteria_list=gnocchi_criteria_lists[name])
571             elif aodh_running:
572                 res = conf.test_plugins_with_aodh(
573                    compute_node.get_id(), plugin_interval,
574                    logger, creteria_list=aodh_criteria_lists[name])
575             elif snmp_running:
576                 res = \
577                     name in snmp_mib_files and name in snmp_mib_strings \
578                     and tests.test_snmp_sends_data(
579                         compute_node,
580                         conf.get_plugin_interval(compute_node, name), logger,
581                         SNMPClient(conf, compute_node), snmp_mib_files[name],
582                         snmp_mib_strings[name], snmp_in_commands[name], conf)
583             else:
584                 res = tests.test_csv_handles_plugin_data(
585                     compute_node, conf.get_plugin_interval(compute_node, name),
586                     name, csv_subdirs[name], csv_meter_categories[name],
587                     logger, CSVClient(conf))
588             if res and plugin_errors:
589                 logger.info(
590                     'Test works, but will be reported as failure,'
591                     + 'because of non-critical errors.')
592                 res = False
593             _process_result(
594                 compute_node.get_id(), test_labels[name], res, results)
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     for node in nodes:
618         if node.is_compute():
619             node.run_cmd('sudo ovs-vsctl add-br br0')
620             node.run_cmd('sudo ovs-vsctl set-manager ptcp:6640')
621         logger.info('OVS Bridges created on compute nodes')
622
623
624 def mcelog_install():
625     """Install mcelog on compute nodes."""
626     _print_label('Enabling mcelog 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     for node in nodes:
633         if node.is_compute():
634             centos_release = node.run_cmd('uname -r')
635             if '3.10.0-514.26.2.el7.x86_64' not in centos_release:
636                 logger.info(
637                     'Mcelog will not be enabled '
638                     + 'on node-{0}, '.format(node.get_dict()['id'])
639                     + 'unsupported CentOS release found ({1}).'.format(
640                         centos_release))
641             else:
642                 logger.info(
643                     'Checking if  mcelog is enabled'
644                     + ' on node-{}...'.format(node.get_dict()['id']))
645                 res = node.run_cmd('ls')
646             if 'mce-inject_ea' and 'corrected' in res:
647                 logger.info(
648                     'Mcelog seems to be already installed '
649                     + 'on node-{}.'.format(node.get_dict()['id']))
650                 node.run_cmd('sudo modprobe mce-inject')
651                 node.run_cmd('sudo ./mce-inject_ea < corrected')
652             else:
653                 logger.info(
654                     'Mcelog will be enabled on node-{}...'.format(
655                         node.get_dict()['id']))
656                 node.put_file(
657                     '/usr/local/lib/python2.7/dist-packages/baro_tests/'
658                     + 'mce-inject_ea', '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} ({2})'.format(
738         node.get_id(), node.get_name(),
739         node.get_ip())) for node in controllers]))
740     logger.info('computes: {}'.format([('{0}: {1} ({2})'.format(
741         node.get_id(), node.get_name(), node.get_ip()))
742         for node in computes]))
743
744     mcelog_install()
745     create_ovs_bridge()
746     gnocchi_running_on_con = False
747     aodh_running_on_con = False
748     snmp_running = False
749     _print_label('Testing Gnocchi, AODH and SNMP on controller nodes')
750
751     for controller in controllers:
752         gnocchi_client = GnocchiClient()
753         gnocchi_client.auth_token()
754         gnocchi_running = (
755             gnocchi_running_on_con and conf.is_gnocchi_running(controller))
756         aodh_client = AodhClient()
757         aodh_client.auth_token()
758         aodh_running = (
759             aodh_running_on_con and conf.is_aodh_running(controller))
760     if gnocchi_running:
761         logger.info("Gnocchi is running on controller.")
762     elif aodh_running:
763         logger.error("Gnocchi is not running on controller.")
764         logger.info("AODH is running on controller.")
765     elif snmp_running:
766         logger.error("Gnocchi is not running on Controller")
767         logger.error("AODH is not running on controller.")
768         logger.info("SNMP is running on controller.")
769     else:
770         logger.error("Gnocchi is not running on Controller")
771         logger.error("AODH is not running on controller.")
772         logger.error("SNMP is not running on controller.")
773         logger.info("CSV will be enabled on compute nodes.")
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     out_plugins = {
786         'gnocchi': 'Gnocchi',
787         'aodh': 'AODH',
788         'snmp': 'SNMP',
789         'csv': 'CSV'}
790     for compute_node in computes:
791         node_id = compute_node.get_id()
792         node_name = compute_node.get_name()
793         out_plugins[node_id] = 'CSV'
794         compute_ids.append(node_id)
795         compute_node_names.append(node_name)
796         plugins_to_enable = []
797         _print_label('NODE {}: Test Gnocchi Plug-in'.format(node_name))
798         logger.info('Checking if gnocchi plug-in is included in compute nodes.')
799         if not conf.check_gnocchi_plugin_included(compute_node):
800             logger.error('Gnocchi plug-in is not included.')
801             logger.info(
802                 'Testcases on node {} will not be executed'.format(node_name))
803         else:
804             collectd_restarted, collectd_warnings = \
805                 conf.restart_collectd(compute_node)
806             sleep_time = 30
807             logger.info(
808                 'Sleeping for {} seconds after collectd restart...'.format(
809                     sleep_time))
810             time.sleep(sleep_time)
811             if not collectd_restarted:
812                 for warning in collectd_warnings:
813                     logger.warning(warning)
814                 logger.error(
815                     'Restart of collectd on node {} failed'.format(node_name))
816                 logger.info(
817                     'Testcases on node {} will not be executed'.format(
818                         node_name))
819             else:
820                 for warning in collectd_warnings:
821                     logger.warning(warning)
822
823                 if gnocchi_running:
824                     out_plugins[node_id] = 'Gnocchi'
825                     logger.info("Gnocchi is active and collecting data")
826                 elif aodh_running:
827                     out_plugins[node_id] = 'AODH'
828                     logger.info("AODH withh be tested")
829                     _print_label('Node {}: Test AODH' .format(node_name))
830                     logger.info("Checking if AODH is running")
831                     logger.info("AODH is running")
832                 elif snmp_running:
833                     out_plugins[node_id] = 'SNMP'
834                     logger.info("SNMP will be tested.")
835                     _print_label('NODE {}: Test SNMP'.format(node_id))
836                     logger.info("Checking if SNMP is running.")
837                     logger.info("SNMP is running.")
838                 else:
839                     plugins_to_enable.append('csv')
840                     out_plugins[node_id] = 'CSV'
841                     logger.error("Gnocchi, AODH, SNMP are not running")
842                     logger.info(
843                         "CSV will be enabled for verification "
844                         + "of test plugins.")
845                 if plugins_to_enable:
846                     _print_label(
847                         'NODE {}: Enabling Test Plug-in '.format(node_name)
848                         + 'and Test case execution')
849                 error_plugins = []
850                 if plugins_to_enable and not conf.enable_plugins(
851                         compute_node, plugins_to_enable, error_plugins,
852                         create_backup=False):
853                     logger.error(
854                         'Failed to test plugins on node {}.'.format(node_id))
855                     logger.info(
856                         'Testcases on node {} will not be executed'.format(
857                             node_id))
858                 else:
859                     if plugins_to_enable:
860                         collectd_restarted, collectd_warnings = \
861                             conf.restart_collectd(compute_node)
862                         sleep_time = 30
863                         logger.info(
864                             'Sleeping for {} seconds'.format(sleep_time)
865                             + ' after collectd restart...')
866                         time.sleep(sleep_time)
867                     if plugins_to_enable and not collectd_restarted:
868                         for warning in collectd_warnings:
869                             logger.warning(warning)
870                         logger.error(
871                             'Restart of collectd on node {} failed'.format(
872                                 node_id))
873                         logger.info(
874                             'Testcases on node {}'.format(node_id)
875                             + ' will not be executed.')
876                     else:
877                         if collectd_warnings:
878                             for warning in collectd_warnings:
879                                 logger.warning(warning)
880
881                         for plugin_name in sorted(plugin_labels.keys()):
882                             _exec_testcase(
883                                 plugin_labels, plugin_name, gnocchi_running,
884                                 aodh_running, snmp_running, controllers,
885                                 compute_node, conf, results, error_plugins,
886                                 out_plugins[node_id])
887
888             # _print_label('NODE {}: Restoring config file'.format(node_name))
889             # conf.restore_config(compute_node)
890         mcelog_delete()
891     print_overall_summary(compute_ids, plugin_labels, results, out_plugins)
892
893     if ((len([res for res in results if not res[2]]) > 0)
894             or (len(results) < len(computes) * len(plugin_labels))):
895         logger.error('Some tests have failed or have not been executed')
896         return 1
897     return 0
898
899
900 if __name__ == '__main__':
901     sys.exit(main())