#! /usr/bin/python

# 
# A script that uses dmidecode to interrogate the SMBIOS records
# and dump out a filtered version of the information. Once we
# have a true inventory capability (post-Bonneville), this script
# will more than likely be retired but we may find it useful in
# the meantime.
#

import os
import sys
import isi.app.lib.procs as procs

TOOL = "/usr/local/sbin/dmidecode"

DMITYPE_BIOS = 0
DMITYPE_SYSTEM = 1
DMITYPE_CPU = 4
DMITYPE_MEMORY = 17

# Handle a command error
def cmd_error(cmd=None, output=None):

    print('COMMAND ERROR: "%s" failed' % cmd)

    # If there was output with the failure, display it as well
    if len(output) > 0:
        print('OUTPUT FROM COMMAND:')
        print(output)
    
    return

# Count the number of DMI handles for the specified DMI type
def num_handles(dmitype=None):

    handles = 0
    cmd = '%s -t %d | grep "^Handle"' % (TOOL, dmitype)
    (error, output) = procs.get_cmd_output(cmd)
    if error:
        cmd_error(cmd, output)
        return 0

    for line in output:
        handles += 1

    return handles

# Dump filtered BIOS information
def dump_bios():

    filters = "-e Vendor -e Version -e Release -e Runtime -e ROM"

    cmd = '%s -t %d | grep %s' % (TOOL, DMITYPE_BIOS, filters)
    (error, output) = procs.get_cmd_output(cmd)
    if error:
        cmd_error(cmd, output)
        return None

    number_of_records = num_handles(DMITYPE_BIOS)
    if number_of_records > 1:
        print 'WARNING: Unexpected number of BIOS records found'
    print 'BIOS Information -- %d record(s) found' % number_of_records
    for line in output:
        print line
    
    print ''
    return

# Dump filtered System information
def dump_system():
    
    filters = "-e Manufacturer -e Product -e Version -e Serial -e UUID -e SKU"

    cmd = '%s -t %d | grep %s' % (TOOL, DMITYPE_SYSTEM, filters)
    (error, output) = procs.get_cmd_output(cmd)
    if error:
        cmd_error(cmd, output)
        return None

    number_of_records = num_handles(DMITYPE_SYSTEM)
    if number_of_records > 1:
        print 'WARNING: Unexpected number of System records found'
    print 'System Information -- %d record(s) found' % number_of_records
    for line in output:
        print line
    
    print ''
    return

# Dump filtered CPU information
def dump_cpu():

    filters = "-e 'Socket Des' -e Family -e Manufacturer -e ID -e Signature \
               -e Version -e 'External Cl' -e 'Current Speed' -e Status \
               -e Serial -e Part -e Core -e Thread"

    cmd = '%s -t %d | grep %s' % (TOOL, DMITYPE_CPU, filters)
    (error, output) = procs.get_cmd_output(cmd)
    if error:
        cmd_error(cmd, output)
        return None

    cpu_number = 1
    add_marker = True
    number_of_records = num_handles(DMITYPE_CPU)
    print 'CPU Information -- %d record(s) found' % number_of_records
    for line in output:
        if add_marker: 
            print '   ===== CPU %d =====' % cpu_number
            add_marker = False
        print line
        # Cheezy way of locating the end of each record
        if line.count('Thread'):
            print ''
            cpu_number += 1
            add_marker = True

    print ''
    return

# Dump filtered Memory information
def dump_memory():
    
    filters = "-e 'Total Width' -e 'Data Width' -e Size -e Locator -e Bank \
               -e Type -e Speed -e Manufacturer -e Serial -e Part"

    cmd = '%s -t %d | grep %s' % (TOOL, DMITYPE_MEMORY, filters)
    (error, output) = procs.get_cmd_output(cmd)
    if error:
        cmd_error(cmd, output)
        return None

    dimm_number = 1
    add_marker = True
    number_of_records = num_handles(DMITYPE_MEMORY)
    print 'Memory Information -- %d record(s) found' % number_of_records
    for line in output:
        if add_marker: 
            print '   ===== DIMM %d =====' % dimm_number
            add_marker = False
        print line
        # Cheezy way of locating the end of each record
        if line.count('Part'):
            print ''
            dimm_number += 1
            add_marker = True

    print ''
    return

def main(args):

    dump_bios()
    dump_system()
    dump_cpu()
    dump_memory()

if __name__ == '__main__':
    main(sys.argv)
