Statistics
| Branch: | Tag: | Revision:

root / pithos / backends / base.py @ 2e662088

History | View | Annotate | Download (19.4 kB)

1
# Copyright 2011-2012 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
# Default setting for new accounts.
35
DEFAULT_QUOTA = 0 # No quota.
36
DEFAULT_VERSIONING = 'auto'
37

    
38

    
39
class NotAllowedError(Exception):
40
    pass
41

    
42
class QuotaError(Exception):
43
    pass
44

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