~ubuntu-branches/ubuntu/trusty/swift/trusty-updates

« back to all changes in this revision

Viewing changes to swift/proxy/controllers/account.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Soren Hansen, Chuck Short
  • Date: 2012-09-07 19:02:36 UTC
  • mfrom: (1.2.12)
  • Revision ID: package-import@ubuntu.com-20120907190236-fqrmbzm7v6zivs8d
Tags: 1.7.0-0ubuntu1
[ Soren Hansen ]
* Update debian/watch to account for symbolically named tarballs and
  use newer URL.
* Run unit tests at build time.
* Fix Launchpad URLs in debian/watch.

[ Chuck Short ]
* New upstream release
* debian/control: Add pubthon-moc as a build dep
* debian/rules: Dont fail if testsuite fails.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2010-2012 OpenStack, LLC.
 
2
#
 
3
# Licensed under the Apache License, Version 2.0 (the "License");
 
4
# you may not use this file except in compliance with the License.
 
5
# You may obtain a copy of the License at
 
6
#
 
7
#    http://www.apache.org/licenses/LICENSE-2.0
 
8
#
 
9
# Unless required by applicable law or agreed to in writing, software
 
10
# distributed under the License is distributed on an "AS IS" BASIS,
 
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 
12
# implied.
 
13
# See the License for the specific language governing permissions and
 
14
# limitations under the License.
 
15
 
 
16
# NOTE: swift_conn
 
17
# You'll see swift_conn passed around a few places in this file. This is the
 
18
# source httplib connection of whatever it is attached to.
 
19
#   It is used when early termination of reading from the connection should
 
20
# happen, such as when a range request is satisfied but there's still more the
 
21
# source connection would like to send. To prevent having to read all the data
 
22
# that could be left, the source connection can be .close() and then reads
 
23
# commence to empty out any buffers.
 
24
#   These shenanigans are to ensure all related objects can be garbage
 
25
# collected. We've seen objects hang around forever otherwise.
 
26
 
 
27
import time
 
28
from urllib import unquote
 
29
from random import shuffle
 
30
 
 
31
from webob.exc import HTTPBadRequest, HTTPMethodNotAllowed
 
32
from webob import Request
 
33
 
 
34
from swift.common.utils import normalize_timestamp, public
 
35
from swift.common.constraints import check_metadata, MAX_ACCOUNT_NAME_LENGTH
 
36
from swift.common.http import is_success, HTTP_NOT_FOUND
 
37
from swift.proxy.controllers.base import Controller
 
38
 
 
39
 
 
40
class AccountController(Controller):
 
41
    """WSGI controller for account requests"""
 
42
    server_type = 'Account'
 
43
 
 
44
    def __init__(self, app, account_name, **kwargs):
 
45
        Controller.__init__(self, app)
 
46
        self.account_name = unquote(account_name)
 
47
 
 
48
    def GETorHEAD(self, req):
 
49
        """Handler for HTTP GET/HEAD requests."""
 
50
        partition, nodes = self.app.account_ring.get_nodes(self.account_name)
 
51
        shuffle(nodes)
 
52
        resp = self.GETorHEAD_base(req, _('Account'), partition, nodes,
 
53
                req.path_info.rstrip('/'), len(nodes))
 
54
        if resp.status_int == HTTP_NOT_FOUND and self.app.account_autocreate:
 
55
            if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH:
 
56
                resp = HTTPBadRequest(request=req)
 
57
                resp.body = 'Account name length of %d longer than %d' % \
 
58
                            (len(self.account_name), MAX_ACCOUNT_NAME_LENGTH)
 
59
                return resp
 
60
            headers = {'X-Timestamp': normalize_timestamp(time.time()),
 
61
                       'X-Trans-Id': self.trans_id,
 
62
                       'Connection': 'close'}
 
63
            resp = self.make_requests(
 
64
                Request.blank('/v1/' + self.account_name),
 
65
                self.app.account_ring, partition, 'PUT',
 
66
                '/' + self.account_name, [headers] * len(nodes))
 
67
            if not is_success(resp.status_int):
 
68
                self.app.logger.warning('Could not autocreate account %r' %
 
69
                                        self.account_name)
 
70
                return resp
 
71
            resp = self.GETorHEAD_base(req, _('Account'), partition, nodes,
 
72
                req.path_info.rstrip('/'), len(nodes))
 
73
        return resp
 
74
 
 
75
    @public
 
76
    def PUT(self, req):
 
77
        """HTTP PUT request handler."""
 
78
        if not self.app.allow_account_management:
 
79
            return HTTPMethodNotAllowed(request=req)
 
80
        error_response = check_metadata(req, 'account')
 
81
        if error_response:
 
82
            return error_response
 
83
        if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH:
 
84
            resp = HTTPBadRequest(request=req)
 
85
            resp.body = 'Account name length of %d longer than %d' % \
 
86
                        (len(self.account_name), MAX_ACCOUNT_NAME_LENGTH)
 
87
            return resp
 
88
        account_partition, accounts = \
 
89
            self.app.account_ring.get_nodes(self.account_name)
 
90
        headers = {'X-Timestamp': normalize_timestamp(time.time()),
 
91
                   'x-trans-id': self.trans_id,
 
92
                   'Connection': 'close'}
 
93
        self.transfer_headers(req.headers, headers)
 
94
        if self.app.memcache:
 
95
            self.app.memcache.delete('account%s' % req.path_info.rstrip('/'))
 
96
        resp = self.make_requests(req, self.app.account_ring,
 
97
            account_partition, 'PUT', req.path_info, [headers] * len(accounts))
 
98
        return resp
 
99
 
 
100
    @public
 
101
    def POST(self, req):
 
102
        """HTTP POST request handler."""
 
103
        error_response = check_metadata(req, 'account')
 
104
        if error_response:
 
105
            return error_response
 
106
        account_partition, accounts = \
 
107
            self.app.account_ring.get_nodes(self.account_name)
 
108
        headers = {'X-Timestamp': normalize_timestamp(time.time()),
 
109
                   'X-Trans-Id': self.trans_id,
 
110
                   'Connection': 'close'}
 
111
        self.transfer_headers(req.headers, headers)
 
112
        if self.app.memcache:
 
113
            self.app.memcache.delete('account%s' % req.path_info.rstrip('/'))
 
114
        resp = self.make_requests(req, self.app.account_ring,
 
115
            account_partition, 'POST', req.path_info,
 
116
            [headers] * len(accounts))
 
117
        if resp.status_int == HTTP_NOT_FOUND and self.app.account_autocreate:
 
118
            if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH:
 
119
                resp = HTTPBadRequest(request=req)
 
120
                resp.body = 'Account name length of %d longer than %d' % \
 
121
                            (len(self.account_name), MAX_ACCOUNT_NAME_LENGTH)
 
122
                return resp
 
123
            resp = self.make_requests(
 
124
                Request.blank('/v1/' + self.account_name),
 
125
                self.app.account_ring, account_partition, 'PUT',
 
126
                '/' + self.account_name, [headers] * len(accounts))
 
127
            if not is_success(resp.status_int):
 
128
                self.app.logger.warning('Could not autocreate account %r' %
 
129
                                        self.account_name)
 
130
                return resp
 
131
        return resp
 
132
 
 
133
    @public
 
134
    def DELETE(self, req):
 
135
        """HTTP DELETE request handler."""
 
136
        if not self.app.allow_account_management:
 
137
            return HTTPMethodNotAllowed(request=req)
 
138
        account_partition, accounts = \
 
139
            self.app.account_ring.get_nodes(self.account_name)
 
140
        headers = {'X-Timestamp': normalize_timestamp(time.time()),
 
141
                   'X-Trans-Id': self.trans_id,
 
142
                   'Connection': 'close'}
 
143
        if self.app.memcache:
 
144
            self.app.memcache.delete('account%s' % req.path_info.rstrip('/'))
 
145
        resp = self.make_requests(req, self.app.account_ring,
 
146
            account_partition, 'DELETE', req.path_info,
 
147
            [headers] * len(accounts))
 
148
        return resp