Merge most important changes from the 'trash' branch.
[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         'block_size': Suggested is 4MB
50     """
51     
52     def get_account_meta(self, user, account, until=None):
53         """Return a dictionary with the account metadata.
54         
55         The keys returned are all user-defined, except:
56             'name': The account name
57             'count': The number of containers (or 0)
58             'bytes': The total data size (or 0)
59             'modified': Last modification timestamp (overall)
60             'until_timestamp': Last modification until the timestamp provided
61         
62         Raises:
63             NotAllowedError: Operation not permitted
64         """
65         return {}
66     
67     def update_account_meta(self, user, account, meta, replace=False):
68         """Update the metadata associated with the account.
69         
70         Parameters:
71             'meta': Dictionary with metadata to update
72             'replace': Replace instead of update
73         
74         Raises:
75             NotAllowedError: Operation not permitted
76         """
77         return
78     
79     def get_account_groups(self, user, account):
80         """Return a dictionary with the user groups defined for this account.
81         
82         Raises:
83             NotAllowedError: Operation not permitted
84         """
85         return {}
86     
87     def update_account_groups(self, user, account, groups, replace=False):
88         """Update the groups associated with the account.
89         
90         Raises:
91             NotAllowedError: Operation not permitted
92             ValueError: Invalid data in groups
93         """
94         return
95     
96     def delete_account(self, user, account):
97         """Delete the account with the given name.
98         
99         Raises:
100             NotAllowedError: Operation not permitted
101             IndexError: Account is not empty
102         """
103         return
104     
105     def list_containers(self, user, account, marker=None, limit=10000, until=None):
106         """Return a list of container (name, version_id) tuples existing under an account.
107         
108         Parameters:
109             'marker': Start list from the next item after 'marker'
110             'limit': Number of containers to return
111         
112         Raises:
113             NotAllowedError: Operation not permitted
114         """
115         return []
116     
117     def get_container_meta(self, user, account, container, until=None):
118         """Return a dictionary with the container metadata.
119         
120         The keys returned are all user-defined, except:
121             'name': The container name
122             'count': The number of objects
123             'bytes': The total data size
124             'modified': Last modification timestamp (overall)
125             'until_timestamp': Last modification until the timestamp provided
126         
127         Raises:
128             NotAllowedError: Operation not permitted
129             NameError: Container does not exist
130         """
131         return {}
132     
133     def update_container_meta(self, user, account, container, meta, replace=False):
134         """Update the metadata associated with the container.
135         
136         Parameters:
137             'meta': Dictionary with metadata to update
138             'replace': Replace instead of update
139         
140         Raises:
141             NotAllowedError: Operation not permitted
142             NameError: Container does not exist
143         """
144         return
145     
146     def get_container_policy(self, user, account, container):
147         """Return a dictionary with the container policy.
148         
149         The keys returned are:
150             'quota': The maximum bytes allowed (default is 0 - unlimited)
151             'versioning': Can be 'auto', 'manual' or 'none' (default is 'manual')
152         
153         Raises:
154             NotAllowedError: Operation not permitted
155             NameError: Container does not exist
156         """
157         return {}
158     
159     def update_container_policy(self, user, account, container, policy, replace=False):
160         """Update the policy associated with the account.
161         
162         Raises:
163             NotAllowedError: Operation not permitted
164             NameError: Container does not exist
165             ValueError: Invalid policy defined
166         """
167         return
168     
169     def put_container(self, user, account, container, policy=None):
170         """Create a new container with the given name.
171         
172         Raises:
173             NotAllowedError: Operation not permitted
174             NameError: Container already exists
175             ValueError: Invalid policy defined
176         """
177         return
178     
179     def delete_container(self, user, account, container, until=None):
180         """Delete/purge the container with the given name.
181         
182         Raises:
183             NotAllowedError: Operation not permitted
184             NameError: Container does not exist
185             IndexError: Container is not empty
186         """
187         return
188     
189     def list_objects(self, user, account, container, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], until=None):
190         """Return a list of object (name, version_id) tuples existing under a container.
191         
192         Parameters:
193             'prefix': List objects starting with 'prefix'
194             'delimiter': Return unique names before 'delimiter' and after 'prefix'
195             'marker': Start list from the next item after 'marker'
196             'limit': Number of objects to return
197             'virtual': If not set, the result will only include names starting\
198                        with 'prefix' and ending without a 'delimiter' or with\
199                        the first occurance of the 'delimiter' after 'prefix'.\
200                        If set, the result will include all names after 'prefix',\
201                        up to and including the 'delimiter' if it is found
202             'keys': Include objects that have meta with the keys in the list
203         
204         Raises:
205             NotAllowedError: Operation not permitted
206             NameError: Container does not exist
207         """
208         return []
209     
210     def list_object_meta(self, user, account, container, until=None):
211         """Return a list with all the container's object meta keys.
212         
213         Raises:
214             NotAllowedError: Operation not permitted
215             NameError: Container does not exist
216         """
217         return []
218     
219     def get_object_meta(self, user, account, container, name, version=None):
220         """Return a dictionary with the object metadata.
221         
222         The keys returned are all user-defined, except:
223             'name': The object name
224             'bytes': The total data size
225             'modified': Last modification timestamp (overall)
226             'modified_by': The user that committed the object (version requested)
227             'version': The version identifier
228             'version_timestamp': The version's modification timestamp
229         
230         Raises:
231             NotAllowedError: Operation not permitted
232             NameError: Container/object does not exist
233             IndexError: Version does not exist
234         """
235         return {}
236     
237     def update_object_meta(self, user, account, container, name, meta, replace=False):
238         """Update the metadata associated with the object.
239         
240         Parameters:
241             'meta': Dictionary with metadata to update
242             'replace': Replace instead of update
243         
244         Raises:
245             NotAllowedError: Operation not permitted
246             NameError: Container/object does not exist
247         """
248         return
249     
250     def get_object_permissions(self, user, account, container, name):
251         """Return the path from which this object gets its permissions from,\
252         along with a dictionary containing the permissions.
253         
254         The keys are:
255             'read': The object is readable by the users/groups in the list
256             'write': The object is writable by the users/groups in the list
257         
258         Raises:
259             NotAllowedError: Operation not permitted
260             NameError: Container/object does not exist
261         """
262         return {}
263     
264     def update_object_permissions(self, user, account, container, name, permissions):
265         """Update the permissions associated with the object.
266         
267         Parameters:
268             'permissions': Dictionary with permissions to update
269         
270         Raises:
271             NotAllowedError: Operation not permitted
272             NameError: Container/object does not exist
273             ValueError: Invalid users/groups in permissions
274             AttributeError: Can not set permissions, as this object\
275                 is already shared/private by another object higher\
276                 in the hierarchy, or setting permissions here will\
277                 invalidate other permissions deeper in the hierarchy
278         """
279         return
280     
281     def get_object_public(self, user, account, container, name):
282         """Return the public URL of the object if applicable.
283         
284         Raises:
285             NotAllowedError: Operation not permitted
286             NameError: Container/object does not exist
287         """
288         return None
289     
290     def update_object_public(self, user, account, container, name, public):
291         """Update the public status of the object.
292         
293         Parameters:
294             'public': Boolean value
295         
296         Raises:
297             NotAllowedError: Operation not permitted
298             NameError: Container/object does not exist
299         """
300         return
301     
302     def get_object_hashmap(self, user, account, container, name, version=None):
303         """Return the object's size and a list with partial hashes.
304         
305         Raises:
306             NotAllowedError: Operation not permitted
307             NameError: Container/object does not exist
308             IndexError: Version does not exist
309         """
310         return 0, []
311     
312     def update_object_hashmap(self, user, account, container, name, size, hashmap, meta={}, replace_meta=False, permissions=None):
313         """Create/update an object with the specified size and partial hashes.
314         
315         Parameters:
316             'dest_meta': Dictionary with metadata to change
317             'replace_meta': Replace metadata instead of update
318             'permissions': Updated object permissions
319         
320         Raises:
321             NotAllowedError: Operation not permitted
322             NameError: Container does not exist
323             ValueError: Invalid users/groups in permissions
324             AttributeError: Can not set permissions
325         """
326         return
327     
328     def copy_object(self, user, account, src_container, src_name, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions=None, src_version=None):
329         """Copy an object's data and metadata.
330         
331         Parameters:
332             'dest_meta': Dictionary with metadata to change from source to destination
333             'replace_meta': Replace metadata instead of update
334             'permissions': New object permissions
335             'src_version': Copy from the version provided
336         
337         Raises:
338             NotAllowedError: Operation not permitted
339             NameError: Container/object does not exist
340             IndexError: Version does not exist
341             ValueError: Invalid users/groups in permissions
342             AttributeError: Can not set permissions
343         """
344         return
345     
346     def move_object(self, user, account, src_container, src_name, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions=None):
347         """Move an object's data and metadata.
348         
349         Parameters:
350             'dest_meta': Dictionary with metadata to change from source to destination
351             'replace_meta': Replace metadata instead of update
352             'permissions': New object permissions
353         
354         Raises:
355             NotAllowedError: Operation not permitted
356             NameError: Container/object does not exist
357             ValueError: Invalid users/groups in permissions
358             AttributeError: Can not set permissions
359         """
360         return
361     
362     def delete_object(self, user, account, container, name, until=None):
363         """Delete/purge an object.
364         
365         Raises:
366             NotAllowedError: Operation not permitted
367             NameError: Container/object does not exist
368         """
369         return
370     
371     def list_versions(self, user, account, container, name):
372         """Return a list of all (version, version_timestamp) tuples for an object.
373         
374         Raises:
375             NotAllowedError: Operation not permitted
376         """
377         return []
378     
379     def get_block(self, hash):
380         """Return a block's data.
381         
382         Raises:
383             NameError: Block does not exist
384         """
385         return ''
386     
387     def put_block(self, data):
388         """Store a block and return the hash."""
389         return 0
390     
391     def update_block(self, hash, data, offset=0):
392         """Update a known block and return the hash.
393         
394         Raises:
395             IndexError: Offset or data outside block limits
396         """
397         return 0