Revision ae75584f
b/pithos/api/tests.py | ||
---|---|---|
1 |
#coding=utf8 |
|
2 |
|
|
1 | 3 |
# Copyright 2011 GRNET S.A. All rights reserved. |
2 | 4 |
# |
3 | 5 |
# Redistribution and use in source and binary forms, with or |
... | ... | |
56 | 58 |
DEFAULT_USER = 'test' |
57 | 59 |
DEFAULT_AUTH = '0000' |
58 | 60 |
|
61 |
OTHER_ACCOUNTS = { |
|
62 |
'0001': 'verigak', |
|
63 |
'0002': 'chazapis', |
|
64 |
'0003': 'gtsouk', |
|
65 |
'0004': 'papagian', |
|
66 |
'0005': 'louridas', |
|
67 |
'0006': 'chstath', |
|
68 |
'0007': 'pkanavos', |
|
69 |
'0008': 'mvasilak'} |
|
70 |
|
|
59 | 71 |
class BaseTestCase(unittest.TestCase): |
60 | 72 |
#TODO unauthorized request |
61 | 73 |
def setUp(self): |
... | ... | |
110 | 122 |
'name', |
111 | 123 |
'count', |
112 | 124 |
'bytes', |
113 |
'last_modified'), |
|
125 |
'last_modified', |
|
126 |
'x_container_policy_quota', |
|
127 |
'x_container_policy_versioning',), |
|
114 | 128 |
'object':( |
115 | 129 |
'name', |
116 | 130 |
'hash', |
... | ... | |
122 | 136 |
|
123 | 137 |
def tearDown(self): |
124 | 138 |
for c in self.client.list_containers(): |
125 |
for o in self.client.list_objects(c): |
|
126 |
self.client.delete_object(c, o) |
|
139 |
while True: |
|
140 |
#list objects returns at most 10000 objects |
|
141 |
#so repeat until there are no more objects |
|
142 |
objects = self.client.list_objects(c) |
|
143 |
if not objects: |
|
144 |
break |
|
145 |
for o in objects: |
|
146 |
self.client.delete_object(c, o) |
|
127 | 147 |
self.client.delete_container(c) |
128 | 148 |
|
129 | 149 |
def assert_status(self, status, codes): |
... | ... | |
134 | 154 |
l.append(codes) |
135 | 155 |
self.assertTrue(status in l) |
136 | 156 |
|
137 |
#def assert_list(self, path, entity, limit=10000, format='text', params=None, **headers): |
|
138 |
# status, headers, data = self.client.get(path, format=format, |
|
139 |
# headers=headers, params=params) |
|
140 |
# |
|
141 |
# self.assert_status(status, [200, 204, 304, 412]) |
|
142 |
# if format == 'text': |
|
143 |
# data = data.strip().split('\n') if data else [] |
|
144 |
# self.assertTrue(len(data) <= limit) |
|
145 |
# else: |
|
146 |
# exp_content_type = self.contentTypes[format] |
|
147 |
# self.assertEqual(headers['content_type'].find(exp_content_type), 0) |
|
148 |
# #self.assert_extended(data, format, entity, limit) |
|
149 |
# if format == 'json': |
|
150 |
# data = json.loads(data) if data else [] |
|
151 |
# elif format == 'xml': |
|
152 |
# data = minidom.parseString(data) |
|
153 |
# return status, headers, data |
|
154 |
|
|
155 | 157 |
#def assert_headers(self, headers, type, **exp_meta): |
156 | 158 |
# prefix = 'x-%s-meta-' %type |
157 | 159 |
# system_headers = [h for h in headers if not h.startswith(prefix)] |
... | ... | |
162 | 164 |
# k = k.split(prefix)[-1] |
163 | 165 |
# self.assertEqual(v, exp_meta[k]) |
164 | 166 |
|
165 |
def assert_extended(self, data, format, type, size): |
|
167 |
def assert_extended(self, data, format, type, size=10000):
|
|
166 | 168 |
if format == 'xml': |
167 | 169 |
self._assert_xml(data, type, size) |
168 | 170 |
elif format == 'json': |
... | ... | |
190 | 192 |
self.assertTrue(len(entities) <= size) |
191 | 193 |
for e in entities: |
192 | 194 |
for item in info: |
193 |
self.assertTrue(e.hasAttribute(item))
|
|
195 |
self.assertTrue(e.getElementsByTagName(item))
|
|
194 | 196 |
|
195 | 197 |
def assert_raises_fault(self, status, callableObj, *args, **kwargs): |
196 | 198 |
""" |
... | ... | |
198 | 200 |
when callableObj is called with the specific arguments |
199 | 201 |
""" |
200 | 202 |
try: |
201 |
callableObj(*args, **kwargs) |
|
203 |
r = callableObj(*args, **kwargs)
|
|
202 | 204 |
self.fail('Should never reach here') |
203 | 205 |
except Fault, f: |
204 | 206 |
self.failUnless(f.status == status) |
... | ... | |
244 | 246 |
args = {} |
245 | 247 |
args['etag'] = etag if etag else obj['hash'] |
246 | 248 |
|
247 |
guess = mimetypes.guess_type(name) |
|
248 |
type = type if type else guess[0] |
|
249 |
enc = enc if enc else guess[1] |
|
249 |
try: |
|
250 |
guess = mimetypes.guess_type(name) |
|
251 |
type = type if type else guess[0] |
|
252 |
enc = enc if enc else guess[1] |
|
253 |
except: |
|
254 |
pass |
|
250 | 255 |
args['content_type'] = type if type else 'plain/text' |
251 | 256 |
args['content_encoding'] = enc if enc else None |
252 | 257 |
|
... | ... | |
259 | 264 |
return obj |
260 | 265 |
except IOError: |
261 | 266 |
return |
267 |
class TopLevel(BaseTestCase): |
|
268 |
def test_list_shared_by_other(self): |
|
269 |
pass |
|
262 | 270 |
|
263 | 271 |
class AccountHead(BaseTestCase): |
264 | 272 |
def setUp(self): |
... | ... | |
333 | 341 |
meta = self.client.retrieve_account_metadata(restricted=True, |
334 | 342 |
until='kshfksfh') |
335 | 343 |
self.assertTrue('premium' in meta) |
336 |
|
|
344 |
|
|
337 | 345 |
class AccountGet(BaseTestCase): |
338 | 346 |
def setUp(self): |
339 | 347 |
BaseTestCase.setUp(self) |
... | ... | |
381 | 389 |
l = 2 |
382 | 390 |
m = 'oranges' |
383 | 391 |
xml = self.client.list_containers(limit=l, marker=m, format='xml') |
384 |
#self.assert_extended(xml, 'xml', 'container', l)
|
|
392 |
self.assert_extended(xml, 'xml', 'container', l) |
|
385 | 393 |
nodes = xml.getElementsByTagName('name') |
386 | 394 |
self.assertEqual(len(nodes), 1) |
387 | 395 |
self.assertEqual(nodes[0].childNodes[0].data, 'pears') |
... | ... | |
591 | 599 |
l.sort() |
592 | 600 |
self.assertEqual(objects, l) |
593 | 601 |
|
602 |
def test_list_objects_containing_slash(self): |
|
603 |
self.client.create_container('test') |
|
604 |
self.upload_random_data('test', '/objectname') |
|
605 |
|
|
606 |
objects = self.client.list_objects('test') |
|
607 |
self.assertEqual(objects, ['/objectname']) |
|
608 |
|
|
609 |
objects = self.client.list_objects('test', format='json') |
|
610 |
self.assertEqual(objects[0]['name'], '/objectname') |
|
611 |
|
|
612 |
objects = self.client.list_objects('test', format='xml') |
|
613 |
self.assert_extended(objects, 'xml', 'object') |
|
614 |
node_name = objects.getElementsByTagName('name')[0] |
|
615 |
self.assertEqual(node_name.firstChild.data, '/objectname') |
|
616 |
|
|
617 |
#objects = self.client.list_objects('test', prefix='/') |
|
618 |
#self.assertEqual(objects, ['/objectname']) |
|
619 |
# |
|
620 |
#objects = self.client.list_objects('test', path='/') |
|
621 |
#self.assertEqual(objects, ['/objectname']) |
|
622 |
# |
|
623 |
#objects = self.client.list_objects('test', prefix='/', delimiter='n') |
|
624 |
#self.assertEqual(objects, ['/object']) |
|
625 |
|
|
594 | 626 |
def test_list_objects_with_limit_marker(self): |
595 | 627 |
objects = self.client.list_objects(self.container[0], limit=2) |
596 | 628 |
l = [elem['name'] for elem in self.obj[:8]] |
... | ... | |
610 | 642 |
end = len(l) >= end and end or len(l) |
611 | 643 |
self.assertEqual(objects, l[start:end]) |
612 | 644 |
|
645 |
#takes too long |
|
646 |
#def test_list_limit_exceeds(self): |
|
647 |
# self.client.create_container('pithos') |
|
648 |
# |
|
649 |
# for i in range(10001): |
|
650 |
# self.client.create_zero_length_object('pithos', i) |
|
651 |
# |
|
652 |
# self.assertEqual(10000, len(self.client.list_objects('pithos'))) |
|
653 |
|
|
654 |
def test_list_empty_params(self): |
|
655 |
objects = self.client.get('/%s' % self.container[0])[2] |
|
656 |
if objects: |
|
657 |
objects = objects.strip().split('\n') |
|
658 |
self.assertEqual(objects, |
|
659 |
self.client.list_objects(self.container[0])) |
|
660 |
|
|
613 | 661 |
def test_list_pseudo_hierarchical_folders(self): |
614 | 662 |
objects = self.client.list_objects(self.container[1], prefix='photos', |
615 | 663 |
delimiter='/') |
... | ... | |
635 | 683 |
def test_extended_list_xml(self): |
636 | 684 |
xml = self.client.list_objects(self.container[1], format='xml', limit=4, |
637 | 685 |
prefix='photos', delimiter='/') |
686 |
self.assert_extended(xml, 'xml', 'object', size=4) |
|
638 | 687 |
dirs = xml.getElementsByTagName('subdir') |
639 | 688 |
self.assertEqual(len(dirs), 2) |
640 | 689 |
self.assertEqual(dirs[0].attributes['name'].value, 'photos/animals/') |
... | ... | |
1160 | 1209 |
#assert content-type |
1161 | 1210 |
self.assertEqual(h['content-type'], o['meta']['content_type']) |
1162 | 1211 |
|
1212 |
def test_maximum_upload_size_exceeds(self): |
|
1213 |
name = o_names[0] |
|
1214 |
meta = {'test':'test1'} |
|
1215 |
#upload 100MB |
|
1216 |
length=1024*1024*100 |
|
1217 |
self.assert_raises_fault(400, self.upload_random_data, self.container, |
|
1218 |
name, length, **meta) |
|
1219 |
|
|
1220 |
##d = get_random_data(length=1024*1024*100) |
|
1221 |
##self.client.create_object_using_chunks(self.container, name, StringIO(d)) |
|
1222 |
|
|
1223 |
|
|
1163 | 1224 |
def test_upload_with_name_containing_slash(self): |
1164 | 1225 |
name = '/%s' % o_names[0] |
1165 | 1226 |
meta = {'test':'test1'} |
... | ... | |
1191 | 1252 |
|
1192 | 1253 |
uploaded_data = self.client.retrieve_object(self.container, objname) |
1193 | 1254 |
self.assertEqual(data, uploaded_data) |
1194 |
|
|
1255 |
|
|
1256 |
def test_manifestation(self): |
|
1257 |
prefix = 'myobject/' |
|
1258 |
data = '' |
|
1259 |
for i in range(5): |
|
1260 |
part = '%s%d' %(prefix, i) |
|
1261 |
o = self.upload_random_data(self.container, part) |
|
1262 |
data += o['data'] |
|
1263 |
|
|
1264 |
manifest = '%s/%s' %(self.container, prefix) |
|
1265 |
self.client.create_manifestation(self.container, 'large-object', |
|
1266 |
manifest) |
|
1267 |
|
|
1268 |
self.assert_object_exists(self.container, 'large-object') |
|
1269 |
self.assertEqual(data, self.client.retrieve_object(self.container, |
|
1270 |
'large-object')) |
|
1271 |
|
|
1272 |
#wrong manifestation |
|
1273 |
self.client.create_manifestation(self.container, 'large-object', |
|
1274 |
'invalid') |
|
1275 |
|
|
1195 | 1276 |
class ObjectCopy(BaseTestCase): |
1196 | 1277 |
def setUp(self): |
1197 | 1278 |
BaseTestCase.setUp(self) |
... | ... | |
1201 | 1282 |
self.client.create_container(c) |
1202 | 1283 |
self.obj = self.upload_random_data(self.containers[0], o_names[0]) |
1203 | 1284 |
|
1285 |
def tearDown(self): |
|
1286 |
pass |
|
1287 |
|
|
1204 | 1288 |
def test_copy(self): |
1205 | 1289 |
with AssertMappingInvariant(self.client.retrieve_object_metadata, |
1206 | 1290 |
self.containers[0], self.obj['name']): |
... | ... | |
1259 | 1343 |
self.assert_raises_fault(404, self.client.copy_object, self.containers[1], |
1260 | 1344 |
self.obj['name'], self.containers[1], |
1261 | 1345 |
'testcopy', meta) |
1262 |
|
|
1263 | 1346 |
|
1264 | 1347 |
class ObjectMove(BaseTestCase): |
1265 | 1348 |
def setUp(self): |
... | ... | |
1426 | 1509 |
self.assert_raises_fault(404, self.client.delete_object, self.containers[1], |
1427 | 1510 |
self.obj['name']) |
1428 | 1511 |
|
1512 |
class ListSharing(BaseTestCase): |
|
1513 |
def setUp(self): |
|
1514 |
BaseTestCase.setUp(self) |
|
1515 |
self.client.create_container('c') |
|
1516 |
for i in range(2): |
|
1517 |
self.upload_random_data('c', 'o%s' %i) |
|
1518 |
accounts = OTHER_ACCOUNTS.copy() |
|
1519 |
self.o1_sharing_with = accounts.popitem() |
|
1520 |
self.o1_sharing = [self.o1_sharing_with[1]] |
|
1521 |
self.client.share_object('c', 'o1', self.o1_sharing, read=True) |
|
1522 |
|
|
1523 |
l = [] |
|
1524 |
for i in range(2): |
|
1525 |
l.append(accounts.popitem()) |
|
1526 |
#self.client.set_account_groups({'pithos-dev':'chazapis,verigak,papagian'}) |
|
1527 |
#self.o2_sharing = 'write=%s' % |
|
1528 |
#self.client.share_object('c', 'o2', self.o2_sharing) |
|
1529 |
|
|
1530 |
def test_listing(self): |
|
1531 |
self.other = Pithos_Client(DEFAULT_HOST, |
|
1532 |
self.o1_sharing_with[0], |
|
1533 |
self.o1_sharing_with[1], |
|
1534 |
DEFAULT_API) |
|
1535 |
self.assertTrue('test' in self.other.list_shared_by_others()) |
|
1536 |
|
|
1537 |
class TestGreek(BaseTestCase): |
|
1538 |
def tearDown(self): |
|
1539 |
pass |
|
1540 |
|
|
1541 |
def test_create_container(self): |
|
1542 |
self.client.create_container('φάκελος') |
|
1543 |
self.assert_container_exists('φάκελος') |
|
1544 |
|
|
1545 |
def test_create_object(self): |
|
1546 |
self.client.create_container('φάκελος') |
|
1547 |
self.upload_random_data('φάκελος', 'αντικείμενο') |
|
1548 |
|
|
1549 |
self.assert_object_exists('φάκελος', 'αντικείμενο') |
|
1550 |
|
|
1551 |
def test_copy_object(self): |
|
1552 |
self.client.create_container('φάκελος') |
|
1553 |
self.upload_random_data('φάκελος', 'αντικείμενο') |
|
1554 |
|
|
1555 |
self.client.create_container('αντίγραφα') |
|
1556 |
self.client.copy_object('φάκελος', 'αντικείμενο', 'αντίγραφα', |
|
1557 |
'αντικείμενο') |
|
1558 |
|
|
1559 |
self.assert_object_exists('αντίγραφα', 'αντικείμενο') |
|
1560 |
self.assert_object_exists('φάκελος', 'αντικείμενο') |
|
1561 |
|
|
1562 |
def test_move_object(self): |
|
1563 |
self.client.create_container('φάκελος') |
|
1564 |
self.upload_random_data('φάκελος', 'αντικείμενο') |
|
1565 |
|
|
1566 |
self.client.create_container('αντίγραφα') |
|
1567 |
self.client.copy_object('φάκελος', 'αντικείμενο', 'αντίγραφα', |
|
1568 |
'αντικείμενο') |
|
1569 |
|
|
1570 |
self.assert_object_exists('αντίγραφα', 'αντικείμενο') |
|
1571 |
self.assert_object_not_exists('φάκελος', 'αντικείμενο') |
|
1572 |
|
|
1573 |
def test_delete_object(self): |
|
1574 |
pass |
|
1575 |
|
|
1576 |
def test_delete_container(self): |
|
1577 |
pass |
|
1578 |
|
|
1579 |
def test_account_meta(self): |
|
1580 |
pass |
|
1581 |
|
|
1582 |
def test_container_meta(self): |
|
1583 |
pass |
|
1584 |
|
|
1585 |
def test_obejct_meta(self): |
|
1586 |
pass |
|
1587 |
|
|
1588 |
def test_list_meta_filtering(self): |
|
1589 |
pass |
|
1590 |
|
|
1591 |
def test_groups(self): |
|
1592 |
pass |
|
1593 |
|
|
1594 |
def test_permissions(self): |
|
1595 |
pass |
|
1596 |
|
|
1429 | 1597 |
class AssertMappingInvariant(object): |
1430 | 1598 |
def __init__(self, callable, *args, **kwargs): |
1431 | 1599 |
self.callable = callable |
b/pithos/lib/client.py | ||
---|---|---|
38 | 38 |
import json |
39 | 39 |
import types |
40 | 40 |
import socket |
41 |
import urllib |
|
41 | 42 |
import pithos.api.faults |
42 | 43 |
|
43 | 44 |
ERROR_CODES = {304:'Not Modified', |
... | ... | |
71 | 72 |
self.token = token |
72 | 73 |
|
73 | 74 |
def _req(self, method, path, body=None, headers={}, format='text', |
74 |
params={}): |
|
75 |
full_path = '/%s/%s%s?format=%s' % (self.api, self.account, path, |
|
76 |
format) |
|
75 |
params={}, top_level_req=False): |
|
76 |
path = urllib.quote(path) |
|
77 |
account = '' if top_level_req else self.account |
|
78 |
full_path = '/%s/%s%s?format=%s' % (self.api, account, path, format) |
|
79 |
|
|
77 | 80 |
for k,v in params.items(): |
78 | 81 |
if v: |
79 | 82 |
full_path = '%s&%s=%s' %(full_path, k, v) |
... | ... | |
97 | 100 |
kwargs['headers'].setdefault('content-type', |
98 | 101 |
'application/octet-stream') |
99 | 102 |
kwargs['headers'].setdefault('content-length', len(body) if body else 0) |
100 |
try: |
|
101 |
#print '*', method, full_path, kwargs |
|
102 |
conn.request(method, full_path, **kwargs) |
|
103 |
except socket.error, e: |
|
104 |
raise Fault(status=503) |
|
103 |
kwargs['headers'] = _encode_headers(kwargs['headers']) |
|
104 |
#print '#', method, full_path, kwargs |
|
105 |
conn.request(method, full_path, **kwargs) |
|
106 |
|
|
107 |
#try: |
|
108 |
# conn.request(method, full_path, **kwargs) |
|
109 |
#except socket.error, e: |
|
110 |
# print '###', e[0], conn.auto_open |
|
111 |
# raise Fault(status=503) |
|
105 | 112 |
|
106 | 113 |
resp = conn.getresponse() |
107 | 114 |
headers = dict(resp.getheaders()) |
... | ... | |
128 | 135 |
def delete(self, path, format='text', params={}): |
129 | 136 |
return self._req('DELETE', path, format=format, params=params) |
130 | 137 |
|
131 |
def get(self, path, format='text', headers=None, params={}): |
|
138 |
def get(self, path, format='text', headers={}, params={}, |
|
139 |
top_level_req=False): |
|
132 | 140 |
return self._req('GET', path, headers=headers, format=format, |
133 |
params=params) |
|
141 |
params=params, top_level_req=top_level_req)
|
|
134 | 142 |
|
135 | 143 |
def head(self, path, format='text', params={}): |
136 |
return self._req('HEAD', path, format=format, params=params) |
|
144 |
return self._req('HEAD', path, format=format, params=params)
|
|
137 | 145 |
|
138 | 146 |
def post(self, path, body=None, format='text', headers=None, params={}): |
139 | 147 |
return self._req('POST', path, body, headers=headers, format=format, |
... | ... | |
142 | 150 |
def put(self, path, body=None, format='text', headers=None): |
143 | 151 |
return self._req('PUT', path, body, headers=headers, format=format) |
144 | 152 |
|
145 |
def _list(self, path, format='text', params={}, **headers): |
|
153 |
def _list(self, path, format='text', params={}, top_level_req=False, |
|
154 |
**headers): |
|
146 | 155 |
status, headers, data = self.get(path, format=format, headers=headers, |
147 |
params=params) |
|
156 |
params=params, |
|
157 |
top_level_req=top_level_req) |
|
148 | 158 |
if format == 'json': |
149 | 159 |
data = json.loads(data) if data else '' |
150 | 160 |
elif format == 'xml': |
... | ... | |
216 | 226 |
|
217 | 227 |
# Storage Account Services |
218 | 228 |
|
219 |
def list_containers(self, format='text', limit=10000, marker=None, params={},
|
|
229 |
def list_containers(self, format='text', limit=None, marker=None, params={},
|
|
220 | 230 |
**headers): |
221 | 231 |
"""lists containers""" |
222 |
if not params: |
|
223 |
params = {} |
|
224 | 232 |
params.update({'limit':limit, 'marker':marker}) |
225 | 233 |
return self._list('', format, params, **headers) |
226 | 234 |
|
... | ... | |
246 | 254 |
def _filter_trashed(self, l): |
247 | 255 |
return self._filter(l, {'trash':'true'}) |
248 | 256 |
|
249 |
def list_objects(self, container, format='text', limit=10000, marker=None,
|
|
257 |
def list_objects(self, container, format='text', limit=None, marker=None,
|
|
250 | 258 |
prefix=None, delimiter=None, path=None, |
251 | 259 |
include_trashed=False, params={}, **headers): |
252 | 260 |
"""returns a list with the container objects""" |
... | ... | |
369 | 377 |
path = '/%s/%s' % (dst_container, dst_object) |
370 | 378 |
headers = {} if not headers else headers |
371 | 379 |
for k, v in meta.items(): |
372 |
headers['x-object-meta-%s' % k] = v
|
|
380 |
headers['x-object-meta-%s' % k] = v |
|
373 | 381 |
if remove: |
374 | 382 |
headers['x-move-from'] = '/%s/%s' % (src_container, src_object) |
375 | 383 |
else: |
... | ... | |
440 | 448 |
block = f.read(blocksize) |
441 | 449 |
if block == '': |
442 | 450 |
break |
443 |
data = '%s\r\n%s\r\n' % (hex(len(block)), block)
|
|
451 |
data = '%x\r\n%s\r\n' % (len(block), block)
|
|
444 | 452 |
try: |
445 | 453 |
http.send(data) |
446 | 454 |
except: |
447 | 455 |
#retry |
448 | 456 |
http.send(data) |
449 |
data = '0x0\r\n'
|
|
457 |
data = '0\r\n\r\n'
|
|
450 | 458 |
try: |
451 | 459 |
http.send(data) |
452 | 460 |
except: |
... | ... | |
505 | 513 |
if_unmodified_since=None, limit=1000, marker=None, |
506 | 514 |
until=None): |
507 | 515 |
"""returns a list with the account containers""" |
508 |
params = {'until':until} if until else None
|
|
516 |
params = {'until':until} if until else {}
|
|
509 | 517 |
headers = {'if-modified-since':if_modified_since, |
510 | 518 |
'if-unmodified-since':if_unmodified_since} |
511 | 519 |
return OOS_Client.list_containers(self, format=format, limit=limit, |
... | ... | |
521 | 529 |
def set_account_groups(self, **groups): |
522 | 530 |
"""create account groups""" |
523 | 531 |
headers = {} |
524 |
for key, val in groups.items():
|
|
525 |
headers['x-account-group-%s' % key] = val
|
|
532 |
for k, v in groups.items():
|
|
533 |
headers['x-account-group-%s' % k] = v
|
|
526 | 534 |
params = {'update':None} |
527 | 535 |
return self.post('', headers=headers, params=params) |
528 | 536 |
|
... | ... | |
551 | 559 |
def reset_account_groups(self, **groups): |
552 | 560 |
"""overrides account groups""" |
553 | 561 |
headers = {} |
554 |
for key, val in groups.items(): |
|
555 |
headers['x-account-group-%s' % key] = val |
|
562 |
for k, v in groups.items(): |
|
563 |
v = v.strip() |
|
564 |
headers['x-account-group-%s' % k] = v |
|
556 | 565 |
meta = self.retrieve_account_metadata() |
557 | 566 |
headers.update(meta) |
558 | 567 |
return self.post('', headers=headers) |
559 | 568 |
|
560 | 569 |
# Storage Container Services |
561 | 570 |
|
562 |
def list_objects(self, container, format='text', limit=10000, marker=None,
|
|
571 |
def list_objects(self, container, format='text', limit=None, marker=None,
|
|
563 | 572 |
prefix=None, delimiter=None, path=None, |
564 | 573 |
include_trashed=False, params={}, if_modified_since=None, |
565 | 574 |
if_unmodified_since=None, meta={}, until=None): |
... | ... | |
672 | 681 |
headers.update({elem:eval(elem)}) |
673 | 682 |
|
674 | 683 |
for k,v in meta.items(): |
675 |
headers['x-object-meta-%s' %k.strip()] = v.strip() |
|
684 |
v = v.strip() |
|
685 |
headers['x-object-meta-%s' %k.strip()] = v |
|
676 | 686 |
|
677 | 687 |
return self._chunked_transfer(path, 'PUT', f, headers=headers, |
678 | 688 |
blocksize=blocksize) |
... | ... | |
738 | 748 |
headers['content_range'] = 'bytes */*' |
739 | 749 |
|
740 | 750 |
for k,v in meta.items(): |
741 |
headers['x-object-meta-%s' %k.strip()] = v.strip() |
|
751 |
v = v.strip() |
|
752 |
headers['x-object-meta-%s' %k.strip()] = v |
|
742 | 753 |
|
743 | 754 |
return self._chunked_transfer(path, 'POST', f, headers=headers, |
744 | 755 |
blocksize=blocksize) |
... | ... | |
777 | 788 |
path = '/%s/%s' % (dst_container, dst_object) |
778 | 789 |
headers = {} if not headers else headers |
779 | 790 |
for k, v in meta.items(): |
780 |
headers['x-object-meta-%s' % k] = v
|
|
791 |
headers['x-object-meta-%s' % k] = v |
|
781 | 792 |
if remove: |
782 | 793 |
headers['x-move-from'] = '/%s/%s' % (src_container, src_object) |
783 | 794 |
else: |
... | ... | |
805 | 816 |
headers['x_object_version'] = version |
806 | 817 |
return OOS_Client.move_object(self, src_container, src_object, |
807 | 818 |
dst_container, dst_object, meta=meta, |
808 |
**headers) |
|
819 |
**headers) |
|
820 |
|
|
821 |
def list_shared_by_others(self, limit=None, marker=None, format='text'): |
|
822 |
l = ['limit', 'marker'] |
|
823 |
params = {} |
|
824 |
for elem in [elem for elem in l if eval(elem)]: |
|
825 |
params[elem] = eval(elem) |
|
826 |
return self._list('', format, params, top_level_req=True) |
|
827 |
|
|
828 |
def share_object(self, container, object, l, read=True): |
|
829 |
action = 'read' if read else 'write' |
|
830 |
sharing = '%s=%s' % (action, ','.join(l)) |
|
831 |
self.update_object(container, object, f=None, x_object_sharing=sharing) |
|
832 |
|
|
833 |
def _encode_headers(headers): |
|
834 |
h = {} |
|
835 |
for k, v in headers.items(): |
|
836 |
k = urllib.quote(k) |
|
837 |
if v and type(v) == types.StringType: |
|
838 |
v = urllib.quote(v, '/=,-* :"') |
|
839 |
h[k] = v |
|
840 |
return h |
b/tools/store | ||
---|---|---|
47 | 47 |
import time as _time |
48 | 48 |
import os |
49 | 49 |
|
50 |
#DEFAULT_HOST = 'pithos.dev.grnet.gr'
|
|
51 |
DEFAULT_HOST = '127.0.0.1:8000' |
|
50 |
DEFAULT_HOST = 'pithos.dev.grnet.gr' |
|
51 |
#DEFAULT_HOST = '127.0.0.1:8000'
|
|
52 | 52 |
DEFAULT_API = 'v1' |
53 | 53 |
|
54 | 54 |
_cli_commands = {} |
... | ... | |
685 | 685 |
print '\nCommands:\n' + '\n'.join(sorted(commands)) |
686 | 686 |
|
687 | 687 |
def print_dict(d, header='name', f=stdout, detail=True): |
688 |
header = header in d and header or 'subdir'
|
|
688 |
header = header if header in d else 'subdir'
|
|
689 | 689 |
if header and header in d: |
690 |
f.write('%s\n' %d.pop(header)) |
|
690 |
f.write('%s\n' %d.pop(header).encode('utf8'))
|
|
691 | 691 |
if detail: |
692 | 692 |
patterns = ['^x_(account|container|object)_meta_(\w+)$'] |
693 | 693 |
patterns.append(patterns[0].replace('_', '-')) |
Also available in: Unified diff