Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-backend / pithos / backends / base.py @ 5f8bbf54

History | View | Annotate | Download (21.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 AccountExists(NameError):
46
    pass
47
    
48
class ContainerExists(NameError):
49
    pass
50

    
51
class AccountNotEmpty(IndexError):
52
    pass
53

    
54
class ContainerNotEmpty(IndexError):
55
    pass
56

    
57
class ItemNotExists(NameError):
58
    pass
59

    
60
class VersionNotExists(IndexError):
61
    pass
62

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