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
31 changes: 31 additions & 0 deletions hwinfo/host/cpuinfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Module for parsing the output of /proc/cpuinfo"""

from hwinfo.util import CommandParser

REGEX_TEMPLATE = r'%s([\ \t])+\:\ (?P<%s>.*)'

class CPUInfoParser(CommandParser):

ITEM_SEPERATOR = "\n\n"

ITEM_REGEXS = [
REGEX_TEMPLATE % ('processor', 'processor'),
REGEX_TEMPLATE % ('vendor_id', 'vendor_id'),
REGEX_TEMPLATE % (r'cpu\ family', 'cpu_family'),
REGEX_TEMPLATE % ('model', 'model'),
REGEX_TEMPLATE % (r'model\ name', 'model_name'),
REGEX_TEMPLATE % ('stepping', 'stepping'),
REGEX_TEMPLATE % ('microcode', 'microcode'),
REGEX_TEMPLATE % (r'cpu\ MHz', 'cpu_mhz'),
REGEX_TEMPLATE % (r'cache\ size', 'cache_size'),
REGEX_TEMPLATE % (r'fpu', 'fpu'),
REGEX_TEMPLATE % (r'fpu_exception', 'fpu_exception'),
REGEX_TEMPLATE % (r'cpuid\ level', 'cpuid_level'),
REGEX_TEMPLATE % (r'wp', 'wp'),
REGEX_TEMPLATE % (r'flags', 'flags'),
REGEX_TEMPLATE % (r'bogomips', 'bogomips'),
REGEX_TEMPLATE % (r'clflush\ size', 'clflush_size'),
REGEX_TEMPLATE % (r'cache_alignment', 'cache_alignment'),
REGEX_TEMPLATE % (r'address\ sizes', 'address_sizes'),
REGEX_TEMPLATE % (r'power\ management', 'power_management'),
]
80 changes: 80 additions & 0 deletions hwinfo/host/tests/data/cpuinfo
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 30
model name : Intel(R) Xeon(R) CPU X3430 @ 2.40GHz
stepping : 5
microcode : 0x3
cpu MHz : 2394.052
cache size : 8192 KB
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu de tsc msr pae mce cx8 apic sep mca cmov pat clflush acpi mmx fxsr sse sse2 ss ht syscall nx lm constant_tsc rep_good nopl nonstop_tsc pni monitor vmx est ssse3 cx16 sse4_1 sse4_2 popcnt hypervisor lahf_lm dtherm tpr_shadow vnmi flexpriority ept vpid
bogomips : 4788.10
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 30
model name : Intel(R) Xeon(R) CPU X3430 @ 2.40GHz
stepping : 5
microcode : 0x3
cpu MHz : 2394.052
cache size : 8192 KB
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu de tsc msr pae mce cx8 apic sep mca cmov pat clflush acpi mmx fxsr sse sse2 ss ht syscall nx lm constant_tsc rep_good nopl nonstop_tsc pni monitor vmx est ssse3 cx16 sse4_1 sse4_2 popcnt hypervisor lahf_lm dtherm tpr_shadow vnmi flexpriority ept vpid
bogomips : 4788.10
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

processor : 2
vendor_id : GenuineIntel
cpu family : 6
model : 30
model name : Intel(R) Xeon(R) CPU X3430 @ 2.40GHz
stepping : 5
microcode : 0x3
cpu MHz : 2394.052
cache size : 8192 KB
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu de tsc msr pae mce cx8 apic sep mca cmov pat clflush acpi mmx fxsr sse sse2 ss ht syscall nx lm constant_tsc rep_good nopl nonstop_tsc pni monitor vmx est ssse3 cx16 sse4_1 sse4_2 popcnt hypervisor lahf_lm dtherm tpr_shadow vnmi flexpriority ept vpid
bogomips : 4788.10
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

processor : 3
vendor_id : GenuineIntel
cpu family : 6
model : 30
model name : Intel(R) Xeon(R) CPU X3430 @ 2.40GHz
stepping : 5
microcode : 0x3
cpu MHz : 2394.052
cache size : 8192 KB
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu de tsc msr pae mce cx8 apic sep mca cmov pat clflush acpi mmx fxsr sse sse2 ss ht syscall nx lm constant_tsc rep_good nopl nonstop_tsc pni monitor vmx est ssse3 cx16 sse4_1 sse4_2 popcnt hypervisor lahf_lm dtherm tpr_shadow vnmi flexpriority ept vpid
bogomips : 4788.10
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

128 changes: 128 additions & 0 deletions hwinfo/host/tests/test_cpuinfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
"""Module for unittesting dmidecode methods"""

import unittest
from hwinfo.host.cpuinfo import CPUInfoParser

DATA_DIR = 'hwinfo/host/tests/data'

class CPUInfoParserTests(unittest.TestCase):

DATA = """
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 30
model name : Intel(R) Xeon(R) CPU X3430 @ 2.40GHz
stepping : 5
microcode : 0x3
cpu MHz : 2394.052
cache size : 8192 KB
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu de tsc msr pae mce cx8 apic sep mca cmov pat clflush acpi mmx fxsr sse sse2 ss ht syscall nx lm constant_tsc rep_good nopl nonstop_tsc pni monitor vmx est ssse3 cx16 sse4_1 sse4_2 popcnt hypervisor lahf_lm dtherm tpr_shadow vnmi flexpriority ept vpid
bogomips : 4788.10
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
"""

DATA_REC = {
'processor': '0',
'vendor_id': 'GenuineIntel',
'cpu_family': '6',
'model': '30',
'model_name': 'Intel(R) Xeon(R) CPU X3430 @ 2.40GHz',
'stepping': '5',
'microcode': '0x3',
'cpu_mhz': '2394.052',
'cache_size': '8192 KB',
'fpu': 'yes',
'fpu_exception': 'yes',
'cpuid_level': '11',
'wp': 'yes',
'flags': 'fpu de tsc msr pae mce cx8 apic sep mca cmov pat clflush acpi mmx fxsr sse sse2 ss ht syscall nx lm constant_tsc rep_good nopl nonstop_tsc pni monitor vmx est ssse3 cx16 sse4_1 sse4_2 popcnt hypervisor lahf_lm dtherm tpr_shadow vnmi flexpriority ept vpid',
'bogomips': '4788.10',
'clflush_size': '64',
'cache_alignment': '64',
'address_sizes': '36 bits physical, 48 bits virtual',
'power_management': '',
}


def setUp(self):
self.parser = CPUInfoParser(self.DATA.strip())

def _assert_equal(self, key):
rec = self.parser.parse_items()[0]
return self.assertEqual(rec[key], self.DATA_REC[key])

def test_cpuinfo_processor(self):
return self._assert_equal('processor')

def test_vendor_id(self):
return self._assert_equal('vendor_id')

def test_cpu_family(self):
return self._assert_equal('cpu_family')

def test_model(self):
return self._assert_equal('model')

def test_model_name(self):
return self._assert_equal('model_name')

def test_stepping(self):
return self._assert_equal('stepping')

def test_microcode(self):
return self._assert_equal('microcode')

def test_cpu_mhz(self):
return self._assert_equal('cpu_mhz')

def test_cache_size(self):
return self._assert_equal('cache_size')

def test_fpu(self):
return self._assert_equal('fpu')

def test_fpu_exception(self):
return self._assert_equal('fpu_exception')

def test_cpuid_level(self):
return self._assert_equal('cpuid_level')

def test_wp(self):
return self._assert_equal('wp')

def test_flags(self):
return self._assert_equal('flags')

def test_bogomips(self):
return self._assert_equal('bogomips')

def test_clflush_size(self):
return self._assert_equal('clflush_size')

def test_cache_alignment(self):
return self._assert_equal('cache_alignment')

def test_address_sizes(self):
return self._assert_equal('address_sizes')

class CPUInfoMultipleParseTest(unittest.TestCase):

DATA_FILE = "%s/cpuinfo" % DATA_DIR

def setUp(self):
fh = open(self.DATA_FILE)
data = fh.read()
fh.close()
self.parser = CPUInfoParser(data)

def test_number_of_processors(self):
recs = self.parser.parse_items()
self.assertEqual(len(recs), 4)
45 changes: 39 additions & 6 deletions hwinfo/tools/inspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from hwinfo.pci.lspci import *

from hwinfo.host import dmidecode
from hwinfo.host import cpuinfo

def remote_command(host, username, password, cmd):
client = paramiko.SSHClient()
Expand Down Expand Up @@ -54,6 +55,9 @@ def get_lspci_data(self):
def get_dmidecode_data(self):
return self.exec_command(['dmidecode'])

def get_cpuinfo_data(self):
return self.exec_command(['cat /proc/cpuinfo'])

def get_pci_devices(self):
data = self.get_lspci_data()
parser = LspciNNMMParser(data)
Expand All @@ -66,6 +70,11 @@ def get_info(self):
rec = parser.parse()
return rec

def get_cpu_info(self):
data = self.get_cpuinfo_data()
parser = cpuinfo.CPUInfoParser(data)
return parser.parse_items()

def search_for_file(dirname, filename):
for root, _, files in os.walk(dirname):
if filename in files:
Expand Down Expand Up @@ -93,6 +102,9 @@ def get_lspci_data(self):
def get_dmidecode_data(self):
return self._load_from_file('dmidecode.out')

def get_cpuinfo_data(self):
return self._load_from_file('cpuinfo')

def pci_filter(devices, types):
res = []
for device in devices:
Expand Down Expand Up @@ -122,6 +134,13 @@ def rec_to_table(rec):
table.add_row([k, v])
return table

def tabulate_recs(recs, header):
table = PrettyTable(header)
for rec in recs:
vls = [rec[k] for k in header]
table.add_row(vls)
return table

def tabulate_pci_recs(recs):
header = [
'vendor_name',
Expand All @@ -133,18 +152,26 @@ def tabulate_pci_recs(recs):
'subdevice_name',
'subdevice_id',
]
table = PrettyTable(header)
for rec in recs:
vls = [rec[k] for k in header]
table.add_row(vls)
return table
return tabulate_recs(recs, header)

def tabulate_cpu_recs(recs):
header = [
'processor',
'vendor_id',
'cpu_family',
'model',
'stepping',
'model_name',
'cpu_mhz',
]
return tabulate_recs(recs, header)

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

parser = ArgumentParser(prog="hwinfo")

filter_choices = ['bios', 'nic', 'storage', 'gpu']
filter_choices = ['bios', 'nic', 'storage', 'gpu', 'cpu']
parser.add_argument("-f", "--filter", choices=filter_choices, help="Query a specific class.")
parser.add_argument("-m", "--machine", default='localhost', help="Remote host address.")
parser.add_argument("-u", "--username", help="Username for remote host.")
Expand Down Expand Up @@ -173,6 +200,12 @@ def main():
print rec_to_table(host.get_info())
print ""

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

if 'nic' in options:
devices = pci_filter_for_nics(host.get_pci_devices())
print "Ethernet Controller Info:"
Expand Down