Statistics
| Branch: | Tag: | Revision:

root / pithos / lib / client.py @ 2e662088

History | View | Annotate | Download (40.3 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 81ed48a5 Sofia Papagiannaki
               503:'Service Unavailable',
58 81ed48a5 Sofia Papagiannaki
               }
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 615e561b Sofia Papagiannaki
        for k, v in meta.items():
452 ae75584f Sofia Papagiannaki
            headers['x-object-meta-%s' % k] = v
453 ec1b8d3e Sofia Papagiannaki
        if remove:
454 615e561b Sofia Papagiannaki
            headers['x-move-from'] = '/%s/%s' % (src_container, src_object)
455 ec1b8d3e Sofia Papagiannaki
        else:
456 615e561b Sofia Papagiannaki
            headers['x-copy-from'] = '/%s/%s' % (src_container, src_object)
457 7812e1f9 Sofia Papagiannaki
        headers['content_length'] = 0
458 d4a63b9b Sofia Papagiannaki
        if content_type:
459 d4a63b9b Sofia Papagiannaki
            headers['content_type'] = content_type 
460 615e561b Sofia Papagiannaki
        return self.put(path, headers=headers)
461 f7ab99df Sofia Papagiannaki
    
462 7812e1f9 Sofia Papagiannaki
    def copy_object(self, src_container, src_object, dst_container, dst_object,
463 d4a63b9b Sofia Papagiannaki
                   meta={}, account=None, content_type=None, **headers):
464 7812e1f9 Sofia Papagiannaki
        """copies an object"""
465 95e92490 Sofia Papagiannaki
        account = account or self.account
466 615e561b Sofia Papagiannaki
        return self._change_obj_location(src_container, src_object,
467 95e92490 Sofia Papagiannaki
                                   dst_container, dst_object, account=account,
468 d4a63b9b Sofia Papagiannaki
                                   remove=False, meta=meta,
469 d4a63b9b Sofia Papagiannaki
                                   content_type=content_type, **headers)
470 f7ab99df Sofia Papagiannaki
    
471 ec1b8d3e Sofia Papagiannaki
    def move_object(self, src_container, src_object, dst_container,
472 95e92490 Sofia Papagiannaki
                             dst_object, meta={}, account=None,
473 d4a63b9b Sofia Papagiannaki
                             content_type=None, **headers):
474 7812e1f9 Sofia Papagiannaki
        """moves an object"""
475 95e92490 Sofia Papagiannaki
        account = account or self.account
476 615e561b Sofia Papagiannaki
        return self._change_obj_location(src_container, src_object,
477 95e92490 Sofia Papagiannaki
                                         dst_container, dst_object,
478 95e92490 Sofia Papagiannaki
                                         account=account, remove=True,
479 d4a63b9b Sofia Papagiannaki
                                         meta=meta, content_type=content_type,
480 d4a63b9b Sofia Papagiannaki
                                         **headers)
481 f7ab99df Sofia Papagiannaki
    
482 95e92490 Sofia Papagiannaki
    def delete_object(self, container, object, params={}, account=None):
483 7812e1f9 Sofia Papagiannaki
        """deletes an object"""
484 95e92490 Sofia Papagiannaki
        account = account or self.account
485 95e92490 Sofia Papagiannaki
        return self.delete('/%s/%s/%s' % (account, container, object),
486 95e92490 Sofia Papagiannaki
                           params=params)
487 f7ab99df Sofia Papagiannaki
    
488 8fe01d72 Sofia Papagiannaki
    def retrieve_object_metadata(self, container, object, restricted=False,
489 95e92490 Sofia Papagiannaki
                                 version=None, account=None):
490 615e561b Sofia Papagiannaki
        """
491 615e561b Sofia Papagiannaki
        set restricted to True to get only user defined metadata
492 615e561b Sofia Papagiannaki
        """
493 95e92490 Sofia Papagiannaki
        account = account or self.account
494 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
495 f7ab99df Sofia Papagiannaki
        prefix = 'x-object-meta-' if restricted else None
496 25c3841c Sofia Papagiannaki
        params = {'version':version} if version else {}
497 8fe01d72 Sofia Papagiannaki
        return self._get_metadata(path, prefix, params=params)
498 f7ab99df Sofia Papagiannaki
    
499 95e92490 Sofia Papagiannaki
    def update_object_metadata(self, container, object, account=None,
500 95e92490 Sofia Papagiannaki
                               **meta):
501 e7b51248 Sofia Papagiannaki
        """
502 e7b51248 Sofia Papagiannaki
        updates object's metadata
503 e7b51248 Sofia Papagiannaki
        """
504 95e92490 Sofia Papagiannaki
        account = account or self.account
505 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
506 615e561b Sofia Papagiannaki
        return self._update_metadata(path, 'object', **meta)
507 f7ab99df Sofia Papagiannaki
    
508 95e92490 Sofia Papagiannaki
    def delete_object_metadata(self, container, object, meta=[], account=None):
509 e7b51248 Sofia Papagiannaki
        """
510 e7b51248 Sofia Papagiannaki
        deletes object's metadata
511 e7b51248 Sofia Papagiannaki
        """
512 95e92490 Sofia Papagiannaki
        account = account or self.account
513 95e92490 Sofia Papagiannaki
        path = '/%s/%s' % (account, container, object)
514 615e561b Sofia Papagiannaki
        return self._delete_metadata(path, 'object', meta)
515 f7ab99df Sofia Papagiannaki
    
516 25c3841c Sofia Papagiannaki
class Pithos_Client(OOS_Client):
517 25c3841c Sofia Papagiannaki
    """Pithos Storage Client. Extends OOS_Client"""
518 25c3841c Sofia Papagiannaki
    
519 25c3841c Sofia Papagiannaki
    def _update_metadata(self, path, entity, **meta):
520 25c3841c Sofia Papagiannaki
        """
521 25c3841c Sofia Papagiannaki
        adds new and updates the values of previously set metadata
522 25c3841c Sofia Papagiannaki
        """
523 25c3841c Sofia Papagiannaki
        params = {'update':None}
524 25c3841c Sofia Papagiannaki
        headers = {}
525 25c3841c Sofia Papagiannaki
        prefix = 'x-%s-meta-' % entity
526 25c3841c Sofia Papagiannaki
        for k,v in meta.items():
527 25c3841c Sofia Papagiannaki
            k = '%s%s' % (prefix, k)
528 25c3841c Sofia Papagiannaki
            headers[k] = v
529 25c3841c Sofia Papagiannaki
        return self.post(path, headers=headers, params=params)
530 25c3841c Sofia Papagiannaki
    
531 25c3841c Sofia Papagiannaki
    def _delete_metadata(self, path, entity, meta=[]):
532 f7ab99df Sofia Papagiannaki
        """
533 25c3841c Sofia Papagiannaki
        delete previously set metadata
534 f7ab99df Sofia Papagiannaki
        """
535 25c3841c Sofia Papagiannaki
        params = {'update':None}
536 25c3841c Sofia Papagiannaki
        headers = {}
537 25c3841c Sofia Papagiannaki
        prefix = 'x-%s-meta-' % entity
538 25c3841c Sofia Papagiannaki
        for m in meta:
539 f0eacc2c Sofia Papagiannaki
            headers['%s%s' % (prefix, m)] = ''
540 25c3841c Sofia Papagiannaki
        return self.post(path, headers=headers, params=params)
541 25c3841c Sofia Papagiannaki
    
542 25c3841c Sofia Papagiannaki
    # Storage Account Services
543 25c3841c Sofia Papagiannaki
    
544 f0eacc2c Sofia Papagiannaki
    def list_containers(self, format='text', if_modified_since=None,
545 3bceebbe Sofia Papagiannaki
                        if_unmodified_since=None, limit=None, marker=None,
546 8d964102 Sofia Papagiannaki
                        shared=False, until=None, account=None):
547 25c3841c Sofia Papagiannaki
        """returns a list with the account containers"""
548 95e92490 Sofia Papagiannaki
        account = account or self.account
549 ae75584f Sofia Papagiannaki
        params = {'until':until} if until else {}
550 8d964102 Sofia Papagiannaki
        if shared:
551 8d964102 Sofia Papagiannaki
            params['shared'] = None
552 25c3841c Sofia Papagiannaki
        headers = {'if-modified-since':if_modified_since,
553 25c3841c Sofia Papagiannaki
                   'if-unmodified-since':if_unmodified_since}
554 95e92490 Sofia Papagiannaki
        return OOS_Client.list_containers(self, account=account, format=format,
555 95e92490 Sofia Papagiannaki
                                          limit=limit, marker=marker,
556 95e92490 Sofia Papagiannaki
                                          params=params, **headers)
557 25c3841c Sofia Papagiannaki
    
558 95e92490 Sofia Papagiannaki
    def retrieve_account_metadata(self, restricted=False, until=None,
559 95e92490 Sofia Papagiannaki
                                  account=None):
560 25c3841c Sofia Papagiannaki
        """returns the account metadata"""
561 95e92490 Sofia Papagiannaki
        account = account or self.account
562 25c3841c Sofia Papagiannaki
        params = {'until':until} if until else {}
563 95e92490 Sofia Papagiannaki
        return OOS_Client.retrieve_account_metadata(self, account=account,
564 95e92490 Sofia Papagiannaki
                                                    restricted=restricted,
565 95e92490 Sofia Papagiannaki
                                                    **params)
566 25c3841c Sofia Papagiannaki
    
567 95e92490 Sofia Papagiannaki
    def set_account_groups(self, account=None, **groups):
568 25c3841c Sofia Papagiannaki
        """create account groups"""
569 95e92490 Sofia Papagiannaki
        account = account or self.account
570 95e92490 Sofia Papagiannaki
        path = '/%s' % account
571 25c3841c Sofia Papagiannaki
        headers = {}
572 ae75584f Sofia Papagiannaki
        for k, v in groups.items():
573 ae75584f Sofia Papagiannaki
            headers['x-account-group-%s' % k] = v
574 25c3841c Sofia Papagiannaki
        params = {'update':None}
575 95e92490 Sofia Papagiannaki
        return self.post(path, headers=headers, params=params)
576 25c3841c Sofia Papagiannaki
    
577 95e92490 Sofia Papagiannaki
    def retrieve_account_groups(self, account=None):
578 b9ca81a0 Sofia Papagiannaki
        """returns the account groups"""
579 95e92490 Sofia Papagiannaki
        account = account or self.account
580 95e92490 Sofia Papagiannaki
        meta = self.retrieve_account_metadata(account=account)
581 b9ca81a0 Sofia Papagiannaki
        prefix = 'x-account-group-'
582 b9ca81a0 Sofia Papagiannaki
        prefixlen = len(prefix)
583 b9ca81a0 Sofia Papagiannaki
        groups = {}
584 b9ca81a0 Sofia Papagiannaki
        for key, val in meta.items():
585 b9ca81a0 Sofia Papagiannaki
            if prefix and not key.startswith(prefix):
586 b9ca81a0 Sofia Papagiannaki
                continue
587 b9ca81a0 Sofia Papagiannaki
            elif prefix and key.startswith(prefix):
588 b9ca81a0 Sofia Papagiannaki
                key = key[prefixlen:]
589 b9ca81a0 Sofia Papagiannaki
            groups[key] = val
590 b9ca81a0 Sofia Papagiannaki
        return groups
591 b9ca81a0 Sofia Papagiannaki
    
592 95e92490 Sofia Papagiannaki
    def unset_account_groups(self, groups=[], account=None):
593 25c3841c Sofia Papagiannaki
        """delete account groups"""
594 95e92490 Sofia Papagiannaki
        account = account or self.account
595 95e92490 Sofia Papagiannaki
        path = '/%s' % account
596 25c3841c Sofia Papagiannaki
        headers = {}
597 25c3841c Sofia Papagiannaki
        for elem in groups:
598 25c3841c Sofia Papagiannaki
            headers['x-account-group-%s' % elem] = ''
599 25c3841c Sofia Papagiannaki
        params = {'update':None}
600 95e92490 Sofia Papagiannaki
        return self.post(path, headers=headers, params=params)
601 25c3841c Sofia Papagiannaki
    
602 95e92490 Sofia Papagiannaki
    def reset_account_groups(self, account=None, **groups):
603 cd6ada1d Sofia Papagiannaki
        """overrides account groups"""
604 95e92490 Sofia Papagiannaki
        account = account or self.account
605 95e92490 Sofia Papagiannaki
        path = '/%s' % account
606 cd6ada1d Sofia Papagiannaki
        headers = {}
607 ae75584f Sofia Papagiannaki
        for k, v in groups.items():
608 ae75584f Sofia Papagiannaki
            v = v.strip()
609 ae75584f Sofia Papagiannaki
            headers['x-account-group-%s' % k] = v
610 e7b51248 Sofia Papagiannaki
        meta = self.retrieve_account_metadata(restricted=True)
611 e7b51248 Sofia Papagiannaki
        prefix = 'x-account-meta-'
612 e7b51248 Sofia Papagiannaki
        for k,v in meta.items():
613 e7b51248 Sofia Papagiannaki
            k = '%s%s' % (prefix, k)
614 e7b51248 Sofia Papagiannaki
            headers[k] = v
615 95e92490 Sofia Papagiannaki
        return self.post(path, headers=headers)
616 cd6ada1d Sofia Papagiannaki
    
617 25c3841c Sofia Papagiannaki
    # Storage Container Services
618 25c3841c Sofia Papagiannaki
    
619 95e92490 Sofia Papagiannaki
    def list_objects(self, container, format='text',
620 95e92490 Sofia Papagiannaki
                     limit=None, marker=None, prefix=None, delimiter=None,
621 8d964102 Sofia Papagiannaki
                     path=None, shared=False, include_trashed=False, params={},
622 95e92490 Sofia Papagiannaki
                     if_modified_since=None, if_unmodified_since=None, meta='',
623 95e92490 Sofia Papagiannaki
                     until=None, account=None):
624 25c3841c Sofia Papagiannaki
        """returns a list with the container objects"""
625 95e92490 Sofia Papagiannaki
        account = account or self.account
626 25c3841c Sofia Papagiannaki
        params = {'until':until, 'meta':meta}
627 8d964102 Sofia Papagiannaki
        if shared:
628 8d964102 Sofia Papagiannaki
            params['shared'] = None
629 9471fece Sofia Papagiannaki
        args = locals().copy()
630 25c3841c Sofia Papagiannaki
        for elem in ['self', 'container', 'params', 'until', 'meta']:
631 25c3841c Sofia Papagiannaki
            args.pop(elem)
632 95e92490 Sofia Papagiannaki
        return OOS_Client.list_objects(self, container, params=params, **args)
633 25c3841c Sofia Papagiannaki
    
634 25c3841c Sofia Papagiannaki
    def retrieve_container_metadata(self, container, restricted=False,
635 95e92490 Sofia Papagiannaki
                                    until=None, account=None):
636 25c3841c Sofia Papagiannaki
        """returns container's metadata"""
637 95e92490 Sofia Papagiannaki
        account = account or self.account
638 25c3841c Sofia Papagiannaki
        params = {'until':until} if until else {}
639 25c3841c Sofia Papagiannaki
        return OOS_Client.retrieve_container_metadata(self, container,
640 95e92490 Sofia Papagiannaki
                                                      account=account,
641 25c3841c Sofia Papagiannaki
                                                      restricted=restricted,
642 25c3841c Sofia Papagiannaki
                                                      **params)
643 25c3841c Sofia Papagiannaki
    
644 95e92490 Sofia Papagiannaki
    def set_container_policies(self, container, account=None,
645 95e92490 Sofia Papagiannaki
                               **policies):
646 25c3841c Sofia Papagiannaki
        """sets containers policies"""
647 95e92490 Sofia Papagiannaki
        account = account or self.account
648 95e92490 Sofia Papagiannaki
        path = '/%s/%s' % (account, container)
649 25c3841c Sofia Papagiannaki
        headers = {}
650 25c3841c Sofia Papagiannaki
        for key, val in policies.items():
651 25c3841c Sofia Papagiannaki
            headers['x-container-policy-%s' % key] = val
652 25c3841c Sofia Papagiannaki
        return self.post(path, headers=headers)
653 25c3841c Sofia Papagiannaki
    
654 6d897a63 Antony Chazapis
    def update_container_data(self, container, f=stdin):
655 6d897a63 Antony Chazapis
        """adds blocks of data to the container"""
656 6d897a63 Antony Chazapis
        account = self.account
657 6d897a63 Antony Chazapis
        path = '/%s/%s' % (account, container)
658 6d897a63 Antony Chazapis
        params = {'update': None}
659 6d897a63 Antony Chazapis
        headers = {'content_type': 'application/octet-stream'}
660 6d897a63 Antony Chazapis
        data = f.read() if f else None
661 6d897a63 Antony Chazapis
        headers['content_length'] = len(data)
662 6d897a63 Antony Chazapis
        return self.post(path, data, headers=headers, params=params)
663 6d897a63 Antony Chazapis
    
664 95e92490 Sofia Papagiannaki
    def delete_container(self, container, until=None, account=None):
665 25c3841c Sofia Papagiannaki
        """deletes a container or the container history until the date provided"""
666 95e92490 Sofia Papagiannaki
        account = account or self.account
667 25c3841c Sofia Papagiannaki
        params = {'until':until} if until else {}
668 95e92490 Sofia Papagiannaki
        return OOS_Client.delete_container(self, container, account=account,
669 95e92490 Sofia Papagiannaki
                                           params=params)
670 25c3841c Sofia Papagiannaki
    
671 25c3841c Sofia Papagiannaki
    # Storage Object Services
672 25c3841c Sofia Papagiannaki
    
673 95e92490 Sofia Papagiannaki
    def retrieve_object(self, container, object, params={}, format='text',
674 95e92490 Sofia Papagiannaki
                        range=None, if_range=None,
675 95e92490 Sofia Papagiannaki
                        if_match=None, if_none_match=None,
676 25c3841c Sofia Papagiannaki
                        if_modified_since=None, if_unmodified_since=None,
677 95e92490 Sofia Papagiannaki
                        account=None, **headers):
678 25c3841c Sofia Papagiannaki
        """returns an object"""
679 95e92490 Sofia Papagiannaki
        account = account or self.account
680 25c3841c Sofia Papagiannaki
        headers={}
681 25c3841c Sofia Papagiannaki
        l = ['range', 'if_range', 'if_match', 'if_none_match',
682 25c3841c Sofia Papagiannaki
             'if_modified_since', 'if_unmodified_since']
683 25c3841c Sofia Papagiannaki
        l = [elem for elem in l if eval(elem)]
684 25c3841c Sofia Papagiannaki
        for elem in l:
685 25c3841c Sofia Papagiannaki
            headers.update({elem:eval(elem)})
686 9471fece Sofia Papagiannaki
        if format != 'text':
687 9471fece Sofia Papagiannaki
            params['hashmap'] = None
688 95e92490 Sofia Papagiannaki
        return OOS_Client.retrieve_object(self, container, object,
689 95e92490 Sofia Papagiannaki
                                          account=account, format=format,
690 25c3841c Sofia Papagiannaki
                                          params=params, **headers)
691 25c3841c Sofia Papagiannaki
    
692 95e92490 Sofia Papagiannaki
    def retrieve_object_version(self, container, object, version,
693 7f769d34 Sofia Papagiannaki
                                format='text', range=None, if_range=None,
694 95e92490 Sofia Papagiannaki
                                if_match=None, if_none_match=None,
695 95e92490 Sofia Papagiannaki
                                if_modified_since=None, if_unmodified_since=None,
696 95e92490 Sofia Papagiannaki
                                account=None):
697 25c3841c Sofia Papagiannaki
        """returns a specific object version"""
698 95e92490 Sofia Papagiannaki
        account = account or self.account
699 9471fece Sofia Papagiannaki
        args = locals().copy()
700 25c3841c Sofia Papagiannaki
        l = ['self', 'container', 'object']
701 25c3841c Sofia Papagiannaki
        for elem in l:
702 25c3841c Sofia Papagiannaki
            args.pop(elem)
703 25c3841c Sofia Papagiannaki
        params = {'version':version}
704 95e92490 Sofia Papagiannaki
        return self.retrieve_object(container, object, params=params, **args)
705 25c3841c Sofia Papagiannaki
    
706 25c3841c Sofia Papagiannaki
    def retrieve_object_versionlist(self, container, object, range=None,
707 25c3841c Sofia Papagiannaki
                                    if_range=None, if_match=None,
708 25c3841c Sofia Papagiannaki
                                    if_none_match=None, if_modified_since=None,
709 95e92490 Sofia Papagiannaki
                                    if_unmodified_since=None, account=None):
710 25c3841c Sofia Papagiannaki
        """returns the object version list"""
711 95e92490 Sofia Papagiannaki
        account = account or self.account
712 9471fece Sofia Papagiannaki
        args = locals().copy()
713 25c3841c Sofia Papagiannaki
        l = ['self', 'container', 'object']
714 25c3841c Sofia Papagiannaki
        for elem in l:
715 25c3841c Sofia Papagiannaki
            args.pop(elem)
716 8d964102 Sofia Papagiannaki
        
717 25c3841c Sofia Papagiannaki
        return self.retrieve_object_version(container, object, version='list',
718 7f769d34 Sofia Papagiannaki
                                            format='json', **args)
719 25c3841c Sofia Papagiannaki
    
720 95e92490 Sofia Papagiannaki
    def create_zero_length_object(self, container, object,
721 95e92490 Sofia Papagiannaki
                                  meta={}, etag=None, content_type=None,
722 95e92490 Sofia Papagiannaki
                                  content_encoding=None,
723 95e92490 Sofia Papagiannaki
                                  content_disposition=None,
724 95e92490 Sofia Papagiannaki
                                  x_object_manifest=None, x_object_sharing=None,
725 95e92490 Sofia Papagiannaki
                                  x_object_public=None, account=None):
726 cd6ada1d Sofia Papagiannaki
        """createas a zero length object"""
727 95e92490 Sofia Papagiannaki
        account = account or self.account
728 9471fece Sofia Papagiannaki
        args = locals().copy()
729 cd6ada1d Sofia Papagiannaki
        for elem in ['self', 'container', 'object']:
730 cd6ada1d Sofia Papagiannaki
            args.pop(elem)
731 cd6ada1d Sofia Papagiannaki
        return OOS_Client.create_zero_length_object(self, container, object,
732 cd6ada1d Sofia Papagiannaki
                                                    **args)
733 cd6ada1d Sofia Papagiannaki
    
734 9471fece Sofia Papagiannaki
    def create_object(self, container, object, f=stdin, format='text',
735 9471fece Sofia Papagiannaki
                      meta={}, params={}, etag=None, content_type=None,
736 95e92490 Sofia Papagiannaki
                      content_encoding=None, content_disposition=None,
737 95e92490 Sofia Papagiannaki
                      x_object_manifest=None, x_object_sharing=None,
738 95e92490 Sofia Papagiannaki
                      x_object_public=None, account=None):
739 25c3841c Sofia Papagiannaki
        """creates an object"""
740 95e92490 Sofia Papagiannaki
        account = account or self.account
741 9471fece Sofia Papagiannaki
        args = locals().copy()
742 25c3841c Sofia Papagiannaki
        for elem in ['self', 'container', 'object']:
743 25c3841c Sofia Papagiannaki
            args.pop(elem)
744 e871c3b1 Sofia Papagiannaki
        if format != 'text':
745 e871c3b1 Sofia Papagiannaki
            params.update({'hashmap':None})
746 25c3841c Sofia Papagiannaki
        return OOS_Client.create_object(self, container, object, **args)
747 25c3841c Sofia Papagiannaki
        
748 95e92490 Sofia Papagiannaki
    def create_object_using_chunks(self, container, object,
749 95e92490 Sofia Papagiannaki
                                   f=stdin, blocksize=1024, meta={}, etag=None,
750 95e92490 Sofia Papagiannaki
                                   content_type=None, content_encoding=None,
751 95e92490 Sofia Papagiannaki
                                   content_disposition=None,
752 95e92490 Sofia Papagiannaki
                                   x_object_sharing=None, x_object_manifest=None,
753 95e92490 Sofia Papagiannaki
                                   x_object_public=None, account=None):
754 25c3841c Sofia Papagiannaki
        """creates an object (incremental upload)"""
755 95e92490 Sofia Papagiannaki
        account = account or self.account
756 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
757 25c3841c Sofia Papagiannaki
        headers = {}
758 25c3841c Sofia Papagiannaki
        l = ['etag', 'content_type', 'content_encoding', 'content_disposition', 
759 25c3841c Sofia Papagiannaki
             'x_object_sharing', 'x_object_manifest', 'x_object_public']
760 25c3841c Sofia Papagiannaki
        l = [elem for elem in l if eval(elem)]
761 25c3841c Sofia Papagiannaki
        for elem in l:
762 25c3841c Sofia Papagiannaki
            headers.update({elem:eval(elem)})
763 bcd29125 Sofia Papagiannaki
        headers.setdefault('content-type', 'application/octet-stream')
764 25c3841c Sofia Papagiannaki
        
765 25c3841c Sofia Papagiannaki
        for k,v in meta.items():
766 ae75584f Sofia Papagiannaki
            v = v.strip()
767 ae75584f Sofia Papagiannaki
            headers['x-object-meta-%s' %k.strip()] = v
768 25c3841c Sofia Papagiannaki
        
769 25c3841c Sofia Papagiannaki
        return self._chunked_transfer(path, 'PUT', f, headers=headers,
770 25c3841c Sofia Papagiannaki
                                      blocksize=blocksize)
771 25c3841c Sofia Papagiannaki
    
772 9471fece Sofia Papagiannaki
    def create_object_by_hashmap(self, container, object, hashmap={},
773 25c3841c Sofia Papagiannaki
                                 meta={}, etag=None, content_encoding=None,
774 25c3841c Sofia Papagiannaki
                                 content_disposition=None, content_type=None,
775 25c3841c Sofia Papagiannaki
                                 x_object_sharing=None, x_object_manifest=None,
776 95e92490 Sofia Papagiannaki
                                 x_object_public = None, account=None):
777 25c3841c Sofia Papagiannaki
        """creates an object by uploading hashes representing data instead of data"""
778 95e92490 Sofia Papagiannaki
        account = account or self.account
779 9471fece Sofia Papagiannaki
        args = locals().copy()
780 9471fece Sofia Papagiannaki
        for elem in ['self', 'container', 'object', 'hashmap']:
781 25c3841c Sofia Papagiannaki
            args.pop(elem)
782 25c3841c Sofia Papagiannaki
            
783 9471fece Sofia Papagiannaki
        try:
784 9471fece Sofia Papagiannaki
            data = json.dumps(hashmap)
785 9471fece Sofia Papagiannaki
        except SyntaxError:
786 9471fece Sofia Papagiannaki
            raise Fault('Invalid formatting')
787 9471fece Sofia Papagiannaki
        args['params'] = {'hashmap':None}
788 9471fece Sofia Papagiannaki
        args['format'] = 'json'
789 25c3841c Sofia Papagiannaki
        
790 9471fece Sofia Papagiannaki
        return self.create_object(container, object, f=StringIO(data), **args)
791 25c3841c Sofia Papagiannaki
    
792 95e92490 Sofia Papagiannaki
    def create_manifestation(self, container, object, manifest, account=None):
793 25c3841c Sofia Papagiannaki
        """creates a manifestation"""
794 95e92490 Sofia Papagiannaki
        account = account or self.account
795 25c3841c Sofia Papagiannaki
        headers={'x_object_manifest':manifest}
796 95e92490 Sofia Papagiannaki
        return self.create_object(container, object, f=None, account=account,
797 95e92490 Sofia Papagiannaki
                                  **headers)
798 25c3841c Sofia Papagiannaki
    
799 95e92490 Sofia Papagiannaki
    def update_object(self, container, object, f=stdin,
800 633bbb9f Sofia Papagiannaki
                      offset=None, meta={}, replace=False, content_length=None,
801 95e92490 Sofia Papagiannaki
                      content_type=None, content_range=None,
802 25c3841c Sofia Papagiannaki
                      content_encoding=None, content_disposition=None,
803 25c3841c Sofia Papagiannaki
                      x_object_bytes=None, x_object_manifest=None,
804 a5149fd0 Sofia Papagiannaki
                      x_object_sharing=None, x_object_public=None,
805 a5149fd0 Sofia Papagiannaki
                      x_source_object=None, account=None):
806 25c3841c Sofia Papagiannaki
        """updates an object"""
807 95e92490 Sofia Papagiannaki
        account = account or self.account
808 9471fece Sofia Papagiannaki
        args = locals().copy()
809 633bbb9f Sofia Papagiannaki
        for elem in ['self', 'container', 'object', 'replace']:
810 25c3841c Sofia Papagiannaki
            args.pop(elem)
811 633bbb9f Sofia Papagiannaki
        if not replace:
812 633bbb9f Sofia Papagiannaki
            args['params'] = {'update':None}
813 25c3841c Sofia Papagiannaki
        return OOS_Client.update_object(self, container, object, **args)
814 633bbb9f Sofia Papagiannaki
    
815 25c3841c Sofia Papagiannaki
    def update_object_using_chunks(self, container, object, f=stdin,
816 95e92490 Sofia Papagiannaki
                                   blocksize=1024, offset=None, meta={},
817 633bbb9f Sofia Papagiannaki
                                   replace=False, content_type=None, content_encoding=None,
818 95e92490 Sofia Papagiannaki
                                   content_disposition=None, x_object_bytes=None,
819 95e92490 Sofia Papagiannaki
                                   x_object_manifest=None, x_object_sharing=None,
820 95e92490 Sofia Papagiannaki
                                   x_object_public=None, account=None):
821 25c3841c Sofia Papagiannaki
        """updates an object (incremental upload)"""
822 95e92490 Sofia Papagiannaki
        account = account or self.account
823 9471fece Sofia Papagiannaki
        args = locals().copy()
824 633bbb9f Sofia Papagiannaki
        for elem in ['self', 'container', 'object', 'replace']:
825 633bbb9f Sofia Papagiannaki
            args.pop(elem)
826 633bbb9f Sofia Papagiannaki
        if not replace:
827 633bbb9f Sofia Papagiannaki
            args['params'] = {'update':None}
828 633bbb9f Sofia Papagiannaki
        return OOS_Client.update_object_using_chunks(self, container, object, **args)
829 25c3841c Sofia Papagiannaki
    
830 a5149fd0 Sofia Papagiannaki
    def update_from_other_source(self, container, object, source,
831 a5149fd0 Sofia Papagiannaki
                      offset=None, meta={}, content_range=None,
832 a5149fd0 Sofia Papagiannaki
                      content_encoding=None, content_disposition=None,
833 a5149fd0 Sofia Papagiannaki
                      x_object_bytes=None, x_object_manifest=None,
834 a5149fd0 Sofia Papagiannaki
                      x_object_sharing=None, x_object_public=None, account=None):
835 a5149fd0 Sofia Papagiannaki
        """updates an object"""
836 a5149fd0 Sofia Papagiannaki
        account = account or self.account
837 9471fece Sofia Papagiannaki
        args = locals().copy()
838 a5149fd0 Sofia Papagiannaki
        for elem in ['self', 'container', 'object', 'source']:
839 a5149fd0 Sofia Papagiannaki
            args.pop(elem)
840 a5149fd0 Sofia Papagiannaki
        
841 a5149fd0 Sofia Papagiannaki
        args['x_source_object'] = source
842 a5149fd0 Sofia Papagiannaki
        return self.update_object(container, object, f=None, **args)
843 a5149fd0 Sofia Papagiannaki
    
844 95e92490 Sofia Papagiannaki
    def delete_object(self, container, object, until=None, account=None):
845 25c3841c Sofia Papagiannaki
        """deletes an object or the object history until the date provided"""
846 95e92490 Sofia Papagiannaki
        account = account or self.account
847 25c3841c Sofia Papagiannaki
        params = {'until':until} if until else {}
848 95e92490 Sofia Papagiannaki
        return OOS_Client.delete_object(self, container, object, params, account)
849 25c3841c Sofia Papagiannaki
    
850 25c3841c Sofia Papagiannaki
    def trash_object(self, container, object):
851 25c3841c Sofia Papagiannaki
        """trashes an object"""
852 95e92490 Sofia Papagiannaki
        account = account or self.account
853 f7ab99df Sofia Papagiannaki
        path = '/%s/%s' % (container, object)
854 f7ab99df Sofia Papagiannaki
        meta = {'trash':'true'}
855 615e561b Sofia Papagiannaki
        return self._update_metadata(path, 'object', **meta)
856 f7ab99df Sofia Papagiannaki
    
857 95e92490 Sofia Papagiannaki
    def restore_object(self, container, object, account=None):
858 25c3841c Sofia Papagiannaki
        """restores a trashed object"""
859 95e92490 Sofia Papagiannaki
        account = account or self.account
860 95e92490 Sofia Papagiannaki
        return self.delete_object_metadata(container, object, account, ['trash'])
861 f89e3cf4 Sofia Papagiannaki
    
862 95e92490 Sofia Papagiannaki
    def publish_object(self, container, object, account=None):
863 25c3841c Sofia Papagiannaki
        """sets a previously created object publicly accessible"""
864 95e92490 Sofia Papagiannaki
        account = account or self.account
865 35d50a81 Antony Chazapis
        path = '/%s/%s/%s' % (account, container, object)
866 88e015a3 Antony Chazapis
        headers = {}
867 7812e1f9 Sofia Papagiannaki
        headers['x_object_public'] = True
868 88e015a3 Antony Chazapis
        params = {'update':None}
869 88e015a3 Antony Chazapis
        return self.post(path, headers=headers, params=params)
870 f89e3cf4 Sofia Papagiannaki
    
871 95e92490 Sofia Papagiannaki
    def unpublish_object(self, container, object, account=None):
872 25c3841c Sofia Papagiannaki
        """unpublish an object"""
873 95e92490 Sofia Papagiannaki
        account = account or self.account
874 95e92490 Sofia Papagiannaki
        path = '/%s/%s/%s' % (account, container, object)
875 88e015a3 Antony Chazapis
        headers = {}
876 7812e1f9 Sofia Papagiannaki
        headers['x_object_public'] = False
877 88e015a3 Antony Chazapis
        params = {'update':None}
878 88e015a3 Antony Chazapis
        return self.post(path, headers=headers, params=params)
879 7812e1f9 Sofia Papagiannaki
    
880 7812e1f9 Sofia Papagiannaki
    def copy_object(self, src_container, src_object, dst_container, dst_object,
881 d4a63b9b Sofia Papagiannaki
                    meta={}, public=False, version=None, account=None,
882 d4a63b9b Sofia Papagiannaki
                    content_type=None):
883 7812e1f9 Sofia Papagiannaki
        """copies an object"""
884 95e92490 Sofia Papagiannaki
        account = account or self.account
885 7812e1f9 Sofia Papagiannaki
        headers = {}
886 7812e1f9 Sofia Papagiannaki
        headers['x_object_public'] = public
887 7812e1f9 Sofia Papagiannaki
        if version:
888 97d45f69 Antony Chazapis
            headers['x_source_version'] = version
889 7812e1f9 Sofia Papagiannaki
        return OOS_Client.copy_object(self, src_container, src_object,
890 7812e1f9 Sofia Papagiannaki
                                      dst_container, dst_object, meta=meta,
891 d4a63b9b Sofia Papagiannaki
                                      account=account, content_type=content_type,
892 d4a63b9b Sofia Papagiannaki
                                      **headers)
893 7812e1f9 Sofia Papagiannaki
    
894 7812e1f9 Sofia Papagiannaki
    def move_object(self, src_container, src_object, dst_container,
895 97d45f69 Antony Chazapis
                             dst_object, meta={}, public=False,
896 d4a63b9b Sofia Papagiannaki
                             account=None, content_type=None):
897 7812e1f9 Sofia Papagiannaki
        """moves an object"""
898 7812e1f9 Sofia Papagiannaki
        headers = {}
899 7812e1f9 Sofia Papagiannaki
        headers['x_object_public'] = public
900 7812e1f9 Sofia Papagiannaki
        return OOS_Client.move_object(self, src_container, src_object,
901 7812e1f9 Sofia Papagiannaki
                                      dst_container, dst_object, meta=meta,
902 d4a63b9b Sofia Papagiannaki
                                      account=account, content_type=content_type,
903 d4a63b9b Sofia Papagiannaki
                                      **headers)
904 ae75584f Sofia Papagiannaki
    
905 ae75584f Sofia Papagiannaki
    def list_shared_by_others(self, limit=None, marker=None, format='text'):
906 95e92490 Sofia Papagiannaki
        """lists other accounts that share objects to the user"""
907 95e92490 Sofia Papagiannaki
        l = ['limit', 'marker']
908 95e92490 Sofia Papagiannaki
        params = {}
909 95e92490 Sofia Papagiannaki
        for elem in [elem for elem in l if eval(elem)]:
910 95e92490 Sofia Papagiannaki
            params[elem] = eval(elem)
911 95e92490 Sofia Papagiannaki
        return self._list('', format, params)
912 ae75584f Sofia Papagiannaki
    
913 ae75584f Sofia Papagiannaki
    def share_object(self, container, object, l, read=True):
914 e7b51248 Sofia Papagiannaki
        """gives access(read by default) to an object to a user/group list"""
915 ae75584f Sofia Papagiannaki
        action = 'read' if read else 'write'
916 ae75584f Sofia Papagiannaki
        sharing = '%s=%s' % (action, ','.join(l))
917 ae75584f Sofia Papagiannaki
        self.update_object(container, object, f=None, x_object_sharing=sharing)
918 f1716de7 Sofia Papagiannaki
919 f1716de7 Sofia Papagiannaki
def _prepare_path(path, api, format='text', params={}):
920 f1716de7 Sofia Papagiannaki
    slash = '/' if api else ''
921 f1716de7 Sofia Papagiannaki
    full_path = '%s%s%s?format=%s' % (slash, api, quote(path), format)
922 f1716de7 Sofia Papagiannaki
    
923 f1716de7 Sofia Papagiannaki
    for k,v in params.items():
924 f1716de7 Sofia Papagiannaki
        value = quote(str(v)) if v else ''
925 f1716de7 Sofia Papagiannaki
        full_path = '%s&%s=%s' %(full_path, quote(k), value)
926 f1716de7 Sofia Papagiannaki
    return full_path
927 f1716de7 Sofia Papagiannaki
928 f1716de7 Sofia Papagiannaki
def _prepare_headers(headers):
929 f1716de7 Sofia Papagiannaki
    for k,v in headers.items():
930 f1716de7 Sofia Papagiannaki
        headers.pop(k)
931 f1716de7 Sofia Papagiannaki
        k = k.replace('_', '-')
932 f1716de7 Sofia Papagiannaki
        headers[quote(k)] = quote(v, safe='/=,:@ *"') if type(v) == types.StringType else v
933 f1716de7 Sofia Papagiannaki
    return headers
934 f1716de7 Sofia Papagiannaki
935 35c82779 Sofia Papagiannaki
def _handle_response(response, verbose=False, debug=False):
936 f1716de7 Sofia Papagiannaki
    headers = response.getheaders()
937 f1716de7 Sofia Papagiannaki
    headers = dict((unquote(h), unquote(v)) for h,v in headers)
938 f1716de7 Sofia Papagiannaki
    
939 f1716de7 Sofia Papagiannaki
    if verbose:
940 f1716de7 Sofia Papagiannaki
        print '%d %s' % (response.status, response.reason)
941 f1716de7 Sofia Papagiannaki
        for key, val in headers.items():
942 f1716de7 Sofia Papagiannaki
            print '%s: %s' % (key.capitalize(), val)
943 f1716de7 Sofia Papagiannaki
        print
944 f1716de7 Sofia Papagiannaki
    
945 f1716de7 Sofia Papagiannaki
    length = response.getheader('content-length', None)
946 f1716de7 Sofia Papagiannaki
    data = response.read(length)
947 f1716de7 Sofia Papagiannaki
    if debug:
948 f1716de7 Sofia Papagiannaki
        print data
949 f1716de7 Sofia Papagiannaki
        print
950 f1716de7 Sofia Papagiannaki
    
951 f1716de7 Sofia Papagiannaki
    if int(response.status) in ERROR_CODES.keys():
952 f1716de7 Sofia Papagiannaki
        raise Fault(data, int(response.status))
953 f1716de7 Sofia Papagiannaki
    
954 f1716de7 Sofia Papagiannaki
    #print '**',  response.status, headers, data, '\n'
955 35c82779 Sofia Papagiannaki
    return response.status, headers, data