cc1  v2.1
CC1 source code docs
 All Classes Namespaces Files Functions Variables Pages
s3action.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 # @COPYRIGHT_begin
3 #
4 # Copyright [2010-2014] Institute of Nuclear Physics PAN, Krakow, Poland
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 # @COPYRIGHT_end
19 import os
20 import urlparse
21 from ec2 import lookup
22 from ec2.base.action import Action, CLMException
23 from ec2.error import InvalidAction, MethodNotAllowed, InvalidArgument, InvalidURI, EC2Exception
24 from ec2.settings import BUCKETS_PATH
25 from ec2.helpers.auth import authenticate
26 from ec2.helpers.utils import get_path
27 
28 ##
29 # @package src.base.s3action
30 # S3 base action
31 #
32 # @copyright Copyright (c) 2012 Institute of Nuclear Physics PAS <http://www.ifj.edu.pl/>
33 # @author Łukasz Chrząszcz <l.chrzaszcz@gmail.com>
34 #
35 
36 ##
37 # Superclass for S3 API actions.
38 class S3Action(object):
39 
40  def __init__(self, parameters):
41  self.parameters = parameters
42 
43  user_name = self.parameters['authorization'].split(' ')[1].split(':')[0]
44 
45  path = get_path(user_name, self.parameters['path_info'])
46 
47  # bucket_path = self.parameters['path_info']
48  # slash = bucket_path.find('/')
49  # if slash != -1:
50  # bucket_name = bucket_path[:slash+1]
51  # else:
52  # bucket_name = bucket_path
53 
54  self.user_name = user_name
55  self.path = path
56 
57  ##
58  # Return an object of a concrete S3 action class.
59  #
60  # Args:
61  # parameters <dict> of the action
62  # cluster_manager <ClusterManager> the action will be run at
63  #
64  def __new__(cls, parameters):
65  concrete_class = None
66  if cls == S3Action:
67  if parameters['query_string']:
68  qs_dict = urlparse.parse_qs(parameters['query_string'], keep_blank_values=True)
69  for k, v in qs_dict.iteritems():
70  if len(v) == 1 and not v[0]:
71  raise MethodNotAllowed() # we don't support any of the s3 commands defined by query string
72  parameters['query_string'] = '' # we don't care about query string parameters and S3 doesn't use them for authorization
73 
74  path = os.path.normpath(parameters['path_info'])
75  if path.startswith('/'):
76  path = path[1:]
77  if path.endswith('/'):
78  path = path[:-1]
79 
80  path_parts = path.split('/')
81 
82  if len(path_parts) == 1: # bucket
83  if parameters['request_method'] == 'GET' or parameters['request_method'] == 'HEAD':
84  concrete_class_name = 'ListBucket'
85  else:
86  if parameters['request_method'] == 'PUT':
87  concrete_class_name = 'PutObject'
88  if parameters['request_method'] == 'GET':
89  concrete_class_name = 'GetObject'
90 
91  for concrete_class in cls.__subclasses__():
92  if concrete_class.__name__ == concrete_class_name:
93  break
94  else:
95  concrete_class = cls
96 
97  action = super(S3Action, cls).__new__(concrete_class, parameters)
98  action.concrete_class_name = concrete_class_name
99  return action
100 
101 
102  def _get_template(self):
103  name = '%s.xml' % self.concrete_class_name
104  return lookup.get_template(name)
105 
106  def execute(self):
108  context = self._execute()
109 
110  # if body is dict then parse it to xml
111  if context['body'].__class__ is dict:
112  template = self._get_template()
113  response = template.render(**context['body'])
114  else:
115  # if it isn't dict then pass that object directly
116  response = context['body']
117 
118  result = {'body': response,
119  'headers': context.get('headers')}
120 
121  return result
122