Added doc strings and pointers to docs for swift3

This commit is contained in:
Chuck Thier 2011-01-14 13:49:05 -06:00
parent d0651b914d
commit e2c0a23839
4 changed files with 107 additions and 21 deletions

View File

@ -31,7 +31,7 @@ Installing dependencies and the core code
#. `apt-get install curl gcc bzr memcached python-configobj #. `apt-get install curl gcc bzr memcached python-configobj
python-coverage python-dev python-nose python-setuptools python-simplejson python-coverage python-dev python-nose python-setuptools python-simplejson
python-xattr sqlite3 xfsprogs python-webob python-eventlet python-xattr sqlite3 xfsprogs python-webob python-eventlet
python-greenlet python-pastedeploy` python-greenlet python-pastedeploy python-netifaces`
#. Install anything else you want, like screen, ssh, vim, etc. #. Install anything else you want, like screen, ssh, vim, etc.
#. Next, choose either :ref:`partition-section` or :ref:`loopback-section`. #. Next, choose either :ref:`partition-section` or :ref:`loopback-section`.

View File

@ -21,6 +21,7 @@ And the following python libraries:
* Xattr * Xattr
* Nose * Nose
* Sphinx * Sphinx
* netifaces
----------- -----------
Development Development
@ -38,4 +39,4 @@ Production
If you want to set up and configure Swift for a production cluster, the following doc should be useful: If you want to set up and configure Swift for a production cluster, the following doc should be useful:
* :doc:`Multiple Server Swift Installation <howto_installmultinode>` * :doc:`Multiple Server Swift Installation <howto_installmultinode>`

View File

@ -122,3 +122,11 @@ Ratelimit
.. automodule:: swift.common.middleware.ratelimit .. automodule:: swift.common.middleware.ratelimit
:members: :members:
:show-inheritance: :show-inheritance:
Swift3
======
.. automodule:: swift.common.middleware.swift3
:members:
:show-inheritance:

View File

@ -32,25 +32,32 @@ MAX_BUCKET_LISTING = 1000
def get_err_response(code): def get_err_response(code):
error_table = {'AccessDenied': """
(403, 'Access denied'), Given an HTTP response code, create a properly formatted xml error response
'BucketAlreadyExists':
(409, 'The requested bucket name is not available'), :param code: error code
'BucketNotEmpty': :returns: webob.response object
(409, 'The bucket you tried to delete is not empty'), """
'InvalidArgument': error_table = {
(400, 'Invalid Argument'), 'AccessDenied':
'InvalidBucketName': (403, 'Access denied'),
(400, 'The specified bucket is not valid'), 'BucketAlreadyExists':
'InvalidURI': (409, 'The requested bucket name is not available'),
(400, 'Could not parse the specified URI'), 'BucketNotEmpty':
'NoSuchBucket': (409, 'The bucket you tried to delete is not empty'),
(404, 'The specified bucket does not exist'), 'InvalidArgument':
'SignatureDoesNotMatch': (400, 'Invalid Argument'),
(403, 'The calculated request signature does not match '\ 'InvalidBucketName':
'your provided one'), (400, 'The specified bucket is not valid'),
'NoSuchKey': 'InvalidURI':
(404, 'The resource you requested does not exist')} (400, 'Could not parse the specified URI'),
'NoSuchBucket':
(404, 'The specified bucket does not exist'),
'SignatureDoesNotMatch':
(403, 'The calculated request signature does not match '\
'your provided one'),
'NoSuchKey':
(404, 'The resource you requested does not exist')}
resp = Response(content_type='text/xml') resp = Response(content_type='text/xml')
resp.status = error_table[code][0] resp.status = error_table[code][0]
@ -71,12 +78,18 @@ class Controller(object):
class ServiceController(Controller): class ServiceController(Controller):
"""
Handles account level requests.
"""
def __init__(self, env, app, account_name, token, **kwargs): def __init__(self, env, app, account_name, token, **kwargs):
Controller.__init__(self, app) Controller.__init__(self, app)
env['HTTP_X_AUTH_TOKEN'] = token env['HTTP_X_AUTH_TOKEN'] = token
env['PATH_INFO'] = '/v1/%s' % account_name env['PATH_INFO'] = '/v1/%s' % account_name
def GET(self, env, start_response): def GET(self, env, start_response):
"""
Handle GET Service request
"""
env['QUERY_STRING'] = 'format=json' env['QUERY_STRING'] = 'format=json'
body_iter = self.app(env, self.do_start_response) body_iter = self.app(env, self.do_start_response)
status = int(self.response_args[0].split()[0]) status = int(self.response_args[0].split()[0])
@ -105,6 +118,9 @@ class ServiceController(Controller):
class BucketController(Controller): class BucketController(Controller):
"""
Handles bucket request.
"""
def __init__(self, env, app, account_name, token, container_name, def __init__(self, env, app, account_name, token, container_name,
**kwargs): **kwargs):
Controller.__init__(self, app) Controller.__init__(self, app)
@ -113,6 +129,9 @@ class BucketController(Controller):
env['PATH_INFO'] = '/v1/%s/%s' % (account_name, container_name) env['PATH_INFO'] = '/v1/%s/%s' % (account_name, container_name)
def GET(self, env, start_response): def GET(self, env, start_response):
"""
Handle GET Bucket (List Objects) request
"""
if 'QUERY_STRING' in env: if 'QUERY_STRING' in env:
args = dict(cgi.parse_qsl(env['QUERY_STRING'])) args = dict(cgi.parse_qsl(env['QUERY_STRING']))
else: else:
@ -170,6 +189,9 @@ class BucketController(Controller):
return Response(body=body, content_type='text/xml') return Response(body=body, content_type='text/xml')
def PUT(self, env, start_response): def PUT(self, env, start_response):
"""
Handle PUT Bucket request
"""
body_iter = self.app(env, self.do_start_response) body_iter = self.app(env, self.do_start_response)
status = int(self.response_args[0].split()[0]) status = int(self.response_args[0].split()[0])
headers = dict(self.response_args[1]) headers = dict(self.response_args[1])
@ -188,6 +210,9 @@ class BucketController(Controller):
return resp return resp
def DELETE(self, env, start_response): def DELETE(self, env, start_response):
"""
Handle DELETE Bucket request
"""
body_iter = self.app(env, self.do_start_response) body_iter = self.app(env, self.do_start_response)
status = int(self.response_args[0].split()[0]) status = int(self.response_args[0].split()[0])
headers = dict(self.response_args[1]) headers = dict(self.response_args[1])
@ -208,6 +233,9 @@ class BucketController(Controller):
class ObjectController(Controller): class ObjectController(Controller):
"""
Handles requests on objects
"""
def __init__(self, env, app, account_name, token, container_name, def __init__(self, env, app, account_name, token, container_name,
object_name, **kwargs): object_name, **kwargs):
Controller.__init__(self, app) Controller.__init__(self, app)
@ -239,12 +267,21 @@ class ObjectController(Controller):
return get_err_response('InvalidURI') return get_err_response('InvalidURI')
def HEAD(self, env, start_response): def HEAD(self, env, start_response):
"""
Handle HEAD Object request
"""
return self.GETorHEAD(env, start_response) return self.GETorHEAD(env, start_response)
def GET(self, env, start_response): def GET(self, env, start_response):
"""
Handle GET Object request
"""
return self.GETorHEAD(env, start_response) return self.GETorHEAD(env, start_response)
def PUT(self, env, start_response): def PUT(self, env, start_response):
"""
Handle PUT Object and PUT Object (Copy) request
"""
for key, value in env.items(): for key, value in env.items():
if key.startswith('HTTP_X_AMZ_META_'): if key.startswith('HTTP_X_AMZ_META_'):
del env[key] del env[key]
@ -269,6 +306,9 @@ class ObjectController(Controller):
return Response(status=200, etag=headers['etag']) return Response(status=200, etag=headers['etag'])
def DELETE(self, env, start_response): def DELETE(self, env, start_response):
"""
Handle DELETE Object request
"""
body_iter = self.app(env, self.do_start_response) body_iter = self.app(env, self.do_start_response)
status = int(self.response_args[0].split()[0]) status = int(self.response_args[0].split()[0])
headers = dict(self.response_args[1]) headers = dict(self.response_args[1])
@ -287,6 +327,42 @@ class ObjectController(Controller):
class Swift3Middleware(object): class Swift3Middleware(object):
"""
The swift3 middleware will emulate the S3 REST api on top of swift.
The following opperations are currently supported:
* GET Service
* DELETE Bucket
* GET Bucket (List Objects)
* PUT Bucket
* DELETE Object
* GET Object
* HEAD Object
* PUT Object
* PUT Object (Copy)
To add this middleware to your configuration, add the swift3 middleware
in front of the auth middleware, and before any other middleware that
look at swift requests (like rate limiting).
To set up your client, the access key will be the account string that
should look like AUTH_d305e9dbedbc47df8b25ab46f3152f81, and the
secret access key is the account password. The host should also point
to the swift storage hostname. It also will have to use the old style
calling format, and not the hostname based container format.
An example client using the python boto library might look like the
following for an SAIO setup::
connection = boto.s3.Connection(
aws_access_key_id='AUTH_d305e9dbedbc47df8b25ab46f3152f81',
aws_secret_access_key='testing',
port=8080,
host='127.0.0.1',
is_secure=False,
calling_format=boto.s3.connection.OrdinaryCallingFormat())
"""
def __init__(self, app, conf, *args, **kwargs): def __init__(self, app, conf, *args, **kwargs):
self.app = app self.app = app
@ -352,6 +428,7 @@ class Swift3Middleware(object):
def filter_factory(global_conf, **local_conf): def filter_factory(global_conf, **local_conf):
"""Standard filter factory to use the middleware with paste.deploy"""
conf = global_conf.copy() conf = global_conf.copy()
conf.update(local_conf) conf.update(local_conf)