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(','), unique_values=False) phy_nets = list(mapping_dict) self.driver.update_segment_host_mapping(host, phy_nets) if utils.is_ovn_l3(self.l3_plugin): self.l3_plugin.schedule_unhosted_gateways()
def run(self, event, row, old): if not utils.is_ovn_l3(self.l3_plugin): return router = host = None chassis = getattr(row, 'chassis', None) 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}) self.l3_plugin.update_router_gateway_port_bindings( router, host)
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 utils.is_ovn_l3(self.l3_plugin): self.l3_plugin.schedule_unhosted_gateways()
def stop(self): if utils.is_ovn_l3(self.l3_plugin): self.l3_plugin._ovn.ovsdb_connection.stop() self.l3_plugin._sb_ovn.ovsdb_connection.stop() super(OvnNbSynchronizer, self).stop()
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 utils.is_ovn_l3(self.l3_plugin): 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 gw_info = self._ovn_client._get_gw_info(ctx, router) if gw_info.gateway_ip: db_extends[router['id']]['routes'].append({ 'destination': '0.0.0.0/0', 'nexthop': gw_info.gateway_ip }) if gw_info.router_ip and utils.is_snat_enabled(router): networks = ( self._ovn_client._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': gw_info.router_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(fip) interfaces = self.l3_plugin._get_sync_interfaces( ctx, list(db_routers.keys()), [ constants.DEVICE_OWNER_ROUTER_INTF, constants.DEVICE_OWNER_ROUTER_GW, constants.DEVICE_OWNER_DVR_INTERFACE, constants.DEVICE_OWNER_ROUTER_HA_INTF, constants.DEVICE_OWNER_HA_REPLICATED_INT ]) 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 = [] 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: # We dont have to check for the networks and # ipv6_ra_configs values. Lets add it to the # update_lrport_list. If they are in sync, then # update_router_port will be a no-op. update_lrport_list.append(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 = self._calculate_fips_differences( 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( "Router found in Neutron but not in " "OVN DB, router id=%s", router['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning("Creating the router %s in OVN NB DB", router['id']) self._ovn_client.create_router(router, add_external_gateway=False) 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("Create router in OVN NB failed for router %s", router['id']) for rp_id, rrport in db_router_ports.items(): LOG.warning( "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("Creating the router port %s in OVN NB DB", rrport['id']) self._ovn_client.create_router_port( rrport['device_id'], rrport) except RuntimeError: LOG.warning( "Create router port in OVN " "NB failed for router port %s", rrport['id']) for rport in update_lrport_list: LOG.warning( "Router Port port_id=%s needs to be updated " "for networks changed", rport['id']) if self.mode == SYNC_MODE_REPAIR: try: LOG.warning( "Updating networks on router port %s in OVN NB DB", rport['id']) self._ovn_client.update_router_port(rport) except RuntimeError: LOG.warning( "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( "Router found in OVN but not in " "Neutron, router id=%s", lrouter['name']) if self.mode == SYNC_MODE_REPAIR: LOG.warning("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( "Router Port found in OVN but not in " "Neutron, port_id=%s", lrport_info['port']) if self.mode == SYNC_MODE_REPAIR: LOG.warning("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 %(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("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 %(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("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( "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("Delete floating ips %s from OVN NB DB", fip['del']) for nat in fip['del']: self._ovn_client._delete_floatingip(nat, utils.ovn_name( fip['id']), txn=txn) if fip['add']: LOG.warning( "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("Add floating ips %s to OVN NB DB", fip['add']) for nat in fip['add']: self._ovn_client._create_or_update_floatingip( nat, txn=txn) for snat in update_snats_list: if snat['del']: LOG.warning( "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("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( "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("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()))