ait/os/bin/autoshadow/autoshadow.py
branchom
changeset 2 c9bf2537109a
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ait/os/bin/autoshadow/autoshadow.py	Tue Nov 12 11:31:34 2013 +0100
     1.3 @@ -0,0 +1,152 @@
     1.4 +#!/bin/env python
     1.5 +# -*- coding: utf-8 -*-
     1.6 +
     1.7 +# ------------------------------------------------------------
     1.8 +# autoshadow.py
     1.9 +# 
    1.10 +# Listen on DBus and mount any USB stick automatically
    1.11 +# and invoke shadowfuse for it
    1.12 +#
    1.13 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    1.14 +#
    1.15 +# Copyright (C) 2013 AIT Austrian Institute of Technology
    1.16 +# AIT Austrian Institute of Technology GmbH
    1.17 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
    1.18 +# http://www.ait.ac.at
    1.19 +#
    1.20 +# This program is free software; you can redistribute it and/or
    1.21 +# modify it under the terms of the GNU General Public License
    1.22 +# as published by the Free Software Foundation version 2.
    1.23 +# 
    1.24 +# This program is distributed in the hope that it will be useful,
    1.25 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.26 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.27 +# GNU General Public License for more details.
    1.28 +# 
    1.29 +# You should have received a copy of the GNU General Public License
    1.30 +# along with this program; if not, write to the Free Software
    1.31 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    1.32 +# Boston, MA  02110-1301, USA.
    1.33 +# ------------------------------------------------------------
    1.34 +
    1.35 +
    1.36 +# ------------------------------------------------------------
    1.37 +# imports
    1.38 +
    1.39 +import argparse
    1.40 +import dbus
    1.41 +import dbus.glib
    1.42 +import dbus.service
    1.43 +import gobject
    1.44 +import sys
    1.45 +
    1.46 +
    1.47 +# ------------------------------------------------------------
    1.48 +# const
    1.49 +
    1.50 +
    1.51 +__version__ = "0.1"
    1.52 +
    1.53 +
    1.54 +# ------------------------------------------------------------
    1.55 +# code
    1.56 +
    1.57 +
    1.58 +class AutoShadowService(dbus.service.Object):
    1.59 +    
    1.60 +    """The AutoShadowService is the DBus object which listens on UDisk2 events and decides to mount and shadow a device.
    1.61 +    
    1.62 +    This class incorporates a DBus service (at.ac.ait.opensecurity.AutoShadow) and binds
    1.63 +    itself to the /AutoShadow object.
    1.64 +    """
    1.65 +
    1.66 +    def __init__(self):
    1.67 +        
    1.68 +        bus = dbus.SystemBus()
    1.69 +        bus_name = dbus.service.BusName('at.ac.ait.opensecurity.AutoShadow', bus)
    1.70 +        dbus.service.Object.__init__(self, bus_name, '/AutoShadow')
    1.71 +        
    1.72 +        # get the UDisk2 system object
    1.73 +        try:
    1.74 +            udisk2 = bus.get_object('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2')
    1.75 +        except:
    1.76 +            sys.stderr.write('Failed to aquire DBus Service org.freedesktop.UDisks2 object /org/freedesktop/UDisks2 on system DBus.\n')
    1.77 +            sys.exit(1)
    1.78 +            
    1.79 +        # connect our signal
    1.80 +        udisk2.connect_to_signal('InterfacesAdded', self.interface_added, sender_keyword='sender')
    1.81 +    
    1.82 +    
    1.83 +    def interface_added(*args, **kwargs):
    1.84 +        
    1.85 +        """Entry point for signal for new interfaces"""
    1.86 +        
    1.87 +        # a new interface has been added
    1.88 +        object_path = args[1]
    1.89 +        interfaces_and_properties = args[2]
    1.90 +        interface_keys = interfaces_and_properties.keys()
    1.91 +        
    1.92 +        if (interface_keys[0] == 'org.freedesktop.UDisks2.Drive'):
    1.93 +            
    1.94 +            # added a new drive
    1.95 +            drive_values = interfaces_and_properties[interface_keys[0]]
    1.96 +            drive_id = str(drive_values['Id'])
    1.97 +            drive_vendor = str(drive_values['Vendor'])
    1.98 +            drive_removeable = bool(drive_values['Removable'])
    1.99 +            print('detected new drive: id=\'{0}\' vendor=\'{1}\' removeable={2}'.format(drive_id, drive_vendor, drive_removeable))
   1.100 +        
   1.101 +        if (interface_keys[0] == 'org.freedesktop.UDisks2.Block'):
   1.102 +            
   1.103 +            # added a new device - filesystem?
   1.104 +            if ('org.freedesktop.UDisks2.Filesystem' in interface_keys):
   1.105 +                
   1.106 +                # pick values of the device
   1.107 +                device_values = interfaces_and_properties[interface_keys[0]]
   1.108 +                device_path = bytearray(device_values['Device'][0:-1]).decode('latin-1')
   1.109 +                print('detected new device: path=\'{0}\''.format(device_path))
   1.110 +                enforce_mount('/org/freedesktop/UDisks2/block_devices/' + device_path.split('/')[-1])
   1.111 +            
   1.112 +
   1.113 +    def listen(self):
   1.114 +        """Start listening on DBus"""
   1.115 +        self.loop = gobject.MainLoop()
   1.116 +        self.loop.run()
   1.117 +
   1.118 +
   1.119 +    @dbus.service.method('at.ac.ait.opensecurity.AutoShadow')
   1.120 +    def Quit(self):
   1.121 +        """Terminate this service"""
   1.122 +        self.loop.quit()
   1.123 +
   1.124 +
   1.125 +    @dbus.service.method('at.ac.ait.opensecurity.AutoShadow', out_signature='s')
   1.126 +    def Version(self):
   1.127 +        """Give a version string"""
   1.128 +        return __version__
   1.129 +
   1.130 +
   1.131 +def enforce_mount(udisk_object):
   1.132 +    
   1.133 +    """This function does the real mounting of drives. 
   1.134 +    It also enforces the MirrorFuse on these mounts.
   1.135 +    """
   1.136 +    
   1.137 +    print("ENFORCING mount of " + udisk_object)
   1.138 +
   1.139 +
   1.140 +def main():             
   1.141 +            
   1.142 +    # parse command line
   1.143 +    parser = argparse.ArgumentParser(description = 'Automount USB storage devices and invoke shadowfuse for it.')
   1.144 +    args = parser.parse_args()
   1.145 +    
   1.146 +    # setup DBus event loop
   1.147 +    autoshadow_service = AutoShadowService()
   1.148 +    autoshadow_service.listen()    
   1.149 +    
   1.150 +
   1.151 +# start
   1.152 +if __name__ == "__main__":
   1.153 +    main()
   1.154 +
   1.155 +