Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / storage.py @ 2bcb595a

History | View | Annotate | Download (3.9 kB)

1 a1c50326 Giorgos Verigakis
# Copyright 2011 GRNET S.A. All rights reserved.
2 a1c50326 Giorgos Verigakis
#
3 a1c50326 Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
4 a1c50326 Giorgos Verigakis
# without modification, are permitted provided that the following
5 a1c50326 Giorgos Verigakis
# conditions are met:
6 a1c50326 Giorgos Verigakis
#
7 a1c50326 Giorgos Verigakis
#   1. Redistributions of source code must retain the above
8 a1c50326 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
9 a1c50326 Giorgos Verigakis
#      disclaimer.
10 a1c50326 Giorgos Verigakis
#
11 a1c50326 Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
12 a1c50326 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
13 a1c50326 Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
14 a1c50326 Giorgos Verigakis
#      provided with the distribution.
15 a1c50326 Giorgos Verigakis
#
16 a1c50326 Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 a1c50326 Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 a1c50326 Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 a1c50326 Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 a1c50326 Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 a1c50326 Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 a1c50326 Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 a1c50326 Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 a1c50326 Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 a1c50326 Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 a1c50326 Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 a1c50326 Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
28 a1c50326 Giorgos Verigakis
#
29 a1c50326 Giorgos Verigakis
# The views and conclusions contained in the software and
30 a1c50326 Giorgos Verigakis
# documentation are those of the authors and should not be
31 a1c50326 Giorgos Verigakis
# interpreted as representing official policies, either expressed
32 a1c50326 Giorgos Verigakis
# or implied, of GRNET S.A.
33 a1c50326 Giorgos Verigakis
34 6a0b1658 Giorgos Verigakis
from . import Client, ClientError
35 a1c50326 Giorgos Verigakis
36 a1c50326 Giorgos Verigakis
37 6a0b1658 Giorgos Verigakis
class StorageClient(Client):
38 d2cea1e2 Giorgos Verigakis
    """OpenStack Object Storage API 1.0 client"""
39 d2cea1e2 Giorgos Verigakis
    
40 6a0b1658 Giorgos Verigakis
    def __init__(self, base_url, token, account=None, container=None):
41 6a0b1658 Giorgos Verigakis
        super(StorageClient, self).__init__(base_url, token)
42 6a0b1658 Giorgos Verigakis
        self.account = account
43 6a0b1658 Giorgos Verigakis
        self.container = container
44 d2cea1e2 Giorgos Verigakis
    
45 6a0b1658 Giorgos Verigakis
    def assert_account(self):
46 6a0b1658 Giorgos Verigakis
        if not self.account:
47 6a0b1658 Giorgos Verigakis
            raise ClientError("Please provide an account")
48 d2cea1e2 Giorgos Verigakis
    
49 6a0b1658 Giorgos Verigakis
    def assert_container(self):
50 6a0b1658 Giorgos Verigakis
        self.assert_account()
51 6a0b1658 Giorgos Verigakis
        if not self.container:
52 6a0b1658 Giorgos Verigakis
            raise ClientError("Please provide a container")
53 d2cea1e2 Giorgos Verigakis
    
54 60560d7c Giorgos Verigakis
    def create_container(self, container):
55 6a0b1658 Giorgos Verigakis
        self.assert_account()
56 60560d7c Giorgos Verigakis
        path = '/%s/%s' % (self.account, container)
57 6a0b1658 Giorgos Verigakis
        r = self.put(path, success=(201, 202))
58 6a0b1658 Giorgos Verigakis
        if r.status_code == 202:
59 6a0b1658 Giorgos Verigakis
            raise ClientError("Container already exists")
60 60560d7c Giorgos Verigakis
    
61 6a0b1658 Giorgos Verigakis
    def get_container_meta(self, container):
62 6a0b1658 Giorgos Verigakis
        self.assert_account()
63 6a0b1658 Giorgos Verigakis
        path = '/%s/%s' % (self.account, container)
64 6a0b1658 Giorgos Verigakis
        r = self.head(path, success=(204, 404))
65 6a0b1658 Giorgos Verigakis
        if r.status_code == 404:
66 6a0b1658 Giorgos Verigakis
            raise ClientError("Container does not exist", r.status_code)
67 6a0b1658 Giorgos Verigakis
        
68 d2cea1e2 Giorgos Verigakis
        reply = {}
69 d2cea1e2 Giorgos Verigakis
        prefix = 'x-container-'
70 6a0b1658 Giorgos Verigakis
        for key, val in r.headers.items():
71 d2cea1e2 Giorgos Verigakis
            key = key.lower()
72 d2cea1e2 Giorgos Verigakis
            if key.startswith(prefix):
73 d2cea1e2 Giorgos Verigakis
                reply[key[len(prefix):]] = val
74 6a0b1658 Giorgos Verigakis
        
75 d2cea1e2 Giorgos Verigakis
        return reply
76 a1c50326 Giorgos Verigakis
    
77 6a0b1658 Giorgos Verigakis
    def create_object(self, object, f, hash_cb=None, upload_cb=None):
78 6a0b1658 Giorgos Verigakis
        # This is a naive implementation, it loads the whole file in memory
79 6a0b1658 Giorgos Verigakis
        self.assert_container()
80 a1c50326 Giorgos Verigakis
        path = '/%s/%s/%s' % (self.account, self.container, object)
81 a1c50326 Giorgos Verigakis
        data = f.read()
82 6a0b1658 Giorgos Verigakis
        self.put(path, data=data, success=201)
83 6a0b1658 Giorgos Verigakis
    
84 176894c1 Giorgos Verigakis
    def get_object(self, object):
85 6a0b1658 Giorgos Verigakis
        self.assert_container()
86 176894c1 Giorgos Verigakis
        path = '/%s/%s/%s' % (self.account, self.container, object)
87 2bcb595a Giorgos Verigakis
        r = self.get(path, raw=True, success=200)
88 6a0b1658 Giorgos Verigakis
        size = int(r.headers['content-length'])
89 6a0b1658 Giorgos Verigakis
        return r.raw, size
90 6a0b1658 Giorgos Verigakis
    
91 a1c50326 Giorgos Verigakis
    def delete_object(self, object):
92 6a0b1658 Giorgos Verigakis
        self.assert_container()
93 a1c50326 Giorgos Verigakis
        path = '/%s/%s/%s' % (self.account, self.container, object)
94 6a0b1658 Giorgos Verigakis
        self.delete(path, success=204)
95 2bcb595a Giorgos Verigakis
    
96 2bcb595a Giorgos Verigakis
    def list_objects(self, path=''):
97 2bcb595a Giorgos Verigakis
        self.assert_container()
98 2bcb595a Giorgos Verigakis
        path = '/%s/%s' % (self.account, self.container)
99 2bcb595a Giorgos Verigakis
        params = dict(format='json')
100 2bcb595a Giorgos Verigakis
        r = self.get(path, params=params, success=(200, 204))
101 2bcb595a Giorgos Verigakis
        return r.json