Skip to content

Commit 9647684

Browse files
Jenkinsopenstack-gerrit
Jenkins
authored andcommitted
Merge "HTTP status value naming normalization"
2 parents 9920aeb + d2d0922 commit 9647684

17 files changed

+397
-169
lines changed

swift/account/server.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
from swift.common.constraints import ACCOUNT_LISTING_LIMIT, \
3737
check_mount, check_float, check_utf8
3838
from swift.common.db_replicator import ReplicatorRpc
39+
from swift.common.http import HTTPInsufficientStorage
3940

4041

4142
DATADIR = 'accounts'
@@ -70,7 +71,7 @@ def DELETE(self, req):
7071
return HTTPBadRequest(body=str(err), content_type='text/plain',
7172
request=req)
7273
if self.mount_check and not check_mount(self.root, drive):
73-
return Response(status='507 %s is not mounted' % drive)
74+
return HTTPInsufficientStorage(drive=drive, request=req)
7475
if 'x-timestamp' not in req.headers or \
7576
not check_float(req.headers['x-timestamp']):
7677
return HTTPBadRequest(body='Missing timestamp', request=req,
@@ -90,7 +91,7 @@ def PUT(self, req):
9091
return HTTPBadRequest(body=str(err), content_type='text/plain',
9192
request=req)
9293
if self.mount_check and not check_mount(self.root, drive):
93-
return Response(status='507 %s is not mounted' % drive)
94+
return HTTPInsufficientStorage(drive=drive, request=req)
9495
broker = self._get_account_broker(drive, part, account)
9596
if container: # put account container
9697
if 'x-trans-id' in req.headers:
@@ -149,7 +150,7 @@ def HEAD(self, req):
149150
return HTTPBadRequest(body=str(err), content_type='text/plain',
150151
request=req)
151152
if self.mount_check and not check_mount(self.root, drive):
152-
return Response(status='507 %s is not mounted' % drive)
153+
return HTTPInsufficientStorage(drive=drive, request=req)
153154
broker = self._get_account_broker(drive, part, account)
154155
if not container:
155156
broker.pending_timeout = 0.1
@@ -180,7 +181,7 @@ def GET(self, req):
180181
return HTTPBadRequest(body=str(err), content_type='text/plain',
181182
request=req)
182183
if self.mount_check and not check_mount(self.root, drive):
183-
return Response(status='507 %s is not mounted' % drive)
184+
return HTTPInsufficientStorage(drive=drive, request=req)
184185
broker = self._get_account_broker(drive, part, account)
185186
broker.pending_timeout = 0.1
186187
broker.stale_reads_ok = True
@@ -274,7 +275,7 @@ def REPLICATE(self, req):
274275
request=req)
275276
drive, partition, hash = post_args
276277
if self.mount_check and not check_mount(self.root, drive):
277-
return Response(status='507 %s is not mounted' % drive)
278+
return HTTPInsufficientStorage(drive=drive, request=req)
278279
try:
279280
args = simplejson.load(req.environ['wsgi.input'])
280281
except ValueError, err:
@@ -295,7 +296,7 @@ def POST(self, req):
295296
return HTTPBadRequest(body='Missing or bad timestamp',
296297
request=req, content_type='text/plain')
297298
if self.mount_check and not check_mount(self.root, drive):
298-
return Response(status='507 %s is not mounted' % drive)
299+
return HTTPInsufficientStorage(drive=drive, request=req)
299300
broker = self._get_account_broker(drive, part, account)
300301
if broker.is_deleted():
301302
return HTTPNotFound(request=req)

swift/common/bench.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from swift.common.utils import TRUE_VALUES
2525
from swift.common import client
2626
from swift.common import direct_client
27+
from swift.common.http import HTTP_CONFLICT
2728

2829

2930
class ConnectionPool(eventlet.pools.Pool):
@@ -152,7 +153,7 @@ def run(self):
152153
try:
153154
client.delete_container(self.url, self.token, container)
154155
except client.ClientException, e:
155-
if e.http_status != 409:
156+
if e.http_status != HTTP_CONFLICT:
156157
self._log_status("Unable to delete container '%s'. " \
157158
"Got http status '%d'." % (container, e.http_status))
158159

swift/common/direct_client.py

+15-13
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
from swift.common.bufferedhttp import http_connect
2929
from swift.common.client import ClientException, json_loads
3030
from swift.common.utils import normalize_timestamp
31+
from swift.common.http import HTTP_NO_CONTENT, HTTP_INSUFFICIENT_STORAGE, \
32+
is_success, is_server_error
3133

3234

3335
def quote(value, safe='/'):
@@ -69,7 +71,7 @@ def direct_get_account(node, part, account, marker=None, limit=None,
6971
'GET', path, query_string=qs)
7072
with Timeout(response_timeout):
7173
resp = conn.getresponse()
72-
if resp.status < 200 or resp.status >= 300:
74+
if not is_success(resp.status):
7375
resp.read()
7476
raise ClientException(
7577
'Account server %s:%s direct GET %s gave status %s' % (node['ip'],
@@ -81,7 +83,7 @@ def direct_get_account(node, part, account, marker=None, limit=None,
8183
resp_headers = {}
8284
for header, value in resp.getheaders():
8385
resp_headers[header.lower()] = value
84-
if resp.status == 204:
86+
if resp.status == HTTP_NO_CONTENT:
8587
resp.read()
8688
return resp_headers, []
8789
return resp_headers, json_loads(resp.read())
@@ -108,7 +110,7 @@ def direct_head_container(node, part, account, container, conn_timeout=5,
108110
with Timeout(response_timeout):
109111
resp = conn.getresponse()
110112
resp.read()
111-
if resp.status < 200 or resp.status >= 300:
113+
if not is_success(resp.status):
112114
raise ClientException(
113115
'Container server %s:%s direct HEAD %s gave status %s' %
114116
(node['ip'], node['port'],
@@ -157,7 +159,7 @@ def direct_get_container(node, part, account, container, marker=None,
157159
'GET', path, query_string=qs)
158160
with Timeout(response_timeout):
159161
resp = conn.getresponse()
160-
if resp.status < 200 or resp.status >= 300:
162+
if not is_success(resp.status):
161163
resp.read()
162164
raise ClientException(
163165
'Container server %s:%s direct GET %s gave stats %s' % (node['ip'],
@@ -169,7 +171,7 @@ def direct_get_container(node, part, account, container, marker=None,
169171
resp_headers = {}
170172
for header, value in resp.getheaders():
171173
resp_headers[header.lower()] = value
172-
if resp.status == 204:
174+
if resp.status == HTTP_NO_CONTENT:
173175
resp.read()
174176
return resp_headers, []
175177
return resp_headers, json_loads(resp.read())
@@ -185,7 +187,7 @@ def direct_delete_container(node, part, account, container, conn_timeout=5,
185187
with Timeout(response_timeout):
186188
resp = conn.getresponse()
187189
resp.read()
188-
if resp.status < 200 or resp.status >= 300:
190+
if not is_success(resp.status):
189191
raise ClientException(
190192
'Container server %s:%s direct DELETE %s gave status %s' %
191193
(node['ip'], node['port'],
@@ -218,7 +220,7 @@ def direct_head_object(node, part, account, container, obj, conn_timeout=5,
218220
with Timeout(response_timeout):
219221
resp = conn.getresponse()
220222
resp.read()
221-
if resp.status < 200 or resp.status >= 300:
223+
if not is_success(resp.status):
222224
raise ClientException(
223225
'Object server %s:%s direct HEAD %s gave status %s' %
224226
(node['ip'], node['port'],
@@ -256,7 +258,7 @@ def direct_get_object(node, part, account, container, obj, conn_timeout=5,
256258
'GET', path, headers=headers)
257259
with Timeout(response_timeout):
258260
resp = conn.getresponse()
259-
if resp.status < 200 or resp.status >= 300:
261+
if not is_success(resp.status):
260262
resp.read()
261263
raise ClientException(
262264
'Object server %s:%s direct GET %s gave status %s' %
@@ -326,7 +328,7 @@ def direct_put_object(node, part, account, container, name, contents,
326328
with Timeout(response_timeout):
327329
resp = conn.getresponse()
328330
resp.read()
329-
if resp.status < 200 or resp.status >= 300:
331+
if not is_success(resp.status):
330332
raise ClientException(
331333
'Object server %s:%s direct PUT %s gave status %s' %
332334
(node['ip'], node['port'],
@@ -361,7 +363,7 @@ def direct_post_object(node, part, account, container, name, headers,
361363
with Timeout(response_timeout):
362364
resp = conn.getresponse()
363365
resp.read()
364-
if resp.status < 200 or resp.status >= 300:
366+
if not is_success(resp.status):
365367
raise ClientException(
366368
'Object server %s:%s direct POST %s gave status %s' %
367369
(node['ip'], node['port'],
@@ -394,7 +396,7 @@ def direct_delete_object(node, part, account, container, obj,
394396
with Timeout(response_timeout):
395397
resp = conn.getresponse()
396398
resp.read()
397-
if resp.status < 200 or resp.status >= 300:
399+
if not is_success(resp.status):
398400
raise ClientException(
399401
'Object server %s:%s direct DELETE %s gave status %s' %
400402
(node['ip'], node['port'],
@@ -440,8 +442,8 @@ def retry(func, *args, **kwargs):
440442
except ClientException, err:
441443
if error_log:
442444
error_log(err)
443-
if attempts > retries or err.http_status < 500 or \
444-
err.http_status == 507 or err.http_status > 599:
445+
if attempts > retries or not is_server_error(err.http_status) or \
446+
err.http_status == HTTP_INSUFFICIENT_STORAGE:
445447
raise
446448
sleep(backoff)
447449
backoff *= 2

swift/common/http.py

+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
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+
from webob.exc import HTTPClientError,\
17+
HTTPInsufficientStorage as BaseHTTPInsufficientStorage
18+
19+
20+
class HTTPClientDisconnect(HTTPClientError):
21+
"""
22+
subclass of :class:`~HTTPClientError`
23+
24+
This code is introduced to log the case when the connection is closed by
25+
client while HTTP server is processing its request
26+
27+
code: 499, title: Client Disconnect
28+
"""
29+
code = 499
30+
title = 'Client Disconnect'
31+
explanation = (
32+
'This code is introduced to log the case when the connection '
33+
'is closed by client while HTTP server is processing its request')
34+
35+
36+
class HTTPInsufficientStorage(BaseHTTPInsufficientStorage):
37+
"""
38+
subclass of :class:`~HTTPInsufficientStorage`
39+
40+
The server is unable to store the representation needed to
41+
complete the request.
42+
43+
code: 507, title: Insufficient Storage
44+
"""
45+
def __init__(self, drive=None, *args, **kwargs):
46+
if drive:
47+
self.explanation = ('%s is not mounted' % drive)
48+
super(HTTPInsufficientStorage, self).__init__(*args, **kwargs)
49+
50+
51+
def is_informational(status):
52+
"""
53+
Check if HTTP status code is informational.
54+
55+
:param status: http status code
56+
:returns: True if status is successful, else False
57+
"""
58+
return 100 <= status and status <= 199
59+
60+
61+
def is_success(status):
62+
"""
63+
Check if HTTP status code is successful.
64+
65+
:param status: http status code
66+
:returns: True if status is successful, else False
67+
"""
68+
return 200 <= status and status <= 299
69+
70+
71+
def is_redirection(status):
72+
"""
73+
Check if HTTP status code is redirection.
74+
75+
:param status: http status code
76+
:returns: True if status is redirection, else False
77+
"""
78+
return 300 <= status and status <= 399
79+
80+
81+
def is_client_error(status):
82+
"""
83+
Check if HTTP status code is client error.
84+
85+
:param status: http status code
86+
:returns: True if status is client error, else False
87+
"""
88+
return 400 <= status and status <= 499
89+
90+
91+
def is_server_error(status):
92+
"""
93+
Check if HTTP status code is server error.
94+
95+
:param status: http status code
96+
:returns: True if status is server error, else False
97+
"""
98+
return 500 <= status and status <= 599
99+
100+
101+
# List of HTTP status codes
102+
103+
###############################################################################
104+
## 1xx Informational
105+
###############################################################################
106+
107+
HTTP_CONTINUE = 100
108+
HTTP_SWITCHING_PROTOCOLS = 101
109+
HTTP_PROCESSING = 102 # WebDAV
110+
HTTP_CHECKPOINT = 103
111+
HTTP_REQUEST_URI_TOO_LONG = 122
112+
113+
###############################################################################
114+
## 2xx Success
115+
###############################################################################
116+
117+
HTTP_OK = 200
118+
HTTP_CREATED = 201
119+
HTTP_ACCEPTED = 202
120+
HTTP_NON_AUTHORITATIVE_INFORMATION = 203
121+
HTTP_NO_CONTENT = 204
122+
HTTP_RESET_CONTENT = 205
123+
HTTP_PARTIAL_CONTENT = 206
124+
HTTP_MULTI_STATUS = 207 # WebDAV
125+
HTTP_IM_USED = 226
126+
127+
###############################################################################
128+
## 3xx Redirection
129+
###############################################################################
130+
131+
HTTP_MULTIPLE_CHOICES = 300
132+
HTTP_MOVED_PERMANENTLY = 301
133+
HTTP_FOUND = 302
134+
HTTP_SEE_OTHER = 303
135+
HTTP_NOT_MODIFIED = 304
136+
HTTP_USE_PROXY = 305
137+
HTTP_SWITCH_PROXY = 306
138+
HTTP_TEMPORARY_REDIRECT = 307
139+
HTTP_RESUME_INCOMPLETE = 308
140+
141+
###############################################################################
142+
## 4xx Client Error
143+
###############################################################################
144+
145+
HTTP_BAD_REQUEST = 400
146+
HTTP_UNAUTHORIZED = 401
147+
HTTP_PAYMENT_REQUIRED = 402
148+
HTTP_FORBIDDEN = 403
149+
HTTP_NOT_FOUND = 404
150+
HTTP_METHOD_NOT_ALLOWED = 405
151+
HTTP_NOT_ACCEPTABLE = 406
152+
HTTP_PROXY_AUTHENTICATION_REQUIRED = 407
153+
HTTP_REQUEST_TIMEOUT = 408
154+
HTTP_CONFLICT = 409
155+
HTTP_GONE = 410
156+
HTTP_LENGTH_REQUIRED = 411
157+
HTTP_PRECONDITION_FAILED = 412
158+
HTTP_REQUEST_ENTITY_TOO_LARGE = 413
159+
HTTP_REQUEST_URI_TOO_LONG = 414
160+
HTTP_UNSUPPORTED_MEDIA_TYPE = 415
161+
HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416
162+
HTTP_EXPECTATION_FAILED = 417
163+
HTTP_IM_A_TEAPOT = 418
164+
HTTP_UNPROCESSABLE_ENTITY = 422 # WebDAV
165+
HTTP_LOCKED = 423 # WebDAV
166+
HTTP_FAILED_DEPENDENCY = 424 # WebDAV
167+
HTTP_UNORDERED_COLLECTION = 425
168+
HTTP_UPGRADE_REQUIED = 426
169+
HTTP_PRECONDITION_REQUIRED = 428
170+
HTTP_TOO_MANY_REQUESTS = 429
171+
HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431
172+
HTTP_NO_RESPONSE = 444
173+
HTTP_RETRY_WITH = 449
174+
HTTP_BLOCKED_BY_WINDOWS_PARENTAL_CONTROLS = 450
175+
HTTP_CLIENT_CLOSED_REQUEST = 499
176+
177+
###############################################################################
178+
## 5xx Server Error
179+
###############################################################################
180+
181+
HTTP_INTERNAL_SERVER_ERROR = 500
182+
HTTP_NOT_IMPLEMENTED = 501
183+
HTTP_BAD_GATEWAY = 502
184+
HTTP_SERVICE_UNAVAILABLE = 503
185+
HTTP_GATEWAY_TIMEOUT = 504
186+
HTTP_VERSION_NOT_SUPPORTED = 505
187+
HTTP_VARIANT_ALSO_NEGOTIATES = 506
188+
HTTP_INSUFFICIENT_STORAGE = 507 # WebDAV
189+
HTTP_BANDWIDTH_LIMIT_EXCEEDED = 509
190+
HTTP_NOT_EXTENDED = 510
191+
HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511
192+
HTTP_NETWORK_READ_TIMEOUT_ERROR = 598 # not used in RFC
193+
HTTP_NETWORK_CONNECT_TIMEOUT_ERROR = 599 # not used in RFC

0 commit comments

Comments
 (0)