Beispiel #1
0
 def update(self, backend = None, *args, **kwargs):
     """
     Update the database
     """
     import sources
     yield sources.update(self._db, backend, *args, **kwargs)
     kaa.MainThreadCallable(self._sync)()
Beispiel #2
0
def thread2(c, x):
    # call rpc in thread using MainThreadCallback
    cb = kaa.MainThreadCallable(c.rpc)
    # we not only wait to get the InProgress back, we also wait
    # for the real return from rpc
    #cb.set_async(False)
    x = cb('test5', x).wait()
    print x
    return x + 1
Beispiel #3
0
    def rpc(self, cmd, *args, **kwargs):
        """
        Call the remote command and return InProgress.
        """
        if not CoreThreading.is_mainthread():
            # create InProgress object and return
            callback = kaa.InProgress()
            kwargs['_kaa_rpc_callback'] = callback
            kaa.MainThreadCallable(self.rpc)(cmd, *args, **kwargs)
            return callback

        if not self.connected:
            raise NotConnectedError()

        seq = self._next_seq
        self._next_seq += 1
        # create InProgress object
        callback = kwargs.pop('_kaa_rpc_callback', kaa.InProgress())
        payload = cPickle.dumps((cmd, args, kwargs), PICKLE_PROTOCOL)
        self._send_packet(seq, 'CALL', payload)
        # callback with error handler
        self._rpc_in_progress[seq] = (callback, cmd)
        return callback
Beispiel #4
0
 def do_POST(self):
     ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
     if ctype != 'application/json':
         log.error('HTTP/POST not JSON: %s' % ctype)
         self.send_response(500)
         self.end_headers()
         return
     length = int(self.headers.getheader('content-length'))
     data = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1)
     parse_result = urlparse.urlparse(self.path)
     try:
       for path, callback, ctype, encoding in self.server._get_handler:
         if path == parse_result.path or \
                 (parse_result.path.startswith(path) and path.endswith('/')):
             path = parse_result.path[len(path):]
             result = []
             for key in data.keys():
                 calls = json.loads(key)
                 if not isinstance(calls, (list, tuple)):
                     calls = (calls,)
                 for c in calls:
                     result.append(kaa.MainThreadCallable(callback)(path, **c).wait())
             if len(result) == 1:
                 result = json.dumps(result[0])
             else:
                 result = json.dumps(result)
             self.send_response(200)
             self.send_header("Content-type", ctype)
             self.send_header("Content-Length", len(result))
             # self.send_header("Content-Encoding", encoding)
             self.end_headers()
             self.wfile.write(result)
             return
     except:
         self.send_response(500)
         log.exception('server error')
         return
Beispiel #5
0
class UDisks(object):
    """
    Hardware monitor based on UDisks (dbus)
    """
    def __init__(self, handler, db, rootfs):
        log.info('start hardware monitor')
        self._db = db
        # handler == beacon.server.Controller
        self.handler = handler
        self.partition_tables = []
        self.detected_devices = {}
        self._gobject_init()
        self._device_update_media(rootfs)

    @kaa.threaded(kaa.GOBJECT)
    def _gobject_init(self):
        """
        Connect to dbus and start to connect to UDisks.
        """
        self.bus = dbus.SystemBus()
        self.proxy = self.bus.get_object("org.freedesktop.UDisks",
                                         "/org/freedesktop/UDisks")
        self.iface = dbus.Interface(self.proxy, "org.freedesktop.UDisks")
        # #####################################################################
        # The code is broken
        # #####################################################################
        # self.iface.connect_to_signal('DeviceAdded', self._device_udisks_update)
        # self.iface.connect_to_signal('DeviceRemoved', self._device_remove)
        # self.iface.connect_to_signal('DeviceChanged', self._device_udisks_update)
        # for dev in self.iface.EnumerateDevices():
        #     self._device_udisks_update(dev)

    @kaa.threaded(kaa.GOBJECT)
    def mount(self, devdict):
        """
        Mount the device.
        """
        def success(*args):
            pass

        def error(error):
            log.error('unable to mount %s: %s', devdict['block.device'], error)

        path = self.iface.FindDeviceByDeviceFile(devdict['block.device'])
        dbus = self.bus.get_object(OBJ_UDISKS, path)
        dbus.FilesystemMount('', ['auth_no_user_interaction'],
                             reply_handler=success,
                             error_handler=error)

    @kaa.threaded(kaa.GOBJECT)
    def eject(self, devdict):
        """
        Eject the device. This includes umounting and removing from
        the list. Devices that can't be ejected (USB sticks) are only
        umounted and removed from the list.
        """
        def success(*args):
            pass

        def error(error):
            log.error('unable to umount %s: %s', devdict['block.device'],
                      error)

        path = self.iface.FindDeviceByDeviceFile(devdict['block.device'])
        dbus = self.bus.get_object(OBJ_UDISKS, path)
        if path in self.detected_devices:
            del self.detected_devices[path]
        if devdict.get('volume.is_disc'):
            dbus.DriveEject(['unmount'],
                            reply_handler=success,
                            error_handler=error)
        if devdict.get('volume.mount_point'):
            dbus.FilesystemUnmount(['force'],
                                   reply_handler=success,
                                   error_handler=error)

    @kaa.threaded(kaa.MAINTHREAD)
    def _device_remove(self, path):
        """
        Remove a device from the list. This function is called by
        UDisks when a device is removed (e.g. USB sicks) or by
        _device_udisks_update when an optical drive lost its media.
        """
        devdict = self.detected_devices.get(path)
        if not devdict:
            for devdict in self.detected_devices.values()[:]:
                if devdict.get('block.parent') == path:
                    self._device_remove(devdict.get('block.path'))
            return
        beacon_id = devdict.get('beacon.id')
        media = self._db.medialist.get_by_media_id(beacon_id)
        if media is not None:
            log.info('remove device %s' % beacon_id)
            self.handler.media_removed(media)
            self._db.medialist.remove(beacon_id)

    def _device_udisks_update(self, path):
        """
        Gather information about the device described by the UDisks
        path. Note: path is NOT the device path in the filesystem; it
        is the UDisks device path.
        """
        try:
            device_obj = self.bus.get_object(OBJ_UDISKS, path)
            device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE)
            DeviceIsMediaAvailable = device_props.Get(
                'org.freedesktop.UDisks.Device', "DeviceIsMediaAvailable")
            DeviceIsRemovable = device_props.Get(
                'org.freedesktop.UDisks.Device', "DeviceIsRemovable")
            DeviceFile = device_props.Get('org.freedesktop.UDisks.Device',
                                          "DeviceFile")
            IdUuid = device_props.Get('org.freedesktop.UDisks.Device',
                                      "IdUuid")
            IdLabel = device_props.Get('org.freedesktop.UDisks.Device',
                                       "IdLabel")
        except Exception, e:
            log.error('unable to get dbus information: %s', e)
            return False
        # Try to figure out if the device is a removable drive beacon
        # can mount or a media player can play. Right now it can
        # detect optical media and USB sticks. A disc connected via
        # USB may not get detected. For historical reasons the
        # information is stored in a dict with names used by HAL. This
        # should be changed in the future. Other media such as SD
        # cards are not supported yet. Feel free to send patches.
        if not DeviceIsMediaAvailable and path in self.detected_devices:
            # The media was available before and is not anymore. This
            # happens for optical drives where the drive itself is not
            # removed, only the media.
            self._device_remove(path)
            return True
        if device_props.Get('org.freedesktop.UDisks.Device',
                            "DeviceIsOpticalDisc"):
            # Disc in an optical drive
            devdict = {
                'beacon.id':
                str(IdUuid) or kaa.metadata.cdrom.status(DeviceFile)[1],
                'volume.mount_point':
                '',
                'volume.is_disc':
                True,
                'volume.label':
                str(IdLabel),
                'volume.read_only':
                True,
                'block.device':
                str(DeviceFile)
            }
            self.detected_devices[str(path)] = devdict
            return kaa.MainThreadCallable(self._device_update_media)(devdict)
        if DeviceIsRemovable and device_props.Get(
                'org.freedesktop.UDisks.Device', 'DeviceIsPartitionTable'):
            # UDisks reports USB sticks with a filesystem as two
            # different things. The actual device (/dev/sdX) is
            # removable, but of course we cannot mount it. But we have
            # to remember that information because the partition
            # (/dev/sdX1) is not reported as removable.
            self.partition_tables.append(path)
            return True
        is_filesystem = False
        if device_props.Get('org.freedesktop.UDisks.Device',
                            'DeviceIsPartition'):
            # Device is a partition. Check if it is on a removable
            # device. If not, do not cover it.
            for parent in self.partition_tables:
                if path.startswith(parent):
                    break
            else:
                return True
            is_filesystem = True
        if DeviceIsRemovable and DeviceIsMediaAvailable:
            # USB stick without partition table. We should be able to
            # mount /dev/sdX directly. Sadly UDisks does not give away
            # the information what kind of filesystem there is to be
            # sure it is a mountable partition.
            is_filesystem = True
            parent = None
        if not is_filesystem:
            return True
        # Either partition or whole device with a filesystem on it we
        # should be able to mount.
        devdict = {
            'beacon.id':
            str(IdUuid),
            'volume.mount_point':
            '',
            'volume.is_disc':
            False,
            'volume.label':
            str(IdLabel),
            'volume.read_only':
            bool(
                device_props.Get('org.freedesktop.UDisks.Device',
                                 'DeviceIsReadOnly')),
            'block.device':
            str(DeviceFile),
            'block.parent':
            str(parent),
            'block.path':
            str(path)
        }
        DeviceMountPaths = device_props.Get('org.freedesktop.UDisks.Device',
                                            'DeviceMountPaths')
        if DeviceMountPaths:
            # mounted at some location
            devdict['volume.mount_point'] = str(DeviceMountPaths[0])
        self.detected_devices[str(path)] = devdict
        kaa.MainThreadCallable(self._device_update_media)(devdict)
        return True
Beispiel #6
0
 def do_GET(self):
     """
     Serve a GET request.
     """
     callback = None
     parse_result = urlparse.urlparse(self.path)
     for path, callback, ctype, encoding in self.server._get_handler:
         if path == parse_result.path or \
                 (parse_result.path.startswith(path) and path.endswith('/')):
             path = parse_result.path[len(path):]
             try:
                 attributes = {}
                 for key, value in urlparse.parse_qs(parse_result.query).items():
                     if isinstance(value, (list, tuple)):
                         if len(value) == 0:
                             attributes[key] = True
                         elif len(value) == 1:
                             attributes[key] = value[0]
                         else:
                             attributes[key] = value
                     else:
                         attributes[key] = value
                 result = kaa.MainThreadCallable(callback)(path, **attributes).wait()
             except:
                 self.send_response(500)
                 log.exception('server error')
                 return
             if result is None:
                 # return 404
                 self.send_response(404)
                 self.end_headers()
                 return
             # we need content, content type and content encoding
             # as result if not already provided when registering
             # the callback
             if ctype is None or encoding is None:
                 # return must be a list with the actual content as
                 # first item and ctype and encoding if missing
                 # following.
                 result = list(result)
                 if encoding is None:
                     encoding = result.pop()
                 if ctype is None:
                     ctype = result.pop()
                 result = result[0]
             if ctype == "application/json":
                 result = json.dumps(result)
             self.send_response(200)
             self.send_header("Content-type", ctype)
             self.send_header("Content-Length", len(result))
             self.send_header("Content-Encoding", encoding)
             self.end_headers()
             self.wfile.write(result)
             return
     if self.path in self.server._static:
         self.send_response(200)
         self.end_headers()
         f = open(self.server._static[self.path])
         shutil.copyfileobj(f, self.wfile)
         f.close()
         return
     abspath = os.path.abspath(self.path)
     for path, dirname in self.server._directories:
         if abspath.startswith(path):
             fname = os.path.join(dirname, abspath[len(path)+1:])
             if os.path.isfile(fname):
                 self.send_response(200)
                 self.end_headers()
                 f = open(fname)
                 shutil.copyfileobj(f, self.wfile)
                 f.close()
                 return
     self.send_response(404)
     self.end_headers()
     return