Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 40 additions & 15 deletions hwinfo/pci/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,90 @@

class PCIDevice(object):

NONE_VALUE = 'unknown'

def __init__(self, record):
self.rec = record

def lookup_value(self, k):
if k in self.rec:
return self.rec[k]
else:
return "Unknown"
return None

def _fmt(self, value, wrap=None):
if not value:
return self.NONE_VALUE
else:
if wrap:
return "%s%s%s" % (wrap, value, wrap)
else:
return value

def get_device_name(self):
wrap = None
name = self.lookup_value('pci_device_name')

# Fall back to using pci_device_string if it exists.
if not name:
name = self.lookup_value('pci_device_string')
wrap = '-'

if name == 'Device':
# If the input has come from lspci, this is the value for
# not being able to find a key in the pciids db.
return '[Device %s]' % self.get_device_id()
else:
return name
return self._fmt(name, wrap)


def get_device_id(self):
return self.lookup_value('pci_device_id')
return self._fmt(self.lookup_value('pci_device_id'))

def get_vendor_name(self):
return self.lookup_value('pci_vendor_name')
return self._fmt(self.lookup_value('pci_vendor_name'))

def get_vendor_id(self):
return self.lookup_value('pci_vendor_id')
return self._fmt(self.lookup_value('pci_vendor_id'))

def get_subdevice_name(self):
name = self.lookup_value('pci_subdevice_name')
wrap = None

# Fall back to using pci_device_string if it exists.
if not name:
name = self.lookup_value('pci_device_sub_string')
wrap = '-'

if name == 'Device':
# If the input has come from lspci, this is the value for
# not being able to find a key in the pciids db.
return '[Device %s]' % self.get_subdevice_id()
else:
return name
return self._fmt(name, wrap)

def get_subdevice_id(self):
return self.lookup_value('pci_subdevice_id')
return self._fmt(self.lookup_value('pci_subdevice_id'))

def get_subvendor_name(self):
return self.lookup_value('pci_subvendor_name')
return self._fmt(self.lookup_value('pci_subvendor_name'))

def get_subvendor_id(self):
return self.lookup_value('pci_subvendor_id')
return self._fmt(self.lookup_value('pci_subvendor_id'))

def get_pci_id(self):
return "%s:%s %s:%s" % (
self.lookup_value('pci_vendor_id'),
self.lookup_value('pci_device_id'),
self.lookup_value('pci_subvendor_id'),
self.lookup_value('pci_subdevice_id'),
self._fmt(self.lookup_value('pci_vendor_id')),
self._fmt(self.lookup_value('pci_device_id')),
self._fmt(self.lookup_value('pci_subvendor_id')),
self._fmt(self.lookup_value('pci_subdevice_id')),
)

def get_pci_class(self):
return self.lookup_value('pci_device_class')
return self._fmt(self.lookup_value('pci_device_class'))

def is_subdevice(self):
return self.lookup_value('pci_subvendor_id') and self.lookup_value('pci_subdevice_id')
return self.lookup_value('pci_subvendor_id') and self.lookup_value('pci_subdevice_id') or self.lookup_value('pci_device_sub_string')

def get_info(self):

Expand Down
14 changes: 7 additions & 7 deletions hwinfo/pci/lspci.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
class ParserException(Exception):
pass

LABEL_REGEX = r'[\w+\ \.\-\/\[\]\(\)]+'
CODE_REGEX = r'[0-9a-fA-F]{4}'
BUSID_REGEX = r'[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F]'

class LspciVVParser(CommandParser):
"""Parser object for the output of lspci -vv"""

ITEM_REGEXS = [
r'(?P<pci_device_bus_id>([0-9][0-9]:[0-9][0-9]\.[0-9]))\ (?P<pci_device_class_name>[\w\ ]*):\ (?P<pci_device_string>(.*))\n',
r'(?P<pci_device_bus_id>(' + BUSID_REGEX + r'))\ (?P<pci_device_class_name>' + LABEL_REGEX + r'):\ (?P<pci_device_string>(.*))\n',
r'Product\ Name:\ (?P<pci_device_vpd_product_name>(.)*)\n',
r'Subsystem:\ (?P<pci_device_sub_string>(.)*)\n',
]
Expand All @@ -27,7 +31,7 @@ class LspciNParser(CommandParser):

#ff:0d.1 0880: 8086:0ee3 (rev 04)
ITEM_REGEXS = [
r'(?P<pci_device_bus_id>([0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]\.[0-9a-f]))\ (?P<pci_device_class>[0-9a-f]{4}):\ (?P<pci_vendor_id>[0-9a-f]{4}):(?P<pci_device_id>[0-9a-f]{4})',
r'(?P<pci_device_bus_id>(' + BUSID_REGEX + r'))\ (?P<pci_device_class>' + CODE_REGEX + r'):\ (?P<pci_vendor_id>' + CODE_REGEX + r'):(?P<pci_device_id>' + CODE_REGEX + r')',
]

ITEM_SEPERATOR = "\n"
Expand All @@ -39,17 +43,13 @@ class LspciNParser(CommandParser):
'pci_device_class',
]


LABEL_REGEX = r'[\w+\ \.\-\/\[\]\(\)]+'
CODE_REGEX = r'[0-9a-fA-F]{4}'

class LspciNNMMParser(CommandParser):
"""Parser object for the output of lspci -nnmm"""

#02:00.1 "Ethernet controller [0200]" "Broadcom Corporation [14e4]" "NetXtreme II BCM5716 Gigabit Ethernet [163b]" -r20 "Dell [1028]" "Device [02a3]"

ITEM_REGEXS = [
r'(?P<pci_device_bus_id>([0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F]))\ "(?P<pci_device_class_name>' + LABEL_REGEX + r')\ \[(?P<pci_device_class>' + CODE_REGEX + r')\]"' \
r'(?P<pci_device_bus_id>(' + BUSID_REGEX + r'))\ "(?P<pci_device_class_name>' + LABEL_REGEX + r')\ \[(?P<pci_device_class>' + CODE_REGEX + r')\]"' \
+ r'\ "(?P<pci_vendor_name>' + LABEL_REGEX + r')\ \[(?P<pci_vendor_id>' + CODE_REGEX + r')\]"\ "(?P<pci_device_name>' + LABEL_REGEX + r')\ \[(?P<pci_device_id>' + CODE_REGEX + r')\]"' \
+ r'\ .*\"((?P<pci_subvendor_name>' + LABEL_REGEX + r')\ \[(?P<pci_subvendor_id>' + CODE_REGEX + r')\])*"\ "((?P<pci_subdevice_name>' + LABEL_REGEX + r')\ \[(?P<pci_subdevice_id>' + CODE_REGEX + r')\])*',
]
Expand Down
7 changes: 7 additions & 0 deletions hwinfo/pci/tests/test_lspci.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ def setUp(self):
def test_parse_all_devices(self):
recs = self.parser.parse_items()
self.assertEqual(len(recs), 58)
found = False
for rec in recs:
print rec
if rec['pci_device_bus_id'] == '02:00.0':
self.assertEqual(rec['pci_device_class_name'], 'VGA compatible controller')
found = True
self.assertEqual(found, True)

class TestSingleDeviceNParse(unittest.TestCase):

Expand Down
74 changes: 53 additions & 21 deletions hwinfo/tools/inspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import paramiko
import subprocess
import os
import sys

from hwinfo.pci import PCIDevice
from hwinfo.pci.lspci import *
Expand Down Expand Up @@ -76,18 +77,40 @@ def get_cpu_info(self):
parser = cpuinfo.CPUInfoParser(data)
return parser.parse_items()

class FileNotFound(Exception):
pass

def search_for_file(dirname, filename):
for root, _, files in os.walk(dirname):
if filename in files:
return os.path.join(root, filename)
raise Exception("Could not find '%s' in directory '%s'" % (filename, dirname))
raise FileNotFound("Could not find '%s' in directory '%s'" % (filename, dirname))

def read_from_file(filename):
fh = open(filename, 'r')
data = fh.read()
fh.close()
return data

def parse_data(parser, data):
p = parser(data)
return p.parse_items()

def combine_recs(rec_list, key):
"""Use a common key to combine a list of recs"""
final_recs = {}
for rec in rec_list:
rec_key = rec[key]
if rec_key in final_recs:
for k, v in rec.iteritems():
if k in final_recs[rec_key] and final_recs[rec_key][k] != v:
raise Exception("Mis-match for key '%s'" % k)
final_recs[rec_key][k] = v
else:
final_recs[rec_key] = rec
return final_recs.values()


class HostFromLogs(Host):

def __init__(self, dirname):
Expand All @@ -106,6 +129,20 @@ def get_dmidecode_data(self):
def get_cpuinfo_data(self):
return self._load_from_file('cpuinfo')

def get_pci_devices(self):
try:
devs = super(HostFromLogs, self).get_pci_devices()
return devs
except FileNotFound:
# Fall back to looking for the file lspci-vv.out
print "***lspci-nnm.out found. Falling back to looking for lspci-vv.out and lspci-n.out.***"
lspci_vv_recs = parse_data(LspciVVParser, self._load_from_file('lspci-vv.out'))
lspci_n_recs = parse_data(LspciNParser, self._load_from_file('lspci-n.out'))
all_recs = lspci_vv_recs + lspci_n_recs
recs = combine_recs(all_recs, 'pci_device_bus_id')
return [PCIDevice(rec) for rec in recs]


def pci_filter(devices, types):
res = []
for device in devices:
Expand Down Expand Up @@ -167,6 +204,12 @@ def tabulate_cpu_recs(recs):
]
return tabulate_recs(recs, header)

def print_unit(title, content):
print "%s" % title
print ""
print content
print ""

def main():
"""Entry Point"""

Expand All @@ -184,6 +227,10 @@ def main():
if args.logs:
host = HostFromLogs(args.logs)
else:
if args.machine and not args.username or not args.password:
print "Error: you must specify a username and password to query a remote machine."
sys.exit(1)

host = Host(args.machine, args.username, args.password)

options = []
Expand All @@ -196,35 +243,20 @@ def main():
options = filter_choices

if 'bios' in options:
print "Bios Info:"
print ""
print rec_to_table(host.get_info())
print ""
print_unit("Bios Info:", rec_to_table(host.get_info()))

if 'cpu' in options:
print "CPU Info:"
print ""
print tabulate_cpu_recs(host.get_cpu_info())
print ""
print_unit("CPU Info:", tabulate_cpu_recs(host.get_cpu_info()))

if 'nic' in options:
devices = pci_filter_for_nics(host.get_pci_devices())
print "Ethernet Controller Info:"
print ""
print tabulate_pci_recs([dev.get_rec() for dev in devices])
print ""
print_unit("Ethernet Controller Info:", tabulate_pci_recs([dev.get_rec() for dev in devices]))

if 'storage' in options:
devices = pci_filter_for_storage(host.get_pci_devices())
print "Storage Controller Info:"
print ""
print tabulate_pci_recs([dev.get_rec() for dev in devices])
print ""
print_unit("Storage Controller Info:", tabulate_pci_recs([dev.get_rec() for dev in devices]))

if 'gpu' in options:
devices = pci_filter_for_gpu(host.get_pci_devices())
if devices:
print "GPU Info:"
print ""
print tabulate_pci_recs([dev.get_rec() for dev in devices])
print ""
print_unit("GPU Info:", tabulate_pci_recs([dev.get_rec() for dev in devices]))
Loading