Mind Bending

Python Logo

Resurrecting the blog series about Python and Udisks, today I’m going to talk about how to get some more informations about the devices using properties.

About the Delay

First of all, I apologize for the delay in posting this continuation, it was harder to write than it looks. The delay is due to a change in how DBus communicate with UDisks. Since everything is very new, the documentation isn’t complete and there is no tutorial on the internet. So, my search for the error line did not return any results. Below is the code I was using and the DBus error:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
>>> import dbus
>>>
>>> bus = dbus.SystemBus()
>>> proxy = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks")
>>> iface = dbus.Interface(proxy, "org.freedesktop.UDisks")
>>>
>>> devs = iface.EnumerateDevices()
>>> print devs
>>>
>>> device = devs[14]
>>> volume_obj = bus.get_object("org.freedesktop.UDisks", device)
>>> volume = dbus.Interface(volume_obj, "org.freedesktop.UDisks.Device")
>>> volume_obj.Get('','DriveConnectionInterface')
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.AccessDenied:
Rejected send message, 4 matched rules; type="method_call", sender=":1.60"
(uid=1000 pid=19165 comm="/usr/bin/python2 ./test-me ") interface="(unset)"
member="Get" error name="(unset)" requested_reply="0" destination=":1.19"
(uid=0 pid=1010 comm="/usr/lib/udisks/udisks-daemon ")

After some days of research and failed attempts I decided to do something that many people avoid: read the source code from other projects. After some research I found the liveusb-creator project, which use UDisks and DBus to detect new removable devices. My solution was in the creator.py file (more specifically at the method handle_reply, from lines 445 to 450) available here.

Let Me See The Code

Clarified the issue, I’ll show the solution. Our intention is to obtain information about a flash drive device or other removable storage device connected to our computer. So, we will test whether the storage device uses or not the USB communication interface. Take a look at the following code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 >>> import dbus
 >>>
 >>> bus = dbus.SystemBus()
 >>> proxy = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks")
 >>> iface = dbus.Interface(proxy, "org.freedesktop.UDisks")
 >>>
 >>> devs = iface.EnumerateDevices()
 >>>
 >>> dev_obj = bus.get_object("org.freedesktop.UDisks", devs[0])
 >>> type(dev_obj)
 <class 'dbus.proxies.ProxyObject'>
 >>>
 >>> dev = dbus.Interface(dev_obj, "org.freedesktop.DBus.Properties")
 >>> type(dev_obj)
 <class 'dbus.proxies.Interface'>
 >>> print dev.Get('', 'DriveConnectionInterface')
 ata

As you can see, from lines 1 until 8 there is nothing new. All the magic is done at the lines 09 to 17:

  • Line 09 - Obtain an ProxyObject using the method bus.get_object;
  • Line 10 - Calls the type statement to show the returned type;
  • Line 13 - Asks for an interface using the dbus.Interface method and passes the ProxyObject obtained in the line 09 as an argument;
  • Line 14 - Calls the type method to show the returned type;
  • Line 16 - Calls the Get method in order to retrieve the value of the DriveConenctionInterface property;

According to the last line of code above this device uses an ‘ata’ interface to comunicate with the system, so it isn’t a removable device. Since we are only interested in devices that connect via USB, let’s iterate over the devs array and test if the DriveConenctionInterface property is equal to ‘usb’.

1
2
3
4
5
6
7
8
 >>> for dev in devs:
 ...     dev_obj = bus.get_object("org.freedesktop.UDisks", dev)
 ...     dev = dbus.Interface(dev_obj, "org.freedesktop.DBus.Properties")
 ...     if str(dev.Get('', 'DriveConnectionInterface')) == 'usb':
 ...         name = str(dev.Get('', 'DeviceFile'))
 ...         print 'Removable device: ' + name
 Removable device: /dev/sdd
 Removable device: /dev/sdd1

Note that I used the DeviceFile property to get the block device path.

Repeated Devices

As seen on the devs vector iteration we found two devices /dev/sdd and /dev/sdd1, but both represent the same physical device. In my last post I talked about this behaviour. To avoid it we must test if the current device is a partition table:

1
2
3
4
5
6
7
8
9
 >>> for dev in devs:
 ...     dev_obj = bus.get_object("org.freedesktop.UDisks", dev)
 ...     dev = dbus.Interface(dev_obj, "org.freedesktop.DBus.Properties")
 ...     if bool(dev.Get('', 'DeviceIsPartitionTable')):
 ...         continue
 ...     if str(dev.Get('', 'DriveConnectionInterface')) == 'usb':
 ...         name = str(dev.Get('', 'DeviceFile'))
 ...         print 'Removable device: ' + name
 Removable device: /dev/sdd1

Done! Now we can chose only the removable device that we want.

Are There More Properties?

In the official UDisks documentation there is was a Properties section that list all properties with a brief explanation.

To reduce the work, is possible to use the GetAll method, which returns a dictionary containing all the properties and its values. It can be used as below (part of the output is omitted):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 >>> dev_obj = bus.get_object("org.freedesktop.UDisks", devsspan[15])
 >>> dev = dbus.Interface(dev_obj, "org.freedesktop.DBus.Properties")
 >>> data = dev.GetAll('')
 >>> for i in data: print i+': '+str(data[i])
 ...
 DeviceIsMounted: 1
 LinuxLvm2PVNumMetadataAreas: 0
 LinuxLvm2LVGroupUuid:
 LinuxLoopFilename:
 LinuxDmmpComponentHolder: /
 DeviceIsPartitionTable: 0
 (...)
 DriveVendor: Kingston
 (...)
 IdLabel: MAGNUN
 (...)
 IdVersion: FAT32
 DriveSerial: 001CC0EC34C8F071A645131E
 (...)
 DeviceSize: 16011330048
 (...)
 DriveModel: DataTraveler G3
 (...)
 DriveConnectionInterface: usb
 DriveRevision: 1.00
 LinuxLvm2LVGroupName:
 PartitionType: 0x0b
 PartitionSize: 16011330048
 (...)
 DriveConnectionSpeed: 480000000
 (...)

In the next post I’ll show how to call some of the methods presented in UDisks documentation.

Until then…

Magnun

Magnun

Graduated in Telecommunication Engineering, but currently working with GNU/Linux infrastructure and in the spare time I'm an Open Source programmer (Python and C), a drawer and author in the Mind Bending Blog.


Comments

comments powered by Disqus