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