Revision df79206f kamaki/clients/storage.py

b/kamaki/clients/storage.py
31 31
# interpreted as representing official policies, either expressed
32 32
# or implied, of GRNET S.A.
33 33

  
34
from . import ClientError
35
from .http import HTTPClient
34
from . import Client, ClientError
36 35

  
37 36

  
38
class StorageClient(HTTPClient):
37
class StorageClient(Client):
39 38
    """OpenStack Object Storage API 1.0 client"""
40 39
    
41
    @property
42
    def url(self):
43
        url = self.config.get('storage_url') or self.config.get('url')
44
        if not url:
45
            raise ClientError('No URL was given')
46
        return url
47

  
48
    @property
49
    def token(self):
50
        token = self.config.get('storage_token') or self.config.get('token')
51
        if not token:
52
            raise ClientError('No token was given')
53
        return token
40
    def __init__(self, base_url, token, account=None, container=None):
41
        super(StorageClient, self).__init__(base_url, token)
42
        self.account = account
43
        self.container = container
54 44
    
55
    @property
56
    def account(self):
57
        account = self.config.get('storage_account')
58
        if not account:
59
            raise ClientError('No account was given')
60
        return account
45
    def assert_account(self):
46
        if not self.account:
47
            raise ClientError("Please provide an account")
61 48
    
62
    @property
63
    def container(self):
64
        container = self.config.get('storage_container')
65
        if not container:
66
            raise ClientError('No container was given')
67
        return container
49
    def assert_container(self):
50
        self.assert_account()
51
        if not self.container:
52
            raise ClientError("Please provide a container")
68 53
    
69 54
    def create_container(self, container):
55
        self.assert_account()
70 56
        path = '/%s/%s' % (self.account, container)
71
        self.http_put(path, success=201)
57
        r = self.put(path, success=(201, 202))
58
        if r.status_code == 202:
59
            raise ClientError("Container already exists")
72 60
    
73
    def get_container_meta(self):
74
        path = '/%s/%s' % (self.account, self.container)
75
        resp, reply = self.raw_http_cmd('HEAD', path, success=204)
61
    def get_container_meta(self, container):
62
        self.assert_account()
63
        path = '/%s/%s' % (self.account, container)
64
        r = self.head(path, success=(204, 404))
65
        if r.status_code == 404:
66
            raise ClientError("Container does not exist", r.status_code)
67
        
76 68
        reply = {}
77 69
        prefix = 'x-container-'
78
        for key, val in resp.getheaders():
70
        for key, val in r.headers.items():
79 71
            key = key.lower()
80 72
            if key.startswith(prefix):
81 73
                reply[key[len(prefix):]] = val
74
        
82 75
        return reply
83 76
    
84
    def create_object(self, object, f):
77
    def create_object(self, object, f, hash_cb=None, upload_cb=None):
78
        # This is a naive implementation, it loads the whole file in memory
79
        self.assert_container()
85 80
        path = '/%s/%s/%s' % (self.account, self.container, object)
86 81
        data = f.read()
87
        self.http_put(path, data, success=201)
88

  
82
        self.put(path, data=data, success=201)
83
    
89 84
    def get_object(self, object):
85
        self.assert_container()
90 86
        path = '/%s/%s/%s' % (self.account, self.container, object)
91
        resp, reply = self.raw_http_cmd('GET', path, success=200,
92
                skip_read=True)
93
        return resp.fp
94

  
87
        r = self.get(path, raw=True)
88
        size = int(r.headers['content-length'])
89
        return r.raw, size
90
    
95 91
    def delete_object(self, object):
92
        self.assert_container()
96 93
        path = '/%s/%s/%s' % (self.account, self.container, object)
97
        self.http_delete(path)
94
        self.delete(path, success=204)

Also available in: Unified diff