本文分析的是OpenStack的L版本neutron server的启动流程
首先看下进程信息
首先看下进程信息
4 S neutron 16698 1 1 80 0 - 97381 ep_pol 22:51 ? 00:00:07 /usr/bin/python2 /usr/bin/neutron-server --config-file /usr/share/neutron/neutron-dist.conf --config-dir /usr/shareneutron/server --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugin.ini --config-dir /etc/neutron/conf.d/common --config-dir /etc/neutron/conf.d/neutron-server --log-file /var/log/neutron/server.log
1 S neutron 16740 16698 0 80 0 - 98051 ep_pol 22:51 ? 00:00:00 /usr/bin/python2 /usr/bin/neutron-server --config-file /usr/share/neutron/neutron-dist.conf --config-dir /usr/share/neutron/server --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugin.ini --config-dir /etc/neutron/conf.d/common --config-dir /etc/neutron/conf.d/neutron-server --log-file /var/log/neutron/server.log
会发现有两个neutron-server进程,而16740是16698的子进程,具体为什么出现这种情况有待探讨。
从上面信息我们得出,neutron-server的执行入口在/usr/bin/neutron-server看下启动的入口脚本
/usr/bin/neutron-server
import sys
from neutron.cmd.eventlet.server import main_wsgi_eventlet
if __name__ == "__main__":
sys.exit(main_wsgi_eventlet())
~
在看下neutron.cmd.eventlet.server,会发现代码如下
from neutron.server import rpc_eventlet
from neutron.server import wsgi_eventlet
from neutron.server import wsgi_pecan
def main_wsgi_eventlet():
wsgi_eventlet.main()
# Eventlet patching is not required for Pecan, but some plugins still spawn
# eventlet threads
def main_wsgi_pecan():
wsgi_pecan.main()
def main_rpc_eventlet():
rpc_eventlet.main()
接着看下netron.server.wsgi_eventlet
import eventlet
from oslo_log import log
from neutron.i18n import _LI
from neutron import server
from neutron import service
LOG = log.getLogger(__name__)
def _eventlet_wsgi_server():
pool = eventlet.GreenPool()
neutron_api = service.serve_wsgi(service.NeutronApiService)
api_thread = pool.spawn(neutron_api.wait)
try:
neutron_rpc = service.serve_rpc()
except NotImplementedError:
LOG.info(_LI("RPC was already started in parent process by "
"plugin."))
else:
rpc_thread = pool.spawn(neutron_rpc.wait)
plugin_workers = service.start_plugin_workers()
for worker in plugin_workers:
pool.spawn(worker.wait)
# api and rpc should die together. When one dies, kill the other.
rpc_thread.link(lambda gt: api_thread.kill())
api_thread.link(lambda gt: rpc_thread.kill())
pool.waitall()
def main():
server.boot_server(_eventlet_wsgi_server)
server.boot_server在server.__init__.py中实现的,具体代码如下
import sys
from oslo_config import cfg
from neutron.common import config
def boot_server(server_func):
# the configuration will be read into the cfg.CONF global data structure
config.init(sys.argv[1:])
config.setup_logging()
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!"))
try:
server_func()
except KeyboardInterrupt:
pass
except RuntimeError as e:
sys.exit(_("ERROR: %s") % e)