分享

OpenStack J版 Neutron-server服务加载与启动源码分析(一)

pig2 发表于 2014-11-10 20:21:38 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 0 26246
问题导读

1.什么是 Neutron-server
2.作者是如何分析代码的?






本文是在学习Openstack的过程中整理和总结,由于时间和个人能力有限,错误之处在所难免,欢迎指正!
    阅读本文首先明白neutron-server是什么,作用是什么?


neutron-server是neutron的核心组件之一,负责直接接收外部请求,然后调用后端相应plugin进行处理。






在这里首先看Neutron-server的服务加载和启动。

(1)查看/usr/bin/neutron-server脚本中的内容
主要作用调用neutron.servermain(),启动相关线程之后退出。
  1. from neutron.server import main
  2. if __name__ == "__main__":
  3. sys.exit(main())
复制代码



(2)main函数主要的内容
  1. def main():
  2.     try:
  3.         pool =eventlet.GreenPool()  #建立一个事件的绿池(绿色线程池)
  4.               #创建NeutronApiService的wsgi服务,并从线程池中spawn一个线程来监听api请求
  5.        neutron_api = service.serve_wsgi(service.NeutronApiService)
  6.         api_thread= pool.spawn(neutron_api.wait)
  7.         try:
  8.            neutron_rpc = service.serve_rpc()
  9.         exceptNotImplementedError:
  10.            LOG.info(_("RPC was already started in parent process byplugin."))
  11.         else:
  12.            rpc_thread = pool.spawn(neutron_rpc.wait)
  13.             # apiand rpc should die together.  When onedies, kill the other.
  14.            rpc_thread.link(lambda gt: api_thread.kill())
  15.            api_thread.link(lambda gt: rpc_thread.kill())
  16.        pool.waitall()
复制代码


在这里我们仔细分析wsgi服务是怎么样被加载并启动服务的。
  1. def serve_wsgi(cls):
  2.     try:
  3.         service =cls.create()
  4.        service.start()
  5.     exceptException:
  6.         withexcutils.save_and_reraise_exception():
  7.            LOG.exception(_('Unrecoverable error: please check log '
  8.                             'for details.'))
  9.     return service
复制代码


首先调用的是service.NeutronApiService的create函数
  1. class NeutronApiService(WsgiService):
  2.     @classmethod
  3.     defcreate(cls, app_name='neutron'):
  4.        config.setup_logging()
  5.         # Dump the initial option values
  6.        cfg.CONF.log_opt_values(LOG, std_logging.DEBUG)
  7.         service =cls(app_name)
  8.         return service
复制代码


create函数进行日志的安装和配置文件的映射。回到上面调用service.start(),NeutronApiService中没有start()函数,所以他调用的是父类的start的函数,也就是WsgiService这个类中的start函数。
  1. def start(self):
  2.        self.wsgi_app = _run_wsgi(self.app_name)
复制代码


继续看下_run_wsgi中的东西
  1. def _run_wsgi(app_name):
  2.     app =config.load_paste_app(app_name)
  3.     if not app:
  4.        LOG.error(_('No known API applications configured.'))
  5.         return
  6.     server =wsgi.Server("Neutron")
  7.    server.start(app, cfg.CONF.bind_port, cfg.CONF.bind_host,
  8.                 workers=cfg.CONF.api_workers)
  9.     # Dump alloption values here after all options are parsed
  10.    cfg.CONF.log_opt_values(LOG, std_logging.DEBUG)
  11.    LOG.info(_("Neutron service started, listening on%(host)s:%(port)s"),
  12.             {'host': cfg.CONF.bind_host,
  13.              'port': cfg.CONF.bind_port})
  14.     return server
复制代码


首先来看第一个函数load_paste_app(app_name)
  1. def load_paste_app(app_name):
  2.    """Builds and returns a WSGI app from a paste configfile.
  3.     :paramapp_name: Name of the application to load
  4.     :raisesConfigFilesNotFoundError when config file cannot be located
  5.     :raisesRuntimeError when application cannot be loaded from config file
  6.    """
  7.     config_path =cfg.CONF.find_file(cfg.CONF.api_paste_config)
  8.     if notconfig_path:
  9.         raisecfg.ConfigFilesNotFoundError(
  10.            config_files=[cfg.CONF.api_paste_config])
  11.     config_path =os.path.abspath(config_path)
  12.    LOG.info(_("Config paste file: %s"), config_path)
  13.     try:
  14.         app =deploy.loadapp("config:%s" % config_path, name=app_name)
  15.     except(LookupError, ImportError):
  16.         msg =(_("Unable to load %(app_name)s from "
  17.                 "configuration file %(config_path)s.") %
  18.               {'app_name': app_name,
  19.                'config_path': config_path})
  20.        LOG.exception(msg)
  21.         raiseRuntimeError(msg)
  22.     return app
复制代码



调试可以看到config_path指向/etc/neutron/api-paste.ini,neutron通过解析api-paste.ini中的配置信息来进行指定WSGI Application的实现。这里可以看到,在方法load_app中,调用了模块库deploy来实现对api-paste.ini中配置信息的解析和指定WSGI Application的实现。


【注】:
       PasteDeployment是一种机制或者说是一种设计模式,它用于在应用WSGI Application和Server提供一个联系的桥梁,并且为用户提供一个接口,当配置好PasteDeployment之后,用户只需调用loadapp方法就可以使用现有的WSGI Application,而保持了WSGIApplication对用户的透明性。


我们可以看到neutron/ api-paste.ini中的内容如下:
  1. [composite:neutron]
  2. use= egg:Paste#urlmap
  3. /:neutronversions
  4. /v2.0:neutronapi_v2_0
  5. [composite:neutronapi_v2_0]
  6. use= call:neutron.auth:pipeline_factory
  7. noauth= request_id catch_errors extensionsneutronapiapp_v2_0
  8. keystone= request_id catch_errors authtokenkeystonecontext extensionsneutronapiapp_v2_0
  9. [filter:request_id]
  10. paste.filter_factory= neutron.openstack.common.middleware.request_id:RequestIdMiddleware.factory
  11. [filter:catch_errors]
  12. paste.filter_factory=neutron.openstack.common.middleware.catch_errors:CatchErrorsMiddleware.factory
  13. [filter:keystonecontext]
  14. paste.filter_factory= neutron.auth:NeutronKeystoneContext.factory
  15. [filter:authtoken]
  16. paste.filter_factory=keystoneclient.middleware.auth_token:filter_factory
  17. [filter:extensions]
  18. paste.filter_factory=neutron.api.extensions:plugin_aware_extension_middleware_factory
  19. [app:neutronversions]
  20. paste.app_factory= neutron.api.versions:Versions.factory
  21. [app:neutronapiapp_v2_0]
  22. paste.app_factory=neutron.api.v2.router:APIRouter.factory
复制代码


通过对api-paste.ini中配置信息的解析,最终就调用了WSGIApplicationapiv2的实现,具体就是neutron.api.v2.router:APIRouter.factory,这个WSGI Application的具体功能就是实现模块功能的扩展和加载过程。之后我们将深入了解该模块是如何实现模块功能的扩展和加载。


作者:林凯
团队:华为杭州OpenStack研发团队





没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条