版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处!
本文中提到的nova/service.py 等均是指的/usr/lib/python2.6/site-packages/nova 路径下的文件,不再另行说明。
nova-api启动脚本 /usr/bin/nova-api
/usr/bin/nova-api
"""Starter script for Nova API.
Starts both the EC2 and OpenStack APIs in separate greenthreads.
"""
import eventlet
eventlet.monkey_patch(os=False)
import os
import sys
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(
sys.argv[0]), os.pardir, os.pardir))
if os.path.exists(os.path.join(possible_topdir, "nova", "__init__.py")):
sys.path.insert(0, possible_topdir)
from nova import flags
from nova.openstack.common import log as logging
from nova import service
from nova import utils
if __name__ == '__main__':
flags.parse_args(sys.argv)
logging.setup("nova")
utils.monkey_patch()
launcher = service.ProcessLauncher()
for api in flags.FLAGS.enabled_apis:
server = service.WSGIService(api)
launcher.launch_server(server, workers=server.workers or 1)
launcher.wait()
launcher = service.ProcessLauncher()
查看nova/service.py
此处没有什么可以解释的,就是创建了一个launcher
flags.FLAGS.enabled_apis
查看nova/flags.py
cfg.ListOpt('enabled_apis',
default=['ec2', 'osapi_compute', 'osapi_volume', 'metadata'],
help='a list of APIs to enable by default'),
server = service.WSGIService(api)
查看nova/service.py
class WSGIService(object):
"""Provides ability to launch API from a 'paste' configuration."""
def __init__(self, name, loader=None):
"""Initialize, but do not start the WSGI server.
:param name: The name of the WSGI server given to the loader.
:param loader: Loads the WSGI application using the given name.
:returns: None
"""
self.name = name
self.manager = self._get_manager() //此处返回的是None
self.loader = loader or wsgi.Loader() //wsgi的loader,用于加载模块
self.app = self.loader.load_app(name) //加载模块,其配置文件默认使用了/etc/nova/api-paste.ini文件,加载的模块为app:标示的部分
self.host = getattr(FLAGS, '%s_listen' % name, "0.0.0.0") //此处e2c_listen、osapi_volume_listen....等配置选项是在service.py文件中注册到FLAGS的
self.port = getattr(FLAGS, '%s_listen_port' % name, 0)
self.workers = getattr(FLAGS, '%s_workers' % name, None)
self.server = wsgi.Server(name, //返回wsgi的server
self.app,
host=self.host,
port=self.port)
# Pull back actual port used
self.port = self.server.port
从上面的代码可以看出,实际上返回的server是一个wsgi的server
launcher.launch_server(server, workers=server.workers or 1)
launch_server 中调用了
self._start_child(wrap)
_start_child 中调用了 self._child_process(wrap.server)
_child_process中调用了 launcher = Launcher() launcher.run_server(server)
在Launcher类的run_server 方法中调用了 server.start() server.wait()
上面的方法实际上就是调用了 wsgi.Server的 start、wait方法
wsgi.Server的start()方法,启动了一个服务线程来监听请求
self._server = eventlet.spawn(eventlet.wsgi.server,
self._socket,
self.app,
protocol=self._protocol,
custom_pool=self._pool,
log=self._wsgi_logger)
经过上面的分析,可以看到,是循环的将默认的'ec2', 'osapi_compute', 'osapi_volume', 'metadata' API服务全都起来了,让它们处于监听服务状态。
这些服务的入口可以通过查看/etc/nova/api-paste.ini文件中的[app:xxxxx]部分看到,例如:
[app:osapi_compute_app_v2]
paste.app_factory = nova.api.openstack.compute:APIRouter.factory
[pipeline:oscomputeversions]
pipeline = faultwrap oscomputeversionapp
[app:osapi_volume_app_v1]
paste.app_factory = nova.api.openstack.volume:APIRouter.factory
[app:oscomputeversionapp]
paste.app_factory = nova.api.openstack.compute.versions:Versions.factory
[pipeline:osvolumeversions]
pipeline = faultwrap osvolumeversionapp
[app:osvolumeversionapp]
paste.app_factory = nova.api.openstack.volume.versions:Versions.factory
可以看到osapi_compute、osapi_volume都是启动一个“方法功能路由器”来对服务请求进行调用路由