diff --git a/hwinfo/host/cpuinfo.py b/hwinfo/host/cpuinfo.py new file mode 100644 index 0000000..af1b58d --- /dev/null +++ b/hwinfo/host/cpuinfo.py @@ -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'), + ] diff --git a/hwinfo/host/tests/data/cpuinfo b/hwinfo/host/tests/data/cpuinfo new file mode 100644 index 0000000..8168388 --- /dev/null +++ b/hwinfo/host/tests/data/cpuinfo @@ -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: + diff --git a/hwinfo/host/tests/test_cpuinfo.py b/hwinfo/host/tests/test_cpuinfo.py new file mode 100644 index 0000000..38c55cb --- /dev/null +++ b/hwinfo/host/tests/test_cpuinfo.py @@ -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) diff --git a/hwinfo/tools/inspector.py b/hwinfo/tools/inspector.py index 66e2c84..43ebc89 100644 --- a/hwinfo/tools/inspector.py +++ b/hwinfo/tools/inspector.py @@ -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() @@ -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) @@ -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: @@ -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: @@ -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', @@ -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.") @@ -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:"