Skip to content

Commit

Permalink
Merge pull request #7 from rdobson/cpuinfo
Browse files Browse the repository at this point in the history
Add support for parsing cpuinfo
  • Loading branch information
rdobson committed Jul 15, 2014
2 parents 426379a + 76fae91 commit 14e7c91
Show file tree
Hide file tree
Showing 4 changed files with 278 additions and 6 deletions.
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

0 comments on commit 14e7c91

Please sign in to comment.