Merge lp:~sylvain-pineau/checkbox/bug1050920 into lp:checkbox

Proposed by Sylvain Pineau
Status: Merged
Merged at revision: 1718
Proposed branch: lp:~sylvain-pineau/checkbox/bug1050920
Merge into: lp:checkbox
Diff against target: 521 lines (+89/-193)
8 files modified
checkbox/parsers/udevadm.py (+19/-0)
debian/changelog (+3/-0)
jobs/mediacard.txt.in (+1/-1)
jobs/resource.txt.in (+0/-6)
scripts/memorycard_resource (+0/-143)
scripts/optical_write_test (+4/-3)
scripts/removable_storage_test (+29/-20)
scripts/removable_storage_watcher (+33/-20)
To merge this branch: bzr merge lp:~sylvain-pineau/checkbox/bug1050920
Reviewer Review Type Date Requested Status
Marc Tardif (community) Needs Information
Zygmunt Krynicki (community) Approve
Sylvain Pineau (community) Needs Resubmitting
Review via email: mp+124458@code.launchpad.net

Description of the change

This MR fixed the memorycard regexp flags and added the DriveVendor Udisks property to the re.search() string in removable_storage* scripts and the memorycard_resource job.

To post a comment you must log in.
Revision history for this message
Marc Tardif (cr3) wrote :

Out of curiosity, what's the difference between the memorycard_resource and the existing udev_resource script? It looks like I can achieve pretty much the same thing with this shell script:

export PATH=/usr/share/checkbox/scripts:$PATH
run_templates -st "udev_resource | filter_templates -w 'driver=sd'" <<'EOF' \
  | (egrep -vqi '(SD|MMC|CF|MS|SM|xD|Card|Generic)' || !grep -q 'SDHCI controller found' /var/log/kern.log*) \
    && echo 'reader: detected' \
    || echo 'reader: none'
$product
EOF

Revision history for this message
Marc Tardif (cr3) wrote :

Note that one advantage to the shell script is that it doesn't require any crazy call to ioctl, and another advantage is that it doesn't need to run as root since udev_resource leverages udev that exposes some useful information.

Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

udev seems to offer the same results but to fully replace my crazy ioctl I would change your proposal like this:

export PATH=/usr/share/checkbox/scripts:$PATH
run_templates -st "udev_resource | filter_templates -w 'driver=sd'" <<'EOF' \
  | (egrep -qi '(SD|MMC|CF|MS|SM|xD|Card|Generic)' || grep -q 'SDHCI controller found' /var/log/kern.log*) \
    && echo 'reader: detected' \
    || echo 'reader: none'
$product $vendor
EOF

I will change my MR to reflect this very nice improvement, Thx

Revision history for this message
Marc Tardif (cr3) wrote :

We might want to discuss ading the MEDIACARD category in the output of the udev_resource script. However, that really depends on how confident you are about this regular expression to distinguish disk devices from multicard devices: '(SD|MMC|CF|MS|SM|xD|Card|Generic)'

1676. By Sylvain Pineau

the memory_card resource job now uses udev_resource output

1677. By Sylvain Pineau

Merged from trunk

Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

I prefer to keep the memory_card resource job separated from udev_resource. We don't have yet enough feedback on how reliable the regexp is.

review: Needs Resubmitting
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

24 + run_templates -st "udev_resource | filter_templates -w 'driver=sd'" <<'EOF' \
25 + | (egrep -qi '(SD|MMC|CF|MS|SM|xD|Card|Generic)' || grep -q 'SDHCI controller found' /var/log/kern.log*) \
26 + && echo 'reader: detected' \
27 + || echo 'reader: none'

This is the kind of thing that deserves an API as it needs to be reused in various places

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

/me puts syntax nazi hat on

I'm pretty sure (just by looking at a few lines) that this is not PEP8 clean, would you mind fixing it please?

review: Needs Fixing
1678. By Sylvain Pineau

Move the card reader detection logic to udevadm.py

1679. By Sylvain Pineau

Merged from trunk

1680. By Sylvain Pineau

Revert unwanted changes to optical_write_test

1681. By Sylvain Pineau

PEP8 check

Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

/lib/udev/rules.d/80-udisks.rules also matches devices using regexp on device model names, so it's not a bad idea after all. So now the logic is part of the udevadm.py parser with a new category: CARDREADER.

The following drivers are supported: sdhci, sdhci-pci, mmc* and sd.
For sd, the parser checks the model name (aka product in udevadm.py) and the vendor name.

Nota: The code contains several pep8 fixes in removable_storage*

review: Needs Resubmitting
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

No objections to merge.

Looking at the delta I see two things that need fixing (but are unrelated to your change) - the one with namedtuple instead of dev[x] and the one where args.speed is not a integer (removable_storage_test) - it should be marked as such in argparse to make both command line parsing and in-test logic more reliable

You may want to get a second opinion though as I'm temporarily out of precise systems that I can test this on

review: Approve
1682. By Sylvain Pineau

Check if the product field exists in _environment before checking sd driver devices

Revision history for this message
Marc Tardif (cr3) wrote :

This looks very nice, thanks for taking the time to improve udev_resource, I now get this on my system:

path: /devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0
bus: scsi
category: CARDREADER
driver: sd
product: SAMSUNG MMCRE64G8MPP-0VA

Do you think we could import CARD_READER_RE from checkbox.parsers.udevadm in scripts/removable_storage_test and scripts/removable_storage_watcher, instead of defining the same regular expression in both places? It's not that much code reuse but that pattern seems error prone.

review: Needs Information
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

@Marc, Matching an internal SSD drive will prevent it to be used for disks tests.

Could you please pastebin the output of udisks --show-info /dev/sdx (where x is your drive letter). Don't provide the output of an existing partition like sdb2, just sdb to have the drive properties.

I think we could use the rotational media udisks property to avoid them to be detected as card readers. My system reports the following info for a usb reader:

  drive:
    vendor: Generic
    model: Ultra HS-SD/MMC
    revision: 1.82
    serial: 000000264001
    WWN:
    detachable: 1
    can spindown: 0
    rotational media: Yes, unknown rate

1683. By Sylvain Pineau

Card reader detection improved in udev parser, relying on udev properties first and finally and the regexp if not matches found.

1684. By Sylvain Pineau

Updated removable_storage* scripts with udevadm regexp
pep8 fixes
device property is now a namedtuple

1685. By Sylvain Pineau

Merged from trunk

1686. By Sylvain Pineau

Change removable_storage_watcher permissions (+x)

1687. By Sylvain Pineau

lint fixes

Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

I reworked a bit the udevadm parser section about card readers, to follow this schema: give priority to udev rules. First identify memorycard readers with ID_DRIVE_FLASH_SD and if not matches fallback to the regexp identification. When upstream patches will identify crazy usb readers, we could safely remove those lines.

Regexp used in removable_storage* scripts ar all imported from the udevadm parser.

The bug identifying SSD drives is fixed.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'checkbox/parsers/udevadm.py'
2--- checkbox/parsers/udevadm.py 2012-09-25 11:52:25 +0000
3+++ checkbox/parsers/udevadm.py 2012-10-01 07:54:21 +0000
4@@ -59,6 +59,9 @@
5 r"^scsi:"
6 r"t-0x(?P<type>[%(hex)s]{2})"
7 % {"hex": string.hexdigits})
8+CARD_READER_RE = re.compile(r"SD|MMC|CF|MS|SM|xD|Card", re.I)
9+GENERIC_RE = re.compile(r"Generic", re.I)
10+FLASH_RE = re.compile(r"Flash", re.I)
11
12
13 class UdevadmDevice:
14@@ -208,6 +211,22 @@
15 if test_bit(Input.BTN_MOUSE, bitmask, self._bits):
16 return "MOUSE"
17
18+ if self.driver:
19+ if self.driver.startswith("sdhci"):
20+ return "CARDREADER"
21+
22+ if self.driver.startswith("mmc"):
23+ return "CARDREADER"
24+
25+ if self.driver == "sd" and self.product:
26+ if any(FLASH_RE.search(k) for k in self._environment.keys()):
27+ return "CARDREADER"
28+ if any(d.bus == 'usb' for d in self._stack):
29+ if CARD_READER_RE.search(self.product):
30+ return "CARDREADER"
31+ if GENERIC_RE.search(self.vendor):
32+ return "CARDREADER"
33+
34 if "ID_TYPE" in self._environment:
35 id_type = self._environment["ID_TYPE"]
36
37
38=== modified file 'debian/changelog'
39--- debian/changelog 2012-09-28 16:29:41 +0000
40+++ debian/changelog 2012-10-01 07:54:21 +0000
41@@ -165,6 +165,9 @@
42 * checkbox/parsers/udevadm.py: Improved wireless devices detection.
43 The wireless category is now set if the subsystem is equal to ieee80211
44 (LP: #855382)
45+ * scripts/memorycard_resource, scripts/removable_storage_test,
46+ scripts/removable_storage_watcher: Fixed the memorycard regexp flags and
47+ add the DriveVendor Udisks property to the re.search() string (LP: #1050920)
48
49 [Zygmunt Krynicki]
50 * Fixed simple duplicate 'the' mistakes (LP: #1040022)
51
52=== modified file 'jobs/mediacard.txt.in'
53--- jobs/mediacard.txt.in 2012-09-04 19:15:43 +0000
54+++ jobs/mediacard.txt.in 2012-10-01 07:54:21 +0000
55@@ -181,7 +181,7 @@
56 user: root
57 requires:
58 package.name == 'udisks'
59- memory_card.reader == 'detected'
60+ device.category == 'CARDREADER'
61 command: removable_storage_test --memorycard -l sdio usb scsi && removable_storage_test --memorycard sdio usb scsi
62 _description:
63 This is a fully automated version of mediacard/sd-automated and assumes that the
64
65=== modified file 'jobs/resource.txt.in'
66--- jobs/resource.txt.in 2012-09-06 09:42:43 +0000
67+++ jobs/resource.txt.in 2012-10-01 07:54:21 +0000
68@@ -100,9 +100,3 @@
69 for e in `env | sed 's/=/:/g'`; do
70 echo $e | awk -F':' '{print tolower($1) ": " $2}'
71 done
72-
73-name: memory_card
74-plugin: resource
75-user: root
76-command: memorycard_resource
77-description: Create resource info for memorycard readers
78
79=== removed file 'scripts/memorycard_resource'
80--- scripts/memorycard_resource 2012-09-05 20:09:10 +0000
81+++ scripts/memorycard_resource 1970-01-01 00:00:00 +0000
82@@ -1,143 +0,0 @@
83-#!/usr/bin/python3
84-#
85-# This file is part of Checkbox.
86-#
87-# Copyright 2012 Canonical Ltd.
88-#
89-# Checkbox is free software: you can redistribute it and/or modify
90-# it under the terms of the GNU General Public License as published by
91-# the Free Software Foundation, either version 3 of the License, or
92-# (at your option) any later version.
93-#
94-# Checkbox is distributed in the hope that it will be useful,
95-# but WITHOUT ANY WARRANTY; without even the implied warranty of
96-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
97-# GNU General Public License for more details.
98-#
99-# You should have received a copy of the GNU General Public License
100-# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
101-#
102-
103-import re
104-import sys
105-import fcntl
106-import struct
107-import ctypes
108-from glob import glob
109-from subprocess import call
110-
111-
112-class sg_io_hdr(ctypes.Structure):
113- """
114- Do ioctl's using Linux generic SCSI interface.
115- """
116- SG_IO = 0x2285
117-
118- _fields_ = [("interface_id", ctypes.c_int),
119- ("dxfer_direction", ctypes.c_int),
120- ("cmd_len", ctypes.c_ubyte),
121- ("mx_sb_len", ctypes.c_ubyte),
122- ("iovec_count", ctypes.c_ushort),
123- ("dxfer_len", ctypes.c_int),
124- ("dxferp", ctypes.c_char_p),
125- ("cmdp", ctypes.c_char_p),
126- ("sbp", ctypes.c_char_p),
127- ("timeout", ctypes.c_uint),
128- ("flags", ctypes.c_uint),
129- ("pack_id", ctypes.c_int),
130- ("usr_ptr", ctypes.c_char_p),
131- ("status", ctypes.c_ubyte),
132- ("masked_status", ctypes.c_ubyte),
133- ("msg_status", ctypes.c_ubyte),
134- ("sb_len_wr", ctypes.c_ubyte),
135- ("host_status", ctypes.c_ushort),
136- ("driver_status", ctypes.c_ushort),
137- ("resid", ctypes.c_int),
138- ("duration", ctypes.c_uint),
139- ("info", ctypes.c_uint)]
140-
141- def __init__(self):
142- self.interface_id = ord('S')
143- self.dxfer_direction = 0
144- self.cmd_len = 0
145- self.mx_sb_len = 0
146- self.iovec_count = 0
147- self.dxfer_len = 0
148- self.dxferp = None
149- self.cmdp = None
150- self.timeout = 20000
151- self.flags = 0
152- self.pack_id = 0
153- self.usr_ptr = None
154- self.status = 0
155- self.masked_status = 0
156- self.msg_status = 0
157- self.sb_len_wr = 0
158- self.host_status = 0
159- self.driver_status = 0
160- self.resid = 0
161- self.duration = 0
162- self.info = 0
163-
164-
165-def _get_sub_page(size, control_block, device):
166- """
167- ioctl to retrieve a sub-page from the device.
168- """
169- io_hdr = sg_io_hdr()
170- io_hdr.dxfer_direction = -3
171- io_hdr.cmd_len = len(control_block)
172- io_hdr.cmdp = control_block
173- page_buffer = ctypes.create_string_buffer(size)
174- io_hdr.dxfer_len = size
175- io_hdr.dxferp = ctypes.cast(page_buffer, ctypes.c_char_p)
176-
177- i = -1
178- try:
179- with open(device, 'r') as fd:
180- i = fcntl.ioctl(fd, sg_io_hdr.SG_IO, io_hdr)
181- except IOError:
182- return None
183-
184- if i < 0:
185- raise IOError("SG_IO ioctl error")
186-
187- if io_hdr.status != 0x00:
188- raise IOError("io_hdr status is: %x" % io_hdr.status)
189-
190- if io_hdr.resid > 0:
191- retsize = size - io_hdr.resid
192- else:
193- retsize = size
194-
195- return page_buffer[0:retsize]
196-
197-
198-def inquire(device):
199- """
200- Issue a SCSI INQUIRY command
201- """
202- fields = '>BBBBBBBB8s16s4s20sBB8HH'
203- fields_len = struct.calcsize(fields)
204- control_block = struct.pack("BBBBBB", 0x12, 0, 0, 0, fields_len, 0)
205- try:
206- return _get_sub_page(fields_len, control_block, device)[8:32].decode()
207- except TypeError:
208- return ''
209-
210-
211-def main():
212- pattern = re.compile('SD|MMC|CF|MS|SM|xD|Card|Generic')
213- matches = [dev for dev in glob('/dev/sg*') if
214- pattern.search(inquire(dev), re.I)]
215-
216- if matches or not call(
217- "grep -q 'SDHCI controller found' /var/log/kern.log*", shell=True):
218- print('reader: detected')
219- else:
220- print('reader: none')
221-
222- return 0
223-
224-if __name__ == "__main__":
225- sys.exit(main())
226
227=== modified file 'scripts/optical_write_test'
228--- scripts/optical_write_test 2012-09-24 14:39:56 +0000
229+++ scripts/optical_write_test 2012-10-01 07:54:21 +0000
230@@ -68,14 +68,14 @@
231 while true; do
232 sleep $INTERVAL
233 SLEEP_COUNT=`expr $SLEEP_COUNT + $INTERVAL`
234-
235+
236 mount $OPTICAL_DRIVE 2>&1 |egrep -q "already mounted"
237 rt=$?
238 if [ $rt -eq 0 ]; then
239 echo "Drive appears to be mounted now"
240 break
241 fi
242-
243+
244 # If they exceed the timeout limit, make a best effort to load the tray
245 # in the next steps
246 if [ $SLEEP_COUNT -ge $TIMEOUT ]; then
247@@ -84,6 +84,7 @@
248 fi
249 done
250
251+
252 echo "Deleting original data files ..."
253 rm -rf $SAMPLE_FILE
254 if [ ! -z "$(mount | grep $OPTICAL_DRIVE)" ]; then
255@@ -130,7 +131,7 @@
256 OPTICAL_DRIVE=$(readlink -f $1)
257 else
258 OPTICAL_DRIVE='/dev/sr0'
259-fi
260+fi
261
262 create_working_dirs || failed "Failed to create working directories"
263 get_sample_data || failed "Failed to copy sample data"
264
265=== modified file 'scripts/removable_storage_test'
266--- scripts/removable_storage_test 2012-09-06 09:27:13 +0000
267+++ scripts/removable_storage_test 2012-10-01 07:54:21 +0000
268@@ -4,7 +4,6 @@
269 import sys
270 import random
271 import os
272-import re
273 import tempfile
274 import hashlib
275 import argparse
276@@ -12,6 +11,7 @@
277 import threading
278 import time
279 import collections
280+from checkbox.parsers.udevadm import CARD_READER_RE, GENERIC_RE, FLASH_RE
281
282
283 class ActionTimer():
284@@ -142,7 +142,6 @@
285 self.rem_disks_nm = {}
286 self.rem_disks_memory_cards = {}
287 self.rem_disks_memory_cards_nm = {}
288- pattern = re.compile('SD|MMC|CF|MS|SM|xD|Card|Generic')
289 for dev in ud_manager.EnumerateDevices():
290 device_obj = bus.get_object("org.freedesktop.UDisks", dev)
291 device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE)
292@@ -150,20 +149,26 @@
293 if not device_props.Get(udisks, "DeviceIsDrive"):
294 dev_bus = device_props.Get(udisks, "DriveConnectionInterface")
295 if dev_bus in args.device:
296- parent_model = ''
297+ parent_model = parent_vendor = ''
298 if device_props.Get(udisks, "DeviceIsPartition"):
299 parent_obj = bus.get_object(
300 "org.freedesktop.UDisks",
301 device_props.Get(udisks, "PartitionSlave"))
302 parent_props = dbus.Interface(
303 parent_obj, dbus.PROPERTIES_IFACE)
304- parent_model=parent_props.Get(udisks, "DriveModel")
305+ parent_model = parent_props.Get(udisks, "DriveModel")
306+ parent_vendor = parent_props.Get(udisks, "DriveVendor")
307+ parent_media = parent_props.Get(udisks, "DriveMedia")
308 if args.memorycard:
309- if dev_bus != 'sdio' and not pattern.search(
310- parent_model, re.I):
311+ if (dev_bus != 'sdio'
312+ and not FLASH_RE.search(parent_media)
313+ and not CARD_READER_RE.search(parent_model)
314+ and not GENERIC_RE.search(parent_vendor)):
315 continue
316 else:
317- if pattern.search(parent_model, re.I):
318+ if (FLASH_RE.search(parent_media)
319+ or CARD_READER_RE.search(parent_model)
320+ or GENERIC_RE.search(parent_vendor)):
321 continue
322 dev_file = str(device_props.Get(udisks, "DeviceFile"))
323 dev_speed = str(device_props.Get(udisks,
324@@ -178,7 +183,6 @@
325 self.rem_disks_nm[dev_file] = None
326 self.rem_disks_memory_cards_nm[dev_file] = None
327
328-
329 def mount(self):
330 passed_mount = {}
331
332@@ -379,7 +383,8 @@
333 print(" %s : %s : %s bits/s" %
334 (disk, mount_point, supported_speed),
335 end="")
336- if (args.min_speed and int(args.min_speed) > int(supported_speed)):
337+ if (args.min_speed
338+ and int(args.min_speed) > int(supported_speed)):
339 print(" (Will not test it, speed is below %s bits/s)" %
340 args.min_speed, end="")
341
342@@ -387,9 +392,10 @@
343
344 print('-' * 20)
345
346- disks_eligible = {disk: disks_all[disk] for disk in disks_all \
347- if not args.min_speed or \
348- int(test.rem_disks_speed[disk]) >= int(args.min_speed) }
349+ disks_eligible = {disk: disks_all[disk] for disk in disks_all
350+ if not args.min_speed or
351+ int(test.rem_disks_speed[disk])
352+ >= int(args.min_speed)}
353 write_sizes = []
354 test_files = {}
355 # Generate our data file(s)
356@@ -441,8 +447,9 @@
357 test.clean_up(file)
358 total_write_time = sum(write_times)
359 avg_write_time = total_write_time / args.count
360- avg_write_speed = (
361- total_write_size / total_write_time) / 1024 / 1024
362+ avg_write_speed = ((
363+ total_write_size / total_write_time)
364+ / 1024 / 1024)
365 iteration_write_times.append(total_write_time)
366 print("\t[Iteration %s] Average Speed: %0.4f"
367 % (iteration, avg_write_speed))
368@@ -470,25 +477,27 @@
369 "but there were errors" % args.count)
370 return 1
371 elif len(disks_eligible) == 0:
372- print("ERROR: No %s disks with speed higher than %s bits/s" %
373- (args.device, args.min_speed), file=sys.stderr)
374+ print("ERROR: No %s disks with speed higher than %s bits/s"
375+ % (args.device, args.min_speed), file=sys.stderr)
376 return 1
377
378 else:
379 #Pass is not assured!
380- if not args.pass_speed or avg_write_speed >= args.pass_speed:
381+ if (not args.pass_speed or
382+ avg_write_speed >= args.pass_speed):
383 return 0
384 else:
385 print("FAIL: Average speed was lower than desired "
386 "pass speed of %s MB/s" % args.pass_speed)
387 return 1
388 else:
389- print("ERROR: No device being mounted successfully for testing, "
390- "aborting", file=sys.stderr)
391+ print("ERROR: No device being mounted successfully "
392+ "for testing, aborting", file=sys.stderr)
393 return 1
394
395 else: # If we don't have removable drives attached and mounted
396- print("ERROR: No removable drives were detected, aborting", file=sys.stderr)
397+ print("ERROR: No removable drives were detected, aborting",
398+ file=sys.stderr)
399 return 1
400
401 if __name__ == '__main__':
402
403=== modified file 'scripts/removable_storage_watcher'
404--- scripts/removable_storage_watcher 2012-09-25 09:20:00 +0000
405+++ scripts/removable_storage_watcher 2012-10-01 07:54:21 +0000
406@@ -3,14 +3,17 @@
407 import argparse
408 import dbus
409 import logging
410-import re
411 import sys
412
413 from dbus.exceptions import DBusException
414 from gi.repository import GObject
415
416+from collections import namedtuple
417 from checkbox.dbus import connect_to_system_bus
418 from checkbox.dbus.udisks2 import UDisks2Model, UDisks2Observer
419+from checkbox.parsers.udevadm import CARD_READER_RE, GENERIC_RE, FLASH_RE
420+
421+Properties = namedtuple('Properties', 'file bus speed model vendor media')
422
423
424 def is_udisks2_supported(system_bus):
425@@ -89,33 +92,39 @@
426 desired_bus_devices = [
427 device
428 for device in changed_devices
429- if device[1] in self._devices]
430+ if device.bus in self._devices]
431 logging.debug("Desired bus devices: %s", desired_bus_devices)
432- pattern = re.compile('SD|MMC|CF|MS|SM|xD|Card|Generic')
433 for dev in desired_bus_devices:
434 if self._memorycard:
435- if dev[1] != 'sdio' and not pattern.search(dev[3], re.I):
436+ if (dev.bus != 'sdio'
437+ and not FLASH_RE.search(dev.media)
438+ and not CARD_READER_RE.search(dev.model)
439+ and not GENERIC_RE.search(dev.vendor)):
440 logging.debug("The device does not seem to be a memory"
441- " card (dev[1]: %r, dev[3]: %r), skipping",
442- dev[1], dev[3])
443+ " card (bus: %r, model: %r), skipping",
444+ dev.bus, dev.model)
445 return
446- print(message % {'bus': 'memory card', 'file': dev[0]})
447+ print(message % {'bus': 'memory card', 'file': dev.file})
448 else:
449- if pattern.search(dev[3], re.I):
450+ if (FLASH_RE.search(dev.media)
451+ or CARD_READER_RE.search(dev.model)
452+ or GENERIC_RE.search(dev.vendor)):
453 logging.debug("The device seems to be a memory"
454- " card %s (dev[3]: %r), skipping",
455- pattern, dev[3])
456+ " card (bus: %r (model: %r), skipping",
457+ dev.bus, dev.model)
458 return
459- print(message % {'bus': dev[1], 'file': dev[0]})
460+ print(message % {'bus': dev.bus, 'file': dev.file})
461 if self._minimum_speed:
462- if dev[2] >= self._minimum_speed:
463+ if dev.speed >= self._minimum_speed:
464 print("with speed of %(speed)s bits/s "
465 "higher than %(min_speed)s bits/s" %
466- {'speed': dev[2], 'min_speed': self._minimum_speed})
467+ {'speed': dev.speed,
468+ 'min_speed': self._minimum_speed})
469 else:
470 print("ERROR: speed of %(speed)s bits/s lower "
471 "than %(min_speed)s bits/s" %
472- {'speed': dev[2], 'min_speed': self._minimum_speed})
473+ {'speed': dev.speed,
474+ 'min_speed': self._minimum_speed})
475 self._error = True
476 logging.debug("Device matches requirements, exiting event loop")
477 self._loop.quit()
478@@ -189,11 +198,11 @@
479 udisks = 'org.freedesktop.UDisks.Device'
480 _device_file = device_props.Get(udisks,
481 "DeviceFile")
482- _device = device_props.Get(udisks,
483+ _bus = device_props.Get(udisks,
484 "DriveConnectionInterface")
485 _speed = device_props.Get(udisks,
486 "DriveConnectionSpeed")
487- _parent_model = ''
488+ _parent_model = _parent_vendor = ''
489
490 if device_props.Get(udisks, "DeviceIsPartition"):
491 parent_obj = self._bus.get_object(
492@@ -202,13 +211,17 @@
493 parent_props = dbus.Interface(
494 parent_obj, dbus.PROPERTIES_IFACE)
495 _parent_model = parent_props.Get(udisks, "DriveModel")
496+ _parent_vendor = parent_props.Get(udisks, "DriveVendor")
497+ _parent_media = parent_props.Get(udisks, "DriveMedia")
498
499 if not device_props.Get(udisks, "DeviceIsDrive"):
500- device = (
501+ device = Properties(
502 str(_device_file),
503- str(_device),
504+ str(_bus),
505 int(_speed),
506- str(_parent_model))
507+ str(_parent_model),
508+ str(_parent_vendor),
509+ str(_parent_media))
510 existing_devices.append(device)
511
512 except dbus.DBusException:
513@@ -242,7 +255,7 @@
514 # argument uses somewhat different strings. In particular we need to
515 # map 'ieee1394' to 'firewire'
516 #
517- # See: http://udisks.freedesktop.org/docs/latest/gdbus-org.freedesktop.UDisks2.Drive.html#gdbus-property-org-freedesktop-UDisks2-Drive.ConnectionBus
518+ # See: http://goo.gl/jaUAa
519 #
520 # TODO: Report old unsupported possibilities that are still offered by
521 # the command-line interface. We also need samples to understand how

Subscribers

People subscribed via source and target branches