Revision f0eacc2c
b/pithos/api/tests.py | ||
---|---|---|
36 | 36 |
from django.utils import simplejson as json |
37 | 37 |
from xml.dom import minidom |
38 | 38 |
from StringIO import StringIO |
39 |
import time as _time |
|
39 | 40 |
import types |
40 | 41 |
import hashlib |
41 | 42 |
import os |
... | ... | |
45 | 46 |
import string |
46 | 47 |
import re |
47 | 48 |
|
48 |
#from pithos.backends import backend |
|
49 |
|
|
50 | 49 |
DATE_FORMATS = ["%a %b %d %H:%M:%S %Y", |
51 | 50 |
"%A, %d-%b-%y %H:%M:%S GMT", |
52 | 51 |
"%a, %d %b %Y %H:%M:%S GMT"] |
... | ... | |
54 | 53 |
DEFAULT_HOST = 'pithos.dev.grnet.gr' |
55 | 54 |
#DEFAULT_HOST = '127.0.0.1:8000' |
56 | 55 |
DEFAULT_API = 'v1' |
57 |
DEFAULT_USER = 'papagian'
|
|
58 |
DEFAULT_AUTH = '0004'
|
|
56 |
DEFAULT_USER = 'test'
|
|
57 |
DEFAULT_AUTH = '0000'
|
|
59 | 58 |
|
60 | 59 |
class BaseTestCase(unittest.TestCase): |
61 | 60 |
#TODO unauthorized request |
62 | 61 |
def setUp(self): |
63 |
self.client = Pithos_Client(DEFAULT_HOST, DEFAULT_AUTH, DEFAULT_USER, DEFAULT_API) |
|
64 |
self.headers = { |
|
65 |
'account': ('x-account-container-count', |
|
66 |
'x-account-bytes-used', |
|
67 |
'last-modified', |
|
68 |
'content-length', |
|
69 |
'date', |
|
70 |
'content_type', |
|
71 |
'server',), |
|
72 |
'object': ('etag', |
|
73 |
'content-length', |
|
74 |
'content_type', |
|
75 |
'content-encoding', |
|
76 |
'last-modified', |
|
77 |
'date', |
|
78 |
'x-object-manifest', |
|
79 |
'content-range', |
|
80 |
'x-object-modified-by', |
|
81 |
'x-object-version', |
|
82 |
'x-object-version-timestamp', |
|
83 |
'server',), |
|
84 |
'container': ('x-container-object-count', |
|
85 |
'x-container-bytes-used', |
|
86 |
'content_type', |
|
87 |
'last-modified', |
|
88 |
'content-length', |
|
89 |
'date', |
|
90 |
'x-container-block-size', |
|
91 |
'x-container-block-hash', |
|
92 |
'x-container-policy-quota', |
|
93 |
'x-container-policy-versioning', |
|
94 |
'server', |
|
95 |
'x-container-object-meta', |
|
96 |
'x-container-policy-versioning', |
|
97 |
'server',)} |
|
98 |
|
|
99 |
self.contentTypes = {'xml':'application/xml', |
|
100 |
'json':'application/json', |
|
101 |
'':'text/plain'} |
|
62 |
self.client = Pithos_Client(DEFAULT_HOST, |
|
63 |
DEFAULT_AUTH, |
|
64 |
DEFAULT_USER, |
|
65 |
DEFAULT_API) |
|
66 |
self.invalid_client = Pithos_Client(DEFAULT_HOST, |
|
67 |
DEFAULT_AUTH, |
|
68 |
'invalid', |
|
69 |
DEFAULT_API) |
|
70 |
#self.headers = { |
|
71 |
# 'account': ('x-account-container-count', |
|
72 |
# 'x-account-bytes-used', |
|
73 |
# 'last-modified', |
|
74 |
# 'content-length', |
|
75 |
# 'date', |
|
76 |
# 'content_type', |
|
77 |
# 'server',), |
|
78 |
# 'object': ('etag', |
|
79 |
# 'content-length', |
|
80 |
# 'content_type', |
|
81 |
# 'content-encoding', |
|
82 |
# 'last-modified', |
|
83 |
# 'date', |
|
84 |
# 'x-object-manifest', |
|
85 |
# 'content-range', |
|
86 |
# 'x-object-modified-by', |
|
87 |
# 'x-object-version', |
|
88 |
# 'x-object-version-timestamp', |
|
89 |
# 'server',), |
|
90 |
# 'container': ('x-container-object-count', |
|
91 |
# 'x-container-bytes-used', |
|
92 |
# 'content_type', |
|
93 |
# 'last-modified', |
|
94 |
# 'content-length', |
|
95 |
# 'date', |
|
96 |
# 'x-container-block-size', |
|
97 |
# 'x-container-block-hash', |
|
98 |
# 'x-container-policy-quota', |
|
99 |
# 'x-container-policy-versioning', |
|
100 |
# 'server', |
|
101 |
# 'x-container-object-meta', |
|
102 |
# 'x-container-policy-versioning', |
|
103 |
# 'server',)} |
|
104 |
# |
|
105 |
#self.contentTypes = {'xml':'application/xml', |
|
106 |
# 'json':'application/json', |
|
107 |
# '':'text/plain'} |
|
102 | 108 |
self.extended = { |
103 | 109 |
'container':( |
104 | 110 |
'name', |
... | ... | |
146 | 152 |
# data = minidom.parseString(data) |
147 | 153 |
# return status, headers, data |
148 | 154 |
|
149 |
def assert_headers(self, headers, type, **exp_meta): |
|
150 |
prefix = 'x-%s-meta-' %type |
|
151 |
system_headers = [h for h in headers if not h.startswith(prefix)] |
|
152 |
for k,v in headers.items(): |
|
153 |
if k in system_headers: |
|
154 |
self.assertTrue(k in headers[type]) |
|
155 |
elif exp_meta: |
|
156 |
k = k.split(prefix)[-1] |
|
157 |
self.assertEqual(v, exp_meta[k]) |
|
158 |
|
|
159 |
#def assert_extended(self, data, format, type, size): |
|
160 |
# if format == 'xml': |
|
161 |
# self._assert_xml(data, type, size) |
|
162 |
# elif format == 'json': |
|
163 |
# self._assert_json(data, type, size) |
|
164 |
|
|
165 |
#def _assert_json(self, data, type, size): |
|
166 |
# print '#', data |
|
167 |
# convert = lambda s: s.lower() |
|
168 |
# info = [convert(elem) for elem in self.extended[type]] |
|
169 |
# data = json.loads(data) |
|
170 |
# self.assertTrue(len(data) <= size) |
|
171 |
# for item in info: |
|
172 |
# for i in data: |
|
173 |
# if 'subdir' in i.keys(): |
|
174 |
# continue |
|
175 |
# self.assertTrue(item in i.keys()) |
|
176 |
|
|
177 |
#def _assert_xml(self, data, type, size): |
|
178 |
# print '#', data |
|
179 |
# convert = lambda s: s.lower() |
|
180 |
# info = [convert(elem) for elem in self.extended[type]] |
|
181 |
# try: |
|
182 |
# info.remove('content_encoding') |
|
183 |
# except ValueError: |
|
184 |
# pass |
|
185 |
# xml = minidom.parseString(data) |
|
186 |
# entities = xml.getElementsByTagName(type) |
|
187 |
# self.assertTrue(len(entities) <= size) |
|
188 |
# for e in entities: |
|
189 |
# for item in info: |
|
190 |
# self.assertTrue(e.hasAttribute(item)) |
|
155 |
#def assert_headers(self, headers, type, **exp_meta): |
|
156 |
# prefix = 'x-%s-meta-' %type |
|
157 |
# system_headers = [h for h in headers if not h.startswith(prefix)] |
|
158 |
# for k,v in headers.items(): |
|
159 |
# if k in system_headers: |
|
160 |
# self.assertTrue(k in headers[type]) |
|
161 |
# elif exp_meta: |
|
162 |
# k = k.split(prefix)[-1] |
|
163 |
# self.assertEqual(v, exp_meta[k]) |
|
164 |
|
|
165 |
def assert_extended(self, data, format, type, size): |
|
166 |
if format == 'xml': |
|
167 |
self._assert_xml(data, type, size) |
|
168 |
elif format == 'json': |
|
169 |
self._assert_json(data, type, size) |
|
170 |
|
|
171 |
def _assert_json(self, data, type, size): |
|
172 |
print '#', data |
|
173 |
convert = lambda s: s.lower() |
|
174 |
info = [convert(elem) for elem in self.extended[type]] |
|
175 |
self.assertTrue(len(data) <= size) |
|
176 |
for item in info: |
|
177 |
for i in data: |
|
178 |
if 'subdir' in i.keys(): |
|
179 |
continue |
|
180 |
self.assertTrue(item in i.keys()) |
|
181 |
|
|
182 |
def _assert_xml(self, data, type, size): |
|
183 |
convert = lambda s: s.lower() |
|
184 |
info = [convert(elem) for elem in self.extended[type]] |
|
185 |
try: |
|
186 |
info.remove('content_encoding') |
|
187 |
except ValueError: |
|
188 |
pass |
|
189 |
xml = data |
|
190 |
entities = xml.getElementsByTagName(type) |
|
191 |
self.assertTrue(len(entities) <= size) |
|
192 |
for e in entities: |
|
193 |
for item in info: |
|
194 |
print '#', item |
|
195 |
self.assertTrue(e.hasAttribute(item)) |
|
191 | 196 |
|
192 | 197 |
def assert_raises_fault(self, status, callableObj, *args, **kwargs): |
193 | 198 |
""" |
... | ... | |
265 | 270 |
for item in self.containers: |
266 | 271 |
self.client.create_container(item) |
267 | 272 |
|
273 |
def tearDown(self): |
|
274 |
self.client.delete_account_metadata(['foo']) |
|
275 |
BaseTestCase.tearDown(self) |
|
276 |
|
|
268 | 277 |
def test_get_account_meta(self): |
269 | 278 |
meta = self.client.retrieve_account_metadata() |
270 | 279 |
|
... | ... | |
277 | 286 |
size = size + int(m['x-container-bytes-used']) |
278 | 287 |
self.assertEqual(meta['x-account-bytes-used'], str(size)) |
279 | 288 |
|
280 |
#def test_get_account_401(self): |
|
281 |
# response = self.get_account_meta('non-existing-account') |
|
282 |
# print response |
|
283 |
# self.assertEqual(response.status_code, 401) |
|
289 |
def test_get_account_401(self): |
|
290 |
self.assert_raises_fault(401, |
|
291 |
self.invalid_client.retrieve_account_metadata) |
|
292 |
|
|
293 |
def test_get_account_meta_until(self): |
|
294 |
t = datetime.datetime.utcnow() |
|
295 |
past = t - datetime.timedelta(minutes=-15) |
|
296 |
past = int(_time.mktime(past.timetuple())) |
|
297 |
|
|
298 |
meta = {'foo':'bar'} |
|
299 |
self.client.update_account_metadata(**meta) |
|
300 |
meta = self.client.retrieve_account_metadata(restricted=True, |
|
301 |
until=past) |
|
302 |
self.assertTrue('foo' not in meta) |
|
303 |
|
|
304 |
meta = self.client.retrieve_account_metadata(restricted=True) |
|
305 |
self.assertTrue('foo' in meta) |
|
306 |
|
|
307 |
def test_get_account_meta_until_invalid_date(self): |
|
308 |
meta = {'foo':'bar'} |
|
309 |
self.client.update_account_metadata(**meta) |
|
310 |
meta = self.client.retrieve_account_metadata(restricted=True, |
|
311 |
until='kshfksfh') |
|
312 |
self.assertTrue('foo' in meta) |
|
284 | 313 |
|
285 | 314 |
class AccountGet(BaseTestCase): |
286 | 315 |
def setUp(self): |
... | ... | |
296 | 325 |
containers = self.client.list_containers() |
297 | 326 |
self.assertEquals(self.containers, containers) |
298 | 327 |
|
299 |
#def test_list_204(self): |
|
300 |
# response = self.list_containers('non-existing-account') |
|
301 |
# self.assertEqual(response.status_code, 204) |
|
328 |
def test_list_401(self): |
|
329 |
self.assert_raises_fault(401, self.invalid_client.list_containers) |
|
302 | 330 |
|
303 | 331 |
def test_list_with_limit(self): |
304 | 332 |
limit = 2 |
... | ... | |
318 | 346 |
i = self.containers.index(m) + 1 |
319 | 347 |
self.assertEquals(self.containers[i:(i+l)], containers) |
320 | 348 |
|
321 |
#def test_extended_list(self): |
|
322 |
# self.list_containers(self.account, limit=3, format='xml') |
|
323 |
# self.list_containers(self.account, limit=3, format='json') |
|
324 |
|
|
325 | 349 |
def test_list_json_with_marker(self): |
326 | 350 |
l = 2 |
327 | 351 |
m = 'bananas' |
328 |
containers = self.client.list_containers(limit=l, marker=m, detail=True) |
|
352 |
containers = self.client.list_containers(limit=l, marker=m, format='json') |
|
353 |
self.assert_extended(containers, 'json', 'container', l) |
|
329 | 354 |
self.assertEqual(containers[0]['name'], 'kiwis') |
330 | 355 |
self.assertEqual(containers[1]['name'], 'oranges') |
331 | 356 |
|
332 |
#def test_list_xml_with_marker(self): |
|
333 |
# l = 2 |
|
334 |
# m = 'oranges' |
|
335 |
# status, headers, xml = self.list_containers(limit=l, marker=m, format='xml') |
|
336 |
# nodes = xml.getElementsByTagName('name') |
|
337 |
# self.assertEqual(len(nodes), 1) |
|
338 |
# self.assertEqual(nodes[0].childNodes[0].data, 'pears') |
|
357 |
def test_list_xml_with_marker(self): |
|
358 |
l = 2 |
|
359 |
m = 'oranges' |
|
360 |
xml = self.client.list_containers(limit=l, marker=m, format='xml') |
|
361 |
#self.assert_extended(xml, 'xml', 'container', l) |
|
362 |
nodes = xml.getElementsByTagName('name') |
|
363 |
self.assertEqual(len(nodes), 1) |
|
364 |
self.assertEqual(nodes[0].childNodes[0].data, 'pears') |
|
339 | 365 |
|
340 | 366 |
def test_if_modified_since(self): |
341 | 367 |
t = datetime.datetime.utcnow() |
... | ... | |
404 | 430 |
self.client.update_account_metadata(**meta) |
405 | 431 |
self.assertEqual(meta, self.client.retrieve_account_metadata(restricted=True)) |
406 | 432 |
|
407 |
#def test_invalid_account_update_meta(self): |
|
408 |
# with AssertMappingInvariant(self.get_account_meta, self.account): |
|
409 |
# meta = {'HTTP_X_ACCOUNT_META_TEST':'test', |
|
410 |
# 'HTTP_X_ACCOUNT_META_TOST':'tost'} |
|
411 |
# response = self.update_account_meta('non-existing-account', **meta) |
|
433 |
def test_invalid_account_update_meta(self): |
|
434 |
meta = {'HTTP_X_ACCOUNT_META_TEST':'test', |
|
435 |
'HTTP_X_ACCOUNT_META_TOST':'tost'} |
|
436 |
self.assert_raises_fault(401, |
|
437 |
self.invalid_client.update_account_metadata, |
|
438 |
**meta) |
|
412 | 439 |
|
413 | 440 |
class ContainerHead(BaseTestCase): |
414 | 441 |
def setUp(self): |
... | ... | |
486 | 513 |
self.assertEquals(['photos/me.jpg'], objects) |
487 | 514 |
|
488 | 515 |
def test_extended_list_json(self): |
489 |
objects = self.client.list_objects(self.container[1], detail=True,
|
|
516 |
objects = self.client.list_objects(self.container[1], format='json',
|
|
490 | 517 |
limit=2, prefix='photos/animals', |
491 | 518 |
delimiter='/') |
492 | 519 |
self.assertEqual(objects[0]['subdir'], 'photos/animals/cats/') |
493 | 520 |
self.assertEqual(objects[1]['subdir'], 'photos/animals/dogs/') |
494 | 521 |
|
495 |
#def test_extended_list_xml(self):
|
|
496 |
# xml = self.client.list_objects(self.container[1], format='xml', limit=4,
|
|
497 |
# prefix='photos', delimiter='/')
|
|
498 |
# dirs = xml.getElementsByTagName('subdir')
|
|
499 |
# self.assertEqual(len(dirs), 2)
|
|
500 |
# self.assertEqual(dirs[0].attributes['name'].value, 'photos/animals/')
|
|
501 |
# self.assertEqual(dirs[1].attributes['name'].value, 'photos/plants/')
|
|
502 |
# |
|
503 |
# objects = xml.getElementsByTagName('name')
|
|
504 |
# self.assertEqual(len(objects), 1)
|
|
505 |
# self.assertEqual(objects[0].childNodes[0].data, 'photos/me.jpg')
|
|
522 |
def test_extended_list_xml(self): |
|
523 |
xml = self.client.list_objects(self.container[1], format='xml', limit=4, |
|
524 |
prefix='photos', delimiter='/') |
|
525 |
dirs = xml.getElementsByTagName('subdir') |
|
526 |
self.assertEqual(len(dirs), 2) |
|
527 |
self.assertEqual(dirs[0].attributes['name'].value, 'photos/animals/') |
|
528 |
self.assertEqual(dirs[1].attributes['name'].value, 'photos/plants/') |
|
529 |
|
|
530 |
objects = xml.getElementsByTagName('name') |
|
531 |
self.assertEqual(len(objects), 1) |
|
532 |
self.assertEqual(objects[0].childNodes[0].data, 'photos/me.jpg') |
|
506 | 533 |
|
507 | 534 |
def test_list_meta_double_matching(self): |
508 | 535 |
meta = {'quality':'aaa', 'stock':'true'} |
... | ... | |
978 | 1005 |
fname = 'largefile' |
979 | 1006 |
o = self.upload_random_data(self.containers[1], fname, l) |
980 | 1007 |
if o: |
981 |
data = self.client.retrieve_object(self.containers[1], fname, detail=True) |
|
1008 |
data = self.client.retrieve_object(self.containers[1], fname, |
|
1009 |
format='json') |
|
982 | 1010 |
body = json.loads(data) |
983 | 1011 |
hashes = body['hashes'] |
984 | 1012 |
block_size = body['block_size'] |
... | ... | |
1026 | 1054 |
self.assert_raises_fault(422, self.upload_random_data, self.container, |
1027 | 1055 |
o_names[0], **meta) |
1028 | 1056 |
|
1029 |
def test_chucked_transfer(self):
|
|
1057 |
def test_chunked_transfer(self):
|
|
1030 | 1058 |
data = get_random_data() |
1031 | 1059 |
objname = 'object' |
1032 | 1060 |
self.client.create_object_using_chunks(self.container, objname, |
... | ... | |
1197 | 1225 |
self.containers[0], self.obj['name']): |
1198 | 1226 |
self.test_update_object(499, 0, True) |
1199 | 1227 |
|
1200 |
#no use if the server resets the content-legth |
|
1201 | 1228 |
def test_update_object_invalid_range_and_length(self): |
1202 | 1229 |
with AssertContentInvariant(self.client.retrieve_object, |
1203 | 1230 |
self.containers[0], self.obj['name']): |
1204 | 1231 |
self.test_update_object(499, 0, True, -1) |
1205 | 1232 |
|
1206 |
#no use if the server resets the content-legth |
|
1207 | 1233 |
def test_update_object_invalid_range_with_no_content_length(self): |
1208 | 1234 |
with AssertContentInvariant(self.client.retrieve_object, |
1209 | 1235 |
self.containers[0], self.obj['name']): |
b/pithos/lib/client.py | ||
---|---|---|
33 | 33 |
|
34 | 34 |
from httplib import HTTPConnection, HTTP |
35 | 35 |
from sys import stdin |
36 |
from xml.dom import minidom |
|
36 | 37 |
|
37 | 38 |
import json |
38 | 39 |
import types |
... | ... | |
93 | 94 |
kwargs['headers']['X-Auth-Token'] = self.token |
94 | 95 |
if body: |
95 | 96 |
kwargs['body'] = body |
96 |
else:
|
|
97 |
elif 'content-type' not in kwargs['headers']:
|
|
97 | 98 |
kwargs['headers']['content-type'] = '' |
98 | 99 |
kwargs['headers'].setdefault('content-length', len(body) if body else 0) |
99 | 100 |
kwargs['headers'].setdefault('content-type', 'application/octet-stream') |
... | ... | |
141 | 142 |
def put(self, path, body=None, format='text', headers=None): |
142 | 143 |
return self._req('PUT', path, body, headers=headers, format=format) |
143 | 144 |
|
144 |
def _list(self, path, detail=False, params={}, **headers): |
|
145 |
format = 'json' if detail else 'text' |
|
145 |
def _list(self, path, format='text', params={}, **headers): |
|
146 | 146 |
status, headers, data = self.get(path, format=format, headers=headers, |
147 | 147 |
params=params) |
148 |
if detail:
|
|
148 |
if format == 'json':
|
|
149 | 149 |
data = json.loads(data) if data else '' |
150 |
elif format == 'xml': |
|
151 |
print '#', data |
|
152 |
data = minidom.parseString(data) |
|
150 | 153 |
else: |
151 | 154 |
data = data.strip().split('\n') if data else '' |
152 | 155 |
return data |
... | ... | |
178 | 181 |
return ll |
179 | 182 |
|
180 | 183 |
class OOS_Client(Client): |
181 |
"""Openstack Objest Storage Client"""
|
|
184 |
"""Openstack Object Storage Client"""
|
|
182 | 185 |
|
183 | 186 |
def _update_metadata(self, path, entity, **meta): |
184 | 187 |
"""adds new and updates the values of previously set metadata""" |
... | ... | |
203 | 206 |
|
204 | 207 |
# Storage Account Services |
205 | 208 |
|
206 |
def list_containers(self, detail=False, limit=10000, marker=None, params={},
|
|
209 |
def list_containers(self, format='text', limit=10000, marker=None, params={},
|
|
207 | 210 |
**headers): |
208 | 211 |
"""lists containers""" |
209 | 212 |
if not params: |
210 | 213 |
params = {} |
211 | 214 |
params.update({'limit':limit, 'marker':marker}) |
212 |
return self._list('', detail, params, **headers)
|
|
215 |
return self._list('', format, params, **headers)
|
|
213 | 216 |
|
214 | 217 |
def retrieve_account_metadata(self, restricted=False, **params): |
215 | 218 |
"""returns the account metadata""" |
... | ... | |
229 | 232 |
def _filter_trashed(self, l): |
230 | 233 |
return self._filter(l, {'trash':'true'}) |
231 | 234 |
|
232 |
def list_objects(self, container, detail=False, limit=10000, marker=None,
|
|
235 |
def list_objects(self, container, format='text', limit=10000, marker=None,
|
|
233 | 236 |
prefix=None, delimiter=None, path=None, |
234 | 237 |
include_trashed=False, params={}, **headers): |
235 | 238 |
"""returns a list with the container objects""" |
236 | 239 |
params.update({'limit':limit, 'marker':marker, 'prefix':prefix, |
237 | 240 |
'delimiter':delimiter, 'path':path}) |
238 |
l = self._list('/' + container, detail, params, **headers) |
|
239 |
if not include_trashed: |
|
241 |
l = self._list('/' + container, format, params, **headers) |
|
242 |
#TODO support filter trashed with xml also |
|
243 |
if format != 'xml' and not include_trashed: |
|
240 | 244 |
l = self._filter_trashed(l) |
241 | 245 |
return l |
242 | 246 |
|
... | ... | |
272 | 276 |
|
273 | 277 |
# Storage Object Services |
274 | 278 |
|
275 |
def request_object(self, container, object, detail=False, params={},
|
|
279 |
def request_object(self, container, object, format='text', params={},
|
|
276 | 280 |
**headers): |
277 | 281 |
"""returns tuple containing the status, headers and data response for an object request""" |
278 | 282 |
path = '/%s/%s' % (container, object) |
279 |
format = 'json' if detail else 'text' |
|
280 | 283 |
status, headers, data = self.get(path, format, headers, params) |
281 | 284 |
return status, headers, data |
282 | 285 |
|
283 |
def retrieve_object(self, container, object, detail=False, params={},
|
|
286 |
def retrieve_object(self, container, object, format='text', params={},
|
|
284 | 287 |
**headers): |
285 | 288 |
"""returns an object's data""" |
286 |
t = self.request_object(container, object, detail, params, **headers)
|
|
289 |
t = self.request_object(container, object, format, params, **headers)
|
|
287 | 290 |
return t[2] |
288 | 291 |
|
289 | 292 |
def create_directory_marker(self, container, object): |
... | ... | |
469 | 472 |
headers = {} |
470 | 473 |
prefix = 'x-%s-meta-' % entity |
471 | 474 |
for m in meta: |
472 |
headers['%s%s' % (prefix, m)] = None
|
|
475 |
headers['%s%s' % (prefix, m)] = ''
|
|
473 | 476 |
return self.post(path, headers=headers, params=params) |
474 | 477 |
|
475 | 478 |
# Storage Account Services |
476 | 479 |
|
477 |
def list_containers(self, detail=False, if_modified_since=None,
|
|
480 |
def list_containers(self, format='text', if_modified_since=None,
|
|
478 | 481 |
if_unmodified_since=None, limit=1000, marker=None, |
479 | 482 |
until=None): |
480 | 483 |
"""returns a list with the account containers""" |
481 | 484 |
params = {'until':until} if until else None |
482 | 485 |
headers = {'if-modified-since':if_modified_since, |
483 | 486 |
'if-unmodified-since':if_unmodified_since} |
484 |
return OOS_Client.list_containers(self, detail=detail, limit=limit,
|
|
487 |
return OOS_Client.list_containers(self, format=format, limit=limit,
|
|
485 | 488 |
marker=marker, params=params, |
486 | 489 |
**headers) |
487 | 490 |
|
... | ... | |
509 | 512 |
|
510 | 513 |
# Storage Container Services |
511 | 514 |
|
512 |
def list_objects(self, container, detail=False, limit=10000, marker=None,
|
|
515 |
def list_objects(self, container, format='text', limit=10000, marker=None,
|
|
513 | 516 |
prefix=None, delimiter=None, path=None, |
514 | 517 |
include_trashed=False, params={}, if_modified_since=None, |
515 | 518 |
if_unmodified_since=None, meta={}, until=None): |
... | ... | |
545 | 548 |
|
546 | 549 |
# Storage Object Services |
547 | 550 |
|
548 |
def retrieve_object(self, container, object, params={}, detail=False, range=None,
|
|
551 |
def retrieve_object(self, container, object, params={}, format='text', range=None,
|
|
549 | 552 |
if_range=None, if_match=None, if_none_match=None, |
550 | 553 |
if_modified_since=None, if_unmodified_since=None, |
551 | 554 |
**headers): |
... | ... | |
556 | 559 |
l = [elem for elem in l if eval(elem)] |
557 | 560 |
for elem in l: |
558 | 561 |
headers.update({elem:eval(elem)}) |
559 |
return OOS_Client.retrieve_object(self, container, object, detail=detail,
|
|
562 |
return OOS_Client.retrieve_object(self, container, object, format=format,
|
|
560 | 563 |
params=params, **headers) |
561 | 564 |
|
562 | 565 |
def retrieve_object_version(self, container, object, version, detail=False, |
b/pithos/test-settings.py | ||
---|---|---|
60 | 60 |
|
61 | 61 |
# The backend to use and its initilization options. |
62 | 62 |
if TEST: |
63 |
BACKEND = ('SimpleBackend', (os.path.join(PROJECT_PATH, 'data/testpithos.db'),))
|
|
63 |
BACKEND = ('SimpleBackend', (os.path.join(PROJECT_PATH, 'data/test/'),))
|
|
64 | 64 |
else: |
65 |
BACKEND = ('SimpleBackend', (os.path.join(PROJECT_PATH, 'data/pithos.db'),))
|
|
65 |
BACKEND = ('SimpleBackend', (os.path.join(PROJECT_PATH, 'data/pithos/'),))
|
|
66 | 66 |
|
67 | 67 |
# Local time zone for this installation. Choices can be found here: |
68 | 68 |
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name |
... | ... | |
149 | 149 |
'0004': 'papagian', |
150 | 150 |
'0005': 'louridas', |
151 | 151 |
'0006': 'chstath', |
152 |
'0007': 'pkanavos'} |
|
152 |
'0007': 'pkanavos', |
|
153 |
'0008': 'mvasilak'} |
b/tools/store | ||
---|---|---|
143 | 143 |
dest='if_unmodified_since', default=None, |
144 | 144 |
help='show output if not modified since then') |
145 | 145 |
parser.add_option('--until', action='store', dest='until', |
146 |
default=False, help='show metadata until that date')
|
|
146 |
default=None, help='show metadata until that date')
|
|
147 | 147 |
parser.add_option('--format', action='store', dest='format', |
148 | 148 |
default='%d/%m/%Y', help='format to parse until date') |
149 | 149 |
|
... | ... | |
154 | 154 |
self.list_containers() |
155 | 155 |
|
156 | 156 |
def list_containers(self): |
157 |
attrs = ['detail', 'limit', 'marker', 'if_modified_since',
|
|
157 |
attrs = ['limit', 'marker', 'if_modified_since', |
|
158 | 158 |
'if_unmodified_since'] |
159 | 159 |
args = self._build_args(attrs) |
160 |
args['format'] = 'json' if self.detail else 'text' |
|
160 | 161 |
|
161 |
if self.until:
|
|
162 |
if getattr(self, 'until'):
|
|
162 | 163 |
t = _time.strptime(self.until, self.format) |
163 | 164 |
args['until'] = int(_time.mktime(t)) |
164 | 165 |
|
... | ... | |
168 | 169 |
def list_objects(self, container): |
169 | 170 |
#prepate params |
170 | 171 |
params = {} |
171 |
attrs = ['detail', 'limit', 'marker', 'prefix', 'delimiter', 'path',
|
|
172 |
attrs = ['limit', 'marker', 'prefix', 'delimiter', 'path', |
|
172 | 173 |
'meta', 'if_modified_since', 'if_unmodified_since'] |
173 | 174 |
args = self._build_args(attrs) |
175 |
args['format'] = 'json' if self.detail else 'text' |
|
174 | 176 |
|
175 | 177 |
if self.until: |
176 | 178 |
t = _time.strptime(self.until, self.format) |
... | ... | |
195 | 197 |
parser.add_option('-r', action='store_true', dest='restricted', |
196 | 198 |
default=False, help='show only user defined metadata') |
197 | 199 |
parser.add_option('--until', action='store', dest='until', |
198 |
default=False, help='show metadata until that date')
|
|
200 |
default=None, help='show metadata until that date')
|
|
199 | 201 |
parser.add_option('--format', action='store', dest='format', |
200 | 202 |
default='%d/%m/%Y', help='format to parse until date') |
201 | 203 |
parser.add_option('--version', action='store', dest='version', |
... | ... | |
205 | 207 |
def execute(self, path=''): |
206 | 208 |
container, sep, object = path.partition('/') |
207 | 209 |
args = {'restricted':self.restricted} |
208 |
if self.until:
|
|
210 |
if getattr(self, 'until'):
|
|
209 | 211 |
t = _time.strptime(self.until, self.format) |
210 | 212 |
args['until'] = int(_time.mktime(t)) |
211 | 213 |
|
... | ... | |
243 | 245 |
|
244 | 246 |
def add_options(self, parser): |
245 | 247 |
parser.add_option('--until', action='store', dest='until', |
246 |
default=False, help='remove history until that date')
|
|
248 |
default=None, help='remove history until that date')
|
|
247 | 249 |
parser.add_option('--format', action='store', dest='format', |
248 | 250 |
default='%d/%m/%Y', help='format to parse until date') |
249 | 251 |
|
250 | 252 |
def execute(self, path): |
251 | 253 |
container, sep, object = path.partition('/') |
252 |
if self.until: |
|
254 |
until = None |
|
255 |
if getattr(self, 'until'): |
|
253 | 256 |
t = _time.strptime(self.until, self.format) |
254 | 257 |
until = int(_time.mktime(t)) |
255 | 258 |
|
... | ... | |
293 | 296 |
help='get the full object version list') |
294 | 297 |
|
295 | 298 |
def execute(self, path): |
296 |
attrs = ['detail', 'if_match', 'if_none_match', 'if_modified_since',
|
|
299 |
attrs = ['if_match', 'if_none_match', 'if_modified_since', |
|
297 | 300 |
'if_unmodified_since'] |
298 | 301 |
args = self._build_args(attrs) |
299 |
|
|
302 |
args['format'] = 'json' if self.detail else 'text' |
|
300 | 303 |
if self.range: |
301 | 304 |
args['range'] = 'bytes=%s' %self.range |
302 | 305 |
if getattr(self, 'if_range'): |
Also available in: Unified diff