179
133
class Status(DBusExposedObject):
180
""" Represent the status of the syncdaemon """
134
"""Represent the status of the syncdaemon."""
182
def __init__(self, bus_name, dbus_iface):
183
""" Creates the instance.
136
def __init__(self, bus_name, dbus_iface, syncdaemon_status=None):
137
"""Create the instance.
185
139
@param bus: the BusName of this DBusExposedObject.
187
self.dbus_iface = dbus_iface
188
self.action_queue = dbus_iface.action_queue
189
self.fs_manager = dbus_iface.fs_manager
141
if not syncdaemon_status:
142
syncdaemon_status = SyncdaemonStatus(dbus_iface.main,
143
dbus_iface.action_queue,
144
dbus_iface.fs_manager)
145
self.syncdaemon_status = syncdaemon_status
190
146
self.path = '/status'
191
147
DBusExposedObject.__init__(self, bus_name=bus_name,
194
def _get_current_state(self):
195
"""Get the current status of the system."""
196
state = self.dbus_iface.main.state_manager.state
197
connection = self.dbus_iface.main.state_manager.connection.state
198
queues = self.dbus_iface.main.state_manager.queues.state.name
201
'description': state.description,
202
'is_error': bool_str(state.is_error),
203
'is_connected': bool_str(state.is_connected),
204
'is_online': bool_str(state.is_online),
206
'connection': connection,
210
150
@dbus.service.method(DBUS_IFACE_STATUS_NAME,
211
151
in_signature='', out_signature='a{ss}')
212
152
def current_status(self):
213
""" return the current status of the system, one of: local_rescan,
153
"""Return the current status of the system, one of: local_rescan,
214
154
offline, trying_to_connect, server_rescan or online.
216
156
logger.debug('called current_status')
217
return self._get_current_state()
157
return self.syncdaemon_status.current_status()
219
159
@dbus.service.method(DBUS_IFACE_STATUS_NAME, out_signature='aa{ss}')
220
160
def current_downloads(self):
221
161
"""Return a list of files with a download in progress."""
222
162
logger.debug('called current_downloads')
223
current_downloads = []
224
for cmd in self.action_queue.queue.waiting:
225
if isinstance(cmd, Download) and cmd.running:
228
'share_id': cmd.share_id,
229
'node_id': cmd.node_id,
230
'n_bytes_read': str(cmd.n_bytes_read),
232
if cmd.deflated_size is not None:
233
entry['deflated_size'] = str(cmd.deflated_size)
234
current_downloads.append(entry)
235
return current_downloads
237
def _get_command_path(self, cmd):
238
"""Return the path on which the command applies."""
240
if IMarker.providedBy(cmd.node_id):
241
# it's a marker! so it's the mdid :)
242
relpath = self.fs_manager.get_by_mdid(cmd.node_id).path
244
relpath = self.fs_manager.get_by_node_id(cmd.share_id,
246
path = self.fs_manager.get_abspath(cmd.share_id, relpath)
248
# probably in the trash (normal case for Unlink)
250
key = cmd.share_id, cmd.node_id
251
if key in self.fs_manager.trash:
252
node_data = self.fs_manager.trash[key]
253
if len(node_data) == 3:
163
return self.syncdaemon_status.current_downloads()
259
165
@dbus.service.method(DBUS_IFACE_STATUS_NAME, out_signature='a(sa{ss})')
260
166
def waiting_metadata(self):
472
349
self.dbus_iface.events.emit_event(event_dict)
475
class EventListener(object):
476
"""An Event Queue Listener."""
478
def __init__(self, dbus_iface):
479
self.dbus_iface = dbus_iface
481
def handle_AQ_DOWNLOAD_STARTED(self, share_id, node_id, server_hash):
482
"""Handle AQ_DOWNLOAD_STARTED."""
484
mdobj = self.dbus_iface.fs_manager.get_by_node_id(share_id, node_id)
487
path = self.dbus_iface.fs_manager.get_abspath(share_id, mdobj.path)
488
self.dbus_iface.status.emit_download_started(path)
490
args = dict(message='The md is gone before sending '
491
'DownloadStarted signal',
493
share_id=str(share_id),
494
node_id=str(node_id))
495
self.dbus_iface.status.emit_signal_error('DownloadStarted', args)
497
def handle_AQ_DOWNLOAD_FILE_PROGRESS(self, share_id, node_id,
498
n_bytes_read, deflated_size):
499
"""Handle AQ_DOWNLOAD_FILE_PROGRESS."""
501
mdobj = self.dbus_iface.fs_manager.get_by_node_id(share_id, node_id)
503
args = dict(message='The md is gone before sending '
504
'DownloadFileProgress signal',
506
share_id=str(share_id),
507
node_id=str(node_id))
508
self.dbus_iface.status.emit_signal_error('DownloadFileProgress',
511
path = self.dbus_iface.fs_manager.get_abspath(share_id, mdobj.path)
512
self.dbus_iface.status.emit_download_file_progress(path,
513
n_bytes_read=n_bytes_read,
514
deflated_size=deflated_size
517
def handle_AQ_DOWNLOAD_FINISHED(self, share_id, node_id, server_hash):
518
"""Handle AQ_DOWNLOAD_FINISHED."""
520
mdobj = self.dbus_iface.fs_manager.get_by_node_id(share_id, node_id)
523
path = self.dbus_iface.fs_manager.get_abspath(share_id, mdobj.path)
524
self.dbus_iface.status.emit_download_finished(path)
526
# file is gone before we got this
527
args = dict(message='The md is gone before sending '
528
'DownloadFinished signal',
530
share_id=str(share_id),
531
node_id=str(node_id))
532
self.dbus_iface.status.emit_signal_error('DownloadFinished', args)
534
def handle_AQ_DOWNLOAD_CANCELLED(self, share_id, node_id, server_hash):
535
"""Handle AQ_DOWNLOAD_CANCELLED."""
536
self.handle_AQ_DOWNLOAD_ERROR(share_id, node_id, server_hash,
537
'CANCELLED', 'AQ_DOWNLOAD_CANCELLED')
539
def handle_AQ_DOWNLOAD_ERROR(self, share_id, node_id, server_hash, error,
540
event='AQ_DOWNLOAD_ERROR'):
541
"""Handle AQ_DOWNLOAD_ERROR."""
543
mdobj = self.dbus_iface.fs_manager.get_by_node_id(share_id, node_id)
546
path = self.dbus_iface.fs_manager.get_abspath(share_id, mdobj.path)
547
self.dbus_iface.status.emit_download_finished(path, error=error)
549
# file is gone before we got this
550
args = dict(message='The md is gone before sending '
551
'DownloadFinished signal',
553
share_id=str(share_id),
554
node_id=str(node_id),
555
download_error=str(error))
556
self.dbus_iface.status.emit_signal_error('DownloadFinished', args)
558
def handle_AQ_UPLOAD_STARTED(self, share_id, node_id, hash):
559
"""Handle AQ_UPLOAD_STARTED."""
561
mdobj = self.dbus_iface.fs_manager.get_by_node_id(share_id, node_id)
564
path = self.dbus_iface.fs_manager.get_abspath(share_id, mdobj.path)
565
self.dbus_iface.status.emit_upload_started(path)
567
args = dict(message='The md is gone before sending '
568
'UploadStarted signal',
570
share_id=str(share_id),
571
node_id=str(node_id))
572
self.dbus_iface.status.emit_signal_error('UploadStarted', args)
574
def handle_AQ_UPLOAD_FILE_PROGRESS(self, share_id, node_id,
575
n_bytes_written, deflated_size):
576
"""Handle AQ_UPLOAD_FILE_PROGRESS."""
578
mdobj = self.dbus_iface.fs_manager.get_by_node_id(share_id, node_id)
580
args = dict(message='The md is gone before sending '
581
'UploadFileProgress signal',
583
share_id=str(share_id),
584
node_id=str(node_id))
585
self.dbus_iface.status.emit_signal_error('UploadFileProgress',
588
path = self.dbus_iface.fs_manager.get_abspath(share_id, mdobj.path)
589
self.dbus_iface.status.emit_upload_file_progress(path,
590
n_bytes_written=n_bytes_written,
591
deflated_size=deflated_size
594
def handle_AQ_UPLOAD_FINISHED(self, share_id, node_id, hash,
596
"""Handle AQ_UPLOAD_FINISHED."""
598
mdobj = self.dbus_iface.fs_manager.get_by_node_id(share_id,
602
path = self.dbus_iface.fs_manager.get_abspath(share_id, mdobj.path)
603
self.dbus_iface.status.emit_upload_finished(path)
605
# file is gone before we got this
606
args = dict(message='The metadata is gone before sending '
607
'UploadFinished signal',
609
share_id=str(share_id),
610
node_id=str(node_id))
611
self.dbus_iface.status.emit_signal_error('UploadFinished', args)
613
def handle_SV_ACCOUNT_CHANGED(self, account_info):
614
"""Handle SV_ACCOUNT_CHANGED."""
615
self.dbus_iface.status.emit_account_changed(account_info)
617
def handle_AQ_UPLOAD_ERROR(self, share_id, node_id, error, hash):
618
"""Handle AQ_UPLOAD_ERROR."""
620
mdobj = self.dbus_iface.fs_manager.get_by_node_id(share_id, node_id)
623
path = self.dbus_iface.fs_manager.get_abspath(share_id, mdobj.path)
624
self.dbus_iface.status.emit_upload_finished(path, error=error)
626
# file is gone before we got this
627
args = dict(message='The metadata is gone before sending '
628
'UploadFinished signal',
630
share_id=str(share_id),
631
node_id=str(node_id),
632
upload_error=str(error))
633
self.dbus_iface.status.emit_signal_error('UploadFinished', args)
635
def handle_FS_INVALID_NAME(self, dirname, filename):
636
"""Handle FS_INVALID_NAME."""
637
self.dbus_iface.status.emit_invalid_name(dirname, filename)
639
def handle_SYS_BROKEN_NODE(self, volume_id, node_id, mdid, path):
640
"""Handle SYS_BROKEN_NODE."""
641
self.dbus_iface.status.emit_broken_node(volume_id, node_id, mdid, path)
643
def handle_SYS_STATE_CHANGED(self, state):
644
"""Handle SYS_STATE_CHANGED."""
645
self.dbus_iface.status.emit_status_changed(state)
647
def handle_SV_FREE_SPACE(self, share_id, free_bytes):
648
"""Handle SV_FREE_SPACE event, emit ShareChanged signal."""
649
self.dbus_iface.shares.emit_free_space(share_id, free_bytes)
651
def handle_AQ_CREATE_SHARE_OK(self, share_id, marker):
652
"""Handle AQ_CREATE_SHARE_OK event, emit ShareCreated signal."""
653
share = self.dbus_iface.volume_manager.shared.get(str(share_id))
656
# pylint: disable-msg=W0212
657
share_dict.update(_get_share_dict(share))
659
share_dict.update(dict(volume_id=str(share_id)))
660
self.dbus_iface.shares.emit_share_created(share_dict)
662
def handle_AQ_CREATE_SHARE_ERROR(self, marker, error):
663
"""Handle AQ_CREATE_SHARE_ERROR event, emit ShareCreateError signal."""
664
self.dbus_iface.shares.emit_share_create_error(dict(marker=marker),
667
def handle_AQ_ANSWER_SHARE_OK(self, share_id, answer):
668
""" handle AQ_ANSWER_SHARE_OK event, emit ShareAnswerOk signal. """
669
self.dbus_iface.shares.emit_share_answer_response(str(share_id), answer)
671
def handle_AQ_ANSWER_SHARE_ERROR(self, share_id, answer, error):
672
"""Handle AQ_ANSWER_SHARE_ERROR event, emit ShareAnswerError signal."""
673
self.dbus_iface.shares.emit_share_answer_response(str(share_id), answer,
675
def handle_VM_UDF_SUBSCRIBED(self, udf):
676
"""Handle VM_UDF_SUBSCRIBED event, emit FolderSubscribed signal."""
677
self.dbus_iface.folders.emit_folder_subscribed(udf)
679
def handle_VM_UDF_SUBSCRIBE_ERROR(self, udf_id, error):
680
"""Handle VM_UDF_SUBSCRIBE_ERROR, emit FolderSubscribeError signal."""
681
self.dbus_iface.folders.emit_folder_subscribe_error(udf_id, error)
683
def handle_VM_UDF_UNSUBSCRIBED(self, udf):
684
"""Handle VM_UDF_UNSUBSCRIBED event, emit FolderUnSubscribed signal."""
685
self.dbus_iface.folders.emit_folder_unsubscribed(udf)
687
def handle_VM_UDF_UNSUBSCRIBE_ERROR(self, udf_id, error):
688
"""Handle VM_UDF_UNSUBSCRIBE_ERROR, emit FolderUnSubscribeError."""
689
self.dbus_iface.folders.emit_folder_unsubscribe_error(udf_id, error)
691
def handle_VM_UDF_CREATED(self, udf):
692
"""Handle VM_UDF_CREATED event, emit FolderCreated signal."""
693
self.dbus_iface.folders.emit_folder_created(udf)
695
def handle_VM_UDF_CREATE_ERROR(self, path, error):
696
"""Handle VM_UDF_CREATE_ERROR event, emit FolderCreateError signal."""
697
self.dbus_iface.folders.emit_folder_create_error(path, error)
699
def handle_VM_SHARE_SUBSCRIBED(self, share):
700
"""Handle VM_SHARE_SUBSCRIBED event, emit ShareSubscribed signal."""
701
self.dbus_iface.shares.emit_share_subscribed(share)
703
def handle_VM_SHARE_SUBSCRIBE_ERROR(self, share_id, error):
704
"""Handle VM_SHARE_SUBSCRIBE_ERROR, emit ShareSubscribeError signal."""
705
self.dbus_iface.shares.emit_share_subscribe_error(share_id, error)
707
def handle_VM_SHARE_UNSUBSCRIBED(self, share):
708
"""Handle VM_SHARE_UNSUBSCRIBED event, emit ShareUnSubscribed."""
709
self.dbus_iface.shares.emit_share_unsubscribed(share)
711
def handle_VM_SHARE_UNSUBSCRIBE_ERROR(self, share_id, error):
712
"""Handle VM_SHARE_UNSUBSCRIBE_ERROR, emit ShareUnSubscribeError."""
713
self.dbus_iface.shares.emit_share_unsubscribe_error(share_id, error)
715
def handle_VM_SHARE_CREATED(self, share_id):
716
"""Handle VM_SHARE_CREATED event, emit NewShare event."""
717
self.dbus_iface.shares.emit_new_share(share_id)
719
def handle_VM_SHARE_DELETED(self, share):
720
"""Handle VM_SHARE_DELETED event, emit NewShare event."""
721
self.dbus_iface.shares.emit_share_changed('deleted', share)
723
def handle_VM_SHARE_DELETE_ERROR(self, share_id, error):
724
"""Handle VM_DELETE_SHARE_ERROR event, emit ShareCreateError signal."""
725
self.dbus_iface.shares.ShareDeleteError(dict(volume_id=share_id), error)
727
def handle_VM_VOLUME_DELETED(self, volume):
728
"""Handle VM_VOLUME_DELETED event.
730
Emits FolderDeleted or ShareChanged signal.
733
from ubuntuone.syncdaemon.volume_manager import Share, UDF
735
if isinstance(volume, Share):
736
self.dbus_iface.shares.emit_share_changed('deleted', volume)
737
elif isinstance(volume, UDF):
738
self.dbus_iface.folders.emit_folder_deleted(volume)
740
logger.error("Unable to handle VM_VOLUME_DELETE for "
741
"volume_id=%r as it's not a share or UDF", volume.id)
743
def handle_VM_VOLUME_DELETE_ERROR(self, volume_id, error):
744
"""Handle VM_VOLUME_DELETE_ERROR event, emit ShareDeleted event."""
745
from ubuntuone.syncdaemon.volume_manager import Share, UDF, \
749
volume = self.dbus_iface.volume_manager.get_volume(volume_id)
750
except VolumeDoesNotExist:
751
logger.error("Unable to handle VM_VOLUME_DELETE_ERROR for "
752
"volume_id=%r, no such volume.", volume_id)
754
if isinstance(volume, Share):
755
self.dbus_iface.shares.emit_share_delete_error(volume, error)
756
elif isinstance(volume, UDF):
757
self.dbus_iface.folders.emit_folder_delete_error(volume, error)
759
logger.error("Unable to handle VM_VOLUME_DELETE_ERROR for "
760
"volume_id=%r as it's not a share or UDF", volume_id)
762
def handle_VM_SHARE_CHANGED(self, share_id):
763
""" handle VM_SHARE_CHANGED event, emit's ShareChanged signal. """
764
share = self.dbus_iface.volume_manager.shares.get(share_id)
765
self.dbus_iface.shares.emit_share_changed('changed', share)
767
def handle_AQ_CHANGE_PUBLIC_ACCESS_OK(self, share_id, node_id,
768
is_public, public_url):
769
"""Handle the AQ_CHANGE_PUBLIC_ACCESS_OK event."""
770
self.dbus_iface.public_files.emit_public_access_changed(
771
share_id, node_id, is_public, public_url)
773
def handle_AQ_CHANGE_PUBLIC_ACCESS_ERROR(self, share_id, node_id, error):
774
"""Handle the AQ_CHANGE_PUBLIC_ACCESS_ERROR event."""
775
self.dbus_iface.public_files.emit_public_access_change_error(
776
share_id, node_id, error)
778
def handle_SYS_ROOT_MISMATCH(self, root_id, new_root_id):
779
"""Handle the SYS_ROOT_MISMATCH event."""
780
self.dbus_iface.sync.emit_root_mismatch(root_id, new_root_id)
782
def handle_AQ_PUBLIC_FILES_LIST_OK(self, public_files):
783
"""Handle the AQ_PUBLIC_FILES_LIST_OK event."""
784
self.dbus_iface.public_files.emit_public_files_list(public_files)
786
def handle_AQ_PUBLIC_FILES_LIST_ERROR(self, error):
787
"""Handle the AQ_PUBLIC_FILES_LIST_ERROR event."""
788
self.dbus_iface.public_files.emit_public_files_list_error(error)
790
def handle_SYS_QUOTA_EXCEEDED(self, volume_id, free_bytes):
791
"""Handle the SYS_QUOTA_EXCEEDED event."""
792
from ubuntuone.syncdaemon.volume_manager import UDF
794
volume = self.dbus_iface.volume_manager.get_volume(str(volume_id))
797
if isinstance(volume, UDF):
798
volume_dict = _get_udf_dict(volume)
800
# either a Share or Root
801
volume_dict = _get_share_dict(volume)
803
# be sure that the volume has the most updated free bytes info
804
volume_dict['free_bytes'] = str(free_bytes)
806
self.dbus_iface.sync.emit_quota_exceeded(volume_dict)
808
def handle_SYS_QUEUE_ADDED(self, command):
809
"""Handle SYS_QUEUE_ADDED."""
810
if isinstance(command, (Upload, Download)):
811
self.dbus_iface.status.emit_content_queue_changed()
813
self.dbus_iface.status.emit_metaqueue_changed()
815
def handle_SYS_QUEUE_REMOVED(self, command):
816
"""Handle SYS_QUEUE_REMOVED."""
817
self.handle_SYS_QUEUE_ADDED(command)
820
352
class SyncDaemon(DBusExposedObject):
821
""" The Daemon dbus interface. """
353
"""The Daemon dbus interface."""
823
355
def __init__(self, bus_name, dbus_iface):
824
""" Creates the instance.
356
"""Create the instance.
826
358
@param bus: the BusName of this DBusExposedObject.
828
360
self.dbus_iface = dbus_iface
361
self.service = SyncdaemonService(dbus_iface, dbus_iface.main,
362
dbus_iface.volume_manager,
363
dbus_iface.action_queue)
830
365
DBusExposedObject.__init__(self, bus_name=bus_name,
833
368
@dbus.service.method(DBUS_IFACE_SYNC_NAME,
834
369
in_signature='', out_signature='')
835
370
def connect(self):
836
""" Connect to the server. """
371
"""Connect to the server."""
837
372
logger.debug('connect requested')
838
self.dbus_iface.connect()
373
self.service.connect()
840
375
@dbus.service.method(DBUS_IFACE_SYNC_NAME,
841
376
in_signature='', out_signature='')
842
377
def disconnect(self):
843
""" Disconnect from the server. """
378
"""Disconnect from the server."""
844
379
logger.debug('disconnect requested')
845
self.dbus_iface.disconnect()
380
self.service.disconnect()
847
382
@dbus.service.method(DBUS_IFACE_SYNC_NAME,
848
383
in_signature='', out_signature='s')
849
384
def get_rootdir(self):
850
""" Returns the root dir/mount point. """
385
"""Return the root dir/mount point."""
851
386
logger.debug('called get_rootdir')
852
return self.dbus_iface.main.get_rootdir()
387
return self.service.get_rootdir()
854
389
@dbus.service.method(DBUS_IFACE_SYNC_NAME,
855
390
in_signature='', out_signature='s')
856
391
def get_sharesdir(self):
857
""" Returns the shares dir/mount point. """
392
"""Return the shares dir/mount point."""
858
393
logger.debug('called get_sharesdir')
859
return self.dbus_iface.main.get_sharesdir()
394
return self.service.get_sharesdir()
861
396
@dbus.service.method(DBUS_IFACE_SYNC_NAME,
862
397
in_signature='', out_signature='s')
863
398
def get_sharesdir_link(self):
864
""" Returns the shares dir/mount point. """
399
"""Return the shares dir/mount point."""
865
400
logger.debug('called get_sharesdir_link')
866
return self.dbus_iface.main.get_sharesdir_link()
401
return self.service.get_sharesdir_link()
868
403
@dbus.service.method(DBUS_IFACE_SYNC_NAME,
869
404
in_signature='d', out_signature='b',
870
405
async_callbacks=('reply_handler', 'error_handler'))
871
406
def wait_for_nirvana(self, last_event_interval,
872
407
reply_handler=None, error_handler=None):
873
""" call the reply handler when there are no more
408
"""Call the reply handler when there are no more
874
409
events or transfers.
876
411
logger.debug('called wait_for_nirvana')
877
d = self.dbus_iface.main.wait_for_nirvana(last_event_interval)
878
d.addCallbacks(reply_handler, error_handler)
412
return self.service.wait_for_nirvana(last_event_interval,
413
reply_handler, error_handler)
881
415
@dbus.service.method(DBUS_IFACE_SYNC_NAME,
882
416
in_signature='', out_signature='',
883
417
async_callbacks=('reply_handler', 'error_handler'))
884
418
def quit(self, reply_handler=None, error_handler=None):
885
""" shutdown the syncdaemon. """
419
"""Shutdown the syncdaemon."""
886
420
logger.debug('Quit requested')
889
self.dbus_iface.quit()
421
self.service.quit(reply_handler, error_handler)
891
423
@dbus.service.method(DBUS_IFACE_SYNC_NAME,
892
424
in_signature='s', out_signature='')
893
425
def rescan_from_scratch(self, volume_id):
894
426
"""Request a rescan from scratch of the volume with volume_id."""
895
# check that the volume exists
896
volume = self.dbus_iface.volume_manager.get_volume(str(volume_id))
897
self.dbus_iface.action_queue.rescan_from_scratch(volume.volume_id)
427
self.service.rescan_from_scratch(volume_id)
899
429
@dbus.service.signal(DBUS_IFACE_SYNC_NAME,
931
461
def get_metadata(self, path):
932
462
"""Return the metadata (as a dict) for the specified path."""
933
463
logger.debug('get_metadata by path: %r', path)
934
real_path = os.path.realpath(path.encode('utf-8'))
935
mdobj = self.fs_manager.get_by_path(real_path)
936
md_dict = self._mdobj_dict(mdobj)
937
md_dict['path'] = path
464
return self.syncdaemon_filesystem.get_metadata(path)
940
466
@dbus.service.method(DBUS_IFACE_FS_NAME,
941
467
in_signature='ss', out_signature='a{ss}')
942
468
def get_metadata_by_node(self, share_id, node_id):
943
469
"""Return the metadata (as a dict) for the specified share/node."""
944
470
logger.debug('get_metadata by share: %r node: %r', share_id, node_id)
945
mdobj = self.fs_manager.get_by_node_id(share_id, node_id)
946
md_dict = self._mdobj_dict(mdobj)
947
path = self.fs_manager.get_abspath(mdobj.share_id, mdobj.path)
948
md_dict['path'] = path
471
return self.syncdaemon_filesystem.get_metadata_by_node(share_id,
951
474
@dbus.service.method(DBUS_IFACE_FS_NAME,
952
475
in_signature='s', out_signature='a{ss}')
953
476
def get_metadata_and_quick_tree_synced(self, path):
954
""" returns the dict with the attributes of the metadata for
477
"""Return the dict with the attributes of the metadata for
955
478
the specified path, including the quick subtree status.
957
480
logger.debug('get_metadata_and_quick_tree_synced: %r', path)
958
real_path = os.path.realpath(path.encode('utf-8'))
959
mdobj = self.fs_manager.get_by_path(real_path)
960
md_dict = self._mdobj_dict(mdobj)
961
md_dict['path'] = path
962
if self._path_in_queue(real_path):
963
md_dict['quick_tree_synced'] = ''
965
md_dict['quick_tree_synced'] = 'synced'
968
def _path_in_queue(self, path):
969
"""Return whether there are queued commands pertaining to the path."""
970
for cmd in self.action_queue.queue.waiting:
971
share_id = getattr(cmd, 'share_id', None)
972
node_id = getattr(cmd, 'node_id', None)
973
if share_id is not None and node_id is not None:
974
# XXX: nested try/excepts in a loop are probably a
975
# sign that I'm doing something wrong - or that
979
node_md = self.fs_manager.get_by_node_id(share_id, node_id)
981
# maybe it's actually the mdid?
983
node_md = self.fs_manager.get_by_mdid(node_id)
985
# hm, nope. Dunno what to do then
988
this_path = self.fs_manager.get_abspath(share_id,
991
this_path = self.fs_manager.get_abspath(share_id,
993
if this_path.startswith(path):
997
def _mdobj_dict(self, mdobj):
998
"""Returns a dict from a MDObject."""
1000
for k, v in mdobj.__dict__.items():
1004
md_dict[str(k)] = v.decode('utf-8')
1006
md_dict[str(k)] = str(v)
1007
if mdobj.__dict__.get('info', None):
1008
for k, v in mdobj.info.__dict__.items():
1009
md_dict['info_'+str(k)] = str(v)
481
return self.syncdaemon_filesystem.get_metadata_and_quick_tree_synced(
1012
485
@dbus.service.method(DBUS_IFACE_FS_NAME,
1013
486
in_signature='', out_signature='aa{ss}')
1014
487
def get_dirty_nodes(self):
1015
488
"""Rerturn a list of dirty nodes."""
1016
mdobjs = self.fs_manager.get_dirty_nodes()
1018
for mdobj in mdobjs:
1019
dirty_nodes.append(self._mdobj_dict(mdobj))
489
return self.syncdaemon_filesystem.get_dirty_nodes()
1023
492
class Shares(DBusExposedObject):
1097
547
def subscribe(self, share_id):
1098
548
"""Subscribe to the specified share."""
1099
549
logger.debug('Shares.subscribe: %r', share_id)
1100
d = self.vm.subscribe_share(str(share_id))
1101
msg = 'subscribe_share for id %r failed with %r'
1102
d.addErrback(lambda f: logger.error(msg, share_id, f))
550
self.syncdaemon_shares.subscribe(share_id)
1104
552
@dbus.service.method(DBUS_IFACE_SHARES_NAME, in_signature='s')
1105
553
def unsubscribe(self, share_id):
1106
554
"""Unsubscribe from the specified share."""
1107
555
logger.debug('Shares.unsubscribe: %r', share_id)
1108
self.vm.unsubscribe_share(str(share_id))
556
self.syncdaemon_shares.unsubscribe(share_id)
1110
558
@dbus.service.signal(DBUS_IFACE_SHARES_NAME,
1111
559
signature='a{ss}')
1112
560
def ShareChanged(self, share_dict):
1113
""" A share changed, share_dict contains all the share attributes. """
561
"""A share changed, share_dict contains all the share attributes."""
1115
563
@dbus.service.signal(DBUS_IFACE_SHARES_NAME,
1116
564
signature='a{ss}')
1117
565
def ShareDeleted(self, share_dict):
1118
""" A share was deleted, share_dict contains all available
1119
share attributes. """
566
"""A share was deleted, share_dict contains all available share
1121
569
@dbus.service.signal(DBUS_IFACE_SHARES_NAME,
1122
570
signature='a{ss}s')
1123
571
def ShareDeleteError(self, share_dict, error):
1124
""" A share was deleted, share_dict contains all available
1125
share attributes. """
572
"""A share was deleted, share_dict contains all available
1127
575
def emit_share_changed(self, message, share):
1128
""" emits ShareChanged or ShareDeleted signal for the share
576
"""Emit ShareChanged or ShareDeleted signal for the share
1131
579
logger.debug('emit_share_changed: message %r, share %r.',
1133
581
if message == 'deleted':
1134
self.ShareDeleted(_get_share_dict(share))
582
self.ShareDeleted(get_share_dict(share))
1135
583
elif message == 'changed':
1136
self.ShareChanged(_get_share_dict(share))
584
self.ShareChanged(get_share_dict(share))
1138
586
def emit_share_delete_error(self, share, error):
1139
"""Emits ShareDeleteError signal."""
587
"""Emit ShareDeleteError signal."""
1140
588
logger.info('emit_share_delete_error: share %r, error %r.',
1142
self.ShareDeleteError(_get_share_dict(share), error)
590
self.ShareDeleteError(get_share_dict(share), error)
1144
592
def emit_free_space(self, share_id, free_bytes):
1145
""" emits ShareChanged when free space changes """
1146
if share_id in self.vm.shares:
1147
share = self.vm.shares[share_id]
1148
share_dict = _get_share_dict(share)
593
"""Emit ShareChanged when free space changes """
594
if share_id in self.syncdaemon_shares.shares:
595
share = self.syncdaemon_shares.shares[share_id]
596
share_dict = get_share_dict(share)
1149
597
share_dict['free_bytes'] = unicode(free_bytes)
1150
598
self.ShareChanged(share_dict)
1152
600
@dbus.service.method(DBUS_IFACE_SHARES_NAME,
1153
601
in_signature='ssss', out_signature='')
1154
602
def create_share(self, path, username, name, access_level):
1155
""" Share a subtree to the user identified by username.
603
"""Share a subtree to the user identified by username.
1157
605
@param path: that path to share (the root of the subtree)
1158
606
@param username: the username to offer the share to
1422
792
"""Returns True (actually 1) if bandwidth throttling is enabled and
1423
793
False (0) otherwise.
1425
enabled = self.dbus_iface.action_queue.throttling_enabled
1427
reply_handler(enabled)
795
return self.syncdaemon_config.bandwidth_throttling_enabled(
796
reply_handler, error_handler)
1431
798
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
1432
799
in_signature='', out_signature='b')
1433
800
def udf_autosubscribe_enabled(self):
1434
801
"""Return the udf_autosubscribe config value."""
1435
return config.get_user_config().get_udf_autosubscribe()
802
return self.syncdaemon_config.udf_autosubscribe_enabled()
1437
804
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
1438
805
in_signature='', out_signature='')
1439
806
def enable_udf_autosubscribe(self):
1440
807
"""Enable UDF autosubscribe."""
1441
user_config = config.get_user_config()
1442
user_config.set_udf_autosubscribe(True)
808
self.syncdaemon_config.enable_udf_autosubscribe()
1445
810
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
1446
811
in_signature='', out_signature='')
1447
812
def disable_udf_autosubscribe(self):
1448
"""Enable UDF autosubscribe."""
1449
user_config = config.get_user_config()
1450
user_config.set_udf_autosubscribe(False)
813
"""Disable UDF autosubscribe."""
814
self.syncdaemon_config.disable_udf_autosubscribe()
1453
816
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
1454
817
in_signature='', out_signature='b')
1455
818
def share_autosubscribe_enabled(self):
1456
819
"""Return the share_autosubscribe config value."""
1457
return config.get_user_config().get_share_autosubscribe()
820
return self.syncdaemon_config.share_autosubscribe_enabled()
1459
822
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
1460
823
in_signature='', out_signature='')
1461
824
def enable_share_autosubscribe(self):
1462
"""Enable UDF autosubscribe."""
1463
user_config = config.get_user_config()
1464
user_config.set_share_autosubscribe(True)
825
"""Enable share autosubscribe."""
826
self.syncdaemon_config.enable_share_autosubscribe()
1467
828
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
1468
829
in_signature='', out_signature='')
1469
830
def disable_share_autosubscribe(self):
1470
"""Enable UDF autosubscribe."""
1471
user_config = config.get_user_config()
1472
user_config.set_share_autosubscribe(False)
831
"""Disable share autosubscribe."""
832
self.syncdaemon_config.disable_share_autosubscribe()
1475
834
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
1476
835
in_signature='b', out_signature='')
1477
836
def set_files_sync_enabled(self, enabled):
1478
837
"""Enable/disable file sync service."""
1479
838
logger.debug('called set_files_sync_enabled %d', enabled)
1480
user_config = config.get_user_config()
1481
user_config.set_files_sync_enabled(bool(int(enabled)))
839
self.syncdaemon_config.set_files_sync_enabled(enabled)
1484
841
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
1485
842
in_signature='', out_signature='b')
1486
843
def files_sync_enabled(self):
1487
844
"""Return the files_sync_enabled config value."""
1488
845
logger.debug('called files_sync_enabled')
1489
return config.get_user_config().get_files_sync_enabled()
846
return self.syncdaemon_config.files_sync_enabled()
1491
848
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
1492
849
in_signature='', out_signature='b')
1493
850
def autoconnect_enabled(self):
1494
851
"""Return the autoconnect config value."""
1495
return config.get_user_config().get_autoconnect()
852
return self.syncdaemon_config.autoconnect_enabled()
1497
854
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
1498
855
in_signature='b', out_signature='')
1499
856
def set_autoconnect_enabled(self, enabled):
1500
857
"""Enable syncdaemon autoconnect."""
1501
user_config = config.get_user_config()
1502
user_config.set_autoconnect(enabled)
858
self.syncdaemon_config.set_autoconnect_enabled(enabled)
860
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
861
in_signature='', out_signature='b')
862
def show_all_notifications_enabled(self):
863
"""Return the show_all_notifications config value."""
864
return self.syncdaemon_config.show_all_notifications_enabled()
866
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
867
in_signature='', out_signature='')
868
def enable_show_all_notifications(self):
869
"""Enable showing all notifications."""
870
self.syncdaemon_config.enable_show_all_notifications()
872
@dbus.service.method(DBUS_IFACE_CONFIG_NAME,
873
in_signature='', out_signature='')
874
def disable_show_all_notifications(self):
875
"""Disable showing all notifications."""
876
self.syncdaemon_config.disable_show_all_notifications()
1506
879
class Folders(DBusExposedObject):
1507
880
"""A dbus interface to interact with User Defined Folders"""
1509
882
def __init__(self, bus_name, volume_manager, fs_manager):
1510
""" Creates the instance. """
1511
self.vm = volume_manager
1512
self.fs = fs_manager
883
"""Create the instance."""
884
self.syncdaemon_folders = SyncdaemonFolders(volume_manager, fs_manager)
1513
885
self.path = '/folders'
1514
886
DBusExposedObject.__init__(self, bus_name=bus_name,