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