2014-06-17 20:03:43 +00:00
|
|
|
import random
|
|
|
|
import logging
|
|
|
|
|
|
|
|
from functools import wraps
|
|
|
|
|
2015-07-06 19:00:07 +00:00
|
|
|
from storage.basestorage import StoragePaths, BaseStorage, BaseStorageV2
|
2014-06-17 20:03:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
def _location_aware(unbound_func):
|
|
|
|
@wraps(unbound_func)
|
|
|
|
def wrapper(self, locations, *args, **kwargs):
|
|
|
|
storage = None
|
|
|
|
for preferred in self.preferred_locations:
|
|
|
|
if preferred in locations:
|
|
|
|
storage = self._storages[preferred]
|
|
|
|
|
|
|
|
if not storage:
|
|
|
|
storage = self._storages[random.sample(locations, 1)[0]]
|
|
|
|
|
|
|
|
storage_func = getattr(storage, unbound_func.__name__)
|
|
|
|
return storage_func(*args, **kwargs)
|
|
|
|
return wrapper
|
|
|
|
|
|
|
|
|
|
|
|
class DistributedStorage(StoragePaths):
|
2015-06-28 10:29:22 +00:00
|
|
|
def __init__(self, storages, preferred_locations=[], default_locations=[]):
|
2014-06-17 20:03:43 +00:00
|
|
|
self._storages = dict(storages)
|
|
|
|
self.preferred_locations = list(preferred_locations)
|
2015-06-28 10:29:22 +00:00
|
|
|
self.default_locations = list(default_locations)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def locations(self):
|
|
|
|
""" Returns the names of the locations supported. """
|
|
|
|
return list(self._storages.keys())
|
2014-06-17 20:03:43 +00:00
|
|
|
|
|
|
|
get_direct_download_url = _location_aware(BaseStorage.get_direct_download_url)
|
2014-11-24 21:07:38 +00:00
|
|
|
get_direct_upload_url = _location_aware(BaseStorage.get_direct_upload_url)
|
2014-06-17 20:03:43 +00:00
|
|
|
get_content = _location_aware(BaseStorage.get_content)
|
|
|
|
put_content = _location_aware(BaseStorage.put_content)
|
|
|
|
stream_read = _location_aware(BaseStorage.stream_read)
|
|
|
|
stream_read_file = _location_aware(BaseStorage.stream_read_file)
|
|
|
|
stream_write = _location_aware(BaseStorage.stream_write)
|
|
|
|
list_directory = _location_aware(BaseStorage.list_directory)
|
|
|
|
exists = _location_aware(BaseStorage.exists)
|
|
|
|
remove = _location_aware(BaseStorage.remove)
|
2014-09-09 19:54:03 +00:00
|
|
|
get_checksum = _location_aware(BaseStorage.get_checksum)
|
|
|
|
get_supports_resumable_downloads = _location_aware(BaseStorage.get_supports_resumable_downloads)
|
2015-06-28 10:29:22 +00:00
|
|
|
|
2015-07-06 19:00:07 +00:00
|
|
|
initiate_chunked_upload = _location_aware(BaseStorageV2.initiate_chunked_upload)
|
|
|
|
stream_upload_chunk = _location_aware(BaseStorageV2.stream_upload_chunk)
|
|
|
|
complete_chunked_upload = _location_aware(BaseStorageV2.complete_chunked_upload)
|
2015-06-28 10:29:22 +00:00
|
|
|
|
|
|
|
def copy_between(self, path, source_location, destination_location):
|
|
|
|
""" Copies a file between the source location and the destination location. """
|
|
|
|
source_storage = self._storages[source_location]
|
|
|
|
destination_storage = self._storages[destination_location]
|
|
|
|
source_storage.copy_to(destination_storage, path)
|
|
|
|
|