Merge lp:~nelson-chu/opencompute/add-ocp-cpu-memory-job into lp:opencompute/checkbox
- add-ocp-cpu-memory-job
- Merge into checkbox
Status: | Merged |
---|---|
Approved by: | Jeff Lane |
Approved revision: | 2172 |
Merged at revision: | 2170 |
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 (+17/-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 (+80/-0) scripts/processor_topology (+130/-0) |
To merge this branch: | bzr merge lp:~nelson-chu/opencompute/add-ocp-cpu-memory-job |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jeff Lane | Approve | ||
Nelson Chu | Needs Resubmitting | ||
Review via email: mp+206845@code.launchpad.net |
This proposal supersedes a proposal from 2014-02-14.
Commit message
Adds OCP CPU and Memory tests and jobs
Description of the change
Scripts and annotations have been modified.
Jeff Lane (bladernr) wrote : Posted in a previous version of this proposal | # |
Nelson Chu (nelson-chu) wrote : Posted in a previous version of this proposal | # |
OK, Thank you for your suggestion.
I will revise it accordingly.
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
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
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.
Jeff Lane (bladernr) wrote : Posted in a previous version of this proposal | # |
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
certification whitelist
* jobs/TC-
test cases
* jobs/local.txt.in - Added job to parse new PCH job file
* scripts/
* scripts/
[ 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@
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">
<size units="
<width units="
</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_
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.
Nelson Chu (nelson-chu) wrote : Posted in a previous version of this proposal | # |
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">
<product>25Q Series</product>
<size units="
<width units="
<clock units="
</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
Jeff Lane (bladernr) wrote : | # |
Ok, just a couple more minor things... :) sorry for being so pedantic...
1: Changelog still... you don't need a separate entry for each time you make a change... all you need is something like this:
[ Nelson Chu ]
* item 1
* item 2
* item 3
* item 4
* item 5
* item ..X
This just summarises all of your contributions to this particular version (1.16.13) and can be all in one grouping. I'm only sticking on this because it's a matter of enforcing convention.
2: memory script: so it works on Winterfell but what about windmill, roadrunner or any other OCP platform? Does it work on those as well? Tell you what, if you're comfortable with it as-is, I can pass it as-is but it will need to be fixed should it prove to break on other OCP designs.
3: Thanks for fixing the output... I just know from personal experience how frustrating it can be to have a test fail and end up with no output to explain why :)
So to summarize:
Condense the changelog, and either modify the script, or just say "Yes, I can live with it possibly being broken on other OCP Platforms".
Also, you don't have to supercede your previous request. Just push changes and add a comment to this thread and choose "resubmit" from the "Review:" dropdown box. After this, it should be done and I'll push it into trunk.
- 2172. By Nelson Chu
-
debian/changelog file and memory_info script
Nelson Chu (nelson-chu) wrote : | # |
Hi Jeff,
Sorry to late reply...
1.) Changelog is very important, I am great to participate this part.
2.) Due to I don't have other ocp platform, I cannot ensure the script works fine with other ocp servers.
I revised the memory_info script, if still has problems please tell me.
3.) Thanks your advice, it helps me to learn more.
Jeff Lane (bladernr) wrote : | # |
Awesome, thanks. I know how it can be difficult to verify things without the actual hardware to work on... If this does create problems in the future, For Your Information, the process is:
file a bug against ocp-checkbox
bug is then triaged
bug is worked on
patch is submitted using the same process you're using today
patch is reviewed
patch is merged
new ocp-checkbox is created.
Preview Diff
1 | === added file 'data/whitelists/opencompute-certify-local.whitelist' |
2 | --- data/whitelists/opencompute-certify-local.whitelist 1970-01-01 00:00:00 +0000 |
3 | +++ data/whitelists/opencompute-certify-local.whitelist 2014-02-21 09:43:42 +0000 |
4 | @@ -0,0 +1,47 @@ |
5 | +# Resource Jobs |
6 | +block_device |
7 | +cdimage |
8 | +cpuinfo |
9 | +device |
10 | +dmi |
11 | +dpkg |
12 | +efi |
13 | +environment |
14 | +gconf |
15 | +lsb |
16 | +meminfo |
17 | +module |
18 | +optical_drive |
19 | +package |
20 | +sleep |
21 | +uname |
22 | +#Info attachment jobs |
23 | +__info__ |
24 | +cpuinfo_attachment |
25 | +dmesg_attachment |
26 | +dmi_attachment |
27 | +dmidecode_attachment |
28 | +efi_attachment |
29 | +lspci_attachment |
30 | +lshw_attachment |
31 | +mcelog_attachment |
32 | +meminfo_attachment |
33 | +modprobe_attachment |
34 | +modules_attachment |
35 | +sysctl_attachment |
36 | +sysfs_attachment |
37 | +udev_attachment |
38 | +lsmod_attachment |
39 | +acpi_sleep_attachment |
40 | +info/hdparm |
41 | +info/hdparm_.*.txt |
42 | +installer_debug.gz |
43 | +info/disk_partitions |
44 | +# Actual test cases |
45 | +__TC-001-0001-CPU_Memory__ |
46 | +TC-001-0001-001-CPU_Information |
47 | +TC-001-0001-002-Processor_Topology |
48 | +TC-001-0001-003-Memory_Information |
49 | +__TC-001-0002-Platform_Controller_Hub__ |
50 | +TC-001-0002-001-SATA_port |
51 | +TC-001-0002-002-USB_2.0 |
52 | |
53 | === removed file 'data/whitelists/opencompute-certify-local.whitelist' |
54 | --- data/whitelists/opencompute-certify-local.whitelist 2014-02-11 12:16:41 +0000 |
55 | +++ data/whitelists/opencompute-certify-local.whitelist 1970-01-01 00:00:00 +0000 |
56 | @@ -1,43 +0,0 @@ |
57 | -# Resource Jobs |
58 | -block_device |
59 | -cdimage |
60 | -cpuinfo |
61 | -device |
62 | -dmi |
63 | -dpkg |
64 | -efi |
65 | -environment |
66 | -gconf |
67 | -lsb |
68 | -meminfo |
69 | -module |
70 | -optical_drive |
71 | -package |
72 | -sleep |
73 | -uname |
74 | -#Info attachment jobs |
75 | -__info__ |
76 | -cpuinfo_attachment |
77 | -dmesg_attachment |
78 | -dmi_attachment |
79 | -dmidecode_attachment |
80 | -efi_attachment |
81 | -lspci_attachment |
82 | -lshw_attachment |
83 | -mcelog_attachment |
84 | -meminfo_attachment |
85 | -modprobe_attachment |
86 | -modules_attachment |
87 | -sysctl_attachment |
88 | -sysfs_attachment |
89 | -udev_attachment |
90 | -lsmod_attachment |
91 | -acpi_sleep_attachment |
92 | -info/hdparm |
93 | -info/hdparm_.*.txt |
94 | -installer_debug.gz |
95 | -info/disk_partitions |
96 | -# Actual test cases |
97 | -__TC-001-0002-Platform_Controller_Hub__ |
98 | -TC-001-0002-001-SATA_port |
99 | -TC-001-0002-002-USB_2.0 |
100 | |
101 | === modified file 'debian/changelog' |
102 | --- debian/changelog 2013-11-05 20:04:15 +0000 |
103 | +++ debian/changelog 2014-02-21 09:43:42 +0000 |
104 | @@ -1,5 +1,22 @@ |
105 | checkbox (1.16.13~OCP) UNRELEASED; urgency=low |
106 | |
107 | + [ Nelson Chu ] |
108 | + * data/whitelists/opencompute-certify-local.whitelist - Added PCH jobs to |
109 | + OCP certification whitelist |
110 | + * jobs/TC-001-0002-Platform_Controller_Hub.txt - Added new jobs for PCH |
111 | + test cases |
112 | + * jobs/local.txt.in - Added job to parse new PCH job file |
113 | + * scripts/check_sata_port - new script to verify SATA port speed |
114 | + * scripts/check_usb_port - new script to verify USB version |
115 | + * data/whitelists/opencompute-certify-local.whitelist - Added CPU and Memory |
116 | + jobs to OCP certification whitelist |
117 | + * jobs/TC-001-0001-CPU_Memory.txt.in - Added new jobs for CPU and Memory |
118 | + test cases |
119 | + * jobs/local.txt.in - Added job to parse new CPU and Memory job file |
120 | + * scripts/cpu_info - new script to gather CPU information |
121 | + * scripts/memory_info - new script to gather memory information |
122 | + * scripts/processor_topology - Revised script to match certification criteria |
123 | + |
124 | [ Jeff Marcom ] |
125 | * Updated scripts/network script from lp:checkbox |
126 | |
127 | |
128 | === added file 'jobs/TC-001-0001-CPU_Memory.txt.in' |
129 | --- jobs/TC-001-0001-CPU_Memory.txt.in 1970-01-01 00:00:00 +0000 |
130 | +++ jobs/TC-001-0001-CPU_Memory.txt.in 2014-02-21 09:43:42 +0000 |
131 | @@ -0,0 +1,31 @@ |
132 | +plugin: shell |
133 | +name: TC-001-0001-001-CPU_Information |
134 | +requires: package.name == 'lshw' |
135 | +user: root |
136 | +command: cpu_info -p Xeon -f E5 |
137 | +description: |
138 | + 1. Use lshw command to gather CPU information. |
139 | + 2. The program will output CPU model and L1, L2, L3 cache size. |
140 | + 3. Criteria: CPU model must be Intel Xeon processor E5-2600 product family and L3 cache size must be up to 20MB. |
141 | + |
142 | +plugin: shell |
143 | +name: TC-001-0001-002-Processor_Topology |
144 | +command: processor_topology |
145 | +description: |
146 | + 1. This test checks CPU topology for accuracy. |
147 | + 2. Use lscpu command to gather CPU information. |
148 | + 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. |
149 | + 4. Criteria: It should be 8-12 cores per CPU and 2 threads per core. |
150 | + |
151 | +plugin: shell |
152 | +name: TC-001-0001-003-Memory_Information |
153 | +requires: package.name == 'lshw' |
154 | +user: root |
155 | +command: memory_info |
156 | +description: |
157 | + 1. Use lshw command to gather memory information. |
158 | + 2. Testing prerequisites: |
159 | + 4 channels DDR3 registered memory interface on each processor 0 and processor 1. |
160 | + 2 DDR3 slots per channel per processor. (total of 16 DIMMs on the motherboard) |
161 | + 3. The program will output memory module, vendor, size and slot. |
162 | + 4. Criteria: Total of 16 DIMMs on the motherboard. |
163 | |
164 | === renamed file 'jobs/TC-001-0002-Platform_Controller_Hub.txt' => 'jobs/TC-001-0002-Platform_Controller_Hub.txt.in' |
165 | === modified file 'jobs/local.txt.in' |
166 | --- jobs/local.txt.in 2014-02-11 12:16:41 +0000 |
167 | +++ jobs/local.txt.in 2014-02-21 09:43:42 +0000 |
168 | @@ -110,6 +110,13 @@ |
169 | shopt -s extglob |
170 | cat $CHECKBOX_SHARE/jobs/sniff.txt?(.in) |
171 | |
172 | +name: __TC-001-0001-CPU_Memory__ |
173 | +plugin: local |
174 | +_description: Verify CPU and memory |
175 | +command: |
176 | + shopt -s extglob |
177 | + cat $CHECKBOX_SHARE/jobs/TC-001-0001-CPU_Memory.txt?(.in) |
178 | + |
179 | name: __TC-001-0002-Platform_Controller_Hub__ |
180 | plugin: local |
181 | _description: Verify platform controller hub functionality |
182 | |
183 | === added file 'scripts/cpu_info' |
184 | --- scripts/cpu_info 1970-01-01 00:00:00 +0000 |
185 | +++ scripts/cpu_info 2014-02-21 09:43:42 +0000 |
186 | @@ -0,0 +1,100 @@ |
187 | +#!/usr/bin/env python3 |
188 | +""" |
189 | +Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications |
190 | +Industrial Technology Research Institute |
191 | + |
192 | +cpu_info |
193 | + Use lshw command to gather CPU information. |
194 | + The program will output CPU model and L1, L2, L3 cache size. |
195 | + Criteria: CPU model and product family must match user's input |
196 | + and L3 cache should be larger than 20MB. |
197 | + |
198 | +Authors |
199 | + Nelson Chu <Nelson.Chu@itri.org.tw> |
200 | + |
201 | +This program is free software: you can redistribute it and/or modify |
202 | +it under the terms of the GNU General Public License version 3, |
203 | +as published by the Free Software Foundation. |
204 | + |
205 | +This program is distributed in the hope that it will be useful, |
206 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
207 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
208 | +GNU General Public License for more details. |
209 | + |
210 | +You should have received a copy of the GNU General Public License |
211 | +along with this program. If not, see <http://www.gnu.org/licenses/>. |
212 | + |
213 | +""" |
214 | + |
215 | +import os |
216 | +import re |
217 | +import sys |
218 | +import xml.etree.ElementTree as ET |
219 | +from subprocess import check_output |
220 | +from argparse import ArgumentParser, RawTextHelpFormatter |
221 | + |
222 | +def run(product, family): |
223 | + command = "lshw -xml" |
224 | + with open(os.devnull, 'w') as NULL: |
225 | + hwinfo_xml = check_output(command, stderr=NULL, shell=True) |
226 | + root = ET.fromstring(hwinfo_xml) |
227 | + |
228 | + # Parse lshw XML for gathering processor information. |
229 | + processor = root.findall(".//product/..[@class='processor']") |
230 | + |
231 | + if not processor: |
232 | + print("Fail: Cannot parse any processor information.", file=sys.stderr) |
233 | + return 10 |
234 | + |
235 | + for cpu in processor: |
236 | + if cpu.find('product') is None: |
237 | + print("Fail: Cannot find processor product.", file=sys.stderr) |
238 | + return 20 |
239 | + print(cpu.find('product').text) |
240 | + match = re.search(product + '.*' + family, cpu.find('product').text) |
241 | + if not match: |
242 | + print("Fail: Cannot match CPU %s %s family." %(product, family), |
243 | + file=sys.stderr) |
244 | + return 25 |
245 | + |
246 | + cache_list = cpu.findall(".//size/..[@class='memory']") |
247 | + if not cache_list: |
248 | + print("Fail: Cannot find any CPU cache.", file=sys.stderr) |
249 | + return 30 |
250 | + |
251 | + for cache in cache_list: |
252 | + if cache.find('size') is None or cache.find('slot') is None: |
253 | + print("Fail: Cannot access Last Level Cache (LLC).", |
254 | + file=sys.stderr) |
255 | + return 40 |
256 | + |
257 | + cache_size = int(cache.find('size').text) / 1024 |
258 | + if cache_size > 1024: |
259 | + cache_size = cache_size / 1024 |
260 | + print(('%s %d MB') %(cache.find('slot').text, cache_size)) |
261 | + if re.search('L3', cache.find('slot').text): |
262 | + if cache_size < 20: |
263 | + print('Fail: L3 cache size less than 20MB.', |
264 | + file=sys.stderr) |
265 | + return 50 |
266 | + else: |
267 | + print(('%s %d KB') %(cache.find('slot').text, cache_size)) |
268 | + |
269 | + return 0 |
270 | + |
271 | +def main(): |
272 | + parser = ArgumentParser(formatter_class=RawTextHelpFormatter) |
273 | + |
274 | + parser.add_argument('-p', '--product', type=str, required=True, |
275 | + help=("The CPU product name. [Example: Xeon]")) |
276 | + parser.add_argument('-f', '--family', type=str, required=True, |
277 | + help=("Processor family. [Example: E5]")) |
278 | + |
279 | + args = parser.parse_args() |
280 | + |
281 | + product = args.product.title() |
282 | + family = args.family.title() |
283 | + return run(product, family) |
284 | + |
285 | +if __name__ == '__main__': |
286 | + sys.exit(main()) |
287 | |
288 | === added file 'scripts/memory_info' |
289 | --- scripts/memory_info 1970-01-01 00:00:00 +0000 |
290 | +++ scripts/memory_info 2014-02-21 09:43:42 +0000 |
291 | @@ -0,0 +1,80 @@ |
292 | +#!/usr/bin/env python3 |
293 | +""" |
294 | +Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications |
295 | +Industrial Technology Research Institute |
296 | + |
297 | +memory_info |
298 | + 1. Use lshw command to gather memory information. |
299 | + 2. Testing prerequisites: |
300 | + 4 channels DDR3 registered memory interface on each processor 0 |
301 | + and processor 1. |
302 | + 2 DDR3 slots per channel per processor. (total of 16 DIMMs |
303 | + on the motherboard) |
304 | + 3. The program will output memory module, vendor, size and slot. |
305 | + 4. Criteria: Total of 16 DIMMs on the motherboard. |
306 | + |
307 | +Authors |
308 | + Nelson Chu <Nelson.Chu@itri.org.tw> |
309 | + |
310 | +This program is free software: you can redistribute it and/or modify |
311 | +it under the terms of the GNU General Public License version 3, |
312 | +as published by the Free Software Foundation. |
313 | + |
314 | +This program is distributed in the hope that it will be useful, |
315 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
316 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
317 | +GNU General Public License for more details. |
318 | + |
319 | +You should have received a copy of the GNU General Public License |
320 | +along with this program. If not, see <http://www.gnu.org/licenses/>. |
321 | + |
322 | +""" |
323 | + |
324 | +import sys |
325 | +import xml.etree.ElementTree as ET |
326 | +from subprocess import Popen, PIPE |
327 | + |
328 | +def main(): |
329 | + attribute = ['description', 'vendor', 'slot', 'size'] |
330 | + command = 'lshw -xml' |
331 | + hwinfo_xml = Popen(command, stdout=PIPE, stderr=PIPE, |
332 | + shell=True).communicate()[0] |
333 | + root = ET.fromstring(hwinfo_xml) |
334 | + |
335 | + memory_list = root.findall(".//clock/..[@class='memory']") |
336 | + |
337 | + if not memory_list: |
338 | + print("Fail: Cannot parse any memory information.") |
339 | + return 10 |
340 | + |
341 | + count = 0 |
342 | + for dimm in memory_list: |
343 | + if dimm.find('slot') is None: |
344 | + continue |
345 | + |
346 | + for attr in attribute: |
347 | + if dimm.find(attr) is None: |
348 | + print(("Fail: Cannot find memory %s") %attr, file=sys.stderr) |
349 | + return 20 |
350 | + |
351 | + count = count +1 |
352 | + memory_size = int(dimm.find('size').text) / (1024**3) |
353 | + for attr in attribute: |
354 | + if attr == 'description': |
355 | + print('%s' %(dimm.find(attr).text), end=" ") |
356 | + continue |
357 | + elif attr == 'size': |
358 | + print('%s=%dGB.' %(attr, memory_size)) |
359 | + continue |
360 | + print('%s=%s' %(attr, dimm.find(attr).text), end=" ") |
361 | + |
362 | + print("Total number of DIMMs is %s." %(count)) |
363 | + if count != 16: |
364 | + print("Fail: Memory DIMM number is not meet the requirement.", |
365 | + file=sys.stderr) |
366 | + return 20 |
367 | + |
368 | + return 0 |
369 | + |
370 | +if __name__ == '__main__': |
371 | + sys.exit(main()) |
372 | |
373 | === added file 'scripts/processor_topology' |
374 | --- scripts/processor_topology 1970-01-01 00:00:00 +0000 |
375 | +++ scripts/processor_topology 2014-02-21 09:43:42 +0000 |
376 | @@ -0,0 +1,130 @@ |
377 | +#!/usr/bin/env python3 |
378 | +''' |
379 | +cpu_topology |
380 | +Written by Jeffrey Lane <jeffrey.lane@canonical.com> |
381 | +''' |
382 | +import sys |
383 | +import os |
384 | +from subprocess import check_output |
385 | + |
386 | +class proc_cpuinfo(): |
387 | + ''' |
388 | + Class to get and handle information from /proc/cpuinfo |
389 | + Creates a dictionary of data gleaned from that file. |
390 | + ''' |
391 | + def __init__(self): |
392 | + self.cpuinfo = {} |
393 | + cpu_fh = open('/proc/cpuinfo', 'r') |
394 | + try: |
395 | + temp = cpu_fh.readlines() |
396 | + finally: |
397 | + cpu_fh.close() |
398 | + |
399 | + for i in temp: |
400 | + if i.startswith('processor'): |
401 | + key = 'cpu' + (i.split(':')[1].strip()) |
402 | + self.cpuinfo[key] = {'core_id':'', 'physical_package_id':''} |
403 | + elif i.startswith('core id'): |
404 | + self.cpuinfo[key].update({'core_id': i.split(':')[1].strip()}) |
405 | + elif i.startswith('physical id'): |
406 | + self.cpuinfo[key].update({'physical_package_id': |
407 | + i.split(':')[1].strip()}) |
408 | + else: |
409 | + continue |
410 | + |
411 | + |
412 | +class sysfs_cpu(): |
413 | + ''' |
414 | + Class to get and handle information from sysfs as relates to CPU topology |
415 | + Creates an informational class to present information on various CPUs |
416 | + ''' |
417 | + |
418 | + def __init__(self, proc): |
419 | + self.syscpu = {} |
420 | + self.path = '/sys/devices/system/cpu/' + proc + '/topology' |
421 | + items = ['core_id', 'physical_package_id'] |
422 | + for i in items: |
423 | + syscpu_fh = open(os.path.join(self.path, i), 'r') |
424 | + try: |
425 | + self.syscpu[i] = syscpu_fh.readline().strip() |
426 | + finally: |
427 | + syscpu_fh.close() |
428 | + |
429 | + |
430 | +def compare(proc_cpu, sys_cpu): |
431 | + cpu_map = {} |
432 | + ''' |
433 | + If there is only 1 CPU the test don't look for core_id |
434 | + and physical_package_id because those information are absent in |
435 | + /proc/cpuinfo on singlecore system |
436 | + ''' |
437 | + for key in proc_cpu.keys(): |
438 | + if 'cpu1' not in proc_cpu: |
439 | + cpu_map[key] = True |
440 | + else: |
441 | + for subkey in proc_cpu[key].keys(): |
442 | + if proc_cpu[key][subkey] == sys_cpu[key][subkey]: |
443 | + cpu_map[key] = True |
444 | + else: |
445 | + cpu_map[key] = False |
446 | + return cpu_map |
447 | + |
448 | + |
449 | +def main(): |
450 | + cpuinfo = proc_cpuinfo() |
451 | + sys_cpu = {} |
452 | + keys = cpuinfo.cpuinfo.keys() |
453 | + for k in keys: |
454 | + sys_cpu[k] = sysfs_cpu(k).syscpu |
455 | + cpu_map = compare(cpuinfo.cpuinfo, sys_cpu) |
456 | + if False in cpu_map.values() or len(cpu_map) < 1: |
457 | + print("FAIL: CPU Topology is incorrect", file=sys.stderr) |
458 | + print("-" * 52, file=sys.stderr) |
459 | + print("{0}{1}".format("/proc/cpuinfo".center(30), "sysfs".center(25)), |
460 | + file=sys.stderr) |
461 | + print("{0}{1}{2}{3}{1}{2}".format( |
462 | + "CPU".center(6), |
463 | + "Physical ID".center(13), |
464 | + "Core ID".center(9), |
465 | + "|".center(3)), file=sys.stderr) |
466 | + for key in sorted(sys_cpu.keys()): |
467 | + print("{0}{1}{2}{3}{4}{5}".format( |
468 | + key.center(6), |
469 | + cpuinfo.cpuinfo[key]['physical_package_id'].center(13), |
470 | + cpuinfo.cpuinfo[key]['core_id'].center(9), |
471 | + "|".center(3), |
472 | + sys_cpu[key]['physical_package_id'].center(13), |
473 | + sys_cpu[key]['core_id'].center(9)), file=sys.stderr) |
474 | + return 1 |
475 | + else: |
476 | + # Use lscpu command to gather CPU information. |
477 | + # Output the total number of CPUs, the number of threads per core, |
478 | + # the number of cores per socket, and the number of sockets. |
479 | + # Criteria: It must be 8-12 cores per CPU and 2 threads per core. |
480 | + # Revised by Nelson Chu <nelson.chu@itri.org.tw> |
481 | + command = 'lscpu' |
482 | + return_code = 0 |
483 | + |
484 | + with open(os.devnull, "w") as NULL: |
485 | + cpu_info = check_output(command, stderr=NULL, shell=True) |
486 | + |
487 | + cpu_info = cpu_info.decode('utf-8') |
488 | + |
489 | + for cpu in cpu_info.split('\n'): |
490 | + if cpu.startswith("CPU(s)"): |
491 | + print(cpu) |
492 | + if cpu.startswith("Thread(s) per core"): |
493 | + print(cpu) |
494 | + if cpu.startswith("Core(s) per socket"): |
495 | + cores = int(cpu.split(":")[1]) |
496 | + print(cpu) |
497 | + # It should be 8-12 cores per CPU. |
498 | + if cores < 8 or cores > 12: |
499 | + return_code = 1 |
500 | + if cpu.startswith("Socket(s)"): |
501 | + print(cpu) |
502 | + |
503 | + return return_code |
504 | + |
505 | +if __name__ == '__main__': |
506 | + sys.exit(main()) |
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: /opencompute- certify- local.whitelist looks fine.
data/whitelists
jobs/TC- 001-0001- CPU_Memory. txt.in: 0001-003- Memory_ Information also needs 'user: root' added to properly run.
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-
jobs/local.txt.in
1: The word "Verified" should be "Verify" in the description field.
scripts/cpu_info: 0001-001- CPU_information with and without root permissions, I get the following different outputs: klaatu: ~/development/ ocp-nelson- memory- cpu-test$ ./scripts/ cpu_infoIntel( R) Core(TM) i7 CPU Q 720 @ 1.60GHz klaatu: ~/development/ ocp-nelson- memory- cpu-test$ echo $? klaatu: ~/development/ ocp-nelson- memory- cpu-test$ sudo ./scripts/cpu_info klaatu: ~/development/ ocp-nelson- memory- cpu-test$ echo $?
1: When I manually run the cpu_info script for the test TC-001-
bladernr@
Can not found any CPU cache.
bladernr@
30
bladernr@
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@
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: klaatu: ~/development/ ocp-nelson- memory- cpu-test$ sudo ./scripts/cpu_info; echo $?
bladernr@
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 ...