ait/os/bin/autoshadow/autoshadow.py
author om
Tue, 12 Nov 2013 11:31:34 +0100
branchom
changeset 2 c9bf2537109a
permissions -rwxr-xr-x
added C/C++ and Python sources
om@2
     1
#!/bin/env python
om@2
     2
# -*- coding: utf-8 -*-
om@2
     3
om@2
     4
# ------------------------------------------------------------
om@2
     5
# autoshadow.py
om@2
     6
# 
om@2
     7
# Listen on DBus and mount any USB stick automatically
om@2
     8
# and invoke shadowfuse for it
om@2
     9
#
om@2
    10
# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
om@2
    11
#
om@2
    12
# Copyright (C) 2013 AIT Austrian Institute of Technology
om@2
    13
# AIT Austrian Institute of Technology GmbH
om@2
    14
# Donau-City-Strasse 1 | 1220 Vienna | Austria
om@2
    15
# http://www.ait.ac.at
om@2
    16
#
om@2
    17
# This program is free software; you can redistribute it and/or
om@2
    18
# modify it under the terms of the GNU General Public License
om@2
    19
# as published by the Free Software Foundation version 2.
om@2
    20
# 
om@2
    21
# This program is distributed in the hope that it will be useful,
om@2
    22
# but WITHOUT ANY WARRANTY; without even the implied warranty of
om@2
    23
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
om@2
    24
# GNU General Public License for more details.
om@2
    25
# 
om@2
    26
# You should have received a copy of the GNU General Public License
om@2
    27
# along with this program; if not, write to the Free Software
om@2
    28
# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
om@2
    29
# Boston, MA  02110-1301, USA.
om@2
    30
# ------------------------------------------------------------
om@2
    31
om@2
    32
om@2
    33
# ------------------------------------------------------------
om@2
    34
# imports
om@2
    35
om@2
    36
import argparse
om@2
    37
import dbus
om@2
    38
import dbus.glib
om@2
    39
import dbus.service
om@2
    40
import gobject
om@2
    41
import sys
om@2
    42
om@2
    43
om@2
    44
# ------------------------------------------------------------
om@2
    45
# const
om@2
    46
om@2
    47
om@2
    48
__version__ = "0.1"
om@2
    49
om@2
    50
om@2
    51
# ------------------------------------------------------------
om@2
    52
# code
om@2
    53
om@2
    54
om@2
    55
class AutoShadowService(dbus.service.Object):
om@2
    56
    
om@2
    57
    """The AutoShadowService is the DBus object which listens on UDisk2 events and decides to mount and shadow a device.
om@2
    58
    
om@2
    59
    This class incorporates a DBus service (at.ac.ait.opensecurity.AutoShadow) and binds
om@2
    60
    itself to the /AutoShadow object.
om@2
    61
    """
om@2
    62
om@2
    63
    def __init__(self):
om@2
    64
        
om@2
    65
        bus = dbus.SystemBus()
om@2
    66
        bus_name = dbus.service.BusName('at.ac.ait.opensecurity.AutoShadow', bus)
om@2
    67
        dbus.service.Object.__init__(self, bus_name, '/AutoShadow')
om@2
    68
        
om@2
    69
        # get the UDisk2 system object
om@2
    70
        try:
om@2
    71
            udisk2 = bus.get_object('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2')
om@2
    72
        except:
om@2
    73
            sys.stderr.write('Failed to aquire DBus Service org.freedesktop.UDisks2 object /org/freedesktop/UDisks2 on system DBus.\n')
om@2
    74
            sys.exit(1)
om@2
    75
            
om@2
    76
        # connect our signal
om@2
    77
        udisk2.connect_to_signal('InterfacesAdded', self.interface_added, sender_keyword='sender')
om@2
    78
    
om@2
    79
    
om@2
    80
    def interface_added(*args, **kwargs):
om@2
    81
        
om@2
    82
        """Entry point for signal for new interfaces"""
om@2
    83
        
om@2
    84
        # a new interface has been added
om@2
    85
        object_path = args[1]
om@2
    86
        interfaces_and_properties = args[2]
om@2
    87
        interface_keys = interfaces_and_properties.keys()
om@2
    88
        
om@2
    89
        if (interface_keys[0] == 'org.freedesktop.UDisks2.Drive'):
om@2
    90
            
om@2
    91
            # added a new drive
om@2
    92
            drive_values = interfaces_and_properties[interface_keys[0]]
om@2
    93
            drive_id = str(drive_values['Id'])
om@2
    94
            drive_vendor = str(drive_values['Vendor'])
om@2
    95
            drive_removeable = bool(drive_values['Removable'])
om@2
    96
            print('detected new drive: id=\'{0}\' vendor=\'{1}\' removeable={2}'.format(drive_id, drive_vendor, drive_removeable))
om@2
    97
        
om@2
    98
        if (interface_keys[0] == 'org.freedesktop.UDisks2.Block'):
om@2
    99
            
om@2
   100
            # added a new device - filesystem?
om@2
   101
            if ('org.freedesktop.UDisks2.Filesystem' in interface_keys):
om@2
   102
                
om@2
   103
                # pick values of the device
om@2
   104
                device_values = interfaces_and_properties[interface_keys[0]]
om@2
   105
                device_path = bytearray(device_values['Device'][0:-1]).decode('latin-1')
om@2
   106
                print('detected new device: path=\'{0}\''.format(device_path))
om@2
   107
                enforce_mount('/org/freedesktop/UDisks2/block_devices/' + device_path.split('/')[-1])
om@2
   108
            
om@2
   109
om@2
   110
    def listen(self):
om@2
   111
        """Start listening on DBus"""
om@2
   112
        self.loop = gobject.MainLoop()
om@2
   113
        self.loop.run()
om@2
   114
om@2
   115
om@2
   116
    @dbus.service.method('at.ac.ait.opensecurity.AutoShadow')
om@2
   117
    def Quit(self):
om@2
   118
        """Terminate this service"""
om@2
   119
        self.loop.quit()
om@2
   120
om@2
   121
om@2
   122
    @dbus.service.method('at.ac.ait.opensecurity.AutoShadow', out_signature='s')
om@2
   123
    def Version(self):
om@2
   124
        """Give a version string"""
om@2
   125
        return __version__
om@2
   126
om@2
   127
om@2
   128
def enforce_mount(udisk_object):
om@2
   129
    
om@2
   130
    """This function does the real mounting of drives. 
om@2
   131
    It also enforces the MirrorFuse on these mounts.
om@2
   132
    """
om@2
   133
    
om@2
   134
    print("ENFORCING mount of " + udisk_object)
om@2
   135
om@2
   136
om@2
   137
def main():             
om@2
   138
            
om@2
   139
    # parse command line
om@2
   140
    parser = argparse.ArgumentParser(description = 'Automount USB storage devices and invoke shadowfuse for it.')
om@2
   141
    args = parser.parse_args()
om@2
   142
    
om@2
   143
    # setup DBus event loop
om@2
   144
    autoshadow_service = AutoShadowService()
om@2
   145
    autoshadow_service.listen()    
om@2
   146
    
om@2
   147
om@2
   148
# start
om@2
   149
if __name__ == "__main__":
om@2
   150
    main()
om@2
   151
om@2
   152