diff options
| -rwxr-xr-x | bin/ipmi_test | 84 | ||||
| -rwxr-xr-x | bin/ipmi_test.py | 278 |
2 files changed, 278 insertions, 84 deletions
diff --git a/bin/ipmi_test b/bin/ipmi_test deleted file mode 100755 index 74a320b7..00000000 --- a/bin/ipmi_test +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/bash - -# Now make sure the modules are loaded - -echo '---------------------------------' && echo 'Verifying kernel modules:' && echo -for module in ipmi_si ipmi_devintf ipmi_powernv ipmi_ssif ipmi_msghandler; do - if lsmod |grep -q $module; then - echo "$module already loaded" - else - echo "Attempting to load $module..." - modprobe $module > /dev/null - result=$? - # If the IPMI drivers don't load, it could be the system has no BMC, or - # the IPMI driver is bad or not applicable to this SUT. - if [ $result -eq 1 ]; then - echo - echo "*******************************************" - echo "WARNING: Unable to load module $module" - echo "Continuing run, but in-band IPMI may fail" - echo "*******************************************" - echo - else - echo "Successfully loaded module $module\n\n" - fi - fi -done - - -# Now get our info from FreeIPMI to make sure communication works -# First lets check chassis status - -echo '---------------------------------' && echo "Fetching chassis status:" && echo -(ipmi-chassis --get-status) && echo && echo "Successfully fetched chassis status..." && chassis=0 \ - || chassis=1 - - -echo '---------------------------------' && echo "Fetching power status:" && echo -(ipmi-chassis --get-status | grep 'System Power') && echo \ - && echo "Successfully fetched power status.." && power=0 || power=1 - - -echo '---------------------------------' && echo "Fetching IPMI channel user data:" && echo -# LP:1794926 Find the active channel. blindly calling user list sometimes -# fails. -channel=99 -for x in 0 1 2 3 4 5 6 7 8 9 10 11 14 15; do - if !(ipmi-config --checkout --lan-channel-number $x 2>&1 >/dev/null | grep -q '^Unable to get Number of Users$'); then - channel=$x - echo "IPMI channel: $channel" && echo - break - fi -done - -# Extrapolate user list from general IPMI function -(ipmi-config --checkout --category=core | grep -A 19 "User[0-9]*.$" | sed '/#/d' | grep -v "Section$" | sed 's/Section //') \ - && echo && echo "Successfully fetched IPMI channel & user data..." && user=0 || user=1 - - -echo '---------------------------------' && echo "Fetching BMC information and checking IPMI version:" && echo -bmc-info && echo && echo "Successfully called BMC-info..." && echo && bmc=0 || bmc=1 - -version=$(bmc-info | awk '/IPMI Version/ {print $4}') -echo "IPMI Version: $version" && echo -# parse major from ipmi version -version=$(echo $version| cut -d'.' -f1) -# can refactor to evaluate in final check function -if [ $version -lt 2 ]; then - ipmiV=1 && echo "IPMI version below 2.0..." - else - ipmiV=0 && echo "IPMI version OK..." - fi - - -echo '---------------------------------' && echo "Calling IPMI-locate" && echo -(ipmi-locate) && echo "Successfully called ipmi-locate..." && ipmiL=0 || ipmiL=1 - - -# if everything passes, exit 0 -[ $chassis -eq 0 ] && [ $power -eq 0 ] && [ $user -eq 0 ] && [ $bmc -eq 0 ] && [ $ipmiV -eq 0 ] && [ $ipmiL -eq 0 ] \ - && echo "## IPMI checks succeeded. ##" && echo && exit 0 \ - || echo "## FAILURE: chassis: $chassis power: $power user: $user bmc: $bmc ipmi_version: $ipmiV ipmi_locate: $ipmiL ##" - -# otherwise exit 1 -exit 1 diff --git a/bin/ipmi_test.py b/bin/ipmi_test.py new file mode 100755 index 00000000..7563c237 --- /dev/null +++ b/bin/ipmi_test.py @@ -0,0 +1,278 @@ +#!/usr/bin/env python3 +# Copyright 2020 Canonical Ltd. +# All rights reserved. +# +# Written by: +# Adrian Lane <adrian.lane@canonical.com> + +import subprocess +import re +import os +import time + + +def main(): + # globals + # using relative paths + start_time = time.clock() + path_lsmod = 'lsmod' + path_modprobe = 'modprobe' + kernel_modules = ( + 'ipmi_si', + 'ipmi_devintf', + 'ipmi_powernv', + 'ipmi_ssif', + 'ipmi_msghandler') + path_ipmi_chassis = 'ipmi-chassis' + path_ipmi_config = 'ipmi-config' + path_bmc_info = 'bmc-info' + path_ipmi_locate = 'ipmi-locate' + + print ('Running IPMI tests...') + # check kernel modules + kernel_mods(path_lsmod, path_modprobe, kernel_modules) + # tally results + results = [] + results.append(impi_chassis(path_ipmi_chassis)) + results.append(pwr_status(path_ipmi_chassis)) + results.append(ipmi_channel(path_ipmi_config)) + results.append(bmc_info(path_bmc_info)) + results.append(ipmi_version(path_bmc_info)) + results.append(ipmi_locate(path_ipmi_locate)) + + if sum(results) > 0: + end_time = time.clock() + total_time = "{0:.4f}".format(end_time - start_time) + print('-----------------------') + print('## IPMI tests failed! ##') + print( + f'## Chassis: {results[0]} Power: {results[1]} ' + f'Channel: {results[2]} BMC: {results[3]} ' + f'IPMI Version: {results[4]} IPMI Locate: {results[5]} ##') + print ('## Total time:', str(total_time) + 's ##') + else: + end_time = time.clock() + total_time = "{0:.4f}".format(end_time - start_time) + print('-----------------------') + print('## IPMI tests passed! ##') + print ('## Total time:', str(total_time) + 's ##') + + +def kernel_mods(path_lsmod, path_modprobe, kernel_modules): + print('-----------------------') + print ('Verifying kernel modules:') + try: + process = subprocess.Popen( + [path_lsmod], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, error = process.communicate(timeout=15) + for module in kernel_modules: + if module in output.decode('utf-8'): + print ('-', module, 'already loaded.') + else: + try: + subprocess.check_call( + [path_modprobe, module], + stderr=subprocess.PIPE, timeout=15) + print ('- Successfully loaded module', module) + except subprocess.TimeoutExpired: + print (f'{e.timeout} timeout calling modprobe!') + except subprocess.CalledProcessError: + print (' *******************************************') + print (f' WARNING: Unable to load module {module}') + print (' Continuing run, but in-band IPMI may fail') + print (' *******************************************') + except EnvironmentError: + print ('Unable to invoke modprobe!\n') + print ('') + except subprocess.TimeoutExpired as e: + print (f'{e.timeout} timeout calling lsmod!') + except subprocess.SubprocessError: + # fail if true? + print ('Error calling lsmod!\n') + except EnvironmentError: + # fail if true? + print ('Unable to invoke lsmod!\n') + + +def impi_chassis(path_ipmi_chassis): + print('-----------------------') + print('Fetching chassis status:') + start_time = time.clock() + try: + fnull = open(os.devnull, 'w') + subprocess.check_call( + [path_ipmi_chassis, '--get-status'], + stdout=fnull, stderr=subprocess.PIPE, timeout=15) + end_time = time.clock() + total_time = "{0:.4f}".format(end_time - start_time) + print('Successfully fetched chassis status!') + print ('(took', str(total_time) + 's)\n') + return 0 + except subprocess.TimeoutExpired as e: + print (f'Timeout ({e.timeout}s) fetching chassis status!\n') + return 1 + except subprocess.CalledProcessError: + print ('Error calling ipmi-chassis!\n') + return 1 + except EnvironmentError: + print ('Unable to invoke ipmi-chassis!\n') + return 1 + + +def pwr_status(path_ipmi_chassis): + print('-----------------------') + print('Fetching power status:') + start_time = time.clock() + regex = re.compile('^System Power') + matches = 0 + try: + process = subprocess.Popen( + [path_ipmi_chassis, '--get-status'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, error = process.communicate(timeout=15) + output = output.decode('utf-8') + for line in output.rstrip().split('\n'): + if re.search(regex, line): + matches += 1 + end_time = time.clock() + total_time = "{0:.4f}".format(end_time - start_time) + print ('Successfully fetched power status!') + print ('(took', str(total_time) + 's)\n') + return 0 + if matches == 0: + print('Unable to retrieve power status via IPMI.\n') + return 1 + except subprocess.TimeoutExpired as e: + print (f'Timeout ({e.timeout}s) fetching power status!\n') + return 1 + except subprocess.SubprocessError: + print ('Error calling ipmi-chassis!\n') + return 1 + except EnvironmentError: + print ('Unable to invoke ipmi-chassis!\n') + return 1 + + +def ipmi_channel(path_ipmi_config): + print('-----------------------') + print('Fetching IPMI channel:') + start_time = time.clock() + # inverse match (look ahead) + regex = re.compile('^(?!Unable to get Number of Users)') + matches = 0 + try: + # test channels 0 - 15 + for i in range(16): + if (i == 16 and matches == 0): + print('Unable to fetch IPMI channel!\n') + return 1 + else: + process = subprocess.Popen( + [path_ipmi_config, '--checkout', '--lan-channel-number', str(i)], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, error = process.communicate(timeout=15) + if re.search(regex, output.decode('utf-8')): + matches += 1 + end_time = time.clock() + total_time = "{0:.4f}".format(end_time - start_time) + print ('IPMI Channel:', i) + print('(took', str(total_time) + 's)\n') + return 0 + except subprocess.TimeoutExpired as e: + print (f'Timeout ({e.timeout}s) fetching IPMI channel!\n') + return 1 + except subprocess.SubprocessError: + print ('Error calling ipmi-config!\n') + return 1 + except EnvironmentError: + print ('Unable to invoke ipmi-config!\n') + return 1 + + +def bmc_info(path_bmc_info): + print('-----------------------') + print('Fetching BMC information:') + start_time = time.clock() + try: + fnull = open(os.devnull, 'w') + subprocess.check_call( + [path_bmc_info], + stdout=fnull, stderr=subprocess.PIPE, timeout=15) + end_time = time.clock() + total_time = "{0:.4f}".format(end_time - start_time) + print('Successfully fetched chassis status!') + print ('(took', str(total_time) + 's)\n') + return 0 + except subprocess.TimeoutExpired as e: + print (f'Timeout ({e.timeout}s) fetching BMC information!\n') + return 1 + except subprocess.CalledProcessError: + print ('Error calling bmc-info!\n') + return 1 + except EnvironmentError: + print ('Unable to invoke bmc-info!\n') + return 1 + + +def ipmi_version(path_bmc_info): + print('-----------------------') + print('Testing IPMI version:') + start_time = time.clock() + try: + process = subprocess.Popen( + [path_bmc_info], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, error = process.communicate(timeout=15) + output = output.decode('utf-8') + # Prefer .index() over .find() for exception handling + res_index = output.index('IPMI Version') + version = output[(res_index + 24):(res_index + 27)] + print ('IPMI Version:', version) + if float(version) < 2.0: + print ('IPMI Version below 2.0!') + return 1 + else: + end_time = time.clock() + total_time = "{0:.4f}".format(end_time - start_time) + print('(took', str(total_time) + 's)\n') + return 0 + except subprocess.TimeoutExpired as e: + print (f'Timeout ({e.timeout}s) fetching IPMI version!\n') + return 1 + except subprocess.SubprocessError: + print ('Error calling bmc-info!\n') + return 1 + except EnvironmentError: + print ('Unable to invoke bmc-info!\n') + return 1 + + +def ipmi_locate(path_ipmi_locate): + print('-----------------------') + print('Testing ipmi-locate:') + start_time = time.clock() + try: + fnull = open(os.devnull, 'w') + subprocess.check_call( + [path_ipmi_locate], + stdout=fnull, stderr=subprocess.PIPE, timeout=15) + end_time = time.clock() + total_time = "{0:.4f}".format(end_time - start_time) + print('Successfully called ipmi-locate!') + print ('(took', str(total_time) + 's)\n') + return 0 + except subprocess.TimeoutExpired as e: + print (f'Timeout ({e.timeout}s) testing impmi-locate!\n') + return 1 + except subprocess.CalledProcessError: + print ('Error calling ipmi-locate!\n') + return 1 + except EnvironmentError: + print ('Unable to invoke ipmi-locate!\n') + return 1 + + +# call main() +if __name__ == '__main__': + main() |
