Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-backend / pithos / backends / base.py @ 345dcf39

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