天天看點

neutron l3 agent 初始化過程代碼走讀

neutron-l3-agent 初始化流表過程

/usr/bin/neutron-l3-agent --config-file=/etc/neutron/neutron_dvr_compute.conf --config-file=/etc/neutron/dvr_compute_agent.ini

說明:

1  "//" 為 neutron-l3-agent 初始化過程的一個step步驟标記        

+------------------------------------------------------------------------------------+ 

(一) neutron-l3-agent 初始化過程:

+------------------------------------------------------------------------------------+ 

/usr/bin/neutron-l3-agent 調用neutron.agent.l3_agent.py中的main()方法來啟動neutron-l3-agent服務。main()方法中建立一個加載了neutron.agent.l3.agent.L3NATAgentWithStateReport管理器的server,

然後啟動這個server。launch server時,會調用server的start()方法。

(1) neutron.agent.l3_agent.py 中main()方法啟動過程:

   1.1. 初始化 manager: neutron.agent.l3.agent.L3NATAgentWithStateReport:

   1.2. 初始化 neutron.service.py 中 class Service(n_rpc.Service)對象,并執行其start()方法。 初始化過程中将 加載 neutron.agent.l3.agent.L3NATAgentWithStateReport 類以及設定一些配置參數。

   //step 1.2 中 class Service(n_rpc.Service) start 方法邏輯:

        1.2.1 初始化 rpc connection,并建立消費者線程 消費 rpc topic。

        1.2.2 建立loop任務周期性調用report_state方法上報 l3-agent 服務的狀态

        1.2.3 建立loop周期性的任務調用 neutron.agent.l3.agent.L3NATAgentWithStateReport 中的 periodic_sync_routers_task 方法從北向neutron-server fullsync 目前host上的所有的router_ids。

        1.2.4 調用neutron.agent.l3.agent.L3NATAgentWithStateReport 中的after_start 方法處理router loop

        //上述步驟 1.2.3 中 fullsync routers處理過程:

            初始化 namespace_manager(neutron.agent.l3.namespace_manager.py)執行個體對象。該執行個體對象主要是l3 的router namespace,dvr_snat_ns 以及 dvr_fip_ns 進行管理。如清除ns操作等。

            通過plugin_rpc 調用get_router_ids方法從北向擷取目前host上的router_ids。

            通過plugin_rpc 調用get_routers方法批量地(一次取sync_routers_chunk_size 個router)從北向擷取目前host上的所有routers。

            輪訓 routers,處理router:

                将router_id 加入到router namespace中的标記隊列,使其在清除ns時不清楚 router的ns

                如果router 為分布式路由:

                    如果router 存在ext_net_id(即external_gateway_info屬性中的network_id字段存在),将router的fip_ns加入到router namespace中的标記隊列中。

                    如果router 不存在ext_net_id,且l3 agent配置為dvr_snat 模式,則namespace管理器清除router的 snat namespace。

                如果router為HA router:

                    檢測router的狀态是否與db狀态一緻,如果不一緻,發送router狀态變化通知。

                建構RouterUpdate對象,加入到RouterProcessingQueue 的優先級隊列Queue.PriorityQueue中等待處理。RouterUpdate建構參數:

                    queue.RouterUpdate(

                            r['id'],

                            queue.PRIORITY_SYNC_ROUTERS_TASK,

                            router=r,

                            timestamp=timestamp)   // 不設定action

                設定fullsync = False

                調整sync_routers_chunk_size 的值

                将目前router_info中不在北向擷取routers中的router 建構RouterUpdate對象,加入到RouterProcessingQueue中等待處理。RouterUpdate建構參數:

                    queue.RouterUpdate(router_id,

                            queue.PRIORITY_SYNC_ROUTERS_TASK,

                            timestamp=timestamp,

                            action=queue.DELETE_ROUTER)     // 設定action                

        // 上述步驟 1.2.4 中 after_start()處理邏輯

            (a)啟動一個協程池調用 _process_routers_loop 方法輪詢處理router。處理router的方法為_process_router_update:

                按順序從RouterProcessingQueue 的優先級隊列Queue.PriorityQueue中取出RouterUpdate對象。

                    if update.action == queue.PD_UPDATE:  

                        //Processing IPv6 PD Prefix Update,and continue

                    if update.action == queue.DELETE_ROUTER 且最後的更新時間小于router的timstamp:

                        // 将router_id 從記憶體中儲存router更新時間的self.last_update_time字典中删除

                    if update.action == queue.CREATE_DISTRIBUTED_DHCP:

                        if update.id in self.router_info:

                            // continue。此時處理極端情況,當路由更新時,distributed_dhcp_notify 被接受到

                        如果從記憶體中儲存的_prefetched_routers能夠擷取到router:

                            将updateRouter中的prefetched_network 儲存到router的prefetched_networks屬性中

                    if update.action != queue.DELETE_ROUTER and not router:

                        通過router_id 從北向擷取router,擷取不到,傳回異常。

                        if update.action == queue.CREATE_DISTRIBUTED_DHCP:

                            将updateRouter中的prefetched_network 儲存到router的prefetched_networks屬性中,并将router_id儲存到記憶體中的_prefetched_routers字典中

                    if not router and update.action != queue.DELETE_ROUTER and update.id in self._prefetched_routers

                        // continue. Avoid removing prefetched router

                    if not router:

                        将router_id從記憶體中的_prefetched_routers 字典中删除

                        安全删除router:

                            通過router_id從router_info中擷取目前router的router_info

                            通過namespace_manager 删除router的namespace

                            發送 router before_delete消息

                            将router的router_info資訊從router_info中删除

                            發送 router after_delete消息

                        l3_agent_extensions_manager 調用配置檔案中的三層agent擴充驅動(driver)調用自身的delete_router方法删除router

                        更新router的timestamp,使其在processing queue隊列中變為 older events,防止删除的router重新建立。

                        将router_id從記憶體中的 _fetched_router_ids 字典中删除。

                    處理相容的路由:(_process_router_if_compatible)

                        if not self.conf.enable_inat_enat:

                            建立agent gw port(floating ip gw port)。檢測gw port是否存在,不存在進行建立:

                                建立fip namespace(fip-${net-id})

                                通過rpc_plugin從北向neutron-server擷取agent_gateway_port

                                建立fip namespace:

                                    ip netns add ${fip_namespace}

                                    ip netns exec ${fip_namespace} ip link set lo up

                                    ip netns exec ${fip_namespace} sysctl -w net.ipv4.ip_forward=1

                                    ip netns exec ${fip_namespace} sysctl -w net.ipv4.conf.all.rp_filter=0

                                    ip netns exec ${fip_namespace} sysctl -w net.ipv4.conf.default.rp_filter=0

                                擷取fg_interface_name(fg-${port_id前11位})

                                增加fip agent gateway:

                                    如果fip namespace中不存在 fg_interface_name,ovs建立該port。調用 interface_driver(neutron.agent.linux.interface.OVSInterfaceDriver) plug該接口(處理過程在dhcp agent分析過)

                                    fip namespace中初始化路由port. 調用interface_driver(neutron.agent.linux.interface.OVSInterfaceDriver) init_router_port 方法。

                                    在fip namespace中對agent_gateway_port 的每個fixip 執行garp:

                                         python ${python_site_package_dir}/neutron/agent/l3/send_arping.py ${fg_interface_name} ${fixip} ${agent_gateway_port_mac} 1

                                    在fip namespace中的fg_interface_name 接口上增加 agent_gateway_port的gw ip:

                                        ip netns exec ${fip_namespace} ip route replace default via ${gateway_ip}

                                        ip netns exec ${fip_namespace} sysctl -w net.ipv4.conf.${fg_interface_name}.proxy_arp=1

                                清除fg namespace 無用的port(lo接口除外)

                                fip ns 初始化完成        

                        if     router.get("prefetched_networks"): //router 中包含 prefetched_networks屬性

                            // 調用_process_prefetched_router 方法在路由中添加 prefetched_networks 路由資訊

                        如果 router 不在 router_info中:

                            // 增加router

                                從router_info中擷取router

                                調用router_info中的process()方法對router進行處理(router處理的核心邏輯。詳細走讀下期分解)

                                發送router的 after_create 通知

                                調用l3_ext_manager 中配置的driver的 add_router方法處理l3 擴充功能

                        否則:

                            // 更新router

                                從router_info中擷取router

                                發送router的 before_update 通知

                                調用router_info中的process()方法對router進行處理(router處理的核心邏輯。詳細走讀下期分解)

                                發送router的 after_update 通知

                                調用l3_ext_manager 中配置的driver的 add_router方法處理l3 擴充功能

                    更新routerProcess中RouterUpdate 的timestamp

                    +------------------end 完成單個RouterUpdate的處理---------------------------------+

            (b) 啟動一個協程池調用 _send_router_interface_garp 方法三分鐘一次輪詢處理,向router 發送garp。 對每個router中的每個qr port發送arp。

                在router的namespace(qrouter-${router_id})執行指令: python ${python_site_package_dir}/neutron/agent/l3/send_arping.py  ${gw_device_name} fa:fa:fa:fa:fa:fa ${qr_fixip} ${count}

繼續閱讀