neutron网络模块分析一(neutron-server启动)

neutron-server 启动流程

预备知识:

WSGI:一个可以在python web服务中可以广泛使用的API
PASTE:Paste Deployment用于发现和配置WSGI Application和Server,有了Paste Deployment,WSGI applications只需向其用户提供一个单独的入口loadapp函数,然后用户调用这个函数 就可以使用已经开发好的WSGI application,同时,由于只提供了一个入口,WSGI的开发者 也不再需要将App的具体实现暴露给用户,大大简化了整个开发过程。
Webob:提供了一系列的装饰器来将函数包装成WSGI应用。

架构功能划分


这张图片只是讲述了整体的框架

整体分析:
1)位于最上层的Neutron server负责接收来自外部服务的RESTful API请求
2)位于中间的Neutron plugin负责传达指令
3)位于下层的Neutron agent 负责执行具体任务和操作

组件图

图片来源于网络

框架分析

Neutron-server

Neutron只有一个主要的服务进程neutron-server,它运行在网络控制节点提供RESTfulAPI作为访问Neutron的入口。Neutron-server接收到的用户HTTP请求最终由遍布于计算节点和网络节点的各种agent来完成。
主要代码:/neutron/server

Neutron API

Neutron将基于各种虚拟网络资源得到的API资源分成核心资源(Core API)和扩展资源(Exten API)两种,Core API只对应于L2层的network、subnet、port、subnetpool四种抽象资源,其余的各层抽象都属于Exten API的范围。
代码目录:/neutron/api目录

Neutron Plugin

有core plugins 和service pulgins组成。

Core plugins:

提供基础二层网络虚拟网络支持,只要是ML2 plugin,
ML2 plugin不仅实现了network/subnet/port/subnetpool这四个核心资源和包括port binding等在内的部分扩展资源。还实现了网络拓扑类型(Flat、VLAN、VXLAN、GRE)和底层虚拟网络(Linux bridge、Open vSwitch)分离的机制。并分别通过Driver的形式扩展。其中,不同的网络拓扑类型对应着type dirver,由type manager 管理,不同的网络实现机制对应着Machansim Driver,有Mechanism Manager管理。
代码目录:neutron/plugins

Service plugin :

实现除network/subnet/port/subnetpool以外的资源。如FWaas、LBaas、VPNaas等高级服务。
代码目录:neutron/services

Message Queque

使用MessageQueque的一个模块Oslo.Messaging,Oslo.Messaging支持的MQ组件有RabbitMQ、ZeroMQ和Qpid。常用的是RabbitMQ。

Agent

执行各种具体任务和操作

服务启动分析:

stevedore 使用setupool的entry point 来定义并加载插件。
entry point目录:/neutro.egg-info目录下
文件如下图

Neutron-server

服务入口:\neutron\cmd\eventlet\server__init__.py:main()
实现代码:\neutron\services

代码分析

def _main_neutron_server():
     if cfg.CONF.web_framework == 'legacy':
        wsgi_eventlet.eventlet_wsgi_server()
    else:
        wsgi_pecan.pecan_wsgi_server()

web_framework的值是/etc/neutron/neutron.conf中的值

两个不同的wsgi_server框架,默认为evenlet模式,所以重点分析eventlet

 def eventlet_wsgi_server():
        neutron_api = service.serve_wsgi(service.NeutronApiService)
        start_api_and_rpc_workers(neutron_api)

Service.server_wsgi主要创建一个服务并开始运行。

 def serve_wsgi(cls):
        try:
            service = cls.create()
            service.start()
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE('Unrecoverable error: please check log '
                                  'for details.'))

        registry.notify(resources.PROCESS, events.BEFORE_SPAWN, service)
        return service

NeutronApiService继承与WsgiService,所以直接追踪WsgiService的start发现使用_run_wsgi来启动服务。

    def _run_wsgi(app_name):
        app = config.load_paste_app(app_name)
        if not app:
            LOG.error(_LE('No known API applications configured.'))
            return
        return run_wsgi_app(app)

    def run_wsgi_app(app):
        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

    ## start server
    def start(self, application, port, host='0.0.0.0', workers=0):
        """Run a WSGI server with the given application."""
        self._host = host
        self._port = port
        backlog = CONF.backlog

        self._socket = self._get_socket(self._host,
                                        self._port,
                                        backlog=backlog)

        self._launch(application, workers)

下面就是到主要的_launch了

    def _launch(self, application, workers=0):
        service = WorkerService(self, application, self.disable_ssl, workers)
        if workers < 1:
            # The API service should run in the current process.
            self._server = service
            # Dump the initial option values
            cfg.CONF.log_opt_values(LOG, logging.DEBUG)
            service.start()
            systemd.notify_once()
        else:
            # dispose the whole pool before os.fork, otherwise there will
            # be shared DB connections in child processes which may cause
            # DB errors.
            api.context_manager.dispose_pool()
            # The API service runs in a number of child processes.
            # Minimize the cost of checking for child exit by extending the
            # wait interval past the default of 0.01s.
            self._server = common_service.ProcessLauncher(cfg.CONF,
                                                          wait_interval=1.0)
            self._server.launch_service(service,

Load_paste_app从neutron.conf中得知api_paste.ini路径,并从api_paste.ini中加载WSGI app
上面只是对neutron-server的启动做了简单的分析

APIRouter

APIRouter,顾名思义,它是用来路由 API 请求的,把 API 请求真正发往那些实现功能的函数,在这里 Neutron 会加载 core plugin 和 plugin extension,扩展它的 Resource map,针对每一个资源集合(比如 networks、subnets、ports 等)建立 Controller,以后 API 将被路由到 Controller 去,Controller 再去调用对应的 create、get、update、delete 方法。同时在这里还可以做一些通用的检查,比如权限、数据有效性、自动转化数据格式等等。
代码目录:/neutron/api/v2/router.py

   class APIRouter(base_wsgi.Router):

    @classmethod
    def factory(cls, global_config, **local_config):
        return cls(**local_config)

    def __init__(self, **local_config):
        mapper = routes_mapper.Mapper()
        manager.init()
        plugin = directory.get_plugin()
        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

)
这里简单的分析下这个APIRouter类做的事情,首先在调用时会先把core plugin启动然后就到server plugin的启动,启动完之后就会启动plugin相应的extension ,
启动完之后就会担任一个路由转发功能,将外面的HTTP请求访问的资源路由到对应的plugin下的那个extension处理。

这里对APIRouter只做一个简单的介绍,后面的文章会更加详细介绍,plugin的启动顺序,plugin和extension的创建,如何路由资源等

参考文章:https://mp.weixin.qq.com/s?__biz=MjM5NjUxNDIwNw==&mid=201853844&idx=1&sn=4567bf6952dc8dd37c25f3afe64810bf&scene=2&from=timeline&isappinstalled=0#rd

猜你喜欢

转载自blog.csdn.net/energysober/article/details/80349247