Feature #477 - Cloud Files public storage
authorJoar Wandborg <git@wandborg.com>
Thu, 4 Aug 2011 12:49:12 +0000 (14:49 +0200)
committerJoar Wandborg <git@wandborg.com>
Thu, 4 Aug 2011 12:49:12 +0000 (14:49 +0200)
*   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

mediagoblin.ini
mediagoblin/storage.py

index 100e9376c397431883452b14454eb6b9feae6592..e889646abeb73824dd17aefa774e6b9ac35b06b1 100644 (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"
 
index 0e50938f378299be6f82d84aec3bf7864ba08fa4..e449eda3b9995f34724bd51e6d30970011064a94 100644 (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
 
 
 ###############################################
@@ -118,7 +128,7 @@ class StorageInterface(object):
         Eg, if the filename doesn't exist:
         >>> storage_handler.get_unique_filename(['dir1', 'dir2', 'fname.jpg'])
         [u'dir1', u'dir2', u'fname.jpg']
-        
+
         But if a file does exist, let's get one back with at uuid tacked on:
         >>> storage_handler.get_unique_filename(['dir1', 'dir2', 'fname.jpg'])
         [u'dir1', u'dir2', u'd02c3571-dd62-4479-9d62-9e3012dada29-fname.jpg']
@@ -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
@@ -240,7 +195,7 @@ class BasicFileStorage(StorageInterface):
         """
         return os.path.join(
             self.base_dir, *clean_listy_filepath(filepath))
-        
+
     def file_exists(self, filepath):
         return os.path.exists(self._resolve_filepath(filepath))
 
@@ -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)
-
-