983612aa9d4bb7c16892f35c07e211780926bde7
[pithos] / pithos / public / functions.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 import logging
35
36 from django.http import HttpResponse
37
38 from pithos.api.faults import (Fault, BadRequest, ItemNotFound)
39 from pithos.api.util import (put_object_meta, update_manifest_meta,
40     validate_modification_preconditions, validate_matching_preconditions,
41     object_data_response, api_method)
42 from pithos.backends import backend
43
44
45 logger = logging.getLogger(__name__)
46
47
48 def object_demux(request, v_account, v_container, v_object):
49     if request.method == 'HEAD':
50         return object_meta(request, v_account, v_container, v_object)
51     elif request.method == 'GET':
52         return object_read(request, v_account, v_container, v_object)
53     else:
54         return method_not_allowed(request)
55
56 # TODO: Use a version of api_method that does not check for a token.
57
58 @api_method('HEAD')
59 def object_meta(request, v_account, v_container, v_object):
60     # Normal Response Codes: 204
61     # Error Response Codes: serviceUnavailable (503),
62     #                       itemNotFound (404),
63     #                       unauthorized (401),
64     #                       badRequest (400)
65     
66     try:
67         meta = backend.get_object_meta(request.user, v_account, v_container, v_object)
68     except NameError:
69         raise ItemNotFound('Object does not exist')
70     
71     if 'X-Object-Public' not in meta:
72         raise ItemNotFound('Object does not exist')
73     update_manifest_meta(request, v_account, meta)
74     
75     response = HttpResponse(status=204)
76     put_object_meta(response, meta, True)
77     return response
78
79 @api_method('GET')
80 def object_read(request, v_account, v_container, v_object):
81     # Normal Response Codes: 200, 206
82     # Error Response Codes: serviceUnavailable (503),
83     #                       rangeNotSatisfiable (416),
84     #                       preconditionFailed (412),
85     #                       itemNotFound (404),
86     #                       unauthorized (401),
87     #                       badRequest (400),
88     #                       notModified (304)
89     
90     try:
91         meta = backend.get_object_meta(request.user, v_account, v_container, v_object)
92     except NameError:
93         raise ItemNotFound('Object does not exist')
94     
95     if 'X-Object-Public' not in meta:
96         raise ItemNotFound('Object does not exist')
97     update_manifest_meta(request, v_account, meta)
98     
99     # Evaluate conditions.
100     validate_modification_preconditions(request, meta)
101     try:
102         validate_matching_preconditions(request, meta)
103     except NotModified:
104         response = HttpResponse(status=304)
105         response['ETag'] = meta['hash']
106         return response
107     
108     sizes = []
109     hashmaps = []
110     if 'X-Object-Manifest' in meta:
111         try:
112             src_container, src_name = split_container_object_string('/' + meta['X-Object-Manifest'])
113             objects = backend.list_objects(request.user, v_account, src_container, prefix=src_name, virtual=False)
114         except ValueError:
115             raise ItemNotFound('Object does not exist')
116         except NameError:
117             raise ItemNotFound('Object does not exist')
118         
119         try:
120             for x in objects:
121                 s, h = backend.get_object_hashmap(request.user, v_account, src_container, x[0], x[1])
122                 sizes.append(s)
123                 hashmaps.append(h)
124         except NameError:
125             raise ItemNotFound('Object does not exist')
126     else:
127         try:
128             s, h = backend.get_object_hashmap(request.user, v_account, v_container, v_object, version)
129             sizes.append(s)
130             hashmaps.append(h)
131         except NameError:
132             raise ItemNotFound('Object does not exist')
133     
134     return object_data_response(request, sizes, hashmaps, meta, True)
135
136 @api_method()
137 def method_not_allowed(request):
138     raise ItemNotFound('Object does not exist')