1 # Copyright 2011 GRNET S.A. All rights reserved.
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
7 # 1. Redistributions of source code must retain the above
8 # copyright notice, this list of conditions and the following
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.
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.
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.
34 class NotAllowedError(Exception):
37 class BaseBackend(object):
38 """Abstract backend class that serves as a reference for actual implementations.
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.
43 Note that the account level is always valid as it is checked from another subsystem.
45 When not replacing metadata/groups/policy, keys with empty values should be deleted.
47 The following variables should be available:
48 'hash_algorithm': Suggested is 'sha256'
49 'block_size': Suggested is 4MB
52 def get_account_meta(self, user, account, until=None):
53 """Return a dictionary with the account metadata.
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
63 NotAllowedError: Operation not permitted
67 def update_account_meta(self, user, account, meta, replace=False):
68 """Update the metadata associated with the account.
71 'meta': Dictionary with metadata to update
72 'replace': Replace instead of update
75 NotAllowedError: Operation not permitted
79 def get_account_groups(self, user, account):
80 """Return a dictionary with the user groups defined for this account.
83 NotAllowedError: Operation not permitted
87 def update_account_groups(self, user, account, groups, replace=False):
88 """Update the groups associated with the account.
91 NotAllowedError: Operation not permitted
92 ValueError: Invalid data in groups
96 def delete_account(self, user, account):
97 """Delete the account with the given name.
100 NotAllowedError: Operation not permitted
101 IndexError: Account is not empty
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.
109 'marker': Start list from the next item after 'marker'
110 'limit': Number of containers to return
113 NotAllowedError: Operation not permitted
117 def get_container_meta(self, user, account, container, until=None):
118 """Return a dictionary with the container metadata.
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
128 NotAllowedError: Operation not permitted
129 NameError: Container does not exist
133 def update_container_meta(self, user, account, container, meta, replace=False):
134 """Update the metadata associated with the container.
137 'meta': Dictionary with metadata to update
138 'replace': Replace instead of update
141 NotAllowedError: Operation not permitted
142 NameError: Container does not exist
146 def get_container_policy(self, user, account, container):
147 """Return a dictionary with the container policy.
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')
154 NotAllowedError: Operation not permitted
155 NameError: Container does not exist
159 def update_container_policy(self, user, account, container, policy, replace=False):
160 """Update the policy associated with the account.
163 NotAllowedError: Operation not permitted
164 NameError: Container does not exist
165 ValueError: Invalid policy defined
169 def put_container(self, user, account, container, policy=None):
170 """Create a new container with the given name.
173 NotAllowedError: Operation not permitted
174 NameError: Container already exists
175 ValueError: Invalid policy defined
179 def delete_container(self, user, account, container, until=None):
180 """Delete/purge the container with the given name.
183 NotAllowedError: Operation not permitted
184 NameError: Container does not exist
185 IndexError: Container is not empty
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.
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
205 NotAllowedError: Operation not permitted
206 NameError: Container does not exist
210 def list_object_meta(self, user, account, container, until=None):
211 """Return a list with all the container's object meta keys.
214 NotAllowedError: Operation not permitted
215 NameError: Container does not exist
219 def get_object_meta(self, user, account, container, name, version=None):
220 """Return a dictionary with the object metadata.
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
231 NotAllowedError: Operation not permitted
232 NameError: Container/object does not exist
233 IndexError: Version does not exist
237 def update_object_meta(self, user, account, container, name, meta, replace=False):
238 """Update the metadata associated with the object.
241 'meta': Dictionary with metadata to update
242 'replace': Replace instead of update
245 NotAllowedError: Operation not permitted
246 NameError: Container/object does not exist
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.
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
259 NotAllowedError: Operation not permitted
260 NameError: Container/object does not exist
264 def update_object_permissions(self, user, account, container, name, permissions):
265 """Update the permissions associated with the object.
268 'permissions': Dictionary with permissions to update
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
281 def get_object_public(self, user, account, container, name):
282 """Return the public URL of the object if applicable.
285 NotAllowedError: Operation not permitted
286 NameError: Container/object does not exist
290 def update_object_public(self, user, account, container, name, public):
291 """Update the public status of the object.
294 'public': Boolean value
297 NotAllowedError: Operation not permitted
298 NameError: Container/object does not exist
302 def get_object_hashmap(self, user, account, container, name, version=None):
303 """Return the object's size and a list with partial hashes.
306 NotAllowedError: Operation not permitted
307 NameError: Container/object does not exist
308 IndexError: Version does not exist
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.
316 'dest_meta': Dictionary with metadata to change
317 'replace_meta': Replace metadata instead of update
318 'permissions': Updated object permissions
321 NotAllowedError: Operation not permitted
322 NameError: Container does not exist
323 ValueError: Invalid users/groups in permissions
324 AttributeError: Can not set permissions
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.
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
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
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.
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
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
362 def delete_object(self, user, account, container, name, until=None):
363 """Delete/purge an object.
366 NotAllowedError: Operation not permitted
367 NameError: Container/object does not exist
371 def list_versions(self, user, account, container, name):
372 """Return a list of all (version, version_timestamp) tuples for an object.
375 NotAllowedError: Operation not permitted
379 def get_block(self, hash):
380 """Return a block's data.
383 NameError: Block does not exist
387 def put_block(self, data):
388 """Store a block and return the hash."""
391 def update_block(self, hash, data, offset=0):
392 """Update a known block and return the hash.
395 IndexError: Offset or data outside block limits