Ejemplo n.º 1
0
    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()
Ejemplo n.º 2
0
 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)
Ejemplo n.º 3
0
    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()
Ejemplo n.º 4
0
 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()
Ejemplo n.º 5
0
    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()))