Statistics
| Branch: | Tag: | Revision:

root / pithos / lib / client.py @ af7bb62f

History | View | Annotate | Download (40.4 kB)

1 2e662088 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 a4c10cbc Sofia Papagiannaki
# 
3 a4c10cbc Sofia Papagiannaki
# Redistribution and use in source and binary forms, with or
4 a4c10cbc Sofia Papagiannaki
# without modification, are permitted provided that the following
5 a4c10cbc Sofia Papagiannaki
# conditions are met:
6 a4c10cbc Sofia Papagiannaki
# 
7 a4c10cbc Sofia Papagiannaki
#   1. Redistributions of source code must retain the above
8 a4c10cbc Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
9 a4c10cbc Sofia Papagiannaki
#      disclaimer.
10 a4c10cbc Sofia Papagiannaki
# 
11 a4c10cbc Sofia Papagiannaki
#   2. Redistributions in binary form must reproduce the above
12 a4c10cbc Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
13 a4c10cbc Sofia Papagiannaki
#      disclaimer in the documentation and/or other materials
14 a4c10cbc Sofia Papagiannaki
#      provided with the distribution.
15 a4c10cbc Sofia Papagiannaki
# 
16 a4c10cbc Sofia Papagiannaki
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 a4c10cbc Sofia Papagiannaki
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 a4c10cbc Sofia Papagiannaki
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 a4c10cbc Sofia Papagiannaki
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 a4c10cbc Sofia Papagiannaki
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 a4c10cbc Sofia Papagiannaki
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 a4c10cbc Sofia Papagiannaki
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 a4c10cbc Sofia Papagiannaki
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 a4c10cbc Sofia Papagiannaki
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 a4c10cbc Sofia Papagiannaki
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 a4c10cbc Sofia Papagiannaki
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 a4c10cbc Sofia Papagiannaki
# POSSIBILITY OF SUCH DAMAGE.
28 a4c10cbc Sofia Papagiannaki
# 
29 a4c10cbc Sofia Papagiannaki
# The views and conclusions contained in the software and
30 a4c10cbc Sofia Papagiannaki
# documentation are those of the authors and should not be
31 a4c10cbc Sofia Papagiannaki
# interpreted as representing official policies, either expressed
32 a4c10cbc Sofia Papagiannaki
# or implied, of GRNET S.A.
33 a4c10cbc Sofia Papagiannaki
34 ec1b8d3e Sofia Papagiannaki
from httplib import HTTPConnection, HTTP
35 ec1b8d3e Sofia Papagiannaki
from sys import stdin
36 f0eacc2c Sofia Papagiannaki
from xml.dom import minidom
37 9471fece Sofia Papagiannaki
from StringIO import StringIO
38 b5dc1bda Sofia Papagiannaki
from urllib import quote, unquote
39 3f5b02c7 Sofia Papagiannaki
40 3f5b02c7 Sofia Papagiannaki
import json
41 ec1b8d3e Sofia Papagiannaki
import types
42 0ea1dcc4 Sofia Papagiannaki
import socket
43 ae75584f Sofia Papagiannaki
import urllib
44 e7b51248 Sofia Papagiannaki
import datetime
45 e3fd7f91 Sofia Papagiannaki
46 e3fd7f91 Sofia Papagiannaki
ERROR_CODES = {304:'Not Modified',
47 e3fd7f91 Sofia Papagiannaki
               400:'Bad Request',
48 e3fd7f91 Sofia Papagiannaki
               401:'Unauthorized',
49 81ed48a5 Sofia Papagiannaki
               403:'Forbidden',
50 e3fd7f91 Sofia Papagiannaki
               404:'Not Found',
51 e3fd7f91 Sofia Papagiannaki
               409:'Conflict',
52 e3fd7f91 Sofia Papagiannaki
               411:'Length Required',
53 e3fd7f91 Sofia Papagiannaki
               412:'Precondition Failed',
54 81ed48a5 Sofia Papagiannaki
               413:'Request Entity Too Large',
55 e3fd7f91 Sofia Papagiannaki
               416:'Range Not Satisfiable',
56 e3fd7f91 Sofia Papagiannaki
               422:'Unprocessable Entity',
57 08de868d Antony Chazapis
               500:'Internal Server Error',
58 08de868d Antony Chazapis
               501:'Not Implemented'}
59 3f5b02c7 Sofia Papagiannaki
60 3f5b02c7 Sofia Papagiannaki
class Fault(Exception):
61 e3fd7f91 Sofia Papagiannaki
    def __init__(self, data='', status=None):
62 e3fd7f91 Sofia Papagiannaki
        if data == '' and status in ERROR_CODES.keys():
63 e3fd7f91 Sofia Papagiannaki
            data = ERROR_CODES[status]
64 3f5b02c7 Sofia Papagiannaki
        Exception.__init__(self, data)
65 3f5b02c7 Sofia Papagiannaki
        self.data = data
66 e3fd7f91 Sofia Papagiannaki
        self.status = status
67 3f5b02c7 Sofia Papagiannaki
68 3f5b02c7 Sofia Papagiannaki
class Client(object):
69 bcb7c5a8 Sofia Papagiannaki
    def __init__(self, host, token, account, api='v1', verbose=False, debug=False):
70 3f5b02c7 Sofia Papagiannaki
        """`host` can also include a port, e.g '127.0.0.1:8000'."""
71 3f5b02c7 Sofia Papagiannaki
        
72 3f5b02c7 Sofia Papagiannaki
        self.host = host
73 3f5b02c7 Sofia Papagiannaki
        self.account = account
74 3f5b02c7 Sofia Papagiannaki
        self.api = api
75 3f5b02c7 Sofia Papagiannaki
        self.verbose = verbose or debug
76 3f5b02c7 Sofia Papagiannaki
        self.debug = debug
77 bcb7c5a8 Sofia Papagiannaki
        self.token = token
78 f7ab99df Sofia Papagiannaki
    
79 95e92490 Sofia Papagiannaki
    def _req(self, method, path, body=None, headers={}, format='text', params={}):
80 f1716de7 Sofia Papagiannaki
        full_path = _prepare_path(path, self.api, format, params)
81 ae75584f Sofia Papagiannaki
        
82 3f5b02c7 Sofia Papagiannaki
        conn = HTTPConnection(self.host)
83 3f5b02c7 Sofia Papagiannaki
        kwargs = {}
84 f1716de7 Sofia Papagiannaki
        kwargs['headers'] = _prepare_headers(headers)
85 bcb7c5a8 Sofia Papagiannaki
        kwargs['headers']['X-Auth-Token'] = self.token
86 3f5b02c7 Sofia Papagiannaki
        if body:
87 3f5b02c7 Sofia Papagiannaki
            kwargs['body'] = body
88 bcd29125 Sofia Papagiannaki
            kwargs['headers'].setdefault('content-type', 'application/octet-stream')
89 25c3841c Sofia Papagiannaki
        kwargs['headers'].setdefault('content-length', len(body) if body else 0)
90 e7b51248 Sofia Papagiannaki
        
91 ae75584f Sofia Papagiannaki
        #print '#', method, full_path, kwargs
92 f1716de7 Sofia Papagiannaki
        #t1 = datetime.datetime.utcnow()
93 ae75584f Sofia Papagiannaki
        conn.request(method, full_path, **kwargs)
94 ae75584f Sofia Papagiannaki
        
95 3f5b02c7 Sofia Papagiannaki
        resp = conn.getresponse()
96 f1716de7 Sofia Papagiannaki
        #t2 = datetime.datetime.utcnow()
97 e7b51248 Sofia Papagiannaki
        #print 'response time:', str(t2-t1)
98 f1716de7 Sofia Papagiannaki
        return _handle_response(resp, self.verbose, self.debug)
99 f7ab99df Sofia Papagiannaki
    
100 633bbb9f Sofia Papagiannaki
    def _chunked_transfer(self, path, method='PUT', f=stdin, headers=None,
101 633bbb9f Sofia Papagiannaki
                          blocksize=1024, params={}):
102 633bbb9f Sofia Papagiannaki
        """perfomrs a chunked request"""
103 f1716de7 Sofia Papagiannaki
        full_path = _prepare_path(path, self.api, params=params)
104 633bbb9f Sofia Papagiannaki
        
105 f1716de7 Sofia Papagiannaki
        conn = HTTPConnection(self.host)
106 f1716de7 Sofia Papagiannaki
        conn.putrequest(method, full_path)
107 f1716de7 Sofia Papagiannaki
        conn.putheader('x-auth-token', self.token)
108 f1716de7 Sofia Papagiannaki
        conn.putheader('content-type', 'application/octet-stream')
109 f1716de7 Sofia Papagiannaki
        conn.putheader('transfer-encoding', 'chunked')
110 f1716de7 Sofia Papagiannaki
        for k,v in _prepare_headers(headers).items():
111 f1716de7 Sofia Papagiannaki
            conn.putheader(k, v)
112 f1716de7 Sofia Papagiannaki
        conn.endheaders()
113 633bbb9f Sofia Papagiannaki
        
114 633bbb9f Sofia Papagiannaki
        # write body
115 633bbb9f Sofia Papagiannaki
        data = ''
116 633bbb9f Sofia Papagiannaki
        while True:
117 633bbb9f Sofia Papagiannaki
            if f.closed:
118 633bbb9f Sofia Papagiannaki
                break
119 633bbb9f Sofia Papagiannaki
            block = f.read(blocksize)
120 633bbb9f Sofia Papagiannaki
            if block == '':
121 633bbb9f Sofia Papagiannaki
                break
122 633bbb9f Sofia Papagiannaki
            data = '%x\r\n%s\r\n' % (len(block), block)
123 633bbb9f Sofia Papagiannaki
            try:
124 f1716de7 Sofia Papagiannaki
                conn.send(data)
125 633bbb9f Sofia Papagiannaki
            except:
126 633bbb9f Sofia Papagiannaki
                #retry
127 f1716de7 Sofia Papagiannaki
                conn.send(data)
128 633bbb9f Sofia Papagiannaki
        data = '0\r\n\r\n'
129 633bbb9f Sofia Papagiannaki
        try:
130 f1716de7 Sofia Papagiannaki
            conn.send(data)
131 633bbb9f Sofia Papagiannaki
        except:
132 633bbb9f Sofia Papagiannaki
            #retry
133 f1716de7 Sofia Papagiannaki
            conn.send(data)
134 633bbb9f Sofia Papagiannaki
        
135 f1716de7 Sofia Papagiannaki
        resp = conn.getresponse()
136 f1716de7 Sofia Papagiannaki
        return _handle_response(resp, self.verbose, self.debug)
137 633bbb9f Sofia Papagiannaki
    
138 25c3841c Sofia Papagiannaki
    def delete(self, path, format='text', params={}):
139 25c3841c Sofia Papagiannaki
        return self._req('DELETE', path, format=format, params=params)
140 f7ab99df Sofia Papagiannaki
    
141 95e92490 Sofia Papagiannaki
    def get(self, path, format='text', headers={}, params={}):
142 615e561b Sofia Papagiannaki
        return self._req('GET', path, headers=headers, format=format,
143 95e92490 Sofia Papagiannaki
                        params=params)
144 f7ab99df Sofia Papagiannaki
    
145 25c3841c Sofia Papagiannaki
    def head(self, path, format='text', params={}):
146 ae75584f Sofia Papagiannaki
         return self._req('HEAD', path, format=format, params=params)
147 f7ab99df Sofia Papagiannaki
    
148 25c3841c Sofia Papagiannaki
    def post(self, path, body=None, format='text', headers=None, params={}):
149 615e561b Sofia Papagiannaki
        return self._req('POST', path, body, headers=headers, format=format,
150 6749c3bd Sofia Papagiannaki
                        params=params)
151 f7ab99df Sofia Papagiannaki
    
152 9471fece Sofia Papagiannaki
    def put(self, path, body=None, format='text', headers=None, params={}):
153 9471fece Sofia Papagiannaki
        return self._req('PUT', path, body, headers=headers, format=format,
154 9471fece Sofia Papagiannaki
                         params=params)
155 f7ab99df Sofia Papagiannaki
    
156 95e92490 Sofia Papagiannaki
    def _list(self, path, format='text', params={}, **headers):
157 3f5b02c7 Sofia Papagiannaki
        status, headers, data = self.get(path, format=format, headers=headers,
158 95e92490 Sofia Papagiannaki
                                         params=params)
159 f0eacc2c Sofia Papagiannaki
        if format == 'json':
160 bcb7c5a8 Sofia Papagiannaki
            data = json.loads(data) if data else ''
161 f0eacc2c Sofia Papagiannaki
        elif format == 'xml':
162 f0eacc2c Sofia Papagiannaki
            data = minidom.parseString(data)
163 ec1b8d3e Sofia Papagiannaki
        else:
164 908c6f81 Sofia Papagiannaki
            data = data.split('\n')[:-1] if data else ''
165 3f5b02c7 Sofia Papagiannaki
        return data
166 f7ab99df Sofia Papagiannaki
    
167 25c3841c Sofia Papagiannaki
    def _get_metadata(self, path, prefix=None, params={}):
168 d2d5c360 Sofia Papagiannaki
        status, headers, data = self.head(path, params=params)
169 f7ab99df Sofia Papagiannaki
        prefixlen = len(prefix) if prefix else 0
170 3f5b02c7 Sofia Papagiannaki
        meta = {}
171 3f5b02c7 Sofia Papagiannaki
        for key, val in headers.items():
172 0ea1dcc4 Sofia Papagiannaki
            if prefix and not key.startswith(prefix):
173 0ea1dcc4 Sofia Papagiannaki
                continue
174 0ea1dcc4 Sofia Papagiannaki
            elif prefix and key.startswith(prefix):
175 3f5b02c7 Sofia Papagiannaki
                key = key[prefixlen:]
176 0ea1dcc4 Sofia Papagiannaki
            meta[key] = val
177 3f5b02c7 Sofia Papagiannaki
        return meta
178 f7ab99df Sofia Papagiannaki
    
179 25c3841c Sofia Papagiannaki
    def _filter(self, l, d):
180 f7ab99df Sofia Papagiannaki
        """
181 25c3841c Sofia Papagiannaki
        filter out from l elements having the metadata values provided
182 f7ab99df Sofia Papagiannaki
        """
183 25c3841c Sofia Papagiannaki
        ll = l
184 25c3841c Sofia Papagiannaki
        for elem in l:
185 25c3841c Sofia Papagiannaki
            if type(elem) == types.DictionaryType:
186 25c3841c Sofia Papagiannaki
                for key in d.keys():
187 25c3841c Sofia Papagiannaki
                    k = 'x_object_meta_%s' % key
188 25c3841c Sofia Papagiannaki
                    if k in elem.keys() and elem[k] == d[key]:
189 25c3841c Sofia Papagiannaki
                        ll.remove(elem)
190 25c3841c Sofia Papagiannaki
                        break
191 25c3841c Sofia Papagiannaki
        return ll
192 25c3841c Sofia Papagiannaki
    
193 25c3841c Sofia Papagiannaki
class OOS_Client(Client):
194 f0eacc2c Sofia Papagiannaki
    """Openstack Object Storage Client"""
195 25c3841c Sofia Papagiannaki
    
196 25c3841c Sofia Papagiannaki
    def _update_metadata(self, path, entity, **meta):
197 25c3841c Sofia Papagiannaki
        """adds new and updates the values of previously set metadata"""
198 25c3841c Sofia Papagiannaki
        ex_meta = self.retrieve_account_metadata(restricted=True)
199 25c3841c Sofia Papagiannaki
        ex_meta.update(meta)
200 f7ab99df Sofia Papagiannaki
        headers = {}
201 6749c3bd Sofia Papagiannaki
        prefix = 'x-%s-meta-' % entity
202 25c3841c Sofia Papagiannaki
        for k,v in ex_meta.items():
203 6749c3bd Sofia Papagiannaki
            k = '%s%s' % (prefix, k)
204 6749c3bd Sofia Papagiannaki
            headers[k] = v
205 cd6ada1d Sofia Papagiannaki
        return self.post(path, headers=headers)
206 f7ab99df Sofia Papagiannaki
    
207 b9ca81a0 Sofia Papagiannaki
    def _reset_metadata(self, path, entity, **meta):
208 b9ca81a0 Sofia Papagiannaki
        """
209 b9ca81a0 Sofia Papagiannaki
        overwrites all user defined metadata
210 b9ca81a0 Sofia Papagiannaki
        """
211 b9ca81a0 Sofia Papagiannaki
        headers = {}
212 b9ca81a0 Sofia Papagiannaki
        prefix = 'x-%s-meta-' % entity
213 b9ca81a0 Sofia Papagiannaki
        for k,v in meta.items():
214 b9ca81a0 Sofia Papagiannaki
            k = '%s%s' % (prefix, k)
215 b9ca81a0 Sofia Papagiannaki
            headers[k] = v
216 b9ca81a0 Sofia Papagiannaki
        return self.post(path, headers=headers)
217 b9ca81a0 Sofia Papagiannaki
    
218 f7ab99df Sofia Papagiannaki
    def _delete_metadata(self, path, entity, meta=[]):
219 25c3841c Sofia Papagiannaki
        """delete previously set metadata"""
220 25c3841c Sofia Papagiannaki
        ex_meta = self.retrieve_account_metadata(restricted=True)
221 f7ab99df Sofia Papagiannaki
        headers = {}
222 615e561b Sofia Papagiannaki
        prefix = 'x-%s-meta-' % entity
223 25c3841c Sofia Papagiannaki
        for k in ex_meta.keys():
224 25c3841c Sofia Papagiannaki
            if k in meta:
225 25c3841c Sofia Papagiannaki
                headers['%s%s' % (prefix, k)] = ex_meta[k]
226 615e561b Sofia Papagiannaki
        return self.post(path, headers=headers)
227 f7ab99df Sofia Papagiannaki
    
228 3f5b02c7 Sofia Papagiannaki
    # Storage Account Services
229 f7ab99df Sofia Papagiannaki
    
230 95e92490 Sofia Papagiannaki
    def list_containers(self, format='text', limit=None,
231 95e92490 Sofia Papagiannaki
                        marker=None, params={}, account=None, **headers):
232 25c3841c Sofia Papagiannaki
        """lists containers"""
233 95e92490 Sofia Papagiannaki
        account = account or self.account
234 95e92490 Sofia Papagiannaki
        path = '/%s' % account
235 25c3841c Sofia Papagiannaki
        params.update({'limit':limit, 'marker':marker})
236 95e92490 Sofia Papagiannaki
        return self._list(path, format, params, **headers)
237 f7ab99df Sofia Papagiannaki
    
238 95e92490 Sofia Papagiannaki
    def retrieve_account_metadata(self, restricted=False, account=None, **params):
239 25c3841c Sofia Papagiannaki
        """returns the account metadata"""
240 95e92490 Sofia Papagiannaki
        account = account or self.account
241 95e92490 Sofia Papagiannaki
        path = '/%s' % account
242 f7ab99df Sofia Papagiannaki
        prefix = 'x-account-meta-' if restricted else None
243 95e92490 Sofia Papagiannaki
        return self._get_metadata(path, prefix, params)
244 f7ab99df Sofia Papagiannaki
    
245 95e92490 Sofia Papagiannaki
    def update_account_metadata(self, account=None, **meta):
246 25c3841c Sofia Papagiannaki
        """updates the account metadata"""
247 95e92490 Sofia Papagiannaki
        account = account or self.account
248 95e92490 Sofia Papagiannaki
        path = '/%s' % account
249 95e92490 Sofia Papagiannaki
        return self._update_metadata(path, 'account', **meta)
250 f7ab99df Sofia Papagiannaki
        
251 95e92490 Sofia Papagiannaki
    def delete_account_metadata(self, meta=[], account=None):
252 25c3841c Sofia Papagiannaki
        """deletes the account metadata"""
253 95e92490 Sofia Papagiannaki
        account = account or self.account
254 95e92490 Sofia Papagiannaki
        path = '/%s' % account
255 95e92490 Sofia Papagiannaki
        return self._delete_metadata(path, 'account', meta)
256 f7ab99df Sofia Papagiannaki
    
257 95e92490 Sofia Papagiannaki
    def reset_account_metadata(self, account=None, **meta):
258 b9ca81a0 Sofia Papagiannaki
        """resets account metadata"""
259 95e92490 Sofia Papagiannaki
        account = account or self.account
260 95e92490 Sofia Papagiannaki
        path = '/%s' % account
261 95e92490 Sofia Papagiannaki
        return self._reset_metadata(path, 'account', **meta)
262 b9ca81a0 Sofia Papagiannaki
    
263 3f5b02c7 Sofia Papagiannaki
    # Storage Container Services
264 f7ab99df Sofia Papagiannaki
    
265 a4c10cbc Sofia Papagiannaki
    def _filter_trashed(self, l):
266 a4c10cbc Sofia Papagiannaki
        return self._filter(l, {'trash':'true'})
267 a4c10cbc Sofia Papagiannaki
    
268 95e92490 Sofia Papagiannaki
    def list_objects(self, container, format='text',
269 95e92490 Sofia Papagiannaki
                     limit=None, marker=None, prefix=None, delimiter=None,
270 95e92490 Sofia Papagiannaki
                     path=None, include_trashed=False, params={}, account=None,
271 95e92490 Sofia Papagiannaki
                     **headers):
272 25c3841c Sofia Papagiannaki
        """returns a list with the container objects"""
273 95e92490 Sofia Papagiannaki
        account = account or self.account
274 25c3841c Sofia Papagiannaki
        params.update({'limit':limit, 'marker':marker, 'prefix':prefix,
275 25c3841c Sofia Papagiannaki
                       'delimiter':delimiter, 'path':path})
276 95e92490 Sofia Papagiannaki
        l = self._list('/%s/%s' % (account, container), format, params,
277 95e92490 Sofia Papagiannaki
                       **headers)
278 f0eacc2c Sofia Papagiannaki
        #TODO support filter trashed with xml also
279 f0eacc2c Sofia Papagiannaki
        if format != 'xml' and not include_trashed:
280 a4c10cbc Sofia Papagiannaki
            l = self._filter_trashed(l)
281 a4c10cbc Sofia Papagiannaki
        return l
282 f7ab99df Sofia Papagiannaki
    
283 95e92490 Sofia Papagiannaki
    def create_container(self, container, account=None, **meta):
284 25c3841c Sofia Papagiannaki
        """creates a container"""
285 95e92490 Sofia Papagiannaki
        account = account or self.account
286 25c3841c Sofia Papagiannaki
        headers = {}
287 bcb7c5a8 Sofia Papagiannaki
        for k,v in meta.items():
288 615e561b Sofia Papagiannaki
            headers['x-container-meta-%s' %k.strip().upper()] = v.strip()
289 95e92490 Sofia Papagiannaki
        status, header, data = self.put('/%s/%s' % (account, container),
290 95e92490 Sofia Papagiannaki
                                        headers=headers)
291 3f5b02c7 Sofia Papagiannaki
        if status == 202:
292 3f5b02c7 Sofia Papagiannaki
            return False
293 3f5b02c7 Sofia Papagiannaki
        elif status != 201:
294 e3fd7f91 Sofia Papagiannaki
            raise Fault(data, int(status))
295 3f5b02c7 Sofia Papagiannaki
        return True
296 f7ab99df Sofia Papagiannaki
    
297 95e92490 Sofia Papagiannaki
    def delete_container(self, container, params={}, account=None):
298 25c3841c Sofia Papagiannaki
        """deletes a container"""
299 95e92490 Sofia Papagiannaki
        account = account or self.account
300 95e92490 Sofia Papagiannaki
        return self.delete('/%s/%s' % (account, container), params=params)
301 f7ab99df Sofia Papagiannaki
    
302 95e92490 Sofia Papagiannaki
    def retrieve_container_metadata(self, container, restricted=False,
303 95e92490 Sofia Papagiannaki
                                    account=None, **params):
304 25c3841c Sofia Papagiannaki
        """returns the container metadata"""
305 95e92490 Sofia Papagiannaki
        account = account or self.account
306 f7ab99df Sofia Papagiannaki
        prefix = 'x-container-meta-' if restricted else None
307 95e92490 Sofia Papagiannaki
        return self._get_metadata('/%s/%s' % (account, container), prefix,
308 95e92490 Sofia Papagiannaki
                                  params)
309 f7ab99df Sofia Papagiannaki
    
310 95e92490 Sofia Papagiannaki
    def update_container_metadata(self, container, account=None, **meta):
311 25c3841c Sofia Papagiannaki
        """unpdates the container metadata"""
312 95e92490 Sofia Papagiannaki
        account = account or self.account
313 95e92490 Sofia Papagiannaki
        return self._update_metadata('/%s/%s' % (account, container),
314 95e92490 Sofia Papagiannaki
                                     'container', **meta)
315 f7ab99df Sofia Papagiannaki
        
316 95e92490 Sofia Papagiannaki
    def delete_container_metadata(self, container, meta=[], account=None):
317 25c3841c Sofia Papagiannaki
        """deletes the container metadata"""
318 95e92490 Sofia Papagiannaki
        account = account or self.account
319 95e92490 Sofia Papagiannaki
        path = '/%s/%s' % (account, container)
320 615e561b Sofia Papagiannaki
        return self._delete_metadata(path, 'container', meta)
321 f7ab99df Sofia Papagiannaki
    
322 3f5b02c7 Sofia Papagiannaki
    # Storage Object Services
323 f7ab99df Sofia Papagiannaki
    
324 f0eacc2c Sofia Papagiannaki
    def request_object(self, container, object, format='text', params={},
325 95e92490 Sofia Papagiannaki
                       account=None, **headers):
326 25c3841c Sofia Papagiannaki
        """returns tuple containing the status, headers and data response for an object request"""
327 95e92490 Sofia Papagiannaki
        account = account or self.account
328 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
329 8fe01d72 Sofia Papagiannaki
        status, headers, data = self.get(path, format, headers, params)
330 25c3841c Sofia Papagiannaki
        return status, headers, data
331 25c3841c Sofia Papagiannaki
    
332 f0eacc2c Sofia Papagiannaki
    def retrieve_object(self, container, object, format='text', params={},
333 95e92490 Sofia Papagiannaki
                        account=None, **headers):
334 25c3841c Sofia Papagiannaki
        """returns an object's data"""
335 95e92490 Sofia Papagiannaki
        account = account or self.account
336 95e92490 Sofia Papagiannaki
        t = self.request_object(container, object, format, params, account,
337 95e92490 Sofia Papagiannaki
                                **headers)
338 3078108a Sofia Papagiannaki
        data = t[2]
339 3078108a Sofia Papagiannaki
        if format == 'json':
340 3078108a Sofia Papagiannaki
            data = json.loads(data) if data else ''
341 3078108a Sofia Papagiannaki
        elif format == 'xml':
342 3078108a Sofia Papagiannaki
            data = minidom.parseString(data)
343 3078108a Sofia Papagiannaki
        return data
344 3078108a Sofia Papagiannaki
    
345 3078108a Sofia Papagiannaki
    def retrieve_object_hashmap(self, container, object, params={},
346 3078108a Sofia Papagiannaki
                        account=None, **headers):
347 3078108a Sofia Papagiannaki
        """returns the hashmap representing object's data"""
348 9471fece Sofia Papagiannaki
        args = locals().copy()
349 3078108a Sofia Papagiannaki
        for elem in ['self', 'container', 'object']:
350 3078108a Sofia Papagiannaki
            args.pop(elem)
351 fd9f505c Antony Chazapis
        return self.retrieve_object(container, object, format='json', **args)
352 f7ab99df Sofia Papagiannaki
    
353 95e92490 Sofia Papagiannaki
    def create_directory_marker(self, container, object, account=None):
354 25c3841c Sofia Papagiannaki
        """creates a dierectory marker"""
355 95e92490 Sofia Papagiannaki
        account = account or self.account
356 f7ab99df Sofia Papagiannaki
        if not object:
357 f7ab99df Sofia Papagiannaki
            raise Fault('Directory markers have to be nested in a container')
358 7912c553 Sofia Papagiannaki
        h = {'content_type':'application/directory'}
359 95e92490 Sofia Papagiannaki
        return self.create_zero_length_object(container, object, account=account,
360 95e92490 Sofia Papagiannaki
                                              **h)
361 f7ab99df Sofia Papagiannaki
    
362 25c3841c Sofia Papagiannaki
    def create_object(self, container, object, f=stdin, format='text', meta={},
363 9471fece Sofia Papagiannaki
                      params={}, etag=None, content_type=None, content_encoding=None,
364 95e92490 Sofia Papagiannaki
                      content_disposition=None, account=None, **headers):
365 cd6ada1d Sofia Papagiannaki
        """creates a zero-length object"""
366 95e92490 Sofia Papagiannaki
        account = account or self.account
367 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
368 25c3841c Sofia Papagiannaki
        for k, v  in headers.items():
369 38bf2cdc Sofia Papagiannaki
            if v == None:
370 25c3841c Sofia Papagiannaki
                headers.pop(k)
371 25c3841c Sofia Papagiannaki
        
372 25c3841c Sofia Papagiannaki
        l = ['etag', 'content_encoding', 'content_disposition', 'content_type']
373 25c3841c Sofia Papagiannaki
        l = [elem for elem in l if eval(elem)]
374 25c3841c Sofia Papagiannaki
        for elem in l:
375 25c3841c Sofia Papagiannaki
            headers.update({elem:eval(elem)})
376 bcd29125 Sofia Papagiannaki
        headers.setdefault('content-type', 'application/octet-stream')
377 bcd29125 Sofia Papagiannaki
        
378 615e561b Sofia Papagiannaki
        for k,v in meta.items():
379 615e561b Sofia Papagiannaki
            headers['x-object-meta-%s' %k.strip()] = v.strip()
380 25c3841c Sofia Papagiannaki
        data = f.read() if f else None
381 9471fece Sofia Papagiannaki
        return self.put(path, data, format, headers=headers, params=params)
382 615e561b Sofia Papagiannaki
    
383 cd6ada1d Sofia Papagiannaki
    def create_zero_length_object(self, container, object, meta={}, etag=None,
384 cd6ada1d Sofia Papagiannaki
                                  content_type=None, content_encoding=None,
385 95e92490 Sofia Papagiannaki
                                  content_disposition=None, account=None,
386 95e92490 Sofia Papagiannaki
                                  **headers):
387 95e92490 Sofia Papagiannaki
        account = account or self.account
388 9471fece Sofia Papagiannaki
        args = locals().copy()
389 95e92490 Sofia Papagiannaki
        for elem in ['self', 'container', 'headers', 'account']:
390 cd6ada1d Sofia Papagiannaki
            args.pop(elem)
391 cd6ada1d Sofia Papagiannaki
        args.update(headers)
392 95e92490 Sofia Papagiannaki
        return self.create_object(container, account=account, f=None, **args)
393 95e92490 Sofia Papagiannaki
    
394 95e92490 Sofia Papagiannaki
    def update_object(self, container, object, f=stdin,
395 633bbb9f Sofia Papagiannaki
                      offset=None, meta={}, params={}, content_length=None,
396 95e92490 Sofia Papagiannaki
                      content_type=None, content_encoding=None,
397 95e92490 Sofia Papagiannaki
                      content_disposition=None,  account=None, **headers):
398 95e92490 Sofia Papagiannaki
        account = account or self.account
399 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
400 25c3841c Sofia Papagiannaki
        for k, v  in headers.items():
401 38bf2cdc Sofia Papagiannaki
            if v == None:
402 25c3841c Sofia Papagiannaki
                headers.pop(k)
403 25c3841c Sofia Papagiannaki
        
404 25c3841c Sofia Papagiannaki
        l = ['content_encoding', 'content_disposition', 'content_type',
405 25c3841c Sofia Papagiannaki
             'content_length']
406 25c3841c Sofia Papagiannaki
        l = [elem for elem in l if eval(elem)]
407 25c3841c Sofia Papagiannaki
        for elem in l:
408 25c3841c Sofia Papagiannaki
            headers.update({elem:eval(elem)})
409 48a1abe5 Sofia Papagiannaki
        
410 25c3841c Sofia Papagiannaki
        if 'content_range' not in headers.keys():
411 25c3841c Sofia Papagiannaki
            if offset != None:
412 25c3841c Sofia Papagiannaki
                headers['content_range'] = 'bytes %s-/*' % offset
413 25c3841c Sofia Papagiannaki
            else:
414 25c3841c Sofia Papagiannaki
                headers['content_range'] = 'bytes */*'
415 25c3841c Sofia Papagiannaki
            
416 bcb7c5a8 Sofia Papagiannaki
        for k,v in meta.items():
417 615e561b Sofia Papagiannaki
            headers['x-object-meta-%s' %k.strip()] = v.strip()
418 25c3841c Sofia Papagiannaki
        data = f.read() if f else None
419 633bbb9f Sofia Papagiannaki
        return self.post(path, data, headers=headers, params=params)
420 633bbb9f Sofia Papagiannaki
    
421 633bbb9f Sofia Papagiannaki
    def update_object_using_chunks(self, container, object, f=stdin,
422 633bbb9f Sofia Papagiannaki
                                   blocksize=1024, offset=None, meta={},
423 633bbb9f Sofia Papagiannaki
                                   params={}, content_type=None, content_encoding=None,
424 633bbb9f Sofia Papagiannaki
                                   content_disposition=None, account=None, **headers):
425 633bbb9f Sofia Papagiannaki
        """updates an object (incremental upload)"""
426 633bbb9f Sofia Papagiannaki
        account = account or self.account
427 633bbb9f Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
428 633bbb9f Sofia Papagiannaki
        headers = headers if not headers else {}
429 633bbb9f Sofia Papagiannaki
        l = ['content_type', 'content_encoding', 'content_disposition']
430 633bbb9f Sofia Papagiannaki
        l = [elem for elem in l if eval(elem)]
431 633bbb9f Sofia Papagiannaki
        for elem in l:
432 633bbb9f Sofia Papagiannaki
            headers.update({elem:eval(elem)})
433 633bbb9f Sofia Papagiannaki
        
434 633bbb9f Sofia Papagiannaki
        if offset != None:
435 633bbb9f Sofia Papagiannaki
            headers['content_range'] = 'bytes %s-/*' % offset
436 633bbb9f Sofia Papagiannaki
        else:
437 633bbb9f Sofia Papagiannaki
            headers['content_range'] = 'bytes */*'
438 633bbb9f Sofia Papagiannaki
        
439 633bbb9f Sofia Papagiannaki
        for k,v in meta.items():
440 633bbb9f Sofia Papagiannaki
            v = v.strip()
441 633bbb9f Sofia Papagiannaki
            headers['x-object-meta-%s' %k.strip()] = v
442 633bbb9f Sofia Papagiannaki
        return self._chunked_transfer(path, 'POST', f, headers=headers,
443 633bbb9f Sofia Papagiannaki
                                      blocksize=blocksize, params=params)
444 f7ab99df Sofia Papagiannaki
    
445 ec1b8d3e Sofia Papagiannaki
    def _change_obj_location(self, src_container, src_object, dst_container,
446 95e92490 Sofia Papagiannaki
                             dst_object, remove=False, meta={}, account=None,
447 d4a63b9b Sofia Papagiannaki
                             content_type=None, **headers):
448 95e92490 Sofia Papagiannaki
        account = account or self.account
449 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, dst_container, dst_object)
450 7812e1f9 Sofia Papagiannaki
        headers = {} if not headers else headers
451 53cff70c Antony Chazapis
        params = {}
452 615e561b Sofia Papagiannaki
        for k, v in meta.items():
453 ae75584f Sofia Papagiannaki
            headers['x-object-meta-%s' % k] = v
454 ec1b8d3e Sofia Papagiannaki
        if remove:
455 615e561b Sofia Papagiannaki
            headers['x-move-from'] = '/%s/%s' % (src_container, src_object)
456 ec1b8d3e Sofia Papagiannaki
        else:
457 615e561b Sofia Papagiannaki
            headers['x-copy-from'] = '/%s/%s' % (src_container, src_object)
458 7812e1f9 Sofia Papagiannaki
        headers['content_length'] = 0
459 d4a63b9b Sofia Papagiannaki
        if content_type:
460 53cff70c Antony Chazapis
            headers['content_type'] = content_type
461 53cff70c Antony Chazapis
        else:
462 53cff70c Antony Chazapis
            params['ignore_content_type'] = ''
463 53cff70c Antony Chazapis
        return self.put(path, headers=headers, params=params)
464 f7ab99df Sofia Papagiannaki
    
465 7812e1f9 Sofia Papagiannaki
    def copy_object(self, src_container, src_object, dst_container, dst_object,
466 d4a63b9b Sofia Papagiannaki
                   meta={}, account=None, content_type=None, **headers):
467 7812e1f9 Sofia Papagiannaki
        """copies an object"""
468 95e92490 Sofia Papagiannaki
        account = account or self.account
469 615e561b Sofia Papagiannaki
        return self._change_obj_location(src_container, src_object,
470 95e92490 Sofia Papagiannaki
                                   dst_container, dst_object, account=account,
471 d4a63b9b Sofia Papagiannaki
                                   remove=False, meta=meta,
472 d4a63b9b Sofia Papagiannaki
                                   content_type=content_type, **headers)
473 f7ab99df Sofia Papagiannaki
    
474 ec1b8d3e Sofia Papagiannaki
    def move_object(self, src_container, src_object, dst_container,
475 95e92490 Sofia Papagiannaki
                             dst_object, meta={}, account=None,
476 d4a63b9b Sofia Papagiannaki
                             content_type=None, **headers):
477 7812e1f9 Sofia Papagiannaki
        """moves an object"""
478 95e92490 Sofia Papagiannaki
        account = account or self.account
479 615e561b Sofia Papagiannaki
        return self._change_obj_location(src_container, src_object,
480 95e92490 Sofia Papagiannaki
                                         dst_container, dst_object,
481 95e92490 Sofia Papagiannaki
                                         account=account, remove=True,
482 d4a63b9b Sofia Papagiannaki
                                         meta=meta, content_type=content_type,
483 d4a63b9b Sofia Papagiannaki
                                         **headers)
484 f7ab99df Sofia Papagiannaki
    
485 95e92490 Sofia Papagiannaki
    def delete_object(self, container, object, params={}, account=None):
486 7812e1f9 Sofia Papagiannaki
        """deletes an object"""
487 95e92490 Sofia Papagiannaki
        account = account or self.account
488 95e92490 Sofia Papagiannaki
        return self.delete('/%s/%s/%s' % (account, container, object),
489 95e92490 Sofia Papagiannaki
                           params=params)
490 f7ab99df Sofia Papagiannaki
    
491 8fe01d72 Sofia Papagiannaki
    def retrieve_object_metadata(self, container, object, restricted=False,
492 95e92490 Sofia Papagiannaki
                                 version=None, account=None):
493 615e561b Sofia Papagiannaki
        """
494 615e561b Sofia Papagiannaki
        set restricted to True to get only user defined metadata
495 615e561b Sofia Papagiannaki
        """
496 95e92490 Sofia Papagiannaki
        account = account or self.account
497 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
498 f7ab99df Sofia Papagiannaki
        prefix = 'x-object-meta-' if restricted else None
499 25c3841c Sofia Papagiannaki
        params = {'version':version} if version else {}
500 8fe01d72 Sofia Papagiannaki
        return self._get_metadata(path, prefix, params=params)
501 f7ab99df Sofia Papagiannaki
    
502 95e92490 Sofia Papagiannaki
    def update_object_metadata(self, container, object, account=None,
503 95e92490 Sofia Papagiannaki
                               **meta):
504 e7b51248 Sofia Papagiannaki
        """
505 e7b51248 Sofia Papagiannaki
        updates object's metadata
506 e7b51248 Sofia Papagiannaki
        """
507 95e92490 Sofia Papagiannaki
        account = account or self.account
508 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
509 615e561b Sofia Papagiannaki
        return self._update_metadata(path, 'object', **meta)
510 f7ab99df Sofia Papagiannaki
    
511 95e92490 Sofia Papagiannaki
    def delete_object_metadata(self, container, object, meta=[], account=None):
512 e7b51248 Sofia Papagiannaki
        """
513 e7b51248 Sofia Papagiannaki
        deletes object's metadata
514 e7b51248 Sofia Papagiannaki
        """
515 95e92490 Sofia Papagiannaki
        account = account or self.account
516 95e92490 Sofia Papagiannaki
        path = '/%s/%s' % (account, container, object)
517 615e561b Sofia Papagiannaki
        return self._delete_metadata(path, 'object', meta)
518 f7ab99df Sofia Papagiannaki
    
519 25c3841c Sofia Papagiannaki
class Pithos_Client(OOS_Client):
520 25c3841c Sofia Papagiannaki
    """Pithos Storage Client. Extends OOS_Client"""
521 25c3841c Sofia Papagiannaki
    
522 25c3841c Sofia Papagiannaki
    def _update_metadata(self, path, entity, **meta):
523 25c3841c Sofia Papagiannaki
        """
524 25c3841c Sofia Papagiannaki
        adds new and updates the values of previously set metadata
525 25c3841c Sofia Papagiannaki
        """
526 25c3841c Sofia Papagiannaki
        params = {'update':None}
527 25c3841c Sofia Papagiannaki
        headers = {}
528 25c3841c Sofia Papagiannaki
        prefix = 'x-%s-meta-' % entity
529 25c3841c Sofia Papagiannaki
        for k,v in meta.items():
530 25c3841c Sofia Papagiannaki
            k = '%s%s' % (prefix, k)
531 25c3841c Sofia Papagiannaki
            headers[k] = v
532 25c3841c Sofia Papagiannaki
        return self.post(path, headers=headers, params=params)
533 25c3841c Sofia Papagiannaki
    
534 25c3841c Sofia Papagiannaki
    def _delete_metadata(self, path, entity, meta=[]):
535 f7ab99df Sofia Papagiannaki
        """
536 25c3841c Sofia Papagiannaki
        delete previously set metadata
537 f7ab99df Sofia Papagiannaki
        """
538 25c3841c Sofia Papagiannaki
        params = {'update':None}
539 25c3841c Sofia Papagiannaki
        headers = {}
540 25c3841c Sofia Papagiannaki
        prefix = 'x-%s-meta-' % entity
541 25c3841c Sofia Papagiannaki
        for m in meta:
542 f0eacc2c Sofia Papagiannaki
            headers['%s%s' % (prefix, m)] = ''
543 25c3841c Sofia Papagiannaki
        return self.post(path, headers=headers, params=params)
544 25c3841c Sofia Papagiannaki
    
545 25c3841c Sofia Papagiannaki
    # Storage Account Services
546 25c3841c Sofia Papagiannaki
    
547 f0eacc2c Sofia Papagiannaki
    def list_containers(self, format='text', if_modified_since=None,
548 3bceebbe Sofia Papagiannaki
                        if_unmodified_since=None, limit=None, marker=None,
549 8d964102 Sofia Papagiannaki
                        shared=False, until=None, account=None):
550 25c3841c Sofia Papagiannaki
        """returns a list with the account containers"""
551 95e92490 Sofia Papagiannaki
        account = account or self.account
552 ae75584f Sofia Papagiannaki
        params = {'until':until} if until else {}
553 8d964102 Sofia Papagiannaki
        if shared:
554 8d964102 Sofia Papagiannaki
            params['shared'] = None
555 25c3841c Sofia Papagiannaki
        headers = {'if-modified-since':if_modified_since,
556 25c3841c Sofia Papagiannaki
                   'if-unmodified-since':if_unmodified_since}
557 95e92490 Sofia Papagiannaki
        return OOS_Client.list_containers(self, account=account, format=format,
558 95e92490 Sofia Papagiannaki
                                          limit=limit, marker=marker,
559 95e92490 Sofia Papagiannaki
                                          params=params, **headers)
560 25c3841c Sofia Papagiannaki
    
561 95e92490 Sofia Papagiannaki
    def retrieve_account_metadata(self, restricted=False, until=None,
562 95e92490 Sofia Papagiannaki
                                  account=None):
563 25c3841c Sofia Papagiannaki
        """returns the account metadata"""
564 95e92490 Sofia Papagiannaki
        account = account or self.account
565 25c3841c Sofia Papagiannaki
        params = {'until':until} if until else {}
566 95e92490 Sofia Papagiannaki
        return OOS_Client.retrieve_account_metadata(self, account=account,
567 95e92490 Sofia Papagiannaki
                                                    restricted=restricted,
568 95e92490 Sofia Papagiannaki
                                                    **params)
569 25c3841c Sofia Papagiannaki
    
570 95e92490 Sofia Papagiannaki
    def set_account_groups(self, account=None, **groups):
571 25c3841c Sofia Papagiannaki
        """create account groups"""
572 95e92490 Sofia Papagiannaki
        account = account or self.account
573 95e92490 Sofia Papagiannaki
        path = '/%s' % account
574 25c3841c Sofia Papagiannaki
        headers = {}
575 ae75584f Sofia Papagiannaki
        for k, v in groups.items():
576 ae75584f Sofia Papagiannaki
            headers['x-account-group-%s' % k] = v
577 25c3841c Sofia Papagiannaki
        params = {'update':None}
578 95e92490 Sofia Papagiannaki
        return self.post(path, headers=headers, params=params)
579 25c3841c Sofia Papagiannaki
    
580 95e92490 Sofia Papagiannaki
    def retrieve_account_groups(self, account=None):
581 b9ca81a0 Sofia Papagiannaki
        """returns the account groups"""
582 95e92490 Sofia Papagiannaki
        account = account or self.account
583 95e92490 Sofia Papagiannaki
        meta = self.retrieve_account_metadata(account=account)
584 b9ca81a0 Sofia Papagiannaki
        prefix = 'x-account-group-'
585 b9ca81a0 Sofia Papagiannaki
        prefixlen = len(prefix)
586 b9ca81a0 Sofia Papagiannaki
        groups = {}
587 b9ca81a0 Sofia Papagiannaki
        for key, val in meta.items():
588 b9ca81a0 Sofia Papagiannaki
            if prefix and not key.startswith(prefix):
589 b9ca81a0 Sofia Papagiannaki
                continue
590 b9ca81a0 Sofia Papagiannaki
            elif prefix and key.startswith(prefix):
591 b9ca81a0 Sofia Papagiannaki
                key = key[prefixlen:]
592 b9ca81a0 Sofia Papagiannaki
            groups[key] = val
593 b9ca81a0 Sofia Papagiannaki
        return groups
594 b9ca81a0 Sofia Papagiannaki
    
595 95e92490 Sofia Papagiannaki
    def unset_account_groups(self, groups=[], account=None):
596 25c3841c Sofia Papagiannaki
        """delete account groups"""
597 95e92490 Sofia Papagiannaki
        account = account or self.account
598 95e92490 Sofia Papagiannaki
        path = '/%s' % account
599 25c3841c Sofia Papagiannaki
        headers = {}
600 25c3841c Sofia Papagiannaki
        for elem in groups:
601 25c3841c Sofia Papagiannaki
            headers['x-account-group-%s' % elem] = ''
602 25c3841c Sofia Papagiannaki
        params = {'update':None}
603 95e92490 Sofia Papagiannaki
        return self.post(path, headers=headers, params=params)
604 25c3841c Sofia Papagiannaki
    
605 95e92490 Sofia Papagiannaki
    def reset_account_groups(self, account=None, **groups):
606 cd6ada1d Sofia Papagiannaki
        """overrides account groups"""
607 95e92490 Sofia Papagiannaki
        account = account or self.account
608 95e92490 Sofia Papagiannaki
        path = '/%s' % account
609 cd6ada1d Sofia Papagiannaki
        headers = {}
610 ae75584f Sofia Papagiannaki
        for k, v in groups.items():
611 ae75584f Sofia Papagiannaki
            v = v.strip()
612 ae75584f Sofia Papagiannaki
            headers['x-account-group-%s' % k] = v
613 e7b51248 Sofia Papagiannaki
        meta = self.retrieve_account_metadata(restricted=True)
614 e7b51248 Sofia Papagiannaki
        prefix = 'x-account-meta-'
615 e7b51248 Sofia Papagiannaki
        for k,v in meta.items():
616 e7b51248 Sofia Papagiannaki
            k = '%s%s' % (prefix, k)
617 e7b51248 Sofia Papagiannaki
            headers[k] = v
618 95e92490 Sofia Papagiannaki
        return self.post(path, headers=headers)
619 cd6ada1d Sofia Papagiannaki
    
620 25c3841c Sofia Papagiannaki
    # Storage Container Services
621 25c3841c Sofia Papagiannaki
    
622 95e92490 Sofia Papagiannaki
    def list_objects(self, container, format='text',
623 95e92490 Sofia Papagiannaki
                     limit=None, marker=None, prefix=None, delimiter=None,
624 8d964102 Sofia Papagiannaki
                     path=None, shared=False, include_trashed=False, params={},
625 95e92490 Sofia Papagiannaki
                     if_modified_since=None, if_unmodified_since=None, meta='',
626 95e92490 Sofia Papagiannaki
                     until=None, account=None):
627 25c3841c Sofia Papagiannaki
        """returns a list with the container objects"""
628 95e92490 Sofia Papagiannaki
        account = account or self.account
629 25c3841c Sofia Papagiannaki
        params = {'until':until, 'meta':meta}
630 8d964102 Sofia Papagiannaki
        if shared:
631 8d964102 Sofia Papagiannaki
            params['shared'] = None
632 9471fece Sofia Papagiannaki
        args = locals().copy()
633 25c3841c Sofia Papagiannaki
        for elem in ['self', 'container', 'params', 'until', 'meta']:
634 25c3841c Sofia Papagiannaki
            args.pop(elem)
635 95e92490 Sofia Papagiannaki
        return OOS_Client.list_objects(self, container, params=params, **args)
636 25c3841c Sofia Papagiannaki
    
637 25c3841c Sofia Papagiannaki
    def retrieve_container_metadata(self, container, restricted=False,
638 95e92490 Sofia Papagiannaki
                                    until=None, account=None):
639 25c3841c Sofia Papagiannaki
        """returns container's metadata"""
640 95e92490 Sofia Papagiannaki
        account = account or self.account
641 25c3841c Sofia Papagiannaki
        params = {'until':until} if until else {}
642 25c3841c Sofia Papagiannaki
        return OOS_Client.retrieve_container_metadata(self, container,
643 95e92490 Sofia Papagiannaki
                                                      account=account,
644 25c3841c Sofia Papagiannaki
                                                      restricted=restricted,
645 25c3841c Sofia Papagiannaki
                                                      **params)
646 25c3841c Sofia Papagiannaki
    
647 95e92490 Sofia Papagiannaki
    def set_container_policies(self, container, account=None,
648 95e92490 Sofia Papagiannaki
                               **policies):
649 25c3841c Sofia Papagiannaki
        """sets containers policies"""
650 95e92490 Sofia Papagiannaki
        account = account or self.account
651 95e92490 Sofia Papagiannaki
        path = '/%s/%s' % (account, container)
652 25c3841c Sofia Papagiannaki
        headers = {}
653 25c3841c Sofia Papagiannaki
        for key, val in policies.items():
654 25c3841c Sofia Papagiannaki
            headers['x-container-policy-%s' % key] = val
655 25c3841c Sofia Papagiannaki
        return self.post(path, headers=headers)
656 25c3841c Sofia Papagiannaki
    
657 6d897a63 Antony Chazapis
    def update_container_data(self, container, f=stdin):
658 6d897a63 Antony Chazapis
        """adds blocks of data to the container"""
659 6d897a63 Antony Chazapis
        account = self.account
660 6d897a63 Antony Chazapis
        path = '/%s/%s' % (account, container)
661 6d897a63 Antony Chazapis
        params = {'update': None}
662 6d897a63 Antony Chazapis
        headers = {'content_type': 'application/octet-stream'}
663 6d897a63 Antony Chazapis
        data = f.read() if f else None
664 6d897a63 Antony Chazapis
        headers['content_length'] = len(data)
665 6d897a63 Antony Chazapis
        return self.post(path, data, headers=headers, params=params)
666 6d897a63 Antony Chazapis
    
667 95e92490 Sofia Papagiannaki
    def delete_container(self, container, until=None, account=None):
668 25c3841c Sofia Papagiannaki
        """deletes a container or the container history until the date provided"""
669 95e92490 Sofia Papagiannaki
        account = account or self.account
670 25c3841c Sofia Papagiannaki
        params = {'until':until} if until else {}
671 95e92490 Sofia Papagiannaki
        return OOS_Client.delete_container(self, container, account=account,
672 95e92490 Sofia Papagiannaki
                                           params=params)
673 25c3841c Sofia Papagiannaki
    
674 25c3841c Sofia Papagiannaki
    # Storage Object Services
675 25c3841c Sofia Papagiannaki
    
676 95e92490 Sofia Papagiannaki
    def retrieve_object(self, container, object, params={}, format='text',
677 95e92490 Sofia Papagiannaki
                        range=None, if_range=None,
678 95e92490 Sofia Papagiannaki
                        if_match=None, if_none_match=None,
679 25c3841c Sofia Papagiannaki
                        if_modified_since=None, if_unmodified_since=None,
680 95e92490 Sofia Papagiannaki
                        account=None, **headers):
681 25c3841c Sofia Papagiannaki
        """returns an object"""
682 95e92490 Sofia Papagiannaki
        account = account or self.account
683 25c3841c Sofia Papagiannaki
        headers={}
684 25c3841c Sofia Papagiannaki
        l = ['range', 'if_range', 'if_match', 'if_none_match',
685 25c3841c Sofia Papagiannaki
             'if_modified_since', 'if_unmodified_since']
686 25c3841c Sofia Papagiannaki
        l = [elem for elem in l if eval(elem)]
687 25c3841c Sofia Papagiannaki
        for elem in l:
688 25c3841c Sofia Papagiannaki
            headers.update({elem:eval(elem)})
689 9471fece Sofia Papagiannaki
        if format != 'text':
690 9471fece Sofia Papagiannaki
            params['hashmap'] = None
691 95e92490 Sofia Papagiannaki
        return OOS_Client.retrieve_object(self, container, object,
692 95e92490 Sofia Papagiannaki
                                          account=account, format=format,
693 25c3841c Sofia Papagiannaki
                                          params=params, **headers)
694 25c3841c Sofia Papagiannaki
    
695 95e92490 Sofia Papagiannaki
    def retrieve_object_version(self, container, object, version,
696 7f769d34 Sofia Papagiannaki
                                format='text', range=None, if_range=None,
697 95e92490 Sofia Papagiannaki
                                if_match=None, if_none_match=None,
698 95e92490 Sofia Papagiannaki
                                if_modified_since=None, if_unmodified_since=None,
699 95e92490 Sofia Papagiannaki
                                account=None):
700 25c3841c Sofia Papagiannaki
        """returns a specific object version"""
701 95e92490 Sofia Papagiannaki
        account = account or self.account
702 9471fece Sofia Papagiannaki
        args = locals().copy()
703 25c3841c Sofia Papagiannaki
        l = ['self', 'container', 'object']
704 25c3841c Sofia Papagiannaki
        for elem in l:
705 25c3841c Sofia Papagiannaki
            args.pop(elem)
706 25c3841c Sofia Papagiannaki
        params = {'version':version}
707 95e92490 Sofia Papagiannaki
        return self.retrieve_object(container, object, params=params, **args)
708 25c3841c Sofia Papagiannaki
    
709 25c3841c Sofia Papagiannaki
    def retrieve_object_versionlist(self, container, object, range=None,
710 25c3841c Sofia Papagiannaki
                                    if_range=None, if_match=None,
711 25c3841c Sofia Papagiannaki
                                    if_none_match=None, if_modified_since=None,
712 95e92490 Sofia Papagiannaki
                                    if_unmodified_since=None, account=None):
713 25c3841c Sofia Papagiannaki
        """returns the object version list"""
714 95e92490 Sofia Papagiannaki
        account = account or self.account
715 9471fece Sofia Papagiannaki
        args = locals().copy()
716 25c3841c Sofia Papagiannaki
        l = ['self', 'container', 'object']
717 25c3841c Sofia Papagiannaki
        for elem in l:
718 25c3841c Sofia Papagiannaki
            args.pop(elem)
719 8d964102 Sofia Papagiannaki
        
720 25c3841c Sofia Papagiannaki
        return self.retrieve_object_version(container, object, version='list',
721 7f769d34 Sofia Papagiannaki
                                            format='json', **args)
722 25c3841c Sofia Papagiannaki
    
723 95e92490 Sofia Papagiannaki
    def create_zero_length_object(self, container, object,
724 95e92490 Sofia Papagiannaki
                                  meta={}, etag=None, content_type=None,
725 95e92490 Sofia Papagiannaki
                                  content_encoding=None,
726 95e92490 Sofia Papagiannaki
                                  content_disposition=None,
727 95e92490 Sofia Papagiannaki
                                  x_object_manifest=None, x_object_sharing=None,
728 95e92490 Sofia Papagiannaki
                                  x_object_public=None, account=None):
729 cd6ada1d Sofia Papagiannaki
        """createas a zero length object"""
730 95e92490 Sofia Papagiannaki
        account = account or self.account
731 9471fece Sofia Papagiannaki
        args = locals().copy()
732 cd6ada1d Sofia Papagiannaki
        for elem in ['self', 'container', 'object']:
733 cd6ada1d Sofia Papagiannaki
            args.pop(elem)
734 cd6ada1d Sofia Papagiannaki
        return OOS_Client.create_zero_length_object(self, container, object,
735 cd6ada1d Sofia Papagiannaki
                                                    **args)
736 cd6ada1d Sofia Papagiannaki
    
737 9471fece Sofia Papagiannaki
    def create_object(self, container, object, f=stdin, format='text',
738 9471fece Sofia Papagiannaki
                      meta={}, params={}, etag=None, content_type=None,
739 95e92490 Sofia Papagiannaki
                      content_encoding=None, content_disposition=None,
740 95e92490 Sofia Papagiannaki
                      x_object_manifest=None, x_object_sharing=None,
741 95e92490 Sofia Papagiannaki
                      x_object_public=None, account=None):
742 25c3841c Sofia Papagiannaki
        """creates an object"""
743 95e92490 Sofia Papagiannaki
        account = account or self.account
744 9471fece Sofia Papagiannaki
        args = locals().copy()
745 25c3841c Sofia Papagiannaki
        for elem in ['self', 'container', 'object']:
746 25c3841c Sofia Papagiannaki
            args.pop(elem)
747 e871c3b1 Sofia Papagiannaki
        if format != 'text':
748 e871c3b1 Sofia Papagiannaki
            params.update({'hashmap':None})
749 25c3841c Sofia Papagiannaki
        return OOS_Client.create_object(self, container, object, **args)
750 25c3841c Sofia Papagiannaki
        
751 95e92490 Sofia Papagiannaki
    def create_object_using_chunks(self, container, object,
752 95e92490 Sofia Papagiannaki
                                   f=stdin, blocksize=1024, meta={}, etag=None,
753 95e92490 Sofia Papagiannaki
                                   content_type=None, content_encoding=None,
754 95e92490 Sofia Papagiannaki
                                   content_disposition=None,
755 95e92490 Sofia Papagiannaki
                                   x_object_sharing=None, x_object_manifest=None,
756 95e92490 Sofia Papagiannaki
                                   x_object_public=None, account=None):
757 25c3841c Sofia Papagiannaki
        """creates an object (incremental upload)"""
758 95e92490 Sofia Papagiannaki
        account = account or self.account
759 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
760 25c3841c Sofia Papagiannaki
        headers = {}
761 25c3841c Sofia Papagiannaki
        l = ['etag', 'content_type', 'content_encoding', 'content_disposition', 
762 25c3841c Sofia Papagiannaki
             'x_object_sharing', 'x_object_manifest', 'x_object_public']
763 25c3841c Sofia Papagiannaki
        l = [elem for elem in l if eval(elem)]
764 25c3841c Sofia Papagiannaki
        for elem in l:
765 25c3841c Sofia Papagiannaki
            headers.update({elem:eval(elem)})
766 bcd29125 Sofia Papagiannaki
        headers.setdefault('content-type', 'application/octet-stream')
767 25c3841c Sofia Papagiannaki
        
768 25c3841c Sofia Papagiannaki
        for k,v in meta.items():
769 ae75584f Sofia Papagiannaki
            v = v.strip()
770 ae75584f Sofia Papagiannaki
            headers['x-object-meta-%s' %k.strip()] = v
771 25c3841c Sofia Papagiannaki
        
772 25c3841c Sofia Papagiannaki
        return self._chunked_transfer(path, 'PUT', f, headers=headers,
773 25c3841c Sofia Papagiannaki
                                      blocksize=blocksize)
774 25c3841c Sofia Papagiannaki
    
775 9471fece Sofia Papagiannaki
    def create_object_by_hashmap(self, container, object, hashmap={},
776 25c3841c Sofia Papagiannaki
                                 meta={}, etag=None, content_encoding=None,
777 25c3841c Sofia Papagiannaki
                                 content_disposition=None, content_type=None,
778 25c3841c Sofia Papagiannaki
                                 x_object_sharing=None, x_object_manifest=None,
779 95e92490 Sofia Papagiannaki
                                 x_object_public = None, account=None):
780 25c3841c Sofia Papagiannaki
        """creates an object by uploading hashes representing data instead of data"""
781 95e92490 Sofia Papagiannaki
        account = account or self.account
782 9471fece Sofia Papagiannaki
        args = locals().copy()
783 9471fece Sofia Papagiannaki
        for elem in ['self', 'container', 'object', 'hashmap']:
784 25c3841c Sofia Papagiannaki
            args.pop(elem)
785 25c3841c Sofia Papagiannaki
            
786 9471fece Sofia Papagiannaki
        try:
787 9471fece Sofia Papagiannaki
            data = json.dumps(hashmap)
788 9471fece Sofia Papagiannaki
        except SyntaxError:
789 9471fece Sofia Papagiannaki
            raise Fault('Invalid formatting')
790 9471fece Sofia Papagiannaki
        args['params'] = {'hashmap':None}
791 9471fece Sofia Papagiannaki
        args['format'] = 'json'
792 25c3841c Sofia Papagiannaki
        
793 9471fece Sofia Papagiannaki
        return self.create_object(container, object, f=StringIO(data), **args)
794 25c3841c Sofia Papagiannaki
    
795 95e92490 Sofia Papagiannaki
    def create_manifestation(self, container, object, manifest, account=None):
796 25c3841c Sofia Papagiannaki
        """creates a manifestation"""
797 95e92490 Sofia Papagiannaki
        account = account or self.account
798 25c3841c Sofia Papagiannaki
        headers={'x_object_manifest':manifest}
799 95e92490 Sofia Papagiannaki
        return self.create_object(container, object, f=None, account=account,
800 95e92490 Sofia Papagiannaki
                                  **headers)
801 25c3841c Sofia Papagiannaki
    
802 95e92490 Sofia Papagiannaki
    def update_object(self, container, object, f=stdin,
803 633bbb9f Sofia Papagiannaki
                      offset=None, meta={}, replace=False, content_length=None,
804 95e92490 Sofia Papagiannaki
                      content_type=None, content_range=None,
805 25c3841c Sofia Papagiannaki
                      content_encoding=None, content_disposition=None,
806 25c3841c Sofia Papagiannaki
                      x_object_bytes=None, x_object_manifest=None,
807 a5149fd0 Sofia Papagiannaki
                      x_object_sharing=None, x_object_public=None,
808 a5149fd0 Sofia Papagiannaki
                      x_source_object=None, account=None):
809 25c3841c Sofia Papagiannaki
        """updates an object"""
810 95e92490 Sofia Papagiannaki
        account = account or self.account
811 9471fece Sofia Papagiannaki
        args = locals().copy()
812 633bbb9f Sofia Papagiannaki
        for elem in ['self', 'container', 'object', 'replace']:
813 25c3841c Sofia Papagiannaki
            args.pop(elem)
814 633bbb9f Sofia Papagiannaki
        if not replace:
815 633bbb9f Sofia Papagiannaki
            args['params'] = {'update':None}
816 25c3841c Sofia Papagiannaki
        return OOS_Client.update_object(self, container, object, **args)
817 633bbb9f Sofia Papagiannaki
    
818 25c3841c Sofia Papagiannaki
    def update_object_using_chunks(self, container, object, f=stdin,
819 95e92490 Sofia Papagiannaki
                                   blocksize=1024, offset=None, meta={},
820 633bbb9f Sofia Papagiannaki
                                   replace=False, content_type=None, content_encoding=None,
821 95e92490 Sofia Papagiannaki
                                   content_disposition=None, x_object_bytes=None,
822 95e92490 Sofia Papagiannaki
                                   x_object_manifest=None, x_object_sharing=None,
823 95e92490 Sofia Papagiannaki
                                   x_object_public=None, account=None):
824 25c3841c Sofia Papagiannaki
        """updates an object (incremental upload)"""
825 95e92490 Sofia Papagiannaki
        account = account or self.account
826 9471fece Sofia Papagiannaki
        args = locals().copy()
827 633bbb9f Sofia Papagiannaki
        for elem in ['self', 'container', 'object', 'replace']:
828 633bbb9f Sofia Papagiannaki
            args.pop(elem)
829 633bbb9f Sofia Papagiannaki
        if not replace:
830 633bbb9f Sofia Papagiannaki
            args['params'] = {'update':None}
831 633bbb9f Sofia Papagiannaki
        return OOS_Client.update_object_using_chunks(self, container, object, **args)
832 25c3841c Sofia Papagiannaki
    
833 a5149fd0 Sofia Papagiannaki
    def update_from_other_source(self, container, object, source,
834 a5149fd0 Sofia Papagiannaki
                      offset=None, meta={}, content_range=None,
835 a5149fd0 Sofia Papagiannaki
                      content_encoding=None, content_disposition=None,
836 a5149fd0 Sofia Papagiannaki
                      x_object_bytes=None, x_object_manifest=None,
837 a5149fd0 Sofia Papagiannaki
                      x_object_sharing=None, x_object_public=None, account=None):
838 a5149fd0 Sofia Papagiannaki
        """updates an object"""
839 a5149fd0 Sofia Papagiannaki
        account = account or self.account
840 9471fece Sofia Papagiannaki
        args = locals().copy()
841 a5149fd0 Sofia Papagiannaki
        for elem in ['self', 'container', 'object', 'source']:
842 a5149fd0 Sofia Papagiannaki
            args.pop(elem)
843 a5149fd0 Sofia Papagiannaki
        
844 a5149fd0 Sofia Papagiannaki
        args['x_source_object'] = source
845 a5149fd0 Sofia Papagiannaki
        return self.update_object(container, object, f=None, **args)
846 a5149fd0 Sofia Papagiannaki
    
847 95e92490 Sofia Papagiannaki
    def delete_object(self, container, object, until=None, account=None):
848 25c3841c Sofia Papagiannaki
        """deletes an object or the object history until the date provided"""
849 95e92490 Sofia Papagiannaki
        account = account or self.account
850 25c3841c Sofia Papagiannaki
        params = {'until':until} if until else {}
851 95e92490 Sofia Papagiannaki
        return OOS_Client.delete_object(self, container, object, params, account)
852 25c3841c Sofia Papagiannaki
    
853 25c3841c Sofia Papagiannaki
    def trash_object(self, container, object):
854 25c3841c Sofia Papagiannaki
        """trashes an object"""
855 95e92490 Sofia Papagiannaki
        account = account or self.account
856 f7ab99df Sofia Papagiannaki
        path = '/%s/%s' % (container, object)
857 f7ab99df Sofia Papagiannaki
        meta = {'trash':'true'}
858 615e561b Sofia Papagiannaki
        return self._update_metadata(path, 'object', **meta)
859 f7ab99df Sofia Papagiannaki
    
860 95e92490 Sofia Papagiannaki
    def restore_object(self, container, object, account=None):
861 25c3841c Sofia Papagiannaki
        """restores a trashed object"""
862 95e92490 Sofia Papagiannaki
        account = account or self.account
863 95e92490 Sofia Papagiannaki
        return self.delete_object_metadata(container, object, account, ['trash'])
864 f89e3cf4 Sofia Papagiannaki
    
865 95e92490 Sofia Papagiannaki
    def publish_object(self, container, object, account=None):
866 25c3841c Sofia Papagiannaki
        """sets a previously created object publicly accessible"""
867 95e92490 Sofia Papagiannaki
        account = account or self.account
868 35d50a81 Antony Chazapis
        path = '/%s/%s/%s' % (account, container, object)
869 88e015a3 Antony Chazapis
        headers = {}
870 7812e1f9 Sofia Papagiannaki
        headers['x_object_public'] = True
871 88e015a3 Antony Chazapis
        params = {'update':None}
872 88e015a3 Antony Chazapis
        return self.post(path, headers=headers, params=params)
873 f89e3cf4 Sofia Papagiannaki
    
874 95e92490 Sofia Papagiannaki
    def unpublish_object(self, container, object, account=None):
875 25c3841c Sofia Papagiannaki
        """unpublish an object"""
876 95e92490 Sofia Papagiannaki
        account = account or self.account
877 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
878 88e015a3 Antony Chazapis
        headers = {}
879 7812e1f9 Sofia Papagiannaki
        headers['x_object_public'] = False
880 88e015a3 Antony Chazapis
        params = {'update':None}
881 88e015a3 Antony Chazapis
        return self.post(path, headers=headers, params=params)
882 7812e1f9 Sofia Papagiannaki
    
883 7812e1f9 Sofia Papagiannaki
    def copy_object(self, src_container, src_object, dst_container, dst_object,
884 d4a63b9b Sofia Papagiannaki
                    meta={}, public=False, version=None, account=None,
885 d4a63b9b Sofia Papagiannaki
                    content_type=None):
886 7812e1f9 Sofia Papagiannaki
        """copies an object"""
887 95e92490 Sofia Papagiannaki
        account = account or self.account
888 7812e1f9 Sofia Papagiannaki
        headers = {}
889 7812e1f9 Sofia Papagiannaki
        headers['x_object_public'] = public
890 7812e1f9 Sofia Papagiannaki
        if version:
891 97d45f69 Antony Chazapis
            headers['x_source_version'] = version
892 7812e1f9 Sofia Papagiannaki
        return OOS_Client.copy_object(self, src_container, src_object,
893 7812e1f9 Sofia Papagiannaki
                                      dst_container, dst_object, meta=meta,
894 d4a63b9b Sofia Papagiannaki
                                      account=account, content_type=content_type,
895 d4a63b9b Sofia Papagiannaki
                                      **headers)
896 7812e1f9 Sofia Papagiannaki
    
897 7812e1f9 Sofia Papagiannaki
    def move_object(self, src_container, src_object, dst_container,
898 97d45f69 Antony Chazapis
                             dst_object, meta={}, public=False,
899 d4a63b9b Sofia Papagiannaki
                             account=None, content_type=None):
900 7812e1f9 Sofia Papagiannaki
        """moves an object"""
901 7812e1f9 Sofia Papagiannaki
        headers = {}
902 7812e1f9 Sofia Papagiannaki
        headers['x_object_public'] = public
903 7812e1f9 Sofia Papagiannaki
        return OOS_Client.move_object(self, src_container, src_object,
904 7812e1f9 Sofia Papagiannaki
                                      dst_container, dst_object, meta=meta,
905 d4a63b9b Sofia Papagiannaki
                                      account=account, content_type=content_type,
906 d4a63b9b Sofia Papagiannaki
                                      **headers)
907 ae75584f Sofia Papagiannaki
    
908 ae75584f Sofia Papagiannaki
    def list_shared_by_others(self, limit=None, marker=None, format='text'):
909 95e92490 Sofia Papagiannaki
        """lists other accounts that share objects to the user"""
910 95e92490 Sofia Papagiannaki
        l = ['limit', 'marker']
911 95e92490 Sofia Papagiannaki
        params = {}
912 95e92490 Sofia Papagiannaki
        for elem in [elem for elem in l if eval(elem)]:
913 95e92490 Sofia Papagiannaki
            params[elem] = eval(elem)
914 95e92490 Sofia Papagiannaki
        return self._list('', format, params)
915 ae75584f Sofia Papagiannaki
    
916 ae75584f Sofia Papagiannaki
    def share_object(self, container, object, l, read=True):
917 e7b51248 Sofia Papagiannaki
        """gives access(read by default) to an object to a user/group list"""
918 ae75584f Sofia Papagiannaki
        action = 'read' if read else 'write'
919 ae75584f Sofia Papagiannaki
        sharing = '%s=%s' % (action, ','.join(l))
920 ae75584f Sofia Papagiannaki
        self.update_object(container, object, f=None, x_object_sharing=sharing)
921 f1716de7 Sofia Papagiannaki
922 f1716de7 Sofia Papagiannaki
def _prepare_path(path, api, format='text', params={}):
923 f1716de7 Sofia Papagiannaki
    slash = '/' if api else ''
924 f1716de7 Sofia Papagiannaki
    full_path = '%s%s%s?format=%s' % (slash, api, quote(path), format)
925 f1716de7 Sofia Papagiannaki
    
926 f1716de7 Sofia Papagiannaki
    for k,v in params.items():
927 f1716de7 Sofia Papagiannaki
        value = quote(str(v)) if v else ''
928 f1716de7 Sofia Papagiannaki
        full_path = '%s&%s=%s' %(full_path, quote(k), value)
929 f1716de7 Sofia Papagiannaki
    return full_path
930 f1716de7 Sofia Papagiannaki
931 f1716de7 Sofia Papagiannaki
def _prepare_headers(headers):
932 f1716de7 Sofia Papagiannaki
    for k,v in headers.items():
933 f1716de7 Sofia Papagiannaki
        headers.pop(k)
934 f1716de7 Sofia Papagiannaki
        k = k.replace('_', '-')
935 f1716de7 Sofia Papagiannaki
        headers[quote(k)] = quote(v, safe='/=,:@ *"') if type(v) == types.StringType else v
936 f1716de7 Sofia Papagiannaki
    return headers
937 f1716de7 Sofia Papagiannaki
938 35c82779 Sofia Papagiannaki
def _handle_response(response, verbose=False, debug=False):
939 f1716de7 Sofia Papagiannaki
    headers = response.getheaders()
940 f1716de7 Sofia Papagiannaki
    headers = dict((unquote(h), unquote(v)) for h,v in headers)
941 f1716de7 Sofia Papagiannaki
    
942 f1716de7 Sofia Papagiannaki
    if verbose:
943 f1716de7 Sofia Papagiannaki
        print '%d %s' % (response.status, response.reason)
944 f1716de7 Sofia Papagiannaki
        for key, val in headers.items():
945 f1716de7 Sofia Papagiannaki
            print '%s: %s' % (key.capitalize(), val)
946 f1716de7 Sofia Papagiannaki
        print
947 f1716de7 Sofia Papagiannaki
    
948 f1716de7 Sofia Papagiannaki
    length = response.getheader('content-length', None)
949 f1716de7 Sofia Papagiannaki
    data = response.read(length)
950 f1716de7 Sofia Papagiannaki
    if debug:
951 f1716de7 Sofia Papagiannaki
        print data
952 f1716de7 Sofia Papagiannaki
        print
953 f1716de7 Sofia Papagiannaki
    
954 f1716de7 Sofia Papagiannaki
    if int(response.status) in ERROR_CODES.keys():
955 f1716de7 Sofia Papagiannaki
        raise Fault(data, int(response.status))
956 f1716de7 Sofia Papagiannaki
    
957 f1716de7 Sofia Papagiannaki
    #print '**',  response.status, headers, data, '\n'
958 35c82779 Sofia Papagiannaki
    return response.status, headers, data