Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-backend / pithos / backends / base.py @ 4d15c94e

History | View | Annotate | Download (20.8 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, include_user_defined=True):
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, public=False):
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
            'public': Only list containers containing public objects
183
            
184
        
185
        Raises:
186
            NotAllowedError: Operation not permitted
187
        """
188
        return []
189
    
190
    def list_container_meta(self, user, account, container, domain, until=None):
191
        """Return a list with all the container's object meta keys for the domain.
192
        
193
        Raises:
194
            NotAllowedError: Operation not permitted
195
            
196
            NameError: Container does not exist
197
        """
198
        return []
199
    
200
    def get_container_meta(self, user, account, container, domain, until=None, include_user_defined=True):
201
        """Return a dictionary with the container metadata for the domain.
202
        
203
        The keys returned are all user-defined, except:
204
            'name': The container name
205
            
206
            'count': The number of objects
207
            
208
            'bytes': The total data size
209
            
210
            'modified': Last modification timestamp (overall)
211
            
212
            'until_timestamp': Last modification until the timestamp provided
213
        
214
        Raises:
215
            NotAllowedError: Operation not permitted
216
            
217
            NameError: Container does not exist
218
        """
219
        return {}
220
    
221
    def update_container_meta(self, user, account, container, domain, meta, replace=False):
222
        """Update the metadata associated with the container for the domain.
223
        
224
        Parameters:
225
            'domain': Metadata domain
226
            
227
            'meta': Dictionary with metadata to update
228
            
229
            'replace': Replace instead of update
230
        
231
        Raises:
232
            NotAllowedError: Operation not permitted
233
            
234
            NameError: Container does not exist
235
        """
236
        return
237
    
238
    def get_container_policy(self, user, account, container):
239
        """Return a dictionary with the container policy.
240
        
241
        The keys returned are:
242
            'quota': The maximum bytes allowed (default is 0 - unlimited)
243
            
244
            'versioning': Can be 'auto', 'manual' or 'none' (default is 'manual')
245
        
246
        Raises:
247
            NotAllowedError: Operation not permitted
248
            
249
            NameError: Container does not exist
250
        """
251
        return {}
252
    
253
    def update_container_policy(self, user, account, container, policy, replace=False):
254
        """Update the policy associated with the container.
255
        
256
        Raises:
257
            NotAllowedError: Operation not permitted
258
            
259
            NameError: Container does not exist
260
            
261
            ValueError: Invalid policy defined
262
        """
263
        return
264
    
265
    def put_container(self, user, account, container, policy={}):
266
        """Create a new container with the given name.
267
        
268
        Raises:
269
            NotAllowedError: Operation not permitted
270
            
271
            NameError: Container already exists
272
            
273
            ValueError: Invalid policy defined
274
        """
275
        return
276
    
277
    def delete_container(self, user, account, container, until=None):
278
        """Delete/purge the container with the given name.
279
        
280
        Raises:
281
            NotAllowedError: Operation not permitted
282
            
283
            NameError: Container does not exist
284
            
285
            IndexError: Container is not empty
286
        """
287
        return
288
    
289
    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, public=False):
290
        """Return a list of object (name, version_id) tuples existing under a container.
291
        
292
        Parameters:
293
            'prefix': List objects starting with 'prefix'
294
            
295
            'delimiter': Return unique names before 'delimiter' and after 'prefix'
296
            
297
            'marker': Start list from the next item after 'marker'
298
            
299
            'limit': Number of objects to return
300
            
301
            'virtual': If not set, the result will only include names starting
302
                       with 'prefix' and ending without a 'delimiter' or with
303
                       the first occurance of the 'delimiter' after 'prefix'.
304
                       If set, the result will include all names after 'prefix',
305
                       up to and including the 'delimiter' if it is found
306
            
307
            'domain': Metadata domain for keys
308
            
309
            'keys': Include objects that satisfy the key queries in the list.
310
                    Use 'key', '!key' for existence queries, 'key op value' for
311
                    value queries, where 'op' can be one of =, !=, <=, >=, <, >
312
            
313
            'shared': Only list objects with permissions set
314
             
315
            'size_range': Include objects with byte size in (from, to).
316
                          Use None to specify unlimited
317
            
318
            'public': Only list public objects
319
             
320
        
321
        Raises:
322
            NotAllowedError: Operation not permitted
323
            
324
            NameError: Container does not exist
325
        """
326
        return []
327
    
328
    def list_object_meta(self, user, account, container, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, domain=None, keys=[], shared=False, until=None, size_range=None):
329
        """Return a list of object metadata dicts existing under a container.
330
        
331
        Same parameters with list_objects. Returned dicts have no user-defined
332
        metadata and, if until is not None, a None 'modified' timestamp.
333
        
334
        Raises:
335
            NotAllowedError: Operation not permitted
336
            
337
            NameError: Container does not exist
338
        """
339
        return []
340
    
341
    def list_object_permissions(self, user, account, container, prefix=''):
342
        """Return a list of paths that enforce permissions under a container.
343
        
344
        Raises:
345
            NotAllowedError: Operation not permitted
346
        """
347
        return []
348
    
349
    def list_object_public(self, user, account, container, prefix=''):
350
        """Return a dict mapping paths to public ids for objects that are public under a container."""
351
        return {}
352
    
353
    def get_object_meta(self, user, account, container, name, domain, version=None, include_user_defined=True):
354
        """Return a dictionary with the object metadata for the domain.
355
        
356
        The keys returned are all user-defined, except:
357
            'name': The object name
358
            
359
            'bytes': The total data size
360
            
361
            'type': The content type
362
            
363
            'hash': The hashmap hash
364
            
365
            'modified': Last modification timestamp (overall)
366
            
367
            'modified_by': The user that committed the object (version requested)
368
            
369
            'version': The version identifier
370
            
371
            'version_timestamp': The version's modification timestamp
372
            
373
            'uuid': A unique identifier that persists data or metadata updates and renames
374
            
375
            'checksum': The MD5 sum of the object (may be empty)
376
        
377
        Raises:
378
            NotAllowedError: Operation not permitted
379
            
380
            NameError: Container/object does not exist
381
            
382
            IndexError: Version does not exist
383
        """
384
        return {}
385
    
386
    def update_object_meta(self, user, account, container, name, domain, meta, replace=False):
387
        """Update the metadata associated with the object for the domain and return the new version.
388
        
389
        Parameters:
390
            'domain': Metadata domain
391
            
392
            'meta': Dictionary with metadata to update
393
            
394
            'replace': Replace instead of update
395
        
396
        Raises:
397
            NotAllowedError: Operation not permitted
398
            
399
            NameError: Container/object does not exist
400
        """
401
        return ''
402
    
403
    def get_object_permissions(self, user, account, container, name):
404
        """Return the action allowed on the object, the path
405
        from which the object gets its permissions from,
406
        along with a dictionary containing the permissions.
407
        
408
        The dictionary keys are (also used for defining the action):
409
            'read': The object is readable by the users/groups in the list
410
            
411
            'write': The object is writable by the users/groups in the list
412
        
413
        Raises:
414
            NotAllowedError: Operation not permitted
415
            
416
            NameError: Container/object does not exist
417
        """
418
        return {}
419
    
420
    def update_object_permissions(self, user, account, container, name, permissions):
421
        """Update (set) the permissions associated with the object.
422
        
423
        Parameters:
424
            'permissions': Dictionary with permissions to set
425
        
426
        Raises:
427
            NotAllowedError: Operation not permitted
428
            
429
            NameError: Container/object does not exist
430
            
431
            ValueError: Invalid users/groups in permissions
432
        """
433
        return
434
    
435
    def get_object_public(self, user, account, container, name):
436
        """Return the public id of the object if applicable.
437
        
438
        Raises:
439
            NotAllowedError: Operation not permitted
440
            
441
            NameError: Container/object does not exist
442
        """
443
        return None
444
    
445
    def update_object_public(self, user, account, container, name, public):
446
        """Update the public status of the object.
447
        
448
        Parameters:
449
            'public': Boolean value
450
        
451
        Raises:
452
            NotAllowedError: Operation not permitted
453
            
454
            NameError: Container/object does not exist
455
        """
456
        return
457
    
458
    def get_object_hashmap(self, user, account, container, name, version=None):
459
        """Return the object's size and a list with partial hashes.
460
        
461
        Raises:
462
            NotAllowedError: Operation not permitted
463
            
464
            NameError: Container/object does not exist
465
            
466
            IndexError: Version does not exist
467
        """
468
        return 0, []
469
    
470
    def update_object_hashmap(self, user, account, container, name, size, type, hashmap, checksum, domain, meta={}, replace_meta=False, permissions=None):
471
        """Create/update an object with the specified size and partial hashes and return the new version.
472
        
473
        Parameters:
474
            'domain': Metadata domain
475
            
476
            'meta': Dictionary with metadata to change
477
            
478
            'replace_meta': Replace metadata instead of update
479
            
480
            'permissions': Updated object permissions
481
        
482
        Raises:
483
            NotAllowedError: Operation not permitted
484
            
485
            NameError: Container does not exist
486
            
487
            ValueError: Invalid users/groups in permissions
488
            
489
            QuotaError: Account or container quota exceeded
490
        """
491
        return ''
492
    
493
    def update_object_checksum(self, user, account, container, name, version, checksum):
494
        """Update an object's checksum."""
495
        return
496
    
497
    def copy_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta={}, replace_meta=False, permissions=None, src_version=None, delimiter=None):
498
        """Copy an object's data and metadata and return the new version.
499
        
500
        Parameters:
501
            'domain': Metadata domain
502
            
503
            'meta': Dictionary with metadata to change from source to destination
504
            
505
            'replace_meta': Replace metadata instead of update
506
            
507
            'permissions': New object permissions
508
            
509
            'src_version': Copy from the version provided
510
            
511
            'delimiter': Copy objects whose path starts with src_name + delimiter
512
        
513
        Raises:
514
            NotAllowedError: Operation not permitted
515
            
516
            NameError: Container/object does not exist
517
            
518
            IndexError: Version does not exist
519
            
520
            ValueError: Invalid users/groups in permissions
521
            
522
            QuotaError: Account or container quota exceeded
523
        """
524
        return ''
525
    
526
    def move_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, type, domain, meta={}, replace_meta=False, permissions=None, delimiter=None):
527
        """Move an object's data and metadata and return the new version.
528
        
529
        Parameters:
530
            'domain': Metadata domain
531
            
532
            'meta': Dictionary with metadata to change from source to destination
533
            
534
            'replace_meta': Replace metadata instead of update
535
            
536
            'permissions': New object permissions
537
            
538
            'delimiter': Move objects whose path starts with src_name + delimiter
539
        
540
        Raises:
541
            NotAllowedError: Operation not permitted
542
            
543
            NameError: Container/object does not exist
544
            
545
            ValueError: Invalid users/groups in permissions
546
            
547
            QuotaError: Account or container quota exceeded
548
        """
549
        return ''
550
    
551
    def delete_object(self, user, account, container, name, until=None, delimiter=None):
552
        """Delete/purge an object.
553
        
554
        Parameters:
555
            'delimiter': Delete objects whose path starting with name + delimiter
556
        
557
        Raises:
558
            NotAllowedError: Operation not permitted
559
            
560
            NameError: Container/object does not exist
561
        """
562
        return
563
    
564
    def list_versions(self, user, account, container, name):
565
        """Return a list of all (version, version_timestamp) tuples for an object.
566
        
567
        Raises:
568
            NotAllowedError: Operation not permitted
569
        """
570
        return []
571
    
572
    def get_uuid(self, user, uuid):
573
        """Return the (account, container, name) for the UUID given.
574
        
575
        Raises:
576
            NotAllowedError: Operation not permitted
577
            
578
            NameError: UUID does not exist
579
        """
580
        return None
581
    
582
    def get_public(self, user, public):
583
        """Return the (account, container, name) for the public id given.
584
        
585
        Raises:
586
            NotAllowedError: Operation not permitted
587
            
588
            NameError: Public id does not exist
589
        """
590
        return None
591
    
592
    def get_block(self, hash):
593
        """Return a block's data.
594
        
595
        Raises:
596
            NameError: Block does not exist
597
        """
598
        return ''
599
    
600
    def put_block(self, data):
601
        """Store a block and return the hash."""
602
        return 0
603
    
604
    def update_block(self, hash, data, offset=0):
605
        """Update a known block and return the hash.
606
        
607
        Raises:
608
            IndexError: Offset or data outside block limits
609
        """
610
        return 0