首先,Neutron Server作为一种处事(neutron-server.service),可以到Neutron项目目录中的setup.cfg配置文件中找到对应的代码入口。
[entry_points] console_scripts = neutron-db-manage = neutron.db.migration.cli:main neutron-debug = neutron.debug.shell:main neutron-dhcp-agent = neutron.cmd.eventlet.agents.dhcp:main neutron-keepalived-state-change = neutron.cmd.keepalived_state_change:main neutron-ipset-cleanup = neutron.cmd.ipset_cleanup:main neutron-l3-agent = neutron.cmd.eventlet.agents.l3:main neutron-linuxbridge-agent = neutron.cmd.eventlet.plugins.linuxbridge_neutron_agent:main neutron-linuxbridge-cleanup = neutron.cmd.linuxbridge_cleanup:main neutron-macvtap-agent = neutron.cmd.eventlet.plugins.macvtap_neutron_agent:main neutron-metadata-agent = neutron.cmd.eventlet.agents.metadata:main neutron-netns-cleanup = neutron.cmd.netns_cleanup:main neutron-ns-metadata-proxy = neutron.cmd.eventlet.agents.metadata_proxy:main neutron-openvswitch-agent = neutron.cmd.eventlet.plugins.ovs_neutron_agent:main neutron-ovs-cleanup = neutron.cmd.ovs_cleanup:main neutron-pd-notify = neutron.cmd.pd_notify:main neutron-server = neutron.cmd.eventlet.server:main neutron-rpc-server = neutron.cmd.eventlet.server:main_rpc_eventlet neutron-rootwrap = oslo_rootwrap.cmd:main neutron-rootwrap-daemon = oslo_rootwrap.cmd:daemon neutron-usage-audit = neutron.cmd.eventlet.usage_audit:main neutron-metering-agent = neutron.cmd.eventlet.services.metering_agent:main neutron-sriov-nic-agent = neutron.cmd.eventlet.plugins.sriov_nic_neutron_agent:main neutron-sanity-check = neutron.cmd.sanity_check:main
neutron-server代码入口:
def main(): server.boot_server(_main_neutron_server)
挪用neutron.server.__init__中的boot_server函数:
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() 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!")) try: server_func() except KeyboardInterrupt: pass except RuntimeError as e: sys.exit(_("ERROR: %s") % e)
该函数在外加了一层初始化日志文件的壳,执行server_func(也就是这里的 _main_neutron_server),并进行异常的捕获。
def _main_neutron_server(): if cfg.CONF.web_framework == ‘legacy‘: wsgi_eventlet.eventlet_wsgi_server() else: wsgi_pecan.pecan_wsgi_server()
按照Neutron配置文件中的web_framework进行判断,默认为legacy。执行neutron.server.wsgi_eventlet.py中的eventlet_wsgi_server。
def eventlet_wsgi_server(): neutron_api = service.serve_wsgi(service.NeutronApiService) # 初始化neutron_api start_api_and_rpc_workers(neutron_api) # 启动neutron_api和rpc
先分析一下neutron_api的启动过程,rpc的启动过程下一节分析。挪用neutron.service.py中的serve_wsgi函数,相关的类代码都在一块,一起贴出来分析。
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): # 初始化类变量,wsgi_app变量在start函数中初始化 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) # super挪用父类的结构函数 @classmethod def create(cls, app_name=‘neutron‘): # Setup logging early config.setup_logging() service = cls(app_name) # 挪用结构函数,app_name为neutron return service # 返回一个NeutronApiService的实例 def serve_wsgi(cls): # 传入的cls参数为service.NeutronApiService try: service = cls.create() # 挪用NeutronApiService.create service.start() # 初始化service.wsgi_app 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
下面分析_run_wsgi函数,,传入参数app_name为‘neutron‘。