Merge lp:~nelson-chu/opencompute/add-ocp-cpu-memory-job into lp:opencompute/checkbox

Proposed by Nelson Chu
Status: Superseded
Proposed branch: lp:~nelson-chu/opencompute/add-ocp-cpu-memory-job
Merge into: lp:opencompute/checkbox
Diff against target: 506 lines (+365/-43)
7 files modified
data/whitelists/opencompute-certify-local.whitelist (+0/-43)
debian/changelog (+19/-0)
jobs/TC-001-0001-CPU_Memory.txt.in (+31/-0)
jobs/local.txt.in (+7/-0)
scripts/cpu_info (+100/-0)
scripts/memory_info (+78/-0)
scripts/processor_topology (+130/-0)
To merge this branch: bzr merge lp:~nelson-chu/opencompute/add-ocp-cpu-memory-job
Reviewer Review Type Date Requested Status
Nelson Chu Needs Resubmitting
Jeff Lane  Needs Fixing
Review via email: mp+206113@code.launchpad.net

This proposal supersedes a proposal from 2014-02-12.

This proposal has been superseded by a proposal from 2014-02-14.

Description of the change

Scripts and annotations have been modified.

To post a comment you must log in.
Revision history for this message
Jeff Lane  (bladernr) wrote : Posted in a previous version of this proposal
Download full text (4.6 KiB)

Hi Nelson,

Thank you for breaking this into smaller pieces... it makes review a LOT easier. Now, there are some things that need fixing.

I'll take them one file at a time:
data/whitelists/opencompute-certify-local.whitelist looks fine.

jobs/TC-001-0001-CPU_Memory.txt.in:
1: any job that calls a script that needs root permissions to run must include the 'user: root' definition. See the file 'jobs/cpu.txt.in' for some examples where this is necessary. When I run the script cpu_info without root, the cache data is not returned and the test will fail. So this job needs 'user:root'
2: TC-001-0001-003-Memory_Information also needs 'user: root' added to properly run.

jobs/local.txt.in
1: The word "Verified" should be "Verify" in the description field.

scripts/cpu_info:
1: When I manually run the cpu_info script for the test TC-001-0001-001-CPU_information with and without root permissions, I get the following different outputs:
bladernr@klaatu:~/development/ocp-nelson-memory-cpu-test$ ./scripts/cpu_infoIntel(R) Core(TM) i7 CPU Q 720 @ 1.60GHz
Can not found any CPU cache.
bladernr@klaatu:~/development/ocp-nelson-memory-cpu-test$ echo $?
30
bladernr@klaatu:~/development/ocp-nelson-memory-cpu-test$ sudo ./scripts/cpu_info
Intel(R) Core(TM) i7 CPU Q 720 @ 1.60GHz
L1 Cache 32 KB
L2 Cache 256 KB
L3 Cache 6 MB
L3 cache size less than 20MB.
bladernr@klaatu:~/development/ocp-nelson-memory-cpu-test$ echo $?
50

I don't have a system that meets the test criteria, so it will always fail for me. First, the explanation for failure should be more explicit. Example: 'FAIL: Can not find any CPU cache.' for the first example. This is more important in the second example where 'L3 cache size less than 20MB' looks like part of the lshw output. It would be better more explicitly stated as 'FAIL: L3 cache size less than 20MB.'

2: You don't need all those explicit error codes. Checkbox only knows and stores 0 and Not 0 exit codes. A 0 exit code indicates a test passed. A non-zero exit code indicates a failure. Checkbox does not store the actual exit codes. This is not necessarily something you need to change, but you DO need to be aware of the behaviour in case a script behaves differently than expected when you run it via checkbox.

3: The description and spec for this test says: "CPU model should belong to Intel Xeon processor E5-2600 family..." but your test does not fail on non-Xeon processors. For example, when I comment out the error code return for my cache limit on my laptop, I get this output:
bladernr@klaatu:~/development/ocp-nelson-memory-cpu-test$ sudo ./scripts/cpu_info; echo $?
Intel(R) Core(TM) i7 CPU Q 720 @ 1.60GHz
L1 Cache 32 KB
L2 Cache 256 KB
L3 Cache 6 MB
L3 cache size less than 20MB.
0

but my laptop should clearly fail the test case since it's not up to OCP spec.

4: The output needs to be cleaned up a bit. Sorry, I know English is a second language for you, so I'll try to help as much as I can.
    "Can not parser" should be "Can not parse"
    "Can not found" should be "Can not find"
    "# Parser lshw XML for gather" should be "# Parse lshw XML for gathering"

scripts/memory_info:
1: Needs to be run as ...

Read more...

review: Needs Fixing
Revision history for this message
Nelson Chu (nelson-chu) wrote : Posted in a previous version of this proposal

OK, Thank you for your suggestion.
I will revise it accordingly.

Revision history for this message
Nelson Chu (nelson-chu) wrote : Posted in a previous version of this proposal

Hi Jeff,

I have modified scripts. Please help me review them.
Any suggestion will be appreciated.

Thanks,
Nelson

review: Needs Resubmitting
Revision history for this message
Jeff Lane  (bladernr) wrote : Posted in a previous version of this proposal

Before I can go any further, you have a conflict in data/whitelists/opencompute-certify-local.whitelist

To see this, you should do the following:

bzr branch lp:opencompute/checkbox ocp-checkbox
cd ocp-checkbox
bzr merge lp:~nelson-chu/opencompute/add-ocp-cpu-memory-job

That MAY actually just clean it up... but there's a file conflict in there. so please resolve that and I'll review the rest at that time.

review: Needs Fixing
Revision history for this message
Jeff Lane  (bladernr) wrote :

Hi Nelson.. Most everything looks good now. There are two remaining issues...

1: the changelog now seems to have duplicate entreies (see the diff below).

I am sorry if I wasn't clear, but you need to put your entries BETWEEN the version header and timestamp lines. For example:

checkbox (1.16.13~OCP) UNRELEASED; urgency=low

  [ Jeff Marcom ]
  * Updated scripts/network script from lp:checkbox

 -- Jeff Marcom <email address hidden> Tue, 5 Nov 2013 11:12:04 -0400

You entry should come after the "checkbox (1.16.13~OCP) line and above the first entry by Jeff Marcom like so:

checkbox (1.16.13~OCP) UNRELEASED; urgency=low

  [ Nelson Chu ]
  * data/whitelists/opencompute-certify-local.whitelist - Added new jobs to
    certification whitelist
  * jobs/TC-001-0002-Platform_Controller_Hub.txt - Added new jobs for PCH
    test cases
  * jobs/local.txt.in - Added job to parse new PCH job file
  * scripts/check_sata_port - new script to verify SATA port speed
  * scripts/check_usb_port - new script to verify USB version

  [ Jeff Marcom ]
  * Updated scripts/network script from lp:checkbox

 -- Jeff Marcom <email address hidden> Tue, 5 Nov 2013 11:12:04 -0400

2: the memory_info script doesn't seem to work... I keep getting this when I try to run it:
bladernr@mini-ubuntu:~/development/nelson-cpu-memory$ sudo ./scripts/memory_info
Fail: Cannot find memory slot

If I run lshw manually, I see memory class objects in the listing:
<node id="bank:0" claimed="true" class="memory" handle="DMI:001F">
       <description>DIMM</description>
       <product>None</product>
       <vendor>None</vendor>
       <physid>0</physid>
       <serial>None</serial>
       <slot>A0</slot>
       <size units="bytes">1073741824</size>
       <width units="bits">64</width>
      </node>

which does list all the required attributes (vendor, description, slot and size).

Can you show me an example of XML from lshw that is correct and works, and an example of passing script output

3: one other thing I just noticed... you do this a lot:

  print("some error message")
  return SOME_NON_ZERO_INTEGER

If you do it this way, your error message will not appear in the checkbox results. Checkbox will add stdout if a test passes and stderr if a test returns a non-zero exit code.

To correct this, ANY message that should be printed when a script exits in an error condition like this:

  print("FAIL: Some necessary criteria was not met")
  return 50

should be instead be printed to stderr like this:
  print("FAIL: Some necessary criteria was not met", file=sys.stderr)
  return 50

This will save your sanity in the long run if a test fails and you don't see any output in the results file.

review: Needs Fixing
2171. By Nelson Chu

Modify cpu_info and memory_info scripts. Revise debian/changelog file.

Revision history for this message
Nelson Chu (nelson-chu) wrote :

Hi Jeff,

I glad I am getting closer.

1.) I misunderstood what you meant. Sorry for that...

2.) This is a strange issue. When I run memory_info script on Winterfell is fine.

But, run on other server both good and bad.

I parse lshw XML from server that occur this issue. It appears this section as below:
      <node id="bank" class="memory" handle="DMI:0057">
       <description>FLASH Non-volatile 33 MHz (30.3 ns)</description>
       <product>25Q Series</product>
       <vendor>Micron/Numonyx</vendor>
       <physid>0</physid>
       <size units="bytes">16777216</size>
       <width units="bits">8</width>
       <clock units="Hz">33000000</clock>
      </node>

So XML parser cannot gather memory info correctly...

I think it work fine with Winterfell, the successful output is:
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelA_Dimm1 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelA_Dimm2 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelB_Dimm1 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelB_Dimm2 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelC_Dimm1 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelC_Dimm2 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelD_Dimm1 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelD_Dimm2 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelE_Dimm1 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelE_Dimm2 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelF_Dimm1 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelF_Dimm2 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelG_Dimm1 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelG_Dimm2 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelH_Dimm1 size=8GB.
DIMM DDR3 1333 MHz (0.8 ns) vendor=Samsung slot=ChannelH_Dimm2 size=8GB.
Total number of DIMMs is 16.

if you insist I will modify the script.

3.) I didn't notice that before. I have modified it correctly.

I am appreciated greatly your help.

Nelson

review: Needs Resubmitting
2172. By Nelson Chu

debian/changelog file and memory_info script

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'data/whitelists/opencompute-certify-local.whitelist'
--- data/whitelists/opencompute-certify-local.whitelist 1970-01-01 00:00:00 +0000
+++ data/whitelists/opencompute-certify-local.whitelist 2014-02-14 10:30:58 +0000
@@ -0,0 +1,47 @@
1# Resource Jobs
2block_device
3cdimage
4cpuinfo
5device
6dmi
7dpkg
8efi
9environment
10gconf
11lsb
12meminfo
13module
14optical_drive
15package
16sleep
17uname
18#Info attachment jobs
19__info__
20cpuinfo_attachment
21dmesg_attachment
22dmi_attachment
23dmidecode_attachment
24efi_attachment
25lspci_attachment
26lshw_attachment
27mcelog_attachment
28meminfo_attachment
29modprobe_attachment
30modules_attachment
31sysctl_attachment
32sysfs_attachment
33udev_attachment
34lsmod_attachment
35acpi_sleep_attachment
36info/hdparm
37info/hdparm_.*.txt
38installer_debug.gz
39info/disk_partitions
40# Actual test cases
41__TC-001-0001-CPU_Memory__
42TC-001-0001-001-CPU_Information
43TC-001-0001-002-Processor_Topology
44TC-001-0001-003-Memory_Information
45__TC-001-0002-Platform_Controller_Hub__
46TC-001-0002-001-SATA_port
47TC-001-0002-002-USB_2.0
048
=== removed file 'data/whitelists/opencompute-certify-local.whitelist'
--- data/whitelists/opencompute-certify-local.whitelist 2014-02-11 12:16:41 +0000
+++ data/whitelists/opencompute-certify-local.whitelist 1970-01-01 00:00:00 +0000
@@ -1,43 +0,0 @@
1# Resource Jobs
2block_device
3cdimage
4cpuinfo
5device
6dmi
7dpkg
8efi
9environment
10gconf
11lsb
12meminfo
13module
14optical_drive
15package
16sleep
17uname
18#Info attachment jobs
19__info__
20cpuinfo_attachment
21dmesg_attachment
22dmi_attachment
23dmidecode_attachment
24efi_attachment
25lspci_attachment
26lshw_attachment
27mcelog_attachment
28meminfo_attachment
29modprobe_attachment
30modules_attachment
31sysctl_attachment
32sysfs_attachment
33udev_attachment
34lsmod_attachment
35acpi_sleep_attachment
36info/hdparm
37info/hdparm_.*.txt
38installer_debug.gz
39info/disk_partitions
40# Actual test cases
41__TC-001-0002-Platform_Controller_Hub__
42TC-001-0002-001-SATA_port
43TC-001-0002-002-USB_2.0
440
=== modified file 'debian/changelog'
--- debian/changelog 2013-11-05 20:04:15 +0000
+++ debian/changelog 2014-02-14 10:30:58 +0000
@@ -1,5 +1,24 @@
1checkbox (1.16.13~OCP) UNRELEASED; urgency=low1checkbox (1.16.13~OCP) UNRELEASED; urgency=low
22
3 [ Nelson Chu ]
4 * data/whitelists/opencompute-certify-local.whitelist - Added new jobs to
5 certification whitelist
6 * jobs/TC-001-0002-Platform_Controller_Hub.txt - Added new jobs for PCH
7 test cases
8 * jobs/local.txt.in - Added job to parse new PCH job file
9 * scripts/check_sata_port - new script to verify SATA port speed
10 * scripts/check_usb_port - new script to verify USB version
11
12 [ Nelson Chu ]
13 * data/whitelists/opencompute-certify-local.whitelist - Added new jobs to
14 certification whitelist
15 * jobs/TC-001-0001-CPU_Memory.txt.in - Added new jobs for CPU and Memory
16 test cases
17 * jobs/local.txt.in - Added job to parse new CPU and Memory job file
18 * scripts/cpu_info - new script to gather CPU information
19 * scripts/memory_info - new script to gather memory information
20 * scripts/processor_topology - Revised script to match certification criteria
21
3 [ Jeff Marcom ]22 [ Jeff Marcom ]
4 * Updated scripts/network script from lp:checkbox23 * Updated scripts/network script from lp:checkbox
524
625
=== added file 'jobs/TC-001-0001-CPU_Memory.txt.in'
--- jobs/TC-001-0001-CPU_Memory.txt.in 1970-01-01 00:00:00 +0000
+++ jobs/TC-001-0001-CPU_Memory.txt.in 2014-02-14 10:30:58 +0000
@@ -0,0 +1,31 @@
1plugin: shell
2name: TC-001-0001-001-CPU_Information
3requires: package.name == 'lshw'
4user: root
5command: cpu_info -p Xeon -f E5
6description:
7 1. Use lshw command to gather CPU information.
8 2. The program will output CPU model and L1, L2, L3 cache size.
9 3. Criteria: CPU model must be Intel Xeon processor E5-2600 product family and L3 cache size must be up to 20MB.
10
11plugin: shell
12name: TC-001-0001-002-Processor_Topology
13command: processor_topology
14description:
15 1. This test checks CPU topology for accuracy.
16 2. Use lscpu command to gather CPU information.
17 3. The program will output the total number of CPUs, the number of threads per core, the number of cores per socket, and the number of sockets.
18 4. Criteria: It should be 8-12 cores per CPU and 2 threads per core.
19
20plugin: shell
21name: TC-001-0001-003-Memory_Information
22requires: package.name == 'lshw'
23user: root
24command: memory_info
25description:
26 1. Use lshw command to gather memory information.
27 2. Testing prerequisites:
28 4 channels DDR3 registered memory interface on each processor 0 and processor 1.
29 2 DDR3 slots per channel per processor. (total of 16 DIMMs on the motherboard)
30 3. The program will output memory module, vendor, size and slot.
31 4. Criteria: Total of 16 DIMMs on the motherboard.
032
=== renamed file 'jobs/TC-001-0002-Platform_Controller_Hub.txt' => 'jobs/TC-001-0002-Platform_Controller_Hub.txt.in'
=== modified file 'jobs/local.txt.in'
--- jobs/local.txt.in 2014-02-11 12:16:41 +0000
+++ jobs/local.txt.in 2014-02-14 10:30:58 +0000
@@ -110,6 +110,13 @@
110 shopt -s extglob110 shopt -s extglob
111 cat $CHECKBOX_SHARE/jobs/sniff.txt?(.in)111 cat $CHECKBOX_SHARE/jobs/sniff.txt?(.in)
112112
113name: __TC-001-0001-CPU_Memory__
114plugin: local
115_description: Verify CPU and memory
116command:
117 shopt -s extglob
118 cat $CHECKBOX_SHARE/jobs/TC-001-0001-CPU_Memory.txt?(.in)
119
113name: __TC-001-0002-Platform_Controller_Hub__120name: __TC-001-0002-Platform_Controller_Hub__
114plugin: local121plugin: local
115_description: Verify platform controller hub functionality122_description: Verify platform controller hub functionality
116123
=== added file 'scripts/cpu_info'
--- scripts/cpu_info 1970-01-01 00:00:00 +0000
+++ scripts/cpu_info 2014-02-14 10:30:58 +0000
@@ -0,0 +1,100 @@
1#!/usr/bin/env python3
2"""
3Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
4Industrial Technology Research Institute
5
6cpu_info
7 Use lshw command to gather CPU information.
8 The program will output CPU model and L1, L2, L3 cache size.
9 Criteria: CPU model and product family must match user's input
10 and L3 cache should be larger than 20MB.
11
12Authors
13 Nelson Chu <Nelson.Chu@itri.org.tw>
14
15This program is free software: you can redistribute it and/or modify
16it under the terms of the GNU General Public License version 3,
17as published by the Free Software Foundation.
18
19This program is distributed in the hope that it will be useful,
20but WITHOUT ANY WARRANTY; without even the implied warranty of
21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22GNU General Public License for more details.
23
24You should have received a copy of the GNU General Public License
25along with this program. If not, see <http://www.gnu.org/licenses/>.
26
27"""
28
29import os
30import re
31import sys
32import xml.etree.ElementTree as ET
33from subprocess import check_output
34from argparse import ArgumentParser, RawTextHelpFormatter
35
36def run(product, family):
37 command = "lshw -xml"
38 with open(os.devnull, 'w') as NULL:
39 hwinfo_xml = check_output(command, stderr=NULL, shell=True)
40 root = ET.fromstring(hwinfo_xml)
41
42 # Parse lshw XML for gathering processor information.
43 processor = root.findall(".//product/..[@class='processor']")
44
45 if not processor:
46 print("Fail: Cannot parse any processor information.", file=sys.stderr)
47 return 10
48
49 for cpu in processor:
50 if cpu.find('product') is None:
51 print("Fail: Cannot find processor product.", file=sys.stderr)
52 return 20
53 print(cpu.find('product').text)
54 match = re.search(product + '.*' + family, cpu.find('product').text)
55 if not match:
56 print("Fail: Cannot match CPU %s %s family." %(product, family),
57 file=sys.stderr)
58 return 25
59
60 cache_list = cpu.findall(".//size/..[@class='memory']")
61 if not cache_list:
62 print("Fail: Cannot find any CPU cache.", file=sys.stderr)
63 return 30
64
65 for cache in cache_list:
66 if cache.find('size') is None or cache.find('slot') is None:
67 print("Fail: Cannot access Last Level Cache (LLC).",
68 file=sys.stderr)
69 return 40
70
71 cache_size = int(cache.find('size').text) / 1024
72 if cache_size > 1024:
73 cache_size = cache_size / 1024
74 print(('%s %d MB') %(cache.find('slot').text, cache_size))
75 if re.search('L3', cache.find('slot').text):
76 if cache_size < 20:
77 print('Fail: L3 cache size less than 20MB.',
78 file=sys.stderr)
79 return 50
80 else:
81 print(('%s %d KB') %(cache.find('slot').text, cache_size))
82
83 return 0
84
85def main():
86 parser = ArgumentParser(formatter_class=RawTextHelpFormatter)
87
88 parser.add_argument('-p', '--product', type=str, required=True,
89 help=("The CPU product name. [Example: Xeon]"))
90 parser.add_argument('-f', '--family', type=str, required=True,
91 help=("Processor family. [Example: E5]"))
92
93 args = parser.parse_args()
94
95 product = args.product.title()
96 family = args.family.title()
97 return run(product, family)
98
99if __name__ == '__main__':
100 sys.exit(main())
0101
=== added file 'scripts/memory_info'
--- scripts/memory_info 1970-01-01 00:00:00 +0000
+++ scripts/memory_info 2014-02-14 10:30:58 +0000
@@ -0,0 +1,78 @@
1#!/usr/bin/env python3
2"""
3Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
4Industrial Technology Research Institute
5
6memory_info
7 1. Use lshw command to gather memory information.
8 2. Testing prerequisites:
9 4 channels DDR3 registered memory interface on each processor 0
10 and processor 1.
11 2 DDR3 slots per channel per processor. (total of 16 DIMMs
12 on the motherboard)
13 3. The program will output memory module, vendor, size and slot.
14 4. Criteria: Total of 16 DIMMs on the motherboard.
15
16Authors
17 Nelson Chu <Nelson.Chu@itri.org.tw>
18
19This program is free software: you can redistribute it and/or modify
20it under the terms of the GNU General Public License version 3,
21as published by the Free Software Foundation.
22
23This program is distributed in the hope that it will be useful,
24but WITHOUT ANY WARRANTY; without even the implied warranty of
25MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26GNU General Public License for more details.
27
28You should have received a copy of the GNU General Public License
29along with this program. If not, see <http://www.gnu.org/licenses/>.
30
31"""
32
33import sys
34import xml.etree.ElementTree as ET
35from subprocess import Popen, PIPE
36
37def main():
38 attribute = ['description', 'vendor', 'slot', 'size']
39 command = 'lshw -xml'
40 hwinfo_xml = Popen(command, stdout=PIPE, stderr=PIPE,
41 shell=True).communicate()[0]
42 root = ET.fromstring(hwinfo_xml)
43
44 # Parse lshw XML for gathering memory information.
45 memory_list = root.findall(".//clock/..[@class='memory']")
46
47 if not memory_list:
48 print("Fail: Cannot parse any memory information.", file=sys.stderr)
49 return 10
50
51 count = 0
52 for dimm in memory_list:
53 count = count +1
54 for attr in attribute:
55 if dimm.find(attr) is None:
56 print(("Fail: Cannot find memory %s") %attr, file=sys.stderr)
57 return 20
58
59 memory_size = int(dimm.find('size').text) / (1024**3)
60 for attr in attribute:
61 if attr == 'description':
62 print('%s' %(dimm.find(attr).text), end=" ")
63 continue
64 elif attr == 'size':
65 print('%s=%dGB.' %(attr, memory_size))
66 continue
67 print('%s=%s' %(attr, dimm.find(attr).text), end=" ")
68
69 print("Total number of DIMMs is %s." %(count))
70 if count != 16:
71 print("Fail: Memory DIMM number is not meet the requirement.",
72 file=sys.stderr)
73 return 30
74
75 return 0
76
77if __name__ == '__main__':
78 sys.exit(main())
079
=== added file 'scripts/processor_topology'
--- scripts/processor_topology 1970-01-01 00:00:00 +0000
+++ scripts/processor_topology 2014-02-14 10:30:58 +0000
@@ -0,0 +1,130 @@
1#!/usr/bin/env python3
2'''
3cpu_topology
4Written by Jeffrey Lane <jeffrey.lane@canonical.com>
5'''
6import sys
7import os
8from subprocess import check_output
9
10class proc_cpuinfo():
11 '''
12 Class to get and handle information from /proc/cpuinfo
13 Creates a dictionary of data gleaned from that file.
14 '''
15 def __init__(self):
16 self.cpuinfo = {}
17 cpu_fh = open('/proc/cpuinfo', 'r')
18 try:
19 temp = cpu_fh.readlines()
20 finally:
21 cpu_fh.close()
22
23 for i in temp:
24 if i.startswith('processor'):
25 key = 'cpu' + (i.split(':')[1].strip())
26 self.cpuinfo[key] = {'core_id':'', 'physical_package_id':''}
27 elif i.startswith('core id'):
28 self.cpuinfo[key].update({'core_id': i.split(':')[1].strip()})
29 elif i.startswith('physical id'):
30 self.cpuinfo[key].update({'physical_package_id':
31 i.split(':')[1].strip()})
32 else:
33 continue
34
35
36class sysfs_cpu():
37 '''
38 Class to get and handle information from sysfs as relates to CPU topology
39 Creates an informational class to present information on various CPUs
40 '''
41
42 def __init__(self, proc):
43 self.syscpu = {}
44 self.path = '/sys/devices/system/cpu/' + proc + '/topology'
45 items = ['core_id', 'physical_package_id']
46 for i in items:
47 syscpu_fh = open(os.path.join(self.path, i), 'r')
48 try:
49 self.syscpu[i] = syscpu_fh.readline().strip()
50 finally:
51 syscpu_fh.close()
52
53
54def compare(proc_cpu, sys_cpu):
55 cpu_map = {}
56 '''
57 If there is only 1 CPU the test don't look for core_id
58 and physical_package_id because those information are absent in
59 /proc/cpuinfo on singlecore system
60 '''
61 for key in proc_cpu.keys():
62 if 'cpu1' not in proc_cpu:
63 cpu_map[key] = True
64 else:
65 for subkey in proc_cpu[key].keys():
66 if proc_cpu[key][subkey] == sys_cpu[key][subkey]:
67 cpu_map[key] = True
68 else:
69 cpu_map[key] = False
70 return cpu_map
71
72
73def main():
74 cpuinfo = proc_cpuinfo()
75 sys_cpu = {}
76 keys = cpuinfo.cpuinfo.keys()
77 for k in keys:
78 sys_cpu[k] = sysfs_cpu(k).syscpu
79 cpu_map = compare(cpuinfo.cpuinfo, sys_cpu)
80 if False in cpu_map.values() or len(cpu_map) < 1:
81 print("FAIL: CPU Topology is incorrect", file=sys.stderr)
82 print("-" * 52, file=sys.stderr)
83 print("{0}{1}".format("/proc/cpuinfo".center(30), "sysfs".center(25)),
84 file=sys.stderr)
85 print("{0}{1}{2}{3}{1}{2}".format(
86 "CPU".center(6),
87 "Physical ID".center(13),
88 "Core ID".center(9),
89 "|".center(3)), file=sys.stderr)
90 for key in sorted(sys_cpu.keys()):
91 print("{0}{1}{2}{3}{4}{5}".format(
92 key.center(6),
93 cpuinfo.cpuinfo[key]['physical_package_id'].center(13),
94 cpuinfo.cpuinfo[key]['core_id'].center(9),
95 "|".center(3),
96 sys_cpu[key]['physical_package_id'].center(13),
97 sys_cpu[key]['core_id'].center(9)), file=sys.stderr)
98 return 1
99 else:
100 # Use lscpu command to gather CPU information.
101 # Output the total number of CPUs, the number of threads per core,
102 # the number of cores per socket, and the number of sockets.
103 # Criteria: It must be 8-12 cores per CPU and 2 threads per core.
104 # Revised by Nelson Chu <nelson.chu@itri.org.tw>
105 command = 'lscpu'
106 return_code = 0
107
108 with open(os.devnull, "w") as NULL:
109 cpu_info = check_output(command, stderr=NULL, shell=True)
110
111 cpu_info = cpu_info.decode('utf-8')
112
113 for cpu in cpu_info.split('\n'):
114 if cpu.startswith("CPU(s)"):
115 print(cpu)
116 if cpu.startswith("Thread(s) per core"):
117 print(cpu)
118 if cpu.startswith("Core(s) per socket"):
119 cores = int(cpu.split(":")[1])
120 print(cpu)
121 # It should be 8-12 cores per CPU.
122 if cores < 8 or cores > 12:
123 return_code = 1
124 if cpu.startswith("Socket(s)"):
125 print(cpu)
126
127 return return_code
128
129if __name__ == '__main__':
130 sys.exit(main())

Subscribers

People subscribed via source and target branches