SyncDaemonTool

The SyncDaemonTool class provides a high level interface that can be used by Python programs to talk with the Ubuntu One file synchronisation daemon. The interface makes use of the Twisted framework to handle the asynchronous calls.

To make use of the API on Ubuntu systems, you will need a bit of boilerplate code at the start of your program to configure Twisted to interoperate with D-Bus:

from twisted.internet import glib2reactor
glib2reactor.install()
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)

The methods make use of the Deferred results, to allow asynchronous operation. If you are not overly familiar with the concept, it is probably best to make use of the inlineCallbacks decorator, which lets you write code that resembles synchronous code:

from twisted.internet import defer

from ubuntuone.platform.tools import SyncDaemonTool

@defer.inlineCallbacks
def do_something():
    # This function body is run as a generator, where we can yield
    # deferred objects, and have their result sent to the
    # generator when available.
    tool = SyncDaemonTool()
    yield tool.refresh_shares()
    shares = yield tool.get_shares()
    # A generator can't directly return a value, so we need to use
    # this syntax to return something:
    defer.returnValue(shares[0])

Finally, you will need to run Twisted’s reactor event loop for asynchronous events to be handled. For example:

from twisted.internet import reactor

@defer.inlineCallbacks
def main():
    result = yield do_something()
    reactor.stop()

reactor.callWhenRunning(main)
reactor.run()

Daemon Lifecycle

While you can usually rely on the synchronisation daemon being connected and running, the SyncDaemonTool interface allows a program to query the status of the daemon, and ask for it to connect or disconnect.

SyncDaemonTool.start()

Start syncdaemon if it is not already running.

Returns:a deferred that will fire once the daemon has started.
SyncDaemonTool.quit()

Ask the syncdaemon to shut down, if it is running.

Returns:a deferred that will fire once the daemon has quit.
SyncDaemonTool.connect()

Ask the syncdaemon to connect to the cloud.

Returns:a deferred that will fire once the CONNECT event has been emitted. The daemon may not be connected at this point however.
SyncDaemonTool.disconnect()

Ask the syncdaemon to disconnect from the cloud.

Returns:a deferred that will fire once the DISCONNECT event has been emitted. The daemon may not have fully disconnected at this point though.
SyncDaemonTool.get_status()

Get the current status of the syncdaemon.

Returns:a deferred that will fire with the status dictionary

The result should look something like this:

{
  'name': '...', # The state of the syncdaemon
  'description': '...', # Description of the curtrent state.
  'is_error': False,    # Whether the syncdaemon is in an error state
  'is_connected': True, # Whether the syncdaemon is connected
  'is_online': True,    # Whether the syncdaemon is online
  'connection': '...',  # The state of the connection.
}
SyncDaemonTool.wait_connected()

Wait until the syncdaemon has connected to the cloud.

Returns:a deferred that will fire when the daemon has connected.

Enabling and Disabling SyncDaemon Features

These methods control various aspects of how the synchronisation daemon performs its job.

SyncDaemonTool.is_throttling_enabled()

Check if bandwidth throttling is enabled.

Returns:a deferred that will fire with a boolean value specifying whether throttling is enabled.
SyncDaemonTool.enable_throttling(enabled=True)

Enable or disable bandwidth throttling.

Parameters:enabled – a boolean value specifying whether throttling should be enabled.
Returns:a deferred that will fire when the setting has been updated.
SyncDaemonTool.get_throttling_limits()

Get the current bandwidth throttling limits.

Returns:a deferred that will fire with a dictionary containing te bandwidth throttling limits. The dictionary will contain download and upload keys.
SyncDaemonTool.set_throttling_limits(read_limit, write_limit)

Set the bandwidth throttling limits

Parameters:
  • read_limit – The rate limit for downloads in bytes/s, or -1 for no limit.
  • write_limit – The rate limit for uploads in bytes/s, or -1 for no limit.
Returns:

a deferred that will fire when the setting has been updated.

SyncDaemonTool.is_files_sync_enabled()

Check whether the file synchronisation service is enabled.

Returns:a deferred that will fire with a boolean value specifying whether file synchronisation is enabled.
SyncDaemonTool.enable_files_sync(enabled)

Enable or disable the file synchronisation service.

Parameters:enabled – a boolean value specifying whether file synchronisation should be enabled.
Returns:a deferred that will fire when the setting has been updated.
SyncDaemonTool.is_autoconnect_enabled()

Check whether the file synchronisation service should automatically connect to the cloud.

Returns:a deferred that will fire with a boolean value specifying whether the service should autoconnect.
SyncDaemonTool.enable_autoconnect(enabled)

Enable or disable the file synchronisation autoconnect.

Parameters:enabled – a boolean value specifying whether the service should autoconnect.
Returns:a deferred that will fire when the setting has been updated.
SyncDaemonTool.is_show_all_notifications_enabled()

Check whether all notifications should be shown to the user.

Returns:a deferred that will fire with a boolean value specifying whether all notifications will be shown.
SyncDaemonTool.enable_show_all_notifications(enabled)

Enable or disable the whether all notifications should be shown to the user.

Parameters:enabled – a boolean value specifying whether all notifications should be shown.
Returns:a deferred that will fire when the setting has been updated.
SyncDaemonTool.is_share_autosubscribe_enabled()

Check whether a local synchronised copy of new shares should be created automatically.

Returns:a deferred that will fire with a boolean value specifying whether new shares should automatically be subscribed.
SyncDaemonTool.enable_share_autosubscribe(enabled)

Enable or disable the whether a local synchronised copy of new shares should be created automatically.

Parameters:enabled – a boolean value specifying whether new shares should automatically be subscribed.
Returns:a deferred that will fire when the setting has been updated.
SyncDaemonTool.is_udf_autosubscribe_enabled()

Check whether a local synchronised copy of new folders should be created automatically.

Returns:a deferred that will fire with a boolean value specifying whether new folders should automatically be subscribed.
SyncDaemonTool.enable_udf_autosubscribe(enabled)

Enable or disable the whether a local synchronised copy of new folders should be created automatically.

Parameters:enabled – a boolean value specifying whether new folders should automatically be subscribed.
Returns:a deferred that will fire when the setting has been updated.

Managing Upload and Download Queues

When a file is copied to a synchronised folder, it takes some time for the contents to be mirrored remotely. Similarly, if a file is uploaded by another system, it will take some time for it to arrive locally.

These methods allow programs to inspect the upload and download queues, or wait until the queues empty. If you have performed a lot of file operations, this can be an easy way to make sure all operations have completed.

Note that if you are interested in the status of a single upload, you may find the SyncDaemonTool.wait_for_signals() method more appropriate.

SyncDaemonTool.wait_all_downloads(verbose=False)

Wait until there are no more pending download operations.

Parameters:verbose – if True, print status information to stdout.
Returns:a deferred that will fire when the download queue is empty.
SyncDaemonTool.wait_all_uploads(verbose=False)

Wait until there are no more pending upload operations.

Parameters:verbose – if True, print status information to stdout.
Returns:a deferred that will fire when the upload queue is empty.
SyncDaemonTool.get_current_downloads()

Get a list of the pending download operations.

Returns:a deferred that will fire with the list of downloads.

The list will contain dictionaries of the following form:

{
  'path': '...',         # The path of the download
  'share_id': '...',     # An identifier for the volume containing the file
  'node_id': '...',      # An identifier for the file
  'n_bytes_read': '...', # The number of bytes read so far.
}
SyncDaemonTool.get_current_uploads()

Get a list of the pending upload operations.

Returns:a deferred that will fire with the list of upload.

The list will contain dictionaries of the following form:

{
  'path': '...',            # The path of the download
  'share_id': '...',        # An identifier for the volume containing the file
  'node_id': '...',         # An identifier for the file
  'n_bytes_written': '...', # The number of bytes read so far.
}

File Metadata

In some cases it may be useful to know what metadata the syncdaemon is storing for a particular file or directory.

SyncDaemonTool.get_metadata(path)

Get the syncdaemon metadata associated with a particular path.

Parameters:path – the path of the file or directory.
Returns:a deferred that will fire with the metadata dictionary.

The metadata dictionary will look something like this:

{
  'path': '...',                  # the path for the metadata
  'node_id': '...',               # the node ID assigned to the path
  'share_id': '...',              # the volume ID for the given path
  'mdid': '...',                  # an identifier for this metadata record
  'is_dir': 'False',              # whether this path is a directory
  'size': '10750',                # the size of the file (if it is a file)
  'stat': '...',                  # the stat metadata of the path.
  'server_hash': '...',           # the content hash of the cloud copy
  'local_hash': '...',            # the content hash of the local copy
  'crc32': '2866587618',          # the CRC32 hash of the local copy
  'generation': '172',            # the volume generation when the file was last changed
  'info_is_partial': '...',       # whether the path is partially downloaded
  'info_created': '...',          # when the metadata record was created
  'info_last_uploaded': '...',    # when the file was last uploaded
  'info_node_id_assigned': '...', # when the node ID for the path was assigned
}

Public Files

These methods can be used to publish a file to the general public, or get a list of such published files.

SyncDaemonTool.change_public_access(path, is_public)

Publish a file to the general public.

Parameters:
  • path – The local path of the file to be published. The file must be under the ~/Ubuntu One folder or another synchronised folder.
  • is_public – a boolean value that determines whether the file should be published.
Returns:

a deferred that will fire with the result of the operation.

The result will be a dictionary of the following form:

{
  'path': '...',
  'node_id': '...',
  'share_id': '...',
  'is_public': 'True',
  'public_url': 'http://ubuntuone.com/...',
}
SyncDaemonTool.get_public_files()

Get a list of all files published by the user. The list will contain dictionaries in the same format as the result of SyncDaemonTool.change_public_access().

Returns:a deferred that will fire with the list of published files.

Managing Folders

These methods provide a way to manage the synchronised folders outside of ~/Ubuntu One.

SyncDaemonTool.get_folders()

Get the list of the user’s folders (both those subscribed and unsubscribed ones).

Returns:a deferred that will fire with a list of shares.

The list will contain dictionaries of the following form:

{
  'type': 'UDF',
  'volume_id': '...',          # The volume identifier for the folder
  'node_id': '...',            # The node identifier for the folder root
  'suggested_path': '~/...',   # The suggested path of the folder
  'path': '...',               # The path of the local copy of the folder
  'subscribed': 'True',        # Whether the folder has been subscribed to
  'generation': '...',         # The current generation of the folder
}
SyncDaemonTool.refresh_volumes()

Refresh the list of available volumes from the cloud.

Returns:a deferred that will fire when the list has been updated.
SyncDaemonTool.create_folder(path)

Create a new synchronised folder for the given path.

Returns:a deferred that will fire when the operation is complete.
SyncDaemonTool.delete_folder(folder_id)

Delete a share. The local copy of the share will remain after the share has been deleted

Parameters:folder_id – The volume identifier of the folder to delete.
Returns:a deferred that will fire when the operation is complete.
SyncDaemonTool.subscribe_folder(folder_id)

Subscribe to a folder, and create a local synchronised copy.

Parameters:folder_id – The volume identifier of the folder to subscribe to.
Returns:a deferred that will fire when the operation is complete.
SyncDaemonTool.unsubscribe_folder(folder_id)

Unsubscribe from a folder. The local copy of the folder will remain, but changes will no longer be synchronised.

Parameters:folder_id – The volume identifier of the folder to unsubscribe from.
Returns:a deferred that will fire when the operation is complete.

Managing Shares

These methods provide a way to act on the list of folders shared with or by the user.

SyncDaemonTool.get_shares()

Get a list of folders that have been shared with the user.

Returns:a deferred that will fire with a list of shares.

The list will contain dictionaries of the following form:

{
  'type': 'Share',
  'volume_id': '...',          # The volume identifier for the share
  'node_id': '...',            # The node identifier for the share root
  'name': '...',               # The name given to the share
  'other_username': '...',     # The user who created the share
  'other_visible_name': '...', # The display name of the share creator
  'path': '...',               # The path of the local copy of the share
  'access_level': '...',       # The access level for the share
  'accepted': 'True',          # Whether the share has been accepted
  'subscribed': 'True',        # Whether the share has been subscribed to
  'free_bytes': '...',         # Free space available in the share
  'generation': '...',         # The current generation of the share
}
SyncDaemonTool.refresh_shares()

Refresh the list of available shares from the cloud.

Returns:a deferred that will fire when the list has been updated.
SyncDaemonTool.list_shared()

Get a list of folders that the user has shared with others.

Returns:a deferred that will fire with a list of shares.

The list will contain dictionaries of the following form:

{
  'type': 'Shared',
  'volume_id': '...',          # The volume identifier for the share
  'node_id': '...',            # The node identifier for the share root
  'name': '...',               # The name given to the share
  'other_username': '...',     # The recipient of this share
  'other_visible_name': '...', # The display name of the recipient
  'path': '...',               # The path of the local copy of the share
  'access_level': '...',       # The access level for the share
  'accepted': 'True',          # Whether the share has been accepted
  'subscribed': 'True',        # Whether the share has been subscribed to
  'free_bytes': '...',         # Free space available in the share
  'generation': '...',         # The current generation of the share
}
SyncDaemonTool.subscribe_share(share_id)

Subscribe to a share, and create a local synchronised copy.

Parameters:share_id – The volume identifier of the share to subscribe to.
Returns:a deferred that will fire when the operation is complete.
SyncDaemonTool.unsubscribe_share(share_id)

Unsubscribe from a share. The local copy of the share will remain, but changes will no longer be synchronised.

Parameters:share_id – The volume identifier of the share to unsubscribe from.
Returns:a deferred that will fire when the operation is complete.
SyncDaemonTool.delete_share(share_id)

Delete a share. This can be performed on both folders the user has shared and folders that have been shared with the user. The local copy of the share will remain after the share has been deleted

Parameters:share_id – The volume identifier of the share to delete.
Returns:a deferred that will fire when the operation is complete.
SyncDaemonTool.offer_share(path, username, name, access_level)

Offer a share to another user.

Parameters:
  • path – the path of the folder to share. This must either be under ~/Ubuntu One or another synchronised folder.
  • username – the email address of the recipient user.
  • name – a name to identify the share.
  • access_level – the level of access to give the user. This should be one of 'Read' or 'Modify'.
Returns:

a deferred that will fire when the operation is complete.

SyncDaemonTool.accept_share(share_id)

Accept a share from another user.

Parameters:share_id – The volume identifier of the share to accept.
Returns:a deferred that will fire when the operation is complete.
SyncDaemonTool.reject_share(share_id)

Reject a share from another user.

Parameters:share_id – The volume identifier of the share to reject.
Returns:a deferred that will fire when the operation is complete.

Waiting for Events

Sometimes it is necessary to wait for the syncdaemon to finish an operation before proceeding. This can be done by waiting on one or more signals from the syncdaemon.

SyncDaemonTool.wait_for_signals(signal_ok, signal_error=None, success_filter=function, error_filter=function)

Wait for a signal from the syncdaemon.

Parameters:
  • signal_ok – the name of the signal to wait for.
  • signal_error – the name of a second signal to wait for that will be treated as an error.
  • success_filter – a function that will filter received signal_ok signals. If the function returns False, the signal will be ignored.
  • error_filter – a function used to filter received signal_error signals. If the function returns False, the signal will be ignored.
Returns:

a deferred that will fire when the signal is received. If signal_error is received, then the deferrred’s errback will be called.

Some signals that may be of interest include:

Signal Arguments Description
DownloadStarted path A file download has started.
DownloadFileProgress path, info Progress notification for an download.
DownloadFinished path, info A file download has completed.
UploadStarted path A file upload has started.
UploadFileProgress path, info Progress notification for an upload.
UploadFinished path, info A file upload has completed.

For example, to publish a file after it has uploaded, this API could be used as follows:

@defer.inlineCallbacks
def make_and_publish_file(path, content):
    # Prepare to wait for the file to upload.  We set this up
    # first to avoid race conditions.
    tool = SyncDaemonTool()
    success_filter = lambda upload_path, info: upload_path == path
    d = tool.wait_for_signals(signal_ok='UploadFinished',
                              success_filter=success_filter)

    # Create the file with the desired contents.
    with open(path, 'w') as fp:
        fp.write(content)

    # Now wait for the operation to complete.
    path, info = yield d

    # Now that the file has been uploaded, publish it and return
    # the public URL.
    info = yield tool.change_public_access(path, True)
    defer.returnValue(info['public_url'])