Feature #477 - Cloud Files public storage

*   mediagoblin.storage is now fully PEP-8 compliant.
*   mediagoblin.storage:BaseFileStorage precedes CloudFilesStorage
*   Removed all the cloudfiles-specific options from mediagoblin.ini, now it's in the wiki, http://wiki.mediagoblin.org/ConfigureMediaGoblin#Setting_up_Cloud_Files_public_storage
This commit is contained in:
Joar Wandborg 2011-08-04 14:49:12 +02:00
parent 851c51a354
commit aa797ca130
2 changed files with 77 additions and 91 deletions

View File

@ -1,33 +1,7 @@
[mediagoblin]
##
# BEGIN CloudFiles public storage
##
# Uncomment the following line and fill in your details to enable Cloud Files
# (or OpenStack Object Storage [Swift])
# -
# publicstore_storage_class = mediagoblin.storage:CloudFilesStorage
publicstore_cloudfiles_user = user
publicstore_cloudfiles_api_key = 1a2b3c4d5e6f7g8h9i
publicstore_cloudfiles_container = mediagoblin
# Only applicable if you run MediaGoblin on a Rackspace Cloud Server
# it routes traffic through the internal Rackspace network, this
# means that the bandwith betis free.
publicstore_cloudfiles_use_servicenet = false
##
# END CloudFiles
##
##
# BEGIN filesystem public storage
##
queuestore_base_dir = %(here)s/user_dev/media/queue
publicstore_base_dir = %(here)s/user_dev/media/public
publicstore_base_url = /mgoblin_media/
##
# END
##
queuestore_base_dir = %(here)s/user_dev/media/queue
direct_remote_path = /mgoblin_static/
email_sender_address = "notice@mediagoblin.example.org"

View File

@ -29,11 +29,21 @@ from mediagoblin import util
# Errors
########
class Error(Exception): pass
class InvalidFilepath(Error): pass
class NoWebServing(Error): pass
class NotImplementedError(Error): pass
class Error(Exception):
pass
class InvalidFilepath(Error):
pass
class NoWebServing(Error):
pass
class NotImplementedError(Error):
pass
###############################################
@ -162,61 +172,6 @@ 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
@ -272,6 +227,65 @@ class BasicFileStorage(StorageInterface):
return self._resolve_filepath(filepath)
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 == \
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()
###########
# Utilities
###########
@ -339,7 +353,7 @@ def storage_system_from_config(paste_config, storage_prefix):
for key, value in paste_config.iteritems()
if prefix_re.match(key)])
if config_params.has_key('storage_class'):
if 'storage_class' in config_params:
storage_class = config_params['storage_class']
config_params.pop('storage_class')
else:
@ -347,5 +361,3 @@ def storage_system_from_config(paste_config, storage_prefix):
storage_class = util.import_component(storage_class)
return storage_class(**config_params)