Statistics
| Branch: | Tag: | Revision:

root / pithos / backends / base.py @ 95d47e1a

History | View | Annotate | Download (18.4 kB)

1
# Copyright 2011 GRNET S.A. All rights reserved.
2
# 
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
# 
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
# 
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
# 
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
# 
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
class NotAllowedError(Exception):
35
    pass
36

    
37
class QuotaError(Exception):
38
    pass
39

    
40
class BaseBackend(object):
41
    """Abstract backend class that serves as a reference for actual implementations.
42
    
43
    The purpose of the backend is to provide the necessary functions for handling data
44
    and metadata. It is responsible for the actual storage and retrieval of information.
45
    
46
    Note that the account level is always valid as it is checked from another subsystem.
47
    
48
    When not replacing metadata/groups/policy, keys with empty values should be deleted.
49
    
50
    The following variables should be available:
51
        'hash_algorithm': Suggested is 'sha256'
52
        
53
        'block_size': Suggested is 4MB
54
        
55
        'default_policy': A dictionary with default policy settings
56
    """
57
    
58
    def __init__(self, db_module, db_connection, block_module, block_path):
59
        """Initialize backend with supplied modules and options."""
60
        pass
61
    
62
    def close(self):
63
        """Close the backend connection."""
64
        pass
65
    
66
    def list_accounts(self, user, marker=None, limit=10000):
67
        """Return a list of accounts the user can access.
68
        
69
        Parameters:
70
            'marker': Start list from the next item after 'marker'
71
            
72
            'limit': Number of containers to return
73
        """
74
        return []
75
    
76
    def get_account_meta(self, user, account, until=None):
77
        """Return a dictionary with the account metadata.
78
        
79
        The keys returned are all user-defined, except:
80
            'name': The account name
81
            
82
            'count': The number of containers (or 0)
83
            
84
            'bytes': The total data size (or 0)
85
            
86
            'modified': Last modification timestamp (overall)
87
            
88
            'until_timestamp': Last modification until the timestamp provided
89
        
90
        Raises:
91
            NotAllowedError: Operation not permitted
92
        """
93
        return {}
94
    
95
    def update_account_meta(self, user, account, meta, replace=False):
96
        """Update the metadata associated with the account.
97
        
98
        Parameters:
99
            'meta': Dictionary with metadata to update
100
            
101
            'replace': Replace instead of update
102
        
103
        Raises:
104
            NotAllowedError: Operation not permitted
105
        """
106
        return
107
    
108
    def get_account_groups(self, user, account):
109
        """Return a dictionary with the user groups defined for this account.
110
        
111
        Raises:
112
            NotAllowedError: Operation not permitted
113
        """
114
        return {}
115
    
116
    def update_account_groups(self, user, account, groups, replace=False):
117
        """Update the groups associated with the account.
118
        
119
        Raises:
120
            NotAllowedError: Operation not permitted
121
            
122
            ValueError: Invalid data in groups
123
        """
124
        return
125
    
126
    def get_account_policy(self, user, account):
127
        """Return a dictionary with the account policy.
128
        
129
        The keys returned are:
130
            'quota': The maximum bytes allowed (default is 0 - unlimited)
131
            
132
            'versioning': Can be 'auto', 'manual' or 'none' (default is 'manual')
133
        
134
        Raises:
135
            NotAllowedError: Operation not permitted
136
        """
137
        return {}
138
    
139
    def update_account_policy(self, user, account, policy, replace=False):
140
        """Update the policy associated with the account.
141
        
142
        Raises:
143
            NotAllowedError: Operation not permitted
144
            
145
            ValueError: Invalid policy defined
146
        """
147
        return
148
    
149
    def put_account(self, user, account, policy={}):
150
        """Create a new account with the given name.
151
        
152
        Raises:
153
            NotAllowedError: Operation not permitted
154
            
155
            ValueError: Invalid policy defined
156
        """
157
        return
158
    
159
    def delete_account(self, user, account):
160
        """Delete the account with the given name.
161
        
162
        Raises:
163
            NotAllowedError: Operation not permitted
164
            
165
            IndexError: Account is not empty
166
        """
167
        return
168
    
169
    def list_containers(self, user, account, marker=None, limit=10000, shared=False, until=None):
170
        """Return a list of container names existing under an account.
171
        
172
        Parameters:
173
            'marker': Start list from the next item after 'marker'
174
            
175
            'limit': Number of containers to return
176
            
177
            'shared': Only list containers with permissions set
178
            
179
        
180
        Raises:
181
            NotAllowedError: Operation not permitted
182
        """
183
        return []
184
    
185
    def get_container_meta(self, user, account, container, until=None):
186
        """Return a dictionary with the container metadata.
187
        
188
        The keys returned are all user-defined, except:
189
            'name': The container name
190
            
191
            'count': The number of objects
192
            
193
            'bytes': The total data size
194
            
195
            'modified': Last modification timestamp (overall)
196
            
197
            'until_timestamp': Last modification until the timestamp provided
198
        
199
        Raises:
200
            NotAllowedError: Operation not permitted
201
            
202
            NameError: Container does not exist
203
        """
204
        return {}
205
    
206
    def update_container_meta(self, user, account, container, meta, replace=False):
207
        """Update the metadata associated with the container.
208
        
209
        Parameters:
210
            'meta': Dictionary with metadata to update
211
            
212
            'replace': Replace instead of update
213
        
214
        Raises:
215
            NotAllowedError: Operation not permitted
216
            
217
            NameError: Container does not exist
218
        """
219
        return
220
    
221
    def get_container_policy(self, user, account, container):
222
        """Return a dictionary with the container policy.
223
        
224
        The keys returned are:
225
            'quota': The maximum bytes allowed (default is 0 - unlimited)
226
            
227
            'versioning': Can be 'auto', 'manual' or 'none' (default is 'manual')
228
        
229
        Raises:
230
            NotAllowedError: Operation not permitted
231
            
232
            NameError: Container does not exist
233
        """
234
        return {}
235
    
236
    def update_container_policy(self, user, account, container, policy, replace=False):
237
        """Update the policy associated with the container.
238
        
239
        Raises:
240
            NotAllowedError: Operation not permitted
241
            
242
            NameError: Container does not exist
243
            
244
            ValueError: Invalid policy defined
245
        """
246
        return
247
    
248
    def put_container(self, user, account, container, policy={}):
249
        """Create a new container with the given name.
250
        
251
        Raises:
252
            NotAllowedError: Operation not permitted
253
            
254
            NameError: Container already exists
255
            
256
            ValueError: Invalid policy defined
257
        """
258
        return
259
    
260
    def delete_container(self, user, account, container, until=None):
261
        """Delete/purge the container with the given name.
262
        
263
        Raises:
264
            NotAllowedError: Operation not permitted
265
            
266
            NameError: Container does not exist
267
            
268
            IndexError: Container is not empty
269
        """
270
        return
271
    
272
    def list_objects(self, user, account, container, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], shared=False, until=None):
273
        """Return a list of object (name, version_id) tuples existing under a container.
274
        
275
        Parameters:
276
            'prefix': List objects starting with 'prefix'
277
            
278
            'delimiter': Return unique names before 'delimiter' and after 'prefix'
279
            
280
            'marker': Start list from the next item after 'marker'
281
            
282
            'limit': Number of objects to return
283
            
284
            'virtual': If not set, the result will only include names starting
285
                       with 'prefix' and ending without a 'delimiter' or with
286
                       the first occurance of the 'delimiter' after 'prefix'.
287
                       If set, the result will include all names after 'prefix',
288
                       up to and including the 'delimiter' if it is found
289
            
290
            'keys': Include objects that satisfy the key queries in the list.
291
                    Use 'key', '!key' for existence queries, 'key op value' for
292
                    value queries, where 'op' can be one of ==, != <=, >=, <, >
293
            
294
            'shared': Only list objects with permissions set
295
        
296
        Raises:
297
            NotAllowedError: Operation not permitted
298
            
299
            NameError: Container does not exist
300
        """
301
        return []
302
    
303
    def list_object_meta(self, user, account, container, until=None):
304
        """Return a list with all the container's object meta keys.
305
        
306
        Raises:
307
            NotAllowedError: Operation not permitted
308
            
309
            NameError: Container does not exist
310
        """
311
        return []
312
    
313
    def get_object_meta(self, user, account, container, name, version=None):
314
        """Return a dictionary with the object metadata.
315
        
316
        The keys returned are all user-defined, except:
317
            'name': The object name
318
            
319
            'bytes': The total data size
320
            
321
            'hash': The hashmap hash
322
            
323
            'modified': Last modification timestamp (overall)
324
            
325
            'modified_by': The user that committed the object (version requested)
326
            
327
            'version': The version identifier
328
            
329
            'version_timestamp': The version's modification timestamp
330
        
331
        Raises:
332
            NotAllowedError: Operation not permitted
333
            
334
            NameError: Container/object does not exist
335
            
336
            IndexError: Version does not exist
337
        """
338
        return {}
339
    
340
    def update_object_meta(self, user, account, container, name, meta, replace=False):
341
        """Update the metadata associated with the object and return the new version.
342
        
343
        Parameters:
344
            'meta': Dictionary with metadata to update
345
            
346
            'replace': Replace instead of update
347
        
348
        Raises:
349
            NotAllowedError: Operation not permitted
350
            
351
            NameError: Container/object does not exist
352
        """
353
        return ''
354
    
355
    def get_object_permissions(self, user, account, container, name):
356
        """Return the action allowed on the object, the path
357
        from which the object gets its permissions from,
358
        along with a dictionary containing the permissions.
359
        
360
        The dictionary keys are (also used for defining the action):
361
            'read': The object is readable by the users/groups in the list
362
            
363
            'write': The object is writable by the users/groups in the list
364
        
365
        Raises:
366
            NotAllowedError: Operation not permitted
367
            
368
            NameError: Container/object does not exist
369
        """
370
        return {}
371
    
372
    def update_object_permissions(self, user, account, container, name, permissions):
373
        """Update the permissions associated with the object.
374
        
375
        Parameters:
376
            'permissions': Dictionary with permissions to update
377
        
378
        Raises:
379
            NotAllowedError: Operation not permitted
380
            
381
            NameError: Container/object does not exist
382
            
383
            ValueError: Invalid users/groups in permissions
384
            
385
            AttributeError: Can not set permissions, as this object
386
                is already shared/private by another object higher
387
                in the hierarchy, or setting permissions here will
388
                invalidate other permissions deeper in the hierarchy
389
        """
390
        return
391
    
392
    def get_object_public(self, user, account, container, name):
393
        """Return the public id of the object if applicable.
394
        
395
        Raises:
396
            NotAllowedError: Operation not permitted
397
            
398
            NameError: Container/object does not exist
399
        """
400
        return None
401
    
402
    def update_object_public(self, user, account, container, name, public):
403
        """Update the public status of the object.
404
        
405
        Parameters:
406
            'public': Boolean value
407
        
408
        Raises:
409
            NotAllowedError: Operation not permitted
410
            
411
            NameError: Container/object does not exist
412
        """
413
        return
414
    
415
    def get_object_hashmap(self, user, account, container, name, version=None):
416
        """Return the object's size and a list with partial hashes.
417
        
418
        Raises:
419
            NotAllowedError: Operation not permitted
420
            
421
            NameError: Container/object does not exist
422
            
423
            IndexError: Version does not exist
424
        """
425
        return 0, []
426
    
427
    def update_object_hashmap(self, user, account, container, name, size, hashmap, meta={}, replace_meta=False, permissions=None):
428
        """Create/update an object with the specified size and partial hashes and return the new version.
429
        
430
        Parameters:
431
            'dest_meta': Dictionary with metadata to change
432
            
433
            'replace_meta': Replace metadata instead of update
434
            
435
            'permissions': Updated object permissions
436
        
437
        Raises:
438
            NotAllowedError: Operation not permitted
439
            
440
            NameError: Container does not exist
441
            
442
            ValueError: Invalid users/groups in permissions
443
            
444
            AttributeError: Can not set permissions
445
            
446
            QuotaError: Account or container quota exceeded
447
        """
448
        return ''
449
    
450
    def copy_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions=None, src_version=None):
451
        """Copy an object's data and metadata and return the new version.
452
        
453
        Parameters:
454
            'dest_meta': Dictionary with metadata to change from source to destination
455
            
456
            'replace_meta': Replace metadata instead of update
457
            
458
            'permissions': New object permissions
459
            
460
            'src_version': Copy from the version provided
461
        
462
        Raises:
463
            NotAllowedError: Operation not permitted
464
            
465
            NameError: Container/object does not exist
466
            
467
            IndexError: Version does not exist
468
            
469
            ValueError: Invalid users/groups in permissions
470
            
471
            AttributeError: Can not set permissions
472
            
473
            QuotaError: Account or container quota exceeded
474
        """
475
        return ''
476
    
477
    def move_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions=None):
478
        """Move an object's data and metadata and return the new version.
479
        
480
        Parameters:
481
            'dest_meta': Dictionary with metadata to change from source to destination
482
            
483
            'replace_meta': Replace metadata instead of update
484
            
485
            'permissions': New object permissions
486
        
487
        Raises:
488
            NotAllowedError: Operation not permitted
489
            
490
            NameError: Container/object does not exist
491
            
492
            ValueError: Invalid users/groups in permissions
493
            
494
            AttributeError: Can not set permissions
495
            
496
            QuotaError: Account or container quota exceeded
497
        """
498
        return ''
499
    
500
    def delete_object(self, user, account, container, name, until=None):
501
        """Delete/purge an object.
502
        
503
        Raises:
504
            NotAllowedError: Operation not permitted
505
            
506
            NameError: Container/object does not exist
507
        """
508
        return
509
    
510
    def list_versions(self, user, account, container, name):
511
        """Return a list of all (version, version_timestamp) tuples for an object.
512
        
513
        Raises:
514
            NotAllowedError: Operation not permitted
515
        """
516
        return []
517
    
518
    def get_public(self, user, public):
519
        """Return the (account, container, name) for the public id given.
520
        
521
        Raises:
522
            NotAllowedError: Operation not permitted
523
            
524
            NameError: Public id does not exist
525
        """
526
        return None
527
    
528
    def get_block(self, hash):
529
        """Return a block's data.
530
        
531
        Raises:
532
            NameError: Block does not exist
533
        """
534
        return ''
535
    
536
    def put_block(self, data):
537
        """Store a block and return the hash."""
538
        return 0
539
    
540
    def update_block(self, hash, data, offset=0):
541
        """Update a known block and return the hash.
542
        
543
        Raises:
544
            IndexError: Offset or data outside block limits
545
        """
546
        return 0