Merge lp:~rodsmith/checkbox/smart-for-dmraid into lp:checkbox
- smart-for-dmraid
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Jeff Lane | ||||
Approved revision: | 4161 | ||||
Merged at revision: | 4175 | ||||
Proposed branch: | lp:~rodsmith/checkbox/smart-for-dmraid | ||||
Merge into: | lp:checkbox | ||||
Diff against target: |
419 lines (+240/-57) 2 files modified
providers/plainbox-provider-checkbox/bin/disk_smart (+189/-51) providers/plainbox-provider-resource-generic/bin/block_device_resource (+51/-6) |
||||
To merge this branch: | bzr merge lp:~rodsmith/checkbox/smart-for-dmraid | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jeff Lane | Approve | ||
Review via email: mp+282457@code.launchpad.net |
Commit message
Description of the change
Add support for several hardware RAID types to SMART test. The changes should not affect tests on non-RAID systems; but on supported RAID systems, the test will now run and pass if all disks on a Linux device (/dev/sda, etc.) pass. If any one RAID disk fails, the entire device will fail. See https:/
Sylvain Pineau (sylvain-pineau) wrote : | # |
The attempt to merge lp:~rodsmith/checkbox/smart-for-dmraid into lp:checkbox failed. Below is the output from the failed tests.
[precise] starting container
[precise] Unable to start ephemeral container!
[precise] stdout:
[precise] stderr: http://
[precise] NOTE: unable to execute tests, marked as failed
[precise] Destroying failed container to reclaim resources
[trusty] starting container
[trusty] (timing) 0.07user 0.08system 0:05.32elapsed 2%CPU (0avgtext+0avgdata 10248maxresident)k
[trusty] (timing) 0inputs+32outputs (0major+
[trusty] provisioning container
[trusty] (timing) 53.95user 15.48system 1:18.15elapsed 88%CPU (0avgtext+0avgdata 61780maxresident)k
[trusty] (timing) 0inputs+
[trusty-testing] Starting tests...
Found a test script: ./checkbox-
[trusty-testing] container-
[trusty-testing] (timing) 0.75user 0.15system 0:00.92elapsed 98%CPU (0avgtext+0avgdata 31932maxresident)k
[trusty-testing] (timing) 0inputs+1088outputs (0major+
Found a test script: ./checkbox-
[trusty-testing] container-
[trusty-testing] (timing) 25.20user 0.18system 0:25.44elapsed 99%CPU (0avgtext+0avgdata 106572maxresident)k
[trusty-testing] (timing) 0inputs+1072outputs (0major+
Found a test script: ./checkbox-
[trusty-testing] container-
[trusty-testing] (timing) 0.01user 0.01system 0:00.03elapsed 78%CPU (0avgtext+0avgdata 2180maxresident)k
[trusty-testing] (timing) 0inputs+0outputs (0major+
Found a test script: ./plainbox/
[trusty-testing] container-
[trusty-testing] (timing) 0.96user 0.06system 0:01.04elapsed 98%CPU (0avgtext+0avgdata 29420maxresident)k
[trusty-testing] (timing) 0inputs+48outputs (0major+
Found a test script: ./plainbox/
[trusty-testing] 001-container-
[trusty-testing] (timing) 0.42user 0.06system 0:00.49elapsed 97%CPU (0avgtext+0avgdata 19096maxresident)k
[trusty-testing] (timing) 0inputs+96outputs (0major+
Found a test script: ./plainbox/
[trusty-testing] container-
[trusty-testing] (timing) 50.91user 1.01system 0:52.15elapsed 99%CPU (0avgtext+0avgdata 95620maxresident)k
[trusty-testing] (timing) 0inputs+2712outputs (0major+
Found a test script: ./plainbox/
[trusty-testing] container-
[trusty-testing] (timing) 125.20user 0.40system 2:05.82elapsed 99%CPU (0avgtext+0avgdata 115680maxresident)k
[trusty-testing] (timing) 0...
Jeff Lane (bladernr) wrote : | # |
Ok. lets try again...
Sylvain Pineau (sylvain-pineau) wrote : | # |
The attempt to merge lp:~rodsmith/checkbox/smart-for-dmraid into lp:checkbox failed. Below is the output from the failed tests.
[precise] starting container
[precise] (timing) 0.08user 0.08system 0:05.53elapsed 3%CPU (0avgtext+0avgdata 10256maxresident)k
[precise] (timing) 0inputs+32outputs (0major+
[precise] provisioning container
[precise] (timing) 42.31user 12.01system 1:02.83elapsed 86%CPU (0avgtext+0avgdata 95724maxresident)k
[precise] (timing) 0inputs+
[precise-testing] Starting tests...
Found a test script: ./checkbox-
[precise-testing] container-
[precise-testing] (timing) 0.69user 0.11system 0:00.81elapsed 98%CPU (0avgtext+0avgdata 47532maxresident)k
[precise-testing] (timing) 0inputs+1336outputs (0major+
Found a test script: ./checkbox-
[precise-testing] container-
[precise-testing] (timing) 23.83user 0.19system 0:24.13elapsed 99%CPU (0avgtext+0avgdata 150596maxresident)k
[precise-testing] (timing) 0inputs+1328outputs (0major+
Found a test script: ./checkbox-
[precise-testing] container-
[precise-testing] (timing) 0.01user 0.01system 0:00.03elapsed 84%CPU (0avgtext+0avgdata 2180maxresident)k
[precise-testing] (timing) 0inputs+8outputs (0major+
Found a test script: ./plainbox/
[precise-testing] container-
[precise-testing] (timing) 0.99user 0.12system 0:01.13elapsed 98%CPU (0avgtext+0avgdata 46960maxresident)k
[precise-testing] (timing) 0inputs+64outputs (0major+
Found a test script: ./plainbox/
[precise-testing] 001-container-
[precise-testing] (timing) 0.28user 0.09system 0:00.39elapsed 97%CPU (0avgtext+0avgdata 20240maxresident)k
[precise-testing] (timing) 0inputs+96outputs (0major+
Found a test script: ./plainbox/
[precise-testing] container-
[precise-testing] (timing) 55.59user 1.44system 0:57.21elapsed 99%CPU (0avgtext+0avgdata 195980maxresident)k
[precise-testing] (timing) 0inputs+3304outputs (0major+
Found a test script: ./plainbox/
[precise-testing] container-
[precise-testing] (timing) 141.13user 0.61system 2:22.04elapsed 99%CPU (0avgtext+0avgdata 179064maxresident)k
[precise-testing] (timing) 0inputs+
Found a test script: ./plainbox/
[precise-testing] container-
[precise-testing] (ti...
Jeff Lane (bladernr) wrote : | # |
Try again... Tarmac is on a roll
Preview Diff
1 | === modified file 'providers/plainbox-provider-checkbox/bin/disk_smart' |
2 | --- providers/plainbox-provider-checkbox/bin/disk_smart 2016-01-11 21:50:37 +0000 |
3 | +++ providers/plainbox-provider-checkbox/bin/disk_smart 2016-01-13 16:02:11 +0000 |
4 | @@ -77,6 +77,9 @@ |
5 | from subprocess import CalledProcessError |
6 | from argparse import ArgumentParser |
7 | |
8 | +# NOTE: If raid_types changes, also change it in block_device_resource script! |
9 | +raid_types = ["megaraid", "cciss", "3ware", "areca"] |
10 | + |
11 | |
12 | class ListHandler(logging.StreamHandler): |
13 | |
14 | @@ -97,38 +100,100 @@ |
15 | logging.StreamHandler.emit(self, record) |
16 | |
17 | |
18 | -def enable_smart(disk): |
19 | +def enable_smart(disk, raid_element, raid_type): |
20 | """Log data and, if necessary, enable SMART on the specified disk. |
21 | |
22 | See also smart_support() in block_device_resource script. |
23 | :param disk: |
24 | disk device filename (e.g., /dev/sda) |
25 | + :param raid_element: |
26 | + element number to enable in RAID array; undefined if not a RAID device |
27 | + :param raid_type: |
28 | + type of raid device (none, megaraid, etc.) |
29 | :returns: |
30 | True if enabling smart was successful, False otherwise |
31 | """ |
32 | # Check with smartctl to record basic SMART data on the disk |
33 | - command = 'smartctl -i %s' % disk |
34 | + if raid_type == 'none': |
35 | + command = 'smartctl -i {}'.format(disk) |
36 | + logging.debug('SMART Info for disk {}'.format(disk)) |
37 | + else: |
38 | + command = 'smartctl -i {} -d {},{}'.format(disk, raid_type, |
39 | + raid_element) |
40 | + logging.debug('SMART Info for disk {}, element {}'. |
41 | + format(disk, raid_element)) |
42 | diskinfo_bytes = (Popen(command, stdout=PIPE, shell=True) |
43 | .communicate()[0]) |
44 | diskinfo = (diskinfo_bytes.decode(encoding='utf-8', errors='ignore') |
45 | .splitlines()) |
46 | - logging.debug('SMART Info for disk %s', disk) |
47 | logging.debug(diskinfo) |
48 | if len(diskinfo) > 2 and not any("SMART support is" in s and "Enabled" |
49 | in s for s in diskinfo): |
50 | logging.debug('SMART disabled; attempting to enable it.') |
51 | - command = 'smartctl -s on %s' % disk |
52 | + if raid_type == 'none': |
53 | + command = 'smartctl -s on {}'.format(disk) |
54 | + else: |
55 | + command = ('smartctl -s on {} -d {},{}'. |
56 | + format(disk, raid_type, raid_element)) |
57 | try: |
58 | check_call(shlex.split(command)) |
59 | return True |
60 | except CalledProcessError: |
61 | + if raid_type == 'none': |
62 | + logging.warning('SMART could not be enabled on {}'. |
63 | + format(disk)) |
64 | + else: |
65 | + logging.warning('SMART could not be enabled on {}, element ' |
66 | + '{}'.format(disk, raid_element)) |
67 | return False |
68 | return True |
69 | |
70 | |
71 | -def run_smart_test(disk, type='short'): |
72 | - ctl_command = 'smartctl -t %s %s' % (type, disk) |
73 | - logging.debug('Beginning test with %s', ctl_command) |
74 | +def count_raid_disks(disk): |
75 | + """Count the disks in a RAID array. |
76 | + |
77 | + :param disk: |
78 | + Disk device filename (e.g., /dev/sda) |
79 | + :returns: |
80 | + Number of disks in array (0 for non-RAID disk) |
81 | + Type of RAID (none, megaraid, 3ware, areca, or cciss; note that only |
82 | + none and megaraid are tested, as of Jan. 2016) |
83 | + """ |
84 | + raid_element = 0 |
85 | + raid_type = 'none' |
86 | + command = 'smartctl -i {}'.format(disk) |
87 | + diskinfo_bytes = (Popen(command, stdout=PIPE, shell=True) |
88 | + .communicate()[0]) |
89 | + diskinfo = (diskinfo_bytes.decode(encoding='utf-8', errors='ignore') |
90 | + .splitlines()) |
91 | + for type in raid_types: |
92 | + if any("-d {},N".format(type) in s for s in diskinfo): |
93 | + logging.info('Found RAID controller of type {}'.format(type)) |
94 | + raid_type = type |
95 | + break |
96 | + if raid_type != 'none': |
97 | + # This is a hardware RAID controller, so count individual disks.... |
98 | + disk_exists = True |
99 | + while disk_exists: |
100 | + command = ('smartctl -i {} -d {},{}'. |
101 | + format(disk, raid_type, raid_element)) |
102 | + try: |
103 | + check_output(shlex.split(command)) |
104 | + raid_element += 1 |
105 | + except CalledProcessError: |
106 | + disk_exists = False |
107 | + logging.info("Counted {} RAID disks on {}\n". |
108 | + format(raid_element, disk)) |
109 | + return raid_element, raid_type |
110 | + |
111 | + |
112 | +def initiate_smart_test(disk, raid_element, raid_type, type='short'): |
113 | + if raid_type == 'none': |
114 | + ctl_command = 'smartctl -t {} {}'.format(type, disk) |
115 | + else: |
116 | + ctl_command = ('smartctl -t {} {} -d {},{}'. |
117 | + format(type, disk, raid_type, raid_element)) |
118 | + logging.debug('Beginning test with {}'.format(ctl_command)) |
119 | |
120 | smart_proc = Popen(ctl_command, stderr=PIPE, stdout=PIPE, |
121 | universal_newlines=True, shell=True) |
122 | @@ -139,11 +204,17 @@ |
123 | return smart_proc.returncode |
124 | |
125 | |
126 | -def get_smart_entries(disk, type='selftest'): |
127 | +def get_smart_entries(disk, raid_element, raid_type, type='selftest'): |
128 | entries = [] |
129 | try: |
130 | - stdout = check_output(['smartctl', '-l', type, disk], |
131 | - universal_newlines=True) |
132 | + if raid_type == 'none': |
133 | + stdout = check_output(['smartctl', '-l', type, disk], |
134 | + universal_newlines=True) |
135 | + else: |
136 | + stdout = check_output(['smartctl', '-l', type, disk, |
137 | + '-d', '{},{}'. |
138 | + format(raid_type, raid_element)], |
139 | + universal_newlines=True) |
140 | returncode = 0 |
141 | except CalledProcessError as err: |
142 | stdout = err.output |
143 | @@ -185,10 +256,14 @@ |
144 | return entries, returncode |
145 | |
146 | |
147 | -# Returns True if an "in-progress" message is found in the smartctl |
148 | -# output, False if such a message is not found. In the former case, |
149 | -# the in-progress message entries are logged. |
150 | def in_progress(current_entries): |
151 | + """Check to see if the test is in progress. |
152 | + |
153 | + :param current_entries: |
154 | + Output of smartctl command to be checked for status indicator. |
155 | + :returns: |
156 | + True if an "in-progress" message is found, False otherwise |
157 | + """ |
158 | statuses = [entry for entry in current_entries |
159 | if isinstance(entry, dict) |
160 | and 'status' in entry |
161 | @@ -205,13 +280,28 @@ |
162 | return False |
163 | |
164 | |
165 | -# Wait for SMART test to complete; return status and return code. |
166 | -# Note that different disks return different types of values. |
167 | -# Some return no status reports while a test is ongoing; others |
168 | -# show a status line at the START of the list of tests, and |
169 | -# others show a status line at the END of the list of tests |
170 | -# (and then move it to the top once the tests are done). |
171 | -def poll_for_status(args, disk, previous_entries): |
172 | +def poll_for_status(args, disk, raid_element, raid_type, previous_entries): |
173 | + """Poll a disk for its SMART status. |
174 | + |
175 | + Wait for SMART test to complete; return status and return code. |
176 | + Note that different disks return different types of values. |
177 | + Some return no status reports while a test is ongoing; others |
178 | + show a status line at the START of the list of tests, and |
179 | + others show a status line at the END of the list of tests |
180 | + (and then move it to the top once the tests are done). |
181 | + :param args: |
182 | + Script's command-line arguments |
183 | + :param disk: |
184 | + Disk device (e.g., /dev/sda) |
185 | + :param raid_element: |
186 | + RAID disk number (undefined for non-RAID disk) |
187 | + :param raid_type: |
188 | + Type of RAID device (megaraid, etc.) |
189 | + :param previous_entries: |
190 | + Previous SMART output; used to spot a change |
191 | + :returns: |
192 | + Current output and return code |
193 | + """ |
194 | # Priming read... this is here in case our test is finished or fails |
195 | # immediate after it beginsAccording to. |
196 | logging.debug('Polling selftest.log for status') |
197 | @@ -221,7 +311,8 @@ |
198 | # Poll every sleep seconds until test is complete$ |
199 | time.sleep(args.sleep) |
200 | |
201 | - current_entries, returncode = get_smart_entries(disk) |
202 | + current_entries, returncode = get_smart_entries(disk, raid_element, |
203 | + raid_type) |
204 | if current_entries != previous_entries: |
205 | if not in_progress(current_entries): |
206 | keep_going = False |
207 | @@ -239,8 +330,69 @@ |
208 | return current_entries[0]['status'], returncode |
209 | |
210 | |
211 | +def run_smart_test(args, disk, raid_element, raid_type): |
212 | + """Run a test on a single disk device (possibly multiple RAID elements). |
213 | + |
214 | + :param args: |
215 | + Command-line arguments passed to script |
216 | + :param disk: |
217 | + Disk device filename (e.g., /dev/sda) |
218 | + :param raid_element: |
219 | + Number of RAID array element or undefined for non-RAID disk |
220 | + :param raid_type: |
221 | + Type of RAID device (e.g., megaraid) |
222 | + :returns: |
223 | + True for success, False for failure |
224 | + """ |
225 | + previous_entries, returncode = get_smart_entries(disk, raid_element, |
226 | + raid_type) |
227 | + if raid_type == 'none': |
228 | + logging.info("Starting SMART self-test on {}".format(disk)) |
229 | + else: |
230 | + logging.info("Starting SMART self-test on {}, element {}". |
231 | + format(disk, raid_element)) |
232 | + if initiate_smart_test(disk, raid_element, raid_type) != 0: |
233 | + logging.error("Error reported during smartctl test") |
234 | + return False |
235 | + |
236 | + if len(previous_entries) > 20: |
237 | + # Abort the previous instance |
238 | + # so that polling can identify the difference |
239 | + initiate_smart_test(disk, raid_element, raid_type) |
240 | + previous_entries, returncode = get_smart_entries(disk, raid_element, |
241 | + raid_type) |
242 | + |
243 | + status, returncode = poll_for_status(args, disk, raid_element, raid_type, |
244 | + previous_entries) |
245 | + |
246 | + if returncode != 0: |
247 | + log, returncode = get_smart_entries(disk, raid_element, raid_type) |
248 | + if raid_type == 'none': |
249 | + logging.error("FAIL: SMART Self-Test appears to have failed " |
250 | + "for some reason. Run 'sudo smartctl -l selftest " |
251 | + "{}' to see the SMART log".format(disk)) |
252 | + else: |
253 | + logging.error("FAIL: SMART Self-Test appears to have failed " |
254 | + "for some reason. Run 'sudo smartctl -l selftest " |
255 | + "{} -d {},{}' to see the SMART log". |
256 | + format(disk, raid_type, raid_element)) |
257 | + logging.debug("Last smartctl return code: %d", returncode) |
258 | + logging.debug("Last smartctl run status: %s", status) |
259 | + return False |
260 | + else: |
261 | + if raid_type == 'none': |
262 | + logging.info("PASS: SMART Self-Test on {} completed without error". |
263 | + format(disk)) |
264 | + else: |
265 | + logging.info("PASS: SMART Self-Test on {}, element {} completed " |
266 | + "without error\n".format(disk, raid_element)) |
267 | + return True |
268 | + |
269 | + |
270 | def main(): |
271 | - description = 'Tests that SMART capabilities on disks that support SMART function.' |
272 | + """Test SMART capabilities on disks that support SMART functions.""" |
273 | + description = ('Tests SMART capabilities on disks that support ' |
274 | + 'SMART functions.') |
275 | parser = ArgumentParser(description=description) |
276 | parser.add_argument('-b', '--block-dev', |
277 | metavar='DISK', |
278 | @@ -278,35 +430,21 @@ |
279 | parser.error("You must be root to run this program") |
280 | |
281 | disk = args.block_dev |
282 | - if not enable_smart(disk): |
283 | - logging.warning('SMART could not be enabled on %s' % disk) |
284 | - return 1 |
285 | - |
286 | - # Initiate a self test and start polling until the test is done |
287 | - previous_entries, returncode = get_smart_entries(disk) |
288 | - logging.info("Starting SMART self-test on %s", disk) |
289 | - if run_smart_test(disk) != 0: |
290 | - logging.error("Error reported during smartctl test") |
291 | - return 1 |
292 | - |
293 | - if len(previous_entries) > 20: |
294 | - # Abort the previous instance |
295 | - # so that polling can identify the difference |
296 | - run_smart_test(disk) |
297 | - previous_entries, returncode = get_smart_entries(disk) |
298 | - |
299 | - status, returncode = poll_for_status(args, disk, previous_entries) |
300 | - |
301 | - if returncode != 0: |
302 | - log, returncode = get_smart_entries(disk) |
303 | - logging.error("FAIL: SMART Self-Test appears to have failed for some reason. " |
304 | - "Run 'sudo smartctl -l selftest %s' to see the SMART log", |
305 | - disk) |
306 | - logging.debug("Last smartctl return code: %d", returncode) |
307 | - logging.debug("Last smartctl run status: %s", status) |
308 | - return 1 |
309 | - else: |
310 | - logging.info("PASS: SMART Self-Test completed without error") |
311 | + num_disks, raid_type = count_raid_disks(disk) |
312 | + if num_disks == 0: |
313 | + success = enable_smart(disk, -1, raid_type) |
314 | + success = success and run_smart_test(args, disk, -1, raid_type) |
315 | + else: |
316 | + success = True |
317 | + for raid_element in range(0, num_disks): |
318 | + if enable_smart(disk, raid_element, raid_type): |
319 | + success = (run_smart_test(args, disk, raid_element, raid_type) |
320 | + and success) |
321 | + else: |
322 | + success = False |
323 | + if success is False: |
324 | + return 1 |
325 | + else: |
326 | return 0 |
327 | |
328 | |
329 | |
330 | === modified file 'providers/plainbox-provider-resource-generic/bin/block_device_resource' |
331 | --- providers/plainbox-provider-resource-generic/bin/block_device_resource 2016-01-11 23:52:28 +0000 |
332 | +++ providers/plainbox-provider-resource-generic/bin/block_device_resource 2016-01-13 16:02:11 +0000 |
333 | @@ -2,17 +2,18 @@ |
334 | |
335 | import os |
336 | import re |
337 | +import shlex |
338 | from glob import glob |
339 | -from subprocess import Popen, PIPE |
340 | +from subprocess import Popen, PIPE, check_output, CalledProcessError |
341 | |
342 | rootdir_pattern = re.compile('^.*?/devices') |
343 | |
344 | +# NOTE: If raid_types changes, also change it in disk_smart script! |
345 | +raid_types = ["megaraid", "cciss", "3ware", "areca"] |
346 | + |
347 | |
348 | def device_state(name): |
349 | - """ |
350 | - Follow pmount policy to determine whether a device is removable |
351 | - or internal. |
352 | - """ |
353 | + """Follow pmount policy to find if a device is removable or internal.""" |
354 | with open('/sys/block/%s/device/block/%s/removable' % (name, name), |
355 | "rt") as f: |
356 | if f.read(1) == '1': |
357 | @@ -69,10 +70,49 @@ |
358 | return 'no' |
359 | |
360 | |
361 | +def smart_support_raid(name, raid_type): |
362 | + """Check for availability of SMART support in a RAID device. |
363 | + |
364 | + See also count_raid_disks() in disk_smart script. |
365 | + :param name: |
366 | + disk device filename within /dev (e.g., sda) |
367 | + :param raid_type: |
368 | + type of raid device (e.g., megaraid, 3ware, etc. -- codes used |
369 | + by smartctl) |
370 | + :returns: |
371 | + 'True' or 'False' as string (for return to Checkbox) |
372 | + """ |
373 | + supported = 'False' |
374 | + disk_num = 0 |
375 | + disk_exists = True |
376 | + # Loop through all disks in array to verify that SMART is available on |
377 | + # at least one of them. Note that if there's a mix of supported and |
378 | + # unsupported, this test returns 'True', which will result in a failure |
379 | + # of disk_smart. This is by design, since such a mix is likely an assembly |
380 | + # error by the manufacturer. |
381 | + while disk_exists: |
382 | + command = 'smartctl -i /dev/{} -d {},{}'.format(name, raid_type, |
383 | + disk_num) |
384 | + # Return 'True' if the output (diskinfo) includes |
385 | + # "SMART support is.*Available", and terminate check when a failure |
386 | + # is found or when number of disks rises above level supported by |
387 | + # smartctl (which likely indicates a bug). |
388 | + try: |
389 | + diskinfo = (check_output(shlex.split(command)).decode('utf-8'). |
390 | + splitlines()) |
391 | + if any("SMART support is" in s and "Available" in s for |
392 | + s in diskinfo): |
393 | + supported = 'True' |
394 | + disk_num += 1 |
395 | + except CalledProcessError: |
396 | + disk_exists = False |
397 | + return supported |
398 | + |
399 | + |
400 | def smart_support(name): |
401 | """Check for availability of SMART support in the device. |
402 | |
403 | - See also enable_smart() in disk_smart script. |
404 | + See also count_raid_disks() in disk_smart script. |
405 | :param name: |
406 | disk device filename within /dev (e.g., sda) |
407 | :returns: |
408 | @@ -92,6 +132,11 @@ |
409 | if any("SMART support is" in s and "Available" in s |
410 | for s in diskinfo): |
411 | supported = 'True' |
412 | + else: |
413 | + for type in raid_types: |
414 | + if any("-d {},N".format(type) in s for s in diskinfo): |
415 | + supported = smart_support_raid(name, type) |
416 | + break |
417 | return supported |
418 | |
419 | for path in glob('/sys/block/*/device'): |
Thanks