Source code for object_storage.container

"""
    Container module

    See COPYING for license information
"""
import json
import os
import UserDict
from object_storage import errors
from object_storage.storage_object import StorageObject
from object_storage.utils import get_path

class ContainerModel(UserDict.UserDict):
    def __init__(self, controller, name, headers={}):
        self.name = name
        _headers = {}

        # Lowercase headers
        for key, value in headers.iteritems():
            _key = key.lower()
            _headers[_key] = value
        self.headers = _headers
        self._meta = None

        _properties = {'name': self.name}

        _properties['count'] = int(self.headers.get('x-container-object-count') or\
                                   self.headers.get('count') or 0)
        _properties['object_count'] = _properties['count']
        _properties['size'] = int(self.headers.get('x-container-bytes-used') or\
                                  self.headers.get('size') or 0)
        _properties['read'] = self.headers.get('x-container-read') or\
                              self.headers.get('read')
        _properties['write'] = self.headers.get('x-container-read') or\
                               self.headers.get('read')
        _properties['ttl'] = int(self.headers.get('x-cdn-ttl') or 0)
        _properties['date'] = self.headers.get('date')
        _properties['cdn_url'] = self.headers.get('x-cdn-url')
        _properties['cdn_ssl_url'] = self.headers.get('x-cdn-ssl-url')

        _properties['path'] = controller.path
        _properties['url'] = controller.url

        meta = {}

        for key, value in self.headers.iteritems():
            if key.startswith('meta_'):
                meta[key[5:]] = value
            elif key.startswith('x-container-meta-'):
                meta[key[17:]] = value
        self.meta = meta
        _properties['meta'] = self.meta

        self.properties = _properties
        self.data = self.properties

[docs]class Container: """ Container class. Encapsulates Storage containers. """ def __init__(self, name, headers=None, client=None): """ constructor for Container @param name: container name @param headers: init headers to use when initializing the container @param client: `object_storage.client` instance. """ self.name = name self.client = client self.model = None if headers: self.model = ContainerModel(self, self.name, headers)
[docs] def exists(self): """ Tries to load the container to check existance @raises ResponseError @return: boolean, true if exists else false """ def _formatter(res): self.model = ContainerModel(self, self.name, res.headers) return True try: return self.make_request('HEAD', formatter=_formatter) except errors.NotFound: return False
[docs] def load(self, cdn=True): """ load data for the container @param cdn: True if you want CDN information; default=True @return: object_storage.container, self """ headers = {} if cdn: headers.setdefault('X-Context', 'cdn') def _formatter(res): self.model = ContainerModel(self, self.name, res.headers) return self return self.make_request('HEAD', headers=headers, formatter=_formatter)
[docs] def get_info(self): """ loads data if not already available and returns the properties """ if not self.model: self.load() return self.model.properties
@property
[docs] def properties(self): """ loads data if not already available and returns the properties """ return self.get_info()
props = properties @property
[docs] def headers(self): """ loads data if not already available and returns the raw headers for the container """ if not self.model: self.load() return self.model.headers
@property
[docs] def meta(self): """ loads data if not already available and returns the metadata for the container """ if not self.model: self.load() return self.model.meta
@property
[docs] def path(self): """ returns path of the container """ path = [self.name] return get_path(path)
@property
[docs] def url(self): """ Returns the url of the container """ path = [self.name] return self.client.get_url(path)
[docs] def is_dir(self): """ Returns if the container is a directory (always True) """ return True
[docs] def set_metadata(self, meta): """ Sets metadata for the container @param meta: dict of metadata on the container @raises ResponseError """ meta_headers = {} for k, v in meta.iteritems(): meta_headers["x-container-meta-{0}".format(k)] = v return self.make_request('POST', headers=meta_headers)
[docs] def create(self): """ Create container @raises ResponseError @return: Containert - self """ def _formatter(res): return self return self.make_request('PUT', formatter=_formatter, headers={'Content-Length': '0'})
[docs] def delete(self, recursive=False): """ Delete container @param recursive: true if you want to delete all of the objects in the container as well. @raises ResponseError @return: True """ return self.client.delete_container(self.name, recursive=recursive)
[docs] def delete_all_objects(self): """ Deletes all objects in the container @raises ResponseError """ resps = [] for item in self.list(): resps.append(item.delete()) return resps
[docs] def delete_object(self, obj): """ Deletes an object in the container @param obj: object name to delete @raises ResponseError """ if isinstance(obj, StorageObject): obj = obj.name return self.client.delete_object(self.name, obj)
[docs] def rename(self, new_container): """ Rename container. Will not work if container is not empty. @param new_container: new container name @raises ResponseError """ self.delete() new_container.create()
[docs] def objects(self, limit=None, marker=None, base_only=False, headers=None): """ Lists objects in the container. @param limit: limit of results to return. @param marker: start listing after this object name @param base_only: only return the base objects. container/object not container/dir/object @param headers: extra headers to use in the request @raises ResponseError @return: list of StorageObject instances """ params = {'format': 'json'} if base_only: params['delimiter'] = '/' if limit: params['limit'] = limit if marker: params['marker'] = marker def _formatter(res): objects = [] if res.content: items = json.loads(res.content) for item in items: if 'name' in item: objects.append(self.storage_object(item['name'], item)) return objects return self.make_request('GET', params=params, headers=headers, formatter=_formatter)
[docs] def set_ttl(self, ttl): """ Set time to live for CDN @param ttl: time in seconds to set as the TTL @raises ResponseError """ if not ttl: ttl = ' ' headers = {'x-cdn-ttl': str(ttl)} return self.make_request('POST', headers=headers)
[docs] def set_read_acl(self, acl): """ Set read ACL @param acl: ACL to set for the container @raises ResponseError """ headers = {'x-container-read': acl} return self.make_request('POST', headers=headers)
[docs] def set_write_acl(self, acl): """ Set write ACL @param acl: ACL to set for the container @raises ResponseError """ headers = {'x-container-write': acl} return self.make_request('POST', headers=headers)
[docs] def make_public(self, ttl=1440): """ Make container public @param ttl: time in seconds to set as the TTL @raises ResponseError """ headers = {'x-container-read': '.r:*', 'x-cdn-ttl': str(ttl)} return self.make_request('POST', headers=headers)
enable_cdn = make_public
[docs] def make_private(self): """ Make container private (empty ACL) @raises ResponseError """ headers = {'x-container-read': ' '} return self.make_request('POST', headers=headers)
disable_cdn = make_private
[docs] def search(self, q, options=None, **kwargs): """ Search within container. """ options = options or {} options.update({'path': self.name}) return self.client.search(q, options=options, **kwargs)
[docs] def get_object(self, name): """ Calls get_object() on the client. """ return self.client.get_object(self.name, name)
[docs] def storage_object(self, name, headers=None): """ Creates a new instance of Object """ return self.client.storage_object(self.name, name, headers=headers)
[docs] def load_from_filename(self, filename): """ Creates an object from a file. Uses the basename of the file path as the object name. """ name = os.path.basename(filename) return self.storage_object(name).load_from_filename(filename)
[docs] def make_request(self, method, path=None, *args, **kwargs): """ Makes a request on the resource. """ path = [self.name] return self.client.make_request(method, path, *args, **kwargs)
def __getitem__(self, name): """ Returns object corresponding to the given name """ return self.storage_object(name) def __str__(self): return self.name def __repr__(self): return 'Container({0})'.format(self.name.encode("utf-8")) def __iter__(self): """ Returns an interator based on results of self.list() """ listing = self.objects() for obj in listing: yield obj