def _get_l3_admin_net(self, create=False):
        network = None
        context = self._get_admin_context()
        filters = self._get_l3_admin_net_query_filter()
        networks = self._plugin.get_networks(context, filters=filters)

        if len(networks) == 0 and create:
            try:
                network = self._create_l3_admin_net(context)
                self._create_l3_admin_subnet(context, network["id"])
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(_LE("Error in creating L3 admin network."))
        elif len(networks) == 1:
            network = networks[0]
            subnet_ids = network.get("subnets")
            net_id = network["id"]
            if not subnet_ids and create:
                try:
                    self._create_l3_admin_subnet(context, net_id)
                except Exception:
                    with excutils.save_and_reraise_exception():
                        LOG.error(_LE("Error in creating l3 admin subnet."))
            elif len(subnet_ids) == 1:
                self._validate_l3_admin_subnet(context, subnet_ids[0])
            else:
                msg = _("Expected number of subnets in l3 admin network is " "1, found %d.") % len(subnet_ids)
                raise exc.L3AdminNetSubnetError(error_message=msg)
        else:
            msg = _("Expected number of l3 admin networks is 1, found " "%d.") % len(networks)
            raise exc.L3AdminNetError(error_message=msg)
        return network
Example #2
0
    def update_floatingip(self, context, id, floatingip):
        fip_db = self._get_floatingip(context, id)
        previous_fip = self._make_floatingip_dict(fip_db)
        previous_port_id = previous_fip.get('port_id')

        fip = super(OVNL3RouterPlugin,
                    self).update_floatingip(context, id, floatingip)
        new_port_id = fip.get('port_id')
        fip_status = None
        if previous_port_id and (
                previous_port_id != new_port_id or
            (previous_fip['fixed_ip_address'] != fip['fixed_ip_address'])):
            # 1. Floating IP dissociated
            # 2. Floating IP re-associated to a new port
            # 3. Floating IP re-associated to a new fixed_ip (same port)
            update_fip = {}
            update_fip['logical_ip'] = previous_fip['fixed_ip_address']
            update_fip['external_ip'] = fip['floating_ip_address']
            try:
                self._update_floating_ip_in_ovn(context,
                                                previous_fip['router_id'],
                                                update_fip,
                                                associate=False)
                fip_status = n_const.FLOATINGIP_STATUS_DOWN
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(
                        _LE('Unable to update floating ip in '
                            'gateway router'))

        if new_port_id:
            update_fip = {}
            update_fip['fip_port_id'] = fip_db['floating_port_id']
            update_fip['fip_net_id'] = fip['floating_network_id']
            update_fip['logical_ip'] = fip['fixed_ip_address']
            update_fip['external_ip'] = fip['floating_ip_address']
            try:
                self._update_floating_ip_in_ovn(context, fip['router_id'],
                                                update_fip)
                fip_status = n_const.FLOATINGIP_STATUS_ACTIVE
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(
                        _LE('Unable to update floating ip in '
                            'gateway router'))

        if fip_status:
            self.update_floatingip_status(context, id, fip_status)

        return fip
Example #3
0
    def _add_router_ext_gw(self, context, router):
        router_id = router['id']
        lrouter_name = utils.ovn_name(router['id'])

        # 1. Add the external gateway router port.
        ext_gw_ip = self._get_external_gateway_ip(context, router)
        gw_port_id = router['gw_port_id']
        port = self._plugin.get_port(context.elevated(), gw_port_id)
        try:
            self.create_lrouter_port_in_ovn(context.elevated(), router_id,
                                            port)
        except Exception:
            with excutils.save_and_reraise_exception():
                self._delete_router_ext_gw(context, router_id, router)
                LOG.error(
                    _LE('Unable to add external router port %(id)s to'
                        'lrouter %(name)s'), {
                            'id': port['id'],
                            'name': lrouter_name
                        })

        # 2. Add default route with nexthop as ext_gw_ip
        route = [{'destination': '0.0.0.0/0', 'nexthop': ext_gw_ip}]
        try:
            self._update_lrouter_routes(context, router_id, route, [])
        except Exception:
            with excutils.save_and_reraise_exception():
                self._delete_router_ext_gw(context, router_id, router)
                LOG.error(
                    _LE('Error updating routes %(route)s in lrouter '
                        '%(name)s'), {
                            'route': route,
                            'name': lrouter_name
                        })

        # 3. Add snat rules for tenant networks in lrouter if snat is enabled
        if utils.is_snat_enabled(router):
            try:
                networks = self._get_v4_network_of_all_router_ports(
                    context, router_id)
                if networks:
                    self._update_snat_for_networks(context,
                                                   router,
                                                   networks,
                                                   enable_snat=True)
            except Exception:
                with excutils.save_and_reraise_exception():
                    self._delete_router_ext_gw(context, router_id, router)
                    LOG.error(_LE('Error in updating SNAT for lrouter %s'),
                              lrouter_name)
Example #4
0
 def create_floatingip(self, context, floatingip,
                       initial_status=n_const.FLOATINGIP_STATUS_ACTIVE):
     fip = super(OVNL3RouterPlugin, self).create_floatingip(
         context, floatingip,
         initial_status=n_const.FLOATINGIP_STATUS_ACTIVE)
     router_id = fip.get('router_id')
     if router_id:
         update_fip = {}
         fip_db = self._get_floatingip(context, fip['id'])
         # Elevating the context here, to pass this test case
         # OVNL3ExtrarouteTests.test_floatingip_association_on_unowned_
         # router
         router = self.get_router(context.elevated(), router_id)
         update_fip['fip_port_id'] = fip_db['floating_port_id']
         update_fip['fip_net_id'] = fip['floating_network_id']
         update_fip['logical_ip'] = fip['fixed_ip_address']
         update_fip['external_ip'] = fip['floating_ip_address']
         update_fip['gw_port_id'] = router['gw_port_id']
         try:
             self._update_floating_ip_in_ovn(context, router_id, update_fip)
         except Exception:
             with excutils.save_and_reraise_exception():
                 LOG.error(_LE('Unable to create floating ip in gateway'
                           'router'))
     return fip
Example #5
0
 def _update_floating_ip_in_ovn(self, context, router_id, update,
                                associate=True):
     fip_apis = {}
     fip_apis['nat'] = self._ovn.add_nat_rule_in_lrouter if \
         associate else self._ovn.delete_nat_rule_in_lrouter
     fip_apis['garp'] = self._ovn.add_nat_ip_to_lrport_peer_options if \
         associate else self._ovn.delete_nat_ip_from_lrport_peer_options
     gw_lrouter_name = utils.ovn_gateway_router_name(router_id)
     try:
         with self._ovn.transaction(check_error=True) as txn:
             if associate:
                 # TODO(chandrav): Since the floating ip port is not
                 # bound to any chassis, packets destined to floating ip
                 # will be dropped. To overcome this, delete the floating
                 # ip port. Proper fix for this would be to redirect packets
                 # destined to floating ip to the router port. This would
                 # require changes in ovn-northd.
                 txn.add(self._ovn.delete_lswitch_port(
                     update['fip_port_id'],
                     utils.ovn_name(update['fip_net_id'])))
             txn.add(fip_apis['nat'](gw_lrouter_name, type='dnat_and_snat',
                                     logical_ip=update['logical_ip'],
                                     external_ip=update['external_ip']))
             txn.add(fip_apis['garp'](update['gw_port_id'],
                                      nat_ip=update['external_ip']))
     except Exception:
         with excutils.save_and_reraise_exception():
             LOG.error(_LE('Unable to update NAT rule in gateway router'))
Example #6
0
 def create_floatingip(self,
                       context,
                       floatingip,
                       initial_status=n_const.FLOATINGIP_STATUS_DOWN):
     fip = super(OVNL3RouterPlugin,
                 self).create_floatingip(context, floatingip,
                                         initial_status)
     router_id = fip.get('router_id')
     if router_id:
         update_fip = {}
         fip_db = self._get_floatingip(context, fip['id'])
         # Elevating the context here, to pass this test case
         # OVNL3ExtrarouteTests.test_floatingip_association_on_unowned_
         # router
         router = self.get_router(context.elevated(), router_id)
         update_fip['fip_port_id'] = fip_db['floating_port_id']
         update_fip['fip_net_id'] = fip['floating_network_id']
         update_fip['logical_ip'] = fip['fixed_ip_address']
         update_fip['external_ip'] = fip['floating_ip_address']
         update_fip['gw_port_id'] = router['gw_port_id']
         try:
             self._update_floating_ip_in_ovn(context, router_id, update_fip)
             self.update_floatingip_status(context, fip['id'],
                                           n_const.FLOATINGIP_STATUS_ACTIVE)
         except Exception:
             with excutils.save_and_reraise_exception():
                 LOG.error(
                     _LE('Unable to create floating ip in gateway'
                         'router'))
     return fip
Example #7
0
 def create_floatingip(self,
                       context,
                       floatingip,
                       initial_status=n_const.FLOATINGIP_STATUS_DOWN):
     fip = super(OVNL3RouterPlugin,
                 self).create_floatingip(context, floatingip,
                                         initial_status)
     router_id = fip.get('router_id')
     if router_id:
         update_fip = {}
         fip_db = self._get_floatingip(context, fip['id'])
         update_fip['fip_port_id'] = fip_db['floating_port_id']
         update_fip['fip_net_id'] = fip['floating_network_id']
         update_fip['logical_ip'] = fip['fixed_ip_address']
         update_fip['external_ip'] = fip['floating_ip_address']
         try:
             self._update_floating_ip_in_ovn(context, router_id, update_fip)
             self.update_floatingip_status(context, fip['id'],
                                           n_const.FLOATINGIP_STATUS_ACTIVE)
         except Exception:
             with excutils.save_and_reraise_exception():
                 LOG.error(
                     _LE('Unable to create floating ip in gateway'
                         'router'))
     return fip
Example #8
0
    def create_router(self, context, router):
        gw_info, router = self._create_router(context, router)
        try:
            self.create_lrouter_in_ovn(router)
        except Exception:
            LOG.exception(_LE('Unable to create lrouter for %s'), router['id'])
            super(OVNL3RouterPlugin, self).delete_router(context, router['id'])
            raise n_exc.ServiceUnavailable()
        try:
            if gw_info:
                self._update_router_gw_info(context, router['id'], gw_info)
        except Exception:
            LOG.exception(_LE('Fail to set gateway for router %s'),
                          router['id'])

        return router
Example #9
0
    def update_floatingip(self, context, id, floatingip):
        fip_db = self._get_floatingip(context, id)
        previous_fip = self._make_floatingip_dict(fip_db)
        previous_router_id = previous_fip.get('router_id')

        fip = super(OVNL3RouterPlugin,
                    self).update_floatingip(context, id, floatingip)
        new_router_id = fip['router_id']
        if previous_router_id:
            update_fip = {}
            router = self.get_router(context.elevated(), previous_router_id)
            update_fip['logical_ip'] = previous_fip['fixed_ip_address']
            update_fip['external_ip'] = fip['floating_ip_address']
            update_fip['gw_port_id'] = router['gw_port_id']
            try:
                self._update_floating_ip_in_ovn(context,
                                                previous_router_id,
                                                update_fip,
                                                associate=False)
                self.update_floatingip_status(context, id,
                                              n_const.FLOATINGIP_STATUS_DOWN)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(
                        _LE('Unable to update floating ip in '
                            'gateway router'))

        if new_router_id:
            router = self.get_router(context.elevated(), new_router_id)
            update_fip = {}
            update_fip['fip_port_id'] = fip_db['floating_port_id']
            update_fip['fip_net_id'] = fip['floating_network_id']
            update_fip['logical_ip'] = fip['fixed_ip_address']
            update_fip['external_ip'] = fip['floating_ip_address']
            update_fip['gw_port_id'] = router['gw_port_id']
            try:
                self._update_floating_ip_in_ovn(context, new_router_id,
                                                update_fip)
                self.update_floatingip_status(context, id,
                                              n_const.FLOATINGIP_STATUS_ACTIVE)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(
                        _LE('Unable to update floating ip in '
                            'gateway router'))

        return fip
Example #10
0
    def add_router_interface(self, context, router_id, interface_info):
        router_interface_info = \
            super(OVNL3RouterPlugin, self).add_router_interface(
                context, router_id, interface_info)
        port = self._plugin.get_port(context, router_interface_info['port_id'])

        multi_prefix = False
        if (len(router_interface_info['subnet_ids']) == 1 and
                len(port['fixed_ips']) > 1):
            # NOTE(lizk) It's adding a subnet onto an already existing router
            # interface port, try to update lrouter port 'networks' column.
            self.update_lrouter_port_in_ovn(context, router_id, port)
            multi_prefix = True
        else:
            self.create_lrouter_port_in_ovn(context, router_id, port)

        router = self.get_router(context, router_id)
        if not router.get(l3.EXTERNAL_GW_INFO):
            return router_interface_info

        cidr = None
        for fixed_ip in port['fixed_ips']:
            subnet = self._plugin.get_subnet(context, fixed_ip['subnet_id'])
            if multi_prefix:
                if 'subnet_id' in interface_info:
                    if subnet['id'] is not interface_info['subnet_id']:
                        continue
            if subnet['ip_version'] == 4:
                cidr = subnet['cidr']

        if not cidr:
            return router_interface_info

        try:
            transit_net_ports = self._get_transit_network_ports()
            nexthop = transit_net_ports['dtsp']['ip']
            gw_lrouter_name = utils.ovn_gateway_router_name(router_id)
            if self._is_snat_enabled(router):
                self._update_snat_and_static_routes_for_networks(
                    context, router, networks=[cidr], nexthop=nexthop,
                    enable_snat=True, update_static_routes=True)
            else:
                route = {'destination': cidr, 'nexthop': nexthop}
                self._update_lrouter_routes(
                    context, router_id, add=[route], remove=[],
                    lrouter_name=gw_lrouter_name)
        except Exception:
            with excutils.save_and_reraise_exception():
                self._ovn.delete_lrouter_port(
                    utils.ovn_lrouter_port_name(port['id']),
                    utils.ovn_name(router_id)).execute(check_error=True)
                super(OVNL3RouterPlugin, self).remove_router_interface(
                    context, router_id, router_interface_info)
                LOG.error(_LE('Error updating snat for subnet %(subnet)s in '
                          'router %(router)s'),
                          {'subnet': router_interface_info['subnet_id'],
                           'router': router_id})

        return router_interface_info
def main():
    """Main method for syncing neutron networks and ports with ovn nb db.

    The utility syncs neutron db with ovn nb db.
    """
    conf = setup_conf()

    # if no config file is passed or no configuration options are passed
    # then load configuration from /etc/neutron/neutron.conf
    try:
        conf(project='neutron')
    except TypeError:
        LOG.error(_LE('Error parsing the configuration values. '
                      'Please verify.'))
        return

    logging.setup(conf, 'neutron_ovn_db_sync_util')
    LOG.info(_LI('Started Neutron OVN db sync'))
    mode = ovn_config.get_ovn_neutron_sync_mode()
    if mode not in [ovn_nb_sync.SYNC_MODE_LOG, ovn_nb_sync.SYNC_MODE_REPAIR]:
        LOG.error(_LE('Invalid sync mode : ["%s"]. Should be "log" or '
                      '"repair"'), mode)
        return

    # we dont want the service plugins to be loaded.
    conf.service_plugins = []
    ovn_plugin = manager.NeutronManager.get_plugin()
    try:
        ovn_plugin._ovn = impl_idl_ovn.OvsdbOvnIdl(ovn_plugin)
    except RuntimeError:
        LOG.error(_LE('Invalid --ovn-ovsdb_connection parameter provided.'))
        return

    synchronizer = ovn_nb_sync.OvnNbSynchronizer(
        ovn_plugin, ovn_plugin._ovn, mode)

    ctx = context.get_admin_context()

    LOG.info(_LI('Syncing the networks and ports with mode : %s'), mode)
    try:
        synchronizer.sync_networks_and_ports(ctx)
    except Exception:
        LOG.exception(_LE("Error syncing  the networks and ports. Check the "
                          "--database-connection value again"))
        return
    LOG.info(_LI('Sync completed'))
Example #12
0
    def create_router(self, context, router):
        router = super(OVNL3RouterPlugin, self).create_router(context, router)
        try:
            self.create_lrouter_in_ovn(router)
        except Exception:
            LOG.exception(_LE('Unable to create lrouter for %s'), router['id'])
            super(OVNL3RouterPlugin, self).delete_router(context, router['id'])
            raise n_exc.ServiceUnavailable()

        return router
Example #13
0
 def delete_network(self, context, network_id):
     with context.session.begin(subtransactions=True):
         super(OVNPlugin, self).delete_network(context,
                                               network_id)
     try:
         self._ovn.delete_lswitch(
             utils.ovn_name(network_id), if_exists=True).execute(
                 check_error=True)
     except Exception:
         LOG.exception(_LE('Unable to delete lswitch for %s'), network_id)
Example #14
0
    def update_floatingip(self, context, id, floatingip):
        fip_db = self._get_floatingip(context, id)
        previous_fip = self._make_floatingip_dict(fip_db)
        previous_router_id = previous_fip.get('router_id')

        fip = super(OVNL3RouterPlugin, self).update_floatingip(context, id,
                                                               floatingip)
        new_router_id = fip['router_id']
        if previous_router_id:
            update_fip = {}
            router = self.get_router(context.elevated(), previous_router_id)
            update_fip['logical_ip'] = previous_fip['fixed_ip_address']
            update_fip['external_ip'] = fip['floating_ip_address']
            update_fip['gw_port_id'] = router['gw_port_id']
            try:
                self._update_floating_ip_in_ovn(context, previous_router_id,
                                                update_fip, associate=False)
                self.update_floatingip_status(context, id,
                                              n_const.FLOATINGIP_STATUS_DOWN)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(_LE('Unable to update floating ip in '
                                  'gateway router'))

        if new_router_id:
            router = self.get_router(context.elevated(), new_router_id)
            update_fip = {}
            update_fip['fip_port_id'] = fip_db['floating_port_id']
            update_fip['fip_net_id'] = fip['floating_network_id']
            update_fip['logical_ip'] = fip['fixed_ip_address']
            update_fip['external_ip'] = fip['floating_ip_address']
            update_fip['gw_port_id'] = router['gw_port_id']
            try:
                self._update_floating_ip_in_ovn(context, new_router_id,
                                                update_fip)
                self.update_floatingip_status(context, id,
                                              n_const.FLOATINGIP_STATUS_ACTIVE)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(_LE('Unable to update floating ip in '
                                  'gateway router'))

        return fip
Example #15
0
    def add_router_interface(self, context, router_id, interface_info):
        router_interface_info = \
            super(OVNL3RouterPlugin, self).add_router_interface(
                context, router_id, interface_info)
        port = self._plugin.get_port(context, router_interface_info['port_id'])

        multi_prefix = False
        if (len(router_interface_info['subnet_ids']) == 1
                and len(port['fixed_ips']) > 1):
            # NOTE(lizk) It's adding a subnet onto an already existing router
            # interface port, try to update lrouter port 'networks' column.
            self.update_lrouter_port_in_ovn(context, router_id, port)
            multi_prefix = True
        else:
            self.create_lrouter_port_in_ovn(context, router_id, port)

        router = self.get_router(context, router_id)
        if not router.get(l3.EXTERNAL_GW_INFO):
            return router_interface_info

        cidr = None
        for fixed_ip in port['fixed_ips']:
            subnet = self._plugin.get_subnet(context, fixed_ip['subnet_id'])
            if multi_prefix:
                if 'subnet_id' in interface_info:
                    if subnet['id'] is not interface_info['subnet_id']:
                        continue
            if subnet['ip_version'] == 4:
                cidr = subnet['cidr']

        if not cidr:
            return router_interface_info

        try:
            if utils.is_snat_enabled(router):
                self._update_snat_for_networks(context,
                                               router,
                                               networks=[cidr],
                                               enable_snat=True)
        except Exception:
            with excutils.save_and_reraise_exception():
                self._ovn.delete_lrouter_port(
                    utils.ovn_lrouter_port_name(port['id']),
                    utils.ovn_name(router_id)).execute(check_error=True)
                super(OVNL3RouterPlugin,
                      self).remove_router_interface(context, router_id,
                                                    router_interface_info)
                LOG.error(
                    _LE('Error updating snat for subnet %(subnet)s in '
                        'router %(router)s'), {
                            'subnet': router_interface_info['subnet_id'],
                            'router': router_id
                        })

        return router_interface_info
Example #16
0
    def remove_router_interface(self, context, router_id, interface_info):
        router_interface_info = \
            super(OVNL3RouterPlugin, self).remove_router_interface(
                context, router_id, interface_info)
        router = self.get_router(context, router_id)
        port_id = router_interface_info['port_id']
        multi_prefix = False
        try:
            port = self._plugin.get_port(context, port_id)
            # The router interface port still exists, call ovn to update it.
            self.update_lrouter_port_in_ovn(context, router_id, port)
            multi_prefix = True
        except n_exc.PortNotFound:
            # The router interface port doesn't exist any more, call ovn to
            # delete it.
            self._ovn.delete_lrouter_port(
                utils.ovn_lrouter_port_name(port_id),
                utils.ovn_name(router_id),
                if_exists=False).execute(check_error=True)

        if not router.get(l3.EXTERNAL_GW_INFO):
            return router_interface_info

        try:
            cidr = None
            if multi_prefix:
                subnet = self._plugin.get_subnet(context,
                                                 interface_info['subnet_id'])
                if subnet['ip_version'] == 4:
                    cidr = subnet['cidr']
            else:
                subnet_ids = router_interface_info.get('subnet_ids')
                for subnet_id in subnet_ids:
                    subnet = self._plugin.get_subnet(context, subnet_id)
                    if subnet['ip_version'] == 4:
                        cidr = subnet['cidr']
                        break

            if not cidr:
                return router_interface_info

            if utils.is_snat_enabled(router):
                self._update_snat_for_networks(context,
                                               router,
                                               networks=[cidr],
                                               enable_snat=False)
        except Exception:
            with excutils.save_and_reraise_exception():
                super(OVNL3RouterPlugin,
                      self).add_router_interface(context, router_id,
                                                 interface_info)
                LOG.error(_LE('Error is deleting snat'))

        return router_interface_info
Example #17
0
    def update_router(self, context, id, router):
        original_router = self.get_router(context, id)
        result = super(OVNL3RouterPlugin,
                       self).update_router(context, id, router)

        update = {}
        added = []
        removed = []
        router_name = utils.ovn_name(id)
        if 'admin_state_up' in router['router']:
            enabled = router['router']['admin_state_up']
            if enabled != original_router['admin_state_up']:
                update['enabled'] = enabled

        if 'name' in router['router']:
            if router['router']['name'] != original_router['name']:
                external_ids = {
                    ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY:
                    router['router']['name']
                }
                update['external_ids'] = external_ids
        """ Update static routes """
        if 'routes' in router['router']:
            routes = router['router']['routes']
            added, removed = n_utils.diff_list_of_dict(
                original_router['routes'], routes)

        if update or added or removed:
            try:
                with self._ovn.transaction(check_error=True) as txn:
                    if update:
                        txn.add(self._ovn.update_lrouter(
                            router_name, **update))

                    for route in added:
                        txn.add(
                            self._ovn.add_static_route(
                                router_name,
                                ip_prefix=route['destination'],
                                nexthop=route['nexthop']))

                    for route in removed:
                        txn.add(
                            self._ovn.delete_static_route(
                                router_name,
                                ip_prefix=route['destination'],
                                nexthop=route['nexthop']))
            except Exception:
                LOG.exception(_LE('Unable to update lrouter for %s'), id)
                super(OVNL3RouterPlugin,
                      self).update_router(context, id, original_router)
                raise n_exc.ServiceUnavailable()

        return result
Example #18
0
    def create_router(self, context, router):
        router = super(OVNL3RouterPlugin, self).create_router(
            context, router)
        try:
            self.create_lrouter_in_ovn(router)
        except Exception:
            LOG.exception(_LE('Unable to create lrouter for %s'),
                          router['id'])
            super(OVNL3RouterPlugin, self).delete_router(context, router['id'])
            raise n_exc.ServiceUnavailable()

        return router
Example #19
0
    def update_router(self, context, id, router):
        original_router = self.get_router(context, id)
        result = super(OVNL3RouterPlugin, self).update_router(
            context, id, router)

        update = {}
        added = []
        removed = []
        router_name = utils.ovn_name(id)
        if 'admin_state_up' in router['router']:
            enabled = router['router']['admin_state_up']
            if enabled != original_router['admin_state_up']:
                update['enabled'] = enabled

        if 'name' in router['router']:
            if router['router']['name'] != original_router['name']:
                external_ids = {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY:
                                router['router']['name']}
                update['external_ids'] = external_ids

        """ Update static routes """
        if 'routes' in router['router']:
            routes = router['router']['routes']
            added, removed = n_utils.diff_list_of_dict(
                original_router['routes'], routes)

        if update or added or removed:
            try:
                with self._ovn.transaction(check_error=True) as txn:
                    if update:
                        txn.add(self._ovn.update_lrouter(router_name,
                                **update))

                    for route in added:
                        txn.add(self._ovn.add_static_route(router_name,
                                ip_prefix=route['destination'],
                                nexthop=route['nexthop']))

                    for route in removed:
                        txn.add(self._ovn.delete_static_route(router_name,
                                ip_prefix=route['destination'],
                                nexthop=route['nexthop']))
            except Exception:
                LOG.exception(_LE('Unable to update lrouter for %s'), id)
                super(OVNL3RouterPlugin, self).update_router(context,
                                                             id,
                                                             original_router)
                raise n_exc.ServiceUnavailable()

        return result
Example #20
0
 def create_router(self, context, router):
     router = super(OVNL3RouterPlugin, self).create_router(context, router)
     try:
         # Create distributed logical router
         self.create_lrouter_in_ovn(router)
         if router.get(l3.EXTERNAL_GW_INFO):
             self._add_router_ext_gw(context, router)
     except Exception:
         with excutils.save_and_reraise_exception():
             # Delete the logical router
             LOG.error(_LE('Unable to create lrouter for %s'), router['id'])
             super(OVNL3RouterPlugin, self).delete_router(context,
                                                          router['id'])
     return router
Example #21
0
 def create_router(self, context, router):
     router = super(OVNL3RouterPlugin, self).create_router(context, router)
     try:
         # Create distributed logical router
         self.create_lrouter_in_ovn(router)
         if router.get(l3.EXTERNAL_GW_INFO):
             self._add_router_ext_gw(context, router)
     except Exception:
         with excutils.save_and_reraise_exception():
             # Delete the logical router
             LOG.error(_LE('Unable to create lrouter for %s'), router['id'])
             super(OVNL3RouterPlugin,
                   self).delete_router(context, router['id'])
     return router
Example #22
0
    def delete_floatingip(self, context, id):
        original_fip = self.get_floatingip(context, id)
        router_id = original_fip.get('router_id')
        super(OVNL3RouterPlugin, self).delete_floatingip(context, id)

        if router_id and original_fip.get('fixed_ip_address'):
            update_fip = {}
            update_fip['logical_ip'] = original_fip['fixed_ip_address']
            update_fip['external_ip'] = original_fip['floating_ip_address']
            try:
                self._update_floating_ip_in_ovn(context, router_id, update_fip,
                                                associate=False)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(_LE('Error in disassociating floatingip: %s'),
                              id)
Example #23
0
 def notify_loop(self):
     while True:
         try:
             match, event, row, updates = self.notifications.get()
             if (not isinstance(match, row_event.RowEvent) and
                     (match, event, row, updates) == OvnIdl.STOP_EVENT):
                 self.notifications.task_done()
                 break
             match.run(event, row, updates)
             if match.ONETIME:
                 self.unwatch_event(match)
             self.notifications.task_done()
         except Exception:
             # If any unexpected exception happens we don't want the
             # notify_loop to exit.
             LOG.exception(_LE('Unexpected exception in notify_loop'))
Example #24
0
 def notify_loop(self):
     while True:
         try:
             match, event, row, updates = self.notifications.get()
             if (not isinstance(match, row_event.RowEvent) and
                     (match, event, row, updates) == (
                         OvnDbNotifyHandler.STOP_EVENT)):
                 self.notifications.task_done()
                 break
             match.run(event, row, updates)
             if match.ONETIME:
                 self.unwatch_event(match)
             self.notifications.task_done()
         except Exception:
             # If any unexpected exception happens we don't want the
             # notify_loop to exit.
             LOG.exception(_LE('Unexpected exception in notify_loop'))
Example #25
0
    def _update_floating_ip_in_ovn(self,
                                   context,
                                   router_id,
                                   update,
                                   associate=True):
        fip_apis = {}
        fip_apis['nat'] = self._ovn.add_nat_rule_in_lrouter if \
            associate else self._ovn.delete_nat_rule_in_lrouter
        gw_lrouter_name = utils.ovn_name(router_id)
        try:
            with self._ovn.transaction(check_error=True) as txn:
                nat_rule_args = (gw_lrouter_name, )
                if associate:
                    # TODO(chandrav): Since the floating ip port is not
                    # bound to any chassis, packets destined to floating ip
                    # will be dropped. To overcome this, delete the floating
                    # ip port. Proper fix for this would be to redirect packets
                    # destined to floating ip to the router port. This would
                    # require changes in ovn-northd.
                    txn.add(
                        self._ovn.delete_lswitch_port(
                            update['fip_port_id'],
                            utils.ovn_name(update['fip_net_id'])))

                    # Get the list of nat rules and check if the external_ip
                    # with type 'dnat_and_snat' already exists or not.
                    # If exists, set the new value.
                    # This happens when the port associated to a floating ip
                    # is deleted before the disassociation.
                    lrouter_nat_rules = self._ovn.get_lrouter_nat_rules(
                        gw_lrouter_name)
                    for nat_rule in lrouter_nat_rules:
                        if nat_rule['external_ip'] == update['external_ip'] \
                                and nat_rule['type'] == 'dnat_and_snat':
                            fip_apis['nat'] = self._ovn.set_nat_rule_in_lrouter
                            nat_rule_args = (gw_lrouter_name, nat_rule['uuid'])
                            break

                txn.add(fip_apis['nat'](*nat_rule_args,
                                        type='dnat_and_snat',
                                        logical_ip=update['logical_ip'],
                                        external_ip=update['external_ip']))
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE('Unable to update NAT rule in gateway router'))
Example #26
0
    def create_network(self, context, network):
        net = network['network']  # obviously..
        ext_ids = {}
        physnet = self._get_attribute(net, pnet.PHYSICAL_NETWORK)
        if physnet:
            # If this is a provider network, validate that it's a type we
            # support. (flat or vlan)
            nettype = self._get_attribute(net, pnet.NETWORK_TYPE)
            if nettype not in ('flat', 'vlan'):
                msg = _('%s network type is not supported with provider '
                        'networks (only flat or vlan).') % nettype
                raise n_exc.InvalidInput(error_message=msg)

            # NOTE(russellb) This is the provider network case.  We stash the
            # provider networks fields on OVN Logical Switch.  This logical
            # switch isn't actually used for anything else because a special
            # switch is created for every port attached to the provider
            # network.  The reason we stash them is because these fields are
            # not actually stored in the Neutron database anywhere. :-(
            # They are stored in an ML2 specific db table by the ML2 plugin,
            # but there's no common code and table for other plugins.  Stashing
            # them here is the easy solution for now, but a common Neutron db
            # table and YAM (yet another mixin) would be better eventually.
            segid = self._get_attribute(net, pnet.SEGMENTATION_ID)
            ext_ids.update({
                ovn_const.OVN_PHYSNET_EXT_ID_KEY: physnet,
                ovn_const.OVN_NETTYPE_EXT_ID_KEY: nettype,
            })
            if segid:
                ext_ids.update({
                    ovn_const.OVN_SEGID_EXT_ID_KEY: str(segid),
                })

        with context.session.begin(subtransactions=True):
            result = super(OVNPlugin, self).create_network(context,
                                                           network)
            self._process_l3_create(context, result, net)

        try:
            return self.create_network_in_ovn(result, ext_ids)
        except Exception:
            LOG.exception(_LE('Unable to create lswitch for %s'),
                          result['id'])
            self.delete_network(context, result['id'])
            raise n_exc.ServiceUnavailable()
Example #27
0
    def delete_floatingip(self, context, id):
        original_fip = self.get_floatingip(context, id)
        router_id = original_fip.get('router_id')
        super(OVNL3RouterPlugin, self).delete_floatingip(context, id)

        if router_id and original_fip.get('fixed_ip_address'):
            update_fip = {}
            router = self.get_router(context.elevated(), router_id)
            update_fip['logical_ip'] = original_fip['fixed_ip_address']
            update_fip['external_ip'] = original_fip['floating_ip_address']
            update_fip['gw_port_id'] = router['gw_port_id']
            try:
                self._update_floating_ip_in_ovn(context, router_id, update_fip,
                                                associate=False)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(_LE('Error in disassociating floatingip: %s'),
                              id)
    def get_l3_admin_net_ports(self, names, device_id, device_owner, create=False):
        ctx = self._get_admin_context()
        filters = self._get_l3_admin_net_ports_query_filter(device_id, device_owner)
        ports = self._plugin.get_ports(ctx, filters=filters)
        if len(ports) == 0 and create:
            try:
                network = self._get_l3_admin_net(create=True)
                net_id = network["id"]
                ports = self._create_l3_admin_net_ports(ctx, net_id, names, device_id, device_owner)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(_LE("Error in creating l3 admin net ports %r."), names)
        elif len(ports) == len(names):
            self._validate_l3_admin_net_ports(ports, names)
        else:
            msg = _("Expected number of l3 admin net ports %(e)d, " "found %(f)d.") % {"e": len(names), "f": len(ports)}
            raise exc.L3AdminNetPortsError(error_message=msg)

        return ports
Example #29
0
    def _create_router_gw_port(self, context, router, network_id, ext_ips):
        # Port has no 'tenant-id', as it is hidden from user
        LOG.debug("Class OVNL3RouterPlugin:::")
        gw_port = self._core_plugin.create_port(
            context.elevated(), {
                'port': {
                    'tenant_id': router['tenant_id'],
                    'network_id': network_id,
                    'mac_address': attributes.ATTR_NOT_SPECIFIED,
                    'fixed_ips': attributes.ATTR_NOT_SPECIFIED,
                    'device_id': router['id'],
                    'device_owner': l3_db.DEVICE_OWNER_ROUTER_GW,
                    'admin_state_up': True,
                    'name': 'Extnet_' + router['name'][0:18]
                }
            })

        if not gw_port['fixed_ips']:
            self._core_plugin.delete_port(context.elevated(),
                                          gw_port['id'],
                                          l3_port_check=False)
            msg = (_('No IPs available for external network %s') % network_id)
            raise n_exc.BadRequest(resource='router', msg=msg)
        try:
            self.create_gw_router_port_in_ovn(context, router['id'], gw_port)
        except Exception:
            self._core_plugin.delete_port(context.elevated(),
                                          gw_port['id'],
                                          l3_port_check=False)
            self.delete_gw_router_port_in_ovn(router['id'], gw_port['id'])
            LOG.exception(_LE('Fail to update gateway info for router %s'),
                          router['id'])
            raise n_exc.ServiceUnavailable()
        with context.session.begin(subtransactions=True):
            router.gw_port = self._core_plugin._get_port(
                context.elevated(), gw_port['id'])
            router_port = l3_db.RouterPort(
                router_id=router.id,
                port_id=gw_port['id'],
                port_type=l3_db.DEVICE_OWNER_ROUTER_GW)
            context.session.add(router)
            context.session.add(router_port)
    def _validate_l3_admin_subnet(self, context, subnet_id):
        subnet = None
        try:
            subnet = self._plugin.get_subnet(context, subnet_id)
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("L3 admin subnet not found"))
        if subnet.get("cidr") != self._cidr:
            msg = _("Subnet CIDR %(a)s does not match configured value " "%(e)s.") % {
                "a": subnet.get("cidr"),
                "e": self._cidr,
            }
            raise exc.L3AdminNetSubnetError(error_message=msg)

        if subnet.get("name") != ovn_const.OVN_L3_ADMIN_NET_SUBNET_NAME:
            msg = _("Subnet name %(a)s does not match expected name " "%(e)s.") % {
                "a": subnet.get("name"),
                "e": ovn_const.OVN_L3_ADMIN_NET_SUBNET_NAME,
            }
            raise exc.L3AdminNetSubnetError(error_message=msg)
Example #31
0
    def _add_router_ext_gw(self, context, router):
        # TODO(chandrav): Add sync support, bug #1629076 to track this.
        transit_net_ports = self._get_transit_network_ports(create=True)
        router_id = router['id']
        gw_lrouter_name = utils.ovn_gateway_router_name(router['id'])
        cleanup = []

        # 1. Create gateway router
        try:
            self.create_lrouter_in_ovn(router, is_gateway_router=True)
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE('Unable to create gateway router %s'),
                          gw_lrouter_name)
        cleanup.append('gw_router')

        # 2. Add the external gateway router port to gateway router.
        ext_gw_ip = self._get_external_gateway_ip(context, router)
        gw_port_id = router['gw_port_id']
        port = self._plugin.get_port(context.elevated(), gw_port_id)
        try:
            self.create_lrouter_port_in_ovn(context.elevated(),
                                            router_id, port,
                                            is_lrouter_gateway_router=True)
        except Exception:
            with excutils.save_and_reraise_exception():
                self._delete_router_ext_gw(context, router_id, router,
                                           transit_net_ports, cleanup)
                LOG.error(_LE('Unable to add external router port %(id)s to'
                              'gateway_router %(name)s'),
                          {'id': port['id'], 'name': gw_lrouter_name})
        cleanup.append('ext_gw_port')

        # 3. Add default route in gateway router with nexthop as ext_gw_ip
        route = [{'destination': '0.0.0.0/0', 'nexthop': ext_gw_ip}]
        try:
            self._update_lrouter_routes(context, router_id, route, [],
                                        gw_lrouter_name)
        except Exception:
            with excutils.save_and_reraise_exception():
                self._delete_router_ext_gw(context, router_id, router,
                                           transit_net_ports, cleanup)
                LOG.error(_LE('Error updating routes %(route)s in lrouter '
                              '%(name)s'), {'route': route,
                                            'name': gw_lrouter_name})
        cleanup.append('ext_gw_ip_nexthop')

        # 4. Join the logical router and gateway router
        try:
            self._join_lrouter_and_gw_lrouter(router, transit_net_ports)
        except Exception:
            with excutils.save_and_reraise_exception():
                self._delete_router_ext_gw(context, router_id, router,
                                           transit_net_ports, cleanup)
                LOG.error(_LE('Error in connecting lrouter and gateway router '
                              'for router %s'), router_id)
        cleanup.append('join')

        # 5. Check if tenant router ports are already configured.
        # If snat is enabled, add snat rules and static routes for tenant
        # networks in gateway router
        # If snat is disabled, add only static routes for tenant networks in
        # gateway router (For traffic destined to floating ips)
        # Static routes are added with a nexthop of gtsp port ip in logical
        # router.
        try:
            networks = self._get_v4_network_of_all_router_ports(context,
                                                                router_id)
            if not networks:
                return
            nexthop = transit_net_ports['dtsp']['ip']
            if self._is_snat_enabled(router):
                self._update_snat_and_static_routes_for_networks(
                    context, router, networks, nexthop, enable_snat=True,
                    update_static_routes=True)
            else:
                routes = []
                for network in networks:
                    routes.append({'destination': network, 'nexthop': nexthop})
                self._update_lrouter_routes(
                    context, router_id, routes, remove=[],
                    lrouter_name=gw_lrouter_name)
        except Exception:
            with excutils.save_and_reraise_exception():
                self._delete_router_ext_gw(context, router_id, router,
                                           transit_net_ports, cleanup)
                LOG.error(_LE('Error in updating SNAT for router %s'),
                          router_id)
Example #32
0
    def update_router(self, context, id, router):
        original_router = self.get_router(context, id)
        result = super(OVNL3RouterPlugin,
                       self).update_router(context, id, router)
        gateway_new = result.get(l3.EXTERNAL_GW_INFO)
        gateway_old = original_router.get(l3.EXTERNAL_GW_INFO)
        revert_router = {'router': original_router}
        try:
            if gateway_new and not gateway_old:
                # Route gateway is set
                self._add_router_ext_gw(context, result)
            elif gateway_old and not gateway_new:
                # router gateway is removed
                self._delete_router_ext_gw(context, id, original_router)
            elif gateway_new and gateway_old:
                # Check if external gateway has changed, if yes, delete the old
                # gateway and add the new gateway
                if (gateway_old['network_id'] != gateway_new['network_id']
                        or set([
                            str(fixed_ip)
                            for fixed_ip in gateway_old['external_fixed_ips']
                        ]) != set([
                            str(fixed_ip)
                            for fixed_ip in gateway_new['external_fixed_ips']
                        ])):
                    self._delete_router_ext_gw(context, id, original_router)
                    self._add_router_ext_gw(context, result)
                else:
                    # Check if snat has been enabled/disabled and update
                    old_snat_state = gateway_old.get('enable_snat', True)
                    new_snat_state = gateway_new.get('enable_snat', True)
                    if old_snat_state != new_snat_state:
                        networks = self._get_v4_network_of_all_router_ports(
                            context, id)
                        self._update_snat_for_networks(
                            context,
                            result,
                            networks,
                            enable_snat=new_snat_state)
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE('Unable to update lrouter for %s'), id)
                super(OVNL3RouterPlugin,
                      self).update_router(context, id, revert_router)

        # Check for change in admin_state_up
        update = {}
        router_name = utils.ovn_name(id)
        if 'admin_state_up' in router['router']:
            enabled = router['router']['admin_state_up']
            if enabled != original_router['admin_state_up']:
                update['enabled'] = enabled

        # Check for change in name
        if 'name' in router['router']:
            if router['router']['name'] != original_router['name']:
                external_ids = {
                    ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY:
                    router['router']['name']
                }
                update['external_ids'] = external_ids

        if update:
            try:
                self._ovn.update_lrouter(router_name,
                                         **update).execute(check_error=True)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(_LE('Unable to update lrouter for %s'), id)
                    super(OVNL3RouterPlugin,
                          self).update_router(context, id, revert_router)

        # Check for route updates
        added = []
        removed = []
        if 'routes' in router['router']:
            routes = router['router']['routes']
            added, removed = helpers.diff_list_of_dict(
                original_router['routes'], routes)

        if added or removed:
            try:
                self._update_lrouter_routes(context, id, added, removed)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(
                        _LE('Unable to update static routes in lrouter '
                            '%s'), id)
                    super(OVNL3RouterPlugin,
                          self).update_router(context, id, revert_router)

        return result
Example #33
0
    def update_router(self, context, id, router):
        original_router = self.get_router(context, id)
        result = super(OVNL3RouterPlugin, self).update_router(context, id,
                                                              router)
        gateway_new = result.get(l3.EXTERNAL_GW_INFO)
        gateway_old = original_router.get(l3.EXTERNAL_GW_INFO)

        try:
            if gateway_new and not gateway_old:
                # Route gateway is set
                self._add_router_ext_gw(context, result)
            elif gateway_old and not gateway_new:
                # router gateway is removed
                self._delete_router_ext_gw(context, id, original_router)
            elif gateway_new and gateway_old:
                # Check if external gateway has changed, if yes, delete the old
                # gateway and add the new gateway
                if gateway_old['network_id'] != gateway_new['network_id']:
                    self._delete_router_ext_gw(context, id, original_router)
                    self._add_router_ext_gw(context, result)

                # Check if snat has been enabled/disabled and update
                old_snat_state = gateway_old.get('enable_snat', 'True')
                new_snat_state = gateway_new.get('enable_snat', 'True')
                if old_snat_state != new_snat_state:
                    networks = self._get_v4_network_of_all_router_ports(
                        context, id)
                    self._update_snat_and_static_routes_for_networks(
                        context, result, networks, nexthop=None,
                        enable_snat=new_snat_state, update_static_routes=False)
        except Exception:
            with excutils.save_and_reraise_exception():
                revert_router = {}
                LOG.error(_LE('Unable to update lrouter for %s'), id)
                revert_router['router'] = original_router
                super(OVNL3RouterPlugin, self).update_router(context, id,
                                                             revert_router)

        # Check for change in admin_state_up
        update = {}
        router_name = utils.ovn_name(id)
        if 'admin_state_up' in router['router']:
            enabled = router['router']['admin_state_up']
            if enabled != original_router['admin_state_up']:
                update['enabled'] = enabled

        # Check for change in name
        if 'name' in router['router']:
            if router['router']['name'] != original_router['name']:
                external_ids = {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY:
                                router['router']['name']}
                update['external_ids'] = external_ids

        if update:
            try:
                self._ovn.update_lrouter(router_name, **update).execute(
                    check_error=True)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(_LE('Unable to update lrouter for %s'), id)
                    router['router'] = original_router
                    super(OVNL3RouterPlugin, self).update_router(context, id,
                                                                 router)

        # Check for route updates
        added = []
        removed = []
        if 'routes' in router['router']:
            routes = router['router']['routes']
            added, removed = helpers.diff_list_of_dict(
                original_router['routes'], routes)

        if added or removed:
            try:
                self._update_lrouter_routes(context, id, added, removed)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(_LE('Unable to update static routes in lrouter '
                                  '%s'), id)
                    router['router'] = original_router
                    super(OVNL3RouterPlugin, self).update_router(context, id,
                                                                 router)

        return result
Example #34
0
    def remove_router_interface(self, context, router_id, interface_info):
        router_interface_info = \
            super(OVNL3RouterPlugin, self).remove_router_interface(
                context, router_id, interface_info)
        router = self.get_router(context, router_id)
        port_id = router_interface_info['port_id']
        multi_prefix = False
        try:
            port = self._plugin.get_port(context, port_id)
            # The router interface port still exists, call ovn to update it.
            self.update_lrouter_port_in_ovn(context, router_id, port)
            multi_prefix = True
        except n_exc.PortNotFound:
            # The router interface port doesn't exist any more, call ovn to
            # delete it.
            self._ovn.delete_lrouter_port(utils.ovn_lrouter_port_name(port_id),
                                          utils.ovn_name(router_id),
                                          if_exists=False
                                          ).execute(check_error=True)

        if not router.get(l3.EXTERNAL_GW_INFO):
            return router_interface_info

        try:
            cidr = None
            if multi_prefix:
                subnet = self._plugin.get_subnet(context,
                                                 interface_info['subnet_id'])
                if subnet['ip_version'] == 4:
                    cidr = subnet['cidr']
            else:
                subnet_ids = router_interface_info.get('subnet_ids')
                for subnet_id in subnet_ids:
                    subnet = self._plugin.get_subnet(context, subnet_id)
                    if subnet['ip_version'] == 4:
                        cidr = subnet['cidr']
                        break

            if not cidr:
                return router_interface_info

            router_name = utils.ovn_gateway_router_name(router_id)
            transit_net_ports = self._get_transit_network_ports()
            nexthop = transit_net_ports['dtsp']['ip']

            if self._is_snat_enabled(router):
                self._update_snat_and_static_routes_for_networks(
                    context, router, networks=[cidr], nexthop=nexthop,
                    enable_snat=False, update_static_routes=True)
            else:
                route = {'destination': cidr, 'nexthop': nexthop}
                self._update_lrouter_routes(
                    context, router_id, add=[route], remove=[],
                    lrouter_name=router_name)
        except Exception:
            with excutils.save_and_reraise_exception():
                super(OVNL3RouterPlugin, self).add_router_interface(
                    context, router_id, interface_info)
                LOG.error(_LE('Error is deleting snat'))

        return router_interface_info
Example #35
0
def main():
    """Main method for syncing neutron networks and ports with ovn nb db.

    The utility syncs neutron db with ovn nb db.
    """
    conf = setup_conf()

    # if no config file is passed or no configuration options are passed
    # then load configuration from /etc/neutron/neutron.conf
    try:
        conf(project='neutron')
    except TypeError:
        LOG.error(
            _LE('Error parsing the configuration values. '
                'Please verify.'))
        return

    logging.setup(conf, 'neutron_ovn_db_sync_util')
    LOG.info(_LI('Started Neutron OVN db sync'))
    mode = ovn_config.get_ovn_neutron_sync_mode()
    if mode not in [ovn_db_sync.SYNC_MODE_LOG, ovn_db_sync.SYNC_MODE_REPAIR]:
        LOG.error(
            _LE('Invalid sync mode : ["%s"]. Should be "log" or '
                '"repair"'), mode)
        return

    # Validate and modify core plugin and ML2 mechanism drivers for syncing.
    if cfg.CONF.core_plugin.endswith('.Ml2Plugin'):
        cfg.CONF.core_plugin = (
            'networking_ovn.cmd.neutron_ovn_db_sync_util.Ml2Plugin')
        if 'ovn' not in cfg.CONF.ml2.mechanism_drivers:
            LOG.error(_LE('No "ovn" mechanism driver found : "%s".'),
                      cfg.CONF.ml2.mechanism_drivers)
            return
        cfg.CONF.set_override('mechanism_drivers', ['ovn-sync'], 'ml2')
        conf.service_plugins = ['networking_ovn.l3.l3_ovn.OVNL3RouterPlugin']
    else:
        LOG.error(_LE('Invalid core plugin : ["%s"].'), cfg.CONF.core_plugin)
        return

    try:
        ovn_api = impl_idl_ovn.OvsdbNbOvnIdl(None)
    except RuntimeError:
        LOG.error(_LE('Invalid --ovn-ovn_nb_connection parameter provided.'))
        return

    core_plugin = manager.NeutronManager.get_plugin()
    ovn_driver = core_plugin.mechanism_manager.mech_drivers['ovn-sync'].obj
    ovn_driver._nb_ovn = ovn_api

    synchronizer = ovn_db_sync.OvnNbSynchronizer(core_plugin, ovn_api, mode,
                                                 ovn_driver)

    ctx = context.get_admin_context()

    LOG.info(_LI('Syncing the networks and ports with mode : %s'), mode)
    try:
        synchronizer.sync_address_sets(ctx)
    except Exception:
        LOG.exception(
            _LE("Error syncing  the Address Sets. Check the "
                "--database-connection value again"))
        return
    try:
        synchronizer.sync_networks_ports_and_dhcp_opts(ctx)
    except Exception:
        LOG.exception(
            _LE("Error syncing  Networks, Ports and DHCP options "
                "for unknown reason please try again"))
        return
    try:
        synchronizer.sync_acls(ctx)
    except Exception:
        LOG.exception(
            _LE("Error syncing  ACLs for unknown "
                "reason please try again"))
        return
    try:
        synchronizer.sync_routers_and_rports(ctx)
    except Exception:
        LOG.exception(
            _LE("Error syncing  Routers and Router ports "
                "please try again"))
        return
    LOG.info(_LI('Sync completed'))
Example #36
0
    def _start_ovsdb_server_and_idls(self):
        self.temp_dir = self.useFixture(fixtures.TempDir()).path
        # Start 2 ovsdb-servers one each for OVN NB DB and OVN SB DB
        # ovsdb-server with OVN SB DB can be used to test the chassis up/down
        # events.
        self.ovsdb_server_mgr = self.useFixture(
            process.OvsdbServer(self.temp_dir, self.OVS_INSTALL_SHARE_PATH,
                                ovn_nb_db=True, ovn_sb_db=True))
        cfg.CONF.set_override(
            'ovn_nb_connection',
            self.ovsdb_server_mgr.get_ovsdb_connection_path(),
            'ovn')
        cfg.CONF.set_override(
            'ovn_sb_connection',
            self.ovsdb_server_mgr.get_ovsdb_connection_path(db_type='sb'),
            'ovn')
        num_attempts = 0
        # 5 seconds should be more than enough for the transaction to complete
        # for the test cases.
        # This also fixes the bug #1607639.
        cfg.CONF.set_override(
            'ovsdb_connection_timeout', 5,
            'ovn')

        # Created monitor IDL connection to the OVN NB DB.
        # This monitor IDL connection can be used to
        #   - Verify that the ML2 OVN driver has written to the OVN NB DB
        #     as expected.
        #   - Create and delete resources in OVN NB DB outside of the
        #     ML2 OVN driver scope to test scenarios like ovn_nb_sync.
        while num_attempts < 3:
            try:
                self.monitor_nb_idl_con = connection.Connection(
                    self.ovsdb_server_mgr.get_ovsdb_connection_path(),
                    60, 'OVN_Northbound')
                self.monitor_nb_idl_con.start()
                self.monitor_nb_db_idl = self.monitor_nb_idl_con.idl
                break
            except Exception:
                LOG.exception(_LE("Error connecting to the OVN_Northbound DB"))
                num_attempts += 1
                time.sleep(1)

        num_attempts = 0

        # Create monitor IDL connection to the OVN SB DB.
        # This monitor IDL connection can be used to
        #  - Create chassis rows
        #  - Update chassis columns etc.
        while num_attempts < 3:
            try:
                self.monitor_sb_idl_con = connection.Connection(
                    self.ovsdb_server_mgr.get_ovsdb_connection_path(
                        db_type='sb'),
                    60, 'OVN_Southbound')
                self.monitor_sb_idl_con.start()
                self.monitor_sb_db_idl = self.monitor_sb_idl_con.idl
                break
            except Exception:
                LOG.exception(_LE("Error connecting to the OVN_Southbound DB"))
                num_attempts += 1
                time.sleep(1)

        trigger = mock.MagicMock()
        if self.ovn_worker:
            trigger.im_class = ovsdb_monitor.OvnWorker
            cfg.CONF.set_override('neutron_sync_mode', 'off', 'ovn')
        trigger.im_class.__name__ = 'trigger'

        # mech_driver.post_fork_initialize creates the IDL connections
        self.mech_driver.post_fork_initialize(mock.ANY, mock.ANY, trigger)
Example #37
0
    def _start_ovsdb_server_and_idls(self):
        self.temp_dir = self.useFixture(fixtures.TempDir()).path
        # Start 2 ovsdb-servers one each for OVN NB DB and OVN SB DB
        # ovsdb-server with OVN SB DB can be used to test the chassis up/down
        # events.
        self.ovsdb_server_mgr = self.useFixture(
            process.OvsdbServer(self.temp_dir,
                                self.OVS_INSTALL_SHARE_PATH,
                                ovn_nb_db=True,
                                ovn_sb_db=True))
        cfg.CONF.set_override(
            'ovn_nb_connection',
            self.ovsdb_server_mgr.get_ovsdb_connection_path(), 'ovn')
        cfg.CONF.set_override(
            'ovn_sb_connection',
            self.ovsdb_server_mgr.get_ovsdb_connection_path(db_type='sb'),
            'ovn')
        num_attempts = 0
        # 5 seconds should be more than enough for the transaction to complete
        # for the test cases.
        # This also fixes the bug #1607639.
        cfg.CONF.set_override('ovsdb_connection_timeout', 5, 'ovn')

        # Created monitor IDL connection to the OVN NB DB.
        # This monitor IDL connection can be used to
        #   - Verify that the ML2 OVN driver has written to the OVN NB DB
        #     as expected.
        #   - Create and delete resources in OVN NB DB outside of the
        #     ML2 OVN driver scope to test scenarios like ovn_nb_sync.
        while num_attempts < 3:
            try:
                self.monitor_nb_idl_con = connection.Connection(
                    self.ovsdb_server_mgr.get_ovsdb_connection_path(), 60,
                    'OVN_Northbound')
                self.monitor_nb_idl_con.start()
                self.monitor_nb_db_idl = self.monitor_nb_idl_con.idl
                break
            except Exception:
                LOG.exception(_LE("Error connecting to the OVN_Northbound DB"))
                num_attempts += 1
                time.sleep(1)

        num_attempts = 0
        while num_attempts < 3:
            try:
                self.monitor_sb_idl_con = connection.Connection(
                    self.ovsdb_server_mgr.get_ovsdb_connection_path(
                        db_type='sb'), 60, 'OVN_Southbound')
                self.monitor_sb_idl_con.start()
                self.monitor_sb_db_idl = self.monitor_sb_idl_con.idl
                break
            except Exception:
                LOG.exception(_LE("Error connecting to the OVN_Southbound DB"))
                num_attempts += 1
                time.sleep(1)

        trigger = mock.MagicMock()
        if self.ovn_worker:
            trigger.im_class = ovsdb_monitor.OvnWorker
            cfg.CONF.set_override('neutron_sync_mode', 'off', 'ovn')

        # mech_driver.post_fork_initialize creates the IDL connections
        self.mech_driver.post_fork_initialize(mock.ANY, mock.ANY, trigger)
def main():
    """Main method for syncing neutron networks and ports with ovn nb db.

    The utility syncs neutron db with ovn nb db.
    """
    conf = setup_conf()

    # if no config file is passed or no configuration options are passed
    # then load configuration from /etc/neutron/neutron.conf
    try:
        conf(project='neutron')
    except TypeError:
        LOG.error(_LE('Error parsing the configuration values. '
                      'Please verify.'))
        return

    logging.setup(conf, 'neutron_ovn_db_sync_util')
    LOG.info(_LI('Started Neutron OVN db sync'))
    mode = ovn_config.get_ovn_neutron_sync_mode()
    if mode not in [ovn_db_sync.SYNC_MODE_LOG, ovn_db_sync.SYNC_MODE_REPAIR]:
        LOG.error(_LE('Invalid sync mode : ["%s"]. Should be "log" or '
                      '"repair"'), mode)
        return

    # Validate and modify core plugin and ML2 mechanism drivers for syncing.
    if cfg.CONF.core_plugin.endswith('.Ml2Plugin'):
        cfg.CONF.core_plugin = (
            'networking_ovn.cmd.neutron_ovn_db_sync_util.Ml2Plugin')
        if 'ovn' not in cfg.CONF.ml2.mechanism_drivers:
            LOG.error(_LE('No "ovn" mechanism driver found : "%s".'),
                      cfg.CONF.ml2.mechanism_drivers)
            return
        cfg.CONF.set_override('mechanism_drivers', ['ovn-sync'], 'ml2')
        conf.service_plugins = ['networking_ovn.l3.l3_ovn.OVNL3RouterPlugin']
    else:
        LOG.error(_LE('Invalid core plugin : ["%s"].'), cfg.CONF.core_plugin)
        return

    try:
        ovn_api = impl_idl_ovn.OvsdbNbOvnIdl(None)
    except RuntimeError:
        LOG.error(_LE('Invalid --ovn-ovn_nb_connection parameter provided.'))
        return

    core_plugin = manager.NeutronManager.get_plugin()
    ovn_driver = core_plugin.mechanism_manager.mech_drivers['ovn-sync'].obj
    ovn_driver._nb_ovn = ovn_api

    synchronizer = ovn_db_sync.OvnNbSynchronizer(
        core_plugin, ovn_api, mode, ovn_driver)

    ctx = context.get_admin_context()

    LOG.info(_LI('Syncing the networks and ports with mode : %s'), mode)
    try:
        synchronizer.sync_address_sets(ctx)
    except Exception:
        LOG.exception(_LE("Error syncing  the Address Sets. Check the "
                          "--database-connection value again"))
        return
    try:
        synchronizer.sync_networks_ports_and_dhcp_opts(ctx)
    except Exception:
        LOG.exception(_LE("Error syncing  Networks, Ports and DHCP options "
                          "for unknown reason please try again"))
        return
    try:
        synchronizer.sync_acls(ctx)
    except Exception:
        LOG.exception(_LE("Error syncing  ACLs for unknown "
                          "reason please try again"))
        return
    try:
        synchronizer.sync_routers_and_rports(ctx)
    except Exception:
        LOG.exception(_LE("Error syncing  Routers and Router ports "
                          "please try again"))
        return
    LOG.info(_LI('Sync completed'))
Example #39
0
def main():
    """Main method for syncing neutron networks and ports with ovn nb db.

    The utility syncs neutron db with ovn nb db.
    """
    conf = setup_conf()

    # if no config file is passed or no configuration options are passed
    # then load configuration from /etc/neutron/neutron.conf
    try:
        conf(project='neutron')
    except TypeError:
        LOG.error(
            _LE('Error parsing the configuration values. '
                'Please verify.'))
        return

    logging.setup(conf, 'neutron_ovn_db_sync_util')
    LOG.info(_LI('Started Neutron OVN db sync'))
    mode = ovn_config.get_ovn_neutron_sync_mode()
    if mode not in [ovn_nb_sync.SYNC_MODE_LOG, ovn_nb_sync.SYNC_MODE_REPAIR]:
        LOG.error(
            _LE('Invalid sync mode : ["%s"]. Should be "log" or '
                '"repair"'), mode)
        return

    # we dont want the service plugins to be loaded.
    conf.service_plugins = []
    ovn_plugin = manager.NeutronManager.get_plugin()
    try:
        ovn_plugin._ovn = impl_idl_ovn.OvsdbOvnIdl(ovn_plugin)
    except RuntimeError:
        LOG.error(_LE('Invalid --ovn-ovsdb_connection parameter provided.'))
        return

    synchronizer = ovn_nb_sync.OvnNbSynchronizer(ovn_plugin, ovn_plugin._ovn,
                                                 mode)

    ctx = context.get_admin_context()

    LOG.info(_LI('Syncing the networks and ports with mode : %s'), mode)
    try:
        synchronizer.sync_networks_and_ports(ctx)
    except Exception:
        LOG.exception(
            _LE("Error syncing  the networks and ports. Check the "
                "--database-connection value again"))
        return
    try:
        synchronizer.sync_acls(ctx)
    except Exception:
        LOG.exception(
            _LE("Error syncing  ACLs for unknown reason "
                "please try again"))
        return
    try:
        synchronizer.sync_routers_and_rports(ctx)
    except Exception:
        LOG.exception(
            _LE("Error syncing  Routers and Router ports "
                "please try again"))
        return
    LOG.info(_LI('Sync completed'))