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