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