轉載自https://blog.csdn.net/canxinghen/article/details/39395957數據庫
【小小:原文寫的很好,高屋建瓴的描述了啓動過程的主要步驟。根據原文所在博客的其餘系列文章,多是基於J版進行描述的。我目前讀的代碼是M版。】安全
【如下內容提綱挈領的文字摘抄自原文,具體代碼及分析過程是新增長的】網絡
【原文聲明】:app
本博客歡迎轉載,但請保留原做者信息!socket
做者:華爲雲計算工程師 林凱ide
團隊:華爲杭州研發中心OpenStack社區團隊函數
引用其中對L2 Agent的組件的介紹:L2Agent一般運行在Hypervisor,與neutron-server經過RPC通訊、監聽並通知設備的變化,建立新的設備來確保網絡segment的正確性,應用security groups規則等。oop
例如,OVS Agent,使用Open vSwitch來實現VLAN, GRE,VxLAN來實現網絡的隔離,還包括了網絡流量的轉發控制。ui
OVS Agent組件啓動大體流程以下圖所示:雲計算
1 # 小小:這裏引用的是M版代碼 2 def main(bridge_classes): 3 prepare_xen_compute() 4 validate_tunnel_config(cfg.CONF.AGENT.tunnel_types, cfg.CONF.OVS.local_ip) 5 6 try: 7 agent = OVSNeutronAgent(bridge_classes, cfg.CONF) 8 except (RuntimeError, ValueError) as e: 9 LOG.error(_LE("%s Agent terminated!"), e) 10 sys.exit(1) 11 agent.daemon_loop()
上述代碼中,最重要的是:
(第7行)實例化一個OVSNeutronAgent,在實例初始化過程當中,完成OVS Agent的一系列初始化工做。
(第11行)函數一直在循環檢查一些狀態,發現狀態發生變化,執行相應的操做。
接下來,首先仔細分析OVSNeutronAgent實例化,看它作了哪些初始化工做:
1 def __init__(self, bridge_classes, conf=None): 2 '''Constructor. 3 4 :param bridge_classes: a dict for bridge classes. 5 :param conf: an instance of ConfigOpts 6 ''' 7 super(OVSNeutronAgent, self).__init__() 8 self.conf = conf or cfg.CONF 9 # 【!!!】BaseOVS類中利用OVSDbVsctl類執行ovs的各類操做命令 10 self.ovs = ovs_lib.BaseOVS() 11 agent_conf = self.conf.AGENT 12 ovs_conf = self.conf.OVS 13 14 self.fullsync = False 15 # init bridge classes with configured datapath type. 16 # 【?】datapath_type在配置文件中爲system 17 self.br_int_cls, self.br_phys_cls, self.br_tun_cls = ( 18 functools.partial(bridge_classes[b], 19 datapath_type=ovs_conf.datapath_type) 20 for b in ('br_int', 'br_phys', 'br_tun')) 21 22 self.use_veth_interconnection = ovs_conf.use_veth_interconnection 23 self.veth_mtu = agent_conf.veth_mtu 24 # 保存還沒有被使用的local vlan 25 self.available_local_vlans = set(moves.range(p_const.MIN_VLAN_TAG, 26 p_const.MAX_VLAN_TAG)) 27 # 配置文件中tunnel_types = vxlan 28 self.tunnel_types = agent_conf.tunnel_types or [] 29 self.l2_pop = agent_conf.l2_population 30 # TODO(ethuleau): Change ARP responder so it's not dependent on the 31 # ML2 l2 population mechanism driver. 32 # 是否啓用了DVR模式 配置中爲True 33 self.enable_distributed_routing = agent_conf.enable_distributed_routing 34 self.arp_responder_enabled = agent_conf.arp_responder and self.l2_pop 35 36 host = self.conf.host 37 self.agent_id = 'ovs-agent-%s' % host 38 39 if self.tunnel_types: 40 self.enable_tunneling = True 41 else: 42 self.enable_tunneling = False 43 44 # Validate agent configurations 45 self._check_agent_configurations() 46 47 # Keep track of int_br's device count for use by _report_state() 48 self.int_br_device_count = 0 49 50 # 【!!!】建立br-int網橋 51 self.int_br = self.br_int_cls(ovs_conf.integration_bridge) 52 self.setup_integration_br() 53 # Stores port update notifications for processing in main rpc loop 54 self.updated_ports = set() 55 # Stores port delete notifications 56 self.deleted_ports = set() 57 58 self.network_ports = collections.defaultdict(set) 59 # keeps association between ports and ofports to detect ofport change 60 self.vifname_to_ofport_map = {} 61 # 【!!!】建立RPC相關客戶端(請求plugin提供服務)、服務端(響應plugin的資源變化通知) 62 self.setup_rpc() 63 # 示例配置bridge_mappings = test_vlan_net:brqd8d5c382-f7 64 self.bridge_mappings = self._parse_bridge_mappings( 65 ovs_conf.bridge_mappings) 66 # 【!!!】建立物理網的網橋 67 self.setup_physical_bridges(self.bridge_mappings) 68 # 【?】 69 self.local_vlan_map = {} 70 71 self._reset_tunnel_ofports() 72 73 self.polling_interval = agent_conf.polling_interval 74 self.minimize_polling = agent_conf.minimize_polling 75 self.ovsdb_monitor_respawn_interval = ( 76 agent_conf.ovsdb_monitor_respawn_interval or 77 constants.DEFAULT_OVSDBMON_RESPAWN) 78 self.local_ip = ovs_conf.local_ip 79 self.tunnel_count = 0 80 self.vxlan_udp_port = agent_conf.vxlan_udp_port 81 self.dont_fragment = agent_conf.dont_fragment 82 self.tunnel_csum = agent_conf.tunnel_csum 83 self.tun_br = None 84 self.patch_int_ofport = constants.OFPORT_INVALID 85 self.patch_tun_ofport = constants.OFPORT_INVALID 86 if self.enable_tunneling: 87 # The patch_int_ofport and patch_tun_ofport are updated 88 # here inside the call to setup_tunnel_br() 89 # 【!!!】建立br-tun 90 self.setup_tunnel_br(ovs_conf.tunnel_bridge) 91 92 # 【?】當前沒有配置extension(entry文件中僅有一個qos) 93 self.init_extension_manager(self.connection) 94 95 # 【!!!】DVR相關的主機mac、端口流表的處理類 96 self.dvr_agent = ovs_dvr_neutron_agent.OVSDVRNeutronAgent( 97 self.context, 98 self.dvr_plugin_rpc, 99 self.int_br, 100 self.tun_br, 101 self.bridge_mappings, 102 self.phys_brs, 103 self.int_ofports, 104 self.phys_ofports, 105 self.patch_int_ofport, 106 self.patch_tun_ofport, 107 host, 108 self.enable_tunneling, 109 self.enable_distributed_routing) 110 111 if self.enable_tunneling: 112 # 【!!!】下發br-tun的初始化流表 113 self.setup_tunnel_br_flows() 114 115 # 【!!!】下發DVR的初始化流表 116 self.dvr_agent.setup_dvr_flows() 117 118 # 【?】建立輔助橋,如今看來爲空 119 # Collect additional bridges to monitor 120 self.ancillary_brs = self.setup_ancillary_bridges( 121 ovs_conf.integration_bridge, ovs_conf.tunnel_bridge) 122 123 # In order to keep existed device's local vlan unchanged, 124 # restore local vlan mapping at start 125 # 【!!!】掃描br-int的ports,找已被使用的vlan號和network的對應關係 126 self._restore_local_vlan_map() 127 128 # Security group agent support 129 # 【!!!】調用xxxFirewallDriver利用iptables實現安全組規則 130 # 使用到的driver=iptables_hybrid(不用ovs實現,在qbr上實現) 131 self.sg_agent = sg_rpc.SecurityGroupAgentRpc(self.context, 132 self.sg_plugin_rpc, self.local_vlan_map, 133 defer_refresh_firewall=True, integration_bridge=self.int_br) 134 135 # we default to False to provide backward compat with out of tree 136 # firewall drivers that expect the logic that existed on the Neutron 137 # server which only enabled hybrid plugging based on the use of the 138 # hybrid driver. 139 hybrid_plug = getattr(self.sg_agent.firewall, 140 'OVS_HYBRID_PLUG_REQUIRED', False) 141 # 當前場景配置爲True 142 self.prevent_arp_spoofing = ( 143 agent_conf.prevent_arp_spoofing and 144 not self.sg_agent.firewall.provides_arp_spoofing_protection) 145 146 #TODO(mangelajo): optimize resource_versions to only report 147 # versions about resources which are common, 148 # or which are used by specific extensions. 149 # 狀態報告的內容,由_report_state()函數上報給plugin 150 self.agent_state = { 151 'binary': 'neutron-openvswitch-agent', 152 'host': host, 153 'topic': n_const.L2_AGENT_TOPIC, 154 'configurations': {'bridge_mappings': self.bridge_mappings, 155 'tunnel_types': self.tunnel_types, 156 'tunneling_ip': self.local_ip, 157 'l2_population': self.l2_pop, 158 'arp_responder_enabled': 159 self.arp_responder_enabled, 160 'enable_distributed_routing': 161 self.enable_distributed_routing, 162 'log_agent_heartbeats': 163 agent_conf.log_agent_heartbeats, 164 'extensions': self.ext_manager.names(), 165 'datapath_type': ovs_conf.datapath_type, 166 'ovs_capabilities': self.ovs.capabilities, 167 'vhostuser_socket_dir': 168 ovs_conf.vhostuser_socket_dir, 169 portbindings.OVS_HYBRID_PLUG: hybrid_plug}, 170 'resource_versions': resources.LOCAL_RESOURCE_VERSIONS, 171 'agent_type': agent_conf.agent_type, 172 'start_flag': True} 173 174 report_interval = agent_conf.report_interval 175 if report_interval: 176 heartbeat = loopingcall.FixedIntervalLoopingCall( 177 self._report_state) 178 heartbeat.start(interval=report_interval) 179 # 【!!!】這裏初始化的變量均會用在rpc_loop()中 180 # Initialize iteration counter 181 self.iter_num = 0 182 self.run_daemon_loop = True 183 184 self.catch_sigterm = False 185 self.catch_sighup = False 186 187 # 【!!!】開始接收消息,處理RPC請求 188 # The initialization is complete; we can start receiving messages 189 self.connection.consume_in_threads() 190 191 self.quitting_rpc_timeout = agent_conf.quitting_rpc_timeout
注意代碼中的【!!!】和【?】註釋,歎號表示主要過程和函數,問號表示沒看懂。
最後把run_daemon_loop變量置爲True,開始循環查詢的工做。當run_daemon_loop變量置爲True,main函數調用daemon_loop函數,以後調用rpc_loop函數,咱們來看下rpc_loop函數都完成了哪些工做。
rpc_loop作的工做很明顯就是進行循環地查詢一些狀態,根據這些狀態,進行相應的操做,其中最重要的工做就是掃描數據庫中的ports信息,而後對這些信息進行處理。
獲取到port_info以後就要根據這些信息,對port進行真正的操做,真正的操做就在函數process_network_ports中進行。
從代碼的解釋能夠看到,process_network_ports完成了port的添加,刪除和更新的操做。以後循環檢測是否已經到了循環間隔,若是尚未到間隔時間就sleep到那個時間,而後繼續循環工做。