Merge lp:~sylvain-pineau/checkbox/fix-1458462 into lp:checkbox

Proposed by Sylvain Pineau
Status: Merged
Approved by: Sylvain Pineau
Approved revision: 4201
Merged at revision: 4200
Proposed branch: lp:~sylvain-pineau/checkbox/fix-1458462
Merge into: lp:checkbox
Diff against target: 192 lines (+58/-23)
1 file modified
providers/plainbox-provider-checkbox/bin/removable_storage_test (+58/-23)
To merge this branch: bzr merge lp:~sylvain-pineau/checkbox/fix-1458462
Reviewer Review Type Date Requested Status
Pierre Equoy Approve
Checkbox Developers Pending
Review via email: mp+284791@code.launchpad.net

Description of the change

Fixes the linked bug where the removable storage test was run on internal eMMC drives.

We are now checking the / mount point using lsblk to discard partitions belonging to the same drive.

To post a comment you must log in.
Revision history for this message
Pierre Equoy (pieq) wrote :

+1

It works well on the two devices I tested it on, one with a NVMe drive + HDD (and a SD card reader), one with eMMC drive (and a micro SD card reader).

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'providers/plainbox-provider-checkbox/bin/removable_storage_test'
--- providers/plainbox-provider-checkbox/bin/removable_storage_test 2014-10-19 18:18:41 +0000
+++ providers/plainbox-provider-checkbox/bin/removable_storage_test 2016-02-02 20:32:54 +0000
@@ -6,6 +6,8 @@
6import hashlib6import hashlib
7import logging7import logging
8import os8import os
9import re
10import shlex
9import subprocess11import subprocess
10import sys12import sys
11import tempfile13import tempfile
@@ -26,6 +28,7 @@
26from checkbox_support.parsers.udevadm import CARD_READER_RE28from checkbox_support.parsers.udevadm import CARD_READER_RE
27from checkbox_support.parsers.udevadm import GENERIC_RE29from checkbox_support.parsers.udevadm import GENERIC_RE
28from checkbox_support.parsers.udevadm import FLASH_RE30from checkbox_support.parsers.udevadm import FLASH_RE
31from checkbox_support.parsers.udevadm import find_pkname_is_root_mountpoint
29from checkbox_support.udev import get_interconnect_speed32from checkbox_support.udev import get_interconnect_speed
30from checkbox_support.udev import get_udev_block_devices33from checkbox_support.udev import get_udev_block_devices
31from checkbox_support.udev import get_udev_xhci_devices34from checkbox_support.udev import get_udev_xhci_devices
@@ -97,7 +100,7 @@
97class DiskTest():100class DiskTest():
98 ''' Class to contain various methods for testing removable disks '''101 ''' Class to contain various methods for testing removable disks '''
99102
100 def __init__(self, device, memorycard):103 def __init__(self, device, memorycard, lsblkcommand):
101 self.rem_disks = {} # mounted before the script running104 self.rem_disks = {} # mounted before the script running
102 self.rem_disks_nm = {} # not mounted before the script running105 self.rem_disks_nm = {} # not mounted before the script running
103 self.rem_disks_memory_cards = {}106 self.rem_disks_memory_cards = {}
@@ -106,8 +109,10 @@
106 # LP: #1313581, TODO: extend to be rem_disks_driver109 # LP: #1313581, TODO: extend to be rem_disks_driver
107 self.rem_disks_xhci = {}110 self.rem_disks_xhci = {}
108 self.data = ''111 self.data = ''
112 self.lsblk = ''
109 self.device = device113 self.device = device
110 self.memorycard = memorycard114 self.memorycard = memorycard
115 self._run_lsblk(lsblkcommand)
111 self._probe_disks()116 self._probe_disks()
112117
113 def read_file(self, source):118 def read_file(self, source):
@@ -145,6 +150,24 @@
145 logging.error("Unable to remove tempfile %s", target)150 logging.error("Unable to remove tempfile %s", target)
146 logging.error(" %s", exc)151 logging.error(" %s", exc)
147152
153 def _find_parent(self, device):
154 if self.lsblk:
155 pattern = re.compile('KNAME="(?P<KNAME>.*)" '
156 'TYPE="(?P<TYPE>.*)" '
157 'MOUNTPOINT="(?P<MOUNTPOINT>.*)"')
158 for line in self.lsblk.splitlines():
159 m = pattern.match(line)
160 if m and device.startswith(m.group('KNAME')):
161 return m.group('KNAME')
162 return False
163
164 def _run_lsblk(self, lsblkcommand):
165 try:
166 self.lsblk = subprocess.check_output(shlex.split(lsblkcommand),
167 universal_newlines=True)
168 except subprocess.CalledProcessError as exc:
169 raise SystemExit(exc)
170
148 def _probe_disks(self):171 def _probe_disks(self):
149 """172 """
150 Internal method used to probe for available disks173 Internal method used to probe for available disks
@@ -223,6 +246,9 @@
223 # Get the block device pathname,246 # Get the block device pathname,
224 # to avoid the confusion, this is something like /dev/sdbX247 # to avoid the confusion, this is something like /dev/sdbX
225 dev_file = udev_device.get_device_file()248 dev_file = udev_device.get_device_file()
249 parent = self._find_parent(dev_file.replace('/dev/', ''))
250 if parent and find_pkname_is_root_mountpoint(parent, self.lsblk):
251 continue
226 # Get the list of mount points of this block device252 # Get the list of mount points of this block device
227 mount_points = (253 mount_points = (
228 udisks2_object[UDISKS2_FILESYSTEM_INTERFACE]['MountPoints'])254 udisks2_object[UDISKS2_FILESYSTEM_INTERFACE]['MountPoints'])
@@ -280,15 +306,15 @@
280 parent_vendor = parent_props.Get(udisks, "DriveVendor")306 parent_vendor = parent_props.Get(udisks, "DriveVendor")
281 parent_media = parent_props.Get(udisks, "DriveMedia")307 parent_media = parent_props.Get(udisks, "DriveMedia")
282 if self.memorycard:308 if self.memorycard:
283 if (dev_bus != 'sdio'309 if (dev_bus != 'sdio' and not
284 and not FLASH_RE.search(parent_media)310 FLASH_RE.search(parent_media) and not
285 and not CARD_READER_RE.search(parent_model)311 CARD_READER_RE.search(parent_model) and not
286 and not GENERIC_RE.search(parent_vendor)):312 GENERIC_RE.search(parent_vendor)):
287 continue313 continue
288 else:314 else:
289 if (FLASH_RE.search(parent_media)315 if (FLASH_RE.search(parent_media) or
290 or CARD_READER_RE.search(parent_model)316 CARD_READER_RE.search(parent_model) or
291 or GENERIC_RE.search(parent_vendor)):317 GENERIC_RE.search(parent_vendor)):
292 continue318 continue
293 dev_file = str(device_props.Get(udisks, "DeviceFile"))319 dev_file = str(device_props.Get(udisks, "DeviceFile"))
294 dev_speed = str(device_props.Get(udisks,320 dev_speed = str(device_props.Get(udisks,
@@ -376,9 +402,11 @@
376 # then compare this pci slot name to the other402 # then compare this pci slot name to the other
377 dl = devpath.split('/')403 dl = devpath.split('/')
378 s = set([x for x in dl if dl.count(x) > 1])404 s = set([x for x in dl if dl.count(x) > 1])
379 if ((pci_slot_name in dl)405 if (
380 and (dl.index(pci_slot_name) < dl.index('block'))406 (pci_slot_name in dl) and
381 and (not(pci_slot_name in s))):407 (dl.index(pci_slot_name) < dl.index('block')) and
408 (not(pci_slot_name in s))
409 ):
382 # 1. there is such pci_slot_name410 # 1. there is such pci_slot_name
383 # 2. sysfs topology looks like411 # 2. sysfs topology looks like
384 # DEVPATH = ....../pci_slot_name/....../block/......412 # DEVPATH = ....../pci_slot_name/....../block/......
@@ -451,10 +479,14 @@
451 choices=['xhci_hcd'],479 choices=['xhci_hcd'],
452 help=("Detect the driver of the host controller."480 help=("Detect the driver of the host controller."
453 "Only xhci_hcd for usb3 is supported so far."))481 "Only xhci_hcd for usb3 is supported so far."))
482 parser.add_argument("--lsblkcommand", action='store', type=str,
483 default="lsblk -i -n -P -o KNAME,TYPE,MOUNTPOINT",
484 help=("Command to execute to get lsblk information. "
485 "Only change it if you know what you're doing."))
454486
455 args = parser.parse_args()487 args = parser.parse_args()
456488
457 test = DiskTest(args.device, args.memorycard)489 test = DiskTest(args.device, args.memorycard, args.lsblkcommand)
458490
459 errors = 0491 errors = 0
460 # If we do have removable drives attached and mounted492 # If we do have removable drives attached and mounted
@@ -505,8 +537,8 @@
505 % errors_mount)537 % errors_mount)
506 errors += errors_mount538 errors += errors_mount
507539
508 disks_all = dict(list(test.rem_disks.items())540 disks_all = dict(list(test.rem_disks.items()) +
509 + list(test.rem_disks_nm.items()))541 list(test.rem_disks_nm.items()))
510542
511 if len(disks_all) > 0:543 if len(disks_all) > 0:
512 print("Found the following mounted %s partitions:"544 print("Found the following mounted %s partitions:"
@@ -528,8 +560,8 @@
528560
529 disks_eligible = {disk: disks_all[disk] for disk in disks_all561 disks_eligible = {disk: disks_all[disk] for disk in disks_all
530 if not args.min_speed or562 if not args.min_speed or
531 int(test.rem_disks_speed[disk])563 int(test.rem_disks_speed[disk]) >=
532 >= int(args.min_speed)}564 int(args.min_speed)}
533 if len(disks_eligible) == 0:565 if len(disks_eligible) == 0:
534 logging.error(566 logging.error(
535 "No %s disks with speed higher than %s bits/s",567 "No %s disks with speed higher than %s bits/s",
@@ -542,21 +574,24 @@
542 stat = os.statvfs(path)574 stat = os.statvfs(path)
543 disks_freespace[disk] = stat.f_bfree * stat.f_bsize575 disks_freespace[disk] = stat.f_bfree * stat.f_bsize
544 smallest_freespace = min(disks_freespace.values())576 smallest_freespace = min(disks_freespace.values())
577 smallest_partition = [d for d, v in disks_freespace.items() if
578 v == smallest_freespace][0]
545 desired_size = args.size579 desired_size = args.size
546 if desired_size > smallest_freespace:580 if desired_size > smallest_freespace:
547 if args.auto_reduce_size:581 if args.auto_reduce_size:
548 min_space = HumanReadableBytes("1MiB")582 min_space = HumanReadableBytes("1MiB")
549 if smallest_freespace < min_space:583 if smallest_freespace < min_space:
550 raise IOError("Not enough space. {} is required"584 sys.exit("Not enough space. {} is required on {}"
551 .format(min_space))585 .format(min_space, smallest_partition))
552 new_size = HumanReadableBytes(int(0.8 * smallest_freespace))586 new_size = HumanReadableBytes(
587 int(0.8 * smallest_freespace))
553 logging.warning("Automatically reducing test data size"588 logging.warning("Automatically reducing test data size"
554 ". {} requested. Reducing to {}."589 ". {} requested. Reducing to {}."
555 .format(desired_size, new_size))590 .format(desired_size, new_size))
556 desired_size = new_size591 desired_size = new_size
557 else:592 else:
558 raise IOError("Not enough space. {} is required"593 sys.exit("Not enough space. {} is required on {}"
559 .format(desired_size))594 .format(desired_size, smallest_partition))
560 # Generate our data file(s)595 # Generate our data file(s)
561 for count in range(args.count):596 for count in range(args.count):
562 test_files[count] = RandomData(desired_size)597 test_files[count] = RandomData(desired_size)
@@ -611,8 +646,8 @@
611 # avg_write_time = total_write_time / args.count646 # avg_write_time = total_write_time / args.count
612 try:647 try:
613 avg_write_speed = ((648 avg_write_speed = ((
614 total_write_size / total_write_time)649 total_write_size / total_write_time) /
615 / 1024 / 1024)650 1024 / 1024)
616 except ZeroDivisionError:651 except ZeroDivisionError:
617 avg_write_speed = 0.00652 avg_write_speed = 0.00
618 finally:653 finally:

Subscribers

People subscribed via source and target branches