예제 #1
0
    def _sync_ports(self, ctx):
        LOG.debug("OVN-NB Sync ports started")

        lports = self.ovn_api.get_all_logical_ports_ids()

        for port in self.core_plugin.get_ports(ctx):
            try:
                if self.mode == SYNC_MODE_REPAIR:
                    self.core_plugin.create_port_in_ovn(port)
                res = lports.pop(port['id'], None)
                if self.mode == SYNC_MODE_LOG:
                    if res is None:
                        LOG.warning(_LW("Port found in Neutron but not in OVN "
                                        "DB, port_id=%s"),
                                    port['id'])

            except RuntimeError:
                LOG.warning(_LW("Create port failed for port %s"), port['id'])

        # Only delete logical port if it was previously created by neutron
        with self.ovn_api.transaction() as txn:
            for lport, ext_ids in lports.items():
                if ovn_const.OVN_PORT_NAME_EXT_ID_KEY in ext_ids:
                    if self.mode == SYNC_MODE_REPAIR:
                        txn.add(self.ovn_api.delete_lport(lport))
                    if self.mode == SYNC_MODE_LOG:
                        LOG.warning(
                            _LW("Port found in OVN but not in "
                                "Neutron, port_name=%s"),
                            ext_ids[ovn_const.OVN_PORT_NAME_EXT_ID_KEY])

        LOG.debug("OVN-NB Sync ports finished")
예제 #2
0
    def _sync_networks(self, ctx):
        LOG.debug("OVN-NB Sync networks started")

        lswitches = self.ovn_api.get_all_logical_switches_ids()

        for network in self.core_plugin.get_networks(ctx):
            try:
                if self.mode == SYNC_MODE_REPAIR:
                    self.core_plugin.create_network_in_ovn(network)
                res = lswitches.pop(utils.ovn_name(
                                    network['id']), None)
                if self.mode == SYNC_MODE_LOG:
                    if res is None:
                        LOG.warning(_LW("Network found in Neutron but not in "
                                        "OVN DB, network_id=%s"),
                                    network['id'])

            except RuntimeError:
                LOG.warning(_LW("Create network failed for "
                                "network %s"), network['id'])

        # Only delete logical switch if it was previously created by neutron
        with self.ovn_api.transaction() as txn:
            for lswitch, ext_ids in lswitches.items():
                if ovn_const.OVN_NETWORK_NAME_EXT_ID_KEY in ext_ids:
                    if self.mode == SYNC_MODE_REPAIR:
                        txn.add(self.ovn_api.delete_lswitch(lswitch))
                    if self.mode == SYNC_MODE_LOG:
                        LOG.warning(_LW("Network found in OVN but not in "
                                        "Neutron, network_name=%s"),
                                    (ext_ids
                                     [ovn_const.OVN_NETWORK_NAME_EXT_ID_KEY]))

        LOG.debug("OVN-NB Sync networks finished")
예제 #3
0
    def _sync_port_dhcp_options(self, ctx, ports_need_sync_dhcp_opts,
                                ovn_port_dhcp_options):
        if not config.is_ovn_dhcp():
            return

        LOG.debug('OVN-NB Sync DHCP options for Neutron ports with extra '
                  'dhcp options assigned started')

        txn_commands = []
        for port in ports_need_sync_dhcp_opts:
            if self.mode == SYNC_MODE_REPAIR:
                LOG.debug('Updating DHCP options for port %s in OVN NB DB',
                          port['id'])
                dhcp_opts = self.ovn_driver.get_port_dhcpv4_options(port)
                if not dhcp_opts:
                    # If the Logical_Switch_Port.dhcpv4_options no longer
                    # refers a port dhcp options created in DHCP_Options
                    # earlier, that port dhcp options will be deleted
                    # in the following ovn_port_dhcp_options handling.
                    txn_commands.append(
                        self.ovn_api.set_lswitch_port(lport_name=port['id'],
                                                      dhcpv4_options=[]))
                elif port['id'] in ovn_port_dhcp_options:
                    # When the Logical_Switch_Port.dhcpv4_options refers a port
                    # dhcp options in DHCP_Options earlier, if the extra dhcp
                    # options has changed, ovn_driver.get_port_dhcpv4_options
                    # should udpate it, if removed, it will be deleted
                    # in the following ovn_port_dhcp_options handling.
                    if dhcp_opts['external_ids'].get('port_id') is not None:
                        ovn_port_dhcp_options.pop(port['id'])
                elif 'uuid' in dhcp_opts:
                    # If the Logical_Switch_Port.dhcpv4_options is already
                    # in sync, then this transaction will be a no-op.
                    txn_commands.append(
                        self.ovn_api.set_lswitch_port(
                            lport_name=port['id'],
                            dhcpv4_options=[dhcp_opts['uuid']]))

        for port_id, dhcp_opt in ovn_port_dhcp_options.items():
            LOG.warning(
                _LW('Out of sync port DHCP options for (subnet %(subnet_id)s'
                    ' port %(port_id)s) found in OVN NB DB which needs to be '
                    'deleted'), {
                        'subnet_id': dhcp_opt['external_ids']['subnet_id'],
                        'port_id': port_id
                    })

            if self.mode == SYNC_MODE_REPAIR:
                LOG.debug(
                    'Deleting port DHCP options for (subnet %s, port '
                    '%s)', dhcp_opt['external_ids']['subnet_id'], port_id)
                txn_commands.append(
                    self.ovn_api.delete_dhcp_options(dhcp_opt['uuid']))

        if txn_commands:
            with self.ovn_api.transaction(check_error=True) as txn:
                for cmd in txn_commands:
                    txn.add(cmd)
        LOG.debug('OVN-NB Sync DHCP options for Neutron ports with extra '
                  'dhcp options assigned finished')
예제 #4
0
    def _sync_port_dhcp_options(self, ctx, ports_need_sync_dhcp_opts,
                                ovn_port_dhcp_options):
        if not config.is_ovn_dhcp():
            return

        LOG.debug('OVN-NB Sync DHCP options for Neutron ports with extra '
                  'dhcp options assigned started')

        txn_commands = []
        for port in ports_need_sync_dhcp_opts:
            if self.mode == SYNC_MODE_REPAIR:
                LOG.debug('Updating DHCP options for port %s in OVN NB DB',
                          port['id'])
                dhcp_opts = self.ovn_driver.get_port_dhcpv4_options(port)
                if not dhcp_opts:
                    # If the Logical_Switch_Port.dhcpv4_options no longer
                    # refers a port dhcp options created in DHCP_Options
                    # earlier, that port dhcp options will be deleted
                    # in the following ovn_port_dhcp_options handling.
                    txn_commands.append(self.ovn_api.set_lswitch_port(
                        lport_name=port['id'],
                        dhcpv4_options=[]))
                elif port['id'] in ovn_port_dhcp_options:
                    # When the Logical_Switch_Port.dhcpv4_options refers a port
                    # dhcp options in DHCP_Options earlier, if the extra dhcp
                    # options has changed, ovn_driver.get_port_dhcpv4_options
                    # should udpate it, if removed, it will be deleted
                    # in the following ovn_port_dhcp_options handling.
                    if dhcp_opts['external_ids'].get('port_id') is not None:
                        ovn_port_dhcp_options.pop(port['id'])
                elif 'uuid' in dhcp_opts:
                    # If the Logical_Switch_Port.dhcpv4_options is already
                    # in sync, then this transaction will be a no-op.
                    txn_commands.append(self.ovn_api.set_lswitch_port(
                        lport_name=port['id'],
                        dhcpv4_options=[dhcp_opts['uuid']]))

        for port_id, dhcp_opt in ovn_port_dhcp_options.items():
            LOG.warning(
                _LW('Out of sync port DHCP options for (subnet %(subnet_id)s'
                    ' port %(port_id)s) found in OVN NB DB which needs to be '
                    'deleted'),
                {'subnet_id': dhcp_opt['external_ids']['subnet_id'],
                 'port_id': port_id})

            if self.mode == SYNC_MODE_REPAIR:
                LOG.debug('Deleting port DHCP options for (subnet %s, port '
                          '%s)', dhcp_opt['external_ids']['subnet_id'],
                          port_id)
                txn_commands.append(self.ovn_api.delete_dhcp_options(
                    dhcp_opt['uuid']))

        if txn_commands:
            with self.ovn_api.transaction(check_error=True) as txn:
                for cmd in txn_commands:
                    txn.add(cmd)
        LOG.debug('OVN-NB Sync DHCP options for Neutron ports with extra '
                  'dhcp options assigned finished')
예제 #5
0
    def initialize(self):
        """Perform driver initialization.

        Called after all drivers have been loaded and the database has
        been initialized. No abstract methods defined below will be
        called prior to this method being called.
        """
        LOG.info(_LI("Starting OVNMechanismDriver"))
        self._nb_ovn = None
        self._sb_ovn = None
        self._plugin_property = None
        self.sg_enabled = ovn_acl.is_sg_enabled()
        if cfg.CONF.SECURITYGROUP.firewall_driver:
            LOG.warning(_LW('Firewall driver configuration is ignored'))
        self._setup_vif_port_bindings()
        self.subscribe()
        self.qos_driver = qos_driver.OVNQosDriver(self)
예제 #6
0
    def initialize(self):
        """Perform driver initialization.

        Called after all drivers have been loaded and the database has
        been initialized. No abstract methods defined below will be
        called prior to this method being called.
        """
        LOG.info(_LI("Starting OVNMechanismDriver"))
        self._nb_ovn = None
        self._sb_ovn = None
        self._plugin_property = None
        self.sg_enabled = ovn_acl.is_sg_enabled()
        if cfg.CONF.SECURITYGROUP.firewall_driver:
            LOG.warning(_LW('Firewall driver configuration is ignored'))
        self._setup_vif_port_bindings()
        self.subscribe()
        self.qos_driver = qos_driver.OVNQosDriver(self)
예제 #7
0
    def sync_networks_ports_and_dhcp_opts(self, ctx):
        LOG.debug('OVN-NB Sync networks, ports and DHCP options started')
        db_networks = {}
        for net in self.core_plugin.get_networks(ctx):
            db_networks[utils.ovn_name(net['id'])] = net

        db_ports = {}
        for port in self.core_plugin.get_ports(ctx):
            db_ports[port['id']] = port

        ovn_all_dhcp_options = self.ovn_api.get_all_dhcp_options()
        db_network_cache = dict(db_networks)

        ports_need_sync_dhcp_opts = []
        lswitches = self.ovn_api.get_all_logical_switches_with_ports()
        del_lswitchs_list = []
        del_lports_list = []
        for lswitch in lswitches:
            if lswitch['name'] in db_networks:
                for lport in lswitch['ports']:
                    if lport in db_ports:
                        ports_need_sync_dhcp_opts.append(db_ports.pop(lport))
                    else:
                        del_lports_list.append({
                            'port': lport,
                            'lswitch': lswitch['name']
                        })
                del db_networks[lswitch['name']]
            else:
                del_lswitchs_list.append(lswitch)

        for net_id, network in db_networks.items():
            LOG.warning(
                _LW("Network found in Neutron but not in "
                    "OVN DB, network_id=%s"), network['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug('Creating the network %s in OVN NB DB',
                              network['id'])
                    self._create_network_in_ovn(network)
                except RuntimeError:
                    LOG.warning(
                        _LW("Create network in OVN NB failed for"
                            " network %s"), network['id'])

        self._sync_subnet_dhcp_options(ctx, db_network_cache,
                                       ovn_all_dhcp_options['subnets'])

        for port_id, port in db_ports.items():
            LOG.warning(
                _LW("Port found in Neutron but not in OVN "
                    "DB, port_id=%s"), port['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug('Creating the port %s in OVN NB DB', port['id'])
                    self._create_port_in_ovn(ctx, port)
                    if port_id in ovn_all_dhcp_options['ports_v4']:
                        _, lsp_opts = utils.get_lsp_dhcp_opts(
                            port, constants.IP_VERSION_4)
                        if lsp_opts:
                            ovn_all_dhcp_options['ports_v4'].pop(port_id)
                    if port_id in ovn_all_dhcp_options['ports_v6']:
                        _, lsp_opts = utils.get_lsp_dhcp_opts(
                            port, constants.IP_VERSION_6)
                        if lsp_opts:
                            ovn_all_dhcp_options['ports_v6'].pop(port_id)
                except RuntimeError:
                    LOG.warning(
                        _LW("Create port in OVN NB failed for"
                            " port %s"), port['id'])

        with self.ovn_api.transaction(check_error=True) as txn:
            for lswitch in del_lswitchs_list:
                LOG.warning(
                    _LW("Network found in OVN but not in "
                        "Neutron, network_id=%s"), lswitch['name'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Deleting the network %s from OVN NB DB',
                              lswitch['name'])
                    txn.add(
                        self.ovn_api.delete_lswitch(
                            lswitch_name=lswitch['name']))

            for lport_info in del_lports_list:
                LOG.warning(
                    _LW("Port found in OVN but not in "
                        "Neutron, port_id=%s"), lport_info['port'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Deleting the port %s from OVN NB DB',
                              lport_info['port'])
                    txn.add(
                        self.ovn_api.delete_lswitch_port(
                            lport_name=lport_info['port'],
                            lswitch_name=lport_info['lswitch']))
                    if lport_info['port'] in ovn_all_dhcp_options['ports_v4']:
                        LOG.debug('Deleting port DHCPv4 options for (port %s)',
                                  lport_info['port'])
                        txn.add(
                            self.ovn_api.delete_dhcp_options(
                                ovn_all_dhcp_options['ports_v4'].pop(
                                    lport_info['port'])['uuid']))
                    if lport_info['port'] in ovn_all_dhcp_options['ports_v6']:
                        LOG.debug('Deleting port DHCPv6 options for (port %s)',
                                  lport_info['port'])
                        txn.add(
                            self.ovn_api.delete_dhcp_options(
                                ovn_all_dhcp_options['ports_v6'].pop(
                                    lport_info['port'])['uuid']))

        self._sync_port_dhcp_options(ctx, ports_need_sync_dhcp_opts,
                                     ovn_all_dhcp_options['ports_v4'],
                                     ovn_all_dhcp_options['ports_v6'])
        LOG.debug('OVN-NB Sync networks, ports and DHCP options finished')
예제 #8
0
    def _sync_port_dhcp_options(self, ctx, ports_need_sync_dhcp_opts,
                                ovn_port_dhcpv4_opts, ovn_port_dhcpv6_opts):
        if not config.is_ovn_dhcp():
            return

        LOG.debug('OVN-NB Sync DHCP options for Neutron ports with extra '
                  'dhcp options assigned started')

        txn_commands = []
        lsp_dhcp_key = {
            constants.IP_VERSION_4: 'dhcpv4_options',
            constants.IP_VERSION_6: 'dhcpv6_options'
        }
        ovn_port_dhcp_opts = {
            constants.IP_VERSION_4: ovn_port_dhcpv4_opts,
            constants.IP_VERSION_6: ovn_port_dhcpv6_opts
        }
        for port in ports_need_sync_dhcp_opts:
            if self.mode == SYNC_MODE_REPAIR:
                LOG.debug('Updating DHCP options for port %s in OVN NB DB',
                          port['id'])
                set_lsp = {}
                for ip_v in [constants.IP_VERSION_4, constants.IP_VERSION_6]:
                    dhcp_opts = self.ovn_driver.get_port_dhcp_options(
                        port, ip_v)
                    if not dhcp_opts:
                        # If the Logical_Switch_Port.dhcpv4_options or
                        # dhcpv6_options no longer refers a port dhcp options
                        # created in DHCP_Options earlier, that port dhcp
                        # options will be deleted in the following
                        # ovn_port_dhcp_options handling.
                        set_lsp[lsp_dhcp_key[ip_v]] = []
                    elif port['id'] in ovn_port_dhcp_opts[ip_v]:
                        # When the Logical_Switch_Port.dhcpv4_options or
                        # dhcpv6_options refers a port dhcp options in
                        # DHCP_Options earlier, if the extra dhcp options has
                        # changed, ovn_driver.get_port_dhcp_options should
                        # udpate it, if removed, it will be deleted in the
                        # following ovn_port_dhcp_options handling.
                        if dhcp_opts['external_ids'].get('port_id'):
                            ovn_port_dhcp_opts[ip_v].pop(port['id'])
                            # Ensure Logical_Switch_Port still have references
                            # to DHCP_Options rows.
                            set_lsp[lsp_dhcp_key[ip_v]] = [dhcp_opts['uuid']]
                    elif 'uuid' in dhcp_opts:
                        set_lsp[lsp_dhcp_key[ip_v]] = [dhcp_opts['uuid']]
                if set_lsp:
                    txn_commands.append(
                        self.ovn_api.set_lswitch_port(lport_name=port['id'],
                                                      **set_lsp))

        for ip_v in [constants.IP_VERSION_4, constants.IP_VERSION_6]:
            for port_id, dhcp_opt in ovn_port_dhcp_opts[ip_v].items():
                LOG.warning(
                    _LW('Out of sync port DHCPv%(ip_version)d options for '
                        '(subnet %(subnet_id)s port %(port_id)s) found in OVN '
                        'NB DB which needs to be deleted'), {
                            'ip_version': ip_v,
                            'subnet_id': dhcp_opt['external_ids']['subnet_id'],
                            'port_id': port_id
                        })

                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug(
                        'Deleting port DHCPv%d options for (subnet %s, '
                        'port %s)', ip_v,
                        dhcp_opt['external_ids']['subnet_id'], port_id)
                    txn_commands.append(
                        self.ovn_api.delete_dhcp_options(dhcp_opt['uuid']))

        if txn_commands:
            with self.ovn_api.transaction(check_error=True) as txn:
                for cmd in txn_commands:
                    txn.add(cmd)
        LOG.debug('OVN-NB Sync DHCP options for Neutron ports with extra '
                  'dhcp options assigned finished')
예제 #9
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 = {}
        for router in self.l3_plugin.get_routers(ctx):
            db_routers[router['id']] = router

        interfaces = self.l3_plugin._get_sync_interfaces(ctx,
                                                         db_routers.keys())
        for interface in interfaces:
            db_router_ports[interface['id']] = interface
        lrouters = self.ovn_api.get_all_logical_routers_with_rports()
        del_lrouters_list = []
        del_lrouter_ports_list = []
        update_sroutes_list = []
        for lrouter in lrouters:
            if lrouter['name'] in db_routers:
                for lrport in lrouter['ports']:
                    if lrport in db_router_ports:
                        del db_router_ports[lrport]
                    else:
                        del_lrouter_ports_list.append(
                            {'port': lrport, 'lrouter': lrouter['name']})
                if 'routes' in db_routers[lrouter['name']]:
                    db_routes = db_routers[lrouter['name']]['routes']
                else:
                    db_routes = []
                ovn_routes = lrouter['static_routes']
                add_routes, del_routes = n_utils.diff_list_of_dict(
                    ovn_routes, db_routes)
                update_sroutes_list.append({'id': lrouter['name'],
                                            'add': add_routes,
                                            'del': del_routes})
                del db_routers[lrouter['name']]
            else:
                del_lrouters_list.append(lrouter)

        for r_id, router in db_routers.items():
            LOG.warning(_LW("Router found in Neutron but not in "
                            "OVN DB, router id=%s"), router['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.warning(_LW("Creating the router %s in OVN NB DB"),
                                router['id'])
                    self.l3_plugin.create_lrouter_in_ovn(router)
                    if 'routes' in router:
                        update_sroutes_list.append(
                            {'id': router['id'], 'add': router['routes'],
                             'del': []})
                except RuntimeError:
                    LOG.warning(_LW("Create router in OVN NB failed for"
                                    " router %s"), router['id'])

        for rp_id, rrport in db_router_ports.items():
            LOG.warning(_LW("Router Port found in Neutron but not in OVN "
                            "DB, router port_id=%s"), rrport['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.warning(_LW("Creating the router port %s in "
                                    "OVN NB DB"), rrport['id'])
                    self.l3_plugin.create_lrouter_port_in_ovn(
                        ctx, rrport['device_id'], rrport)
                except RuntimeError:
                    LOG.warning(_LW("Create router port in OVN "
                                    "NB failed for"
                                    " router port %s"), rrport['id'])

        with self.ovn_api.transaction(check_error=True) as txn:
            for lrouter in del_lrouters_list:
                LOG.warning(_LW("Router found in OVN but not in "
                                "Neutron, router id=%s"), lrouter['name'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.warning(_LW("Deleting the router %s from OVN NB DB"),
                                lrouter['name'])
                    txn.add(self.ovn_api.delete_lrouter(
                            utils.ovn_name(lrouter['name'])))

            for lrport_info in del_lrouter_ports_list:
                LOG.warning(_LW("Router Port found in OVN but not in "
                                "Neutron, port_id=%s"), lrport_info['port'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.warning(_LW("Deleting the port %s from OVN NB DB"),
                                lrport_info['port'])
                    txn.add(self.ovn_api.delete_lrouter_port(
                            utils.ovn_lrouter_port_name(lrport_info['port']),
                            utils.ovn_name(lrport_info['lrouter']),
                            if_exists=False))
            for sroute in update_sroutes_list:
                if sroute['add']:
                    LOG.warning("Router %s static routes %s found in "
                                "Neutron but not in OVN", sroute['id'],
                                sroute['add'])
                    if self.mode == SYNC_MODE_REPAIR:
                        LOG.warning(_LW("Add static routes %s to OVN NB DB"),
                                    sroute['add'])
                        for route in sroute['add']:
                            txn.add(self.ovn_api.add_static_route(
                                utils.ovn_name(sroute['id']),
                                ip_prefix=route['destination'],
                                nexthop=route['nexthop']))
                if sroute['del']:
                    LOG.warning("Router %s static routes %s found in "
                                "OVN but not in Neutron", sroute['id'],
                                sroute['del'])
                    if self.mode == SYNC_MODE_REPAIR:
                        LOG.warning(_LW("Delete static routes %s from OVN "
                                        "NB DB"), sroute['del'])
                        for route in sroute['del']:
                            txn.add(self.ovn_api.delete_static_route(
                                utils.ovn_name(sroute['id']),
                                ip_prefix=route['destination'],
                                nexthop=route['nexthop']))
        LOG.debug('OVN-NB Sync routers and router ports finished')
예제 #10
0
    def _sync_port_dhcp_options(self, ctx, ports_need_sync_dhcp_opts,
                                ovn_port_dhcpv4_opts, ovn_port_dhcpv6_opts):
        if not config.is_ovn_dhcp():
            return

        LOG.debug('OVN-NB Sync DHCP options for Neutron ports with extra '
                  'dhcp options assigned started')

        txn_commands = []
        lsp_dhcp_key = {constants.IP_VERSION_4: 'dhcpv4_options',
                        constants.IP_VERSION_6: 'dhcpv6_options'}
        ovn_port_dhcp_opts = {constants.IP_VERSION_4: ovn_port_dhcpv4_opts,
                              constants.IP_VERSION_6: ovn_port_dhcpv6_opts}
        for port in ports_need_sync_dhcp_opts:
            if self.mode == SYNC_MODE_REPAIR:
                LOG.debug('Updating DHCP options for port %s in OVN NB DB',
                          port['id'])
                set_lsp = {}
                for ip_v in [constants.IP_VERSION_4, constants.IP_VERSION_6]:
                    dhcp_opts = self.ovn_driver.get_port_dhcp_options(
                        port, ip_v)
                    if not dhcp_opts or 'uuid' in dhcp_opts:
                        # If the Logical_Switch_Port.dhcpv4_options or
                        # dhcpv6_options no longer refers a port dhcp options
                        # created in DHCP_Options earlier, that port dhcp
                        # options will be deleted in the following
                        # ovn_port_dhcp_options handling.
                        set_lsp[lsp_dhcp_key[ip_v]] = (
                            dhcp_opts and [dhcp_opts['uuid']] or [])
                    else:
                        # If port has extra port dhcp options, a command will
                        # returned by ovn_driver.get_port_dhcp_options to add
                        # or update port dhcp options.
                        ovn_port_dhcp_opts[ip_v].pop(port['id'], None)
                        dhcp_options = dhcp_opts['cmd']
                        txn_commands.append(dhcp_options)
                        set_lsp[lsp_dhcp_key[ip_v]] = dhcp_options
                if set_lsp:
                    txn_commands.append(self.ovn_api.set_lswitch_port(
                        lport_name=port['id'], **set_lsp))

        for ip_v in [constants.IP_VERSION_4, constants.IP_VERSION_6]:
            for port_id, dhcp_opt in ovn_port_dhcp_opts[ip_v].items():
                LOG.warning(
                    _LW('Out of sync port DHCPv%(ip_version)d options for '
                        '(subnet %(subnet_id)s port %(port_id)s) found in OVN '
                        'NB DB which needs to be deleted'),
                    {'ip_version': ip_v,
                     'subnet_id': dhcp_opt['external_ids']['subnet_id'],
                     'port_id': port_id})

                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Deleting port DHCPv%d options for (subnet %s, '
                              'port %s)', ip_v,
                              dhcp_opt['external_ids']['subnet_id'], port_id)
                    txn_commands.append(self.ovn_api.delete_dhcp_options(
                        dhcp_opt['uuid']))

        if txn_commands:
            with self.ovn_api.transaction(check_error=True) as txn:
                for cmd in txn_commands:
                    txn.add(cmd)
        LOG.debug('OVN-NB Sync DHCP options for Neutron ports with extra '
                  'dhcp options assigned finished')
예제 #11
0
    def sync_acls(self, ctx):
        """Sync ACLs between neutron and NB.

        @param ctx: neutron context
        @type  ctx: object of type neutron.context.Context
        @var   db_ports: List of ports from neutron DB
        @var   neutron_acls: neutron dictionary of port
               vs list-of-acls
        @var   nb_acls: NB dictionary of port
               vs list-of-acls
        @var   subnet_cache: cache for subnets
        @return: Nothing
        """
        LOG.debug('ACL-SYNC: started @ %s' %
                  str(datetime.now()))

        db_ports = {}
        for port in self.core_plugin.get_ports(ctx):
            db_ports[port['id']] = port

        sg_cache = {}
        subnet_cache = {}
        neutron_acls = {}
        for port_id, port in six.iteritems(db_ports):
            if port['security_groups']:
                acl_list = acl_utils.add_acls(self.core_plugin,
                                              ctx,
                                              port,
                                              sg_cache,
                                              subnet_cache)
                if port_id in neutron_acls:
                    neutron_acls[port_id].extend(acl_list)
                else:
                    neutron_acls[port_id] = acl_list

        nb_acls = self.get_acls(ctx)

        self.remove_common_acls(neutron_acls, nb_acls)

        num_acls_to_add = \
            len(list(itertools.chain(*six.itervalues(neutron_acls))))
        num_acls_to_remove = \
            len(list(itertools.chain(*six.itervalues(nb_acls))))
        if 0 != num_acls_to_add or 0 != num_acls_to_remove:
            LOG.warning(_LW('ACLs-to-be-added %(add)d '
                            'ACLs-to-be-removed %(remove)d'),
                        {'add': num_acls_to_add,
                         'remove': num_acls_to_remove})

        if self.mode == SYNC_MODE_REPAIR:
            with self.ovn_api.transaction(check_error=True) as txn:
                for acla in list(itertools.chain(
                                 *six.itervalues(neutron_acls))):
                    LOG.warning(_LW('ACL found in Neutron but not in '
                                    'OVN DB for port %s'), acla['lport'])
                    txn.add(self.ovn_api.add_acl(**acla))

            with self.ovn_api.transaction(check_error=True) as txn:
                for aclr in list(itertools.chain(*six.itervalues(nb_acls))):
                    # Both lswitch and lport aren't needed within the ACL.
                    lswitchr = aclr.pop('lswitch').replace('neutron-', '')
                    lportr = aclr.pop('lport')
                    aclr_dict = {lportr: aclr}
                    LOG.warning(_LW('ACLs found in OVN DB but not in '
                                    'Neutron for port %s'), lportr)
                    txn.add(self.ovn_api.update_acls(
                        [lswitchr],
                        [lportr],
                        aclr_dict,
                        need_compare=False,
                        is_add_acl=False
                    ))

        LOG.debug('ACL-SYNC: finished @ %s' %
                  str(datetime.now()))
예제 #12
0
    def _sync_port_dhcp_options(self, ctx, ports_need_sync_dhcp_opts,
                                ovn_port_dhcpv4_opts, ovn_port_dhcpv6_opts):
        if not config.is_ovn_dhcp():
            return

        LOG.debug('OVN-NB Sync DHCP options for Neutron ports with extra '
                  'dhcp options assigned started')

        txn_commands = []
        lsp_dhcp_key = {
            constants.IP_VERSION_4: 'dhcpv4_options',
            constants.IP_VERSION_6: 'dhcpv6_options'
        }
        ovn_port_dhcp_opts = {
            constants.IP_VERSION_4: ovn_port_dhcpv4_opts,
            constants.IP_VERSION_6: ovn_port_dhcpv6_opts
        }
        for port in ports_need_sync_dhcp_opts:
            # Ignore the floating ip ports with device_owner set to
            # constants.DEVICE_OWNER_FLOATINGIP
            if port.get('device_owner',
                        '').startswith(constants.DEVICE_OWNER_FLOATINGIP):
                continue

            if self.mode == SYNC_MODE_REPAIR:
                LOG.debug('Updating DHCP options for port %s in OVN NB DB',
                          port['id'])
                set_lsp = {}
                for ip_v in [constants.IP_VERSION_4, constants.IP_VERSION_6]:
                    dhcp_opts = self.ovn_driver.get_port_dhcp_options(
                        port, ip_v)
                    if not dhcp_opts or 'uuid' in dhcp_opts:
                        # If the Logical_Switch_Port.dhcpv4_options or
                        # dhcpv6_options no longer refers a port dhcp options
                        # created in DHCP_Options earlier, that port dhcp
                        # options will be deleted in the following
                        # ovn_port_dhcp_options handling.
                        set_lsp[lsp_dhcp_key[ip_v]] = (dhcp_opts
                                                       and [dhcp_opts['uuid']]
                                                       or [])
                    else:
                        # If port has extra port dhcp options, a command will
                        # returned by ovn_driver.get_port_dhcp_options to add
                        # or update port dhcp options.
                        ovn_port_dhcp_opts[ip_v].pop(port['id'], None)
                        dhcp_options = dhcp_opts['cmd']
                        txn_commands.append(dhcp_options)
                        set_lsp[lsp_dhcp_key[ip_v]] = dhcp_options
                if set_lsp:
                    txn_commands.append(
                        self.ovn_api.set_lswitch_port(lport_name=port['id'],
                                                      **set_lsp))

        for ip_v in [constants.IP_VERSION_4, constants.IP_VERSION_6]:
            for port_id, dhcp_opt in ovn_port_dhcp_opts[ip_v].items():
                LOG.warning(
                    _LW('Out of sync port DHCPv%(ip_version)d options for '
                        '(subnet %(subnet_id)s port %(port_id)s) found in OVN '
                        'NB DB which needs to be deleted'), {
                            'ip_version': ip_v,
                            'subnet_id': dhcp_opt['external_ids']['subnet_id'],
                            'port_id': port_id
                        })

                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug(
                        'Deleting port DHCPv%d options for (subnet %s, '
                        'port %s)', ip_v,
                        dhcp_opt['external_ids']['subnet_id'], port_id)
                    txn_commands.append(
                        self.ovn_api.delete_dhcp_options(dhcp_opt['uuid']))

        if txn_commands:
            with self.ovn_api.transaction(check_error=True) as txn:
                for cmd in txn_commands:
                    txn.add(cmd)
        LOG.debug('OVN-NB Sync DHCP options for Neutron ports with extra '
                  'dhcp options assigned finished')
예제 #13
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
        """
        LOG.debug('OVN-NB Sync Routers and Router ports started')
        db_routers = {}
        db_router_ports = {}
        for router in self.core_plugin.get_routers(ctx):
            db_routers[router['id']] = router

        interfaces = self.core_plugin._get_sync_interfaces(ctx,
                                                           db_routers.keys())
        for interface in interfaces:
            db_router_ports[interface['id']] = interface
        lrouters = self.ovn_api.get_all_logical_routers_with_rports()
        del_lrouters_list = []
        del_lrouter_ports_list = []
        for lrouter in lrouters:
            if lrouter['name'] in db_routers:
                for lrport in lrouter['ports']:
                    if lrport in db_router_ports:
                        del db_router_ports[lrport]
                    else:
                        del_lrouter_ports_list.append(
                            {'port': lrport, 'lrouter': lrouter['name']})
                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.core_plugin.create_lrouter_in_ovn(router)
                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.core_plugin.create_lrouter_port_in_ovn(
                        ctx, rrport['device_id'], rrport)
                except RuntimeError:
                    LOG.warning(_LW("Create router port in OVN "
                                    "NB failed for"
                                    " router port %s"), rrport['id'])

        with self.ovn_api.transaction(check_error=True) as txn:
            for lrouter in del_lrouters_list:
                LOG.warning(_LW("Router found in OVN but not in "
                                "Neutron, router id=%s"), lrouter['name'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.warning(_LW("Deleting the router %s from OVN NB DB"),
                                lrouter['name'])
                    txn.add(self.ovn_api.delete_lrouter(
                            utils.ovn_name(lrouter['name'])))

            for lrport_info in del_lrouter_ports_list:
                LOG.warning(_LW("Router Port found in OVN but not in "
                                "Neutron, port_id=%s"), lrport_info['port'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.warning(_LW("Deleting the port %s from OVN NB DB"),
                                lrport_info['port'])
                    txn.add(self.ovn_api.delete_lrouter_port(
                            utils.ovn_lrouter_port_name(lrport_info['port']),
                            utils.ovn_name(lrport_info['lrouter']),
                            if_exists=False))
        LOG.debug('OVN-NB Sync routers and router ports finished')
예제 #14
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')
예제 #15
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
        """
        LOG.debug('OVN-NB Sync Routers and Router ports started')
        db_routers = {}
        db_router_ports = {}
        for router in self.core_plugin.get_routers(ctx):
            db_routers[router['id']] = router

        interfaces = self.core_plugin._get_sync_interfaces(ctx,
                                                           db_routers.keys())
        for interface in interfaces:
            db_router_ports[interface['id']] = interface
        lrouters = self.ovn_api.get_all_logical_routers_with_rports()
        del_lrouters_list = []
        del_lrouter_ports_list = []
        for lrouter in lrouters:
            if lrouter['name'] in db_routers:
                for lrport in lrouter['ports']:
                    if lrport in db_router_ports:
                        del db_router_ports[lrport]
                    else:
                        del_lrouter_ports_list.append(
                            {'port': lrport, 'lrouter': lrouter['name']})
                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.core_plugin.create_lrouter_in_ovn(router)
                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.core_plugin.create_lrouter_port_in_ovn(
                        ctx, rrport['device_id'], rrport)
                except RuntimeError:
                    LOG.warning(_LW("Create router port in OVN "
                                    "NB failed for"
                                    " router port %s"), rrport['id'])

        with self.ovn_api.transaction(check_error=True) as txn:
            for lrouter in del_lrouters_list:
                LOG.warning(_LW("Router found in OVN but not in "
                                "Neutron, router id=%s"), lrouter['name'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.warning(_LW("Deleting the router %s from OVN NB DB"),
                                lrouter['name'])
                    txn.add(self.ovn_api.delete_lrouter(
                            utils.ovn_name(lrouter['name'])))

            for lrport_info in del_lrouter_ports_list:
                LOG.warning(_LW("Router Port found in OVN but not in "
                                "Neutron, port_id=%s"), lrport_info['port'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.warning(_LW("Deleting the port %s from OVN NB DB"),
                                lrport_info['port'])
                    txn.add(self.ovn_api.delete_lrouter_port(
                            utils.ovn_lrouter_port_name(lrport_info['port']),
                            utils.ovn_name(lrport_info['lrouter']),
                            if_exists=False))
        LOG.debug('OVN-NB Sync routers and router ports finished')
예제 #16
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 = {}
        for router in self.l3_plugin.get_routers(ctx):
            db_routers[router['id']] = router

        interfaces = self.l3_plugin._get_sync_interfaces(
            ctx, db_routers.keys())
        for interface in interfaces:
            db_router_ports[interface['id']] = interface
        lrouters = self.ovn_api.get_all_logical_routers_with_rports()
        del_lrouters_list = []
        del_lrouter_ports_list = []
        update_sroutes_list = []
        for lrouter in lrouters:
            if lrouter['name'] in db_routers:
                for lrport in lrouter['ports']:
                    if lrport in db_router_ports:
                        del db_router_ports[lrport]
                    else:
                        del_lrouter_ports_list.append({
                            'port':
                            lrport,
                            'lrouter':
                            lrouter['name']
                        })
                if 'routes' in db_routers[lrouter['name']]:
                    db_routes = db_routers[lrouter['name']]['routes']
                else:
                    db_routes = []
                ovn_routes = lrouter['static_routes']
                add_routes, del_routes = n_utils.diff_list_of_dict(
                    ovn_routes, db_routes)
                update_sroutes_list.append({
                    'id': lrouter['name'],
                    'add': add_routes,
                    'del': del_routes
                })
                del db_routers[lrouter['name']]
            else:
                del_lrouters_list.append(lrouter)

        for r_id, router in db_routers.items():
            LOG.warning(
                _LW("Router found in Neutron but not in "
                    "OVN DB, router id=%s"), router['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.warning(_LW("Creating the router %s in OVN NB DB"),
                                router['id'])
                    self.l3_plugin.create_lrouter_in_ovn(router)
                    if 'routes' in router:
                        update_sroutes_list.append({
                            'id': router['id'],
                            'add': router['routes'],
                            'del': []
                        })
                except RuntimeError:
                    LOG.warning(
                        _LW("Create router in OVN NB failed for"
                            " router %s"), router['id'])

        for rp_id, rrport in db_router_ports.items():
            LOG.warning(
                _LW("Router Port found in Neutron but not in OVN "
                    "DB, router port_id=%s"), rrport['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.warning(
                        _LW("Creating the router port %s in "
                            "OVN NB DB"), rrport['id'])
                    self.l3_plugin.create_lrouter_port_in_ovn(
                        ctx, rrport['device_id'], rrport)
                except RuntimeError:
                    LOG.warning(
                        _LW("Create router port in OVN "
                            "NB failed for"
                            " router port %s"), rrport['id'])

        with self.ovn_api.transaction(check_error=True) as txn:
            for lrouter in del_lrouters_list:
                LOG.warning(
                    _LW("Router found in OVN but not in "
                        "Neutron, router id=%s"), lrouter['name'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.warning(_LW("Deleting the router %s from OVN NB DB"),
                                lrouter['name'])
                    txn.add(
                        self.ovn_api.delete_lrouter(
                            utils.ovn_name(lrouter['name'])))

            for lrport_info in del_lrouter_ports_list:
                LOG.warning(
                    _LW("Router Port found in OVN but not in "
                        "Neutron, port_id=%s"), lrport_info['port'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.warning(_LW("Deleting the port %s from OVN NB DB"),
                                lrport_info['port'])
                    txn.add(
                        self.ovn_api.delete_lrouter_port(
                            utils.ovn_lrouter_port_name(lrport_info['port']),
                            utils.ovn_name(lrport_info['lrouter']),
                            if_exists=False))
            for sroute in update_sroutes_list:
                if sroute['add']:
                    LOG.warning(
                        _LW("Router %(id)s static routes %(route)s "
                            "found in Neutron but not in OVN"), {
                                'id': sroute['id'],
                                'route': sroute['add']
                            })
                    if self.mode == SYNC_MODE_REPAIR:
                        LOG.warning(_LW("Add static routes %s to OVN NB DB"),
                                    sroute['add'])
                        for route in sroute['add']:
                            txn.add(
                                self.ovn_api.add_static_route(
                                    utils.ovn_name(sroute['id']),
                                    ip_prefix=route['destination'],
                                    nexthop=route['nexthop']))
                if sroute['del']:
                    LOG.warning(
                        _LW("Router %(id)s static routes %(route)s "
                            "found in OVN but not in Neutron"), {
                                'id': sroute['id'],
                                'route': sroute['del']
                            })
                    if self.mode == SYNC_MODE_REPAIR:
                        LOG.warning(
                            _LW("Delete static routes %s from OVN "
                                "NB DB"), sroute['del'])
                        for route in sroute['del']:
                            txn.add(
                                self.ovn_api.delete_static_route(
                                    utils.ovn_name(sroute['id']),
                                    ip_prefix=route['destination'],
                                    nexthop=route['nexthop']))
        LOG.debug('OVN-NB Sync routers and router ports finished')
예제 #17
0
    def sync_networks_and_ports(self, ctx):
        LOG.debug('OVN-NB Sync networks and ports started')
        db_networks = {}
        for net in self.core_plugin.get_networks(ctx):
            db_networks[utils.ovn_name(net['id'])] = net

        db_ports = {}
        for port in self.core_plugin.get_ports(ctx):
            db_ports[port['id']] = port

        lswitches = self.ovn_api.get_all_logical_switches_with_ports()
        del_lswitchs_list = []
        del_lports_list = []
        for lswitch in lswitches:
            if lswitch['name'] in db_networks:
                for lport in lswitch['ports']:
                    if lport in db_ports:
                        del db_ports[lport]
                    else:
                        del_lports_list.append({
                            'port': lport,
                            'lswitch': lswitch['name']
                        })
                del db_networks[lswitch['name']]
            else:
                del_lswitchs_list.append(lswitch)

        for net_id, network in db_networks.items():
            LOG.warning(
                _LW("Network found in Neutron but not in "
                    "OVN DB, network_id=%s"), network['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug('Creating the network %s in OVN NB DB',
                              network['id'])
                    self._create_network_in_ovn(network)
                except RuntimeError:
                    LOG.warning(
                        _LW("Create network in OVN NB failed for"
                            " network %s"), network['id'])

        for port_id, port in db_ports.items():
            LOG.warning(
                _LW("Port found in Neutron but not in OVN "
                    "DB, port_id=%s"), port['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug('Creating the port %s in OVN NB DB', port['id'])
                    self._create_port_in_ovn(ctx, port)
                except RuntimeError:
                    LOG.warning(
                        _LW("Create port in OVN NB failed for"
                            " port %s"), port['id'])

        with self.ovn_api.transaction(check_error=True) as txn:
            for lswitch in del_lswitchs_list:
                LOG.warning(
                    _LW("Network found in OVN but not in "
                        "Neutron, network_id=%s"), lswitch['name'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Deleting the network %s from OVN NB DB',
                              lswitch['name'])
                    txn.add(
                        self.ovn_api.delete_lswitch(
                            lswitch_name=lswitch['name']))

            for lport_info in del_lports_list:
                LOG.warning(
                    _LW("Port found in OVN but not in "
                        "Neutron, port_id=%s"), lport_info['port'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Deleting the port %s from OVN NB DB',
                              lport_info['port'])
                    txn.add(
                        self.ovn_api.delete_lswitch_port(
                            lport_name=lport_info['port'],
                            lswitch_name=lport_info['lswitch']))
        LOG.debug('OVN-NB Sync networks and ports finished')
예제 #18
0
    def sync_routers_and_rports(self, ctx):
        """Sync Routers between neutron and NB.

        @param ctx: neutron_lib.context
        @type  ctx: object of type neutron_lib.context.Context
        @var   db_routers: List of Routers from neutron DB
        @var   db_router_ports: List of Router ports from neutron DB
        @var   lrouters: NB dictionary of logical routers and
               the corresponding logical router ports.
               vs list-of-acls
        @var   del_lrouters_list: List of Routers that need to be
               deleted from NB
        @var   del_lrouter_ports_list: List of Router ports that need to be
               deleted from NB
        @return: Nothing
        """
        if not config.is_ovn_l3():
            LOG.debug("OVN L3 mode is disabled, skipping "
                      "sync routers and router ports")
            return

        LOG.debug('OVN-NB Sync Routers and Router ports started @ %s' %
                  str(datetime.now()))

        db_routers = {}
        db_extends = {}
        db_router_ports = {}
        for router in self.l3_plugin.get_routers(ctx):
            db_routers[router['id']] = router
            db_extends[router['id']] = {}
            db_extends[router['id']]['routes'] = []
            db_extends[router['id']]['snats'] = []
            db_extends[router['id']]['fips'] = []
            if not router.get(l3.EXTERNAL_GW_INFO):
                continue
            r_ip, gw_ip = self.l3_plugin.get_external_router_and_gateway_ip(
                ctx, router)
            if gw_ip:
                db_extends[router['id']]['routes'].append({
                    'destination': '0.0.0.0/0',
                    'nexthop': gw_ip
                })
            if r_ip and utils.is_snat_enabled(router):
                networks = self.l3_plugin._get_v4_network_of_all_router_ports(
                    ctx, router['id'])
                for network in networks:
                    db_extends[router['id']]['snats'].append({
                        'logical_ip': network,
                        'external_ip': r_ip,
                        'type': 'snat'
                    })

        fips = self.l3_plugin.get_floatingips(
            ctx, {'router_id': list(db_routers.keys())})
        for fip in fips:
            db_extends[fip['router_id']]['fips'].append({
                'external_ip':
                fip['floating_ip_address'],
                'logical_ip':
                fip['fixed_ip_address'],
                'type':
                'dnat_and_snat'
            })
        interfaces = self.l3_plugin._get_sync_interfaces(
            ctx, db_routers.keys(), [
                constants.DEVICE_OWNER_ROUTER_INTF,
                constants.DEVICE_OWNER_ROUTER_GW
            ])
        for interface in interfaces:
            db_router_ports[interface['id']] = interface
            db_router_ports[interface['id']]['networks'] = sorted(
                self.l3_plugin.get_networks_for_lrouter_port(
                    ctx, interface['fixed_ips']))
        lrouters = self.ovn_api.get_all_logical_routers_with_rports()

        del_lrouters_list = []
        del_lrouter_ports_list = []
        update_sroutes_list = []
        update_lrport_list = []
        update_snats_list = []
        update_fips_list = []
        for lrouter in lrouters:
            if lrouter['name'] in db_routers:
                for lrport, lrport_nets in lrouter['ports'].items():
                    if lrport in db_router_ports:
                        db_lrport_nets = db_router_ports[lrport]['networks']
                        if db_lrport_nets != sorted(lrport_nets):
                            update_lrport_list.append(
                                (lrouter['name'], db_router_ports[lrport]))
                        del db_router_ports[lrport]
                    else:
                        del_lrouter_ports_list.append({
                            'port':
                            lrport,
                            'lrouter':
                            lrouter['name']
                        })
                if 'routes' in db_routers[lrouter['name']]:
                    db_routes = db_routers[lrouter['name']]['routes']
                else:
                    db_routes = []
                if 'routes' in db_extends[lrouter['name']]:
                    db_routes.extend(db_extends[lrouter['name']]['routes'])

                ovn_routes = lrouter['static_routes']
                add_routes, del_routes = helpers.diff_list_of_dict(
                    ovn_routes, db_routes)
                update_sroutes_list.append({
                    'id': lrouter['name'],
                    'add': add_routes,
                    'del': del_routes
                })
                ovn_fips = lrouter['dnat_and_snats']
                db_fips = db_extends[lrouter['name']]['fips']
                add_fips, del_fips = helpers.diff_list_of_dict(
                    ovn_fips, db_fips)
                update_fips_list.append({
                    'id': lrouter['name'],
                    'add': add_fips,
                    'del': del_fips
                })
                ovn_nats = lrouter['snats']
                db_snats = db_extends[lrouter['name']]['snats']
                add_snats, del_snats = helpers.diff_list_of_dict(
                    ovn_nats, db_snats)
                update_snats_list.append({
                    'id': lrouter['name'],
                    'add': add_snats,
                    'del': del_snats
                })
                del db_routers[lrouter['name']]
            else:
                del_lrouters_list.append(lrouter)

        for r_id, router in db_routers.items():
            LOG.warning(
                _LW("Router found in Neutron but not in "
                    "OVN DB, router id=%s"), router['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.warning(_LW("Creating the router %s in OVN NB DB"),
                                router['id'])
                    self.l3_plugin.create_lrouter_in_ovn(router)
                    if 'routes' in router:
                        update_sroutes_list.append({
                            'id': router['id'],
                            'add': router['routes'],
                            'del': []
                        })
                    if 'routes' in db_extends[router['id']]:
                        update_sroutes_list.append({
                            'id':
                            router['id'],
                            'add':
                            db_extends[router['id']]['routes'],
                            'del': []
                        })
                    if 'snats' in db_extends[router['id']]:
                        update_snats_list.append({
                            'id':
                            router['id'],
                            'add':
                            db_extends[router['id']]['snats'],
                            'del': []
                        })
                    if 'fips' in db_extends[router['id']]:
                        update_fips_list.append({
                            'id':
                            router['id'],
                            'add':
                            db_extends[router['id']]['fips'],
                            'del': []
                        })
                except RuntimeError:
                    LOG.warning(
                        _LW("Create router in OVN NB failed for"
                            " router %s"), router['id'])

        for rp_id, rrport in db_router_ports.items():
            LOG.warning(
                _LW("Router Port found in Neutron but not in OVN "
                    "DB, router port_id=%s"), rrport['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.warning(
                        _LW("Creating the router port %s in "
                            "OVN NB DB"), rrport['id'])
                    self.l3_plugin.create_lrouter_port_in_ovn(
                        ctx, rrport['device_id'], rrport)
                except RuntimeError:
                    LOG.warning(
                        _LW("Create router port in OVN "
                            "NB failed for"
                            " router port %s"), rrport['id'])

        for router_id, rport in update_lrport_list:
            LOG.warning(
                _LW("Router Port port_id=%s needs to be updated"
                    " for networks changed"), rport['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.warning(
                        _LW("Updating networks on router port %s in "
                            "OVN NB DB"), rport['id'])
                    self.l3_plugin.update_lrouter_port_in_ovn(
                        ctx, router_id, rport, rport['networks'])
                except RuntimeError:
                    LOG.warning(
                        _LW("Update router port networks in OVN "
                            "NB failed for"
                            " router port %s"), rport['id'])

        with self.ovn_api.transaction(check_error=True) as txn:
            for lrouter in del_lrouters_list:
                LOG.warning(
                    _LW("Router found in OVN but not in "
                        "Neutron, router id=%s"), lrouter['name'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.warning(_LW("Deleting the router %s from OVN NB DB"),
                                lrouter['name'])
                    txn.add(
                        self.ovn_api.delete_lrouter(
                            utils.ovn_name(lrouter['name'])))

            for lrport_info in del_lrouter_ports_list:
                LOG.warning(
                    _LW("Router Port found in OVN but not in "
                        "Neutron, port_id=%s"), lrport_info['port'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.warning(_LW("Deleting the port %s from OVN NB DB"),
                                lrport_info['port'])
                    txn.add(
                        self.ovn_api.delete_lrouter_port(
                            utils.ovn_lrouter_port_name(lrport_info['port']),
                            utils.ovn_name(lrport_info['lrouter']),
                            if_exists=False))
            for sroute in update_sroutes_list:
                if sroute['add']:
                    LOG.warning(
                        _LW("Router %(id)s static routes %(route)s "
                            "found in Neutron but not in OVN"), {
                                'id': sroute['id'],
                                'route': sroute['add']
                            })
                    if self.mode == SYNC_MODE_REPAIR:
                        LOG.warning(_LW("Add static routes %s to OVN NB DB"),
                                    sroute['add'])
                        for route in sroute['add']:
                            txn.add(
                                self.ovn_api.add_static_route(
                                    utils.ovn_name(sroute['id']),
                                    ip_prefix=route['destination'],
                                    nexthop=route['nexthop']))
                if sroute['del']:
                    LOG.warning(
                        _LW("Router %(id)s static routes %(route)s "
                            "found in OVN but not in Neutron"), {
                                'id': sroute['id'],
                                'route': sroute['del']
                            })
                    if self.mode == SYNC_MODE_REPAIR:
                        LOG.warning(
                            _LW("Delete static routes %s from OVN "
                                "NB DB"), sroute['del'])
                        for route in sroute['del']:
                            txn.add(
                                self.ovn_api.delete_static_route(
                                    utils.ovn_name(sroute['id']),
                                    ip_prefix=route['destination'],
                                    nexthop=route['nexthop']))
            for fip in update_fips_list:
                if fip['del']:
                    LOG.warning(
                        _LW("Router %(id)s floating ips %(fip)s "
                            "found in OVN but not in Neutron"), {
                                'id': fip['id'],
                                'fip': fip['del']
                            })
                    if self.mode == SYNC_MODE_REPAIR:
                        LOG.warning(
                            _LW("Delete floating ips %s from OVN NB DB"),
                            fip['del'])
                        for nat in fip['del']:
                            txn.add(
                                self.ovn_api.delete_nat_rule_in_lrouter(
                                    utils.ovn_name(fip['id']),
                                    logical_ip=nat['logical_ip'],
                                    external_ip=nat['external_ip'],
                                    type='dnat_and_snat'))
                if fip['add']:
                    LOG.warning(
                        _LW("Router %(id)s floating ips %(fip)s "
                            "found in Neutron but not in OVN"), {
                                'id': fip['id'],
                                'fip': fip['add']
                            })
                    if self.mode == SYNC_MODE_REPAIR:
                        LOG.warning(_LW("Add floating ips %s to OVN NB DB"),
                                    fip['add'])
                        for nat in fip['add']:
                            txn.add(
                                self.ovn_api.add_nat_rule_in_lrouter(
                                    utils.ovn_name(fip['id']),
                                    logical_ip=nat['logical_ip'],
                                    external_ip=nat['external_ip'],
                                    type='dnat_and_snat'))
            for snat in update_snats_list:
                if snat['del']:
                    LOG.warning(
                        _LW("Router %(id)s snat %(snat)s "
                            "found in OVN but not in Neutron"), {
                                'id': snat['id'],
                                'snat': snat['del']
                            })
                    if self.mode == SYNC_MODE_REPAIR:
                        LOG.warning(_LW("Delete snats %s from OVN NB DB"),
                                    snat['del'])
                        for nat in snat['del']:
                            txn.add(
                                self.ovn_api.delete_nat_rule_in_lrouter(
                                    utils.ovn_name(snat['id']),
                                    logical_ip=nat['logical_ip'],
                                    external_ip=nat['external_ip'],
                                    type='snat'))
                if snat['add']:
                    LOG.warning(
                        _LW("Router %(id)s snat %(snat)s "
                            "found in Neutron but not in OVN"), {
                                'id': snat['id'],
                                'snat': snat['add']
                            })
                    if self.mode == SYNC_MODE_REPAIR:
                        LOG.warning(_LW("Add snats %s to OVN NB DB"),
                                    snat['add'])
                        for nat in snat['add']:
                            txn.add(
                                self.ovn_api.add_nat_rule_in_lrouter(
                                    utils.ovn_name(snat['id']),
                                    logical_ip=nat['logical_ip'],
                                    external_ip=nat['external_ip'],
                                    type='snat'))
        LOG.debug('OVN-NB Sync routers and router ports finished %s' %
                  str(datetime.now()))
예제 #19
0
    def _sync_subnet_dhcp_options(self, ctx, db_networks,
                                  ovn_subnet_dhcp_options):
        if not config.is_ovn_dhcp():
            return

        LOG.debug('OVN-NB Sync DHCP options for Neutron subnets started')

        db_subnets = {}
        filters = {'enable_dhcp': [1]}
        for subnet in self.core_plugin.get_subnets(ctx, filters=filters):
            if subnet['ip_version'] == constants.IP_VERSION_6 and (
                subnet.get('ipv6_address_mode') == constants.IPV6_SLAAC):
                continue
            db_subnets[subnet['id']] = subnet

        del_subnet_dhcp_opts_list = []
        for subnet_id, ovn_dhcp_opts in ovn_subnet_dhcp_options.items():
            if subnet_id in db_subnets:
                network = db_networks[utils.ovn_name(
                    db_subnets[subnet_id]['network_id'])]
                server_mac = ovn_dhcp_opts['options'].get('server_mac')
                dhcp_options = self.ovn_driver.get_ovn_dhcp_options(
                    db_subnets[subnet_id], network, server_mac=server_mac)
                # Verify that the cidr and options are also in sync.
                if dhcp_options['cidr'] == ovn_dhcp_opts['cidr'] and (
                        dhcp_options['options'] == ovn_dhcp_opts['options']):
                    del db_subnets[subnet_id]
                else:
                    db_subnets[subnet_id]['ovn_dhcp_options'] = dhcp_options
            else:
                del_subnet_dhcp_opts_list.append(ovn_dhcp_opts)

        for subnet_id, subnet in db_subnets.items():
            LOG.warning(_LW('DHCP options for subnet %s is present in '
                            'Neutron but out of sync for OVN'), subnet_id)
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug('Adding/Updating DHCP options for subnet %s in '
                              ' OVN NB DB', subnet_id)
                    network = db_networks[utils.ovn_name(subnet['network_id'])]
                    # ovn_driver.add_subnet_dhcp_options_in_ovn doesn't create
                    # a new row in DHCP_Options if the row already exists.
                    # See commands.AddDHCPOptionsCommand.
                    self.ovn_driver.add_subnet_dhcp_options_in_ovn(
                        subnet, network, subnet.get('ovn_dhcp_options'))
                except RuntimeError:
                    LOG.warning(_LW('Adding/Updating DHCP options for subnet '
                                    '%s failed in OVN NB DB'), subnet_id)

        txn_commands = []
        for dhcp_opt in del_subnet_dhcp_opts_list:
            LOG.warning(_LW('Out of sync subnet DHCP options for subnet %s '
                            'found in OVN NB DB which needs to be deleted'),
                        dhcp_opt['external_ids']['subnet_id'])
            if self.mode == SYNC_MODE_REPAIR:
                LOG.debug('Deleting subnet DHCP options for subnet %s ',
                          dhcp_opt['external_ids']['subnet_id'])
                txn_commands.append(self.ovn_api.delete_dhcp_options(
                    dhcp_opt['uuid']))

        if txn_commands:
            with self.ovn_api.transaction(check_error=True) as txn:
                for cmd in txn_commands:
                    txn.add(cmd)
        LOG.debug('OVN-NB Sync DHCP options for Neutron subnets finished')
예제 #20
0
    def sync_networks_ports_and_dhcp_opts(self, ctx):
        LOG.debug('OVN-NB Sync networks, ports and DHCP options started')
        db_networks = {}
        for net in self.core_plugin.get_networks(ctx):
            db_networks[utils.ovn_name(net['id'])] = net

        # Ignore the floating ip ports with device_owner set to
        # constants.DEVICE_OWNER_FLOATINGIP
        db_ports = {
            port['id']: port
            for port in self.core_plugin.get_ports(ctx)
            if not port.get('device_owner', '').startswith(
                constants.DEVICE_OWNER_FLOATINGIP)
        }

        ovn_all_dhcp_options = self.ovn_api.get_all_dhcp_options()
        db_network_cache = dict(db_networks)

        ports_need_sync_dhcp_opts = []
        lswitches = self.ovn_api.get_all_logical_switches_with_ports()
        del_lswitchs_list = []
        del_lports_list = []
        add_provnet_ports_list = []
        for lswitch in lswitches:
            if lswitch['name'] in db_networks:
                for lport in lswitch['ports']:
                    if lport in db_ports:
                        ports_need_sync_dhcp_opts.append(db_ports.pop(lport))
                    else:
                        del_lports_list.append({
                            'port': lport,
                            'lswitch': lswitch['name']
                        })
                db_network = db_networks[lswitch['name']]
                physnet = db_network.get(pnet.PHYSICAL_NETWORK)
                # Updating provider attributes is forbidden by neutron, thus
                # we only need to consider missing provnet-ports in OVN DB.
                if physnet and not lswitch['provnet_port']:
                    add_provnet_ports_list.append({
                        'network': db_network,
                        'lswitch': lswitch['name']
                    })

                del db_networks[lswitch['name']]
            else:
                del_lswitchs_list.append(lswitch)

        for net_id, network in db_networks.items():
            LOG.warning(
                _LW("Network found in Neutron but not in "
                    "OVN DB, network_id=%s"), network['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug('Creating the network %s in OVN NB DB',
                              network['id'])
                    self._create_network_in_ovn(network)
                except RuntimeError:
                    LOG.warning(
                        _LW("Create network in OVN NB failed for"
                            " network %s"), network['id'])

        self._sync_subnet_dhcp_options(ctx, db_network_cache,
                                       ovn_all_dhcp_options['subnets'])

        for port_id, port in db_ports.items():
            LOG.warning(
                _LW("Port found in Neutron but not in OVN "
                    "DB, port_id=%s"), port['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug('Creating the port %s in OVN NB DB', port['id'])
                    self._create_port_in_ovn(ctx, port)
                    if port_id in ovn_all_dhcp_options['ports_v4']:
                        _, lsp_opts = utils.get_lsp_dhcp_opts(
                            port, constants.IP_VERSION_4)
                        if lsp_opts:
                            ovn_all_dhcp_options['ports_v4'].pop(port_id)
                    if port_id in ovn_all_dhcp_options['ports_v6']:
                        _, lsp_opts = utils.get_lsp_dhcp_opts(
                            port, constants.IP_VERSION_6)
                        if lsp_opts:
                            ovn_all_dhcp_options['ports_v6'].pop(port_id)
                except RuntimeError:
                    LOG.warning(
                        _LW("Create port in OVN NB failed for"
                            " port %s"), port['id'])

        with self.ovn_api.transaction(check_error=True) as txn:
            for lswitch in del_lswitchs_list:
                LOG.warning(
                    _LW("Network found in OVN but not in "
                        "Neutron, network_id=%s"), lswitch['name'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Deleting the network %s from OVN NB DB',
                              lswitch['name'])
                    txn.add(
                        self.ovn_api.delete_lswitch(
                            lswitch_name=lswitch['name']))

            for provnet_port_info in add_provnet_ports_list:
                network = provnet_port_info['network']
                LOG.warning(
                    _LW("Provider network found in Neutron but "
                        "provider network port not found in OVN DB, "
                        "network_id=%s"), provnet_port_info['lswitch'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Creating the provnet port %s in OVN NB DB',
                              utils.ovn_provnet_port_name(network['id']))
                    self.ovn_driver.create_provnet_port(
                        txn, network, network.get(pnet.PHYSICAL_NETWORK),
                        network.get(pnet.SEGMENTATION_ID))

            for lport_info in del_lports_list:
                LOG.warning(
                    _LW("Port found in OVN but not in "
                        "Neutron, port_id=%s"), lport_info['port'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Deleting the port %s from OVN NB DB',
                              lport_info['port'])
                    txn.add(
                        self.ovn_api.delete_lswitch_port(
                            lport_name=lport_info['port'],
                            lswitch_name=lport_info['lswitch']))
                    if lport_info['port'] in ovn_all_dhcp_options['ports_v4']:
                        LOG.debug('Deleting port DHCPv4 options for (port %s)',
                                  lport_info['port'])
                        txn.add(
                            self.ovn_api.delete_dhcp_options(
                                ovn_all_dhcp_options['ports_v4'].pop(
                                    lport_info['port'])['uuid']))
                    if lport_info['port'] in ovn_all_dhcp_options['ports_v6']:
                        LOG.debug('Deleting port DHCPv6 options for (port %s)',
                                  lport_info['port'])
                        txn.add(
                            self.ovn_api.delete_dhcp_options(
                                ovn_all_dhcp_options['ports_v6'].pop(
                                    lport_info['port'])['uuid']))

        self._sync_port_dhcp_options(ctx, ports_need_sync_dhcp_opts,
                                     ovn_all_dhcp_options['ports_v4'],
                                     ovn_all_dhcp_options['ports_v6'])
        LOG.debug('OVN-NB Sync networks, ports and DHCP options finished')
예제 #21
0
    def sync_networks_ports_and_dhcp_opts(self, ctx):
        LOG.debug('OVN-NB Sync networks, ports and DHCP options started')
        db_networks = {}
        for net in self.core_plugin.get_networks(ctx):
            db_networks[utils.ovn_name(net['id'])] = net

        db_ports = {}
        for port in self.core_plugin.get_ports(ctx):
            db_ports[port['id']] = port

        ovn_all_dhcp_options = self.ovn_api.get_all_dhcp_options()
        db_network_cache = dict(db_networks)

        ports_need_sync_dhcp_opts = []
        lswitches = self.ovn_api.get_all_logical_switches_with_ports()
        del_lswitchs_list = []
        del_lports_list = []
        for lswitch in lswitches:
            if lswitch['name'] in db_networks:
                for lport in lswitch['ports']:
                    if lport in db_ports:
                        ports_need_sync_dhcp_opts.append(db_ports.pop(lport))
                    else:
                        del_lports_list.append({'port': lport,
                                                'lswitch': lswitch['name']})
                del db_networks[lswitch['name']]
            else:
                del_lswitchs_list.append(lswitch)

        for net_id, network in db_networks.items():
            LOG.warning(_LW("Network found in Neutron but not in "
                            "OVN DB, network_id=%s"), network['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug('Creating the network %s in OVN NB DB',
                              network['id'])
                    self._create_network_in_ovn(network)
                except RuntimeError:
                    LOG.warning(_LW("Create network in OVN NB failed for"
                                    " network %s"), network['id'])

        self._sync_subnet_dhcp_options(
            ctx, db_network_cache, ovn_all_dhcp_options['subnets'])

        for port_id, port in db_ports.items():
            LOG.warning(_LW("Port found in Neutron but not in OVN "
                            "DB, port_id=%s"), port['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug('Creating the port %s in OVN NB DB',
                              port['id'])
                    self._create_port_in_ovn(ctx, port)
                    if port_id in ovn_all_dhcp_options['ports_v4']:
                        _, lsp_opts = utils.get_lsp_dhcp_opts(
                            port, constants.IP_VERSION_4)
                        if lsp_opts:
                            ovn_all_dhcp_options['ports_v4'].pop(port_id)
                    if port_id in ovn_all_dhcp_options['ports_v6']:
                        _, lsp_opts = utils.get_lsp_dhcp_opts(
                            port, constants.IP_VERSION_6)
                        if lsp_opts:
                            ovn_all_dhcp_options['ports_v6'].pop(port_id)
                except RuntimeError:
                    LOG.warning(_LW("Create port in OVN NB failed for"
                                    " port %s"), port['id'])

        with self.ovn_api.transaction(check_error=True) as txn:
            for lswitch in del_lswitchs_list:
                LOG.warning(_LW("Network found in OVN but not in "
                                "Neutron, network_id=%s"), lswitch['name'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Deleting the network %s from OVN NB DB',
                              lswitch['name'])
                    txn.add(self.ovn_api.delete_lswitch(
                        lswitch_name=lswitch['name']))

            for lport_info in del_lports_list:
                LOG.warning(_LW("Port found in OVN but not in "
                                "Neutron, port_id=%s"), lport_info['port'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Deleting the port %s from OVN NB DB',
                              lport_info['port'])
                    txn.add(self.ovn_api.delete_lswitch_port(
                        lport_name=lport_info['port'],
                        lswitch_name=lport_info['lswitch']))
                    if lport_info['port'] in ovn_all_dhcp_options['ports_v4']:
                        LOG.debug('Deleting port DHCPv4 options for (port %s)',
                                  lport_info['port'])
                        txn.add(self.ovn_api.delete_dhcp_options(
                                ovn_all_dhcp_options['ports_v4'].pop(
                                    lport_info['port'])['uuid']))
                    if lport_info['port'] in ovn_all_dhcp_options['ports_v6']:
                        LOG.debug('Deleting port DHCPv6 options for (port %s)',
                                  lport_info['port'])
                        txn.add(self.ovn_api.delete_dhcp_options(
                                ovn_all_dhcp_options['ports_v6'].pop(
                                    lport_info['port'])['uuid']))

        self._sync_port_dhcp_options(ctx, ports_need_sync_dhcp_opts,
                                     ovn_all_dhcp_options['ports_v4'],
                                     ovn_all_dhcp_options['ports_v6'])
        LOG.debug('OVN-NB Sync networks, ports and DHCP options finished')
예제 #22
0
    def sync_acls(self, ctx):
        """Sync ACLs between neutron and NB.

        @param ctx: neutron context
        @type  ctx: object of type neutron.context.Context
        @var   db_ports: List of ports from neutron DB
        @var   neutron_acls: neutron dictionary of port
               vs list-of-acls
        @var   nb_acls: NB dictionary of port
               vs list-of-acls
        @var   subnet_cache: cache for subnets
        @return: Nothing
        """
        LOG.debug('ACL-SYNC: started @ %s' % str(datetime.now()))

        db_ports = {}
        for port in self.core_plugin.get_ports(ctx):
            db_ports[port['id']] = port

        sg_cache = {}
        subnet_cache = {}
        neutron_acls = {}
        for port_id, port in six.iteritems(db_ports):
            if port['security_groups']:
                acl_list = acl_utils.add_acls(self.core_plugin, ctx, port,
                                              sg_cache, subnet_cache)
                if port_id in neutron_acls:
                    neutron_acls[port_id].extend(acl_list)
                else:
                    neutron_acls[port_id] = acl_list

        nb_acls = self.get_acls(ctx)

        self.remove_common_acls(neutron_acls, nb_acls)

        num_acls_to_add = \
            len(list(itertools.chain(*six.itervalues(neutron_acls))))
        num_acls_to_remove = \
            len(list(itertools.chain(*six.itervalues(nb_acls))))
        if 0 != num_acls_to_add or 0 != num_acls_to_remove:
            LOG.warning(
                _LW('ACLs-to-be-added %(add)d '
                    'ACLs-to-be-removed %(remove)d'), {
                        'add': num_acls_to_add,
                        'remove': num_acls_to_remove
                    })

        if self.mode == SYNC_MODE_REPAIR:
            with self.ovn_api.transaction(check_error=True) as txn:
                for acla in list(
                        itertools.chain(*six.itervalues(neutron_acls))):
                    LOG.warning(
                        _LW('ACL found in Neutron but not in '
                            'OVN DB for port %s'), acla['lport'])
                    txn.add(self.ovn_api.add_acl(**acla))

            # TODO(rtheis): Each delete must be done in a separate
            # transaction until bug 1629099 is fixed. Otherwise, ACLs may
            # not be deleted because of previous row mutations on a logical
            # switch.
            for aclr in list(itertools.chain(*six.itervalues(nb_acls))):
                # Both lswitch and lport aren't needed within the ACL.
                lswitchr = aclr.pop('lswitch').replace('neutron-', '')
                lportr = aclr.pop('lport')
                aclr_dict = {lportr: aclr}
                LOG.warning(
                    _LW('ACLs found in OVN DB but not in '
                        'Neutron for port %s'), lportr)
                self.ovn_api.update_acls(
                    [lswitchr], [lportr],
                    aclr_dict,
                    need_compare=False,
                    is_add_acl=False).execute(check_error=True)

        LOG.debug('ACL-SYNC: finished @ %s' % str(datetime.now()))
예제 #23
0
    def sync_networks_and_ports(self, ctx):
        LOG.debug('OVN-NB Sync networks and ports started')
        db_networks = {}
        for net in self.core_plugin.get_networks(ctx):
            db_networks[utils.ovn_name(net['id'])] = net

        db_ports = {}
        for port in self.core_plugin.get_ports(ctx):
            db_ports[port['id']] = port

        lswitches = self.ovn_api.get_all_logical_switches_with_ports()
        del_lswitchs_list = []
        del_lports_list = []
        for lswitch in lswitches:
            if lswitch['name'] in db_networks:
                for lport in lswitch['ports']:
                    if lport in db_ports:
                        del db_ports[lport]
                    else:
                        del_lports_list.append({'port': lport,
                                                'lswitch': lswitch['name']})
                del db_networks[lswitch['name']]
            else:
                del_lswitchs_list.append(lswitch)

        for net_id, network in db_networks.items():
            LOG.warning(_LW("Network found in Neutron but not in "
                            "OVN DB, network_id=%s"), network['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug('Creating the network %s in OVN NB DB',
                              network['id'])
                    self._create_network_in_ovn(network)
                except RuntimeError:
                    LOG.warning(_LW("Create network in OVN NB failed for"
                                    " network %s"), network['id'])

        for port_id, port in db_ports.items():
            LOG.warning(_LW("Port found in Neutron but not in OVN "
                            "DB, port_id=%s"), port['id'])
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug('Creating the port %s in OVN NB DB',
                              port['id'])
                    self._create_port_in_ovn(ctx, port)
                except RuntimeError:
                    LOG.warning(_LW("Create port in OVN NB failed for"
                                    " port %s"), port['id'])

        with self.ovn_api.transaction(check_error=True) as txn:
            for lswitch in del_lswitchs_list:
                LOG.warning(_LW("Network found in OVN but not in "
                                "Neutron, network_id=%s"), lswitch['name'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Deleting the network %s from OVN NB DB',
                              lswitch['name'])
                    txn.add(self.ovn_api.delete_lswitch(
                        lswitch_name=lswitch['name']))

            for lport_info in del_lports_list:
                LOG.warning(_LW("Port found in OVN but not in "
                                "Neutron, port_id=%s"), lport_info['port'])
                if self.mode == SYNC_MODE_REPAIR:
                    LOG.debug('Deleting the port %s from OVN NB DB',
                              lport_info['port'])
                    txn.add(self.ovn_api.delete_lswitch_port(
                        lport_name=lport_info['port'],
                        lswitch_name=lport_info['lswitch']))
        LOG.debug('OVN-NB Sync networks and ports finished')
예제 #24
0
    def _sync_subnet_dhcp_options(self, ctx, db_networks,
                                  ovn_subnet_dhcp_options):
        if not config.is_ovn_dhcp():
            return

        LOG.debug('OVN-NB Sync DHCP options for Neutron subnets started')

        db_subnets = {}
        filters = {'enable_dhcp': [1]}
        for subnet in self.core_plugin.get_subnets(ctx, filters=filters):
            if subnet['ip_version'] == constants.IP_VERSION_6 and (
                    subnet.get('ipv6_address_mode') == constants.IPV6_SLAAC):
                continue
            db_subnets[subnet['id']] = subnet

        del_subnet_dhcp_opts_list = []
        for subnet_id, ovn_dhcp_opts in ovn_subnet_dhcp_options.items():
            if subnet_id in db_subnets:
                network = db_networks[utils.ovn_name(
                    db_subnets[subnet_id]['network_id'])]
                server_mac = ovn_dhcp_opts['options'].get('server_mac')
                dhcp_options = self.ovn_driver.get_ovn_dhcp_options(
                    db_subnets[subnet_id], network, server_mac=server_mac)
                # Verify that the cidr and options are also in sync.
                if dhcp_options['cidr'] == ovn_dhcp_opts['cidr'] and (
                        dhcp_options['options'] == ovn_dhcp_opts['options']):
                    del db_subnets[subnet_id]
                else:
                    db_subnets[subnet_id]['ovn_dhcp_options'] = dhcp_options
            else:
                del_subnet_dhcp_opts_list.append(ovn_dhcp_opts)

        for subnet_id, subnet in db_subnets.items():
            LOG.warning(
                _LW('DHCP options for subnet %s is present in '
                    'Neutron but out of sync for OVN'), subnet_id)
            if self.mode == SYNC_MODE_REPAIR:
                try:
                    LOG.debug(
                        'Adding/Updating DHCP options for subnet %s in '
                        ' OVN NB DB', subnet_id)
                    network = db_networks[utils.ovn_name(subnet['network_id'])]
                    # ovn_driver.add_subnet_dhcp_options_in_ovn doesn't create
                    # a new row in DHCP_Options if the row already exists.
                    # See commands.AddDHCPOptionsCommand.
                    self.ovn_driver.add_subnet_dhcp_options_in_ovn(
                        subnet, network, subnet.get('ovn_dhcp_options'))
                except RuntimeError:
                    LOG.warning(
                        _LW('Adding/Updating DHCP options for subnet '
                            '%s failed in OVN NB DB'), subnet_id)

        txn_commands = []
        for dhcp_opt in del_subnet_dhcp_opts_list:
            LOG.warning(
                _LW('Out of sync subnet DHCP options for subnet %s '
                    'found in OVN NB DB which needs to be deleted'),
                dhcp_opt['external_ids']['subnet_id'])
            if self.mode == SYNC_MODE_REPAIR:
                LOG.debug('Deleting subnet DHCP options for subnet %s ',
                          dhcp_opt['external_ids']['subnet_id'])
                txn_commands.append(
                    self.ovn_api.delete_dhcp_options(dhcp_opt['uuid']))

        if txn_commands:
            with self.ovn_api.transaction(check_error=True) as txn:
                for cmd in txn_commands:
                    txn.add(cmd)
        LOG.debug('OVN-NB Sync DHCP options for Neutron subnets finished')