neutron服务启动源码分析(一)

基于 openstack stein , 从代码梳理一下neutron server的启动以及 ovs agent的启动流程

PS:本篇是关于neutron server启动的

neutron-server的启动命令如下:

42435     519598  0.0  0.0 371240 137840 ?       S    Oct17   4:01 /var/lib/kolla/venv/bin/python /var/lib/kolla/venv/bin/neutron-server --config-file /etc/neutron/neutron.conf --config-file /etc/neutro
n/plugins/ml2/ml2_conf.ini --config-file /etc/neutron/neutron_lbaas.conf --config-file /etc/neutron/neutron_vpnaas.conf --config-file /etc/neutron/fwaas_driver.ini

开始分析整个代码流程

  1. /var/lib/kolla/venv/bin/neutron-server

只是做了一件事情,引用了cmd.eventlet.server的main方法,再调用

from neutron.cmd.eventlet.server import main

  1. neutron/cmd/eventlet/server/_init_.py

main方法中只是调用了boot_server函数

def main():
    server.boot_server(wsgi_eventlet.eventlet_wsgi_server)
  1. neutron/server/_init__.py

boot_server函数主要是加载配置文件,配置日志,最终调用server_func() ,也就是 wsgi_eventlet.eventlet_wsgi_server

def _init_configuration():
    # the configuration will be read into the cfg.CONF global data structure
    conf_files = _get_config_files()

    config.init(sys.argv[1:], default_config_files=conf_files)
    config.setup_logging()
    config.set_config_defaults()
    if not cfg.CONF.config_file:
        sys.exit(_("ERROR: Unable to find configuration file via the default"
                   " search paths (~/.neutron/, ~/, /etc/neutron/, /etc/) and"
                   " the '--config-file' option!"))


def boot_server(server_func):
    _init_configuration()
    try:
        server_func()
    except KeyboardInterrupt:
        pass
    except RuntimeError as e:
        sys.exit(_("ERROR: %s") % e)
  1. neutron/server/wsgi_eventlet.py

从上面可以看出,neutron加载了配置开启日之后最终直接通过eventlet启动wsgi服务, 启动了api和rpc服务。serve_wsgi 函数中传入neutronApiService,

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


def start_api_and_rpc_workers(neutron_api):
    try:
        worker_launcher = service.start_all_workers()

        pool = eventlet.GreenPool()
        api_thread = pool.spawn(neutron_api.wait)
        plugin_workers_thread = pool.spawn(worker_launcher.wait)

        # api and other workers should die together. When one dies,
        # kill the other.
        api_thread.link(lambda gt: plugin_workers_thread.kill())
        plugin_workers_thread.link(lambda gt: api_thread.kill())

        pool.waitall()
    except NotImplementedError:
        LOG.info("RPC was already started in parent process by "
                 "plugin.")

        neutron_api.wait()
  1. neutron/service.py

    serve_wsgi 传入cls,然后直接调用对于cls的create函数并start启动,这里代指NeutronApiService class的create和start

	def serve_wsgi(cls):

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

    registry.publish(resources.PROCESS, events.BEFORE_SPAWN, service)
    return service
  1. neutron/service.py

NeutronApiService继承了WsgiService,本质上是一个wsgi 服务,实现了create和start等功能

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):
        self.wsgi_app = _run_wsgi(self.app_name)

    def wait(self):
        self.wsgi_app.wait()


class NeutronApiService(WsgiService):
    """Class for neutron-api service."""
    def __init__(self, app_name):
        profiler.setup('neutron-server', cfg.CONF.host)
        super(NeutronApiService, self).__init__(app_name)

    @classmethod
    def create(cls, app_name='neutron'):
        # Setup logging early
        config.setup_logging()
        service = cls(app_name)
        return service

start 服务时, 调用了_run_wsgi, 通过paster.deploy 创建了neutron的app, 最终调用 run_wsgi_app ,

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

run_wsgi_app() 函数最终构造了一个wsgi Server实例,名字为Neutron,start函数中传入监听地址和端口号以及worker数量

	def run_wsgi_app(app):
    server = wsgi.Server("Neutron")
    server.start(app, cfg.CONF.bind_port, cfg.CONF.bind_host,
                 workers=_get_api_workers(), desc="api worker")
    LOG.info("Neutron service started, listening on %(host)s:%(port)s",
             {'host': cfg.CONF.bind_host, 'port': cfg.CONF.bind_port})
    return server

start 函数中调用 _get_socket 通过eventlet listen了相关端口。最后调用launch ,worker数量肯定大于1,else里面先初始化了数据库连接,并fork子进程

    def start(self, application, port, host='0.0.0.0', workers=0, desc=None):
        """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)

    def _launch(self, application, workers=0, desc=None):
        set_proctitle = "off" if desc is None else CONF.setproctitle
        service = WorkerService(self, application, set_proctitle,
                                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(desc=desc)
            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.
            db_api.get_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, restart_method='mutate')
            self._server.launch_service(service,
                                        workers=service.worker_process_count)

至此neutron server启动完成

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

robin5911

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值