Developing your own Swift middleware OpenStack Summit Atlanta, May - - PowerPoint PPT Presentation

developing your own swift middleware openstack summit
SMART_READER_LITE
LIVE PREVIEW

Developing your own Swift middleware OpenStack Summit Atlanta, May - - PowerPoint PPT Presentation

Developing your own Swift middleware OpenStack Summit Atlanta, May 2014 About me Christian Schwede Developer @ eNovance Mostly working on Swift, testing and automation Started using Swift in 2012 Agenda Using middlewares


slide-1
SLIDE 1

Developing your own Swift middleware OpenStack Summit Atlanta, May 2014

slide-2
SLIDE 2

About me

  • Christian Schwede
  • Developer @ eNovance
  • Mostly working on Swift, testing and automation
  • Started using Swift in 2012
slide-3
SLIDE 3

Agenda

  • Using middlewares to extend Swift functionality
  • Introduction to wsgi, middlewares and paste.deploy
  • Developing our own middleware for Swift Proxy
  • Testing & Packaging
  • References
slide-4
SLIDE 4

Writing Swift middlewares?

slide-5
SLIDE 5

Swift middlewares?

  • Most of Swift features are implemented as a middleware

○ logging, tempurl, dlo, ratelimit, tempauth, quotas, ...

  • Flexibility to extend existing functionality
  • No need to fork or modify existing code
  • Several additional middlewares outside of Swift
slide-6
SLIDE 6

wsgi and middlewares?

slide-7
SLIDE 7

wsgi

  • simple interface between web servers & web applications
  • defined in PEP0333 and PEP3333
  • application

○ callable object (with a __call__ method)

  • server

○ invokes the callable once for each client request

Client Server App

slide-8
SLIDE 8

application objects

  • must accept two positional arguments

○ environ: Python dictionary ○ start_response: callable ■ status = „200 OK“ ■ headers = [(„header_name“, „header_value“), ]

slide-9
SLIDE 9

environ

  • REQUEST_METHOD
  • PATH_INFO
  • QUERY_STRING
  • HTTP_HEADERNAME
  • wsgi.input
slide-10
SLIDE 10

from wsgiref.simple_server import make_server def myapp(environ, start_response): body = [] body.append("PATH_INFO: '%s'\n" % environ.get('PATH_INFO')) headers = [('Content-Type', 'text/plain')] start_response('200 OK', headers) return body srv = make_server('localhost', 8000, myapp) srv.serve_forever()

Sample server

slide-11
SLIDE 11

middleware

  • can act as a server for an application and vice versa
  • run multiple applications side-by-side
  • authentication
  • rerouting a request
  • content processing

Client Server App Middleware

slide-12
SLIDE 12

class SummitMiddleware(object): def __init__(self, app, *args, **kwargs): self.app = app def __call__(self, env, start_response): response = self.app(env, start_response) if env.get('PATH_INFO') == '/echo': length = int(env.get('CONTENT_LENGTH') or 0) return env.get('wsgi.input').read(length) return response srv = make_server(‘localhost’, 8000, SummitMiddleware(myapp))

Sample middleware

slide-13
SLIDE 13

Testing, packaging & deploying

slide-14
SLIDE 14

class FakeApp(object): def __call__(self, env, start_response): start_response('200 OK', []) return "" class TestSummitMiddleware(unittest.TestCase): def test_simple_request(self): environ = {'REQUEST_METHOD': 'PUT'} req = Request.blank('/echo', environ, body="Hello World") mw = SummitMiddleware(FakeApp()) resp = req.get_response(mw) self.assertEqual("Hello World", resp.body)

Testing a middleware

slide-15
SLIDE 15

paste.deploy

  • load WSGI applications and servers from URI
  • uses INI-style configuration files
  • separates config from code
  • Paste Script can serve applications from config files
  • widely used in Openstack
slide-16
SLIDE 16

[app:sample] use = egg:sample#app [filter:middleware] use = egg:sample#middleware suffix = /echoresponse [pipeline:main] pipeline = middleware sample [server:main] use = egg:Paste#http port = 8000

config.ini for paste.deploy

slide-17
SLIDE 17

setup(name='sample', packages=['sample', ], zip_safe=False, entry_points={ 'paste.app_factory': ['app=sample.app:app_factory'], 'paste.filter_factory': ['middleware = sample.middleware: filter_factory'] })

setup.py

slide-18
SLIDE 18

Writing a Swift middleware

slide-19
SLIDE 19

Preview middleware

  • PUT

○ create a small preview image and store it separate

  • GET

○ return preview if QUERY_STRING contains “preview”

  • DELETE

○ also delete preview if exists

slide-20
SLIDE 20

Useful helpers

  • swift.common.utils.split_path

path = /v1/AUTH_account/test/img.jpg ver, acc, cont, obj = split_path(path)

  • swift.common.wsgi.make_subrequest

○ add middleware after authentication middleware

  • swift.common.swob.wsgify

○ decorator

slide-21
SLIDE 21

@wsgify def __call__(self, request): # request.params # request.path_info # request.method # request.environ # request.body return self.app

wsgify?

slide-22
SLIDE 22

@wsgify def __call__(self, req): try: (ver, acc, con, obj) = split_path(req.path_info, 4, 4, True) except ValueError: return self.app preview_path= '/%s/%s/%s_%s/%s' % (ver, acc, con, self.suffix, obj) if req.method == 'GET' and request.params.has_key('preview'): req.path_info = preview_path

Return preview

slide-23
SLIDE 23

Extract preview

if req.method == 'PUT': preview = create_preview(request.body) if preview: sub = wsgi.make_subrequest( request.environ, path=preview_path, body=preview) sub.get_response(self.app)

slide-24
SLIDE 24

Delete preview

if req.method == 'DELETE': sub = wsgi.make_subrequest(req.environ, path=preview_path) sub.get_response(self.app) return self.app

slide-25
SLIDE 25

References

slide-26
SLIDE 26

3rd party middlewares

  • swauth - github.com/gholt/swauth
  • swift3 - github.com/stackforge/swift3
  • CDMI - github.com/osaddon/cdmi
  • Swift informant - github.com/pandemicsyn/swift-informant
  • Swift Origin Server - github.com/dpgoetz/sos
  • Ceilometer - ceilometer/objectstore/swift_middleware.py
slide-27
SLIDE 27
  • github.com/enovance/swift-middleware-sample
  • docs.openstack.org/developer/swift/

○ middleware.html ○ development_middleware.html ○ development_auth.html ○ associated_projects.html

  • legacy.python.org/dev/peps/pep-3333

Something to read

slide-28
SLIDE 28

THANK YOU!

christian@enovance.com | @cschwede_de | OpenStack Juno Summit | May 2014, Atlanta