diff options
| author | Sylvain Pineau <sylvain.pineau@canonical.com> | 2016-10-07 09:48:55 +0200 |
|---|---|---|
| committer | Sylvain Pineau <sylvain.pineau@canonical.com> | 2016-10-07 09:48:55 +0200 |
| commit | 33a440473829a82188a9547146789fae72185c5e (patch) | |
| tree | aa8efa1434f252432ab99274eaca45a9427207bc /bin/dmitest | |
| parent | cbbe2fe63a1b22f6d0873bfe11ff3e834a1a883c (diff) | |
Import plainbox-provider-checkbox_0.21.orig.tar.gzupstream-0.21patched-0.21-1
Diffstat (limited to 'bin/dmitest')
| -rwxr-xr-x | bin/dmitest | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/bin/dmitest b/bin/dmitest new file mode 100755 index 0000000..02e67a9 --- /dev/null +++ b/bin/dmitest @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 +# +# This file is part of Checkbox. +# +# Copyright 2014 Canonical Ltd. +# +# Checkbox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, +# as published by the Free Software Foundation. +# +# Checkbox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Checkbox. If not, see <http://www.gnu.org/licenses/>. +# +# Test for sane dmidecode output, particularly with respect to +# various manufacturer information fields. Also, verify that the +# system reports a chassis type that suits its class (server or +# desktop/laptop) +# +# By: Rod Smith +# +# Parameters: +# * --dmifile {filename} -- Input filename; optional. If specified, +# file is used instead of dmidecode output. +# * --test_versions -- Include chassis, system, and base boad version +# numbers among tests. +# * --test_serials -- Include system and base board serial numbers among +# tests. +# * 'desktop' or 'server' -- Type of system being tested. + +import re +import subprocess +import sys + +from argparse import ArgumentParser + +# Command to retrieve DMI information +COMMAND = "dmidecode" + + +def find_in_section(stream, section, label, strings, find_empty): + """ Search for a set of strings on a labelled line in a section + of the output. + :param stream: + input text stream (dmidecode output) + :param section: + section label in which to search (e.g., "Chassis Information") + :param label: + label of line on which to search (e.g., "Type:") + :param strings: + set of strings for which to search (e.g., ["server", "blade"]) + :param find_empty: + if True, matches empty label field (as if '""' were passed as + a strings value) + :returns found: + True if one or more of strings was found on "label" line in "section" + section, or if "label" line is empty AND find_empty is True; + False otherwise + """ + start_looking = False + found = False + empty = True + for line in stream: + if line == section: + start_looking = True + if start_looking and re.search(label, line): + print("\n" + section) + print(line.strip()) + empty = len(line.strip()) == len(label) + if empty and find_empty: + found = True + for s in strings: + if re.search(s, line, flags=re.IGNORECASE): + found = True + break + start_looking = False + + return found + + +def main(): + parser = ArgumentParser("dmitest") + parser.add_argument('system_type', + help="System type ('server' or 'desktop').", + choices=['server', 'desktop']) + parser.add_argument('--dmifile', + help="File to use in lieu of dmidecode.") + parser.add_argument('--test_versions', action="store_true", + help="Set to check version information") + parser.add_argument('--test_serials', action="store_true", + help="Set to check serial number information") + args = parser.parse_args() + + try: + if args.dmifile: + print("Reading " + args.dmifile + " as DMI data") + stream = subprocess.check_output(['cat', args.dmifile], universal_newlines=True).splitlines() + else: + stream = subprocess.check_output(COMMAND, universal_newlines=True).splitlines() + except subprocess.CalledProcessError as err: + print("Error running {}: {}".format(COMMAND, err)) + return 1 + + retval = 0 + + """ + NOTE: System type is encoded in both the "Chassis Information" and "Base + Board Type" sections. The former is more reliable, so we do a whitelist + test on it -- the type MUST be specified correctly. The "Base Board Type" + section is less reliable, so rather than flag large numbers of systems + for having "Unknown", "Other", or something similar here, we just flag + it when it's at odds with the type passed on the command line. Also, + the "Base Board Type" may specify a desktop or tower system on servers + shipped in those form factors, so we don't flag that combination as an + error. + """ + if args.system_type == 'server': + if not find_in_section(stream, 'Chassis Information', 'Type:', + ['server', 'rack mount', 'blade', + 'expansion chassis', 'multi-system'], False): + print("*** Incorrect or unknown server chassis type!") + retval = 1 + if find_in_section(stream, 'Base Board Information', 'Type:', + ['portable', 'notebook', 'space-saving', + 'all in one'], False): + print("*** Incorrect server base board type!") + retval = 1 + else: + if not find_in_section(stream, 'Chassis Information', 'Type:', + ['notebook', 'portable', 'laptop', 'desktop', + 'lunch box', 'space-saving', 'tower', + 'all in one', 'hand held'], False): + print("*** Incorrect or unknown desktop chassis type!") + retval = 1 + if find_in_section(stream, 'Base Board Information', 'Type:', + ['rack mount', 'server', 'multi-system', + 'interconnect board'], False): + print("*** Incorrect desktop base board type!") + retval = 1 + + if find_in_section(stream, 'Chassis Information', 'Manufacturer:', + ['empty', 'chassis manufacture', 'null', 'insyde', + 'to be filled by o\.e\.m\.', 'no enclosure', + '\.\.\.\.\.'], True): + print("*** Invalid chassis manufacturer!") + retval = 1 + + if find_in_section(stream, 'System Information', 'Manufacturer:', + ['system manufacture', 'insyde', 'standard', + 'to be filled by o\.e\.m\.', 'no enclosure'], True): + print("*** Invalid system manufacturer!") + retval = 1 + + if find_in_section(stream, 'Base Board Information', 'Manufacturer:', + ['to be filled by o\.e\.m\.'], True): + print("*** Invalid base board manufacturer!") + retval = 1 + + if find_in_section(stream, 'System Information', 'Product Name:', + ['system product name', 'to be filled by o\.e\.m\.'], + False): + print("*** Invalid system product name!") + retval = 1 + + if find_in_section(stream, 'Base Board Information', 'Product Name:', + ['base board product name', + 'to be filled by o\.e\.m\.'], False): + print("*** Invalid base board product name!") + retval = 1 + + if args.test_versions: + + if find_in_section(stream, 'Chassis Information', 'Version:', + ['to be filled by o\.e\.m\.', 'empty'], + False): + print("*** Invalid chassis version!") + retval = 1 + + if find_in_section(stream, 'System Information', 'Version:', + ['to be filled by o\.e\.m\.', '\(none\)', + 'null', 'system version', 'not applicable', + '\.\.\.\.\.'], False): + print("*** Invalid system information version!") + retval = 1 + + if find_in_section(stream, 'Base Board Information', 'Version:', + ['base board version', + 'empty', 'to be filled by o\.e\.m\.'], False): + print("*** Invalid base board version!") + retval = 1 + + if args.test_serials: + + if find_in_section(stream, 'System Information', 'Serial Number:', + ['to be filled by o\.e\.m\.', + 'system serial number', '\.\.\.\.\.'], + False): + print("*** Invalid system information serial number!") + retval = 1 + + if find_in_section(stream, 'Base Board Information', 'Serial Number:', + ['n/a', 'base board serial number', + 'to be filled by o\.e\.m\.', 'empty', '\.\.\.'], + False): + print("*** Invalid base board serial number!") + retval = 1 + + if find_in_section(stream, 'Processor Information', 'Version:', + ['sample'], False): + print("*** Invalid processor information!") + retval = 1 + + # In review of dmidecode data on 10/23/2014, no conspicuous problems + # found in BIOS Information section's Vendor, Version, or Release Date + # fields. Therefore, no tests based on these fields have been written. + + if retval: + print("\nFailed one or more tests (see above)") + else: + print("\nPassed all tests") + + return retval + + +if __name__ == "__main__": + sys.exit(main()) |
