def update(self, backend = None, *args, **kwargs): """ Update the database """ import sources yield sources.update(self._db, backend, *args, **kwargs) kaa.MainThreadCallable(self._sync)()
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
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
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
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
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