Example #1
0
 def delete_gw_router_port_in_ovn(self, router_id, gw_port_id,
                                  provnet_gw_ip):
     LOG.debug("Class OVNL3RouterPlugin:::")
     # delete default route on dvr-router if exists.
     dvr_default_route = {
         'destination': ovn_const.OVN_DEFAULT_ROUTE_CIDR,
         'nexthop': ovn_const.OVN_GATEWAY_TRANSIT_PORT_IP
     }
     dvr_router_name = utils.ovn_name(router_id)
     gw_router_name = utils.ovn_gateway_name(router_id)
     with self._ovn.transaction(check_error=True) as txn:
         # 1. clear default route of dvr-router.
         txn.add(
             self._ovn.delete_static_route(
                 dvr_router_name,
                 ip_prefix=dvr_default_route['destination'],
                 nexthop=dvr_default_route['nexthop']))
         # 2. remove gw port of gw-router.
         txn.add(
             self._ovn.delete_lrouter_port('lrp-%s' % gw_port_id,
                                           lrouter=gw_router_name))
         # 3. clear default snat on gw-router.
         txn.add(
             self._ovn.delete_nat(gw_router_name, logical_ip='0.0.0.0/0'))
         # 4. clear default route on gw-router.
         txn.add(
             self._ovn.delete_static_route(
                 gw_router_name,
                 ip_prefix=ovn_const.OVN_DEFAULT_ROUTE_CIDR,
                 nexthop=provnet_gw_ip))
Example #2
0
    def create_gw_router_port_in_ovn(self, context, router_id, gw_port):
        """Create lrouter in OVN

        @param context:
        @param router_id: neutron Router id for the port that needs to be created
        @param chassis: chassis where gateway Router to be created
        @param gw_port: neutorn gw port
        @return: Nothing
        """
        dvr_router_name = utils.ovn_name(router_id)
        gw_router_name = utils.ovn_gateway_name(router_id)
        gw_port_name = 'lrp-%s' % gw_port['id']
        with self._ovn.transaction(check_error=True) as txn:
            txn.add(
                self._ovn.add_lrouter_port(
                    name=gw_port_name,
                    lrouter=gw_router_name,
                    mac=gw_port['mac_address'],
                    networks=self.get_networks_for_lrouter_port(
                        context, gw_port['fixed_ips'])))
            # connect  Gateway to provnet
            txn.add(
                self._ovn.set_lrouter_port_in_lswitch_port(
                    lswitch_port=gw_port['id'], lrouter_port=gw_port_name))
        # add static route for gw_router and dvr-router.
        dvr_default_route = {
            'destination': ovn_const.OVN_DEFAULT_ROUTE_CIDR,
            'nexthop': ovn_const.OVN_GATEWAY_TRANSIT_PORT_IP
        }
        gw_default_gateway = self.get_subnet_gateway_ips(
            context, gw_port['fixed_ips'])[0]
        gw_default_route = {
            'destination': ovn_const.OVN_DEFAULT_ROUTE_CIDR,
            'nexthop': gw_default_gateway
        }
        with self._ovn.transaction(check_error=True) as txn:
            # add default route for two ovn-router.
            txn.add(
                self._ovn.add_static_route(
                    dvr_router_name,
                    ip_prefix=dvr_default_route['destination'],
                    nexthop=dvr_default_route['nexthop']))
            txn.add(
                self._ovn.add_static_route(
                    gw_router_name,
                    ip_prefix=gw_default_route['destination'],
                    nexthop=gw_default_route['nexthop']))
            # add default snat to gw_router .
            txn.add(
                self._ovn.add_nat(
                    gw_router_name,
                    logical_ip='0.0.0.0/0',
                    external_ip=gw_port['fixed_ips'][0]['ip_address'],
                    type='snat'))
Example #3
0
    def disassociate_floatingip(self, context, router_id, floatingip):
        LOG.debug('OVNL3RouterPlugin::')

        fixed_ip = floatingip['fixed_ip_address']
        floating_ip = floatingip['floating_ip_address']
        gw_router_name = utils.ovn_gateway_name(router_id)
        with self._ovn.transaction(check_error=True) as txn:
            txn.add(
                self._ovn.delete_nat(gw_router_name,
                                     logical_ip=fixed_ip,
                                     external_ip=floating_ip,
                                     type='dnat_and_snat'))
Example #4
0
 def delete_router(self, context, id):
     router_name = utils.ovn_name(id)
     ret_val = super(OVNL3RouterPlugin, self).delete_router(context, id)
     self._ovn.delete_lrouter(router_name).execute(check_error=True)
     # NOTE(zhoucx): here we needn't delete gw_info(neutron gw_port) ,
     # parent class will do it if gw_port exists(by call update_router_gw_info).
     # (zhoucx)delete gw_router and transit_switch.
     gw_router_name = utils.ovn_gateway_name(id)
     switch_name = utils.ovn_transit_name(id)
     self._ovn.delete_lrouter(gw_router_name).execute(check_error=True)
     self._ovn.delete_lswitch(switch_name).execute(check_error=True)
     return ret_val
Example #5
0
    def del_returned_route_on_gw(self, context, router_id, subnet_id):
        """del static route for subnet that ports located in on gw-router.

        @param router id : LRouter ID for the port
        @param subnet_id : subnet_id router-interface belongs to
        @return: Nothing
        """
        LOG.debug('OVNL3RouterPlugin::')
        ovn_router_name = utils.ovn_gateway_name(router_id)
        subnet = self._plugin.get_subnet(context, subnet_id)
        route = {'destination': subnet['cidr'], 'nexthop': '169.254.128.2'}
        with self._ovn.transaction(check_error=True) as txn:
            txn.add(
                self._ovn.delete_static_route(ovn_router_name,
                                              ip_prefix=route['destination'],
                                              nexthop=route['nexthop']))
Example #6
0
    def add_returned_route_on_gw(self, context, router_id, port):
        """add static route for subnet that ports located in on gw-router.

        @param router id : LRouter ID for the port
        @param port : LRouter port
        @return: Nothing
        """
        LOG.debug('OVNL3RouterPlugin::')
        ovn_router_name = utils.ovn_gateway_name(router_id)
        for fixed_ip in port['fixed_ips']:
            subnet_id = fixed_ip['subnet_id']
            subnet = self._plugin.get_subnet(context, subnet_id)
            route = {
                'destination': subnet['cidr'],
                'nexthop': ovn_const.OVN_LROUTER_TRANSIT_PORT_IP
            }
            with self._ovn.transaction(check_error=True) as txn:
                txn.add(
                    self._ovn.add_static_route(ovn_router_name,
                                               ip_prefix=route['destination'],
                                               nexthop=route['nexthop']))
Example #7
0
    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')
Example #8
0
    def create_lrouter_in_ovn(self, router):
        """Create lrouter in OVN

        @param router: Router to be created in OVN
        @return: Nothing
        """

        router_name = utils.ovn_name(router['id'])
        external_ids = {
            ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY:
            router.get('name', 'no_router_name')
        }
        enabled = router.get('admin_state_up')
        with self._ovn.transaction(check_error=True) as txn:
            txn.add(
                self._ovn.create_lrouter(router_name,
                                         external_ids=external_ids,
                                         enabled=enabled))
            # todo(zhoucx): create gw resource.
            selected_chassis = self.scheduler.select(self._ovn, self._sb_ovn,
                                                     None)
            # NOTE(zhoucx) here we can ignore selected_chassis == ovn_const.OVN_GATEWAY_INVALID_CHASSIS,
            # schedule_unhosted_routers() will update it .
            gw_router_name = utils.ovn_gateway_name(router['id'])
            router_options = {'chassis': selected_chassis}
            txn.add(
                self._ovn.create_lrouter(gw_router_name,
                                         external_ids={
                                             ovn_const.OVN_GATEWAY_EXT_ID_KEY:
                                             router['name']
                                         },
                                         options=router_options,
                                         enabled=True))
            # create transit switch
            transit_switch_name = 'transit-' + router['id']
            txn.add(
                self._ovn.create_lswitch(
                    lswitch_name=transit_switch_name,
                    external_ids={
                        ovn_const.OVN_TRANSIT_NETWORK_EXT_ID_KEY:
                        router['name']
                    }))
        # create
        with self._ovn.transaction(check_error=True) as txn:
            base_mac = n_cfg.CONF.base_mac.split(':')
            dvr_to_transit_port = {
                'mac_address': n_utils.get_random_mac(base_mac),
                'networks': ovn_const.OVN_LROUTER_TRANSIT_PORT_NETWORK,
                'ip_address': ovn_const.OVN_LROUTER_TRANSIT_PORT_IP
            }
            txn.add(
                self._ovn.add_lrouter_port(
                    name='dvr-to-transit-%s' % router['id'],
                    lrouter=router_name,
                    mac=dvr_to_transit_port['mac_address'],
                    networks=dvr_to_transit_port['networks']))

            txn.add(
                self._ovn.create_lswitch_port(
                    lport_name='transit-to-dvr-%s' % router['id'],
                    lswitch_name=transit_switch_name,
                    addresses=[
                        dvr_to_transit_port['mac_address'] + ' ' +
                        dvr_to_transit_port['ip_address']
                    ],
                    external_ids=None,
                    type='router'))
            gw_to_transit_port = {
                'mac_address': n_utils.get_random_mac(base_mac),
                'networks': ovn_const.OVN_GATEWAY_TRANSIT_PORT_NETWORK,
                'ip_address': ovn_const.OVN_GATEWAY_TRANSIT_PORT_IP
            }
            txn.add(
                self._ovn.add_lrouter_port(
                    name='gw-to-transit-%s' % router['id'],
                    lrouter=gw_router_name,
                    mac=gw_to_transit_port['mac_address'],
                    networks=gw_to_transit_port['networks']))
            txn.add(
                self._ovn.create_lswitch_port(
                    lport_name='transit-to-gw-%s' % router['id'],
                    lswitch_name=transit_switch_name,
                    addresses=[
                        gw_to_transit_port['mac_address'] + ' ' +
                        gw_to_transit_port['ip_address']
                    ],
                    external_ids=None,
                    type='router'))
        # connect them.
        with self._ovn.transaction(check_error=True) as txn:
            txn.add(
                self._ovn.set_lrouter_port_in_lswitch_port(
                    lswitch_port='transit-to-dvr-%s' % router['id'],
                    lrouter_port='dvr-to-transit-%s' % router['id']))
            txn.add(
                self._ovn.set_lrouter_port_in_lswitch_port(
                    lswitch_port='transit-to-gw-%s' % router['id'],
                    lrouter_port='gw-to-transit-%s' % router['id']))