Merge lp:~bladernr/opencompute/merge-github-junk into lp:opencompute/opencompute-testing

Proposed by Jeff Lane 
Status: Merged
Approved by: Jeff Lane 
Approved revision: 47
Merged at revision: 30
Proposed branch: lp:~bladernr/opencompute/merge-github-junk
Merge into: lp:opencompute/opencompute-testing
Diff against target: 9031 lines (+7262/-531)
109 files modified
README.tips (+121/-0)
bin/bad_block_test (+72/-0)
bin/bios_info (+2/-0)
bin/block_device_resource (+80/-0)
bin/check_sata_port (+2/-0)
bin/check_sata_port_leopard (+38/-0)
bin/check_usb_port (+2/-0)
bin/check_usb_port_leopard (+43/-0)
bin/cpu_info (+2/-0)
bin/cpu_info_leopard (+83/-0)
bin/create_raid (+140/-0)
bin/dcmi_inventory (+136/-0)
bin/dcmi_power_off_on (+190/-0)
bin/dcmi_power_reset (+139/-0)
bin/dcmi_priv_admin (+174/-0)
bin/dcmi_priv_oper (+174/-0)
bin/dcmi_priv_user (+174/-0)
bin/dcmi_sampling (+271/-0)
bin/dcmi_thermal_ib (+212/-0)
bin/dcmi_thermal_oob (+243/-0)
bin/disk_health (+138/-0)
bin/disk_info (+2/-0)
bin/disk_info_leopard (+67/-0)
bin/ipmi_fru (+163/-0)
bin/ipmi_inventory (+214/-0)
bin/ipmi_power_draw (+126/-0)
bin/ipmi_power_off_on (+193/-0)
bin/ipmi_power_policy (+165/-0)
bin/ipmi_power_reset (+142/-0)
bin/ipmi_priv_admin (+176/-0)
bin/ipmi_priv_oper (+174/-0)
bin/ipmi_priv_user (+176/-0)
bin/ipmi_sampling (+273/-0)
bin/ipmi_sel_entries (+9/-11)
bin/ipmi_sensors_ib (+215/-0)
bin/ipmi_sensors_oob (+240/-0)
bin/ipmi_warm_reboot (+173/-0)
bin/ocp_memory_info (+80/-0)
bin/ping_test (+76/-0)
bin/processor_topology (+6/-0)
bin/raid_availability_test (+62/-0)
bin/raid_hdd_info (+61/-0)
bin/raid_info (+2/-0)
bin/read_write_file (+181/-0)
bin/rebulid_raid (+280/-0)
bin/system_stress (+71/-0)
debian/changelog (+13/-1)
debian/control (+2/-2)
examples/bmc.cfg (+144/-0)
examples/me.cfg (+81/-8)
jobs/TC-001-0001-CPU_Memory.txt.in (+0/-32)
jobs/TC-001-0002-Platform_Controller_Hub.txt.in (+0/-14)
jobs/TC-001-0006-Hardware_Monitoring.txt (+22/-0)
jobs/TC-001-0007-In_band_Platform_Controller_Hub_Management_Engine.txt (+15/-0)
jobs/TC-001-0008-Out_of_band_Platform_Controller_Hub_Management_Engine.txt (+16/-0)
jobs/TC-002-0002-Management_Node_Identifier.txt (+6/-0)
jobs/TC-002-0003-Rights_and_Credentials.txt (+14/-0)
jobs/TC-002-0006-Remotely_Power_Control.txt (+13/-0)
jobs/TC-002-0007-Power_Draw.txt (+9/-0)
jobs/TC-002-0008-Temperature.txt (+8/-0)
jobs/TC-002-0009-User_Levels.txt (+26/-0)
jobs/TC-002-0010-Inventory.txt (+19/-0)
jobs/TC-002-0011-System_Log.txt.in (+0/-10)
jobs/TC-003-0001-Hardware_Information.txt.in (+0/-58)
jobs/TC-003-0003-Network_Performance.txt.in (+0/-23)
jobs/TC-003-0004-Disk_Healthiness.txt (+40/-0)
jobs/TC-003-0005-System_Stress.txt (+7/-0)
jobs/TC-004-0001-JBOD_Testing.txt (+74/-0)
jobs/TC-005-0001-CPU_Memory.txt (+35/-0)
jobs/TC-005-0002-Platform_Controller_Hub.txt (+15/-0)
jobs/TC-005-0006-Sensors_Monitoring.txt (+55/-0)
jobs/TC-005-0009-Power_Policy.txt (+30/-0)
jobs/TC-006-0002-Management_Node_Identifier.txt (+6/-0)
jobs/TC-006-0003-Rights_and_Credentials.txt (+21/-0)
jobs/TC-006-0006-Remotely_Power_Control.txt (+27/-0)
jobs/TC-006-0007-Temperature.txt (+8/-0)
jobs/TC-006-0008-User_Levels.txt (+26/-0)
jobs/TC-006-0009-Inventory.txt (+20/-0)
jobs/TC-006-0010-System_Log.txt (+27/-0)
jobs/TC-007-0001-System_Information.txt (+43/-0)
jobs/TC-007-0002-Network_Interface_Controller.txt (+24/-0)
jobs/TC-007-0003-Hard_Disk_Drive.txt (+44/-0)
jobs/TC-007-0004-System_Idle_and_Stress_Test.txt (+8/-0)
jobs/TC-007-0005-JBOD_Testing.txt (+74/-0)
jobs/dcmi_in_band.txt.in (+0/-56)
jobs/ipmi.txt.in (+0/-151)
jobs/ocp-disk.txt.in (+0/-17)
jobs/ocp-local.txt.in (+0/-62)
jobs/ocp-memory.txt.in (+0/-20)
jobs/ocp-miscellanea.txt.in (+0/-19)
jobs/ocp-power-management.txt.in (+0/-42)
whitelists/opencompute-certify-basic.whitelist (+42/-0)
whitelists/opencompute-certify-basic_leopard.whitelist (+37/-0)
whitelists/opencompute-certify-iperf.whitelist (+1/-1)
whitelists/opencompute-certify-local.whitelist (+18/-2)
whitelists/opencompute-certify-local_leopard.whitelist (+48/-0)
whitelists/opencompute-certify-raid0.whitelist (+29/-0)
whitelists/opencompute-certify-raid0_leopard.whitelist (+29/-0)
whitelists/opencompute-certify-raid6.whitelist (+31/-0)
whitelists/opencompute-certify-raid6_leopard.whitelist (+30/-0)
whitelists/opencompute-certify-remoteBMC_leopard.whitelist (+42/-0)
whitelists/opencompute-certify-remoteME.whitelist (+8/-1)
whitelists/opencompute-certify-remotePC.whitelist (+32/-0)
whitelists/opencompute-certify-remotePC_leopard.whitelist (+34/-0)
whitelists/opencompute-certify-stress.whitelist (+32/-0)
whitelists/opencompute-certify-stressBMC_leopard.whitelist (+27/-0)
whitelists/opencompute-certify-stressME.whitelist (+28/-0)
whitelists/opencompute-certify-stress_leopard.whitelist (+32/-0)
whitelists/sample-normal.whitelist (+27/-1)
To merge this branch: bzr merge lp:~bladernr/opencompute/merge-github-junk
Reviewer Review Type Date Requested Status
Jeff Lane  Approve
Review via email: mp+268148@code.launchpad.net

Description of the change

Merges in all the stuff ITRI put into github.

To post a comment you must log in.
Revision history for this message
Jeff Lane  (bladernr) wrote :

self approve... merge them all, let Jeff sort them out.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'README.tips'
2--- README.tips 1970-01-01 00:00:00 +0000
3+++ README.tips 2015-08-14 22:03:31 +0000
4@@ -0,0 +1,121 @@
5+############User manual and installation guide################
6+Note: Please use Ubuntu 12.04 or lately.
7+
8+######[Run Checkbox]######
9+$ opencompute-certification
10+Note, sudo is not necessary, you should be prompted for a root password.
11+
12+######[Important directory]######
13+Runtime Logs: $HOME/.cache/plainbox/
14+Results: $HOME/.local/plainbox/
15+
16+##############################################################################################
17+Before running ME/BMC test, please fill in related information in configuration file.
18+Each section exists in configuration file has its own purpose.
19+The following will explain how to fill in settings in each section.
20+
21+Note:
22+1. Path of configuration file: /etc/xdg/bmc.cfg or /etc/xdg/me.cfg
23+2. Without these settings pre-setting in configuration file, you won't start tests smoothly.
24+
25+##############################################################################################
26+
27+
28+############User manual of each section################
29+
30+######[Targets]######
31+For remotely access via IPMI/DCMI, you need to fill in ME/BMC IP address of SUT.
32+For example, ME/BMC IP: 10.2.107.5
33+[Targets]
34+Target1: 10.2.107.5
35+
36+######[Account]######
37+For remotely access via IPMI/DCMI, you need to fill in ME/BMC account here.
38+For example, USER/PASSWORD: OCP/OCP. Then, the settings in this section must be
39+[Account]
40+USER: OCP
41+PASSWORD: OCP
42+
43+######[Sensors] and [SensorsForCPUTemp]######
44+For thermal tests of ME/BMC sensors, you need to check and set Sensor ID before starting tests.
45+Refers to TC-001-0006-Hardware_Monitoring.txt.in,
46+there are five kinds of sensors to monitor, so please write corresponding sensor ID to this field.
47+For example, the sensor ID related to these five kinds of sensors on Winterfell
48+are "outlet Temp", "inlet Temp", "PCH Temp", "P0 DIMM Temp", "P1 DIMM Temp", "P0 Therm Margin",
49+"P1 Therm Margin", "CPU0 Tjmax", "CPU1 Tjmax"
50+[Sensors]
51+Outlet: Outlet Temp
52+Inlet: Inlet Temp
53+PCH: PCH Temp
54+Px DIMM: P0 DIMM Temp
55+Py DIMM: P1 DIMM Temp
56+CPUx: CPU0 Temp
57+CPUy: CPU1 Temp
58+
59+Note:
60+ Case1. There are CPU sensors to monitor CPU temperature directly.
61+ You just fill in sensor IDs behind key "CPUx" and "CPUy" and
62+ don't care the section [SensorsForCPUTemp] at all.
63+ Case2. There are no CPU sensors to monitor CPU temperature directly.
64+ CPUx temperature is derived from Px Therm Margin and CPUx Tjmax.
65+ ie,"CPU0 Temp" = "P0 Therm Margin" + "CPU0 Tjmax"
66+ (It still requires "PU0 Temp" marked behind key "CPUx")
67+ Besides, please also fill in "P0 Therm Margin", "PU0 Tjmax"
68+ to corresponding section presented as below.
69+ [SensorsForCPUTemp]
70+ Px Therm Margin: P0 Therm Margin
71+ Py Therm Margin: P1 Therm Margin
72+ CPUx Tjmax: CPU0 Tjmax
73+ CPUy Tjmax: CPU1 Tjmax
74+
75+
76+######[SensorsForSampling]######
77+Refers to test case TC-002-0008-001-Temp_Sampling_Increment, the description is to retrieve CPU and intake temperature 30 times.
78+For example, the related sensor IDs on Winterfell are "Inlet Temp", "P0 Therm Margin", "P1 Therm Margin", "CPU0 Tjmax", "CPU1 Tjmax".
79+[SensorsForSampling]
80+Inlet: Inlet Temp
81+CPUx: CPU0 Temp
82+CPUy: CPU1 Temp
83+Note: if the CPU0 temperature derives from "P0 therm Margin" and "CPU0 Tjmax",
84+you have to give a string "CPU0 temp" behind key "CPUx". And also remember to fill in the sensor ID in section [SensorsForCPUTemp].
85+Please refer to section [Sensors].
86+
87+
88+##############################################################################################
89+The following four sections [Admin Level], [Operator Level], [User Level] and [Add User Test] are for User level test.
90+Please refer to TC-002-0009-User_Levels.txt.in. In these four sections, you don't need to modify settings here.
91+
92+######[Admin Level]######
93+[Admin Level]
94+ADMIN_NAME: ccma_admin
95+ADMIN_PASSWD: ccma_admin
96+priv_level: 4
97+user_id: 3
98+channel_num: 1
99+Note: But please set the settings in the section using ipmitool/dcmitool manually on SUT before starting user level test.
100+
101+######[Operator Level]######
102+[Operator Level]
103+OPER_NAME: ccma_oper
104+OPER_PASSWD: ccma_oper
105+priv_level: 3
106+user_id: 4
107+channel_num: 1
108+Note: But please set the settings in the section using ipmitool/dcmitool manually on SUT before starting user level test.
109+
110+######[User Level]######
111+[User Level]
112+USER_NAME: ccma_user
113+USER_PASSWD: ccma_user
114+priv_level: 2
115+user_id: 5
116+channel_num: 1
117+Note: But please set the settings in the section using ipmitool/dcmitool manually on SUT before starting user level test.
118+
119+
120+######[Add User Test]######
121+[Add User Test]
122+NEW_USER_NAME: ccma_test
123+NEW_USER_ID: 6
124+Note: Do not need to create this account manually
125+
126
127=== added file 'bin/bad_block_test'
128--- bin/bad_block_test 1970-01-01 00:00:00 +0000
129+++ bin/bad_block_test 2015-08-14 22:03:31 +0000
130@@ -0,0 +1,72 @@
131+#!/usr/bin/env python3
132+
133+"""
134+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
135+Industrial Technology Research Institute
136+
137+It is NOT YET officially approved by OCP.
138+
139+bad_block_test
140+ 1. Use badblocks command to perform a full disk bad block scan
141+ with given pattern.
142+ 2. The duration of the test is under 24 hours.
143+ 3. Criteria: pass if no hard disk error.
144+
145+Authors
146+ Nelson Chu <Nelson.Chu@itri.org.tw>
147+
148+This program is free software: you can redistribute it and/or modify
149+it under the terms of the GNU General Public License version 3,
150+as published by the Free Software Foundation.
151+
152+This program is distributed in the hope that it will be useful,
153+but WITHOUT ANY WARRANTY; without even the implied warranty of
154+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155+GNU General Public License for more details.
156+
157+You should have received a copy of the GNU General Public License
158+along with this program. If not, see <http://www.gnu.org/licenses/>.
159+
160+"""
161+
162+import os
163+import re
164+import sys
165+from subprocess import check_output, STDOUT
166+from argparse import ArgumentParser, RawTextHelpFormatter
167+
168+def run(pattern, device):
169+ return_code = 0
170+ command = "badblocks -wsvf -t {0} {1}".format(pattern, device)
171+
172+ try:
173+ with open(os.devnull, "w") as NULL:
174+ output = check_output(command, stderr=STDOUT, shell=True)
175+ output = output.decode('utf-8')
176+ except Exception as e:
177+ print(e.output.decode('utf-8'))
178+ return_code = 10
179+ return return_code
180+
181+ bad_blocks_match = re.search(r'\n(Pass completed\,\s(\d+)\s.*)\n$', output)
182+ if bad_blocks_match:
183+ print(bad_blocks_match.group(1))
184+ if int(bad_blocks_match.group(2)) != 0:
185+ return_code = 20
186+ else:
187+ print("Cannot parse badblocks output.")
188+ return_code = 30
189+ return return_code
190+
191+def main():
192+ parser = ArgumentParser(formatter_class=RawTextHelpFormatter)
193+ parser.add_argument('-t', '--pattern', type=str, required=True,
194+ help=("Specify a test pattern to be read \n"
195+ + "(and written) to disk blocks."))
196+ parser.add_argument('-d', '--device', type=str, required=True,
197+ help=("The device which tests in badblocks."))
198+ args = parser.parse_args()
199+ return run(args.pattern, args.device)
200+
201+if __name__ == '__main__':
202+ sys.exit(main())
203
204=== modified file 'bin/bios_info'
205--- bin/bios_info 2015-03-03 15:59:42 +0000
206+++ bin/bios_info 2015-08-14 22:03:31 +0000
207@@ -3,6 +3,8 @@
208 Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
209 Industrial Technology Research Institute
210
211+It is NOT YET officially approved by OCP.
212+
213 bios_info
214 1. Use lshw command to gather BIOS information.
215 2. The program will output BIOS vendor, version and release date.
216
217=== added file 'bin/block_device_resource'
218--- bin/block_device_resource 1970-01-01 00:00:00 +0000
219+++ bin/block_device_resource 2015-08-14 22:03:31 +0000
220@@ -0,0 +1,80 @@
221+#!/usr/bin/env python3
222+
223+import os
224+import re
225+from glob import glob
226+
227+rootdir_pattern = re.compile('^.*?/devices')
228+
229+def device_state(name):
230+ """
231+ Follow pmount policy to determine whether a device is removable or internal.
232+ """
233+ with open('/sys/block/%s/device/block/%s/removable' % (name, name)) as f:
234+ if f.read(1) == '1':
235+ return 'removable'
236+
237+ path = rootdir_pattern.sub('', os.readlink('/sys/block/%s' % name))
238+ hotplug_buses = ("usb", "ieee1394", "mmc", "pcmcia", "firewire")
239+ for bus in hotplug_buses:
240+ if os.path.exists('/sys/bus/%s' % bus):
241+ for device_bus in os.listdir('/sys/bus/%s/devices' % bus):
242+ device_link = rootdir_pattern.sub('', os.readlink(
243+ '/sys/bus/%s/devices/%s' % (bus, device_bus)))
244+ if re.search(device_link, path):
245+ return 'removable'
246+
247+ return 'internal'
248+
249+
250+def usb_support(name, version):
251+ """
252+ Check the USB specification number for both hub port and device
253+ """
254+ path = rootdir_pattern.sub('', os.readlink('/sys/block/%s' % name))
255+
256+ # Remove the usb config.interface part of the path
257+ m = re.match('((.*usb\d+).*\/)\d-[\d\.:\-]+\/.*', path)
258+ if m:
259+ device_path = m.group(1)
260+ hub_port_path = m.group(2)
261+
262+ # Check the highest version of USB the device supports
263+ with open('/sys/devices/%s/version' %device_path) as f:
264+ if float(f.readline()) < version:
265+ return 'unsupported'
266+
267+ # Check the highest version of USB the hub supports
268+ with open('/sys/devices/%s/version' %hub_port_path) as f:
269+ if float(f.readline()) < version:
270+ return 'unsupported'
271+
272+ return 'supported'
273+
274+ return 'unsupported'
275+
276+def device_rotation(name):
277+ with open('/sys/block/%s/device/block/%s/queue/rotational' % (name, name)) as f:
278+ if f.read(1) == '1':
279+ return 'yes'
280+
281+ return 'no'
282+
283+for path in glob('/sys/block/*/device'):
284+ name = re.sub('.*/(.*?)/device', '\g<1>', path)
285+ state = device_state(name)
286+ usb2 = usb_support(name, 2.00)
287+ usb3 = usb_support(name, 3.00)
288+ rotation = device_rotation(name)
289+ # FIXME: Remove leading block device name when the requirements
290+ # checking code in Checkbox allows it
291+ print("""\
292+%(name)s_state: %(state)s
293+%(name)s_usb2: %(usb2)s
294+%(name)s_usb3: %(usb3)s
295+%(name)s_rotation: %(rotation)s
296+""" % {"name": name,
297+ "state": state,
298+ "usb2": usb2,
299+ "usb3": usb3,
300+ "rotation": rotation})
301
302=== modified file 'bin/check_sata_port'
303--- bin/check_sata_port 2015-03-03 15:59:42 +0000
304+++ bin/check_sata_port 2015-08-14 22:03:31 +0000
305@@ -3,6 +3,8 @@
306 # Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
307 # Industrial Technology Research Institute
308 #
309+# It is NOT YET officially approved by OCP.
310+#
311 # check_sata_port
312 # 1. Use dmesg command to gather SATA information.
313 # 2. Criteria: SATA port speed up to 6.0Gps.
314
315=== added file 'bin/check_sata_port_leopard'
316--- bin/check_sata_port_leopard 1970-01-01 00:00:00 +0000
317+++ bin/check_sata_port_leopard 2015-08-14 22:03:31 +0000
318@@ -0,0 +1,38 @@
319+#!/bin/bash
320+#
321+# Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
322+# Industrial Technology Research Institute
323+#
324+# It is NOT YET officially approved by OCP.
325+#
326+# check_sata_port
327+# 1. Retrieve dmesg log to gather SATA information.
328+# 2. Criteria: SATA port speed up to 6.0Gps.
329+#
330+# Authors
331+# Nelson Chu <Nelson.Chu@itri.org.tw>
332+#
333+# This program is free software: you can redistribute it and/or modify
334+# it under the terms of the GNU General Public License version 3,
335+# as published by the Free Software Foundation.
336+#
337+# This program is distributed in the hope that it will be useful,
338+# but WITHOUT ANY WARRANTY; without even the implied warranty of
339+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
340+# GNU General Public License for more details.
341+#
342+# You should have received a copy of the GNU General Public License
343+# along with this program. If not, see <http://www.gnu.org/licenses/>.
344+#
345+
346+output=(`cat /var/log/dmesg |grep -i "SATA link up"| awk '{print $7}'`)
347+
348+for ((i=0; i<${#output[@]}; i++)); do
349+ if [ "$output" != "6.0" ]; then
350+ echo "Do not support SATA 6Gps ports"
351+ exit 1
352+ fi
353+done
354+
355+echo "Support SATA 6Gps ports"
356+exit 0
357
358=== modified file 'bin/check_usb_port'
359--- bin/check_usb_port 2015-03-03 15:59:42 +0000
360+++ bin/check_usb_port 2015-08-14 22:03:31 +0000
361@@ -3,6 +3,8 @@
362 # Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
363 # Industrial Technology Research Institute
364 #
365+# It is NOT YET officially approved by OCP.
366+#
367 # check_usb_port
368 # 1. Use dmesg command to gather USB information.
369 # 2. Criteria: USB version must be 2.0.
370
371=== added file 'bin/check_usb_port_leopard'
372--- bin/check_usb_port_leopard 1970-01-01 00:00:00 +0000
373+++ bin/check_usb_port_leopard 2015-08-14 22:03:31 +0000
374@@ -0,0 +1,43 @@
375+#!/bin/bash
376+#
377+# Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
378+# Industrial Technology Research Institute
379+#
380+# It is NOT YET officially approved by OCP.
381+#
382+# check_usb_port
383+# 1. Retrieve dmesg log to gather USB information.
384+# 2. Criteria: USB version must be 2.0 or higher.
385+#
386+# Authors
387+# Nelson Chu <Nelson.Chu@itri.org.tw>
388+#
389+# This program is free software: you can redistribute it and/or modify
390+# it under the terms of the GNU General Public License version 3,
391+# as published by the Free Software Foundation.
392+#
393+# This program is distributed in the hope that it will be useful,
394+# but WITHOUT ANY WARRANTY; without even the implied warranty of
395+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
396+# GNU General Public License for more details.
397+#
398+# You should have received a copy of the GNU General Public License
399+# along with this program. If not, see <http://www.gnu.org/licenses/>.
400+#
401+
402+support_usb_3=`cat /var/log/dmesg |grep -i "xhci_hcd" -c`
403+
404+if [ "$support_usb_3" -gt "0" ]; then
405+ echo "Support USB 3.0 ports."
406+ exit 0
407+fi
408+
409+output=`cat /var/log/dmesg |grep -i ehci_hcd:| awk '{print $5}'`
410+
411+if [ "$output" = "2.0" ]; then
412+ echo "Support USB 2.0 ports."
413+ exit 0
414+fi
415+
416+echo "Do not support USB 2.0 ports or higher."
417+exit 1
418
419=== modified file 'bin/cpu_info'
420--- bin/cpu_info 2015-03-03 15:59:42 +0000
421+++ bin/cpu_info 2015-08-14 22:03:31 +0000
422@@ -3,6 +3,8 @@
423 Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
424 Industrial Technology Research Institute
425
426+It is NOT YET officially approved by OCP.
427+
428 cpu_info
429 Use lshw command to gather CPU information.
430 The program will output CPU model and L1, L2, L3 cache size.
431
432=== added file 'bin/cpu_info_leopard'
433--- bin/cpu_info_leopard 1970-01-01 00:00:00 +0000
434+++ bin/cpu_info_leopard 2015-08-14 22:03:31 +0000
435@@ -0,0 +1,83 @@
436+#!/usr/bin/env python3
437+"""
438+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
439+Industrial Technology Research Institute
440+
441+It is NOT YET officially approved by OCP.
442+
443+cpu_info
444+ Use dmidecode command to gather CPU information.
445+ The program will output CPU model and L1, L2, L3 cache size.
446+ Criteria: CPU model and product family must match user's input.
447+
448+Authors
449+ Nelson Chu <Nelson.Chu@itri.org.tw>
450+
451+This program is free software: you can redistribute it and/or modify
452+it under the terms of the GNU General Public License version 3,
453+as published by the Free Software Foundation.
454+
455+This program is distributed in the hope that it will be useful,
456+but WITHOUT ANY WARRANTY; without even the implied warranty of
457+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
458+GNU General Public License for more details.
459+
460+You should have received a copy of the GNU General Public License
461+along with this program. If not, see <http://www.gnu.org/licenses/>.
462+
463+"""
464+
465+import os
466+import re
467+import sys
468+import xml.etree.ElementTree as ET
469+from subprocess import check_output
470+from argparse import ArgumentParser, RawTextHelpFormatter
471+
472+def run(product, family):
473+ command = "dmidecode -t processor |grep -E 'Version|Cache'"
474+ with open(os.devnull, 'w') as NULL:
475+ output = check_output(command, stderr=NULL, shell=True)
476+ output = output.decode('utf-8').strip()
477+
478+ cpu_attr = []
479+ for item in output.split('\n'):
480+ cpu_attr.append(item.strip())
481+
482+ for attr in cpu_attr:
483+ if attr.startswith("Version"):
484+ processor = attr.split(':')[1].strip()
485+ print(processor)
486+ match = re.search(product + '.*' + family, processor)
487+ if not match:
488+ print("Fail: Cannot match CPU %s %s family." %(product, family)
489+ ,file=sys.stderr)
490+ return 1
491+ else:
492+ cache_handle = attr.split(':')[1].strip()
493+ command = "dmidecode -t cache|grep -a6 {0}".format(cache_handle) +\
494+ "|grep -E 'Socket Designation|Installed Size'"
495+ with open(os.devnull, 'w') as NULL:
496+ output = check_output(command, stderr=NULL, shell=True)
497+ output = output.decode('utf-8').strip()
498+ print(output.split('\n')[0].split(':')[1].strip(),":", end="")
499+ print(output.split('\n')[1].split(':')[1].strip())
500+
501+ return 0
502+
503+def main():
504+ parser = ArgumentParser(formatter_class=RawTextHelpFormatter)
505+
506+ parser.add_argument('-p', '--product', type=str, required=True,
507+ help=("The CPU product name. [Example: Xeon]"))
508+ parser.add_argument('-f', '--family', type=str, required=True,
509+ help=("Processor family. [Example: E5]"))
510+
511+ args = parser.parse_args()
512+
513+ product = args.product.title()
514+ family = args.family.title()
515+ return run(product, family)
516+
517+if __name__ == '__main__':
518+ sys.exit(main())
519
520=== added file 'bin/create_raid'
521--- bin/create_raid 1970-01-01 00:00:00 +0000
522+++ bin/create_raid 2015-08-14 22:03:31 +0000
523@@ -0,0 +1,140 @@
524+#!/usr/bin/env python3
525+"""
526+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
527+Industrial Technology Research Institute
528+
529+It is NOT YET officially approved by OCP.
530+
531+create_raid
532+ Use megacli command to build user desired RAID on JBOD.
533+
534+ Warning: Make sure there is no RAID configuration in LSI RAID card
535+ before this program is performed.
536+
537+Authors
538+ Nelson Chu <Nelson.Chu@itri.org.tw>
539+
540+This program is free software: you can redistribute it and/or modify
541+it under the terms of the GNU General Public License version 3,
542+as published by the Free Software Foundation.
543+
544+This program is distributed in the hope that it will be useful,
545+but WITHOUT ANY WARRANTY; without even the implied warranty of
546+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
547+GNU General Public License for more details.
548+
549+You should have received a copy of the GNU General Public License
550+along with this program. If not, see <http://www.gnu.org/licenses/>.
551+
552+"""
553+
554+import os
555+import re
556+import sys
557+from time import sleep
558+from subprocess import check_output, STDOUT, CalledProcessError
559+from argparse import ArgumentParser, RawTextHelpFormatter
560+
561+def get_adapter():
562+ """
563+ Gather all adapter number if there are multiple RAID cards.
564+ """
565+
566+ command = 'megacli -CfgDsply -Aall|grep Adapter'
567+ adapter_list = []
568+
569+ adapter_info = check_output(command, shell=True)
570+ adapter_info = adapter_info.decode('utf-8')
571+
572+ for adapter in adapter_info.strip().split('\n'):
573+ adapter_list.append(adapter.strip().split(' ')[-1])
574+ return adapter_list
575+
576+
577+def get_all_disk(adapter):
578+ """
579+ Gather all disks Enclosure and Slot number, and make a
580+ Enclosure:Slot pair list.
581+ """
582+
583+ command = 'megacli -PDList -A{0}'.format(adapter) \
584+ + '|grep -E "Enclosure Device ID|Slot Number"'
585+
586+ disk_list = []
587+ disk_info = check_output(command, shell=True)
588+ disk_info = disk_info.decode('utf-8')
589+
590+ for line in disk_info.strip().split('\n'):
591+ if line.startswith('Enclosure'):
592+ match = re.search(r'\d+', line)
593+ disk_list.append(match.group(0))
594+ if line.startswith('Slot'):
595+ match = re.search(r'\d+', line)
596+ enclosure = disk_list.pop()
597+ E_S = '%s:%s' %(enclosure, match.group(0))
598+ disk_list.append(E_S)
599+ return disk_list
600+
601+
602+def build_raid(raid_type, adapter, disk_list):
603+ """
604+ Use all disks creatd RAID.
605+ If RAID type is 6 then set last disk as hot spare.
606+ """
607+
608+ if raid_type == 0:
609+ disk = ','.join(disk_list)
610+ command = 'megacli -CfgLDadd -r{0} [{1}] WB Direct -a{2}'.format(
611+ raid_type, disk, adapter)
612+
613+ if raid_type == 6:
614+ # use the last disk as hot spare
615+ spare = disk_list.pop()
616+
617+ disk = ','.join(disk_list)
618+ command = 'megacli -CfgLDadd -r{0} [{1}] WB Direct -Hsp[{2}] -a{3}'.format(
619+ raid_type, disk, spare, adapter)
620+
621+ output = check_output(command, stderr=STDOUT, shell=True)
622+ output = output.decode('utf-8')
623+ # wait for raid created
624+ sleep(5)
625+ print(output)
626+
627+
628+def main():
629+ parser = ArgumentParser(formatter_class=RawTextHelpFormatter)
630+ parser.add_argument('-t', '--type', type=int, required=True,
631+ help=("The RAID type which want to create. "
632+ "[Example: 0 or 6]"))
633+ args = parser.parse_args()
634+ knox_dict = {}
635+
636+ # get RAID card adapter number
637+ try:
638+ adapter_list = get_adapter()
639+ except CalledProcessError as e:
640+ print(e.output.decode('utf-8'))
641+ return 10
642+
643+ # get all disks in JBOD
644+ try:
645+ for adapter in adapter_list:
646+ knox_dict[adapter] = get_all_disk(adapter)
647+ except CalledProcessError as e:
648+ print(e.output.decode('utf-8'))
649+ return 20
650+
651+ # use all HDDs to build RAID
652+ try:
653+ for adapter, disk_list in knox_dict.items():
654+ build_raid(args.type, adapter, disk_list)
655+ except CalledProcessError as e:
656+ print(e.output.decode('utf-8'))
657+ return 30
658+
659+ return 0
660+
661+
662+if __name__ == '__main__':
663+ sys.exit(main())
664
665=== added file 'bin/dcmi_inventory'
666--- bin/dcmi_inventory 1970-01-01 00:00:00 +0000
667+++ bin/dcmi_inventory 2015-08-14 22:03:31 +0000
668@@ -0,0 +1,136 @@
669+#!/usr/bin/env python3
670+"""
671+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
672+Industrial Technology Research Institute
673+
674+File Name
675+ dcmi_inventory
676+ 1. Use dcmitool to collect inventory information including Asset Tag, Device ID, System GUI, Firmware/Software Information, Management Controller ID
677+ 2. Criteria: All information mentioned above must not should not be null
678+Authors
679+ Sophia Wu <Sophia.Wu@itri.org.tw>
680+
681+This program is free software: you can redistribute it and/or modify
682+it under the terms of the GNU General Public License version 3,
683+as published by the Free Software Foundation.
684+
685+This program is distributed in the hope that it will be useful,
686+but WITHOUT ANY WARRANTY; without even the implied warranty of
687+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
688+GNU General Public License for more details.
689+
690+You should have received a copy of the GNU General Public License
691+along with this program. If not, see <http://www.gnu.org/licenses/>.
692+
693+"""
694+
695+import sys
696+import time
697+import shlex
698+import subprocess
699+import re
700+import subprocess
701+from subprocess import (
702+ CalledProcessError,
703+ check_call,
704+ check_output
705+)
706+
707+def get_asset_tag():
708+
709+ try:
710+ cmd = 'dcmitool dcmi asset_tag'
711+ dcmi_asset_tag_return = check_output(shlex.split(cmd), universal_newlines=True)
712+ time.sleep(5)
713+ except CalledProcessError as command_exception:
714+ print("Failed executing dcmi command for getting asset tag. Reason:%s" % command_exception)
715+
716+ try:
717+ asset_tag = re.search(r'Asset tag\s*:\s*([a-zA-Z0-9-._ ]+)', dcmi_asset_tag_return)
718+ if asset_tag == None:
719+ return 'Error'
720+ return asset_tag.group(1).strip()
721+ except:
722+ return 'Error'
723+
724+def get_guid():
725+
726+ try:
727+ cmd = 'dcmitool mc guid'
728+ dcmi_guid_return = check_output(shlex.split(cmd), universal_newlines=True)
729+ time.sleep(5)
730+ except CalledProcessError as command_exception:
731+ print("Failed executing dcmi command for getting guid. Reason:%s" % command_exception)
732+
733+ try:
734+ mcguid = re.search(r'System GUID\s*:\s*([a-zA-Z0-9-._ ]+)', dcmi_guid_return)
735+ if mcguid == None:
736+ return 'Error'
737+ return mcguid.group(1).strip()
738+ except:
739+ return 'Error'
740+
741+def get_mcid():
742+
743+ try:
744+ cmd = 'dcmitool dcmi get_mc_id_string'
745+ dcmi_mcid_return = check_output(shlex.split(cmd), universal_newlines=True)
746+ time.sleep(5)
747+ except CalledProcessError as command_exception:
748+ print("Failed executing dcmi command for getting mc id. Reason:%s" % command_exception)
749+
750+ try:
751+ mcid = re.search(r'Get Management Controller Identifier String\s*:\s*([a-zA-Z0-9-._ ]+)', dcmi_mcid_return)
752+ if mcid == None:
753+ return 'Error'
754+ return mcid.group(1).strip()
755+ except:
756+ return 'Error'
757+
758+def get_mcinfo():
759+
760+ try:
761+ cmd = 'dcmitool mc info'
762+ dcmi_mcinfo_return = check_output(shlex.split(cmd), universal_newlines=True)
763+ time.sleep(5)
764+ except CalledProcessError as command_exception:
765+ print("Failed executing dcmi command for getting mc info. Reason:%s" % command_exception)
766+
767+ try:
768+ deviceid = re.search(r'Device ID\s*:\s*([a-zA-Z0-9-._ ]+)', dcmi_mcinfo_return)
769+ Manufac = re.search(r'Manufacturer Name\s*:\s*([a-zA-Z-._ ]+)', dcmi_mcinfo_return)
770+ Firm = re.search(r'Firmware Revision\s+\s*:\s*([a-zA-Z0-9-._ ]+)', dcmi_mcinfo_return)
771+
772+ if deviceid == None or Manufac == None or Firm == None:
773+ return 'Error', 'Error', 'Error'
774+ return (deviceid.group(1).strip(), Manufac.group(1).strip(), Firm.group(1).strip())
775+ except:
776+ return 'Error', 'Error', 'Error'
777+
778+def main():
779+
780+ flag = 0
781+ inventory_dict = {}
782+ inventory_list = ['Asset Tag', 'System GUID', 'Get Management Controller Identifier String', 'Device ID', 'Manufacturer Name', 'Firmware Revision']
783+ Device_ID, Manufacturer, Firmware = get_mcinfo()
784+ inventory_dict.update({'Asset Tag':get_asset_tag()})
785+ inventory_dict.update({'System GUID':get_guid()})
786+ inventory_dict.update({'Get Management Controller Identifier String':get_mcid()})
787+ inventory_dict.update({'Device ID':Device_ID})
788+ inventory_dict.update({'Manufacturer Name':Manufacturer})
789+ inventory_dict.update({'Firmware Revision':Firmware})
790+
791+ for item in inventory_list:
792+ if inventory_dict.get(item) == 'Error':
793+ flag = 1
794+ else:
795+ print("{}: {}".format(item, inventory_dict.get(item)))
796+
797+ if flag == 1:
798+ return 1
799+ return 0
800+
801+if __name__ == '__main__':
802+ sys.exit(main())
803+
804+
805
806=== added file 'bin/dcmi_power_off_on'
807--- bin/dcmi_power_off_on 1970-01-01 00:00:00 +0000
808+++ bin/dcmi_power_off_on 2015-08-14 22:03:31 +0000
809@@ -0,0 +1,190 @@
810+#! /usr/bin/env python3
811+"""
812+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
813+Industrial Technology Research Institute
814+
815+File Name
816+ dcmi_power_off_on
817+ Use dcmitool out-of-band access to turn on/off the SUT
818+
819+Authors
820+ Sophia Wu <Sophia.Wu@itri.org.tw>
821+
822+This program is free software: you can redistribute it and/or modify
823+it under the terms of the GNU General Public License version 3,
824+as published by the Free Software Foundation.
825+
826+This program is distributed in the hope that it will be useful,
827+but WITHOUT ANY WARRANTY; without even the implied warranty of
828+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
829+GNU General Public License for more details.
830+
831+You should have received a copy of the GNU General Public License
832+along with this program. If not, see <http://www.gnu.org/licenses/>.
833+
834+"""
835+from argparse import (
836+ ArgumentParser,
837+ RawTextHelpFormatter
838+)
839+
840+import sys
841+import configparser
842+import shlex
843+import subprocess
844+import ast
845+import time
846+from subprocess import (
847+ check_output,
848+ CalledProcessError
849+)
850+
851+def check_power_status(host_ip, user, password):
852+
853+ cmd_status_on = 'dcmitool -H {} -U {} -P {} power status| grep -q "on"'\
854+ .format(host_ip, user, password)
855+ check_on_value = subprocess.call(cmd_status_on, shell=True)
856+ time.sleep(5)
857+
858+ cmd_status_off = 'dcmitool -H {} -U {} -P {} power status| grep -q "off"'\
859+ .format(host_ip, user, password)
860+ check_off_value = subprocess.call(cmd_status_off, shell=True)
861+ time.sleep(5)
862+
863+ if check_on_value == 0 and check_off_value == 1:
864+ check_status = 'on'
865+
866+ elif check_on_value == 1 and check_off_value == 0:
867+ check_status = 'off'
868+
869+ else:
870+ check_status = 'error'
871+
872+ return check_status
873+
874+def run_power_off(host_ip, user, password):
875+ cmd_power_off = 'dcmitool -H {} -U {} -P {} power off'\
876+ .format(host_ip, user, password)
877+ power_off_return_code = subprocess.call(cmd_power_off, shell=True)
878+ return power_off_return_code
879+
880+def run_power_on(host_ip, user, password):
881+ cmd_power_on = 'dcmitool -H {} -U {} -P {} power on'\
882+ .format(host_ip, user, password)
883+ power_on_return_code = subprocess.call(cmd_power_on, shell=True)
884+ return power_on_return_code
885+
886+def dcmi_reset_oob(args):
887+
888+ #DCMI config file
889+ DEFAULT_CFG = "/etc/checkbox.d/me.cfg"
890+ if not "config" in vars(args):
891+ config_file = DEFAULT_CFG
892+ else:
893+ config_file = args.config
894+
895+ config = configparser.RawConfigParser()
896+
897+ try:
898+ config.readfp(open(config_file))
899+ except IOError:
900+ print("No config file found")
901+ return 10
902+
903+ try:
904+ targets_options = config.options('Targets')
905+ targets_list = []
906+ for target_key in targets_options:
907+ targets_list.append(config.get('Targets', target_key))
908+
909+ if not targets_list:
910+ print("Invalid or Empty targets")
911+ return 20
912+
913+ except configparser.Error:
914+ print("Invalid or Empty targets")
915+ return 30
916+
917+ try:
918+ user_value = config.get('Account', 'USER')
919+ passwd_value = config.get('Account', 'PASSWORD')
920+ if not user_value or not passwd_value:
921+ print("Invalid or Empty credential info")
922+ return 40
923+
924+ except configparser.Error:
925+ print("Invalid or Empty credential info")
926+ return 50
927+
928+ ping_flag = 0
929+ for tg in targets_list:
930+
931+ if not tg or not user_value or not passwd_value:
932+ print("Require Taget IP, Account(USER/PASSWORD) for DCMI out-of-band access")
933+ return 21
934+ else:
935+
936+ print("SUT =", tg)
937+ print("USER =", user_value)
938+ print("PASSWORD =", passwd_value)
939+
940+ for n in range(2):
941+
942+ count = 0
943+ while count < 10:
944+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(tg)
945+ ping_rtn = subprocess.call(ping_cmd, shell=True)
946+ if ping_rtn == 0:
947+ print("Destination Host Reachable")
948+
949+ #run test
950+ status = check_power_status(tg, user_value, passwd_value)
951+
952+ if status == 'on':
953+ #run power off
954+ power_off_result = run_power_off(tg, user_value, passwd_value)
955+ print(" ")
956+ if power_off_result == 1:
957+ print("Failed to power off SUT.")
958+ return 88
959+ elif status == 'off':
960+ #run power on
961+ power_on_result = run_power_on(tg, user_value, passwd_value)
962+ print(" ")
963+ if power_on_result == 1:
964+ print("Failed to power on SUT.")
965+ return 99
966+ else:
967+ #do nothing
968+ print("Failed to check power status")
969+ return 77
970+
971+ time.sleep(30)
972+ break
973+
974+ else:
975+ time.sleep(10)
976+ count = count+1
977+ print("Destination Host Unreachable")
978+
979+ if count == 10:
980+ print("Host Has No Response, End of Test")
981+ ping_flag = 100
982+
983+ if ping_flag == 100:
984+ return 100
985+ return 0
986+
987+def main():
988+
989+ intro_message = "Default config location is /etc/checkbox.d/me.cfg"
990+ parser = ArgumentParser(description=intro_message,
991+ formatter_class=RawTextHelpFormatter)
992+ parser.add_argument('--config', type=str,
993+ default="/etc/checkbox.d/me.cfg",
994+ help="Supply config file for getting authentication info")
995+ args = parser.parse_args()
996+ return dcmi_reset_oob(args)
997+
998+if __name__ == "__main__":
999+ sys.exit(main())
1000
1001=== added file 'bin/dcmi_power_reset'
1002--- bin/dcmi_power_reset 1970-01-01 00:00:00 +0000
1003+++ bin/dcmi_power_reset 2015-08-14 22:03:31 +0000
1004@@ -0,0 +1,139 @@
1005+#!/usr/bin/env python3
1006+"""
1007+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
1008+Industrial Technology Research Institute
1009+
1010+File Name
1011+ dcmi_power_reset
1012+ Complete 20 power reset on SUT successfully using dcmitool out-of-band access
1013+
1014+Authors
1015+ Sophia Wu <Sophia.Wu@itri.org.tw>
1016+
1017+This program is free software: you can redistribute it and/or modify
1018+it under the terms of the GNU General Public License version 3,
1019+as published by the Free Software Foundation.
1020+
1021+This program is distributed in the hope that it will be useful,
1022+but WITHOUT ANY WARRANTY; without even the implied warranty of
1023+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1024+GNU General Public License for more details.
1025+
1026+You should have received a copy of the GNU General Public License
1027+along with this program. If not, see <http://www.gnu.org/licenses/>.
1028+
1029+"""
1030+
1031+from argparse import (
1032+ ArgumentParser,
1033+ RawTextHelpFormatter
1034+)
1035+
1036+import sys
1037+import configparser
1038+import shlex
1039+import subprocess
1040+import ast
1041+import time
1042+from subprocess import (
1043+ check_output,
1044+ CalledProcessError
1045+)
1046+
1047+def run(host_ip, user, password):
1048+ cmd = 'dcmitool -H {} -U {} -P {} power reset'.format(host_ip, user, password)
1049+ power_reset_return = check_output(shlex.split(cmd), universal_newlines=True)
1050+ return power_reset_return
1051+
1052+def dcmi_reset_oob(args):
1053+
1054+ #DCMI config file
1055+ DEFAULT_CFG = "/etc/checkbox.d/me.cfg"
1056+ if not "config" in vars(args):
1057+ config_file = DEFAULT_CFG
1058+ else:
1059+ config_file = args.config
1060+
1061+ config = configparser.RawConfigParser()
1062+ try:
1063+ config.readfp(open(config_file))
1064+ except IOError:
1065+ print("No config file found")
1066+ return 1
1067+
1068+ try:
1069+ targets_options = config.options('Targets')
1070+ targets_list = []
1071+ for target_key in targets_options:
1072+ targets_list.append(config.get('Targets', target_key))
1073+ if not targets_list:
1074+ print("Invalid or Empty targets")
1075+ return 2
1076+ except configparser.Error:
1077+ print("Invalid or Empty targets")
1078+ return 2
1079+
1080+ try:
1081+ user_value = config.get("Account", "USER")
1082+ password_value = config.get("Account", "PASSWORD")
1083+ except configparser.NoOptionError:
1084+ print("Invalid or Empty credential info")
1085+ return 3
1086+
1087+ ping_flag = 0
1088+ for tg in targets_list:
1089+
1090+ if not tg or not user_value or not password_value:
1091+ print("Require Taget IP, Account(USER/PASSWORD) for DCMI out-of-band access")
1092+ return 4
1093+ else:
1094+ print("SUT =", tg)
1095+ print("USER =", user_value)
1096+ print("PASSWORD =", password_value)
1097+
1098+ for n in range(20):
1099+ print("---------------- %s ----------------" % n)
1100+ count = 0
1101+ while count < 10:
1102+ print("+++++++++++ %s ++++++++++++" % count)
1103+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(tg)
1104+ ping_rtn = subprocess.call(ping_cmd, shell=True)
1105+
1106+ if ping_rtn == 0:
1107+ print("Destination Host Reachable")
1108+
1109+ try:
1110+ power_control = run(tg, user_value, password_value)
1111+ print(power_control)
1112+ except CalledProcessError as dcmi_exception:
1113+ print("Failed executing dcmi, Reason: %s" % dcmi_exception)
1114+ return 6
1115+
1116+ time.sleep(30)
1117+ break
1118+ else:
1119+ time.sleep(10)
1120+ count = count+1
1121+ print("Destination Host Unreachable")
1122+
1123+ if count == 10:
1124+ print("Host Has No Response, End of Test")
1125+ ping_flag = 100
1126+
1127+ if ping_flag == 100:
1128+ return 100
1129+ return 0
1130+
1131+def main():
1132+
1133+ intro_message = "Default config location is /etc/checkbox.d/me.cfg"
1134+ parser = ArgumentParser(description=intro_message,
1135+ formatter_class=RawTextHelpFormatter)
1136+ parser.add_argument('--config',
1137+ default="/etc/checkbox.d/me.cfg",
1138+ help="Supply config file for getting authentication info")
1139+ args = parser.parse_args()
1140+ return dcmi_reset_oob(args)
1141+
1142+if __name__ == "__main__":
1143+ sys.exit(main())
1144
1145=== added file 'bin/dcmi_priv_admin'
1146--- bin/dcmi_priv_admin 1970-01-01 00:00:00 +0000
1147+++ bin/dcmi_priv_admin 2015-08-14 22:03:31 +0000
1148@@ -0,0 +1,174 @@
1149+#! /usr/bin/env python3
1150+"""
1151+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
1152+Industrial Technology Research Institute
1153+
1154+File Name
1155+ dcmi_priv_admin
1156+ 1. Use dcmitool out-of-band to read power status, to perform power reset and add a new user account
1157+ 2. Criteria: Reading power status, performing power reset and adding a user account must all be successful
1158+
1159+Authors
1160+ Sophia Wu <Sophia.Wu@itri.org.tw>
1161+
1162+This program is free software: you can redistribute it and/or modify
1163+it under the terms of the GNU General Public License version 3,
1164+as published by the Free Software Foundation.
1165+
1166+This program is distributed in the hope that it will be useful,
1167+but WITHOUT ANY WARRANTY; without even the implied warranty of
1168+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1169+GNU General Public License for more details.
1170+
1171+You should have received a copy of the GNU General Public License
1172+along with this program. If not, see <http://www.gnu.org/licenses/>.
1173+
1174+"""
1175+from argparse import (
1176+ ArgumentParser,
1177+ RawTextHelpFormatter
1178+)
1179+
1180+import sys
1181+import configparser
1182+import shlex
1183+import subprocess
1184+import ast
1185+import time
1186+from subprocess import (
1187+ check_output,
1188+ CalledProcessError
1189+)
1190+
1191+def get_power_status(host_ip, user, password):
1192+ cmd_status = 'dcmitool -H {} -U {} -P {} power status 1>/dev/null 2>/dev/null'\
1193+ .format(host_ip, user, password)
1194+ status_code = subprocess.call(cmd_status, shell=True)
1195+ return status_code
1196+
1197+def power_reset(host_ip, user, password):
1198+ cmd_reset = 'dcmitool -H {} -U {} -P {} power reset 1>/dev/null 2>/dev/null'\
1199+ .format(host_ip, user, password)
1200+ reset_code = subprocess.call(cmd_reset, shell=True)
1201+ return reset_code
1202+
1203+def add_user(host_ip, user, password, new_id, new_user):
1204+ cmd_add_user = 'dcmitool -H {} -U {} -P {} user set name {} {} 1>/dev/null 2>/dev/null'\
1205+ .format(host_ip, user, password, new_id, new_user)
1206+ add_user_code = subprocess.call(cmd_add_user, shell=True)
1207+ return add_user_code
1208+
1209+def dcmi_user_level_test(args):
1210+
1211+ #DCMI config file
1212+ DEFAULT_CFG = "/etc/checkbox.d/me.cfg"
1213+ if not "config" in vars(args):
1214+ config_file = DEFAULT_CFG
1215+ else:
1216+ config_file = args.config
1217+ config = configparser.RawConfigParser()
1218+ try:
1219+ config.readfp(open(config_file))
1220+ except IOError:
1221+ print("No config file found")
1222+ return 10
1223+
1224+ try:
1225+ targets_options = config.options('Targets')
1226+ targets_list = []
1227+ for target_key in targets_options:
1228+ targets_list.append(config.get('Targets', target_key))
1229+ if not targets_list:
1230+ print("Invalid or Empty targets")
1231+ return 20
1232+ except configparser.Error:
1233+ print("Invalid or Empty targets")
1234+ return 20
1235+
1236+ try:
1237+ user_value = config.get("Admin Level", "ADMIN_NAME")
1238+ password_value = config.get("Admin Level", "ADMIN_PASSWD")
1239+ except configparser.NoOptionError:
1240+ print("Invalid or Empty credential info")
1241+ print("Require Operator Level info pre-configured in /etc/checkbox.d/me.cfg")
1242+ return 30
1243+
1244+ try:
1245+ new_user_value = config.get("Add User Test", "NEW_USER_NAME")
1246+ new_user_id_value = config.get("Add User Test", "NEW_USER_ID")
1247+ except configparser.NoOptionError:
1248+ print("Invalid or Empty new user info")
1249+ print("Require new User info pre-configured in /etc/checkbox.d/me.cfg")
1250+ return 40
1251+
1252+ flag = 0
1253+ for tg in targets_list:
1254+
1255+ if not tg or not user_value or not password_value:
1256+ print("Require Taget IP, Account(USER/PASSWORD) for DCMI out-of-band access")
1257+ return 50
1258+ else:
1259+ print("SUT", tg)
1260+
1261+ ping_result = ping_test(tg)
1262+ if ping_result != 0:
1263+ return 88
1264+
1265+ status_result = get_power_status(tg, user_value, password_value)
1266+ time.sleep(5)
1267+
1268+ reset_result = power_reset(tg, user_value, password_value)
1269+ time.sleep(5)
1270+ if not new_user_value or not new_user_id_value:
1271+ print("Require new user info pre-configured in /etc/checkbox.d/me.cfg")
1272+ return 60
1273+ else:
1274+
1275+ ping_result = ping_test(tg)
1276+ if ping_result != 0:
1277+ return 88
1278+
1279+ add_user_result = add_user(tg, user_value, password_value, new_user_id_value, new_user_value)
1280+ time.sleep(5)
1281+
1282+ if status_result == 0 and reset_result == 0 and add_user_result == 0:
1283+ print("User can read power status.")
1284+ print("User can reset power.")
1285+ print("User can add a new user.")
1286+ else:
1287+ print("Authentication: Not Administrator Level")
1288+ flag = 1
1289+
1290+ if flag == 1:
1291+ return 100
1292+ return 0
1293+
1294+def ping_test(host_ip):
1295+ count = 0
1296+ while count < 10:
1297+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(host_ip)
1298+ ping_rtn = subprocess.call(ping_cmd, shell=True)
1299+ if ping_rtn == 0:
1300+ return 0
1301+ else:
1302+ print("Destination Host Unreachable")
1303+ time.sleep(10)
1304+ count = count+1
1305+
1306+ if count == 10:
1307+ print("Host Has No Response, End of Test")
1308+ return 1
1309+
1310+
1311+def main():
1312+
1313+ intro_message = "Default config location is /etc/checkbox.d/me.cfg"
1314+ parser = ArgumentParser(description=intro_message, formatter_class=RawTextHelpFormatter)
1315+ parser.add_argument('--config', type=str,
1316+ default="/etc/checkbox.d/me.cfg",
1317+ help="Supply config file for getting authentication info")
1318+ args = parser.parse_args()
1319+ return dcmi_user_level_test(args)
1320+
1321+if __name__ == "__main__":
1322+ sys.exit(main())
1323
1324=== added file 'bin/dcmi_priv_oper'
1325--- bin/dcmi_priv_oper 1970-01-01 00:00:00 +0000
1326+++ bin/dcmi_priv_oper 2015-08-14 22:03:31 +0000
1327@@ -0,0 +1,174 @@
1328+#! /usr/bin/env python3
1329+"""
1330+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
1331+Industrial Technology Research Institute
1332+
1333+File Name
1334+ dcmi_priv_oper
1335+ 1. Use dcmitool out-of-band to read power status, to perform power reset and add a new user account
1336+ 2. Criteria: power status reading and power reset must be successful and must fail at adding a new user account
1337+
1338+Authors
1339+ Sophia Wu <Sophia.Wu@itri.org.tw>
1340+
1341+This program is free software: you can redistribute it and/or modify
1342+it under the terms of the GNU General Public License version 3,
1343+as published by the Free Software Foundation.
1344+
1345+This program is distributed in the hope that it will be useful,
1346+but WITHOUT ANY WARRANTY; without even the implied warranty of
1347+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1348+GNU General Public License for more details.
1349+
1350+You should have received a copy of the GNU General Public License
1351+along with this program. If not, see <http://www.gnu.org/licenses/>.
1352+
1353+"""
1354+from argparse import (
1355+ ArgumentParser,
1356+ RawTextHelpFormatter
1357+)
1358+
1359+import sys
1360+import configparser
1361+import shlex
1362+import subprocess
1363+import ast
1364+import time
1365+from subprocess import (
1366+ check_output,
1367+ CalledProcessError
1368+)
1369+
1370+def get_power_status(host_ip, user, password):
1371+ cmd_status = 'dcmitool -H {} -U {} -P {} power status 1>/dev/null 2>/dev/null'\
1372+ .format(host_ip, user, password)
1373+ status_code = subprocess.call(cmd_status, shell=True)
1374+ return status_code
1375+
1376+def power_reset(host_ip, user, password):
1377+ cmd_reset = 'dcmitool -H {} -U {} -P {} power reset 1>/dev/null 2>/dev/null'\
1378+ .format(host_ip, user, password)
1379+ reset_code = subprocess.call(cmd_reset, shell=True)
1380+ return reset_code
1381+
1382+def add_user(host_ip, user, password, new_id, new_user):
1383+ cmd_add_user = 'dcmitool -H {} -U {} -P {} user set name {} {} 1>/dev/null 2>/dev/null'\
1384+ .format(host_ip, user, password, new_id, new_user)
1385+ add_user_code = subprocess.call(cmd_add_user, shell=True)
1386+ return add_user_code
1387+
1388+def dcmi_user_level_test(args):
1389+
1390+ #DCMI config file
1391+ DEFAULT_CFG = "/etc/checkbox.d/me.cfg"
1392+ if not "config" in vars(args):
1393+ config_file = DEFAULT_CFG
1394+ else:
1395+ config_file = args.config
1396+ config = configparser.RawConfigParser()
1397+ try:
1398+ config.readfp(open(config_file))
1399+ except IOError:
1400+ print("No config file found")
1401+ return 10
1402+
1403+ try:
1404+ targets_options = config.options('Targets')
1405+ targets_list = []
1406+ for target_key in targets_options:
1407+ targets_list.append(config.get('Targets', target_key))
1408+ if not targets_list:
1409+ print("Invalid or Empty targets")
1410+ return 20
1411+ except configparser.Error:
1412+ print("Invalid or Empty targets")
1413+ return 20
1414+
1415+ try:
1416+ user_value = config.get("Operator Level", "OPER_NAME")
1417+ password_value = config.get("Operator Level", "OPER_PASSWD")
1418+ except configparser.NoOptionError:
1419+ print("Invalid or Empty credential info")
1420+ print("Require Operator Level info pre-configured in /etc/checkbox.d/me.cfg")
1421+ return 30
1422+
1423+ try:
1424+ new_user_value = config.get("Add User Test", "NEW_USER_NAME")
1425+ new_user_id_value = config.get("Add User Test", "NEW_USER_ID")
1426+ except configparser.NoOptionError:
1427+ print("Invalid or Empty new user info")
1428+ print("Require new User info pre-configured in /etc/checkbox.d/me.cfg")
1429+ return 40
1430+
1431+ flag = 0
1432+ for tg in targets_list:
1433+
1434+ if not tg or not user_value or not password_value:
1435+ print("Require Taget IP, Account(USER/PASSWORD) for DCMI out-of-band access")
1436+ return 50
1437+ else:
1438+ print("SUT", tg)
1439+
1440+ ping_result = ping_test(tg)
1441+ if ping_result != 0:
1442+ return 88
1443+
1444+ status_result = get_power_status(tg, user_value, password_value)
1445+ time.sleep(5)
1446+
1447+ reset_result = power_reset(tg, user_value, password_value)
1448+ time.sleep(5)
1449+ if not new_user_value or not new_user_id_value:
1450+ print("Require new user info pre-configured in /etc/checkbox.d/me.cfg")
1451+ return 60
1452+ else:
1453+
1454+ ping_result = ping_test(tg)
1455+ if ping_result != 0:
1456+ return 88
1457+
1458+ add_user_result = add_user(tg, user_value, password_value, new_user_id_value, new_user_value)
1459+ time.sleep(5)
1460+
1461+ if status_result == 0 and reset_result == 0 and add_user_result == 1:
1462+ print("User can read power status.")
1463+ print("User can reset power.")
1464+ print("User can't add a new user.")
1465+ else:
1466+ print("Authentication: Not Operator Level")
1467+ flag = 1
1468+
1469+ if flag == 1:
1470+ return 100
1471+ return 0
1472+
1473+def ping_test(host_ip):
1474+ count = 0
1475+ while count < 10:
1476+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(host_ip)
1477+ ping_rtn = subprocess.call(ping_cmd, shell=True)
1478+ if ping_rtn == 0:
1479+ return 0
1480+ else:
1481+ print("Destination Host Unreachable")
1482+ time.sleep(10)
1483+ count = count+1
1484+
1485+ if count == 10:
1486+ print("Host Has No Response, End of Test")
1487+ return 1
1488+
1489+
1490+def main():
1491+
1492+ intro_message = "Default config location is /etc/checkbox.d/me.cfg"
1493+ parser = ArgumentParser(description=intro_message, formatter_class=RawTextHelpFormatter)
1494+ parser.add_argument('--config', type=str,
1495+ default="/etc/checkbox.d/me.cfg",
1496+ help="Supply config file for getting authentication info")
1497+ args = parser.parse_args()
1498+ return dcmi_user_level_test(args)
1499+
1500+if __name__ == "__main__":
1501+ sys.exit(main())
1502
1503=== added file 'bin/dcmi_priv_user'
1504--- bin/dcmi_priv_user 1970-01-01 00:00:00 +0000
1505+++ bin/dcmi_priv_user 2015-08-14 22:03:31 +0000
1506@@ -0,0 +1,174 @@
1507+#! /usr/bin/env python3
1508+"""
1509+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
1510+Industrial Technology Research Institute
1511+
1512+File Name
1513+ dcmi_priv_uesr
1514+ 1. Use dcmitool out-of-band to read power status, to perform power reset and add a new user account
1515+ 2. Criteria: power status reading must be successful and must fail at power reset and adding a new user account
1516+
1517+Authors
1518+ Sophia Wu <Sophia.Wu@itri.org.tw>
1519+
1520+This program is free software: you can redistribute it and/or modify
1521+it under the terms of the GNU General Public License version 3,
1522+as published by the Free Software Foundation.
1523+
1524+This program is distributed in the hope that it will be useful,
1525+but WITHOUT ANY WARRANTY; without even the implied warranty of
1526+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1527+GNU General Public License for more details.
1528+
1529+You should have received a copy of the GNU General Public License
1530+along with this program. If not, see <http://www.gnu.org/licenses/>.
1531+
1532+"""
1533+from argparse import (
1534+ ArgumentParser,
1535+ RawTextHelpFormatter
1536+)
1537+
1538+import sys
1539+import configparser
1540+import shlex
1541+import subprocess
1542+import ast
1543+import time
1544+from subprocess import (
1545+ check_output,
1546+ CalledProcessError
1547+)
1548+
1549+def get_power_status(host_ip, user, password):
1550+ cmd_status = 'dcmitool -H {} -U {} -P {} power status 1>/dev/null 2>/dev/null'\
1551+ .format(host_ip, user, password)
1552+ status_code = subprocess.call(cmd_status, shell=True)
1553+ return status_code
1554+
1555+def power_reset(host_ip, user, password):
1556+ cmd_reset = 'dcmitool -H {} -U {} -P {} power reset 1>/dev/null 2>/dev/null'\
1557+ .format(host_ip, user, password)
1558+ reset_code = subprocess.call(cmd_reset, shell=True)
1559+ return reset_code
1560+
1561+def add_user(host_ip, user, password, new_id, new_user):
1562+ cmd_add_user = 'dcmitool -H {} -U {} -P {} user set name {} {} 1>/dev/null 2>/dev/null'\
1563+ .format(host_ip, user, password, new_id, new_user)
1564+ add_user_code = subprocess.call(cmd_add_user, shell=True)
1565+ return add_user_code
1566+
1567+def dcmi_user_level_test(args):
1568+
1569+ #DCMI config file
1570+ DEFAULT_CFG = "/etc/checkbox.d/me.cfg"
1571+ if not "config" in vars(args):
1572+ config_file = DEFAULT_CFG
1573+ else:
1574+ config_file = args.config
1575+ config = configparser.RawConfigParser()
1576+ try:
1577+ config.readfp(open(config_file))
1578+ except IOError:
1579+ print("No config file found")
1580+ return 10
1581+
1582+ try:
1583+ targets_options = config.options('Targets')
1584+ targets_list = []
1585+ for target_key in targets_options:
1586+ targets_list.append(config.get('Targets', target_key))
1587+ if not targets_list:
1588+ print("Invalid or Empty targets")
1589+ return 20
1590+ except configparser.Error:
1591+ print("Invalid or Empty targets")
1592+ return 20
1593+
1594+ try:
1595+ user_value = config.get("User Level", "USER_NAME")
1596+ password_value = config.get("User Level", "USER_PASSWD")
1597+ except configparser.NoOptionError:
1598+ print("Invalid or Empty credential info")
1599+ print("Require User Level info pre-configured in /etc/checkbox.d/me.cfg")
1600+ return 30
1601+
1602+ try:
1603+ new_user_value = config.get("Add User Test", "NEW_USER_NAME")
1604+ new_user_id_value = config.get("Add User Test", "NEW_USER_ID")
1605+ except configparser.NoOptionError:
1606+ print("Invalid or Empty new user info")
1607+ print("Require new User info pre-configured in /etc/checkbox.d/me.cfg")
1608+ return 40
1609+
1610+ flag = 0
1611+ for tg in targets_list:
1612+
1613+ if not tg or not user_value or not password_value:
1614+ print("Require Taget IP, Account(USER/PASSWORD) for DCMI out-of-band access")
1615+ return 50
1616+ else:
1617+ print("SUT", tg)
1618+
1619+ ping_result = ping_test(tg)
1620+ if ping_result != 0:
1621+ return 88
1622+
1623+ status_result = get_power_status(tg, user_value, password_value)
1624+ time.sleep(5)
1625+
1626+ reset_result = power_reset(tg, user_value, password_value)
1627+ time.sleep(5)
1628+ if not new_user_value or not new_user_id_value:
1629+ print("Require new user info pre-configured in /etc/checkbox.d/me.cfg")
1630+ return 60
1631+ else:
1632+
1633+ ping_result = ping_test(tg)
1634+ if ping_result != 0:
1635+ return 88
1636+
1637+ add_user_result = add_user(tg, user_value, password_value, new_user_id_value, new_user_value)
1638+ time.sleep(5)
1639+
1640+ if status_result == 0 and reset_result == 1 and add_user_result == 1:
1641+ print("User can read power status.")
1642+ print("User can't reset power.")
1643+ print("User can't add a new user.")
1644+ else:
1645+ print("Authentication: Not User Level")
1646+ flag = 1
1647+
1648+ if flag == 1:
1649+ return 100
1650+ return 0
1651+
1652+def ping_test(host_ip):
1653+ count = 0
1654+ while count < 10:
1655+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(host_ip)
1656+ ping_rtn = subprocess.call(ping_cmd, shell=True)
1657+ if ping_rtn == 0:
1658+ return 0
1659+ else:
1660+ print("Destination Host Unreachable")
1661+ time.sleep(10)
1662+ count = count+1
1663+
1664+ if count == 10:
1665+ print("Host Has No Response, End of Test")
1666+ return 1
1667+
1668+
1669+def main():
1670+
1671+ intro_message = "Default config location is /etc/checkbox.d/me.cfg"
1672+ parser = ArgumentParser(description=intro_message, formatter_class=RawTextHelpFormatter)
1673+ parser.add_argument('--config', type=str,
1674+ default="/etc/checkbox.d/me.cfg",
1675+ help="Supply config file for getting authentication info")
1676+ args = parser.parse_args()
1677+ return dcmi_user_level_test(args)
1678+
1679+if __name__ == "__main__":
1680+ sys.exit(main())
1681
1682=== added file 'bin/dcmi_sampling'
1683--- bin/dcmi_sampling 1970-01-01 00:00:00 +0000
1684+++ bin/dcmi_sampling 2015-08-14 22:03:31 +0000
1685@@ -0,0 +1,271 @@
1686+#!/usr/bin/env python3
1687+"""
1688+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
1689+Industrial Technology Research Institute
1690+
1691+File Name
1692+ dcmi_sampling
1693+ 1. Retrieve CPU and intake temperature 30 times at 3 second intervals using dcmitool
1694+ 2. If failed to retrieve temperature at any time within 30 times, the test is considered failed
1695+
1696+Authors
1697+ Sophia Wu <Sophia.Wu@itri.org.tw>
1698+
1699+This program is free software: you can redistribute it and/or modify
1700+it under the terms of the GNU General Public License version 3,
1701+as published by the Free Software Foundation.
1702+
1703+This program is distributed in the hope that it will be useful,
1704+but WITHOUT ANY WARRANTY; without even the implied warranty of
1705+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1706+GNU General Public License for more details.
1707+
1708+You should have received a copy of the GNU General Public License
1709+along with this program. If not, see <http://www.gnu.org/licenses/>.
1710+
1711+"""
1712+import sys
1713+import time
1714+import re
1715+import configparser
1716+import shlex
1717+import subprocess
1718+from argparse import (
1719+ ArgumentParser,
1720+ RawTextHelpFormatter
1721+)
1722+from subprocess import (
1723+ check_output,
1724+ CalledProcessError
1725+)
1726+
1727+def get_sdr_remote(host_ip, user, password):
1728+ cmd = "dcmitool -H {} -U {} -P {} sdr".format(host_ip, user, password)
1729+ sdr_return = subprocess.check_output(shlex.split(cmd), stderr=subprocess.STDOUT,
1730+ universal_newlines=True)
1731+ return sdr_return
1732+
1733+def parse_sdr(output):
1734+ output = output.strip()
1735+ output_1Line = output.split("\n")
1736+ data = {}
1737+
1738+ for line in output_1Line:
1739+ sub_value = {}
1740+ string_list = line.split("|")
1741+ name = string_list[0].strip()
1742+ sensor_output = string_list[1].strip()
1743+ sub_value.update({'output':sensor_output})
1744+ status = string_list[2].strip()
1745+ sub_value.update({'status':status})
1746+ data.update({name:sub_value})
1747+ return data
1748+
1749+def calculate_CPU_temp(data_dict, CPU_Therm_Margin_id, CPU_Tjmax_id):
1750+ if data_dict.get(CPU_Therm_Margin_id) and data_dict.get(CPU_Tjmax_id):
1751+ if data_dict.get(CPU_Therm_Margin_id).get('status') == 'ok' and data_dict.get(CPU_Tjmax_id).get('status') == 'ok':
1752+ P_Therm_Margin_output = data_dict.get(CPU_Therm_Margin_id).get('output')
1753+ CPU_Tjmax_output = data_dict.get(CPU_Tjmax_id).get('output')
1754+ P_Therm_Margin = re.search(r'[0-9-]+', P_Therm_Margin_output).group(0)
1755+ CPU_Tjmax = re.search(r'[0-9-]+', CPU_Tjmax_output).group(0)
1756+ CPU_temp = int(P_Therm_Margin)+int(CPU_Tjmax)
1757+ return str(CPU_temp)+' degrees C'
1758+ else:
1759+ return 'Error'
1760+ else:
1761+ return 'None'
1762+
1763+def dcmi_sdr(args):
1764+
1765+ cmd_flag = 0
1766+ #DCMI config file
1767+ DEFAULT_CFG = "/etc/checkbox.d/me.cfg"
1768+ if not "config" in vars(args):
1769+ config_file = DEFAULT_CFG
1770+ else:
1771+ config_file = args.config
1772+
1773+ config = configparser.RawConfigParser()
1774+
1775+ try:
1776+ config.readfp(open(config_file))
1777+ except IOError:
1778+ print("No config file found")
1779+ return 10
1780+
1781+ try:
1782+ sensor_nick = config.options("SensorsForSampling")
1783+ except configparser.NoSectionError:
1784+ print("No Section: SensorsForSampling")
1785+ return 20
1786+
1787+ if sensor_nick:
1788+ sensor_list = []
1789+ for id in sensor_nick:
1790+ sensor_key = config.get("SensorsForSampling", id)
1791+ if sensor_key:
1792+ sensor_list.append(sensor_key)
1793+ else:
1794+ print("No Sensor ID specified in Config file")
1795+ return 30
1796+ else:
1797+ print("No key of Sensor ID specified in config file")
1798+ return 40
1799+
1800+ try:
1801+ targets_options = config.options('Targets')
1802+ targets_list = []
1803+ for target_key in targets_options:
1804+ targets_list.append(config.get('Targets', target_key))
1805+ if not targets_list:
1806+ print("Invalid or Empty targets")
1807+ return 60
1808+ except configparser.Error:
1809+ print("Invalid or Empty targets")
1810+ return 60
1811+
1812+ try:
1813+ user_value = config.get("Account", "USER")
1814+ password_value = config.get("Account", "PASSWORD")
1815+ except configparser.NoOptionError:
1816+ print("Invalid or Empty credential info")
1817+ return 70
1818+
1819+ for tg in targets_list:
1820+
1821+ if not tg or not user_value or not password_value:
1822+ print("Require Taget IP, Account(USER/PASSWORD) for DCMI out-of-band access")
1823+ return 80
1824+ else:
1825+
1826+ c = 0
1827+ while c < 10:
1828+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(tg)
1829+ ping_rtn = subprocess.call(ping_cmd, shell=True)
1830+ if ping_rtn == 0:
1831+ print("Destination Host Reachable")
1832+ break
1833+ else:
1834+ time.sleep(10)
1835+ c = c+1
1836+ print("Destination Host Unreachable")
1837+
1838+ if c == 10:
1839+ print("Host Has No Response, End of Test")
1840+ return 99
1841+
1842+
1843+ sampling_data = []
1844+ times = 30
1845+ for n in range(times):
1846+
1847+ try:
1848+ sensor_data = get_sdr_remote(tg, user_value, password_value)
1849+ time.sleep(3)
1850+ except CalledProcessError as dcmi_exception:
1851+ print("Failed executing dcmi, Reason: %s" % dcmi_exception)
1852+ sensor_data = ''
1853+
1854+ sampling_data.append(sensor_data)
1855+
1856+ count = 0
1857+ prs_flag = 0
1858+ dis_flag = 0
1859+ for output in sampling_data:
1860+ try:
1861+ data = parse_sdr(output)
1862+ except:
1863+ print("Parsing output of sdr table error")
1864+ print("=======================================================")
1865+ prs_flag = 1
1866+ count = count+1
1867+ continue
1868+
1869+ disable = 0
1870+ need_data = {}
1871+
1872+ for need_id in sensor_list:
1873+
1874+ if data.get(need_id):
1875+ need_value = data.get(need_id).get('output')
1876+ need_data.update({need_id:need_value})
1877+ if data.get(need_id).get('status') != 'ok':
1878+ disable = 1
1879+ else:
1880+
1881+ try:
1882+ CPUx_Temp = config.get("Sensors", "CPUx")
1883+ except configparser.NoOptionError:
1884+ CPUx_Temp = ''
1885+
1886+ try:
1887+ CPUy_Temp = config.get("Sensors", "CPUy")
1888+ except configparser.NoOptionError:
1889+ CPUy_Temp = ''
1890+
1891+ if need_id == CPUx_Temp:
1892+
1893+ try:
1894+ PxTM = config.get("SensorsForCPUTemp", "Px Therm Margin")
1895+ except configparser.NoOptionError:
1896+ PxTM = ''
1897+
1898+ try:
1899+ CPUx_Tjmax = config.get("SensorsForCPUTemp", "CPUx Tjmax")
1900+ except configparser.NoOptionError:
1901+ CPUx_Tjmax = ''
1902+
1903+ if PxTM and CPUx_Tjmax:
1904+ Px_temp = calculate_CPU_temp(data, PxTM, CPUx_Tjmax)
1905+ need_data.update({CPUx_Temp:Px_temp})
1906+ if Px_temp == 'None' or Px_temp == 'Error':
1907+ disable = 1
1908+ else:
1909+ disable = 1
1910+
1911+ elif need_id == CPUy_Temp:
1912+
1913+ try:
1914+ PyTM = config.get("SensorsForCPUTemp", "Py Therm Margin")
1915+ except configparser.NoOptionError:
1916+ PyTM = ''
1917+
1918+ try:
1919+ CPUy_Tjmax = config.get("SensorsForCPUTemp", "CPUy Tjmax")
1920+ except configparser.NoOptionError:
1921+ CPUy_Tjmax = ''
1922+
1923+ if PyTM and CPUy_Tjmax:
1924+ Py_temp = calculate_CPU_temp(data, PyTM, CPUy_Tjmax)
1925+ need_data.update({CPUy_Temp:Py_temp})
1926+ if Py_temp == 'None' or Py_temp == 'Error':
1927+ disable = 1
1928+ else:
1929+ disable = 1
1930+
1931+ else:
1932+ need_data.update({need_id:'None'})
1933+ disable = 1
1934+
1935+ if disable == 1:
1936+ dis_flag = 1
1937+ print(need_data)
1938+ print("=======================================================")
1939+ count = count+1
1940+ print("Pass: %d" %(times-count))
1941+ print("Fail: %d" %(count))
1942+
1943+ if cmd_flag == 1 or prs_flag == 1 or dis_flag == 1:
1944+ return 100
1945+ return 0
1946+
1947+def main():
1948+
1949+ intro_message = "Default config location is /etc/checkbox.d/me.cfg"
1950+ parser = ArgumentParser(description=intro_message, formatter_class=RawTextHelpFormatter)
1951+ parser.add_argument('--config', type=str, default="/etc/checkbox.d/me.cfg", help="Supply config file for sensor IDs parameters")
1952+ args = parser.parse_args()
1953+ return dcmi_sdr(args)
1954+
1955+if __name__ == "__main__":
1956+ sys.exit(main())
1957
1958=== added file 'bin/dcmi_thermal_ib'
1959--- bin/dcmi_thermal_ib 1970-01-01 00:00:00 +0000
1960+++ bin/dcmi_thermal_ib 2015-08-14 22:03:31 +0000
1961@@ -0,0 +1,212 @@
1962+#!/usr/bin/env python3
1963+"""
1964+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
1965+Industrial Technology Research Institute
1966+
1967+File Name
1968+ dcmi_thermal_ib
1969+ 1. Retrieve CPU, DIMM, chipset, inlet and outlet temperatures via DCMI in-band access using dcmitool.
1970+ 2. The motherboard has five thermal sensors:
1971+ Two for CPU0 and CPU1 temperatures,
1972+ Two for CPU0 DIMM group and CPU1 DIMM group temperatures,
1973+ One for PCH temperature,
1974+ One for Inlet temperature,
1975+ One for outlet temperature.
1976+ 3. Criteria: Must retrieve temperatures from all abovementioned thermal sensors via DCMI in-band access.
1977+
1978+Authors
1979+ Sophia Wu <Sophia.Wu@itri.org.tw>
1980+
1981+This program is free software: you can redistribute it and/or modify
1982+it under the terms of the GNU General Public License version 3,
1983+as published by the Free Software Foundation.
1984+
1985+This program is distributed in the hope that it will be useful,
1986+but WITHOUT ANY WARRANTY; without even the implied warranty of
1987+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1988+GNU General Public License for more details.
1989+
1990+You should have received a copy of the GNU General Public License
1991+along with this program. If not, see <http://www.gnu.org/licenses/>.
1992+
1993+"""
1994+import sys
1995+import time
1996+import re
1997+import configparser
1998+import shlex
1999+import subprocess
2000+import ast
2001+from argparse import (
2002+ ArgumentParser,
2003+ RawTextHelpFormatter
2004+)
2005+from subprocess import (
2006+ check_output,
2007+ CalledProcessError
2008+)
2009+
2010+
2011+def get_sdr():
2012+ cmd = "dcmitool sdr"
2013+ sdr_return = subprocess.check_output(shlex.split(cmd), universal_newlines=True)
2014+ return sdr_return
2015+
2016+def parse_sdr(output):
2017+ output = output.strip()
2018+ output_1Line = output.split("\n")
2019+ data = {}
2020+
2021+ for line in output_1Line:
2022+ sub_value = {}
2023+ string_list = line.split("|")
2024+ name = string_list[0].strip()
2025+ sensor_output = string_list[1].strip()
2026+ sub_value.update({'output':sensor_output})
2027+ status = string_list[2].strip()
2028+ sub_value.update({'status':status})
2029+ data.update({name:sub_value})
2030+ return data
2031+
2032+def calculate_CPU_temp(data_dict, CPU_Therm_Margin_id, CPU_Tjmax_id):
2033+
2034+ if data_dict.get(CPU_Therm_Margin_id) and data_dict.get(CPU_Tjmax_id):
2035+ if data_dict.get(CPU_Therm_Margin_id).get('status') == 'ok' and data_dict.get(CPU_Tjmax_id).get('status') == 'ok':
2036+ P_Therm_Margin_output = data_dict.get(CPU_Therm_Margin_id).get('output')
2037+ CPU_Tjmax_output = data_dict.get(CPU_Tjmax_id).get('output')
2038+ P_Therm_Margin = re.search(r'[0-9-]+', P_Therm_Margin_output).group(0)
2039+ CPU_Tjmax = re.search(r'[0-9-]+', CPU_Tjmax_output).group(0)
2040+ CPU_temp = int(P_Therm_Margin)+int(CPU_Tjmax)
2041+ return str(CPU_temp)+' degrees C'
2042+ else:
2043+ return 'Error'
2044+ else:
2045+ return 'None'
2046+
2047+def dcmi_sdr(args):
2048+
2049+ flag = 0
2050+ #DCMI config file
2051+ DEFAULT_CFG = "/etc/checkbox.d/me.cfg"
2052+ if not "config" in vars(args):
2053+ config_file = DEFAULT_CFG
2054+ else:
2055+ config_file = args.config
2056+ config = configparser.RawConfigParser()
2057+
2058+ try:
2059+ config.readfp(open(config_file))
2060+ except IOError:
2061+ print("No config file found")
2062+ return 10
2063+
2064+ try:
2065+ sensor_nick = config.options("Sensors")
2066+ except configparser.NoSectionError:
2067+ print("No Section: Sensors")
2068+ return 20
2069+
2070+ if sensor_nick:
2071+ sensor_list = []
2072+ for id in sensor_nick:
2073+ sensor_key = config.get("Sensors", id)
2074+ if sensor_key:
2075+ sensor_list.append(sensor_key)
2076+ else:
2077+ print("No Sensor ID specified in Config file")
2078+ return 30
2079+ else:
2080+ print("No key of Sensor ID specified in config file")
2081+ return 40
2082+
2083+ try:
2084+ sensor_data = get_sdr()
2085+ time.sleep(5)
2086+ except CalledProcessError as dcmi_exception:
2087+ print("Failed executing dcmi, Reason: %s" % dcmi_exception)
2088+ return 50
2089+
2090+ try:
2091+ data = parse_sdr(sensor_data)
2092+ except:
2093+ print("Parsing output of sdr table error")
2094+ return 60
2095+
2096+ need_data = {}
2097+ for need_id in sensor_list:
2098+ if data.get(need_id):
2099+ need_value = data.get(need_id).get('output')
2100+ need_data.update({need_id:need_value})
2101+
2102+ if data.get(need_id).get('status') != 'ok':
2103+ flag = 1
2104+ else:
2105+
2106+ try:
2107+ CPUx_Temp = config.get("Sensors", "CPUx")
2108+ except configparser.NoOptionError:
2109+ CPUx_Temp = ''
2110+
2111+ try:
2112+ CPUy_Temp = config.get("Sensors", "CPUy")
2113+ except configparser.NoOptionError:
2114+ CPUy_Temp = ''
2115+
2116+ if need_id == CPUx_Temp:
2117+
2118+ try:
2119+ PxTM = config.get("SensorsForCPUTemp", "Px Therm Margin")
2120+ except configparser.NoOptionError:
2121+ PxTM = ''
2122+
2123+ try:
2124+ CPUx_Tjmax = config.get("SensorsForCPUTemp", "CPUx Tjmax")
2125+ except configparser.NoOptionError:
2126+ CPUx_Tjmax = ''
2127+
2128+ if PxTM and CPUx_Tjmax:
2129+ need_data.update({CPUx_Temp:calculate_CPU_temp(data, PxTM, CPUx_Tjmax)})
2130+ if calculate_CPU_temp(data, PxTM, CPUx_Tjmax) == 'None' or calculate_CPU_temp(data, PxTM, CPUx_Tjmax) == 'Error':
2131+ flag = 1
2132+ else:
2133+ flag = 1
2134+
2135+ elif need_id == CPUy_Temp:
2136+
2137+ try:
2138+ PyTM = config.get("SensorsForCPUTemp", "Py Therm Margin")
2139+ except configparser.NoOptionError:
2140+ PyTM = ''
2141+
2142+ try:
2143+ CPUy_Tjmax = config.get("SensorsForCPUTemp", "CPUy Tjmax")
2144+ except configparser.NoOptionError:
2145+ CPUy_Tjmax = ''
2146+
2147+
2148+ if PyTM and CPUy_Tjmax:
2149+ need_data.update({CPUy_Temp:calculate_CPU_temp(data, PyTM, CPUy_Tjmax)})
2150+ if calculate_CPU_temp(data, PyTM, CPUy_Tjmax) == 'None' or calculate_CPU_temp(data, PyTM, CPUy_Tjmax) == 'Error':
2151+ flag = 1
2152+ else:
2153+ flag = 1
2154+ else:
2155+ flag = 1
2156+
2157+ print("%s: %s" %(need_id, need_data.get(need_id)))
2158+
2159+ if flag == 1:
2160+ return 100
2161+ return 0
2162+
2163+def main():
2164+
2165+ intro_message = "Default config location is /etc/checkbox.d/me.cfg"
2166+ parser = ArgumentParser(description=intro_message, formatter_class=RawTextHelpFormatter)
2167+ parser.add_argument('--config', type=str, default="/etc/checkbox.d/me.cfg", help="Supply config file for sensor IDs parameters")
2168+ args = parser.parse_args()
2169+ return dcmi_sdr(args)
2170+
2171+if __name__ == "__main__":
2172+ sys.exit(main())
2173+
2174
2175=== added file 'bin/dcmi_thermal_oob'
2176--- bin/dcmi_thermal_oob 1970-01-01 00:00:00 +0000
2177+++ bin/dcmi_thermal_oob 2015-08-14 22:03:31 +0000
2178@@ -0,0 +1,243 @@
2179+#!/usr/bin/env python3
2180+"""
2181+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
2182+Industrial Technology Research Institute
2183+
2184+File Name
2185+ dcmi_thermal_oob
2186+ 1. Retrieving CPU, DIMM, chipset, inlet, outlet temperature via DCMI out-of-band access using dcmitool.
2187+ 2. The motherboard has five thermal sensors: Two for CPU0 and CPU1 temperatures,
2188+ Two for CPU0 DIMM group and CPU1 DIMM group temperatures,
2189+ One for PCH temperature,
2190+ One for Inlet temperature,
2191+ One for outlet temperature.
2192+ 3. Criteria: Must retrieve temperatures from all abovementioned thermal sensors via DCMI out-of-band access.
2193+
2194+Authors
2195+ Sophia Wu <Sophia.Wu@itri.org.tw>
2196+
2197+This program is free software: you can redistribute it and/or modify
2198+it under the terms of the GNU General Public License version 3,
2199+as published by the Free Software Foundation.
2200+
2201+This program is distributed in the hope that it will be useful,
2202+but WITHOUT ANY WARRANTY; without even the implied warranty of
2203+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2204+GNU General Public License for more details.
2205+
2206+You should have received a copy of the GNU General Public License
2207+along with this program. If not, see <http://www.gnu.org/licenses/>.
2208+
2209+"""
2210+import sys
2211+import time
2212+import re
2213+import configparser
2214+import shlex
2215+import subprocess
2216+import ast
2217+from argparse import (
2218+ ArgumentParser,
2219+ RawTextHelpFormatter
2220+)
2221+from subprocess import (
2222+ check_output,
2223+ CalledProcessError
2224+)
2225+
2226+def get_sdr_remote(host_ip, user, password):
2227+ cmd = "dcmitool -H {} -U {} -P {} sdr".format(host_ip, user, password)
2228+ sdr_return = subprocess.check_output(shlex.split(cmd), stderr=subprocess.STDOUT,
2229+ universal_newlines=True)
2230+ return sdr_return
2231+
2232+def parse_sdr(output):
2233+ output = output.strip()
2234+ output_1Line = output.split("\n")
2235+ data = {}
2236+
2237+ for line in output_1Line:
2238+ sub_value = {}
2239+ string_list = line.split("|")
2240+ name = string_list[0].strip()
2241+ sensor_output = string_list[1].strip()
2242+ sub_value.update({'output':sensor_output})
2243+ status = string_list[2].strip()
2244+ sub_value.update({'status':status})
2245+ data.update({name:sub_value})
2246+ return data
2247+
2248+def calculate_CPU_temp(data_dict, CPU_Therm_Margin_id, CPU_Tjmax_id):
2249+
2250+ if data_dict.get(CPU_Therm_Margin_id) and data_dict.get(CPU_Tjmax_id):
2251+ if data_dict.get(CPU_Therm_Margin_id).get('status') == 'ok' and data_dict.get(CPU_Tjmax_id).get('status') == 'ok':
2252+ P_Therm_Margin_output = data_dict.get(CPU_Therm_Margin_id).get('output')
2253+ CPU_Tjmax_output = data_dict.get(CPU_Tjmax_id).get('output')
2254+ P_Therm_Margin = re.search(r'[0-9-]+', P_Therm_Margin_output).group(0)
2255+ CPU_Tjmax = re.search(r'[0-9-]+', CPU_Tjmax_output).group(0)
2256+ CPU_temp = int(P_Therm_Margin)+int(CPU_Tjmax)
2257+ return str(CPU_temp)+' degrees C'
2258+ else:
2259+ return 'Error'
2260+ else:
2261+ return 'None'
2262+
2263+def dcmi_sdr(args):
2264+
2265+ flag = 0
2266+ #DCMI config file
2267+ DEFAULT_CFG = "/etc/checkbox.d/me.cfg"
2268+ if not "config" in vars(args):
2269+ config_file = DEFAULT_CFG
2270+ else:
2271+ config_file = args.config
2272+
2273+ config = configparser.RawConfigParser()
2274+
2275+ try:
2276+ config.readfp(open(config_file))
2277+ except IOError:
2278+ print("No config file found")
2279+ return 10
2280+
2281+ try:
2282+ sensor_nick = config.options("Sensors")
2283+ except configparser.NoSectionError:
2284+ print("No Section: Sensors")
2285+ return 20
2286+
2287+ if sensor_nick:
2288+ sensor_list = []
2289+ for id in sensor_nick:
2290+ sensor_key = config.get("Sensors", id)
2291+ if sensor_key:
2292+ sensor_list.append(sensor_key)
2293+ else:
2294+ print("No Sensor ID specified in Config file")
2295+ return 30
2296+ else:
2297+ print("No key of Sensor ID specified in config file")
2298+ return 40
2299+
2300+ try:
2301+ targets_options = config.options('Targets')
2302+ targets_list = []
2303+ for target_key in targets_options:
2304+ targets_list.append(config.get('Targets', target_key))
2305+ if not targets_list:
2306+ print("Invalid or Empty targets")
2307+ return 60
2308+ except configparser.Error:
2309+ print("Invalid or Empty targets")
2310+ return 60
2311+
2312+ try:
2313+ user_value = config.get("Account", "USER")
2314+ password_value = config.get("Account", "PASSWORD")
2315+ except configparser.NoOptionError:
2316+ print("Invalid or Empty credential info")
2317+ return 70
2318+
2319+ for tg in targets_list:
2320+
2321+ if not tg or not user_value or not password_value:
2322+ print("Require Taget IP, Account(USER/PASSWORD) for DCMI out-of-band access")
2323+ return 80
2324+ else:
2325+
2326+ print("SUT =", tg)
2327+ print("USER =", user_value)
2328+ print("PASSWORD =", password_value)
2329+
2330+ try:
2331+ sensor_data = get_sdr_remote(tg, user_value, password_value)
2332+ time.sleep(5)
2333+ except CalledProcessError as dcmi_exception:
2334+ print("Failed executing dcmi, Reason: %s" % dcmi_exception)
2335+ return 50
2336+
2337+ try:
2338+ data = parse_sdr(sensor_data)
2339+ except:
2340+ print("Parsing output of sdr table error")
2341+ flag = 1
2342+ continue
2343+
2344+ need_data = {}
2345+ for need_id in sensor_list:
2346+
2347+ if data.get(need_id):
2348+ need_value = data.get(need_id).get('output')
2349+ need_data.update({need_id:need_value})
2350+
2351+ if data.get(need_id).get('status') != 'ok':
2352+ flag = 1
2353+ else:
2354+
2355+ try:
2356+ CPUx_Temp = config.get("Sensors", "CPUx")
2357+ except configparser.NoOptionError:
2358+ CPUx_Temp = ''
2359+
2360+ try:
2361+ CPUy_Temp = config.get("Sensors", "CPUy")
2362+ except configparser.NoOptionError:
2363+ CPUy_Temp = ''
2364+
2365+ if need_id == CPUx_Temp:
2366+
2367+ try:
2368+ PxTM = config.get("SensorsForCPUTemp", "Px Therm Margin")
2369+ except configparser.NoOptionError:
2370+ PxTM = ''
2371+
2372+ try:
2373+ CPUx_Tjmax = config.get("SensorsForCPUTemp", "CPUx Tjmax")
2374+ except configparser.NoOptionError:
2375+ CPUx_Tjmax = ''
2376+
2377+ if PxTM and CPUx_Tjmax:
2378+ need_data.update({CPUx_Temp:calculate_CPU_temp(data, PxTM, CPUx_Tjmax)})
2379+ if calculate_CPU_temp(data, PxTM, CPUx_Tjmax) == 'None' or calculate_CPU_temp(data, PxTM, CPUx_Tjmax) == 'Error':
2380+ flag = 1
2381+ else:
2382+ flag = 1
2383+
2384+ elif need_id == CPUy_Temp:
2385+
2386+ try:
2387+ PyTM = config.get("SensorsForCPUTemp", "Py Therm Margin")
2388+ except configparser.NoOptionError:
2389+ PyTM = ''
2390+
2391+ try:
2392+ CPUy_Tjmax = config.get("SensorsForCPUTemp", "CPUy Tjmax")
2393+ except configparser.NoOptionError:
2394+ CPUy_Tjmax = ''
2395+
2396+ if PyTM and CPUy_Tjmax:
2397+ need_data.update({CPUy_Temp:calculate_CPU_temp(data, PyTM, CPUy_Tjmax)})
2398+ if calculate_CPU_temp(data, PyTM, CPUy_Tjmax) == 'None' or calculate_CPU_temp(data, PyTM, CPUy_Tjmax) == 'Error':
2399+ flag = 1
2400+ else:
2401+ flag = 1
2402+ else:
2403+ #need_data.update({need_id:'None'})
2404+ flag = 1
2405+
2406+ print("%s: %s" %(need_id, need_data.get(need_id)))
2407+
2408+ if flag == 1:
2409+ return 100
2410+ return 0
2411+
2412+def main():
2413+
2414+ intro_message = "Default config location is /etc/checkbox.d/me.cfg"
2415+ parser = ArgumentParser(description=intro_message, formatter_class=RawTextHelpFormatter)
2416+ parser.add_argument('--config', type=str, default="/etc/checkbox.d/me.cfg", help="Supply config file for sensor IDs parameters")
2417+ args = parser.parse_args()
2418+ return dcmi_sdr(args)
2419+
2420+if __name__ == "__main__":
2421+ sys.exit(main())
2422
2423=== added file 'bin/disk_health'
2424--- bin/disk_health 1970-01-01 00:00:00 +0000
2425+++ bin/disk_health 2015-08-14 22:03:31 +0000
2426@@ -0,0 +1,138 @@
2427+#!/usr/bin/env python3
2428+
2429+"""
2430+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
2431+Industrial Technology Research Institute
2432+
2433+It is NOT YET officially approved by OCP.
2434+
2435+disk_health
2436+ 1. Use smartmontools to monitor disk health.
2437+ 2. SMART threshold, grown defect list (glist or reallocated sectors)
2438+ <= 100 for 4TB, glist <=50 for 2TB for all vendors.
2439+ 3. SMART HDD temp <= 60 degrees centigrade.
2440+ 4. Criteria: all threshold must not exceed the criteria listed in item 2
2441+ and 3.
2442+
2443+Authors
2444+ Nelson Chu <Nelson.Chu@itri.org.tw>
2445+
2446+This program is free software: you can redistribute it and/or modify
2447+it under the terms of the GNU General Public License version 3,
2448+as published by the Free Software Foundation.
2449+
2450+This program is distributed in the hope that it will be useful,
2451+but WITHOUT ANY WARRANTY; without even the implied warranty of
2452+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2453+GNU General Public License for more details.
2454+
2455+You should have received a copy of the GNU General Public License
2456+along with this program. If not, see <http://www.gnu.org/licenses/>.
2457+
2458+"""
2459+
2460+import os
2461+import re
2462+import sys
2463+from subprocess import check_output
2464+from argparse import ArgumentParser, RawTextHelpFormatter
2465+
2466+def run(device):
2467+ return_code = 0
2468+ command = "smartctl -a {0}".format(device)
2469+
2470+ try:
2471+ with open(os.devnull, "w") as NULL:
2472+ smartctl_info = check_output(command, stderr=NULL, shell=True)
2473+ except Exception as e:
2474+ print(e.output.decode('utf-8'))
2475+ return_code = 10
2476+ return return_code
2477+
2478+ smartctl_info = smartctl_info.decode('utf-8')
2479+
2480+ # Verify disk capacity match the criteria or not.
2481+ capacity_match =re.search(r'User Capacity.*\[(2|4).*TB\]', smartctl_info)
2482+ if not capacity_match:
2483+ print("Disk capacity is not match 2TB or 4TB.")
2484+ return_code = 20
2485+ return return_code
2486+
2487+ disk_capacity = int(capacity_match.group(1))
2488+ print("Disk capacity: %dTB" %(disk_capacity))
2489+
2490+ # Verify disk temperature match the criteria or not.
2491+ temperature_match = re.search(r'Temperature_Celsius.*\s(\d+)(\s\(|\n)',
2492+ smartctl_info)
2493+ if not temperature_match:
2494+ temperature_match = re.search(r'Current Drive Temperature\D*(\d+)',
2495+ smartctl_info)
2496+ if not temperature_match:
2497+ print("Cannot retrieve disk temperature.")
2498+ return_code = 30
2499+ return return_code
2500+
2501+ disk_temperature = int(temperature_match.group(1))
2502+ print("Disk current temperature: %d degrees centigrade"
2503+ %disk_temperature)
2504+ if disk_temperature > 60:
2505+ return_code = 40
2506+
2507+ # Verify reallocated sectors match the criteria or not.
2508+ reallocated_sector_match = re.search(r'Reallocated_Sector_Ct.*\s(\d+)\n',
2509+ smartctl_info)
2510+ if reallocated_sector_match:
2511+ reallocated_sector = int(reallocated_sector_match.group(1))
2512+ print("Reallocated_Sector_Ct: %d" %reallocated_sector)
2513+ if disk_capacity == 2 and reallocated_sector > 50:
2514+ return_code = 50
2515+ if disk_capacity == 4 and reallocated_sector > 100:
2516+ return_code = 60
2517+
2518+ # Verify grown defect list match the criteria or not.
2519+ grown_defect_match = re.search(r'Elements in grown defect list\:\s(\d+)\n',
2520+ smartctl_info)
2521+ if grown_defect_match:
2522+ grown_defect_list = int(grown_defect_match.group(1))
2523+ print("Elements in grown defect list: %d" %grown_defect_list)
2524+ if disk_capacity == 2 and grown_defect_list > 50:
2525+ return_code = 70
2526+ if disk_capacity == 4 and grown_defect_list > 100:
2527+ return_code = 80
2528+
2529+ # Check current pending sectort.
2530+ current_pending_match = re.search(r'Current_Pending_Sector.*\s(\d+)\n',
2531+ smartctl_info)
2532+ if current_pending_match:
2533+ current_pending_sector = int(current_pending_match.group(1))
2534+ print("Current_Pending_Sector: %d" %current_pending_sector)
2535+ if current_pending_sector != 0:
2536+ return_code = 90
2537+
2538+ # Check error counter log.
2539+ total_uncorrected_errors = re.search(
2540+ r'\nread.*\s(\d+)\nwrite.*\s(\d+)\nverify.*\s(\d+)', smartctl_info)
2541+ if total_uncorrected_errors:
2542+ read = int(total_uncorrected_errors.group(1))
2543+ write = int(total_uncorrected_errors.group(2))
2544+ verify = int(total_uncorrected_errors.group(3))
2545+ print("Total uncorrected errors: read=%d write=%d verify=%d"
2546+ %(read, write, verify))
2547+ if read != 0 or write != 0 or verify != 0:
2548+ return_code = 100
2549+ return return_code
2550+
2551+def main():
2552+ parser = ArgumentParser(formatter_class=RawTextHelpFormatter)
2553+ parser.add_argument('-d', '--device', type=str, required=True,
2554+ help=("The device that wants to monitor health."))
2555+ args = parser.parse_args()
2556+
2557+ device = args.device
2558+ if not device.startswith('/dev/'):
2559+ device = '/dev/' + device
2560+
2561+ return run(device)
2562+
2563+if __name__ == '__main__':
2564+ sys.exit(main())
2565
2566=== modified file 'bin/disk_info'
2567--- bin/disk_info 2015-03-03 15:59:42 +0000
2568+++ bin/disk_info 2015-08-14 22:03:31 +0000
2569@@ -3,6 +3,8 @@
2570 Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
2571 Industrial Technology Research Institute
2572
2573+It is NOT YET officially approved by OCP.
2574+
2575 disk_info
2576 1. Use lshw command to gather disk information.
2577 2. The program will output disk type, vendor, product, capacity.
2578
2579=== added file 'bin/disk_info_leopard'
2580--- bin/disk_info_leopard 1970-01-01 00:00:00 +0000
2581+++ bin/disk_info_leopard 2015-08-14 22:03:31 +0000
2582@@ -0,0 +1,67 @@
2583+#!/usr/bin/env python3
2584+"""
2585+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
2586+Industrial Technology Research Institute
2587+
2588+It is NOT YET officially approved by OCP.
2589+
2590+disk_info
2591+ 1. Use lshw command to gather disk information.
2592+ 2. The program will output disk type, vendor, product, capacity.
2593+ 3. Criteria: must be able to retrieve disk information.
2594+
2595+Authors
2596+ Nelson Chu <Nelson.Chu@itri.org.tw>
2597+
2598+This program is free software: you can redistribute it and/or modify
2599+it under the terms of the GNU General Public License version 3,
2600+as published by the Free Software Foundation.
2601+
2602+This program is distributed in the hope that it will be useful,
2603+but WITHOUT ANY WARRANTY; without even the implied warranty of
2604+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2605+GNU General Public License for more details.
2606+
2607+You should have received a copy of the GNU General Public License
2608+along with this program. If not, see <http://www.gnu.org/licenses/>.
2609+
2610+"""
2611+
2612+import sys
2613+import xml.etree.ElementTree as ET
2614+from subprocess import Popen, PIPE
2615+
2616+def main():
2617+ attribute = ['description', 'product', 'size']
2618+ command = 'lshw -xml'
2619+ hwinfo_xml = Popen(command, stdout=PIPE, stderr=PIPE,
2620+ shell=True).communicate()[0]
2621+ root = ET.fromstring(hwinfo_xml)
2622+
2623+ # Parse lshw XML for gathering disk information.
2624+ disk_list = root.findall(".//node[@class='disk']")
2625+
2626+ if not disk_list:
2627+ print("Cannot parse any disk information.", file=sys.stderr)
2628+ return 10
2629+
2630+ for disk in disk_list:
2631+ for attr in attribute:
2632+ if disk.find(attr) is None:
2633+ print(("Cannot found disk %s") %attr, file=sys.stderr)
2634+ return 20
2635+
2636+ disk_size = int(disk.find('size').text) / (1000**3)
2637+ for attr in attribute:
2638+ if attr == 'description':
2639+ print(("Type=\"%s\"") %disk.find(attr).text)
2640+ continue
2641+ elif attr == 'size':
2642+ print(("%s=\"%dGB\"") %(attr.capitalize(), disk_size))
2643+ continue
2644+ else:
2645+ print(("%s=\"%s\"") %(attr.capitalize(), disk.find(attr).text))
2646+ return 0
2647+
2648+if __name__ == '__main__':
2649+ sys.exit(main())
2650
2651=== added file 'bin/ipmi_fru'
2652--- bin/ipmi_fru 1970-01-01 00:00:00 +0000
2653+++ bin/ipmi_fru 2015-08-14 22:03:31 +0000
2654@@ -0,0 +1,163 @@
2655+#!/usr/bin/env python3
2656+"""
2657+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
2658+Industrial Technology Research Institute
2659+
2660+File Name
2661+ ipmi_fru
2662+
2663+Description
2664+ 1. Use ipmitool to retrieve FRU data.
2665+ 2. The data contains product manufacture, product part number, product serial number, motherboard serial number.
2666+ 3. Criteria: Above All data mentioned above must notshould not be null
2667+
2668+Authors
2669+ Sophia Wu <Sophia.Wu@itri.org.tw>
2670+
2671+This program is free software: you can redistribute it and/or modify
2672+it under the terms of the GNU General Public License version 3,
2673+as published by the Free Software Foundation.
2674+
2675+This program is distributed in the hope that it will be useful,
2676+but WITHOUT ANY WARRANTY; without even the implied warranty of
2677+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2678+GNU General Public License for more details.
2679+
2680+You should have received a copy of the GNU General Public License
2681+along with this program. If not, see <http://www.gnu.org/licenses/>.
2682+
2683+"""
2684+
2685+from argparse import (
2686+ ArgumentParser,
2687+ RawTextHelpFormatter
2688+)
2689+
2690+import sys
2691+import shlex
2692+import time
2693+import subprocess
2694+from subprocess import (
2695+ check_output,
2696+ CalledProcessError
2697+)
2698+import re
2699+import configparser
2700+
2701+def get_system_manufacturer(output):
2702+ system_manufacture = re.search(r'Product Manufacturer\s*:\s*([a-zA-Z0-9-._ ]+\n)', output)
2703+ if system_manufacture == None:
2704+ return 'Error'
2705+ else:
2706+ return system_manufacture.group(1).strip()
2707+
2708+def get_system_part_number(output):
2709+ system_part_number = re.search(r'Product Part Number\s*:\s*([a-zA-Z0-9-._ ]+\n)', output)
2710+ if system_part_number == None:
2711+ return 'Error'
2712+ else:
2713+ return system_part_number.group(1).strip()
2714+
2715+def get_system_serial_number(output):
2716+ system_serial_number = re.search(r'Product Serial\s*:\s*([a-zA-Z0-9-._ ]+\n)', output)
2717+ if system_serial_number == None:
2718+ return 'Error'
2719+ else:
2720+ return system_serial_number.group(1).strip()
2721+
2722+def get_board_serial_number(output):
2723+ board_serial_number = re.search(r'Board Serial\s*:\s*([a-zA-Z0-9-._ ]+\n)', output)
2724+ if board_serial_number == None:
2725+ return 'Error'
2726+ else:
2727+ return board_serial_number.group(1).strip()
2728+
2729+def get_fru_info(host_ip, user, password):
2730+ fru_cmd = 'ipmitool -H {} -U {} -P {} fru'.format(host_ip, user, password)
2731+ fru_return = check_output(shlex.split(fru_cmd), universal_newlines=True)
2732+ return fru_return
2733+
2734+def ipmi_fru(args):
2735+ #IPMI config file
2736+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
2737+
2738+ if not "config" in vars(args):
2739+ config_file = DEFAULT_CFG
2740+ else:
2741+ config_file = args.config
2742+
2743+ config = configparser.RawConfigParser()
2744+
2745+ try:
2746+ config.readfp(open(config_file))
2747+ except IOError:
2748+ print("No config file found")
2749+ return 10
2750+
2751+ try:
2752+ targets_options = config.options('Targets')
2753+ targets_list = []
2754+ for target_key in targets_options:
2755+ targets_list.append(config.get('Targets', target_key))
2756+
2757+ if not targets_list:
2758+ print("Invalid or Empty targets")
2759+ return 20
2760+
2761+ except configparser.Error:
2762+ print("Invalid or Empty targets")
2763+ return 30
2764+
2765+ try:
2766+ user_value = config.get('Account', 'USER')
2767+ passwd_value = config.get('Account', 'PASSWORD')
2768+ if not user_value or not passwd_value:
2769+ print("Invalid or Empty credential info")
2770+ return 40
2771+
2772+ except configparser.Error:
2773+ print("Invalid or Empty credential info")
2774+ return 50
2775+
2776+ inevntory_fru = {}
2777+ flag = 0
2778+ for tg in targets_list:
2779+
2780+ if not tg or not user_value or not passwd_value:
2781+ print("Require Taget IP, Account(USER/PASSWORD) for IPMI out-of-band access")
2782+ return 60
2783+ else:
2784+ print("SUT =", tg)
2785+ try:
2786+ fru_data = get_fru_info(tg, user_value, passwd_value)
2787+ time.sleep(5)
2788+ except CalledProcessError as ipmi_exception:
2789+ print("Failed executing ipmi, Reason: %s" % ipmi_exception)
2790+ return 70
2791+
2792+ inevntory_fru.update({'Product Manufacturer':get_system_manufacturer(fru_data)})
2793+ inevntory_fru.update({'Product Part Number':get_system_part_number(fru_data)})
2794+ inevntory_fru.update({'Product Serial':get_system_serial_number(fru_data)})
2795+ inevntory_fru.update({'Board Serial':get_board_serial_number(fru_data)})
2796+
2797+ inevntory_fru_list = ['Product Manufacturer', 'Product Part Number', 'Product Serial', 'Board Serial']
2798+ for item in inevntory_fru_list:
2799+ print("{}: {}".format(item, inevntory_fru.get(item)))
2800+ if inevntory_fru.get(item) == 'Error' or inevntory_fru.get(item) == '':
2801+ flag = 1
2802+ if flag == 1:
2803+ return 100
2804+ return 0
2805+
2806+def main():
2807+ intro_message = "Default config location is /etc/checkbox.d/bmc.cfg"
2808+ parser = ArgumentParser(description=intro_message,
2809+ formatter_class=RawTextHelpFormatter)
2810+ parser.add_argument('--config', type=str,
2811+ default="/etc/checkbox.d/bmc.cfg",
2812+ help="Supply config file for getting authentication info")
2813+ args = parser.parse_args()
2814+ return ipmi_fru(args)
2815+
2816+if __name__ == '__main__':
2817+ sys.exit(main())
2818
2819=== added file 'bin/ipmi_inventory'
2820--- bin/ipmi_inventory 1970-01-01 00:00:00 +0000
2821+++ bin/ipmi_inventory 2015-08-14 22:03:31 +0000
2822@@ -0,0 +1,214 @@
2823+#!/usr/bin/env python3
2824+"""
2825+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
2826+Industrial Technology Research Institute
2827+
2828+File Name
2829+ ipmi_inventory
2830+ 1. Use ipmitool to collect inventory information including Asset Tag, Device ID, System GUID, Firmware Revision, IPMI Version, Management Controller ID.
2831+ 2. Criteria: All information mentioned above must not should not be null.
2832+Authors
2833+ Sophia Wu <Sophia.Wu@itri.org.tw>
2834+
2835+This program is free software: you can redistribute it and/or modify
2836+it under the terms of the GNU General Public License version 3,
2837+as published by the Free Software Foundation.
2838+
2839+This program is distributed in the hope that it will be useful,
2840+but WITHOUT ANY WARRANTY; without even the implied warranty of
2841+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2842+GNU General Public License for more details.
2843+
2844+You should have received a copy of the GNU General Public License
2845+along with this program. If not, see <http://www.gnu.org/licenses/>.
2846+
2847+"""
2848+
2849+from argparse import (
2850+ ArgumentParser,
2851+ RawTextHelpFormatter
2852+)
2853+
2854+import sys
2855+import shlex
2856+import time
2857+import subprocess
2858+from subprocess import (
2859+ check_output,
2860+ CalledProcessError
2861+)
2862+import re
2863+import configparser
2864+
2865+
2866+def get_mcinfo(host_ip, user, password):
2867+
2868+ try:
2869+ cmd = 'ipmitool -H {} -U {} -P {} mc info'.format(host_ip, user, password)
2870+ mcinfo_return = check_output(shlex.split(cmd), universal_newlines=True)
2871+ time.sleep(5)
2872+ except CalledProcessError as command_exception:
2873+ print("Failed executing ipmi command for getting mc info. Reason:%s" % command_exception)
2874+
2875+ try:
2876+
2877+ deviceid = re.search(r'Device ID\s*:\s*([a-zA-Z0-9-._ ]+)', mcinfo_return)
2878+ if deviceid == None:
2879+ deviceid = 'Error'
2880+ else:
2881+ deviceid = deviceid.group(1).strip()
2882+
2883+ Firm = re.search(r'Firmware Revision\s+\s*:\s*([a-zA-Z0-9-._ ]+)', mcinfo_return)
2884+ if Firm == None:
2885+ Firm = 'Error'
2886+ else:
2887+ Firm = Firm.group(1).strip()
2888+
2889+ IPMI_Ver = re.search(r'IPMI Version\s+\s*:\s*([a-zA-Z0-9-._ ]+)', mcinfo_return)
2890+ if IPMI_Ver == None:
2891+ IPMI_Ver = 'Error'
2892+ else:
2893+ IPMI_Ver = IPMI_Ver.group(1).strip()
2894+
2895+ return deviceid, Firm, IPMI_Ver
2896+
2897+ except:
2898+
2899+ return 'Error', 'Error', 'Error'
2900+
2901+def get_asset_tag(host_ip, user, password):
2902+
2903+ try:
2904+ cmd = 'ipmitool -H {} -U {} -P {} fru'.format(host_ip, user, password)
2905+ asset_tag_return = check_output(shlex.split(cmd), universal_newlines=True)
2906+ time.sleep(5)
2907+ except CalledProcessError as command_exception:
2908+ print("Failed executing ipmi command for getting asset tag. Reason:%s" % command_exception)
2909+
2910+ try:
2911+ asset_tag = re.search(r'Product Asset Tag\s*:\s*([a-zA-Z0-9-._ ]+)', asset_tag_return)
2912+ if asset_tag == None:
2913+ return 'Error'
2914+ return asset_tag.group(1).strip()
2915+ except:
2916+ return 'Error'
2917+
2918+def get_guid(host_ip, user, password):
2919+
2920+ try:
2921+ cmd = 'ipmitool -H {} -U {} -P {} mc guid'.format(host_ip, user, password)
2922+ guid_return = check_output(shlex.split(cmd), universal_newlines=True)
2923+ time.sleep(5)
2924+ except CalledProcessError as command_exception:
2925+ print("Failed executing ipmi command for getting guid. Reason:%s" % command_exception)
2926+
2927+ try:
2928+ mcguid = re.search(r'System GUID\s*:\s*([a-zA-Z0-9-._ ]+)', guid_return)
2929+ if mcguid == None:
2930+ return 'Error'
2931+ return mcguid.group(1).strip()
2932+ except:
2933+ return 'Error'
2934+
2935+def get_mcid(host_ip, user, password):
2936+
2937+ try:
2938+ cmd = 'ipmitool -H {} -U {} -P {} dcmi get_mc_id_string'.format(host_ip, user, password)
2939+ mcid_return = check_output(shlex.split(cmd), universal_newlines=True)
2940+ time.sleep(5)
2941+ except CalledProcessError as command_exception:
2942+ print("Failed executing ipmi command for getting mc id. Reason:%s" % command_exception)
2943+
2944+ try:
2945+ mcid = re.search(r'Get Management Controller Identifier String\s*:\s*([a-zA-Z0-9-._ ]+)', mcid_return)
2946+ if mcid == None:
2947+ return 'Error'
2948+ return mcid.group(1).strip()
2949+ except:
2950+ return 'Error'
2951+
2952+def inventory(args):
2953+
2954+ #IPMI config file
2955+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
2956+
2957+ if not "config" in vars(args):
2958+ config_file = DEFAULT_CFG
2959+ else:
2960+ config_file = args.config
2961+
2962+ config = configparser.RawConfigParser()
2963+
2964+ try:
2965+ config.readfp(open(config_file))
2966+ except IOError:
2967+ print("No config file found")
2968+ return 10
2969+
2970+ try:
2971+ targets_options = config.options('Targets')
2972+ targets_list = []
2973+ for target_key in targets_options:
2974+ targets_list.append(config.get('Targets', target_key))
2975+
2976+ if not targets_list:
2977+ print("Invalid or Empty targets")
2978+ return 20
2979+ except configparser.Error:
2980+ print("Invalid or Empty targets")
2981+ return 30
2982+
2983+ try:
2984+ user_value = config.get('Account', 'USER')
2985+ passwd_value = config.get('Account', 'PASSWORD')
2986+ if not user_value or not passwd_value:
2987+ print("Invalid or Empty credential info")
2988+ return 40
2989+
2990+ except configparser.Error:
2991+ print("Invalid or Empty credential info")
2992+ return 50
2993+
2994+
2995+ flag = 0
2996+ for tg in targets_list:
2997+
2998+ if not tg or not user_value or not passwd_value:
2999+ print("Require Taget IP, Account(USER/PASSWORD) for IPMI out-of-band access")
3000+ return 60
3001+ else:
3002+ print("SUT =", tg)
3003+ inventory_dict = {}
3004+ inventory_list = ['Asset Tag', 'System GUID', 'Get Management Controller Identifier String', 'Device ID', 'Firmware Revision', 'IPMI Version']
3005+ Device_ID, Firmware, IPMI_version = get_mcinfo(tg, user_value, passwd_value)
3006+ inventory_dict.update({'Asset Tag':get_asset_tag(tg, user_value, passwd_value)})
3007+ inventory_dict.update({'System GUID':get_guid(tg, user_value, passwd_value)})
3008+ inventory_dict.update({'Get Management Controller Identifier String':get_mcid(tg, user_value, passwd_value)})
3009+ inventory_dict.update({'Device ID':Device_ID})
3010+ #inventory_dict.update({'Manufacturer Name':Manufacturer})
3011+ inventory_dict.update({'Firmware Revision':Firmware})
3012+ inventory_dict.update({'IPMI Version':IPMI_version})
3013+
3014+ for item in inventory_list:
3015+ if inventory_dict.get(item) == 'Error' or inventory_dict.get(item) == None:
3016+ flag = 1
3017+
3018+ print("{}: {}".format(item, inventory_dict.get(item)))
3019+
3020+ if flag == 1:
3021+ return 1
3022+ return 0
3023+
3024+def main():
3025+ intro_message = "Default config location is /etc/checkbox.d/bmc.cfg"
3026+ parser = ArgumentParser(description=intro_message,
3027+ formatter_class=RawTextHelpFormatter)
3028+ parser.add_argument('--config', type=str,
3029+ default="/etc/checkbox.d/bmc.cfg",
3030+ help="Supply config file for getting authentication info")
3031+ args = parser.parse_args()
3032+
3033+ return inventory(args)
3034+
3035+if __name__ == '__main__':
3036+ sys.exit(main())
3037
3038=== added file 'bin/ipmi_power_draw'
3039--- bin/ipmi_power_draw 1970-01-01 00:00:00 +0000
3040+++ bin/ipmi_power_draw 2015-08-14 22:03:31 +0000
3041@@ -0,0 +1,126 @@
3042+#!/usr/bin/env python3
3043+"""
3044+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
3045+Industrial Technology Research Institute
3046+
3047+File Name
3048+ ipmi_power_draw
3049+ 1. GatherRetrieving power draw datainfo via ipmitool
3050+ 2. The datainfo contains "Minimum during sampling period", "Maximum during sampling period", "Average power reading over sample period", "IPMI timestamp", "Sampling period", "Power reading state".
3051+ 3. Criteria: The return value of each item cannot be null
3052+
3053+Authors
3054+ Sophia Wu <Sophia.Wu@itri.org.tw>
3055+
3056+This program is free software: you can redistribute it and/or modify
3057+it under the terms of the GNU General Public License version 3,
3058+as published by the Free Software Foundation.
3059+
3060+This program is distributed in the hope that it will be useful,
3061+but WITHOUT ANY WARRANTY; without even the implied warranty of
3062+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3063+GNU General Public License for more details.
3064+
3065+You should have received a copy of the GNU General Public License
3066+along with this program. If not, see <http://www.gnu.org/licenses/>.
3067+
3068+"""
3069+from argparse import (
3070+ ArgumentParser,
3071+ RawTextHelpFormatter
3072+)
3073+import sys
3074+import shlex
3075+import re
3076+import time
3077+import configparser
3078+import subprocess
3079+from subprocess import (
3080+ CalledProcessError,
3081+ check_call,
3082+ check_output
3083+)
3084+
3085+def get_power_draw(host_ip, user, password):
3086+ cmd = 'ipmitool -H {} -U {} -P {} dcmi power reading'.format(host_ip, user, password)
3087+ output = check_output(shlex.split(cmd), universal_newlines=True)
3088+ return output
3089+
3090+def power_draw_test(args):
3091+
3092+ #Default config file to config requirement info for DCMI in-band/out-of-band access
3093+ DEFAULT_CFG = "/etc/checkbox.d/me.cfg"
3094+ if not "config" in vars(args):
3095+ config_file = DEFAULT_CFG
3096+ else:
3097+ config_file = args.config
3098+
3099+ config = configparser.RawConfigParser()
3100+
3101+ try:
3102+ config.readfp(open(config_file))
3103+ except IOError:
3104+ print("No config file found")
3105+ return 10
3106+
3107+ # Acquire ME IP/Credential parameters from config file
3108+ try:
3109+ targets_options = config.options('Targets')
3110+ targets_list = []
3111+ for target_key in targets_options:
3112+ targets_list.append(config.get('Targets', target_key))
3113+ if not targets_list:
3114+ print("Invalid or Empty targets")
3115+ return 20
3116+ except configparser.Error:
3117+ print("Invalid or Empty targets")
3118+ return 30
3119+
3120+ try:
3121+ user_value = config.get('Account', 'USER')
3122+ passwd_value = config.get('Account', 'PASSWORD')
3123+ except configparser.Error:
3124+ print("Invalid or Empty credential info")
3125+ return 40
3126+
3127+ flag = 0
3128+ for target in targets_list:
3129+
3130+ if not target or not user_value or not passwd_value:
3131+ print("Require Taget IP, Account(USER/PASSWORD) for DCMI out-of-band access")
3132+ return 50
3133+ else:
3134+ print("SUT =", target)
3135+
3136+ try:
3137+ power_draw_return = get_power_draw(target, user_value, passwd_value)
3138+ time.sleep(5)
3139+ except CalledProcessError as command_exception:
3140+ print("Failed executing dcmi command", command_exception)
3141+ return 60
3142+
3143+ power_list = ['Minimum during sampling period', 'Maximum during sampling period',\
3144+ 'Average power reading over sample period',\
3145+ 'IPMI timestamp', 'Sampling period', 'Power reading state is']
3146+ for i in power_list:
3147+ value = re.search(i+':\s*([a-zA-Z0-9-: ]+)', power_draw_return)
3148+ if value == None:
3149+ print("{}: Error".format(i))
3150+ flag = 1
3151+ else:
3152+ print("{}: {}".format(i, value.group(1)))
3153+ if flag == 1:
3154+ return 1
3155+ return 0
3156+
3157+def main():
3158+ intro_message = "Default config location is /etc/checkbox.d/me.cfg"
3159+ parser = ArgumentParser(description=intro_message,
3160+ formatter_class=RawTextHelpFormatter)
3161+ parser.add_argument('--config', default="/etc/checkbox.d/me.cfg",
3162+ help="Supply config file for getting authentication info")
3163+ args = parser.parse_args()
3164+ return power_draw_test(args)
3165+
3166+if __name__ == '__main__':
3167+ sys.exit(main())
3168
3169=== added file 'bin/ipmi_power_off_on'
3170--- bin/ipmi_power_off_on 1970-01-01 00:00:00 +0000
3171+++ bin/ipmi_power_off_on 2015-08-14 22:03:31 +0000
3172@@ -0,0 +1,193 @@
3173+#! /usr/bin/env python3
3174+"""
3175+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
3176+Industrial Technology Research Institute
3177+
3178+File Name
3179+ ipmi_power_off_on
3180+
3181+Description
3182+ 1. Use ipmitool out-of-band access to turn on/off the SUT.
3183+ 2. Criteria: the SUT can be powered on/off by ipmitool out-of-band access.
3184+
3185+Authors
3186+ Sophia Wu <Sophia.Wu@itri.org.tw>
3187+
3188+This program is free software: you can redistribute it and/or modify
3189+it under the terms of the GNU General Public License version 3,
3190+as published by the Free Software Foundation.
3191+
3192+This program is distributed in the hope that it will be useful,
3193+but WITHOUT ANY WARRANTY; without even the implied warranty of
3194+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3195+GNU General Public License for more details.
3196+
3197+You should have received a copy of the GNU General Public License
3198+along with this program. If not, see <http://www.gnu.org/licenses/>.
3199+
3200+"""
3201+from argparse import (
3202+ ArgumentParser,
3203+ RawTextHelpFormatter
3204+)
3205+
3206+import sys
3207+import configparser
3208+import shlex
3209+import subprocess
3210+import ast
3211+import time
3212+from subprocess import (
3213+ check_output,
3214+ CalledProcessError
3215+)
3216+
3217+def check_power_status(host_ip, user, password):
3218+
3219+ cmd_status_on = 'ipmitool -H {} -U {} -P {} power status| grep -q "on"'\
3220+ .format(host_ip, user, password)
3221+ check_on_value = subprocess.call(cmd_status_on, shell=True)
3222+ time.sleep(5)
3223+
3224+ cmd_status_off = 'ipmitool -H {} -U {} -P {} power status| grep -q "off"'\
3225+ .format(host_ip, user, password)
3226+ check_off_value = subprocess.call(cmd_status_off, shell=True)
3227+ time.sleep(5)
3228+
3229+ if check_on_value == 0 and check_off_value == 1:
3230+ check_status = 'on'
3231+
3232+ elif check_on_value == 1 and check_off_value == 0:
3233+ check_status = 'off'
3234+
3235+ else:
3236+ check_status = 'error'
3237+
3238+ return check_status
3239+
3240+def run_power_off(host_ip, user, password):
3241+ cmd_power_off = 'ipmitool -H {} -U {} -P {} power off'\
3242+ .format(host_ip, user, password)
3243+ power_off_return_code = subprocess.call(cmd_power_off, shell=True)
3244+ return power_off_return_code
3245+
3246+def run_power_on(host_ip, user, password):
3247+ cmd_power_on = 'ipmitool -H {} -U {} -P {} power on'\
3248+ .format(host_ip, user, password)
3249+ power_on_return_code = subprocess.call(cmd_power_on, shell=True)
3250+ return power_on_return_code
3251+
3252+def ipmi_reset_oob(args):
3253+
3254+ #IPMI config file
3255+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
3256+ if not "config" in vars(args):
3257+ config_file = DEFAULT_CFG
3258+ else:
3259+ config_file = args.config
3260+
3261+ config = configparser.RawConfigParser()
3262+
3263+ try:
3264+ config.readfp(open(config_file))
3265+ except IOError:
3266+ print("No config file found")
3267+ return 10
3268+
3269+ try:
3270+ targets_options = config.options('Targets')
3271+ targets_list = []
3272+ for target_key in targets_options:
3273+ targets_list.append(config.get('Targets', target_key))
3274+
3275+ if not targets_list:
3276+ print("Invalid or Empty targets")
3277+ return 20
3278+
3279+ except configparser.Error:
3280+ print("Invalid or Empty targets")
3281+ return 30
3282+
3283+ try:
3284+ user_value = config.get('Account', 'USER')
3285+ passwd_value = config.get('Account', 'PASSWORD')
3286+ if not user_value or not passwd_value:
3287+ print("Invalid or Empty credential info")
3288+ return 40
3289+
3290+ except configparser.Error:
3291+ print("Invalid or Empty credential info")
3292+ return 50
3293+
3294+ ping_flag = 0
3295+ for tg in targets_list:
3296+
3297+ if not tg or not user_value or not passwd_value:
3298+ print("Require Taget IP, Account(USER/PASSWORD) for IPMI out-of-band access")
3299+ return 21
3300+ else:
3301+
3302+ print("SUT =", tg)
3303+ print("USER =", user_value)
3304+ print("PASSWORD =", passwd_value)
3305+
3306+ for n in range(2):
3307+
3308+ count = 0
3309+ while count < 10:
3310+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(tg)
3311+ ping_rtn = subprocess.call(ping_cmd, shell=True)
3312+ if ping_rtn == 0:
3313+ print("Destination Host Reachable")
3314+
3315+ #run test
3316+ status = check_power_status(tg, user_value, passwd_value)
3317+
3318+ if status == 'on':
3319+ #run power off
3320+ power_off_result = run_power_off(tg, user_value, passwd_value)
3321+ print(" ")
3322+ if power_off_result == 1:
3323+ print("Failed to power off SUT.")
3324+ return 88
3325+ elif status == 'off':
3326+ #run power on
3327+ power_on_result = run_power_on(tg, user_value, passwd_value)
3328+ print(" ")
3329+ if power_on_result == 1:
3330+ print("Failed to power on SUT.")
3331+ return 99
3332+ else:
3333+ #do nothing
3334+ print("Failed to check power status")
3335+ return 77
3336+
3337+ time.sleep(180)
3338+ break
3339+
3340+ else:
3341+ time.sleep(10)
3342+ count = count+1
3343+ print("Destination Host Unreachable")
3344+
3345+ if count == 10:
3346+ print("Host Has No Response, End of Test")
3347+ ping_flag = 100
3348+
3349+ if ping_flag == 100:
3350+ return 100
3351+ return 0
3352+
3353+def main():
3354+
3355+ intro_message = "Default config location is /etc/checkbox.d/bmc.cfg"
3356+ parser = ArgumentParser(description=intro_message,
3357+ formatter_class=RawTextHelpFormatter)
3358+ parser.add_argument('--config', type=str,
3359+ default="/etc/checkbox.d/bmc.cfg",
3360+ help="Supply config file for getting authentication info")
3361+ args = parser.parse_args()
3362+ return ipmi_reset_oob(args)
3363+
3364+if __name__ == "__main__":
3365+ sys.exit(main())
3366
3367=== added file 'bin/ipmi_power_policy'
3368--- bin/ipmi_power_policy 1970-01-01 00:00:00 +0000
3369+++ bin/ipmi_power_policy 2015-08-14 22:03:31 +0000
3370@@ -0,0 +1,165 @@
3371+#!/usr/bin/env python3
3372+"""
3373+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
3374+Industrial Technology Research Institute
3375+
3376+File Name
3377+ ipmi_power_policy
3378+
3379+Description
3380+ 1. Use ipmitool to set power on policy through OOB.
3381+ 2. Criteria: the change of power policy should take effect without BMC firmware cold reset or system reboot.
3382+
3383+Authors
3384+ Sophia Wu <Sophia.Wu@itri.org.tw>
3385+
3386+This program is free software: you can redistribute it and/or modify
3387+it under the terms of the GNU General Public License version 3,
3388+as published by the Free Software Foundation.
3389+
3390+This program is distributed in the hope that it will be useful,
3391+but WITHOUT ANY WARRANTY; without even the implied warranty of
3392+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3393+GNU General Public License for more details.
3394+
3395+You should have received a copy of the GNU General Public License
3396+along with this program. If not, see <http://www.gnu.org/licenses/>.
3397+
3398+"""
3399+
3400+from argparse import (
3401+ ArgumentParser,
3402+ RawTextHelpFormatter
3403+)
3404+
3405+import sys
3406+import shlex
3407+import time
3408+import subprocess
3409+from subprocess import (
3410+ check_output,
3411+ CalledProcessError
3412+)
3413+import re
3414+import configparser
3415+import os
3416+
3417+def set_power_policy(host_ip, user, password, rule):
3418+ os.system('ipmitool -H {} -U {} -P {} chassis policy {}'.format(host_ip, user, password, rule))
3419+
3420+def get_chassis_status(host_ip, user, password):
3421+ cmd = 'ipmitool -H {} -U {} -P {} chassis status'.format(host_ip, user, password)
3422+ output = check_output(shlex.split(cmd), universal_newlines=True)
3423+ return output
3424+
3425+def get_power_policy(host_ip, user, password):
3426+ result = get_chassis_status(host_ip, user, password)
3427+ policy = re.search(r'Power Restore Policy\s*:\s*([a-zA-Z0-9-._ ]+\n)', result)
3428+ if policy == None:
3429+ return 'Error'
3430+ else:
3431+ return policy.group(1).strip()
3432+
3433+def check_policy(host_ip, user, password, rule):
3434+ current_policy = get_power_policy(host_ip, user, password)
3435+ if current_policy == rule:
3436+ print("Successfully setting power policy")
3437+ return 0
3438+ else:
3439+ return 1
3440+
3441+def power_policy_test(args):
3442+
3443+ #IPMI config file
3444+ policy_rule = args.rule
3445+ if not policy_rule:
3446+ print("No specified policy to set")
3447+ return 88
3448+
3449+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
3450+
3451+ if not "config" in vars(args):
3452+ config_file = DEFAULT_CFG
3453+ else:
3454+ config_file = args.config
3455+
3456+ config = configparser.RawConfigParser()
3457+
3458+ try:
3459+ config.readfp(open(config_file))
3460+ except IOError:
3461+ print("No config file found")
3462+ return 10
3463+
3464+ try:
3465+ targets_options = config.options('Targets')
3466+ targets_list = []
3467+ for target_key in targets_options:
3468+ targets_list.append(config.get('Targets', target_key))
3469+
3470+ if not targets_list:
3471+ print("Invalid or Empty targets")
3472+ return 20
3473+
3474+ except configparser.Error:
3475+ print("Invalid or Empty targets")
3476+ return 30
3477+
3478+ try:
3479+ user_value = config.get('Account', 'USER')
3480+ passwd_value = config.get('Account', 'PASSWORD')
3481+ if not user_value or not passwd_value:
3482+ print("Invalid or Empty credential info")
3483+ return 40
3484+
3485+ except configparser.Error:
3486+ print("Invalid or Empty credential info")
3487+ return 50
3488+
3489+ flag = 0
3490+ for tg in targets_list:
3491+
3492+ if not tg or not user_value or not passwd_value:
3493+ print("Require Taget IP, Account(USER/PASSWORD) for IPMI out-of-band access")
3494+ return 60
3495+ else:
3496+ print("SUT =", tg)
3497+
3498+ try:
3499+ set_power_policy(tg, user_value, passwd_value, policy_rule)
3500+ except:
3501+ print("Fail to set power policy")
3502+ return 70
3503+
3504+ time.sleep(5)
3505+
3506+ try:
3507+ chassis_status = get_chassis_status(tg, user_value, passwd_value)
3508+ except:
3509+ print("Fail to get chassis status")
3510+ return 80
3511+
3512+ current_policy = get_power_policy(tg, user_value, passwd_value)
3513+
3514+ value = check_policy(tg, user_value, passwd_value, policy_rule)
3515+
3516+ if value == 1:
3517+ flag = 1
3518+
3519+ if flag == 1:
3520+ return 1
3521+ return 0
3522+
3523+def main():
3524+ intro_message = "Default config location is /etc/checkbox.d/bmc.cfg"
3525+ parser = ArgumentParser(description=intro_message,
3526+ formatter_class=RawTextHelpFormatter)
3527+ parser.add_argument('--config', type=str,
3528+ default="/etc/checkbox.d/bmc.cfg",
3529+ help="Supply config file for getting authentication info")
3530+ parser.add_argument('--rule', help="always-on, always-off or previous")
3531+ args = parser.parse_args()
3532+ return power_policy_test(args)
3533+
3534+if __name__ == '__main__':
3535+ sys.exit(main())
3536
3537=== added file 'bin/ipmi_power_reset'
3538--- bin/ipmi_power_reset 1970-01-01 00:00:00 +0000
3539+++ bin/ipmi_power_reset 2015-08-14 22:03:31 +0000
3540@@ -0,0 +1,142 @@
3541+#!/usr/bin/env python3
3542+"""
3543+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
3544+Industrial Technology Research Institute
3545+
3546+File Name
3547+ ipmi_power_reset
3548+
3549+Description
3550+ 1. Use ipmitool out-of-band access to power hard reset the SUT 20 times.
3551+ 2. Criteria: complete 20 power hard reset on SUT successfully using ipmitool out-of-band access.
3552+
3553+Authors
3554+ Sophia Wu <Sophia.Wu@itri.org.tw>
3555+
3556+This program is free software: you can redistribute it and/or modify
3557+it under the terms of the GNU General Public License version 3,
3558+as published by the Free Software Foundation.
3559+
3560+This program is distributed in the hope that it will be useful,
3561+but WITHOUT ANY WARRANTY; without even the implied warranty of
3562+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3563+GNU General Public License for more details.
3564+
3565+You should have received a copy of the GNU General Public License
3566+along with this program. If not, see <http://www.gnu.org/licenses/>.
3567+
3568+"""
3569+
3570+from argparse import (
3571+ ArgumentParser,
3572+ RawTextHelpFormatter
3573+)
3574+
3575+import sys
3576+import configparser
3577+import shlex
3578+import subprocess
3579+import ast
3580+import time
3581+from subprocess import (
3582+ check_output,
3583+ CalledProcessError
3584+)
3585+
3586+def run(host_ip, user, password):
3587+ cmd = 'ipmitool -H {} -U {} -P {} power reset'.format(host_ip, user, password)
3588+ power_reset_return = check_output(shlex.split(cmd), universal_newlines=True)
3589+ return power_reset_return
3590+
3591+def ipmi_reset_oob(args):
3592+
3593+ #IPMI config file
3594+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
3595+ if not "config" in vars(args):
3596+ config_file = DEFAULT_CFG
3597+ else:
3598+ config_file = args.config
3599+
3600+ config = configparser.RawConfigParser()
3601+ try:
3602+ config.readfp(open(config_file))
3603+ except IOError:
3604+ print("No config file found")
3605+ return 1
3606+
3607+ try:
3608+ targets_options = config.options('Targets')
3609+ targets_list = []
3610+ for target_key in targets_options:
3611+ targets_list.append(config.get('Targets', target_key))
3612+ if not targets_list:
3613+ print("Invalid or Empty targets")
3614+ return 2
3615+ except configparser.Error:
3616+ print("Invalid or Empty targets")
3617+ return 2
3618+
3619+ try:
3620+ user_value = config.get("Account", "USER")
3621+ password_value = config.get("Account", "PASSWORD")
3622+ except configparser.NoOptionError:
3623+ print("Invalid or Empty credential info")
3624+ return 3
3625+
3626+ ping_flag = 0
3627+ for tg in targets_list:
3628+
3629+ if not tg or not user_value or not password_value:
3630+ print("Require Taget IP, Account(USER/PASSWORD) for IPMI out-of-band access")
3631+ return 4
3632+ else:
3633+ print("SUT =", tg)
3634+ print("USER =", user_value)
3635+ print("PASSWORD =", password_value)
3636+
3637+ for n in range(20):
3638+ print("---------------- %s ----------------" % n)
3639+ count = 0
3640+ while count < 10:
3641+ print("+++++++++++ %s ++++++++++++" % count)
3642+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(tg)
3643+ ping_rtn = subprocess.call(ping_cmd, shell=True)
3644+
3645+ if ping_rtn == 0:
3646+ print("Destination Host Reachable")
3647+
3648+ try:
3649+ power_control = run(tg, user_value, password_value)
3650+ print(power_control)
3651+ except CalledProcessError as ipmi_exception:
3652+ print("Failed executing ipmi, Reason: %s" % ipmi_exception)
3653+ return 6
3654+
3655+ time.sleep(180)
3656+ break
3657+ else:
3658+ time.sleep(10)
3659+ count = count+1
3660+ print("Destination Host Unreachable")
3661+
3662+ if count == 10:
3663+ print("Host Has No Response, End of Test")
3664+ ping_flag = 100
3665+
3666+ if ping_flag == 100:
3667+ return 100
3668+ return 0
3669+
3670+def main():
3671+
3672+ intro_message = "Default config location is /etc/checkbox.d/bmc.cfg"
3673+ parser = ArgumentParser(description=intro_message,
3674+ formatter_class=RawTextHelpFormatter)
3675+ parser.add_argument('--config',
3676+ default="/etc/checkbox.d/bmc.cfg",
3677+ help="Supply config file for getting authentication info")
3678+ args = parser.parse_args()
3679+ return ipmi_reset_oob(args)
3680+
3681+if __name__ == "__main__":
3682+ sys.exit(main())
3683
3684=== added file 'bin/ipmi_priv_admin'
3685--- bin/ipmi_priv_admin 1970-01-01 00:00:00 +0000
3686+++ bin/ipmi_priv_admin 2015-08-14 22:03:31 +0000
3687@@ -0,0 +1,176 @@
3688+#! /usr/bin/env python3
3689+"""
3690+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
3691+Industrial Technology Research Institute
3692+
3693+File Name
3694+ ipmi_priv_admin
3695+
3696+Description
3697+ 1. Use ipmitool out-of-band to read power status, to perform power reset and add a new user account.
3698+ 2. Criteria: reading power status, performing power reset and adding a user account must all be successful.
3699+
3700+Authors
3701+ Sophia Wu <Sophia.Wu@itri.org.tw>
3702+
3703+This program is free software: you can redistribute it and/or modify
3704+it under the terms of the GNU General Public License version 3,
3705+as published by the Free Software Foundation.
3706+
3707+This program is distributed in the hope that it will be useful,
3708+but WITHOUT ANY WARRANTY; without even the implied warranty of
3709+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3710+GNU General Public License for more details.
3711+
3712+You should have received a copy of the GNU General Public License
3713+along with this program. If not, see <http://www.gnu.org/licenses/>.
3714+
3715+"""
3716+from argparse import (
3717+ ArgumentParser,
3718+ RawTextHelpFormatter
3719+)
3720+
3721+import sys
3722+import configparser
3723+import shlex
3724+import subprocess
3725+import ast
3726+import time
3727+from subprocess import (
3728+ check_output,
3729+ CalledProcessError
3730+)
3731+
3732+def get_power_status(host_ip, user, password):
3733+ cmd_status = 'ipmitool -H {} -U {} -P {} power status 1>/dev/null 2>/dev/null'\
3734+ .format(host_ip, user, password)
3735+ status_code = subprocess.call(cmd_status, shell=True)
3736+ return status_code
3737+
3738+def power_reset(host_ip, user, password):
3739+ cmd_reset = 'ipmitool -H {} -U {} -P {} power reset 1>/dev/null 2>/dev/null'\
3740+ .format(host_ip, user, password)
3741+ reset_code = subprocess.call(cmd_reset, shell=True)
3742+ return reset_code
3743+
3744+def add_user(host_ip, user, password, new_id, new_user):
3745+ cmd_add_user = 'ipmitool -H {} -U {} -P {} user set name {} {} 1>/dev/null 2>/dev/null'\
3746+ .format(host_ip, user, password, new_id, new_user)
3747+ add_user_code = subprocess.call(cmd_add_user, shell=True)
3748+ return add_user_code
3749+
3750+def ipmi_user_level_test(args):
3751+
3752+ #IPMI config file
3753+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
3754+ if not "config" in vars(args):
3755+ config_file = DEFAULT_CFG
3756+ else:
3757+ config_file = args.config
3758+ config = configparser.RawConfigParser()
3759+ try:
3760+ config.readfp(open(config_file))
3761+ except IOError:
3762+ print("No config file found")
3763+ return 10
3764+
3765+ try:
3766+ targets_options = config.options('Targets')
3767+ targets_list = []
3768+ for target_key in targets_options:
3769+ targets_list.append(config.get('Targets', target_key))
3770+ if not targets_list:
3771+ print("Invalid or Empty targets")
3772+ return 20
3773+ except configparser.Error:
3774+ print("Invalid or Empty targets")
3775+ return 20
3776+
3777+ try:
3778+ user_value = config.get("Admin Level", "ADMIN_NAME")
3779+ password_value = config.get("Admin Level", "ADMIN_PASSWD")
3780+ except configparser.NoOptionError:
3781+ print("Invalid or Empty credential info")
3782+ print("Require Operator Level info pre-configured in /etc/checkbox.d/bmc.cfg")
3783+ return 30
3784+
3785+ try:
3786+ new_user_value = config.get("Add User Test", "NEW_USER_NAME")
3787+ new_user_id_value = config.get("Add User Test", "NEW_USER_ID")
3788+ except configparser.NoOptionError:
3789+ print("Invalid or Empty new user info")
3790+ print("Require new User info pre-configured in /etc/checkbox.d/bmc.cfg")
3791+ return 40
3792+
3793+ flag = 0
3794+ for tg in targets_list:
3795+
3796+ if not tg or not user_value or not password_value:
3797+ print("Require Taget IP, Account(USER/PASSWORD) for IPMI out-of-band access")
3798+ return 50
3799+ else:
3800+ print("SUT", tg)
3801+
3802+ ping_result = ping_test(tg)
3803+ if ping_result != 0:
3804+ return 88
3805+
3806+ status_result = get_power_status(tg, user_value, password_value)
3807+ time.sleep(5)
3808+
3809+ reset_result = power_reset(tg, user_value, password_value)
3810+ time.sleep(180)
3811+ if not new_user_value or not new_user_id_value:
3812+ print("Require new user info pre-configured in /etc/checkbox.d/bmc.cfg")
3813+ return 60
3814+ else:
3815+
3816+ ping_result = ping_test(tg)
3817+ if ping_result != 0:
3818+ return 88
3819+
3820+ add_user_result = add_user(tg, user_value, password_value, new_user_id_value, new_user_value)
3821+ time.sleep(5)
3822+
3823+ if status_result == 0 and reset_result == 0 and add_user_result == 0:
3824+ print("User can read power status.")
3825+ print("User can reset power.")
3826+ print("User can add a new user.")
3827+ else:
3828+ print("Authentication: Not Administrator Level")
3829+ flag = 1
3830+
3831+ if flag == 1:
3832+ return 100
3833+ return 0
3834+
3835+def ping_test(host_ip):
3836+ count = 0
3837+ while count < 10:
3838+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(host_ip)
3839+ ping_rtn = subprocess.call(ping_cmd, shell=True)
3840+ if ping_rtn == 0:
3841+ return 0
3842+ else:
3843+ print("Destination Host Unreachable")
3844+ time.sleep(10)
3845+ count = count+1
3846+
3847+ if count == 10:
3848+ print("Host Has No Response, End of Test")
3849+ return 1
3850+
3851+
3852+def main():
3853+
3854+ intro_message = "Default config location is /etc/checkbox.d/bmc.cfg"
3855+ parser = ArgumentParser(description=intro_message, formatter_class=RawTextHelpFormatter)
3856+ parser.add_argument('--config', type=str,
3857+ default="/etc/checkbox.d/bmc.cfg",
3858+ help="Supply config file for getting authentication info")
3859+ args = parser.parse_args()
3860+ return ipmi_user_level_test(args)
3861+
3862+if __name__ == "__main__":
3863+ sys.exit(main())
3864
3865=== added file 'bin/ipmi_priv_oper'
3866--- bin/ipmi_priv_oper 1970-01-01 00:00:00 +0000
3867+++ bin/ipmi_priv_oper 2015-08-14 22:03:31 +0000
3868@@ -0,0 +1,174 @@
3869+#! /usr/bin/env python3
3870+"""
3871+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
3872+Industrial Technology Research Institute
3873+
3874+File Name
3875+ ipmi_priv_oper
3876+ 1. Use ipmitool out-of-band to read power status, to perform power reset and add a new user account.
3877+ 2. Criteria: power status reading and power reset must be successful and must fail at adding a new user account.
3878+
3879+Authors
3880+ Sophia Wu <Sophia.Wu@itri.org.tw>
3881+
3882+This program is free software: you can redistribute it and/or modify
3883+it under the terms of the GNU General Public License version 3,
3884+as published by the Free Software Foundation.
3885+
3886+This program is distributed in the hope that it will be useful,
3887+but WITHOUT ANY WARRANTY; without even the implied warranty of
3888+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3889+GNU General Public License for more details.
3890+
3891+You should have received a copy of the GNU General Public License
3892+along with this program. If not, see <http://www.gnu.org/licenses/>.
3893+
3894+"""
3895+from argparse import (
3896+ ArgumentParser,
3897+ RawTextHelpFormatter
3898+)
3899+
3900+import sys
3901+import configparser
3902+import shlex
3903+import subprocess
3904+import ast
3905+import time
3906+from subprocess import (
3907+ check_output,
3908+ CalledProcessError
3909+)
3910+
3911+def get_power_status(host_ip, user, password):
3912+ cmd_status = 'ipmitool -H {} -U {} -P {} power status -L operator 1>/dev/null 2>/dev/null'\
3913+ .format(host_ip, user, password)
3914+ status_code = subprocess.call(cmd_status, shell=True)
3915+ return status_code
3916+
3917+def power_reset(host_ip, user, password):
3918+ cmd_reset = 'ipmitool -H {} -U {} -P {} power reset -L operator 1>/dev/null 2>/dev/null'\
3919+ .format(host_ip, user, password)
3920+ reset_code = subprocess.call(cmd_reset, shell=True)
3921+ return reset_code
3922+
3923+def add_user(host_ip, user, password, new_id, new_user):
3924+ cmd_add_user = 'ipmitool -H {} -U {} -P {} user set name {} {} -L operator 1>/dev/null 2>/dev/null'\
3925+ .format(host_ip, user, password, new_id, new_user)
3926+ add_user_code = subprocess.call(cmd_add_user, shell=True)
3927+ return add_user_code
3928+
3929+def ipmi_user_level_test(args):
3930+
3931+ #IPMI config file
3932+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
3933+ if not "config" in vars(args):
3934+ config_file = DEFAULT_CFG
3935+ else:
3936+ config_file = args.config
3937+ config = configparser.RawConfigParser()
3938+ try:
3939+ config.readfp(open(config_file))
3940+ except IOError:
3941+ print("No config file found")
3942+ return 10
3943+
3944+ try:
3945+ targets_options = config.options('Targets')
3946+ targets_list = []
3947+ for target_key in targets_options:
3948+ targets_list.append(config.get('Targets', target_key))
3949+ if not targets_list:
3950+ print("Invalid or Empty targets")
3951+ return 20
3952+ except configparser.Error:
3953+ print("Invalid or Empty targets")
3954+ return 20
3955+
3956+ try:
3957+ user_value = config.get("Operator Level", "OPER_NAME")
3958+ password_value = config.get("Operator Level", "OPER_PASSWD")
3959+ except configparser.NoOptionError:
3960+ print("Invalid or Empty credential info")
3961+ print("Require Operator Level info pre-configured in /etc/checkbox.d/bmc.cfg")
3962+ return 30
3963+
3964+ try:
3965+ new_user_value = config.get("Add User Test", "NEW_USER_NAME")
3966+ new_user_id_value = config.get("Add User Test", "NEW_USER_ID")
3967+ except configparser.NoOptionError:
3968+ print("Invalid or Empty new user info")
3969+ print("Require new User info pre-configured in /etc/checkbox.d/bmc.cfg")
3970+ return 40
3971+
3972+ flag = 0
3973+ for tg in targets_list:
3974+
3975+ if not tg or not user_value or not password_value:
3976+ print("Require Taget IP, Account(USER/PASSWORD) for IPMI out-of-band access")
3977+ return 50
3978+ else:
3979+ print("SUT", tg)
3980+
3981+ ping_result = ping_test(tg)
3982+ if ping_result != 0:
3983+ return 88
3984+
3985+ status_result = get_power_status(tg, user_value, password_value)
3986+ time.sleep(5)
3987+
3988+ reset_result = power_reset(tg, user_value, password_value)
3989+ time.sleep(180)
3990+ if not new_user_value or not new_user_id_value:
3991+ print("Require new user info pre-configured in /etc/checkbox.d/bmc.cfg")
3992+ return 60
3993+ else:
3994+
3995+ ping_result = ping_test(tg)
3996+ if ping_result != 0:
3997+ return 88
3998+
3999+ add_user_result = add_user(tg, user_value, password_value, new_user_id_value, new_user_value)
4000+ time.sleep(5)
4001+
4002+ if status_result == 0 and reset_result == 0 and add_user_result == 1:
4003+ print("User can read power status.")
4004+ print("User can reset power.")
4005+ print("User can't add a new user.")
4006+ else:
4007+ print("Authentication: Not Operator Level")
4008+ flag = 1
4009+
4010+ if flag == 1:
4011+ return 100
4012+ return 0
4013+
4014+def ping_test(host_ip):
4015+ count = 0
4016+ while count < 10:
4017+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(host_ip)
4018+ ping_rtn = subprocess.call(ping_cmd, shell=True)
4019+ if ping_rtn == 0:
4020+ return 0
4021+ else:
4022+ print("Destination Host Unreachable")
4023+ time.sleep(10)
4024+ count = count+1
4025+
4026+ if count == 10:
4027+ print("Host Has No Response, End of Test")
4028+ return 1
4029+
4030+
4031+def main():
4032+
4033+ intro_message = "Default config location is /etc/checkbox.d/bmc.cfg"
4034+ parser = ArgumentParser(description=intro_message, formatter_class=RawTextHelpFormatter)
4035+ parser.add_argument('--config', type=str,
4036+ default="/etc/checkbox.d/bmc.cfg",
4037+ help="Supply config file for getting authentication info")
4038+ args = parser.parse_args()
4039+ return ipmi_user_level_test(args)
4040+
4041+if __name__ == "__main__":
4042+ sys.exit(main())
4043
4044=== added file 'bin/ipmi_priv_user'
4045--- bin/ipmi_priv_user 1970-01-01 00:00:00 +0000
4046+++ bin/ipmi_priv_user 2015-08-14 22:03:31 +0000
4047@@ -0,0 +1,176 @@
4048+#! /usr/bin/env python3
4049+"""
4050+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
4051+Industrial Technology Research Institute
4052+
4053+File Name
4054+ ipmi_priv_uesr
4055+
4056+Description
4057+ 1. Use ipmitool out-of-band to read power status, to perform power reset and add a new user account.
4058+ 2. Criteria: power status reading must be successful and must fail at power reset and adding a new user account.
4059+
4060+Authors
4061+ Sophia Wu <Sophia.Wu@itri.org.tw>
4062+
4063+This program is free software: you can redistribute it and/or modify
4064+it under the terms of the GNU General Public License version 3,
4065+as published by the Free Software Foundation.
4066+
4067+This program is distributed in the hope that it will be useful,
4068+but WITHOUT ANY WARRANTY; without even the implied warranty of
4069+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4070+GNU General Public License for more details.
4071+
4072+You should have received a copy of the GNU General Public License
4073+along with this program. If not, see <http://www.gnu.org/licenses/>.
4074+
4075+"""
4076+from argparse import (
4077+ ArgumentParser,
4078+ RawTextHelpFormatter
4079+)
4080+
4081+import sys
4082+import configparser
4083+import shlex
4084+import subprocess
4085+import ast
4086+import time
4087+from subprocess import (
4088+ check_output,
4089+ CalledProcessError
4090+)
4091+
4092+def get_power_status(host_ip, user, password):
4093+ cmd_status = 'ipmitool -H {} -U {} -P {} power status -L user 1>/dev/null 2>/dev/null'\
4094+ .format(host_ip, user, password)
4095+ status_code = subprocess.call(cmd_status, shell=True)
4096+ return status_code
4097+
4098+def power_reset(host_ip, user, password):
4099+ cmd_reset = 'ipmitool -H {} -U {} -P {} power reset -L user 1>/dev/null 2>/dev/null'\
4100+ .format(host_ip, user, password)
4101+ reset_code = subprocess.call(cmd_reset, shell=True)
4102+ return reset_code
4103+
4104+def add_user(host_ip, user, password, new_id, new_user):
4105+ cmd_add_user = 'ipmitool -H {} -U {} -P {} user set name {} {} -L user 1>/dev/null 2>/dev/null'\
4106+ .format(host_ip, user, password, new_id, new_user)
4107+ add_user_code = subprocess.call(cmd_add_user, shell=True)
4108+ return add_user_code
4109+
4110+def ipmi_user_level_test(args):
4111+
4112+ #IPMI config file
4113+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
4114+ if not "config" in vars(args):
4115+ config_file = DEFAULT_CFG
4116+ else:
4117+ config_file = args.config
4118+ config = configparser.RawConfigParser()
4119+ try:
4120+ config.readfp(open(config_file))
4121+ except IOError:
4122+ print("No config file found")
4123+ return 10
4124+
4125+ try:
4126+ targets_options = config.options('Targets')
4127+ targets_list = []
4128+ for target_key in targets_options:
4129+ targets_list.append(config.get('Targets', target_key))
4130+ if not targets_list:
4131+ print("Invalid or Empty targets")
4132+ return 20
4133+ except configparser.Error:
4134+ print("Invalid or Empty targets")
4135+ return 20
4136+
4137+ try:
4138+ user_value = config.get("User Level", "USER_NAME")
4139+ password_value = config.get("User Level", "USER_PASSWD")
4140+ except configparser.NoOptionError:
4141+ print("Invalid or Empty credential info")
4142+ print("Require User Level info pre-configured in /etc/checkbox.d/bmc.cfg")
4143+ return 30
4144+
4145+ try:
4146+ new_user_value = config.get("Add User Test", "NEW_USER_NAME")
4147+ new_user_id_value = config.get("Add User Test", "NEW_USER_ID")
4148+ except configparser.NoOptionError:
4149+ print("Invalid or Empty new user info")
4150+ print("Require new User info pre-configured in /etc/checkbox.d/bmc.cfg")
4151+ return 40
4152+
4153+ flag = 0
4154+ for tg in targets_list:
4155+
4156+ if not tg or not user_value or not password_value:
4157+ print("Require Taget IP, Account(USER/PASSWORD) for IPMI out-of-band access")
4158+ return 50
4159+ else:
4160+ print("SUT", tg)
4161+
4162+ ping_result = ping_test(tg)
4163+ if ping_result != 0:
4164+ return 88
4165+
4166+ status_result = get_power_status(tg, user_value, password_value)
4167+ time.sleep(5)
4168+
4169+ reset_result = power_reset(tg, user_value, password_value)
4170+ time.sleep(180)
4171+ if not new_user_value or not new_user_id_value:
4172+ print("Require new user info pre-configured in /etc/checkbox.d/bmc.cfg")
4173+ return 60
4174+ else:
4175+
4176+ ping_result = ping_test(tg)
4177+ if ping_result != 0:
4178+ return 88
4179+
4180+ add_user_result = add_user(tg, user_value, password_value, new_user_id_value, new_user_value)
4181+ time.sleep(5)
4182+
4183+ if status_result == 0 and reset_result == 1 and add_user_result == 1:
4184+ print("User can read power status.")
4185+ print("User can't reset power.")
4186+ print("User can't add a new user.")
4187+ else:
4188+ print("Authentication: Not User Level")
4189+ flag = 1
4190+
4191+ if flag == 1:
4192+ return 100
4193+ return 0
4194+
4195+def ping_test(host_ip):
4196+ count = 0
4197+ while count < 10:
4198+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(host_ip)
4199+ ping_rtn = subprocess.call(ping_cmd, shell=True)
4200+ if ping_rtn == 0:
4201+ return 0
4202+ else:
4203+ print("Destination Host Unreachable")
4204+ time.sleep(10)
4205+ count = count+1
4206+
4207+ if count == 10:
4208+ print("Host Has No Response, End of Test")
4209+ return 1
4210+
4211+
4212+def main():
4213+
4214+ intro_message = "Default config location is /etc/checkbox.d/bmc.cfg"
4215+ parser = ArgumentParser(description=intro_message, formatter_class=RawTextHelpFormatter)
4216+ parser.add_argument('--config', type=str,
4217+ default="/etc/checkbox.d/bmc.cfg",
4218+ help="Supply config file for getting authentication info")
4219+ args = parser.parse_args()
4220+ return ipmi_user_level_test(args)
4221+
4222+if __name__ == "__main__":
4223+ sys.exit(main())
4224
4225=== added file 'bin/ipmi_sampling'
4226--- bin/ipmi_sampling 1970-01-01 00:00:00 +0000
4227+++ bin/ipmi_sampling 2015-08-14 22:03:31 +0000
4228@@ -0,0 +1,273 @@
4229+#!/usr/bin/env python3
4230+"""
4231+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
4232+Industrial Technology Research Institute
4233+
4234+File Name
4235+ ipmi_sampling
4236+
4237+Description
4238+ 1. Retrieve CPU and intake temperature 30 times at 3 second intervals using ipmitool
4239+ 2. If failed to retrieve temperature at any time within 30 times, the test is considered failed
4240+
4241+Authors
4242+ Sophia Wu <Sophia.Wu@itri.org.tw>
4243+
4244+This program is free software: you can redistribute it and/or modify
4245+it under the terms of the GNU General Public License version 3,
4246+as published by the Free Software Foundation.
4247+
4248+This program is distributed in the hope that it will be useful,
4249+but WITHOUT ANY WARRANTY; without even the implied warranty of
4250+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4251+GNU General Public License for more details.
4252+
4253+You should have received a copy of the GNU General Public License
4254+along with this program. If not, see <http://www.gnu.org/licenses/>.
4255+
4256+"""
4257+import sys
4258+import time
4259+import re
4260+import configparser
4261+import shlex
4262+import subprocess
4263+from argparse import (
4264+ ArgumentParser,
4265+ RawTextHelpFormatter
4266+)
4267+from subprocess import (
4268+ check_output,
4269+ CalledProcessError
4270+)
4271+
4272+def get_sdr_remote(host_ip, user, password):
4273+ cmd = "ipmitool -H {} -U {} -P {} sdr".format(host_ip, user, password)
4274+ sdr_return = subprocess.check_output(shlex.split(cmd), stderr=subprocess.STDOUT,
4275+ universal_newlines=True)
4276+ return sdr_return
4277+
4278+def parse_sdr(output):
4279+ output = output.strip()
4280+ output_1Line = output.split("\n")
4281+ data = {}
4282+
4283+ for line in output_1Line:
4284+ sub_value = {}
4285+ string_list = line.split("|")
4286+ name = string_list[0].strip()
4287+ sensor_output = string_list[1].strip()
4288+ sub_value.update({'output':sensor_output})
4289+ status = string_list[2].strip()
4290+ sub_value.update({'status':status})
4291+ data.update({name:sub_value})
4292+ return data
4293+
4294+def calculate_CPU_temp(data_dict, CPU_Therm_Margin_id, CPU_Tjmax_id):
4295+ if data_dict.get(CPU_Therm_Margin_id) and data_dict.get(CPU_Tjmax_id):
4296+ if data_dict.get(CPU_Therm_Margin_id).get('status') == 'ok' and data_dict.get(CPU_Tjmax_id).get('status') == 'ok':
4297+ P_Therm_Margin_output = data_dict.get(CPU_Therm_Margin_id).get('output')
4298+ CPU_Tjmax_output = data_dict.get(CPU_Tjmax_id).get('output')
4299+ P_Therm_Margin = re.search(r'[0-9-]+', P_Therm_Margin_output).group(0)
4300+ CPU_Tjmax = re.search(r'[0-9-]+', CPU_Tjmax_output).group(0)
4301+ CPU_temp = int(P_Therm_Margin)+int(CPU_Tjmax)
4302+ return str(CPU_temp)+' degrees C'
4303+ else:
4304+ return 'Error'
4305+ else:
4306+ return 'None'
4307+
4308+def ipmi_sdr(args):
4309+
4310+ cmd_flag = 0
4311+ #IPMI config file
4312+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
4313+ if not "config" in vars(args):
4314+ config_file = DEFAULT_CFG
4315+ else:
4316+ config_file = args.config
4317+
4318+ config = configparser.RawConfigParser()
4319+
4320+ try:
4321+ config.readfp(open(config_file))
4322+ except IOError:
4323+ print("No config file found")
4324+ return 10
4325+
4326+ try:
4327+ sensor_nick = config.options("SensorsForSampling")
4328+ except configparser.NoSectionError:
4329+ print("No Section: SensorsForSampling")
4330+ return 20
4331+
4332+ if sensor_nick:
4333+ sensor_list = []
4334+ for id in sensor_nick:
4335+ sensor_key = config.get("SensorsForSampling", id)
4336+ if sensor_key:
4337+ sensor_list.append(sensor_key)
4338+ else:
4339+ print("No Sensor ID specified in Config file")
4340+ return 30
4341+ else:
4342+ print("No key of Sensor ID specified in config file")
4343+ return 40
4344+
4345+ try:
4346+ targets_options = config.options('Targets')
4347+ targets_list = []
4348+ for target_key in targets_options:
4349+ targets_list.append(config.get('Targets', target_key))
4350+ if not targets_list:
4351+ print("Invalid or Empty targets")
4352+ return 60
4353+ except configparser.Error:
4354+ print("Invalid or Empty targets")
4355+ return 60
4356+
4357+ try:
4358+ user_value = config.get("Account", "USER")
4359+ password_value = config.get("Account", "PASSWORD")
4360+ except configparser.NoOptionError:
4361+ print("Invalid or Empty credential info")
4362+ return 70
4363+
4364+ for tg in targets_list:
4365+
4366+ if not tg or not user_value or not password_value:
4367+ print("Require Taget IP, Account(USER/PASSWORD) for IPMI out-of-band access")
4368+ return 80
4369+ else:
4370+
4371+ c = 0
4372+ while c < 10:
4373+ ping_cmd = 'ping -c 1 {}>/dev/null 2>/dev/null'.format(tg)
4374+ ping_rtn = subprocess.call(ping_cmd, shell=True)
4375+ if ping_rtn == 0:
4376+ print("Destination Host Reachable")
4377+ break
4378+ else:
4379+ time.sleep(10)
4380+ c = c+1
4381+ print("Destination Host Unreachable")
4382+
4383+ if c == 10:
4384+ print("Host Has No Response, End of Test")
4385+ return 99
4386+
4387+
4388+ sampling_data = []
4389+ times = 30
4390+ for n in range(times):
4391+
4392+ try:
4393+ sensor_data = get_sdr_remote(tg, user_value, password_value)
4394+ time.sleep(3)
4395+ except CalledProcessError as ipmi_exception:
4396+ print("Failed executing ipmi, Reason: %s" % ipmi_exception)
4397+ sensor_data = ''
4398+
4399+ sampling_data.append(sensor_data)
4400+
4401+ count = 0
4402+ prs_flag = 0
4403+ dis_flag = 0
4404+ for output in sampling_data:
4405+ try:
4406+ data = parse_sdr(output)
4407+ except:
4408+ print("Parsing output of sdr table error")
4409+ print("=======================================================")
4410+ prs_flag = 1
4411+ count = count+1
4412+ continue
4413+
4414+ disable = 0
4415+ need_data = {}
4416+
4417+ for need_id in sensor_list:
4418+
4419+ if data.get(need_id):
4420+ need_value = data.get(need_id).get('output')
4421+ need_data.update({need_id:need_value})
4422+ if data.get(need_id).get('status') != 'ok':
4423+ disable = 1
4424+ else:
4425+
4426+ try:
4427+ CPUx_Temp = config.get("Sensors", "CPUx")
4428+ except configparser.NoOptionError:
4429+ CPUx_Temp = ''
4430+
4431+ try:
4432+ CPUy_Temp = config.get("Sensors", "CPUy")
4433+ except configparser.NoOptionError:
4434+ CPUy_Temp = ''
4435+
4436+ if need_id == CPUx_Temp:
4437+
4438+ try:
4439+ PxTM = config.get("SensorsForCPUTemp", "Px Therm Margin")
4440+ except configparser.NoOptionError:
4441+ PxTM = ''
4442+
4443+ try:
4444+ CPUx_Tjmax = config.get("SensorsForCPUTemp", "CPUx Tjmax")
4445+ except configparser.NoOptionError:
4446+ CPUx_Tjmax = ''
4447+
4448+ if PxTM and CPUx_Tjmax:
4449+ Px_temp = calculate_CPU_temp(data, PxTM, CPUx_Tjmax)
4450+ need_data.update({CPUx_Temp:Px_temp})
4451+ if Px_temp == 'None' or Px_temp == 'Error':
4452+ disable = 1
4453+ else:
4454+ disable = 1
4455+
4456+ elif need_id == CPUy_Temp:
4457+
4458+ try:
4459+ PyTM = config.get("SensorsForCPUTemp", "Py Therm Margin")
4460+ except configparser.NoOptionError:
4461+ PyTM = ''
4462+
4463+ try:
4464+ CPUy_Tjmax = config.get("SensorsForCPUTemp", "CPUy Tjmax")
4465+ except configparser.NoOptionError:
4466+ CPUy_Tjmax = ''
4467+
4468+ if PyTM and CPUy_Tjmax:
4469+ Py_temp = calculate_CPU_temp(data, PyTM, CPUy_Tjmax)
4470+ need_data.update({CPUy_Temp:Py_temp})
4471+ if Py_temp == 'None' or Py_temp == 'Error':
4472+ disable = 1
4473+ else:
4474+ disable = 1
4475+
4476+ else:
4477+ need_data.update({need_id:'None'})
4478+ disable = 1
4479+
4480+ if disable == 1:
4481+ dis_flag = 1
4482+ print(need_data)
4483+ print("=======================================================")
4484+ count = count+1
4485+ print("Pass: %d" %(times-count))
4486+ print("Fail: %d" %(count))
4487+
4488+ if cmd_flag == 1 or prs_flag == 1 or dis_flag == 1:
4489+ return 100
4490+ return 0
4491+
4492+def main():
4493+
4494+ intro_message = "Default config location is /etc/checkbox.d/bmc.cfg"
4495+ parser = ArgumentParser(description=intro_message, formatter_class=RawTextHelpFormatter)
4496+ parser.add_argument('--config', type=str, default="/etc/checkbox.d/bmc.cfg", help="Supply config file for sensor IDs parameters")
4497+ args = parser.parse_args()
4498+ return ipmi_sdr(args)
4499+
4500+if __name__ == "__main__":
4501+ sys.exit(main())
4502
4503=== modified file 'bin/ipmi_sel_entries'
4504--- bin/ipmi_sel_entries 2015-03-03 15:59:42 +0000
4505+++ bin/ipmi_sel_entries 2015-08-14 22:03:31 +0000
4506@@ -5,13 +5,11 @@
4507
4508 File Name
4509 ipmi_sel_entries
4510+
4511+Description
4512 1. Use ipmitool to collect event log information
4513 2. Calculate entries number of system event log
4514- 3. Criteria: the A log must be capable of saving at least 256 entries
4515-
4516-Description
4517- Use ipmitool to get system event log info and calculate whether
4518- total number of entries is more than 256.
4519+ 3. Criteria: the log must be capable of saving at least 256 entries
4520
4521 Authors
4522 Sophia Wu <Sophia.Wu@itri.org.tw>
4523@@ -63,8 +61,8 @@
4524
4525 def sel_entry_test(args):
4526
4527- #Default config file to config requirement info for DCMI in-band/out-of-band access
4528- DEFAULT_CFG = "/etc/checkbox.d/me.cfg"
4529+ #Default config file to config requirement info for IPMI in-band/out-of-band access
4530+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
4531 if not "config" in vars(args):
4532 config_file = DEFAULT_CFG
4533 else:
4534@@ -101,7 +99,7 @@
4535 for target in targets_list:
4536
4537 if not target or not user_value or not passwd_value:
4538- print("Require Taget IP, Account(USER/PASSWORD) for DCMI out-of-band access")
4539+ print("Require Taget IP, Account(USER/PASSWORD) for IPMI out-of-band access")
4540 return 50
4541 else:
4542 print("SUT =", target)
4543@@ -135,11 +133,11 @@
4544
4545 def main():
4546
4547- intro_message = "Default config location is /etc/checkbox.d/me.cfg"
4548+ intro_message = "Default config location is /etc/xdg/bmc.cfg"
4549 parser = ArgumentParser(description=intro_message,
4550 formatter_class=RawTextHelpFormatter)
4551- parser.add_argument('--config', default="/etc/checkbox.d/me.cfg",
4552- help="Supply config file for getting default credential")
4553+ parser.add_argument('--config', default="/etc/checkbox.d/bmc.cfg",
4554+ help="Supply config file for getting authentication info")
4555 args = parser.parse_args()
4556 return sel_entry_test(args)
4557
4558
4559=== added file 'bin/ipmi_sensors_ib'
4560--- bin/ipmi_sensors_ib 1970-01-01 00:00:00 +0000
4561+++ bin/ipmi_sensors_ib 2015-08-14 22:03:31 +0000
4562@@ -0,0 +1,215 @@
4563+#!/usr/bin/env python3
4564+"""
4565+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
4566+Industrial Technology Research Institute
4567+
4568+File Name
4569+ ipmi_sensors_ib
4570+
4571+Description
4572+ 1. Use ipmitool/dcmitool to monitor analog sensors in SDR table through in-band access.
4573+ 2. Criteria: the status of analog sensors should be "ok" and the data should not be null.
4574+
4575+Authors
4576+ Sophia Wu <Sophia.Wu@itri.org.tw>
4577+
4578+This program is free software: you can redistribute it and/or modify
4579+it under the terms of the GNU General Public License version 3,
4580+as published by the Free Software Foundation.
4581+
4582+This program is distributed in the hope that it will be useful,
4583+but WITHOUT ANY WARRANTY; without even the implied warranty of
4584+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4585+GNU General Public License for more details.
4586+
4587+You should have received a copy of the GNU General Public License
4588+along with this program. If not, see <http://www.gnu.org/licenses/>.
4589+
4590+"""
4591+import sys
4592+import time
4593+import re
4594+import configparser
4595+import shlex
4596+import subprocess
4597+import ast
4598+from argparse import (
4599+ ArgumentParser,
4600+ RawTextHelpFormatter
4601+)
4602+from subprocess import (
4603+ check_output,
4604+ CalledProcessError
4605+)
4606+
4607+
4608+def get_sdr(TOOL):
4609+ cmd = "{} sdr".format(TOOL)
4610+ sdr_return = subprocess.check_output(shlex.split(cmd), universal_newlines=True)
4611+ return sdr_return
4612+
4613+def parse_sdr(output):
4614+ output = output.strip()
4615+ output_1Line = output.split("\n")
4616+ data = {}
4617+
4618+ for line in output_1Line:
4619+ sub_value = {}
4620+ string_list = line.split("|")
4621+ name = string_list[0].strip()
4622+ sensor_output = string_list[1].strip()
4623+ sub_value.update({'output':sensor_output})
4624+ status = string_list[2].strip()
4625+ sub_value.update({'status':status})
4626+ data.update({name:sub_value})
4627+ return data
4628+
4629+def calculate_CPU_temp(data_dict, CPU_Therm_Margin_id, CPU_Tjmax_id):
4630+
4631+ if data_dict.get(CPU_Therm_Margin_id) and data_dict.get(CPU_Tjmax_id):
4632+ if data_dict.get(CPU_Therm_Margin_id).get('status') == 'ok' and data_dict.get(CPU_Tjmax_id).get('status') == 'ok':
4633+ P_Therm_Margin_output = data_dict.get(CPU_Therm_Margin_id).get('output')
4634+ CPU_Tjmax_output = data_dict.get(CPU_Tjmax_id).get('output')
4635+ P_Therm_Margin = re.search(r'[0-9-]+', P_Therm_Margin_output).group(0)
4636+ CPU_Tjmax = re.search(r'[0-9-]+', CPU_Tjmax_output).group(0)
4637+ CPU_temp = int(P_Therm_Margin)+int(CPU_Tjmax)
4638+ return str(CPU_temp)+' degrees C'
4639+ else:
4640+ return 'Error'
4641+ else:
4642+ return 'None'
4643+
4644+def ipmi_sdr(args):
4645+
4646+ flag = 0
4647+
4648+ tool_name = args.tool
4649+ if not tool_name:
4650+ print("No specified tool to use")
4651+ return 99
4652+
4653+ #IPMI/DCMI config file
4654+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
4655+ if not "config" in vars(args):
4656+ config_file = DEFAULT_CFG
4657+ else:
4658+ config_file = args.config
4659+ config = configparser.RawConfigParser()
4660+
4661+ try:
4662+ config.readfp(open(config_file))
4663+ except IOError:
4664+ print("No config file found")
4665+ return 10
4666+
4667+ try:
4668+ sensor_nick = config.options("Sensors")
4669+ except configparser.NoSectionError:
4670+ print("No Section: Sensors")
4671+ return 20
4672+
4673+ if sensor_nick:
4674+ sensor_list = []
4675+ for id in sensor_nick:
4676+ sensor_key = config.get("Sensors", id)
4677+ if sensor_key:
4678+ sensor_list.append(sensor_key)
4679+ else:
4680+ print("No Sensor ID specified in Config file")
4681+ return 30
4682+ else:
4683+ print("No key of Sensor ID specified in config file")
4684+ return 40
4685+
4686+ try:
4687+ sensor_data = get_sdr(tool_name)
4688+ time.sleep(5)
4689+ except CalledProcessError as ipmi_exception:
4690+ print("Failed executing ipmi, Reason: %s" % ipmi_exception)
4691+ return 50
4692+
4693+ try:
4694+ data = parse_sdr(sensor_data)
4695+ except:
4696+ print("Parsing output of sdr table error")
4697+ return 60
4698+
4699+ need_data = {}
4700+ for need_id in sensor_list:
4701+ if data.get(need_id):
4702+ need_value = data.get(need_id).get('output')
4703+ need_data.update({need_id:need_value})
4704+
4705+ if data.get(need_id).get('status') != 'ok':
4706+ flag = 1
4707+ else:
4708+
4709+ try:
4710+ CPUx_Temp = config.get("Sensors", "CPUx")
4711+ except configparser.NoOptionError:
4712+ CPUx_Temp = ''
4713+
4714+ try:
4715+ CPUy_Temp = config.get("Sensors", "CPUy")
4716+ except configparser.NoOptionError:
4717+ CPUy_Temp = ''
4718+
4719+ if need_id == CPUx_Temp:
4720+
4721+ try:
4722+ PxTM = config.get("SensorsForCPUTemp", "Px Therm Margin")
4723+ except configparser.NoOptionError:
4724+ PxTM = ''
4725+
4726+ try:
4727+ CPUx_Tjmax = config.get("SensorsForCPUTemp", "CPUx Tjmax")
4728+ except configparser.NoOptionError:
4729+ CPUx_Tjmax = ''
4730+
4731+ if PxTM and CPUx_Tjmax:
4732+ need_data.update({CPUx_Temp:calculate_CPU_temp(data, PxTM, CPUx_Tjmax)})
4733+ if calculate_CPU_temp(data, PxTM, CPUx_Tjmax) == 'None' or calculate_CPU_temp(data, PxTM, CPUx_Tjmax) == 'Error':
4734+ flag = 1
4735+ else:
4736+ flag = 1
4737+
4738+ elif need_id == CPUy_Temp:
4739+
4740+ try:
4741+ PyTM = config.get("SensorsForCPUTemp", "Py Therm Margin")
4742+ except configparser.NoOptionError:
4743+ PyTM = ''
4744+
4745+ try:
4746+ CPUy_Tjmax = config.get("SensorsForCPUTemp", "CPUy Tjmax")
4747+ except configparser.NoOptionError:
4748+ CPUy_Tjmax = ''
4749+
4750+
4751+ if PyTM and CPUy_Tjmax:
4752+ need_data.update({CPUy_Temp:calculate_CPU_temp(data, PyTM, CPUy_Tjmax)})
4753+ if calculate_CPU_temp(data, PyTM, CPUy_Tjmax) == 'None' or calculate_CPU_temp(data, PyTM, CPUy_Tjmax) == 'Error':
4754+ flag = 1
4755+ else:
4756+ flag = 1
4757+ else:
4758+ flag = 1
4759+
4760+ print("%s: %s" %(need_id, need_data.get(need_id)))
4761+
4762+ if flag == 1:
4763+ return 100
4764+ return 0
4765+
4766+def main():
4767+
4768+ intro_message = "Default config location is /etc/checkbox.d/bmc.cfg"
4769+ parser = ArgumentParser(description=intro_message, formatter_class=RawTextHelpFormatter)
4770+ parser.add_argument('--config', type=str, default="/etc/checkbox.d/bmc.cfg", help="Supply config file for sensor IDs parameters")
4771+ parser.add_argument('--tool', help="ipmitool or dcmitool")
4772+ args = parser.parse_args()
4773+ return ipmi_sdr(args)
4774+
4775+if __name__ == "__main__":
4776+ sys.exit(main())
4777+
4778
4779=== added file 'bin/ipmi_sensors_oob'
4780--- bin/ipmi_sensors_oob 1970-01-01 00:00:00 +0000
4781+++ bin/ipmi_sensors_oob 2015-08-14 22:03:31 +0000
4782@@ -0,0 +1,240 @@
4783+#!/usr/bin/env python3
4784+"""
4785+Copyright (C) 2010-2013 by Cloud Computing Center for Mobile Applications
4786+Industrial Technology Research Institute
4787+
4788+File Name
4789+ ipmi_sensors_oob
4790+
4791+Description
4792+ 1. Use ipmitool to monitor analog sensors in SDR table through OOB access.
4793+ 2. Criteria: the status of analog sensors should be "ok" and the data should not be null.
4794+
4795+Authors
4796+ Sophia Wu <Sophia.Wu@itri.org.tw>
4797+
4798+This program is free software: you can redistribute it and/or modify
4799+it under the terms of the GNU General Public License version 3,
4800+as published by the Free Software Foundation.
4801+
4802+This program is distributed in the hope that it will be useful,
4803+but WITHOUT ANY WARRANTY; without even the implied warranty of
4804+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4805+GNU General Public License for more details.
4806+
4807+You should have received a copy of the GNU General Public License
4808+along with this program. If not, see <http://www.gnu.org/licenses/>.
4809+
4810+"""
4811+import sys
4812+import time
4813+import re
4814+import configparser
4815+import shlex
4816+import subprocess
4817+import ast
4818+from argparse import (
4819+ ArgumentParser,
4820+ RawTextHelpFormatter
4821+)
4822+from subprocess import (
4823+ check_output,
4824+ CalledProcessError
4825+)
4826+
4827+def get_sdr_remote(host_ip, user, password):
4828+ cmd = "ipmitool -H {} -U {} -P {} sdr".format(host_ip, user, password)
4829+ sdr_return = subprocess.check_output(shlex.split(cmd), stderr=subprocess.STDOUT,
4830+ universal_newlines=True)
4831+ return sdr_return
4832+
4833+def parse_sdr(output):
4834+ output = output.strip()
4835+ output_1Line = output.split("\n")
4836+ data = {}
4837+
4838+ for line in output_1Line:
4839+ sub_value = {}
4840+ string_list = line.split("|")
4841+ name = string_list[0].strip()
4842+ sensor_output = string_list[1].strip()
4843+ sub_value.update({'output':sensor_output})
4844+ status = string_list[2].strip()
4845+ sub_value.update({'status':status})
4846+ data.update({name:sub_value})
4847+ return data
4848+
4849+def calculate_CPU_temp(data_dict, CPU_Therm_Margin_id, CPU_Tjmax_id):
4850+
4851+ if data_dict.get(CPU_Therm_Margin_id) and data_dict.get(CPU_Tjmax_id):
4852+ if data_dict.get(CPU_Therm_Margin_id).get('status') == 'ok' and data_dict.get(CPU_Tjmax_id).get('status') == 'ok':
4853+ P_Therm_Margin_output = data_dict.get(CPU_Therm_Margin_id).get('output')
4854+ CPU_Tjmax_output = data_dict.get(CPU_Tjmax_id).get('output')
4855+ P_Therm_Margin = re.search(r'[0-9-]+', P_Therm_Margin_output).group(0)
4856+ CPU_Tjmax = re.search(r'[0-9-]+', CPU_Tjmax_output).group(0)
4857+ CPU_temp = int(P_Therm_Margin)+int(CPU_Tjmax)
4858+ return str(CPU_temp)+' degrees C'
4859+ else:
4860+ return 'Error'
4861+ else:
4862+ return 'None'
4863+
4864+def ipmi_sdr(args):
4865+
4866+ flag = 0
4867+ #IPMI config file
4868+ DEFAULT_CFG = "/etc/checkbox.d/bmc.cfg"
4869+ if not "config" in vars(args):
4870+ config_file = DEFAULT_CFG
4871+ else:
4872+ config_file = args.config
4873+
4874+ config = configparser.RawConfigParser()
4875+
4876+ try:
4877+ config.readfp(open(config_file))
4878+ except IOError:
4879+ print("No config file found")
4880+ return 10
4881+
4882+ try:
4883+ sensor_nick = config.options("Sensors")
4884+ except configparser.NoSectionError:
4885+ print("No Section: Sensors")
4886+ return 20
4887+
4888+ if sensor_nick:
4889+ sensor_list = []
4890+ for id in sensor_nick:
4891+ sensor_key = config.get("Sensors", id)
4892+ if sensor_key:
4893+ sensor_list.append(sensor_key)
4894+ else:
4895+ print("No Sensor ID specified in Config file")
4896+ return 30
4897+ else:
4898+ print("No key of Sensor ID specified in config file")
4899+ return 40
4900+
4901+ try:
4902+ targets_options = config.options('Targets')
4903+ targets_list = []
4904+ for target_key in targets_options:
4905+ targets_list.append(config.get('Targets', target_key))
4906+ if not targets_list:
4907+ print("Invalid or Empty targets")
4908+ return 60
4909+ except configparser.Error:
4910+ print("Invalid or Empty targets")
4911+ return 60
4912+
4913+ try:
4914+ user_value = config.get("Account", "USER")
4915+ password_value = config.get("Account", "PASSWORD")
4916+ except configparser.NoOptionError:
4917+ print("Invalid or Empty credential info")
4918+ return 70
4919+
4920+ for tg in targets_list:
4921+
4922+ if not tg or not user_value or not password_value:
4923+ print("Require Taget IP, Account(USER/PASSWORD) for IPMI out-of-band access")
4924+ return 80
4925+ else:
4926+
4927+ print("SUT =", tg)
4928+ print("USER =", user_value)
4929+ print("PASSWORD =", password_value)
4930+
4931+ try:
4932+ sensor_data = get_sdr_remote(tg, user_value, password_value)
4933+ time.sleep(5)
4934+ except CalledProcessError as ipmi_exception:
4935+ print("Failed executing ipmi, Reason: %s" % ipmi_exception)
4936+ return 50
4937+
4938+ try:
4939+ data = parse_sdr(sensor_data)
4940+ except:
4941+ print("Parsing output of sdr table error")
4942+ flag = 1
4943+ continue
4944+
4945+ need_data = {}
4946+ for need_id in sensor_list:
4947+
4948+ if data.get(need_id):
4949+ need_value = data.get(need_id).get('output')
4950+ need_data.update({need_id:need_value})
4951+
4952+ if data.get(need_id).get('status') != 'ok':
4953+ flag = 1
4954+ else:
4955+
4956+ try:
4957+ CPUx_Temp = config.get("Sensors", "CPUx")
4958+ except configparser.NoOptionError:
4959+ CPUx_Temp = ''
4960+
4961+ try:
4962+ CPUy_Temp = config.get("Sensors", "CPUy")
4963+ except configparser.NoOptionError:
4964+ CPUy_Temp = ''
4965+
4966+ if need_id == CPUx_Temp:
4967+
4968+ try:
4969+ PxTM = config.get("SensorsForCPUTemp", "Px Therm Margin")
4970+ except configparser.NoOptionError:
4971+ PxTM = ''
4972+
4973+ try:
4974+ CPUx_Tjmax = config.get("SensorsForCPUTemp", "CPUx Tjmax")
4975+ except configparser.NoOptionError:
4976+ CPUx_Tjmax = ''
4977+
4978+ if PxTM and CPUx_Tjmax:
4979+ need_data.update({CPUx_Temp:calculate_CPU_temp(data, PxTM, CPUx_Tjmax)})
4980+ if calculate_CPU_temp(data, PxTM, CPUx_Tjmax) == 'None' or calculate_CPU_temp(data, PxTM, CPUx_Tjmax) == 'Error':
4981+ flag = 1
4982+ else:
4983+ flag = 1
4984+
4985+ elif need_id == CPUy_Temp:
4986+
4987+ try:
4988+ PyTM = config.get("SensorsForCPUTemp", "Py Therm Margin")
4989+ except configparser.NoOptionError:
4990+ PyTM = ''
4991+
4992+ try:
4993+ CPUy_Tjmax = config.get("SensorsForCPUTemp", "CPUy Tjmax")
4994+ except configparser.NoOptionError:
4995+ CPUy_Tjmax = ''
4996+
4997+ if PyTM and CPUy_Tjmax:
4998+ need_data.update({CPUy_Temp:calculate_CPU_temp(data, PyTM, CPUy_Tjmax)})
4999+ if calculate_CPU_temp(data, PyTM, CPUy_Tjmax) == 'None' or calculate_CPU_temp(data, PyTM, CPUy_Tjmax) == 'Error':
5000+ flag = 1
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches