1)
Method-1
=========
http://docs.repoze.org/moonshining/pep333.htmla)
Open a file named "myapplication.py" and add following code.
##Our Application
def green(environ, start_response):
"""
Simplest possible application object
"""
status = '200 OK'
response_headers = [('Content-Type', 'text/plain')]
start_response(status, response_headers)
return ['%s\n' % environ.get('GREETING', 'Hello world!')]
##Middleware-1/Filter-1
##Class as a middleware component
class Caseless:
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
for chunk in self.app(environ, start_response):
yield chunk.lower()
##Middleware-2/Filter-2
##closure or nested function or decorator as a middleware component
def greeting_setter(app):
def _curried(environ, start_response):
environ['GREETING'] = 'Bonjour, le monde!'
return app(environ, start_response)
return _curried
##Run your application "green" under the "Paste" webserver.
if __name__ == '__main__':
from paste import httpserver
from caseless import Caseless
httpserver.serve(Caseless(greeting_setter(green)),
host='127.0.0.1', port='8080')
b)
#easy_install Paste
c)
##Run the application
#python myapplication.py
2)
Method-2 (OpenStack Using this method for API service)
=================================
http://docs.repoze.org/moonshining/tools/paste.htmla)
Open a file named "configuration.ini" and add following code
[app:green]
paste.app_factory = myapplication:app_factory
[filter:caseless]
paste.filter_app_factory = myapplication:filter_caseless_factory
[filter:greetingsetter]
paste.filter_app_factory = myapplication:filter_greeting_setter_factory
[pipeline:main]
pipeline = caseless greetingsetter green
[server:main]
use = egg:Paste#http
host = 127.0.0.1
port = 8080
b)
Open a file named "myapplication.py" and add following code.
##Our Application
def green(environ, start_response):
"""
Simplest possible application object
"""
status = '200 OK'
response_headers = [('Content-Type', 'text/plain')]
start_response(status, response_headers)
return ['%s\n' % environ.get('GREETING', 'Hello world!')]
##Middleware-1/Filter-1
##Class as a middleware component
class Caseless:
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
for chunk in self.app(environ, start_response):
yield chunk.lower()
##Middleware-2/Filter-2
##closure or nested function or decorator as a middleware component
def greeting_setter(app):
def _curried(environ, start_response):
environ['GREETING'] = 'Bonjour, le monde!'
return app(environ, start_response)
return _curried
##Factory to get middleware "Caseless" warapped application instance
def filter_caseless_factory(app, global_config):
return Caseless(app)
##Factory to get middleware "greeting_setter" warapped application instance
def filter_greeting_setter_factory(app, global_config):
return greeting_setter(app)
c)
#easy_install Paste
#easy_install PasteDeploy
#easy_install PasteScript
d)
##Run the application
#paster serve configuration.ini
3)
Example from OpenStack
=======================
a)heat-api Service:
heat/heat/bin/heat-api
https://github.com/openstack/heat/blob/master/bin/heat-api
from heat.common import config
from heat.common import wsgi
if __name__ == '__main__':
##This line will return all middleware/filter wrapped apllication instance based on pipeine in the .ini file.
app = config.load_paste_app() <=== IMP
##Following line run your application using "eventlet green thread"
##See https://github.com/openstack/heat/blob/master/heat/common/wsgi.py
server = wsgi.Server()
server.start(app, cfg.CONF.heat_api, default_port=port)
server.wait()
b)
heat/heat/common/config.py
https://github.com/openstack/heat/blob/master/heat/common/config.py
from heat.common import wsgi
def load_paste_app(app_name=None):
"""
Builds and returns a WSGI app from a paste config file.
conf_file = /etc/heat/api-paste.ini
app_name = heat-api
"""
app = wsgi.paste_deploy_app(conf_file, app_name, cfg.CONF)
return app
c)
heat/heat/common/wsgi.py
https://github.com/openstack/heat/blob/master/heat/common/wsgi.py
from paste import deploy
def paste_deploy_app(paste_config_file, app_name, conf):
setup_paste_factories(conf) <===
try:
return deploy.loadapp("config:%s" % paste_config_file, name=app_name)
finally:
teardown_paste_factories()
def setup_paste_factories(conf):
global app_factory, filter_factory <===
app_factory = AppFactory(conf) <===
filter_factory = FilterFactory(conf) <===
class AppFactory(BasePasteFactory):
KEY = 'heat.app_factory' <===
def __call__(self, global_conf, **local_conf):
"""
The actual paste.app_factory protocol method.
"""
factory = self._import_factory(local_conf) <===
##Example of factory (app factory) : "heat.api.openstack.v1.API"
return factory(self.conf, **local_conf)
class FilterFactory(AppFactory):
KEY = 'heat.filter_factory'
def __call__(self, global_conf, **local_conf):
"""
The actual paste.filter_factory protocol method.
"""
factory = self._import_factory(local_conf) <===
##Example of factory (filter factory) : "heat.api.openstack.faultwrap_filter"
def filter(app): <===
return factory(app, self.conf, **local_conf)
return filter
class BasePasteFactory(object):
"""
Import an app/filter class.
Lookup the KEY from the PasteDeploy local conf and import the
class named there. This class can then be used as an app or
filter factory.
"""
KEY = None
def __init__(self, conf):
self.conf = conf
def __call__(self, global_conf, **local_conf):
raise NotImplementedError
def _import_factory(self, local_conf):
class_name = local_conf[self.KEY].replace(':', '.').strip()
##Example of class_name : "heat.api.openstack.v1.API", "heat.api.openstack.faultwrap_filter"
return importutils.import_class(class_name)
4)
api-paste.ini
===========
https://github.com/openstack/heat/blob/master/etc/heat/api-paste.inia)
[server:main]
--------------------
* In /etc/heat/api-paste.ini you can not find the section [server:main], because OpenStack explicitly using "paste.deploy.loadapp" to get the Middlewares/Filters wrapped WSGI application instance.
* You can check the following lines in the file https://github.com/openstack/heat/blob/master/heat/common/wsgi.py
def paste_deploy_app(paste_config_file, app_name, conf):
"""
paste_config_file = /etc/heat/api-paste.ini
app_name = heat-api
"""
setup_paste_factories(conf)
try:
return deploy.loadapp("config:%s" % paste_config_file, name=app_name) <===
finally:
teardown_paste_factories()
b)
[pipeline:main]
-----------------------
* In /etc/heat/api-paste.ini you can not find the section [pipeline:main], because we are passinf the name of the pipeline to the method "paste.deploy.loadapp" as "name=app_name". Here value of the variable "app_name" is "heat-api", so that will load the pipeline "[pipeline:heat-api]" defined in the https://github.com/openstack/heat/blob/master/etc/heat/api-paste.ini.
* Also note that, same paste config file https://github.com/openstack/heat/blob/master/etc/heat/api-paste.ini is used for "heat-api", "heat-api-cfn" and "heat-api-cloudwatch". So having one 'main' wouldn't work.
def paste_deploy_app(paste_config_file, app_name, conf):
"""
paste_config_file = /etc/heat/api-paste.ini
app_name = heat-api
"""
setup_paste_factories(conf)
try:
return deploy.loadapp("config:%s" % paste_config_file, name=app_name) <===
finally:
teardown_paste_factories()
OpenStack APIs and WSGI
ReplyDeletehttp://www.slideshare.net/lhrc_mikeyp/openstack-apis-and-wsgi
what is api-paste.ini file in openstack
ReplyDeletehttp://stackoverflow.com/questions/18952315/what-is-api-paste-ini-file-in-openstack
proposed replacing the WSGI framework in Oslo with a combination of Pecan and WSME
ReplyDeletehttps://etherpad.openstack.org/p/havana-common-wsgi
https://etherpad.openstack.org/p/grizzly-common-wsgi-frameworks
PECAN
http://pecan.readthedocs.org/en/latest/
WSME
http://pythonhosted.org/WSME/