Accessing DeviceKit with DBus and Python

Posted by Moser on 08 Jan 2010

Under the impression of loosing some really important data because of a damaged partition table on a USB flash drive I am developing a backup strategy for my system. I know myself and so I decided that I need to automate this. While trying to figure out how one can run a script as soon as a specific drive is mounted, I came across DeviceKit. It’s the planned replacement of HAL and is used in Ubuntu Karmic. Udev is not an option for me, because I don’t want to mess around with mounting myself (and I hate running stuff as root…). So here is what I found out about using DBus and DeviceKit in Python:

import dbus

bus = dbus.SystemBus()

proxy = bus.get_object("org.freedesktop.DeviceKit.Disks", 
                       "/org/freedesktop/DeviceKit/Disks")
iface = dbus.Interface(proxy, "org.freedesktop.DeviceKit.Disks")
#enumerates all devices
print iface.EnumerateDevices()

#gets the device kit path of a specific device
path = iface.FindDeviceByDeviceFile("/dev/sdc1") 
#= "/org/freedesktop/DeviceKit/Disks/devices/sdc"

#gets an object representing the device specified by the path
device = bus.get_object("org.freedesktop.DeviceKit.Disks", path) 

#prints some XML that shows you the available methods, signals and properties
print device.Introspect()

#gets a proxy for getting properties
device_prop = dbus.Interface(device, "org.freedesktop.DBus.Properties")

#you need to specify an interface (properties could be ambiguous)
print device_prop.Get("org.freedesktop.DeviceKit.Disks.Device", "device-mount-paths")

#gets a proxy you can call methods on
device_iface = dbus.Interface(device, "org.freedesktop.DeviceKit.Disks.Device")

#unmounts the partition
device_iface.FilesystemUnmount(dbus.Array([], 's'))

The DBus API of DeviceKit is documented here. Now we want to be notified when a drive is mounted:

import dbus
import gobject
from dbus.mainloop.glib import DBusGMainLoop

def device_added_callback(device):
    print 'Device %s was added' % (device)

def device_changed_callback(device):
    print 'Device %s was changed' % (device)

#must be done before connecting to DBus
DBusGMainLoop(set_as_default=True)

bus = dbus.SystemBus()

proxy = bus.get_object("org.freedesktop.DeviceKit.Disks", 
                       "/org/freedesktop/DeviceKit/Disks")
iface = dbus.Interface(proxy, "org.freedesktop.DeviceKit.Disks")

#addes two signal listeners
iface.connect_to_signal('DeviceAdded', device_added_callback)
iface.connect_to_signal('DeviceChanged', device_changed_callback)

#start the main loop
mainloop = gobject.MainLoop()
mainloop.run()

A typical output when a flash drive is plugged in looks like this:

Device /org/freedesktop/DeviceKit/Disks/devices/sdc was added
Device /org/freedesktop/DeviceKit/Disks/devices/sdc1 was added
Device /org/freedesktop/DeviceKit/Disks/devices/sdc1 was changed

With this knowledge I’m currently working on a little python script that runs in background and executes a shell script when a file system is mounted. I’ll post it, when it’s finished :-)