天天看點

OpenStack之Neutron源碼分析 Neutron-server初始化

從檔案夾的命名也基本可以得出該目錄代碼的作用,幾個重要的檔案夾如下:

agent: 主要是l3 agent及l3 agent ha的相關代碼;

common: 主要是各底層驅動與linux系統指令的互動層;

db: 是neutron各功能與資料庫互動資料的代碼;

extensions: 主要包括的一些擴充功能,包括dvr的代碼等;

plugins: 是core plugin的代碼,包括ovs,ml2和各個廠商ibm、ryu提供等的plugin;

scheduler: 是建立dhcp服務和router到各l3 agent的排程配置設定相關代碼;

server: 是neutron server相關的代碼;

services: 則是包含了lbaas、vpnaas、fwaas、l3-router、metering等服務的plugin和agent代碼;

Neutron是OpenStack中用于管理網絡的項目。neutron代碼的入口配置檔案neutron.setup.cfg,我們可以通過這個檔案了解整個項目的代碼結構。

neutron/setup.cfg

[entry_points]
console_scripts = 
    neutron-l3-agent = neutron.cmd.eventlet.agents.l3:main
    neutron-linuxbridge-agent = neutron.plugins.ml2.drivers.linuxbridge.agent.linuxbridge_neutron_agent:main
    neutron-openvswitch-agent = neutron.cmd.eventlet.plugins.ovs_neutron_agent:main
    neutron-server = neutron.cmd.eventlet.server:main_wsgi_eventlet
    neutron-rpc-server = neutron.cmd.eventlet.server:main_rpc_eventlet
    neutron-sanity-check = neutron.cmd.sanity_check:main
neutron.core_plugins = 
    ml2 = neutron.plugins.ml2.plugin:Ml2Plugin
           
  • neutron-l3-agent:l3 agent部署在計算節點或者網絡節點上,負責3層虛拟網絡的管理。根據setup.cfg檔案可以看出neutron-l3-agent的代碼路徑是neutron/agent/l3/agent
  • neutron-openvswitch-agent:Open vSwitch Agent部署在計算節點或者網絡節點上,進行管理OVS虛拟交換機。根據setup.cfg檔案可以看出neutron-openvswitch-agent的代碼路徑是neutron/plugins/openvswitch/agent.ovs_neutron_agent
  • neutron-server: 是Neutron中唯一的一個服務程序,負責接收使用者的RESTful API請求并分發處理給各種agen來完成這些的任務。根據setup.cfg檔案可以看出neutron代碼路徑是neutron/server
  • ML2Plugin:用于提供二層虛拟網絡,實作了network/subnet/port資源的操作,這些操作最終由Plugin通過RPC調用OpenvSwitch Agent來完成。根據setup.cfg檔案可以看出代碼路徑是 neutron/plugins/ml2/plugin/Ml2Plugin。

neutron-server啟動過程分析

Neutron-Server啟動,無外乎就是加載配置,router各種resource,然後就等待請求了。其中router哪些resource完全是由配置檔案來決定的。 當然,在啟動的過程中也會初始化db,這也就是為何在安裝neutron的時候無需像nova,glance等要執行db sync的原因了。

neutron-server初始化

1. /etc/init.d/neutron-server

該腳本:建立日志目錄,服務目錄,啟動neutron-server守護程序。支援CURD操作。

DAEMON=/usr/bin/neutron-server
DAEMON_ARGS="--log-file=$LOGFILE"
DAEMON_DIR=/var/run
if [ ! -x ${DAEMON} ] ; then
    exit 
fi

case "$1" in
  start)
    test "$ENABLED" = "true" || exit 
    log_daemon_msg "Starting neutron server" "neutron-server"
    start-stop-daemon -Sbmv --pidfile $PIDFILE --chdir $DAEMON_DIR --exec $DAEMON -- $DAEMON_ARGS
    log_end_msg $?
    ;;
  stop)
    test "$ENABLED" = "true" || exit 
    log_daemon_msg "Stopping neutron server" "neutron-server"
    start-stop-daemon --stop --oknodo --pidfile ${PIDFILE}
    log_end_msg $?
    ;;
  restart|force-reload)
    test "$ENABLED" = "true" || exit 
    $0 stop
    sleep 
    $0 start
    ;;
  status)
    test "$ENABLED" = "true" || exit 
    status_of_proc -p $PIDFILE $DAEMON neutron-server && exit  || exit $?
    ;;
  *)
    log_action_msg "Usage: /etc/init.d/neutron-server {start|stop|restart|force-reload|status}"
    exit 
    ;;
esac

exit 
           

2. neutron/server/main主函數

main方法的核心就是serve_wsgi、serve_rpc兩個方法調用,分别建立api服務和rpc服務。新版本對main方法做了高度的抽象與松耦合處理。

1) neutron.server.wsgi_eventlet.py

def _eventlet_wsgi_server():
    pool = eventlet.GreenPool()
    # 啟動Restful API 以協程方式
    neutron_api = service.serve_wsgi(service.NeutronApiService)
    api_thread = pool.spawn(neutron_api.wait)

    try:
        # 啟動RPC API
        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)
           

neutron.server.rpc_eventlet.py

def _eventlet_rpc_server():
    pool = eventlet.GreenPool()
    LOG.info(_LI("Eventlet based AMQP RPC server starting..."))
    try:
        # 啟動RPC API
        neutron_rpc = service.serve_rpc()
    except NotImplementedError:
        LOG.info(_LI("RPC was already started in parent process by "
                     "plugin."))
    else:
        pool.spawn(neutron_rpc.wait)
    pool.waitall()


def main():
    server.boot_server(_eventlet_rpc_server)
           

2) neutron.server._ init _.py

def boot_server(server_func):
    # the configuration will be read into the cfg.CONF global data structure
    config.init(sys.argv[:])
    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)
           

其中:wsgi服務以及rpc服務的啟動過程如下:

Api服務初始化

serve_wsgi服務:

http://blog.csdn.net/qiqishuang/article/details/52056491

Rpc服務初始化

serve_rpc服務:

http://blog.csdn.net/qiqishuang/article/details/52056511

L2-Agent服務初始化

http://blog.csdn.net/qiqishuang/article/details/52056557

L3-Agent服務初始化

http://blog.csdn.net/qiqishuang/article/details/52153034

參考:

About雲:http://www.aboutyun.com/thread-10306-1-1.html

繼續閱讀