diff options
author | Joar Wandborg <git@wandborg.com> | 2011-08-04 01:32:34 +0200 |
---|---|---|
committer | Joar Wandborg <git@wandborg.com> | 2011-08-04 01:32:34 +0200 |
commit | 851c51a354d1355683093cdb04d48fcaafc20c28 (patch) | |
tree | 5dab0d6a8898d43af8601317a6eb46bb2baa348e /mediagoblin/storage.py | |
parent | 4d74812dfc5a671aa50f54951ffe9e0ee520f8f7 (diff) | |
download | mediagoblin-851c51a354d1355683093cdb04d48fcaafc20c28.tar.lz mediagoblin-851c51a354d1355683093cdb04d48fcaafc20c28.tar.xz mediagoblin-851c51a354d1355683093cdb04d48fcaafc20c28.zip |
Feature 477 - Support Cloud Files public storage
* Added configuration options to mediagoblin.ini
* process_media supports the python-cloudfiles
almost-file-like objects by wrapping them in a
contextlib.contextmanager-decorated func.
* storage now has the CloudFilesStorage
* New dependency added to setup.py; `python-cloudfiles`
Diffstat (limited to 'mediagoblin/storage.py')
-rw-r--r-- | mediagoblin/storage.py | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/mediagoblin/storage.py b/mediagoblin/storage.py index 5d6faa4c..0e50938f 100644 --- a/mediagoblin/storage.py +++ b/mediagoblin/storage.py @@ -19,6 +19,7 @@ import re import shutil import urlparse import uuid +import cloudfiles from werkzeug.utils import secure_filename @@ -161,6 +162,61 @@ class StorageInterface(object): dest_file.write(source_file.read()) +class CloudFilesStorage(StorageInterface): + def __init__(self, **kwargs): + self.param_container = kwargs.get('cloudfiles_container') + self.param_user = kwargs.get('cloudfiles_user') + self.param_api_key = kwargs.get('cloudfiles_api_key') + self.param_host = kwargs.get('cloudfiles_host') + self.param_use_servicenet = kwargs.get('cloudfiles_use_servicenet') + + if not self.param_host: + print('No CloudFiles host URL specified, defaulting to Rackspace US') + + self.connection = cloudfiles.get_connection( + username=self.param_user, + api_key=self.param_api_key, + servicenet=True if self.param_use_servicenet == 'true' or \ + self.param_use_servicenet == True else False) + + if not self.param_container in [self.connection.get_container(self.param_container)]: + self.container = self.connection.create_container(self.param_container) + self.container.make_public( + ttl=60 * 60 * 2) + else: + self.container = self.connection.get_container(self.param_container) + + def _resolve_filepath(self, filepath): + return '-'.join( + clean_listy_filepath(filepath)) + + def file_exists(self, filepath): + try: + object = self.container.get_object( + self._resolve_filepath(filepath)) + return True + except cloudfiles.errors.NoSuchObject: + return False + + def get_file(self, filepath, mode='r'): + try: + obj = self.container.get_object( + self._resolve_filepath(filepath)) + except cloudfiles.errors.NoSuchObject: + obj = self.container.create_object( + self._resolve_filepath(filepath)) + + return obj + + def delete_file(self, filepath): + # TODO: Also delete unused directories if empty (safely, with + # checks to avoid race conditions). + self.container.delete_object(filepath) + + def file_url(self, filepath): + return self.get_file(filepath).public_uri() + + class BasicFileStorage(StorageInterface): """ Basic local filesystem implementation of storage API |