天天看点

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}

继续阅读