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