summaryrefslogtreecommitdiff
diff options
-rwxr-xr-xbin/ipmi_test84
-rwxr-xr-xbin/ipmi_test.py278
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()