root / pithos / lib / client.py @ f7ab99df
History | View | Annotate | Download (12.8 kB)
1 | ec1b8d3e | Sofia Papagiannaki | from httplib import HTTPConnection, HTTP |
---|---|---|---|
2 | ec1b8d3e | Sofia Papagiannaki | from sys import stdin |
3 | 3f5b02c7 | Sofia Papagiannaki | |
4 | 3f5b02c7 | Sofia Papagiannaki | import json |
5 | ec1b8d3e | Sofia Papagiannaki | import types |
6 | 0ea1dcc4 | Sofia Papagiannaki | import socket |
7 | e3fd7f91 | Sofia Papagiannaki | import pithos.api.faults |
8 | e3fd7f91 | Sofia Papagiannaki | |
9 | e3fd7f91 | Sofia Papagiannaki | ERROR_CODES = {304:'Not Modified', |
10 | e3fd7f91 | Sofia Papagiannaki | 400:'Bad Request', |
11 | e3fd7f91 | Sofia Papagiannaki | 401:'Unauthorized', |
12 | e3fd7f91 | Sofia Papagiannaki | 404:'Not Found', |
13 | e3fd7f91 | Sofia Papagiannaki | 409:'Conflict', |
14 | e3fd7f91 | Sofia Papagiannaki | 411:'Length Required', |
15 | e3fd7f91 | Sofia Papagiannaki | 412:'Precondition Failed', |
16 | e3fd7f91 | Sofia Papagiannaki | 416:'Range Not Satisfiable', |
17 | e3fd7f91 | Sofia Papagiannaki | 422:'Unprocessable Entity', |
18 | e3fd7f91 | Sofia Papagiannaki | 503:'Service Unavailable'} |
19 | 3f5b02c7 | Sofia Papagiannaki | |
20 | 3f5b02c7 | Sofia Papagiannaki | class Fault(Exception): |
21 | e3fd7f91 | Sofia Papagiannaki | def __init__(self, data='', status=None): |
22 | e3fd7f91 | Sofia Papagiannaki | if data == '' and status in ERROR_CODES.keys(): |
23 | e3fd7f91 | Sofia Papagiannaki | data = ERROR_CODES[status] |
24 | 3f5b02c7 | Sofia Papagiannaki | Exception.__init__(self, data) |
25 | 3f5b02c7 | Sofia Papagiannaki | self.data = data
|
26 | e3fd7f91 | Sofia Papagiannaki | self.status = status
|
27 | 3f5b02c7 | Sofia Papagiannaki | |
28 | 3f5b02c7 | Sofia Papagiannaki | class Client(object): |
29 | 3f5b02c7 | Sofia Papagiannaki | def __init__(self, host, account, api='v1', verbose=False, debug=False): |
30 | 3f5b02c7 | Sofia Papagiannaki | """`host` can also include a port, e.g '127.0.0.1:8000'."""
|
31 | 3f5b02c7 | Sofia Papagiannaki | |
32 | 3f5b02c7 | Sofia Papagiannaki | self.host = host
|
33 | 3f5b02c7 | Sofia Papagiannaki | self.account = account
|
34 | 3f5b02c7 | Sofia Papagiannaki | self.api = api
|
35 | 3f5b02c7 | Sofia Papagiannaki | self.verbose = verbose or debug |
36 | 3f5b02c7 | Sofia Papagiannaki | self.debug = debug
|
37 | f7ab99df | Sofia Papagiannaki | |
38 | ec1b8d3e | Sofia Papagiannaki | def _chunked_transfer(self, path, method='PUT', f=stdin, headers=None, |
39 | ec1b8d3e | Sofia Papagiannaki | blocksize=1024):
|
40 | ec1b8d3e | Sofia Papagiannaki | http = HTTPConnection(self.host)
|
41 | ec1b8d3e | Sofia Papagiannaki | |
42 | ec1b8d3e | Sofia Papagiannaki | # write header
|
43 | ec1b8d3e | Sofia Papagiannaki | path = '/%s/%s%s' % (self.api, self.account, path) |
44 | ec1b8d3e | Sofia Papagiannaki | http.putrequest(method, path) |
45 | ec1b8d3e | Sofia Papagiannaki | http.putheader('Content-Type', 'application/octet-stream') |
46 | ec1b8d3e | Sofia Papagiannaki | http.putheader('Transfer-Encoding', 'chunked') |
47 | ec1b8d3e | Sofia Papagiannaki | if headers:
|
48 | ec1b8d3e | Sofia Papagiannaki | for header,value in headers.items(): |
49 | ec1b8d3e | Sofia Papagiannaki | http.putheader(header, value) |
50 | ec1b8d3e | Sofia Papagiannaki | http.endheaders() |
51 | ec1b8d3e | Sofia Papagiannaki | |
52 | ec1b8d3e | Sofia Papagiannaki | # write body
|
53 | ec1b8d3e | Sofia Papagiannaki | data = ''
|
54 | ec1b8d3e | Sofia Papagiannaki | while True: |
55 | ec1b8d3e | Sofia Papagiannaki | if f.closed:
|
56 | ec1b8d3e | Sofia Papagiannaki | break
|
57 | ec1b8d3e | Sofia Papagiannaki | block = f.read(blocksize) |
58 | ec1b8d3e | Sofia Papagiannaki | if block == '': |
59 | ec1b8d3e | Sofia Papagiannaki | break
|
60 | ec1b8d3e | Sofia Papagiannaki | data = '%s\r\n%s\r\n' % (hex(len(block)), block) |
61 | ec1b8d3e | Sofia Papagiannaki | try:
|
62 | ec1b8d3e | Sofia Papagiannaki | http.send(data) |
63 | ec1b8d3e | Sofia Papagiannaki | except:
|
64 | ec1b8d3e | Sofia Papagiannaki | #retry
|
65 | ec1b8d3e | Sofia Papagiannaki | http.send(data) |
66 | ec1b8d3e | Sofia Papagiannaki | data = '0x0\r\n'
|
67 | ec1b8d3e | Sofia Papagiannaki | try:
|
68 | ec1b8d3e | Sofia Papagiannaki | http.send(data) |
69 | ec1b8d3e | Sofia Papagiannaki | except:
|
70 | ec1b8d3e | Sofia Papagiannaki | #retry
|
71 | ec1b8d3e | Sofia Papagiannaki | http.send(data) |
72 | ec1b8d3e | Sofia Papagiannaki | |
73 | ec1b8d3e | Sofia Papagiannaki | # get response
|
74 | ec1b8d3e | Sofia Papagiannaki | resp = http.getresponse() |
75 | e3fd7f91 | Sofia Papagiannaki | |
76 | ec1b8d3e | Sofia Papagiannaki | headers = dict(resp.getheaders())
|
77 | ec1b8d3e | Sofia Papagiannaki | |
78 | ec1b8d3e | Sofia Papagiannaki | if self.verbose: |
79 | ec1b8d3e | Sofia Papagiannaki | print '%d %s' % (resp.status, resp.reason) |
80 | ec1b8d3e | Sofia Papagiannaki | for key, val in headers.items(): |
81 | ec1b8d3e | Sofia Papagiannaki | print '%s: %s' % (key.capitalize(), val) |
82 | ec1b8d3e | Sofia Papagiannaki | print
|
83 | ec1b8d3e | Sofia Papagiannaki | |
84 | f7ab99df | Sofia Papagiannaki | length = resp.getheader('Content-length', None) |
85 | 6cd1831a | Sofia Papagiannaki | data = resp.read(length) |
86 | ec1b8d3e | Sofia Papagiannaki | if self.debug: |
87 | ec1b8d3e | Sofia Papagiannaki | print data
|
88 | ec1b8d3e | Sofia Papagiannaki | print
|
89 | ec1b8d3e | Sofia Papagiannaki | |
90 | e3fd7f91 | Sofia Papagiannaki | if int(resp.status) in ERROR_CODES.keys(): |
91 | e3fd7f91 | Sofia Papagiannaki | raise Fault(data, int(resp.status)) |
92 | e3fd7f91 | Sofia Papagiannaki | |
93 | f7ab99df | Sofia Papagiannaki | #print '*', resp.status, headers, data
|
94 | ec1b8d3e | Sofia Papagiannaki | return resp.status, headers, data
|
95 | f7ab99df | Sofia Papagiannaki | |
96 | d2d5c360 | Sofia Papagiannaki | def req(self, method, path, body=None, headers=None, format='text', |
97 | d2d5c360 | Sofia Papagiannaki | params=None):
|
98 | d2d5c360 | Sofia Papagiannaki | full_path = '/%s/%s%s?format=%s' % (self.api, self.account, path, |
99 | d2d5c360 | Sofia Papagiannaki | format) |
100 | 3f5b02c7 | Sofia Papagiannaki | if params:
|
101 | 3f5b02c7 | Sofia Papagiannaki | for k,v in params.items(): |
102 | ec1b8d3e | Sofia Papagiannaki | if v:
|
103 | ec1b8d3e | Sofia Papagiannaki | full_path = '%s&%s=%s' %(full_path, k, v)
|
104 | 3f5b02c7 | Sofia Papagiannaki | conn = HTTPConnection(self.host)
|
105 | 3f5b02c7 | Sofia Papagiannaki | |
106 | d2d5c360 | Sofia Papagiannaki | #encode whitespace
|
107 | d2d5c360 | Sofia Papagiannaki | full_path = full_path.replace(' ', '%20') |
108 | ec1b8d3e | Sofia Papagiannaki | |
109 | 3f5b02c7 | Sofia Papagiannaki | kwargs = {} |
110 | 3f5b02c7 | Sofia Papagiannaki | kwargs['headers'] = headers or {} |
111 | ec1b8d3e | Sofia Papagiannaki | if not headers or \ |
112 | ec1b8d3e | Sofia Papagiannaki | 'Transfer-Encoding' not in headers \ |
113 | ec1b8d3e | Sofia Papagiannaki | or headers['Transfer-Encoding'] != 'chunked': |
114 | ec1b8d3e | Sofia Papagiannaki | kwargs['headers']['Content-Length'] = len(body) if body else 0 |
115 | 3f5b02c7 | Sofia Papagiannaki | if body:
|
116 | 3f5b02c7 | Sofia Papagiannaki | kwargs['body'] = body
|
117 | 3f5b02c7 | Sofia Papagiannaki | kwargs['headers']['Content-Type'] = 'application/octet-stream' |
118 | ec1b8d3e | Sofia Papagiannaki | #print '****', method, full_path, kwargs
|
119 | e3fd7f91 | Sofia Papagiannaki | try:
|
120 | e3fd7f91 | Sofia Papagiannaki | conn.request(method, full_path, **kwargs) |
121 | e3fd7f91 | Sofia Papagiannaki | except socket.error, e:
|
122 | e3fd7f91 | Sofia Papagiannaki | raise Fault(status=503) |
123 | e3fd7f91 | Sofia Papagiannaki | |
124 | 3f5b02c7 | Sofia Papagiannaki | resp = conn.getresponse() |
125 | 3f5b02c7 | Sofia Papagiannaki | headers = dict(resp.getheaders())
|
126 | 3f5b02c7 | Sofia Papagiannaki | |
127 | 3f5b02c7 | Sofia Papagiannaki | if self.verbose: |
128 | 3f5b02c7 | Sofia Papagiannaki | print '%d %s' % (resp.status, resp.reason) |
129 | 3f5b02c7 | Sofia Papagiannaki | for key, val in headers.items(): |
130 | 3f5b02c7 | Sofia Papagiannaki | print '%s: %s' % (key.capitalize(), val) |
131 | 3f5b02c7 | Sofia Papagiannaki | print
|
132 | 3f5b02c7 | Sofia Papagiannaki | |
133 | f7ab99df | Sofia Papagiannaki | length = resp.getheader('Content-length', None) |
134 | 6cd1831a | Sofia Papagiannaki | data = resp.read(length) |
135 | 3f5b02c7 | Sofia Papagiannaki | if self.debug: |
136 | 3f5b02c7 | Sofia Papagiannaki | print data
|
137 | 3f5b02c7 | Sofia Papagiannaki | print
|
138 | 3f5b02c7 | Sofia Papagiannaki | |
139 | e3fd7f91 | Sofia Papagiannaki | if int(resp.status) in ERROR_CODES.keys(): |
140 | e3fd7f91 | Sofia Papagiannaki | raise Fault(data, int(resp.status)) |
141 | e3fd7f91 | Sofia Papagiannaki | |
142 | e3fd7f91 | Sofia Papagiannaki | #print '*', resp.status, headers, data
|
143 | 3f5b02c7 | Sofia Papagiannaki | return resp.status, headers, data
|
144 | f7ab99df | Sofia Papagiannaki | |
145 | 3f5b02c7 | Sofia Papagiannaki | def delete(self, path, format='text'): |
146 | 3f5b02c7 | Sofia Papagiannaki | return self.req('DELETE', path, format=format) |
147 | f7ab99df | Sofia Papagiannaki | |
148 | 3f5b02c7 | Sofia Papagiannaki | def get(self, path, format='text', headers=None, params=None): |
149 | 3f5b02c7 | Sofia Papagiannaki | return self.req('GET', path, headers=headers, format=format, |
150 | ec1b8d3e | Sofia Papagiannaki | params=params) |
151 | f7ab99df | Sofia Papagiannaki | |
152 | d2d5c360 | Sofia Papagiannaki | def head(self, path, format='text', params=None): |
153 | d2d5c360 | Sofia Papagiannaki | return self.req('HEAD', path, format=format, params=params) |
154 | f7ab99df | Sofia Papagiannaki | |
155 | 3f5b02c7 | Sofia Papagiannaki | def post(self, path, body=None, format='text', headers=None): |
156 | 3f5b02c7 | Sofia Papagiannaki | return self.req('POST', path, body, headers=headers, format=format) |
157 | f7ab99df | Sofia Papagiannaki | |
158 | 3f5b02c7 | Sofia Papagiannaki | def put(self, path, body=None, format='text', headers=None): |
159 | 3f5b02c7 | Sofia Papagiannaki | return self.req('PUT', path, body, headers=headers, format=format) |
160 | f7ab99df | Sofia Papagiannaki | |
161 | 3f5b02c7 | Sofia Papagiannaki | def _list(self, path, detail=False, params=None, headers=None): |
162 | 3f5b02c7 | Sofia Papagiannaki | format = 'json' if detail else 'text' |
163 | 3f5b02c7 | Sofia Papagiannaki | status, headers, data = self.get(path, format=format, headers=headers,
|
164 | 3f5b02c7 | Sofia Papagiannaki | params=params) |
165 | ec1b8d3e | Sofia Papagiannaki | if detail:
|
166 | ec1b8d3e | Sofia Papagiannaki | data = json.loads(data) |
167 | ec1b8d3e | Sofia Papagiannaki | else:
|
168 | b41a95a0 | Sofia Papagiannaki | data = data.strip().split('\n')
|
169 | 3f5b02c7 | Sofia Papagiannaki | return data
|
170 | f7ab99df | Sofia Papagiannaki | |
171 | d2d5c360 | Sofia Papagiannaki | def _get_metadata(self, path, prefix=None, params=None): |
172 | d2d5c360 | Sofia Papagiannaki | status, headers, data = self.head(path, params=params)
|
173 | f7ab99df | Sofia Papagiannaki | prefixlen = len(prefix) if prefix else 0 |
174 | 3f5b02c7 | Sofia Papagiannaki | meta = {} |
175 | 3f5b02c7 | Sofia Papagiannaki | for key, val in headers.items(): |
176 | 0ea1dcc4 | Sofia Papagiannaki | if prefix and not key.startswith(prefix): |
177 | 0ea1dcc4 | Sofia Papagiannaki | continue
|
178 | 0ea1dcc4 | Sofia Papagiannaki | elif prefix and key.startswith(prefix): |
179 | 3f5b02c7 | Sofia Papagiannaki | key = key[prefixlen:] |
180 | 0ea1dcc4 | Sofia Papagiannaki | meta[key] = val |
181 | 3f5b02c7 | Sofia Papagiannaki | return meta
|
182 | f7ab99df | Sofia Papagiannaki | |
183 | f7ab99df | Sofia Papagiannaki | def _update_metadata(self, path, entity, **meta): |
184 | f7ab99df | Sofia Papagiannaki | """
|
185 | f7ab99df | Sofia Papagiannaki | adds new and updates the values of previously set metadata
|
186 | f7ab99df | Sofia Papagiannaki | """
|
187 | 3f5b02c7 | Sofia Papagiannaki | for key, val in meta.items(): |
188 | f7ab99df | Sofia Papagiannaki | meta.pop(key) |
189 | f7ab99df | Sofia Papagiannaki | meta['X-%s-Meta-%s' %(entity.capitalize(), key.capitalize())] = val
|
190 | f7ab99df | Sofia Papagiannaki | prev_meta = self._get_metadata(path)
|
191 | f7ab99df | Sofia Papagiannaki | prev_meta.update(meta) |
192 | f7ab99df | Sofia Papagiannaki | headers = {} |
193 | f7ab99df | Sofia Papagiannaki | for key, val in prev_meta.items(): |
194 | f7ab99df | Sofia Papagiannaki | headers[key.capitalize()] = val |
195 | f7ab99df | Sofia Papagiannaki | self.post(path, headers=headers)
|
196 | f7ab99df | Sofia Papagiannaki | |
197 | f7ab99df | Sofia Papagiannaki | def _delete_metadata(self, path, entity, meta=[]): |
198 | f7ab99df | Sofia Papagiannaki | """
|
199 | f7ab99df | Sofia Papagiannaki | delete previously set metadata
|
200 | f7ab99df | Sofia Papagiannaki | """
|
201 | f7ab99df | Sofia Papagiannaki | prev_meta = self._get_metadata(path)
|
202 | f7ab99df | Sofia Papagiannaki | headers = {} |
203 | f7ab99df | Sofia Papagiannaki | for key, val in prev_meta.items(): |
204 | f7ab99df | Sofia Papagiannaki | if key.split('-')[-1] in meta: |
205 | f7ab99df | Sofia Papagiannaki | continue
|
206 | f7ab99df | Sofia Papagiannaki | http_key = key.capitalize() |
207 | 3f5b02c7 | Sofia Papagiannaki | headers[http_key] = val |
208 | 3f5b02c7 | Sofia Papagiannaki | self.post(path, headers=headers)
|
209 | f7ab99df | Sofia Papagiannaki | |
210 | 3f5b02c7 | Sofia Papagiannaki | # Storage Account Services
|
211 | f7ab99df | Sofia Papagiannaki | |
212 | ec1b8d3e | Sofia Papagiannaki | def list_containers(self, detail=False, params=None, headers=None): |
213 | 3f5b02c7 | Sofia Papagiannaki | return self._list('', detail, params, headers) |
214 | f7ab99df | Sofia Papagiannaki | |
215 | d2d5c360 | Sofia Papagiannaki | def account_metadata(self, restricted=False, until=None): |
216 | f7ab99df | Sofia Papagiannaki | prefix = 'x-account-meta-' if restricted else None |
217 | f7ab99df | Sofia Papagiannaki | params = {'until':until} if until else None |
218 | d2d5c360 | Sofia Papagiannaki | return self._get_metadata('', prefix, params=params) |
219 | f7ab99df | Sofia Papagiannaki | |
220 | 3f5b02c7 | Sofia Papagiannaki | def update_account_metadata(self, **meta): |
221 | f7ab99df | Sofia Papagiannaki | self._update_metadata('', 'account', **meta) |
222 | f7ab99df | Sofia Papagiannaki | |
223 | f7ab99df | Sofia Papagiannaki | def delete_account_metadata(self, meta=[]): |
224 | f7ab99df | Sofia Papagiannaki | self._delete_metadata('', 'account', meta) |
225 | f7ab99df | Sofia Papagiannaki | |
226 | 3f5b02c7 | Sofia Papagiannaki | # Storage Container Services
|
227 | f7ab99df | Sofia Papagiannaki | |
228 | ec1b8d3e | Sofia Papagiannaki | def list_objects(self, container, detail=False, params=None, headers=None): |
229 | ec1b8d3e | Sofia Papagiannaki | return self._list('/' + container, detail, params, headers) |
230 | f7ab99df | Sofia Papagiannaki | |
231 | ec1b8d3e | Sofia Papagiannaki | def create_container(self, container, headers=None): |
232 | ec1b8d3e | Sofia Papagiannaki | status, header, data = self.put('/' + container, headers=headers) |
233 | 3f5b02c7 | Sofia Papagiannaki | if status == 202: |
234 | 3f5b02c7 | Sofia Papagiannaki | return False |
235 | 3f5b02c7 | Sofia Papagiannaki | elif status != 201: |
236 | e3fd7f91 | Sofia Papagiannaki | raise Fault(data, int(status)) |
237 | 3f5b02c7 | Sofia Papagiannaki | return True |
238 | f7ab99df | Sofia Papagiannaki | |
239 | 3f5b02c7 | Sofia Papagiannaki | def delete_container(self, container): |
240 | 3f5b02c7 | Sofia Papagiannaki | self.delete('/' + container) |
241 | f7ab99df | Sofia Papagiannaki | |
242 | d2d5c360 | Sofia Papagiannaki | def retrieve_container_metadata(self, container, restricted=False, |
243 | d2d5c360 | Sofia Papagiannaki | until=None):
|
244 | f7ab99df | Sofia Papagiannaki | prefix = 'x-container-meta-' if restricted else None |
245 | f7ab99df | Sofia Papagiannaki | params = {'until':until} if until else None |
246 | d2d5c360 | Sofia Papagiannaki | return self._get_metadata('/%s' % container, prefix, params=params) |
247 | f7ab99df | Sofia Papagiannaki | |
248 | 3f5b02c7 | Sofia Papagiannaki | def update_container_metadata(self, container, **meta): |
249 | f7ab99df | Sofia Papagiannaki | self._update_metadata('/' + container, 'container', **meta) |
250 | f7ab99df | Sofia Papagiannaki | |
251 | f7ab99df | Sofia Papagiannaki | def delete_container_metadata(self, container, meta=[]): |
252 | f7ab99df | Sofia Papagiannaki | path = '/%s' % (container)
|
253 | f7ab99df | Sofia Papagiannaki | self._delete_metadata(path, 'container', meta) |
254 | f7ab99df | Sofia Papagiannaki | |
255 | 3f5b02c7 | Sofia Papagiannaki | # Storage Object Services
|
256 | f7ab99df | Sofia Papagiannaki | |
257 | 8fe01d72 | Sofia Papagiannaki | def retrieve_object(self, container, object, detail=False, headers=None, |
258 | 8fe01d72 | Sofia Papagiannaki | version=None):
|
259 | 3f5b02c7 | Sofia Papagiannaki | path = '/%s/%s' % (container, object) |
260 | ec1b8d3e | Sofia Papagiannaki | format = 'json' if detail else 'text' |
261 | f7ab99df | Sofia Papagiannaki | params = {'version':version} if version else None |
262 | 8fe01d72 | Sofia Papagiannaki | status, headers, data = self.get(path, format, headers, params)
|
263 | 3f5b02c7 | Sofia Papagiannaki | return data
|
264 | f7ab99df | Sofia Papagiannaki | |
265 | f7ab99df | Sofia Papagiannaki | def create_directory_marker(self, container, object): |
266 | f7ab99df | Sofia Papagiannaki | if not object: |
267 | f7ab99df | Sofia Papagiannaki | raise Fault('Directory markers have to be nested in a container') |
268 | f7ab99df | Sofia Papagiannaki | h = {'Content-Type':'application/directory'} |
269 | f7ab99df | Sofia Papagiannaki | self.create_object(container, object, f=None, headers=h) |
270 | f7ab99df | Sofia Papagiannaki | |
271 | ec1b8d3e | Sofia Papagiannaki | def create_object(self, container, object, f=stdin, chunked=False, |
272 | ec1b8d3e | Sofia Papagiannaki | blocksize=1024, headers=None): |
273 | d2d5c360 | Sofia Papagiannaki | """
|
274 | d2d5c360 | Sofia Papagiannaki | creates an object
|
275 | d2d5c360 | Sofia Papagiannaki | if f is None then creates a zero length object
|
276 | d2d5c360 | Sofia Papagiannaki | if f is stdin or chunked is set then performs chunked transfer
|
277 | d2d5c360 | Sofia Papagiannaki | """
|
278 | 3f5b02c7 | Sofia Papagiannaki | path = '/%s/%s' % (container, object) |
279 | ec1b8d3e | Sofia Papagiannaki | if not chunked and f != stdin: |
280 | f7ab99df | Sofia Papagiannaki | data = f.read() if f else None |
281 | e3fd7f91 | Sofia Papagiannaki | return self.put(path, data, headers=headers) |
282 | ec1b8d3e | Sofia Papagiannaki | else:
|
283 | e3fd7f91 | Sofia Papagiannaki | return self._chunked_transfer(path, 'PUT', f, headers=headers, |
284 | ec1b8d3e | Sofia Papagiannaki | blocksize=1024)
|
285 | f7ab99df | Sofia Papagiannaki | |
286 | ec1b8d3e | Sofia Papagiannaki | def update_object(self, container, object, f=stdin, chunked=False, |
287 | ec1b8d3e | Sofia Papagiannaki | blocksize=1024, headers=None): |
288 | ec1b8d3e | Sofia Papagiannaki | if not f: |
289 | ec1b8d3e | Sofia Papagiannaki | return
|
290 | ec1b8d3e | Sofia Papagiannaki | path = '/%s/%s' % (container, object) |
291 | ec1b8d3e | Sofia Papagiannaki | if not chunked and f != stdin: |
292 | ec1b8d3e | Sofia Papagiannaki | data = f.read() |
293 | ec1b8d3e | Sofia Papagiannaki | self.post(path, data, headers=headers)
|
294 | ec1b8d3e | Sofia Papagiannaki | else:
|
295 | ec1b8d3e | Sofia Papagiannaki | self._chunked_transfer(path, 'POST', f, headers=headers, |
296 | ec1b8d3e | Sofia Papagiannaki | blocksize=1024)
|
297 | f7ab99df | Sofia Papagiannaki | |
298 | ec1b8d3e | Sofia Papagiannaki | def _change_obj_location(self, src_container, src_object, dst_container, |
299 | ad71a0ce | Sofia Papagiannaki | dst_object, remove=False, headers=None): |
300 | 3f5b02c7 | Sofia Papagiannaki | path = '/%s/%s' % (dst_container, dst_object)
|
301 | ad71a0ce | Sofia Papagiannaki | if not headers: |
302 | ad71a0ce | Sofia Papagiannaki | headers = {} |
303 | ec1b8d3e | Sofia Papagiannaki | if remove:
|
304 | ec1b8d3e | Sofia Papagiannaki | headers['X-Move-From'] = '/%s/%s' % (src_container, src_object) |
305 | ec1b8d3e | Sofia Papagiannaki | else:
|
306 | ec1b8d3e | Sofia Papagiannaki | headers['X-Copy-From'] = '/%s/%s' % (src_container, src_object) |
307 | 3f5b02c7 | Sofia Papagiannaki | headers['Content-Length'] = 0 |
308 | 3f5b02c7 | Sofia Papagiannaki | self.put(path, headers=headers)
|
309 | f7ab99df | Sofia Papagiannaki | |
310 | ec1b8d3e | Sofia Papagiannaki | def copy_object(self, src_container, src_object, dst_container, |
311 | ad71a0ce | Sofia Papagiannaki | dst_object, headers=None):
|
312 | ec1b8d3e | Sofia Papagiannaki | self._change_obj_location(src_container, src_object,
|
313 | 7e999dec | Sofia Papagiannaki | dst_container, dst_object, |
314 | 7e999dec | Sofia Papagiannaki | headers=headers) |
315 | f7ab99df | Sofia Papagiannaki | |
316 | ec1b8d3e | Sofia Papagiannaki | def move_object(self, src_container, src_object, dst_container, |
317 | ad71a0ce | Sofia Papagiannaki | dst_object, headers=None):
|
318 | ec1b8d3e | Sofia Papagiannaki | self._change_obj_location(src_container, src_object,
|
319 | ad71a0ce | Sofia Papagiannaki | dst_container, dst_object, True, headers)
|
320 | f7ab99df | Sofia Papagiannaki | |
321 | 3f5b02c7 | Sofia Papagiannaki | def delete_object(self, container, object): |
322 | 3f5b02c7 | Sofia Papagiannaki | self.delete('/%s/%s' % (container, object)) |
323 | f7ab99df | Sofia Papagiannaki | |
324 | 8fe01d72 | Sofia Papagiannaki | def retrieve_object_metadata(self, container, object, restricted=False, |
325 | 8fe01d72 | Sofia Papagiannaki | version=None):
|
326 | 3f5b02c7 | Sofia Papagiannaki | path = '/%s/%s' % (container, object) |
327 | f7ab99df | Sofia Papagiannaki | prefix = 'x-object-meta-' if restricted else None |
328 | f7ab99df | Sofia Papagiannaki | params = {'version':version} if version else None |
329 | 8fe01d72 | Sofia Papagiannaki | return self._get_metadata(path, prefix, params=params) |
330 | f7ab99df | Sofia Papagiannaki | |
331 | 3f5b02c7 | Sofia Papagiannaki | def update_object_metadata(self, container, object, **meta): |
332 | 3f5b02c7 | Sofia Papagiannaki | path = '/%s/%s' % (container, object) |
333 | f7ab99df | Sofia Papagiannaki | self._update_metadata(path, 'object', **meta) |
334 | f7ab99df | Sofia Papagiannaki | |
335 | f7ab99df | Sofia Papagiannaki | def delete_object_metadata(self, container, object, meta=[]): |
336 | f7ab99df | Sofia Papagiannaki | path = '/%s/%s' % (container, object) |
337 | f7ab99df | Sofia Papagiannaki | self._delete_metadata(path, 'object', meta) |
338 | f7ab99df | Sofia Papagiannaki | |
339 | f7ab99df | Sofia Papagiannaki | def trash_object(self, container, object): |
340 | f7ab99df | Sofia Papagiannaki | """
|
341 | f7ab99df | Sofia Papagiannaki | trashes an object
|
342 | f7ab99df | Sofia Papagiannaki | actually resets all object metadata with trash = true
|
343 | f7ab99df | Sofia Papagiannaki | """
|
344 | f7ab99df | Sofia Papagiannaki | path = '/%s/%s' % (container, object) |
345 | f7ab99df | Sofia Papagiannaki | meta = {'trash':'true'} |
346 | f7ab99df | Sofia Papagiannaki | self._update_metadata(path, 'object', **meta) |
347 | f7ab99df | Sofia Papagiannaki | |
348 | f7ab99df | Sofia Papagiannaki | def restore_object(self, container, object): |
349 | f7ab99df | Sofia Papagiannaki | """
|
350 | f7ab99df | Sofia Papagiannaki | restores a trashed object
|
351 | f7ab99df | Sofia Papagiannaki | actualy just resets all object metadata except trash
|
352 | f7ab99df | Sofia Papagiannaki | """
|
353 | f7ab99df | Sofia Papagiannaki | self.delete_object_metadata(container, object, ['trash']) |