Chinaunix首页 | 论坛 | 博客
  • 博客访问: 18911
  • 博文数量: 4
  • 博客积分: 170
  • 博客等级: 入伍新兵
  • 技术积分: 52
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-28 09:25
个人简介

帝都码农

文章分类

全部博文(4)

文章存档

2013年(1)

2012年(3)

我的朋友

分类: 云计算

2012-12-20 11:08:46

Pasted Deployment是一套查找和配置WSGI应用和服务的系统。向WSGI application(WSGI应用,可调用对象)的用户提 供了一个简单的函数(loadapp)来从配置文件或是python的egg包中加载WSGI application。调用WSGI application的程序只要求你的程序提供一个简单的单独的访问入口,所以application发布者并不需要暴露application的内部 的实现细节。

这样的好处是系统管理员可以很容易的安装和管理,并不需要掌握python,或是WSGI Application的细节和它的container。 目前Paste Deployment不需要依赖Paste项目中的其他部分,可以单独做为一个安装包。 Paste Deploy使用MIT协议发布。

Paste Deploy已经发布了1.0版本,是个活跃的开发项目。在1.0版本中,做了很多工作使它向后兼容,会在必要时包含对一些不再推荐使用的功能的警告。

名词解释
  • application:应用,符合WSGI规范的可调用对象,接受参数(environ, start_response),调用start_response返回状态和HTTP消息头,返回结果作为消息体。
  • filter:过滤器,可调用对象,类似python中的装饰器(decorator),接受一个application对象作为参数,返回一个封装后的application。
  • app_factory:可调用对象,接受参数(global_config, **local_conf),返回application对象。
  • composite_factory:可调用对象,接受参数(loader, global_config, **local_conf),loader有几个方法, get_app用于获取wsgi_app, get_filter用于加载filter, 返回application对象。
  • filter_factory:可调用对象,接受参数(global_config, **local_conf),返回filter对象

Paste Deploy最主要的一方面是它定义的entry points(像paste.app_factory)

paste.deploy用的最多的是通过它的配置文件。

配置文件分为不同的段(section),Paste Deply关心的几个段(section)都有前缀,像 app:main 还有 filter:errors ————冒号后面的部分是段的名字(name of section),冒号前的部分给出段的类型(type of section)。其他的段(section)会被忽略。

paste配置文件就是普通的INI文件格式,可以使用缩进的多行来作为一行的延续。开头的”#”井号或是”;”分号后面是注释。 格式像下面这样定义


点击(此处)折叠或打开

  1. [section_name]
  2. key = value
  3. another key = a long value
  4.     that extends over multiple lines

所有的值都是字符串(不需要用引号括起来),每个段的名字和段中值的名字都是大小写敏感的,可以包含标点符号和空白符,最后键和值两边的空白符都会被去掉。以空白符开始的行被认为是上一行的延续。

通常会添加两个段,一个叫做main的应用段([app:main])和一个服务段([server:main])。[composite:...]表示转发到多个应用的东西。

下面是一个典型的配置文件使用了paste.urlmap来组合多个应用。


点击(此处)折叠或打开

  1. [composite:main]
  2. use = egg:Paste#urlmap
  3. / = home
  4. /blog = blog
  5. /wiki = wiki
  6. /cms = config:cms.ini

  7. [app:home]
  8. use = egg:Paste#static
  9. document_root = %(here)s/htdocs

  10. [filter-app:blog]
  11. use = egg:Authentication#auth
  12. next = blogapp
  13. roles = admin
  14. htpasswd = /home/me/users.htpasswd

  15. [app:blogapp]
  16. use = egg:BlogApp
  17. database = sqlite:/home/me/blog.db

  18. [app:wiki]
  19. use = call:mywiki.main:application
  20. database = sqlite:/home/me/wiki.db

下面解释详细解释每一段:


点击(此处)折叠或打开

  1. [composite:main]
  2. use = egg:Paste#urlmap
  3. / = home
  4. /blog = blog
  5. /wiki = wiki
  6. /cms = config:cms.ini


这是一个composite段,它会转发请求到其他的应用。use = egg:Paste#urlmap 表示使用paste包中的叫做urlmap的 composite applicationurlmap 是一个通用的 composite application —— 它把请求转到其他的应用。这里有几个应用,像”home”, “blog”, “wiki”和”config:cms.ini”。最后一个只是指向同一个文件夹下的cms.ini配置文件。

接下来:

点击(此处)折叠或打开

  1. [app:home]
  2. use = egg:Paste#static
  3. document_root = %(here)s/htdocs

egg:Paste#static 是另一个简单的应用,处理非动态文件。需要参数 document_root, 指定静态文件根目录。还可以使用变量替换,变量是在[DEFAULT]段中定义的,定义替换变量作用标签 %(var_name)s。上面用到的特殊变量 %(here)s 指这个配置文件所在的文件夹。

接下来,看看


点击(此处)折叠或打开

  1. [filter-app:blog]
  2. use = egg:Authentication#auth
  3. next = blogapp
  4. roles = admin
  5. htpasswd = /home/me/users.htpasswd

  6. [app:blogapp]
  7. use = egg:BlogApp
  8. database = sqlite:/home/me/blog.db

[filter-app:blog]段是用到应用上的过滤器(filter)。next字段指定了这个filter应用到哪个应用上。

第二个段只是指向BlogApp应用,database会做为参数传递到应用中。

最后


点击(此处)折叠或打开

  1. [app:wiki]
  2. use = call:mywiki.main:application
  3. database = sqlite:/home/me/wiki.db

这个段和前一个段很像,一个重要的不同点是它直接指向mysiki.main模块中的应用而不是egg包中的入口点(entry point)。指向哪个应用定义由冒号分隔的两部分组成:冒号左边的模块的名字,右边是从模块中引用的应用。

以上就是最常用的功能。

配置文件中的DEFAULT段的选项会被作为全局变量。在其他段中的选项做为局部变量传到相应的application中,如果局部选项中的键和 DEFAULT中的键一样,局部选项中键会被忽略(global_config和local_config中都没有),如果想覆盖全局变量中的键值,使用set字段,如


点击(此处)折叠或打开

  1. DEFAULT]
  2. name = TEST
  3. version = 1.0

  4. [app:test]
  5. use = call:test:test
  6. version = 2.0
  7. set name = test

使用loadapp生成test应用时,会调用test.test,和调用app_factory一样,传入global_config和 local_config,global_config中name=test,被局部配置覆盖了,global_config中version还是 1.0,局部配置中没有version。

使用call时是会转成相应的factory(app转成app_factory,filter转成 filter_factory,composite转成composite_factory)但是调用的方法名,只能是函数,不能是类的方法,虽然在代码 注释中写可以导入如”obj.method”,但是其在引入可调用对象时是直接使用getattr会报错,还是不能有点”.”

示例代码如下:test_wsgi.ini


点击(此处)折叠或打开

  1. [DEFAULT]
  2. name = TEST
  3. version = 1.0

  4. [app:test1]
  5. paste.app_factory = test_wsgi:TestApp.factory
  6. version = 2.0
  7. set name = test

  8. [app:test2]
  9. use = call:test_wsgi:test2_factory
  10. version = 2.0
  11. set name = test

  12. [composite:test3]
  13. use = call:test_wsgi:composite_factory
  14. / = test
  15. /name = Tony NIU

test_wsgi.py



点击(此处)折叠或打开

  1. import os
  2.  
  3. import eventlet
  4. from eventlet import wsgi, listen
  5. from paste import deploy
  6.  
  7. _path = os.path.dirname(__file__)
  8.  
  9. #application object
  10. class TestApp(object):
  11.     @classmethod
  12.     def factory(cls, global_conf, **local_conf):
  13.         return cls()
  14.  
  15.     def __call__(self, env, start_response):
  16.         #print env
  17.         start_response("200 OK", ())
  18.         return ["welcome"]
  19.  
  20. def test_app(self, env, start_response):
  21.     start_response("200 OK", ())
  22.     return ["welcome"]
  23.  
  24. test2_factory = TestApp.factory
  25.  
  26. def composite_factory(loader, global_config, **local_config):
  27.     #print env, start_response, args, kwargs
  28.     return TestApp()
  29.  
  30. def filter_factory(global_config, **local_config):
  31.     import time
  32.     def fiter(app):
  33.         print "now is %f" % time.time()
  34.         return app
  35.     return filter
  36.  
  37. def main():
  38.     f = "config:%s" % os.path.join(_path, "test_paste.ini")
  39.     host = "0.0.0.0"
  40.     server_list = [("test1", 8001),
  41.                     ("test2", 8002),
  42.                     ("test3", 8003),]
  43.  
  44.     servers = []
  45.     for app_name, port in server_list:
  46.         _socket = listen((host, port))
  47.         app = deploy.loadapp(f, app_name)
  48.  
  49.         print "%s is starting" % app_name
  50.         servers.append(eventlet.spawn(wsgi.server, _socket, app))
  51.  
  52.     for server in servers:
  53.         server.wait()
  54.  
  55. if __name__ == '__main__':
  56.     main()

参考:
阅读(1549) | 评论(0) | 转发(0) |
0

上一篇:添加Keystone扩展

下一篇:nova-rootwrap笔记

给主人留下些什么吧!~~