Найти - Пользователи
Полная версия: hal mount часть 2
Начало » Python для экспертов » hal mount часть 2
1 2
pythonwin
доброго времени суток!

кто разбирался с dbus-python, пожалуйста, подскажите как определить куда автоматически примаунтился usb-disc

есть обработка подключения нового устройства через
bus = dbus.SystemBus()
bus.add_signal_receiver(def_device_add, 'DeviceAdded', 'org.freedesktop.Hal.Manager', 'org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')

в def_device_add проверяем аргументы на содержание “volume” и смотрим /mnt и д.р. папки или /etc/mtab

при этом на NewCapability тоже прописана функция, но почему-то она не выполняется

нашел код почти решающий задачу, но он при запуске ругается

hal_service = bus.get_service('org.freedesktop.Hal')
AttributeError: ‘SystemBus’ object has no attribute ‘get_service’


#!/usr/bin/python
import dbus
import gtk
import time
# This is just a very very crude example of what a volume daemon could
# look like... It actually doesn't mount anything; it only prints out
# messages when it should mount/unmount stuff.
#
# A volume daemon should also support optical and floppy disks, it should
# handle multisession cdroms and much more. Maybe someone will write
# this one day... Maybe the disc change stuff should even be in HAL?
#
# This requires udev with DBUS enabled and HAL to work correctly
#
def get_mount_location(udi, device_name):
    """Given a the UDI for a device and the name of the device file,
    determine a name for the mount point"""
    return '/mnt/somewhere/unique%f'%(time.time())
def attempt_mount(udi):
    """See if a block device has enough information so we can mount it"""
    dobj = hal_service.get_object(udi, 'org.freedesktop.Hal.Device')
    if (not mount_dict.has_key(udi)) and dobj.PropertyExists('block.device'):
        device = dobj.GetProperty('block.device')
        mount_location = get_mount_location(udi, device)
        print "mounting device=%s at %s udi=%s"%(device, mount_location, udi)
        mount_dict[udi] = mount_location
def unmount(udi):
    """Unmount a device"""
    mount_location = mount_dict[udi]
    print "unmounting %s"%mount_location
    del mount_dict[udi]
def device_changed(dbus_if, member, svc, obj_path, message):
    """Called when properties on a HAL device changes"""
    #print member
    udi = obj_path
    if udi in vol_list:
        attempt_mount(udi)
def gdl_changed(dbus_if, member, svc, obj_path, message):
    """Called when a HAL device is added, removed or it got a
    new capability"""
    #print member
    if member=='NewCapability':
        [udi, cap] = message.get_args_list()
        if cap=='volume':
            if not udi in vol_list:
                vol_list.append(udi)
                bus.add_signal_receiver(device_changed,
                                        'org.freedesktop.Hal.Device',
                                        'org.freedesktop.Hal',
                                        udi)
                attempt_mount(udi)
                
        #print "  %s %s"%(cap,udi)
    elif member=='DeviceRemoved':
        [udi] = message.get_args_list()
        if udi in vol_list:
            vol_list.remove(udi)
            bus.remove_signal_receiver(device_changed,
                                       'org.freedesktop.Hal.Device',
                                       'org.freedesktop.Hal',
                                       udi)
            unmount(udi)
            
    elif member=='DeviceAdded':
        [udi] = message.get_args_list()
        dobj = hal_service.get_object(udi, 'org.freedesktop.Hal.Device')
        #if dobj.PropertyExists('Capabilities'):
        #    print '  caps=%s'%(dobj.GetProperty('Capabilities'))
        if dobj.QueryCapability('volume'):
            vol_list.append(udi)
            bus.add_signal_receiver(device_changed,
                                    'org.freedesktop.Hal.Device',
                                    'org.freedesktop.Hal',
                                    udi)
            attempt_mount(udi)
def main():
    """Entry point"""
    global bus, hal_service, vol_list, mount_dict
    vol_list = []
    mount_dict = {}
    
    bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM)
##    bus = dbus.SystemBus()
    hal_service = bus.get_service('org.freedesktop.Hal')
    bus.add_signal_receiver(gdl_changed,
                            'org.freedesktop.Hal.Manager',
                            'org.freedesktop.Hal',
                            '/org/freedesktop/Hal/Manager')
    gtk.mainloop()
if __name__=='__main__':
    main()
slivlen
pythonwin
нашел код почти решающий задачу, но он при запуске ругается
Похоже python api для dbus старый. Используй интерфейс к HAL Manager вместо hal_service:
sys_bus = dbus.SystemBus()
hal = sys_bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
hal_iface = dbus.Interface(hal, 'org.freedesktop.Hal.Manager')
А вместо этого кода для получения объекта устройства по udi
dobj = hal_service.get_object(udi, 'org.freedesktop.Hal.Device')
используй этот:
dobj=sys_bus.get_object('org.freedesktop.Hal', udi)
slivlen
Щас внимательней просмотрел твой пример и заметил, что тебе даже HAL Manager не требуется. Нужен только объект системной шины, через который можно объекты устройств получать.
pythonwin
а пример сможешь дать или ссылку на решение аналогичной проблемы?
slivlen
pythonwin
а пример сможешь дать или ссылку на решение аналогичной проблемы?
Так у тебя уже есть пример :) Просто замени соответствующие строки в нем так, как я описал в предыдущем посте и должно все завестись.
pythonwin
пожалуйста, подскажите как определить куда автоматически примаунтился usb-disc
Самое простое - с помощью mount :). А если через Hal, то надо найти все устройства которые предоставляют capability volume и среди них найти такое, info.parent которого == udi твоего usb-disc и получить его свойство volume.mount_point.
pythonwin
поменял - запускается, но просто не срабатывает на событие(я)
#!/usr/bin/python
import dbus
import gtk
import time, gobject
# This is just a very very crude example of what a volume daemon could
# look like... It actually doesn't mount anything; it only prints out
# messages when it should mount/unmount stuff.
#
# A volume daemon should also support optical and floppy disks, it should
# handle multisession cdroms and much more. Maybe someone will write
# this one day... Maybe the disc change stuff should even be in HAL?
#
# This requires udev with DBUS enabled and HAL to work correctly
#
def get_mount_location(udi, device_name):
    """Given a the UDI for a device and the name of the device file,
    determine a name for the mount point"""
    return '/mnt/somewhere/unique%f'%(time.time())
def attempt_mount(udi):
    """See if a block device has enough information so we can mount it"""
##    dobj = hal_service.get_object(udi, 'org.freedesktop.Hal.Device')
    dobj = bus.get_object(udi, 'org.freedesktop.Hal.Device')
    if (not mount_dict.has_key(udi)) and dobj.PropertyExists('block.device'):
        device = dobj.GetProperty('block.device')
        mount_location = get_mount_location(udi, device)
        print "mounting device=%s at %s udi=%s"%(device, mount_location, udi)
        mount_dict[udi] = mount_location
def unmount(udi):
    """Unmount a device"""
    mount_location = mount_dict[udi]
    print "unmounting %s"%mount_location
    del mount_dict[udi]
def device_changed(dbus_if, member, svc, obj_path, message):
    """Called when properties on a HAL device changes"""
    #print member
    udi = obj_path
    if udi in vol_list:
        attempt_mount(udi)
def gdl_changed(dbus_if, member, svc, obj_path, message):
    """Called when a HAL device is added, removed or it got a
    new capability"""
    print member
    if member=='NewCapability':
        [udi, cap] = message.get_args_list()
        if cap=='volume':
            if not udi in vol_list:
                vol_list.append(udi)
                bus.add_signal_receiver(device_changed,
                                        'org.freedesktop.Hal.Device',
                                        'org.freedesktop.Hal',
                                        udi)
                attempt_mount(udi)
                
        #print "  %s %s"%(cap,udi)
    elif member=='DeviceRemoved':
        [udi] = message.get_args_list()
        if udi in vol_list:
            vol_list.remove(udi)
            bus.remove_signal_receiver(device_changed,
                                       'org.freedesktop.Hal.Device',
                                       'org.freedesktop.Hal',
                                       udi)
            unmount(udi)
            
    elif member=='DeviceAdded':
        [udi] = message.get_args_list()
##        dobj = hal_service.get_object(udi, 'org.freedesktop.Hal.Device')
        dobj = bus.get_object(udi, 'org.freedesktop.Hal.Device')
        #if dobj.PropertyExists('Capabilities'):
        #    print '  caps=%s'%(dobj.GetProperty('Capabilities'))
        if dobj.QueryCapability('volume'):
            vol_list.append(udi)
            bus.add_signal_receiver(device_changed,
                                    'org.freedesktop.Hal.Device',
                                    'org.freedesktop.Hal',
                                    udi)
            attempt_mount(udi)
def main():
    """Entry point"""
    global bus, hal_service, vol_list, mount_dict
    vol_list = []
    mount_dict = {}
    
##    bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM)
    bus = dbus.SystemBus()
##
    hal_manager_obj = bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
    hal_manager = dbus.Interface(hal_manager_obj, 'org.freedesktop.Hal.Manager')
    systems1 = bus.get_system()
##    hal_service = bus.get_service('org.freedesktop.Hal')
##    bus.add_signal_receiver(handler_function=gdl_changed,
##                            signal_name=None,
##                            dbus_interface='org.freedesktop.Hal.Manager',
##                            named_service='org.freedesktop.Hal',
##                            path='/org/freedesktop/Hal/Manager')
##    
    bus.add_signal_receiver(gdl_changed, 'DeviceAdded',
                            'org.freedesktop.Hal.Manager',
                            'org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
##    bus.add_signal_receiver(handler_function=gdl_changed,
##                            signal_name='DeviceAdded',
##                            dbus_interface='org.freedesktop.Hal.Manager',
##                            named_service='org.freedesktop.Hal',
##                            path='/org/freedesktop/Hal/Manager')
##
##    bus.add_signal_receiver(gdl_changed,
##                            'org.freedesktop.Hal.Manager',
##                            'org.freedesktop.Hal',
##                            '/org/freedesktop/Hal/Manager')
##    gtk.mainloop()
    loop = gobject.MainLoop()
    loop.run()
if __name__=='__main__':
    main()
пробовал несколько вариантов bus.add_signal_receiver - ни один не реагирует :(
ac
в приведенных выше примерах используется старый API…
у меня естьрабочий пример на новом API…
import gobject 
import threading
import dbus
import os
import sys
if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
  import dbus.glib
class CardReceiver(threading.Thread):
    def __init__(self, tmp_dir, system_core, gui):
        threading.Thread.__init__(self)
        self.__system_core = system_core
        self.__tmp_dir = tmp_dir
        self.__bus = dbus.SystemBus()
        self.__gui = gui
        hal_manager_obj = self.__bus.get_object('org.freedesktop.Hal', 
                                                    '/org/freedesktop/Hal/Manager')
        hal_manager = dbus.Interface(hal_manager_obj, 'org.freedesktop.Hal.Manager')
        hal_manager.connect_to_signal('DeviceAdded', self.device_added_callback)
        hal_manager.connect_to_signal('DeviceRemoved', self.device_removed_callback)
    
    def run(self):
        print "Waiting for card..."
        self.__gui.displayInfo('Waiting for card...')
        #gobject.MainLoop().run()
            
    def __del__(self):
        self.__bus.close();
    def device_added_callback(self,udi):
        self.device = self.__bus.get_object ('org.freedesktop.Hal', udi)
        print "DEBUG: Added device %s" % udi
        self.__gui.displayInfo('Analysing card...')
        if (self.device.PropertyExists('info.category') and (self.device.GetProperty('info.category') == 'volume')):
            self.dev_path = self.device.GetProperty('block.device')
            print "Founded storage device at %s" % self.dev_path
            os.system('mkdir -p ' + self.__tmp_dir + '/storage')
            os.system('mount ' + self.dev_path + ' ' + self.__tmp_dir + '/storage')
            self.readCard()
        
    def device_removed_callback(self, udi):
        self.returnCard()
        self.__gui.hidewinPIN()
        self.__gui.hidewinAccountData()
        self.__gui.displayInfo('Waiting for card...')
        
    def readCard(self):
        if (os.path.exists(self.__tmp_dir + '/storage/openb.data')):
            self.__id = open(self.__tmp_dir + '/storage/openb.data').readline()
            print "DEBUG: openb.data exists... card is valid [ %s ]" % self.__id
            self.__system_core.getAccount(self.__id)
        else:
            print "card is invalid..."
            self.__gui.displayInfo('card is invalid...')
            self.returnCard()
    def umountCard(self):
        print "DEBUG: unmounting..."
        os.system('umount ' + self.__tmp_dir + '/storage')
    
    def returnCard(self):
        self.umountCard()
        
    def moveCardToRepository(self):
        self.umountCard()
        self.__gui.displayInfo('Moving card to repository...')
        print "Moving card to repository..."

З.Ы.: 1. На threading не обращаем внимаения - к проблеме dbus/hal это не имеет никакого отношения.
2. Для связывания реакции на событие (например, DeviceAdded) и метода, обрабатывающего это событие, используется метод connect_to_signal.
pythonwin
что должен содержать udi ?
slivlen
pythonwin
что должен содержать udi ?
udi - уникальный идентификатор устройства.
Выполни команду ‘lshal | grep udi’ и посмотри как выглядит udi.
pythonwin
slivlen
udi - уникальный идентификатор устройства.
Выполни команду ‘lshal | grep udi’ и посмотри как выглядит udi.
спасибо!

а как получить список всех свойств типа info.parent, block.storage_device, block.device и … ?

slivlen
А если через Hal, то надо найти все устройства которые предоставляют capability volume и среди них найти такое, info.parent которого == udi твоего usb-disc и получить его свойство volume.mount_point.
написал

    device = bus.get_object ('org.freedesktop.Hal', udi)
    if (device.PropertyExists('info.category') and (device.GetProperty('info.category') == 'volume')):
        fstype = device.GetProperty ('volume.fstype')
        dev_path = device.GetProperty('block.device')
        storage_udi = device.GetProperty ('block.storage_device')
        storage = bus.get_object ('org.freedesktop.Hal', storage_udi)
        drive_type = storage.GetProperty ('storage.drive_type')
        #
        info_parent = device.GetProperty ('info.parent')
        parent = bus.get_object ('org.freedesktop.Hal', info_parent)
        mount_point = parent.GetProperty ('volume.mount_point')        ##  здесь ругается
Exception dbus_bindings.DBusException: ‘No property volume.mount_point on device with id /org/freedesktop/Hal/devices/storage_serial_Generic_USB_Flash_Disk_0000000000319A’ in ‘dbus_bindings._GIL_safe_cmessage_function_handler’ ignored


ac, slivlen спасибо за помощь :)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB