neutron-server启动过程分析
DAEMON=/usr/bin/neutron-server
DAEMON_ARGS="--log-file=$LOGFILE"
DAEMON_DIR=/var/run
...
case $1 in
start)
test "$ENABLED" = "true" || exit 0
log_daemon_msg "Starting neutron server" "neutron-server"
start-stop-daemon -Sbmv --pidfile $PIDFILE --chdir $DAEMON_DIR --exec $DAEMON -- $DAEMON_ARGS
log_end_msg $?
;;
...
esac
import sys
from neutron.server import main
if __name__ == "__main__":
sys.exit(main())
ef main():
# the configuration will be read into the cfg.CONF global data structure
config.init(sys.argv[1:])
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:
pool = eventlet.GreenPool()
# 以协程方式启动Restful API
neutron_api = service.serve_wsgi(service.NeutronApiService)
api_thread = pool.spawn(neutron_api.wait)
# 启动RPC API
try:
neutron_rpc = service.serve_rpc()
except NotImplementedError:
LOG.info(_("RPC was already started in parent process by plugin."))
else:
rpc_thread = pool.spawn(neutron_rpc.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()
except KeyboardInterrupt:
pass
except RuntimeError as e:
sys.exit(_("ERROR: %s") % e)
neutron.service.serve_rpc()最重要的工作就是启动各个插件的RpcWorker
plugin = manager.NeutronManager.get_plugin()
try:
rpc = RpcWorker(plugin)
if cfg.CONF.rpc_workers < 1:
rpc.start()
return rpc
else:
launcher = common_service.ProcessLauncher(wait_interval=1.0)
launcher.launch_service(rpc, workers=cfg.CONF.rpc_workers)
return launcher
而RpcWorker最重要的工作是调用plugin的start_rpc_listeners来监听消息队列:
def start(self):
# We may have just forked from parent process. A quick disposal of the
# existing sql connections avoids producing errors later when they are
# discovered to be broken.
session.get_engine().pool.dispose()
self._servers = self._plugin.start_rpc_listeners()
service.serve_wsgi(service.NeutronApiService)
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.‘))
return service
service.start()
即为self.wsgi_app = _run_wsgi(self.app_name)
,而该函数最重要的工作是从api-paste.ini中加载app并启动
def _run_wsgi(app_name):
app = config.load_paste_app(app_name)
if not app:
LOG.error(_(‘No known API applications configured.‘))
return
server = wsgi.Server("Neutron")
server.start(app, cfg.CONF.bind_port, cfg.CONF.bind_host,
workers=cfg.CONF.api_workers)
# Dump all option values here after all options are parsed
cfg.CONF.log_opt_values(LOG, std_logging.DEBUG)
LOG.info(_("Neutron service started, listening on %(host)s:%(port)s"),
{‘host‘: cfg.CONF.bind_host,
‘port‘: cfg.CONF.bind_port})
return server
[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 = neutron.openstack.common.middleware.request_id:RequestIdMiddleware.factory
[filter:catch_errors]
paste.filter_factory = neutron.openstack.common.middleware.catch_errors:CatchErrorsMiddleware.factory
[filter:keystonecontext]
paste.filter_factory = neutron.auth:NeutronKeystoneContext.factory
[filter:authtoken]
paste.filter_factory = keystoneclient.middleware.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
neutron.api.v2.router:APIRouter.factory针对network、subnet、port三个资源注册了 index、create等2个collection action以及show、update、delete等3个memver action,这些action最终记录在APIRouter._plugin_handlers中:
{‘create‘: ‘create_subnet‘, ‘delete‘: ‘delete_subnet‘, ‘list‘: ‘get_subnets‘, ‘update‘: ‘update_subnet‘, ‘show‘: ‘get_subnet‘}
{‘create‘: ‘create_network‘, ‘delete‘: ‘delete_network‘, ‘list‘: ‘get_networks‘, ‘update‘: ‘update_network‘, ‘show‘: ‘get_network‘}
{‘create‘: ‘create_port‘, ‘delete‘: ‘delete_port‘, ‘list‘: ‘get_ports‘, ‘update‘: ‘update_port‘, ‘show‘: ‘get_port‘}
在请求进入APIRouter之前,会先经过RequestIdMiddleware(请求header中添加 openstack.request_id)、CatchErrorsMiddleware(错误处理)、keystone权限验证以及 plugin_aware_extension_middleware_factory等几个filter的处理,前三个filter比较直 观,plugin_aware_extension_middleware_factory创建了映射到plugin的处理函数:
{‘create‘: ‘create_router‘, ‘delete‘: ‘delete_router‘, ‘list‘: ‘get_routers‘, ‘update‘: ‘update_router‘, ‘show‘: ‘get_router‘}
{‘create‘: ‘create_floatingip‘, ‘delete‘: ‘delete_floatingip‘, ‘list‘: ‘get_floatingips‘, ‘update‘: ‘update_floatingip‘, ‘show‘: ‘get_floatingip‘}
{‘create‘: ‘create_agent‘, ‘delete‘: ‘delete_agent‘, ‘list‘: ‘get_agents‘, ‘update‘: ‘update_agent‘, ‘show‘: ‘get_agent‘}
Neutron分析(2)——neutron-server启动过程分析,布布扣,bubuko.com
Neutron分析(2)——neutron-server启动过程分析
原文:http://www.cnblogs.com/feisky/p/3844636.html