def test_chassis_delete_event(self): self._test_chassis_helper('delete', self.row_json) self.driver.update_segment_host_mapping.assert_called_once_with( 'fake-hostname', []) if ovn_config.is_ovn_l3(): self.assertEqual( 1, self.l3_plugin.schedule_unhosted_routers.call_count)
def add_router_interface(self, context, router_id, interface_info): router_interface_info = super(OVNPlugin, self).add_router_interface( context, router_id, interface_info) if not config.is_ovn_l3(): LOG.debug(_("OVN L3 mode is disabled, skipping " "add_router_interface")) return router_interface_info port = self.get_port(context, router_interface_info['port_id']) subnet_id = port['fixed_ips'][0]['subnet_id'] subnet = self.get_subnet(context, subnet_id) lrouter = utils.ovn_name(router_id) cidr = netaddr.IPNetwork(subnet['cidr']) network = "%s/%s" % (port['fixed_ips'][0]['ip_address'], str(cidr.prefixlen)) self._ovn.add_lrouter_port(port['id'], lrouter, mac=port['mac_address'], network=network).execute(check_error=True) # TODO(chandrav) # The following code is to update the options column in the lport # table with {router-port: "UUID of logical_router_port"}. Ideally this # should have been handled ine one transaction with add_lrouter_port, # but due to a bug in idl, we are forced to update it in a separate # transaction. After the transaction is committed idl does not update # the UUID that is part of a string from old to new. self._ovn.set_lrouter_port_in_lport(port['id']).execute( check_error=True) return router_interface_info
def add_router_interface(self, context, router_id, interface_info): router_interface_info = super(OVNPlugin, self).add_router_interface( context, router_id, interface_info) if not config.is_ovn_l3(): LOG.debug("OVN L3 mode is disabled, skipping " "add_router_interface") return router_interface_info port = self.get_port(context, router_interface_info['port_id']) subnet_id = port['fixed_ips'][0]['subnet_id'] subnet = self.get_subnet(context, subnet_id) lrouter = utils.ovn_name(router_id) cidr = netaddr.IPNetwork(subnet['cidr']) network = "%s/%s" % (port['fixed_ips'][0]['ip_address'], str(cidr.prefixlen)) lrouter_port_name = utils.ovn_lrouter_port_name(port['id']) with self._ovn.transaction(check_error=True) as txn: txn.add(self._ovn.add_lrouter_port(name=lrouter_port_name, lrouter=lrouter, mac=port['mac_address'], network=network)) txn.add(self._ovn.set_lrouter_port_in_lport(port['id'], lrouter_port_name)) return router_interface_info
def _start_rpc_notifiers(self): """Initialize RPC notifiers for agents.""" self.agent_notifiers[const.AGENT_TYPE_DHCP] = ( dhcp_rpc_agent_api.DhcpAgentNotifyAPI() ) if not config.is_ovn_l3(): self.agent_notifiers[const.AGENT_TYPE_L3] = ( l3_rpc_agent_api.L3AgentNotifyAPI() )
def test_chassis_update_event(self): old_row_json = copy.deepcopy(self.row_json) old_row_json['external_ids'][1][0][1] = ("fake-phynet2:fake-br2") self._test_chassis_helper('update', self.row_json, old_row_json) self.driver.update_segment_host_mapping.assert_called_once_with( 'fake-hostname', ['fake-phynet1']) if ovn_config.is_ovn_l3(): self.assertEqual( 1, self.l3_plugin.schedule_unhosted_routers.call_count)
def start_rpc_listeners(self): self._setup_rpc() self.conn = n_rpc.create_connection() self.conn.create_consumer(topics.PLUGIN, self.endpoints, fanout=False) if not config.is_ovn_l3(): self.conn.create_consumer(topics.L3PLUGIN, self.endpoints, fanout=False) self.conn.create_consumer(topics.REPORTS, [agents_db.AgentExtRpcCallback()], fanout=False) return self.conn.consume_in_threads()
def run(self, event, row, old): host = row.hostname phy_nets = [] if event != self.ROW_DELETE: bridge_mappings = row.external_ids.get('ovn-bridge-mappings', '') mapping_dict = helpers.parse_mappings(bridge_mappings.split(',')) phy_nets = list(mapping_dict) self.driver.update_segment_host_mapping(host, phy_nets) if ovn_config.is_ovn_l3(): self.l3_plugin.schedule_unhosted_routers()
def run(self, event, row, old): host = row.hostname phy_nets = [] if event != self.ROW_DELETE: bridge_mappings = row.external_ids.get('ovn-bridge-mappings', '') mapping_dict = helpers.parse_mappings(bridge_mappings.split(',')) phy_nets = list(mapping_dict) self.driver.update_segment_host_mapping(host, phy_nets) if ovn_config.is_ovn_l3(): self.l3_plugin.schedule_unhosted_gateways()
def test_chassis_update_event(self): old_row_json = copy.deepcopy(self.row_json) old_row_json['external_ids'][1][0][1] = ( "fake-phynet2:fake-br2") self._test_chassis_helper('update', self.row_json, old_row_json) self.driver.update_segment_host_mapping.assert_called_once_with( 'fake-hostname', ['fake-phynet1']) if ovn_config.is_ovn_l3(): self.assertEqual( 1, self.l3_plugin.schedule_unhosted_routers.call_count)
def do_sync(self): """Method to sync the OVN_Southbound DB with neutron DB. OvnSbSynchronizer will sync data from OVN_Southbound to neutron. And the synchronization will always be performed, no matter what mode it is. """ LOG.debug("Starting OVN-Southbound DB sync process") ctx = context.get_admin_context() self.sync_hostname_and_physical_networks(ctx) if config.is_ovn_l3(): self.l3_plugin.schedule_unhosted_gateways()
def run(self, event, row, old): chassis = getattr(row, 'chassis', []) if chassis: router = row.datapath.external_ids.get('name', '').replace('neutron-', '') host = chassis[0].hostname LOG.info("Router %(router)s is bound to host %(host)s", { 'router': router, 'host': host }) if ovn_config.is_ovn_l3(): self.l3_plugin.update_router_gateway_port_bindings( router, host)
def _sync(self): """Method to sync the OVN_Southbound DB with neutron DB. OvnSbSynchronizer will sync data from OVN_Southbound to neutron. And the synchronization will always be performed, no matter what mode it is. """ # Initial delay until service is up greenthread.sleep(10) LOG.debug("Starting OVN-Southbound DB sync process") ctx = context.get_admin_context() self.sync_hostname_and_physical_networks(ctx) if config.is_ovn_l3(): self.l3_plugin.schedule_unhosted_routers()
def setUp(self): super(TestOvnSbIdlNotifyHandler, self).setUp() sb_helper = ovs_idl.SchemaHelper(schema_json=OVN_SB_SCHEMA) sb_helper.register_table('Chassis') self.sb_idl = ovsdb_monitor.OvnSbIdl(self.driver, "remote", sb_helper) self.sb_idl.lock_name = self.sb_idl.event_lock_name self.sb_idl.has_lock = True self.sb_idl.post_initialize(self.driver) self.chassis_table = self.sb_idl.tables.get('Chassis') self.driver.update_segment_host_mapping = mock.Mock() self.l3_plugin = directory.get_plugin(constants.L3) if ovn_config.is_ovn_l3(): self.l3_plugin.schedule_unhosted_gateways = mock.Mock() self.row_json = { "name": "fake-name", "hostname": "fake-hostname", "external_ids": ['map', [["ovn-bridge-mappings", "fake-phynet1:fake-br1"]]] }
def setUp(self): super(TestOvnSbIdlNotifyHandler, self).setUp() sb_helper = ovs_idl.SchemaHelper(schema_json=OVN_SB_SCHEMA) sb_helper.register_table('Chassis') self.sb_idl = ovsdb_monitor.OvnSbIdl(self.driver, "remote", sb_helper) self.sb_idl.lock_name = self.sb_idl.event_lock_name self.sb_idl.has_lock = True self.sb_idl.post_initialize(self.driver) self.chassis_table = self.sb_idl.tables.get('Chassis') self.driver.update_segment_host_mapping = mock.Mock() mgr = manager.NeutronManager.get_instance() self.l3_plugin = mgr.get_service_plugins().get( constants.L3) if ovn_config.is_ovn_l3(): self.l3_plugin.schedule_unhosted_routers = mock.Mock() self.row_json = { "name": "fake-name", "hostname": "fake-hostname", "external_ids": ['map', [["ovn-bridge-mappings", "fake-phynet1:fake-br1"]]] }
def remove_router_interface(self, context, router_id, interface_info): if not config.is_ovn_l3(): LOG.debug("OVN L3 mode is disabled, skipping " "remove_router_interface") return super(OVNPlugin, self).remove_router_interface( context, router_id, interface_info) # TODO(chandrav) # Need to rework this code to get the port_id when the incoming request # contains only the subnet_id. Also need to figure out if OVN needs to # care about multiple prefix subnets on a single router interface. # This code is duplicated from neutron. Probably a better thing to do # is to handle everything in the plugin and just call delete_port # update_port. port_id = None if 'port_id' in interface_info: port_id = interface_info['port_id'] elif 'subnet_id' in interface_info: subnet_id = interface_info['subnet_id'] subnet = self.get_subnet(context, subnet_id) device_filter = {'device_id': [router_id], 'device_owner': [const.DEVICE_OWNER_ROUTER_INTF], 'network_id': [subnet['network_id']]} ports = super(OVNPlugin, self).get_ports(context, filters=device_filter) for p in ports: port_subnets = [fip['subnet_id'] for fip in p['fixed_ips']] if subnet_id in port_subnets and len(port_subnets) == 1: port_id = p['id'] break router_interface_info = super(OVNPlugin, self).remove_router_interface( context, router_id, interface_info) if port_id is not None: self._ovn.delete_lrouter_port(utils.ovn_lrouter_port_name(port_id), utils.ovn_name(router_id), if_exists=False ).execute(check_error=True) return router_interface_info
def sync_routers_and_rports(self, ctx): """Sync Routers between neutron and NB. @param ctx: neutron context @type ctx: object of type neutron.context.Context @var db_routers: List of Routers from neutron DB @var db_router_ports: List of Router ports from neutron DB @var lrouters: NB dictionary of logical routers and the corresponding logical router ports. vs list-of-acls @var del_lrouters_list: List of Routers that need to be deleted from NB @var del_lrouter_ports_list: List of Router ports that need to be deleted from NB @return: Nothing """ if not config.is_ovn_l3(): LOG.debug("OVN L3 mode is disabled, skipping " "sync routers and router ports") return LOG.debug('OVN-NB Sync Routers and Router ports started') db_routers = {} db_router_ports = {} for router in self.l3_plugin.get_routers(ctx): db_routers[router['id']] = router interfaces = self.l3_plugin._get_sync_interfaces( ctx, db_routers.keys()) for interface in interfaces: db_router_ports[interface['id']] = interface lrouters = self.ovn_api.get_all_logical_routers_with_rports() del_lrouters_list = [] del_lrouter_ports_list = [] update_sroutes_list = [] for lrouter in lrouters: if lrouter['name'] in db_routers: for lrport in lrouter['ports']: if lrport in db_router_ports: del db_router_ports[lrport] else: del_lrouter_ports_list.append({ 'port': lrport, 'lrouter': lrouter['name'] }) if 'routes' in db_routers[lrouter['name']]: db_routes = db_routers[lrouter['name']]['routes'] else: db_routes = [] ovn_routes = lrouter['static_routes'] add_routes, del_routes = n_utils.diff_list_of_dict( ovn_routes, db_routes) update_sroutes_list.append({ 'id': lrouter['name'], 'add': add_routes, 'del': del_routes }) del db_routers[lrouter['name']] else: del_lrouters_list.append(lrouter) for r_id, router in db_routers.items(): LOG.warning( _LW("Router found in Neutron but not in " "OVN DB, router id=%s"), router['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning(_LW("Creating the router %s in OVN NB DB"), router['id']) self.l3_plugin.create_lrouter_in_ovn(router) if 'routes' in router: update_sroutes_list.append({ 'id': router['id'], 'add': router['routes'], 'del': [] }) except RuntimeError: LOG.warning( _LW("Create router in OVN NB failed for" " router %s"), router['id']) for rp_id, rrport in db_router_ports.items(): LOG.warning( _LW("Router Port found in Neutron but not in OVN " "DB, router port_id=%s"), rrport['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning( _LW("Creating the router port %s in " "OVN NB DB"), rrport['id']) self.l3_plugin.create_lrouter_port_in_ovn( ctx, rrport['device_id'], rrport) except RuntimeError: LOG.warning( _LW("Create router port in OVN " "NB failed for" " router port %s"), rrport['id']) with self.ovn_api.transaction(check_error=True) as txn: for lrouter in del_lrouters_list: LOG.warning( _LW("Router found in OVN but not in " "Neutron, router id=%s"), lrouter['name']) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Deleting the router %s from OVN NB DB"), lrouter['name']) txn.add( self.ovn_api.delete_lrouter( utils.ovn_name(lrouter['name']))) for lrport_info in del_lrouter_ports_list: LOG.warning( _LW("Router Port found in OVN but not in " "Neutron, port_id=%s"), lrport_info['port']) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Deleting the port %s from OVN NB DB"), lrport_info['port']) txn.add( self.ovn_api.delete_lrouter_port( utils.ovn_lrouter_port_name(lrport_info['port']), utils.ovn_name(lrport_info['lrouter']), if_exists=False)) for sroute in update_sroutes_list: if sroute['add']: LOG.warning( _LW("Router %(id)s static routes %(route)s " "found in Neutron but not in OVN"), { 'id': sroute['id'], 'route': sroute['add'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Add static routes %s to OVN NB DB"), sroute['add']) for route in sroute['add']: txn.add( self.ovn_api.add_static_route( utils.ovn_name(sroute['id']), ip_prefix=route['destination'], nexthop=route['nexthop'])) if sroute['del']: LOG.warning( _LW("Router %(id)s static routes %(route)s " "found in OVN but not in Neutron"), { 'id': sroute['id'], 'route': sroute['del'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning( _LW("Delete static routes %s from OVN " "NB DB"), sroute['del']) for route in sroute['del']: txn.add( self.ovn_api.delete_static_route( utils.ovn_name(sroute['id']), ip_prefix=route['destination'], nexthop=route['nexthop'])) LOG.debug('OVN-NB Sync routers and router ports finished')
def sync_routers_and_rports(self, ctx): """Sync Routers between neutron and NB. @param ctx: neutron context @type ctx: object of type neutron.context.Context @var db_routers: List of Routers from neutron DB @var db_router_ports: List of Router ports from neutron DB @var lrouters: NB dictionary of logical routers and the corresponding logical router ports. vs list-of-acls @var del_lrouters_list: List of Routers that need to be deleted from NB @var del_lrouter_ports_list: List of Router ports that need to be deleted from NB @return: Nothing """ if not config.is_ovn_l3(): LOG.debug("OVN L3 mode is disabled, skipping " "sync routers and router ports") return LOG.debug('OVN-NB Sync Routers and Router ports started') db_routers = {} db_router_ports = {} db_gateway_ports = {} db_fips = {} for router in self.l3_plugin.get_routers(ctx): db_routers[router['id']] = router db_routers[router['id']]['floating_ips'] = [] db_routers_keys = db_routers.keys() fips = self.l3_plugin.get_floatingips(ctx, {'router_id': db_routers_keys}) interfaces = self.l3_plugin._get_sync_interfaces( ctx, db_routers_keys, [ lib_constants.DEVICE_OWNER_ROUTER_INTF, lib_constants.DEVICE_OWNER_ROUTER_GW ]) for fip in fips: db_routers[fip['router_id']]['floating_ips'].append({ 'floating_ip_address': fip['floating_ip_address'], 'fixed_ip_address': fip['fixed_ip_address'] }) for interface in interfaces: if (interface['device_owner'] == lib_constants.DEVICE_OWNER_ROUTER_INTF): db_router_ports[interface['id']] = interface db_router_ports[interface['id']]['networks'] = sorted( self.l3_plugin.get_networks_for_lrouter_port( ctx, interface['fixed_ips'])) else: db_gateway_ports[interface['id']] = interface db_gateway_ports[interface['id']]['networks'] = sorted( self.l3_plugin.get_networks_for_lrouter_port( ctx, interface['fixed_ips'])) LOG.debug("Get neutron routers=%s", db_routers) LOG.debug("Get neutron router ports=%s", db_router_ports) LOG.debug("Get neutron gateway ports=%s", db_gateway_ports) lrouters = self.ovn_api.get_all_logical_routers_with_rports() LOG.debug("Get ovn routers=%s", lrouters) del_lrouters_list = [] del_lrouter_ports_list = [] del_gwrouter_ports_list = [] update_sroutes_list = [] update_fips_list = [] update_lrport_list = [] for lrouter in lrouters: if lrouter['name'] in db_routers: for lrport, lrport_nets in lrouter['ports'].items(): if lrport in db_router_ports: db_lrport_nets = db_router_ports[lrport]['networks'] if db_lrport_nets != sorted(lrport_nets): update_lrport_list.append( (lrouter['name'], db_router_ports[lrport])) del db_router_ports[lrport] else: del_lrouter_ports_list.append({ 'port': lrport, 'lrouter': lrouter['name'] }) for gwport, gwport_nets in lrouter['gateway_ports'].items(): if gwport in db_gateway_ports: del db_gateway_ports[gwport] else: del_gwrouter_ports_list.append({ 'port': gwport, 'lrouter': lrouter['name'], 'next_hop': lrouter['next_hop'] }) if 'routes' in db_routers[lrouter['name']]: db_routes = db_routers[lrouter['name']]['routes'] else: db_routes = [] ovn_routes = lrouter['static_routes'] add_routes, del_routes = n_utils.diff_list_of_dict( ovn_routes, db_routes) update_sroutes_list.append({ 'id': lrouter['name'], 'del': del_routes, 'add': add_routes }) ovn_fips = lrouter['floating_ips'] db_fips = db_routers[lrouter['name']]['floating_ips'] add_fips, del_fips = n_utils.diff_list_of_dict( ovn_fips, db_fips) update_fips_list.append({ 'id': lrouter['name'], 'add': add_fips, 'del': del_fips }) del db_routers[lrouter['name']] else: del_lrouters_list.append(lrouter) for r_id, router in db_routers.items(): LOG.warning( _LW("Router found in Neutron but not in " "OVN DB, router id=%s"), router['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning(_LW("Creating the router %s in OVN NB DB"), router['id']) self.l3_plugin.create_lrouter_in_ovn(router) if 'routes' in router: update_sroutes_list.append({ 'id': router['id'], 'add': router['routes'], 'del': [] }) if 'floating_ips' in router: update_fips_list.append({ 'id': router['id'], 'add': router['floating_ips'], 'del': [] }) except RuntimeError: LOG.warning( _LW("Create router in OVN NB failed for" " router %s"), router['id']) for rp_id, rrport in db_router_ports.items(): LOG.warning( _LW("Router Port found in Neutron but not in OVN " "DB, router port_id=%s"), rrport['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning( _LW("Creating the router port %s in " "OVN NB DB"), rrport['id']) self.l3_plugin.create_lrouter_port_in_ovn( ctx, rrport['device_id'], rrport) except RuntimeError: LOG.warning( _LW("Create router port in OVN " "NB failed for" " router port %s"), rrport['id']) for router_id, rport in update_lrport_list: LOG.warning( _LW("Router Port port_id=%s needs to be updated" " for networks changed"), rport['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning( _LW("Updating networks on router port %s in " "OVN NB DB"), rport['id']) self.l3_plugin.update_lrouter_port_in_ovn( ctx, router_id, rport, rport['networks']) except RuntimeError: LOG.warning( _LW("Update router port networks in OVN " "NB failed for" " router port %s"), rport['id']) for gwport_info in del_gwrouter_ports_list: LOG.warning( _LW("Gateway Port found in OVN but not in " "Neutron, port_id=%s"), gwport_info['port']) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Deleting the port %s from OVN NB DB"), gwport_info['port']) self.l3_plugin.delete_gw_router_port_in_ovn( gwport_info['lrouter'], gwport_info['port'], gwport_info['next_hop']) for gwp_id, gwport in db_gateway_ports.items(): LOG.warning( _LW("Gateway Port found in Neutron but not in OVN " "DB, gateway port_id=%s"), gwport['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning( _LW("Creating the gateway port %s in " "OVN NB DB"), gwport['id']) self.l3_plugin.create_gw_router_port_in_ovn( ctx, gwport['device_id'], gwport) except RuntimeError: LOG.warning( _LW("Create gateway port in OVN " "NB failed for" " gateway port %s"), gwport['id']) with self.ovn_api.transaction(check_error=True) as txn: for lrouter in del_lrouters_list: LOG.warning( _LW("Router found in OVN but not in " "Neutron, router id=%s"), lrouter['name']) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Deleting the router %s from OVN NB DB"), lrouter['name']) txn.add( self.ovn_api.delete_lrouter( utils.ovn_name(lrouter['name']))) txn.add( self.ovn_api.delete_lrouter( utils.ovn_gateway_name(lrouter['name']))) txn.add( self.ovn_api.delete_lswitch( utils.ovn_transit_name(lrouter['name']))) for lrport_info in del_lrouter_ports_list: LOG.warning( _LW("Router Port found in OVN but not in " "Neutron, port_id=%s"), lrport_info['port']) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Deleting the port %s from OVN NB DB"), lrport_info['port']) txn.add( self.ovn_api.delete_lrouter_port( utils.ovn_lrouter_port_name(lrport_info['port']), utils.ovn_name(lrport_info['lrouter']), if_exists=False)) for sroute in update_sroutes_list: if sroute['add']: LOG.warning( _LW("Router %(id)s static routes %(route)s " "found in Neutron but not in OVN"), { 'id': sroute['id'], 'route': sroute['add'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Add static routes %s to OVN NB DB"), sroute['add']) for route in sroute['add']: txn.add( self.ovn_api.add_static_route( utils.ovn_name(sroute['id']), ip_prefix=route['destination'], nexthop=route['nexthop'])) if sroute['del']: LOG.warning( _LW("Router %(id)s static routes %(route)s " "found in OVN but not in Neutron"), { 'id': sroute['id'], 'route': sroute['del'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning( _LW("Delete static routes %s from OVN " "NB DB"), sroute['del']) for route in sroute['del']: txn.add( self.ovn_api.delete_static_route( utils.ovn_name(sroute['id']), ip_prefix=route['destination'], nexthop=route['nexthop'])) for fip in update_fips_list: if fip['del']: LOG.warning( _LW("Router %(id)s floating ips %(fip)s " "found in OVN but not in Neutron"), { 'id': fip['id'], 'fip': fip['del'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning( _LW("Delete floating ips %s from OVN NB DB"), fip['del']) for ifip in fip['del']: txn.add( self.ovn_api.delete_nat( utils.ovn_gateway_name(fip['id']), logical_ip=ifip['fixed_ip_address'], external_ip=ifip['floating_ip_address'], type='dnat_and_snat')) if fip['add']: LOG.warning( _LW("Router %(id)s floating ips %(fip)s " "found in Neutron but not in OVN"), { 'id': fip['id'], 'fip': fip['add'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Add floating ips %s to OVN NB DB"), fip['add']) for ifip in fip['add']: txn.add( self.ovn_api.add_nat( utils.ovn_gateway_name(fip['id']), logical_ip=ifip['fixed_ip_address'], external_ip=ifip['floating_ip_address'], type='dnat_and_snat')) LOG.debug('OVN-NB Sync routers and router ports finished')
def sync_routers_and_rports(self, ctx): """Sync Routers between neutron and NB. @param ctx: neutron_lib.context @type ctx: object of type neutron_lib.context.Context @var db_routers: List of Routers from neutron DB @var db_router_ports: List of Router ports from neutron DB @var lrouters: NB dictionary of logical routers and the corresponding logical router ports. vs list-of-acls @var del_lrouters_list: List of Routers that need to be deleted from NB @var del_lrouter_ports_list: List of Router ports that need to be deleted from NB @return: Nothing """ if not config.is_ovn_l3(): LOG.debug("OVN L3 mode is disabled, skipping " "sync routers and router ports") return LOG.debug('OVN-NB Sync Routers and Router ports started @ %s' % str(datetime.now())) db_routers = {} db_extends = {} db_router_ports = {} for router in self.l3_plugin.get_routers(ctx): db_routers[router['id']] = router db_extends[router['id']] = {} db_extends[router['id']]['routes'] = [] db_extends[router['id']]['snats'] = [] db_extends[router['id']]['fips'] = [] if not router.get(l3.EXTERNAL_GW_INFO): continue r_ip, gw_ip = self.l3_plugin.get_external_router_and_gateway_ip( ctx, router) if gw_ip: db_extends[router['id']]['routes'].append({ 'destination': '0.0.0.0/0', 'nexthop': gw_ip }) if r_ip and utils.is_snat_enabled(router): networks = self.l3_plugin._get_v4_network_of_all_router_ports( ctx, router['id']) for network in networks: db_extends[router['id']]['snats'].append({ 'logical_ip': network, 'external_ip': r_ip, 'type': 'snat' }) fips = self.l3_plugin.get_floatingips( ctx, {'router_id': list(db_routers.keys())}) for fip in fips: db_extends[fip['router_id']]['fips'].append({ 'external_ip': fip['floating_ip_address'], 'logical_ip': fip['fixed_ip_address'], 'type': 'dnat_and_snat' }) interfaces = self.l3_plugin._get_sync_interfaces( ctx, db_routers.keys(), [ constants.DEVICE_OWNER_ROUTER_INTF, constants.DEVICE_OWNER_ROUTER_GW ]) for interface in interfaces: db_router_ports[interface['id']] = interface db_router_ports[interface['id']]['networks'] = sorted( self.l3_plugin.get_networks_for_lrouter_port( ctx, interface['fixed_ips'])) lrouters = self.ovn_api.get_all_logical_routers_with_rports() del_lrouters_list = [] del_lrouter_ports_list = [] update_sroutes_list = [] update_lrport_list = [] update_snats_list = [] update_fips_list = [] for lrouter in lrouters: if lrouter['name'] in db_routers: for lrport, lrport_nets in lrouter['ports'].items(): if lrport in db_router_ports: db_lrport_nets = db_router_ports[lrport]['networks'] if db_lrport_nets != sorted(lrport_nets): update_lrport_list.append( (lrouter['name'], db_router_ports[lrport])) del db_router_ports[lrport] else: del_lrouter_ports_list.append({ 'port': lrport, 'lrouter': lrouter['name'] }) if 'routes' in db_routers[lrouter['name']]: db_routes = db_routers[lrouter['name']]['routes'] else: db_routes = [] if 'routes' in db_extends[lrouter['name']]: db_routes.extend(db_extends[lrouter['name']]['routes']) ovn_routes = lrouter['static_routes'] add_routes, del_routes = helpers.diff_list_of_dict( ovn_routes, db_routes) update_sroutes_list.append({ 'id': lrouter['name'], 'add': add_routes, 'del': del_routes }) ovn_fips = lrouter['dnat_and_snats'] db_fips = db_extends[lrouter['name']]['fips'] add_fips, del_fips = helpers.diff_list_of_dict( ovn_fips, db_fips) update_fips_list.append({ 'id': lrouter['name'], 'add': add_fips, 'del': del_fips }) ovn_nats = lrouter['snats'] db_snats = db_extends[lrouter['name']]['snats'] add_snats, del_snats = helpers.diff_list_of_dict( ovn_nats, db_snats) update_snats_list.append({ 'id': lrouter['name'], 'add': add_snats, 'del': del_snats }) del db_routers[lrouter['name']] else: del_lrouters_list.append(lrouter) for r_id, router in db_routers.items(): LOG.warning( _LW("Router found in Neutron but not in " "OVN DB, router id=%s"), router['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning(_LW("Creating the router %s in OVN NB DB"), router['id']) self.l3_plugin.create_lrouter_in_ovn(router) if 'routes' in router: update_sroutes_list.append({ 'id': router['id'], 'add': router['routes'], 'del': [] }) if 'routes' in db_extends[router['id']]: update_sroutes_list.append({ 'id': router['id'], 'add': db_extends[router['id']]['routes'], 'del': [] }) if 'snats' in db_extends[router['id']]: update_snats_list.append({ 'id': router['id'], 'add': db_extends[router['id']]['snats'], 'del': [] }) if 'fips' in db_extends[router['id']]: update_fips_list.append({ 'id': router['id'], 'add': db_extends[router['id']]['fips'], 'del': [] }) except RuntimeError: LOG.warning( _LW("Create router in OVN NB failed for" " router %s"), router['id']) for rp_id, rrport in db_router_ports.items(): LOG.warning( _LW("Router Port found in Neutron but not in OVN " "DB, router port_id=%s"), rrport['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning( _LW("Creating the router port %s in " "OVN NB DB"), rrport['id']) self.l3_plugin.create_lrouter_port_in_ovn( ctx, rrport['device_id'], rrport) except RuntimeError: LOG.warning( _LW("Create router port in OVN " "NB failed for" " router port %s"), rrport['id']) for router_id, rport in update_lrport_list: LOG.warning( _LW("Router Port port_id=%s needs to be updated" " for networks changed"), rport['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning( _LW("Updating networks on router port %s in " "OVN NB DB"), rport['id']) self.l3_plugin.update_lrouter_port_in_ovn( ctx, router_id, rport, rport['networks']) except RuntimeError: LOG.warning( _LW("Update router port networks in OVN " "NB failed for" " router port %s"), rport['id']) with self.ovn_api.transaction(check_error=True) as txn: for lrouter in del_lrouters_list: LOG.warning( _LW("Router found in OVN but not in " "Neutron, router id=%s"), lrouter['name']) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Deleting the router %s from OVN NB DB"), lrouter['name']) txn.add( self.ovn_api.delete_lrouter( utils.ovn_name(lrouter['name']))) for lrport_info in del_lrouter_ports_list: LOG.warning( _LW("Router Port found in OVN but not in " "Neutron, port_id=%s"), lrport_info['port']) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Deleting the port %s from OVN NB DB"), lrport_info['port']) txn.add( self.ovn_api.delete_lrouter_port( utils.ovn_lrouter_port_name(lrport_info['port']), utils.ovn_name(lrport_info['lrouter']), if_exists=False)) for sroute in update_sroutes_list: if sroute['add']: LOG.warning( _LW("Router %(id)s static routes %(route)s " "found in Neutron but not in OVN"), { 'id': sroute['id'], 'route': sroute['add'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Add static routes %s to OVN NB DB"), sroute['add']) for route in sroute['add']: txn.add( self.ovn_api.add_static_route( utils.ovn_name(sroute['id']), ip_prefix=route['destination'], nexthop=route['nexthop'])) if sroute['del']: LOG.warning( _LW("Router %(id)s static routes %(route)s " "found in OVN but not in Neutron"), { 'id': sroute['id'], 'route': sroute['del'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning( _LW("Delete static routes %s from OVN " "NB DB"), sroute['del']) for route in sroute['del']: txn.add( self.ovn_api.delete_static_route( utils.ovn_name(sroute['id']), ip_prefix=route['destination'], nexthop=route['nexthop'])) for fip in update_fips_list: if fip['del']: LOG.warning( _LW("Router %(id)s floating ips %(fip)s " "found in OVN but not in Neutron"), { 'id': fip['id'], 'fip': fip['del'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning( _LW("Delete floating ips %s from OVN NB DB"), fip['del']) for nat in fip['del']: txn.add( self.ovn_api.delete_nat_rule_in_lrouter( utils.ovn_name(fip['id']), logical_ip=nat['logical_ip'], external_ip=nat['external_ip'], type='dnat_and_snat')) if fip['add']: LOG.warning( _LW("Router %(id)s floating ips %(fip)s " "found in Neutron but not in OVN"), { 'id': fip['id'], 'fip': fip['add'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Add floating ips %s to OVN NB DB"), fip['add']) for nat in fip['add']: txn.add( self.ovn_api.add_nat_rule_in_lrouter( utils.ovn_name(fip['id']), logical_ip=nat['logical_ip'], external_ip=nat['external_ip'], type='dnat_and_snat')) for snat in update_snats_list: if snat['del']: LOG.warning( _LW("Router %(id)s snat %(snat)s " "found in OVN but not in Neutron"), { 'id': snat['id'], 'snat': snat['del'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Delete snats %s from OVN NB DB"), snat['del']) for nat in snat['del']: txn.add( self.ovn_api.delete_nat_rule_in_lrouter( utils.ovn_name(snat['id']), logical_ip=nat['logical_ip'], external_ip=nat['external_ip'], type='snat')) if snat['add']: LOG.warning( _LW("Router %(id)s snat %(snat)s " "found in Neutron but not in OVN"), { 'id': snat['id'], 'snat': snat['add'] }) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Add snats %s to OVN NB DB"), snat['add']) for nat in snat['add']: txn.add( self.ovn_api.add_nat_rule_in_lrouter( utils.ovn_name(snat['id']), logical_ip=nat['logical_ip'], external_ip=nat['external_ip'], type='snat')) LOG.debug('OVN-NB Sync routers and router ports finished %s' % str(datetime.now()))
def sync_routers_and_rports(self, ctx): """Sync Routers between neutron and NB. @param ctx: neutron context @type ctx: object of type neutron.context.Context @var db_routers: List of Routers from neutron DB @var db_router_ports: List of Router ports from neutron DB @var lrouters: NB dictionary of logical routers and the corresponding logical router ports. vs list-of-acls @var del_lrouters_list: List of Routers that need to be deleted from NB @var del_lrouter_ports_list: List of Router ports that need to be deleted from NB @return: Nothing """ if not config.is_ovn_l3(): LOG.debug("OVN L3 mode is disabled, skipping " "sync routers and router ports") return LOG.debug('OVN-NB Sync Routers and Router ports started') db_routers = {} db_router_ports = {} for router in self.l3_plugin.get_routers(ctx): db_routers[router['id']] = router interfaces = self.l3_plugin._get_sync_interfaces(ctx, db_routers.keys()) for interface in interfaces: db_router_ports[interface['id']] = interface lrouters = self.ovn_api.get_all_logical_routers_with_rports() del_lrouters_list = [] del_lrouter_ports_list = [] update_sroutes_list = [] for lrouter in lrouters: if lrouter['name'] in db_routers: for lrport in lrouter['ports']: if lrport in db_router_ports: del db_router_ports[lrport] else: del_lrouter_ports_list.append( {'port': lrport, 'lrouter': lrouter['name']}) if 'routes' in db_routers[lrouter['name']]: db_routes = db_routers[lrouter['name']]['routes'] else: db_routes = [] ovn_routes = lrouter['static_routes'] add_routes, del_routes = n_utils.diff_list_of_dict( ovn_routes, db_routes) update_sroutes_list.append({'id': lrouter['name'], 'add': add_routes, 'del': del_routes}) del db_routers[lrouter['name']] else: del_lrouters_list.append(lrouter) for r_id, router in db_routers.items(): LOG.warning(_LW("Router found in Neutron but not in " "OVN DB, router id=%s"), router['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning(_LW("Creating the router %s in OVN NB DB"), router['id']) self.l3_plugin.create_lrouter_in_ovn(router) if 'routes' in router: update_sroutes_list.append( {'id': router['id'], 'add': router['routes'], 'del': []}) except RuntimeError: LOG.warning(_LW("Create router in OVN NB failed for" " router %s"), router['id']) for rp_id, rrport in db_router_ports.items(): LOG.warning(_LW("Router Port found in Neutron but not in OVN " "DB, router port_id=%s"), rrport['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning(_LW("Creating the router port %s in " "OVN NB DB"), rrport['id']) self.l3_plugin.create_lrouter_port_in_ovn( ctx, rrport['device_id'], rrport) except RuntimeError: LOG.warning(_LW("Create router port in OVN " "NB failed for" " router port %s"), rrport['id']) with self.ovn_api.transaction(check_error=True) as txn: for lrouter in del_lrouters_list: LOG.warning(_LW("Router found in OVN but not in " "Neutron, router id=%s"), lrouter['name']) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Deleting the router %s from OVN NB DB"), lrouter['name']) txn.add(self.ovn_api.delete_lrouter( utils.ovn_name(lrouter['name']))) for lrport_info in del_lrouter_ports_list: LOG.warning(_LW("Router Port found in OVN but not in " "Neutron, port_id=%s"), lrport_info['port']) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Deleting the port %s from OVN NB DB"), lrport_info['port']) txn.add(self.ovn_api.delete_lrouter_port( utils.ovn_lrouter_port_name(lrport_info['port']), utils.ovn_name(lrport_info['lrouter']), if_exists=False)) for sroute in update_sroutes_list: if sroute['add']: LOG.warning("Router %s static routes %s found in " "Neutron but not in OVN", sroute['id'], sroute['add']) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Add static routes %s to OVN NB DB"), sroute['add']) for route in sroute['add']: txn.add(self.ovn_api.add_static_route( utils.ovn_name(sroute['id']), ip_prefix=route['destination'], nexthop=route['nexthop'])) if sroute['del']: LOG.warning("Router %s static routes %s found in " "OVN but not in Neutron", sroute['id'], sroute['del']) if self.mode == SYNC_MODE_REPAIR: LOG.warning(_LW("Delete static routes %s from OVN " "NB DB"), sroute['del']) for route in sroute['del']: txn.add(self.ovn_api.delete_static_route( utils.ovn_name(sroute['id']), ip_prefix=route['destination'], nexthop=route['nexthop'])) LOG.debug('OVN-NB Sync routers and router ports finished')
def _setup_rpc(self): self.endpoints = [dhcp_rpc.DhcpRpcCallback(), agents_db.AgentExtRpcCallback(), metadata_rpc.MetadataRpcCallback()] if not config.is_ovn_l3(): self.endpoints.append(l3_rpc.L3RpcCallback())