Neutron-server初始化 — Api服务初始化

版权声明:本博客为博主原创博文,可以任意转载。转载请附上博客链接: http://blog.csdn.net/qiqishuang https://blog.csdn.net/qiqishuang/article/details/52056491

Restful Api服务初始化

api服务的实现是service.NeutronApiService,这是一个符合WSGI规范的app,通过paste进行配置。

neutron/service.py

# serve_wsgi服务
class NeutronApiService(WsgiService):
    """Class for neutron-api service."""

    @classmethod
    def create(cls, app_name='neutron'):

        # Setup logging early, supplying both the CLI options and the
        # configuration mapping from the config file
        # We only update the conf dict for the verbose and debug
        # flags. Everything else must be set up in the conf file...
        # Log the options used when starting if we're in debug mode...

        config.setup_logging()
        service = cls(app_name)
        return service

def serve_wsgi(cls):

    try:
        # create函数进行日志的安装和配置文件的映射。
        service = cls.create()
        # NeutronApiService中没有start()函数,所以他调用的是父类的start的函数
        # 也就是WsgiService这个类中的start函数。
        service.start()
    except Exception:
        with excutils.save_and_reraise_exception():
            LOG.exception(_LE('Unrecoverable error: please check log '
                              'for details.'))

    return service
class WsgiService(object):
    """Base class for WSGI based services.

    For each api you define, you must also define these flags:
    :<api>_listen: The address on which to listen
    :<api>_listen_port: The port on which to listen

    """

    def __init__(self, app_name):
        self.app_name = app_name
        self.wsgi_app = None

    def start(self):
        # 父类wsgiService的start()方法,其中_run_wsgi
        self.wsgi_app = _run_wsgi(self.app_name)

def _run_wsgi(app_name):
    # load_paste_app
    app = config.load_paste_app(app_name)
    if not app:
        LOG.error(_LE('No known API applications configured.'))
        return
    server = wsgi.Server("Neutron")
    server.start(app, cfg.CONF.bind_port, cfg.CONF.bind_host,
                 workers=_get_api_workers())
    LOG.info(_LI("Neutron service started, listening on %(host)s:%(port)s"),
             {'host': cfg.CONF.bind_host, 'port': cfg.CONF.bind_port})
    return server

其中:
service.start()即为self.wsgi_app = _run_wsgi(self.app_name),而该函数最重要的工作是从api-paste.ini中加载app并启动。

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

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

我们可以看到neutron/api-paste.ini中的内容如下:

[composite:neutron]
use = egg:Paste#urlmap
/: neutronversions
/v2.0: neutronapi_v2_0

[composite:neutronapi_v2_0]
use = call:neutron.auth:pipeline_factory
noauth = request_id catch_errors extensions neutronapiapp_v2_0
keystone = request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0

[filter:request_id]
paste.filter_factory = oslo_middleware:RequestId.factory

[filter:catch_errors]
paste.filter_factory = oslo_middleware:CatchErrors.factory

[filter:keystonecontext]
paste.filter_factory = neutron.auth:NeutronKeystoneContext.factory

[filter:authtoken]
paste.filter_factory = keystonemiddleware.auth_token:filter_factory

[filter:extensions]
paste.filter_factory = neutron.api.extensions:plugin_aware_extension_middleware_factory

[app:neutronversions]
paste.app_factory = neutron.api.versions:Versions.factory

[app:neutronapiapp_v2_0]
paste.app_factory = neutron.api.v2.router:APIRouter.factory

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

paste文件位置可以在配置文件中指定,默认是/etc/neutron/api-paste.ini,在代码中是etc/api-paste.ini。查看api-paste.ini可以确定v2版api的实现是在neutron.api.v2.router:APIRouter

[app:neutronapiapp_v2_0]
paste.app_factory = neutron.api.v2.router:APIRouter.factory

APIRouter在构造时,会根据配置文件core_plugin的配置加载plugin、extension管理器。所在文件:neutron\neutron\api\v2\router.py

class APIRouter(wsgi.Router):
    # 一个工厂类方法
    @classmethod
    def factory(cls, global_config, **local_config):
        return cls(**local_config)
    # 真正调用的实例化方法
    def __init__(self, **local_config):
        mapper = routes_mapper.Mapper()
        #获取NeutornManage的core_plugin,这个定义在/etc/neutron/neutron.conf,比如我的是
        #core_plugin =  neutron.plugins.openvswitch.ovs_neutron_plugin.OVSNeutronPluginV
        plugin = manager.NeutronManager.get_plugin()
        #扫描特定路径下的extensions
        ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
        ext_mgr.extend_resources("2.0", attributes.RESOURCE_ATTRIBUTE_MAP)

        col_kwargs = dict(collection_actions=COLLECTION_ACTIONS,
                          member_actions=MEMBER_ACTIONS)

       #定义的局部方法
        def _map_resource(collection, resource, params, parent=None):
            ...
            controller = base.create_resource(
collection, resource, plugin, params, allow_bulk=allow_bulk,
parent=parent, allow_pagination=allow_pagination,
allow_sorting=allow_sorting)
...
            # 将这些resource加进router中
            return mapper.collection(collection, resource, **mapper_kwargs)

            # 遍历 {'network': 'networks', 'subnet': 'subnets','port': 'ports'}
            # 添加controller
            for resource in RESOURCES:
                _map_resource(RESOURCES[resource], resource,
attributes.RESOURCE_ATTRIBUTE_MAP.get(
RESOURCES[resource], dict()))
            for resource in SUB_RESOURCES:

猜你喜欢

转载自blog.csdn.net/qiqishuang/article/details/52056491