Пример #1
0
    def _get_agent_fdb(self, context, segment, port, agent_host):
        if not agent_host:
            return

        network_id = port['network_id']

        session = db_api.get_session()
        agent_active_ports = l2pop_db.get_agent_network_active_port_count(
            session, agent_host, network_id)

        agent = l2pop_db.get_agent_by_host(db_api.get_session(), agent_host)
        if not self._validate_segment(segment, port['id'], agent):
            return

        agent_ip = l2pop_db.get_agent_ip(agent)
        other_fdb_entries = self._get_fdb_entries_template(
            segment, agent_ip, port['network_id'])
        if agent_active_ports == 0:
            # Agent is removing its last activated port in this network,
            # other agents needs to be notified to delete their flooding entry.
            other_fdb_entries[network_id]['ports'][agent_ip].append(
                const.FLOODING_ENTRY)
        # Notify other agents to remove fdb rules for current port
        if (port['device_owner'] != const.DEVICE_OWNER_DVR_INTERFACE
                and not l3_hamode_db.is_ha_router_port(
                    context, port['device_owner'], port['device_id'])):
            fdb_entries = self._get_port_fdb_entries(port)
            other_fdb_entries[network_id]['ports'][agent_ip] += fdb_entries

        return other_fdb_entries
Пример #2
0
 def notify_ha_port_status(self,
                           port_id,
                           rpc_context,
                           status,
                           host,
                           port=None):
     plugin = directory.get_plugin()
     l2pop_driver = plugin.mechanism_manager.mech_drivers.get(
         'l2population')
     if not l2pop_driver:
         return
     if not port:
         port = ml2_db.get_port(rpc_context, port_id)
         if not port:
             return
     is_ha_port = l3_hamode_db.is_ha_router_port(rpc_context,
                                                 port['device_owner'],
                                                 port['device_id'])
     if is_ha_port:
         port_context = plugin.get_bound_port_context(rpc_context, port_id)
         port_context.current['status'] = status
         port_context.current[portbindings.HOST_ID] = host
         if status == n_const.PORT_STATUS_ACTIVE:
             l2pop_driver.obj.update_port_up(port_context)
         else:
             l2pop_driver.obj.update_port_down(port_context)
Пример #3
0
    def _get_agent_fdb(self, segment, port, agent_host):
        if not agent_host:
            return

        network_id = port['network_id']

        session = db_api.get_session()
        agent_active_ports = l2pop_db.get_agent_network_active_port_count(
            session, agent_host, network_id)

        agent = l2pop_db.get_agent_by_host(db_api.get_session(), agent_host)
        if not self._validate_segment(segment, port['id'], agent):
            return

        agent_ip = l2pop_db.get_agent_ip(agent)
        other_fdb_entries = self._get_fdb_entries_template(
            segment, agent_ip, port['network_id'])
        if agent_active_ports == 0:
            # Agent is removing its last activated port in this network,
            # other agents needs to be notified to delete their flooding entry.
            other_fdb_entries[network_id]['ports'][agent_ip].append(
                const.FLOODING_ENTRY)
        # Notify other agents to remove fdb rules for current port
        if (port['device_owner'] != const.DEVICE_OWNER_DVR_INTERFACE and
            not l3_hamode_db.is_ha_router_port(port['device_owner'],
                                               port['device_id'])):
            fdb_entries = self._get_port_fdb_entries(port)
            other_fdb_entries[network_id]['ports'][agent_ip] += fdb_entries

        return other_fdb_entries
Пример #4
0
    def notify_l2pop_port_wiring(self, port_id, rpc_context,
                                 status, host):
        """Notify the L2pop driver that a port has been wired/unwired.

        The L2pop driver uses this notification to broadcast forwarding
        entries to other agents on the same network as the port for port_id.
        """
        plugin = directory.get_plugin()
        l2pop_driver = plugin.mechanism_manager.mech_drivers.get(
                'l2population')
        if not l2pop_driver:
            return
        port_context = plugin.get_bound_port_context(
                rpc_context, port_id)
        if not port_context:
            # port deleted
            return
        port = port_context.current
        if (status == n_const.PORT_STATUS_ACTIVE and
            port[portbindings.HOST_ID] != host and
            not l3_hamode_db.is_ha_router_port(rpc_context,
                                               port['device_owner'],
                                               port['device_id'])):
                # don't setup ACTIVE forwarding entries unless bound to this
                # host or if it's an HA port (which is special-cased in the
                # mech driver)
                return
        port_context.current['status'] = status
        port_context.current[portbindings.HOST_ID] = host
        if status == n_const.PORT_STATUS_ACTIVE:
            l2pop_driver.obj.update_port_up(port_context)
        else:
            l2pop_driver.obj.update_port_down(port_context)
Пример #5
0
    def update_port_up(self, context, agent_restarted=None):
        port = context.current
        agent_host = context.host
        port_context = context._plugin_context
        agent = l2pop_db.get_agent_by_host(port_context, agent_host)
        if not agent:
            LOG.warning("Unable to retrieve active L2 agent on host %s",
                        agent_host)
            return

        network_id = port['network_id']

        agent_active_ports = l2pop_db.get_agent_network_active_port_count(
            port_context, agent_host, network_id)

        agent_ip = l2pop_db.get_agent_ip(agent)
        segment = context.bottom_bound_segment
        if not self._validate_segment(segment, port['id'], agent):
            return
        other_fdb_entries = self._get_fdb_entries_template(
            segment, agent_ip, network_id)
        other_fdb_ports = other_fdb_entries[network_id]['ports']

        # with high concurrency more than 1 port may be activated on an agent
        # at the same time (like VM port + a DVR port) so checking for 1 or 2
        is_first_port = agent_active_ports in (1, 2)
        if agent_restarted is None:
            # Only for backport compatibility, will be removed.
            agent_restarted = self.agent_restarted(context)
        if is_first_port or agent_restarted:
            # First port(s) activated on current agent in this network,
            # we have to provide it with the whole list of fdb entries
            agent_fdb_entries = self._create_agent_fdb(port_context,
                                                       agent,
                                                       segment,
                                                       network_id)

            # And notify other agents to add flooding entry
            other_fdb_ports[agent_ip].append(const.FLOODING_ENTRY)

            if agent_fdb_entries[network_id]['ports'].keys():
                self.L2populationAgentNotify.add_fdb_entries(
                    self.rpc_ctx, agent_fdb_entries, agent_host)

        # Notify other agents to add fdb rule for current port
        if (port['device_owner'] != const.DEVICE_OWNER_DVR_INTERFACE and
            not l3_hamode_db.is_ha_router_port(
                port_context, port['device_owner'], port['device_id'])):
            other_fdb_ports[agent_ip] += self._get_port_fdb_entries(port)

        self.L2populationAgentNotify.add_fdb_entries(self.rpc_ctx,
                                                     other_fdb_entries)
Пример #6
0
    def notify_l2pop_port_wiring(self,
                                 port_id,
                                 rpc_context,
                                 status,
                                 host,
                                 agent_restarted=None):
        """Notify the L2pop driver that a port has been wired/unwired.

        The L2pop driver uses this notification to broadcast forwarding
        entries to other agents on the same network as the port for port_id.
        """
        plugin = directory.get_plugin()
        l2pop_driver = plugin.mechanism_manager.mech_drivers.get(
            'l2population')
        if not l2pop_driver:
            return
        port = ml2_db.get_port(rpc_context, port_id)
        if not port:
            return
        port_context = plugin.get_bound_port_context(rpc_context, port_id,
                                                     host)
        if not port_context:
            # port deleted
            return
        # NOTE: DVR ports are already handled and updated through l2pop
        # and so we don't need to update it again here. But, l2pop did not
        # handle DVR ports while restart neutron-*-agent, we need to handle
        # it here.
        if agent_restarted is None:
            agent_restarted = l2pop_driver.obj.agent_restarted(port_context)
        if (port['device_owner'] == n_const.DEVICE_OWNER_DVR_INTERFACE
                and not agent_restarted):
            return
        port = port_context.current
        if (port['device_owner'] != n_const.DEVICE_OWNER_DVR_INTERFACE
                and status == n_const.PORT_STATUS_ACTIVE
                and port[portbindings.HOST_ID] != host
                and not l3_hamode_db.is_ha_router_port(
                    rpc_context, port['device_owner'], port['device_id'])):
            # don't setup ACTIVE forwarding entries unless bound to this
            # host or if it's an HA or DVR port (which is special-cased in
            # the mech driver)
            return
        port_context.current['status'] = status
        port_context.current[portbindings.HOST_ID] = host
        if status == n_const.PORT_STATUS_ACTIVE:
            l2pop_driver.obj.update_port_up(port_context, agent_restarted)
        else:
            l2pop_driver.obj.update_port_down(port_context)
Пример #7
0
    def delete_port_postcommit(self, context):
        port = context.current
        agent_host = context.host
        plugin_context = context._plugin_context
        fdb_entries = self._get_agent_fdb(
            plugin_context, context.bottom_bound_segment, port, agent_host)
        if fdb_entries and l3_hamode_db.is_ha_router_port(
                plugin_context, port['device_owner'], port['device_id']):
            network_id = port['network_id']
            other_fdb_ports = self._get_ha_port_agents_fdb(
                plugin_context, network_id, port['device_id'])
            fdb_entries[network_id]['ports'] = other_fdb_ports

        self.L2populationAgentNotify.remove_fdb_entries(self.rpc_ctx,
            fdb_entries)
Пример #8
0
    def delete_port_postcommit(self, context):
        port = context.current
        agent_host = context.host
        plugin_context = context._plugin_context
        fdb_entries = self._get_agent_fdb(
            plugin_context, context.bottom_bound_segment, port, agent_host)
        if fdb_entries and l3_hamode_db.is_ha_router_port(
                plugin_context, port['device_owner'], port['device_id']):
            network_id = port['network_id']
            other_fdb_ports = self._get_ha_port_agents_fdb(
                plugin_context, network_id, port['device_id'])
            fdb_entries[network_id]['ports'] = other_fdb_ports

        self.L2populationAgentNotify.remove_fdb_entries(self.rpc_ctx,
            fdb_entries)
Пример #9
0
    def update_port_up(self, context):
        port = context.current
        agent_host = context.host
        session = db_api.get_reader_session()
        port_context = context._plugin_context
        agent = l2pop_db.get_agent_by_host(session, agent_host)
        if not agent:
            LOG.warning(_LW("Unable to retrieve active L2 agent on host %s"),
                        agent_host)
            return

        network_id = port['network_id']

        agent_active_ports = l2pop_db.get_agent_network_active_port_count(
            session, agent_host, network_id)

        agent_ip = l2pop_db.get_agent_ip(agent)
        segment = context.bottom_bound_segment
        if not self._validate_segment(segment, port['id'], agent):
            return
        other_fdb_entries = self._get_fdb_entries_template(
            segment, agent_ip, network_id)
        other_fdb_ports = other_fdb_entries[network_id]['ports']

        if agent_active_ports == 1 or (l2pop_db.get_agent_uptime(agent) <
                                       cfg.CONF.l2pop.agent_boot_time):
            # First port activated on current agent in this network,
            # we have to provide it with the whole list of fdb entries
            agent_fdb_entries = self._create_agent_fdb(session,
                                                       agent,
                                                       segment,
                                                       network_id)

            # And notify other agents to add flooding entry
            other_fdb_ports[agent_ip].append(const.FLOODING_ENTRY)

            if agent_fdb_entries[network_id]['ports'].keys():
                self.L2populationAgentNotify.add_fdb_entries(
                    self.rpc_ctx, agent_fdb_entries, agent_host)

        # Notify other agents to add fdb rule for current port
        if (port['device_owner'] != const.DEVICE_OWNER_DVR_INTERFACE and
            not l3_hamode_db.is_ha_router_port(
                port_context, port['device_owner'], port['device_id'])):
            other_fdb_ports[agent_ip] += self._get_port_fdb_entries(port)

        self.L2populationAgentNotify.add_fdb_entries(self.rpc_ctx,
                                                     other_fdb_entries)
Пример #10
0
    def update_port_up(self, context):
        port = context.current
        agent_host = context.host
        port_context = context._plugin_context
        agent = l2pop_db.get_agent_by_host(port_context, agent_host)
        if not agent:
            LOG.warning("Unable to retrieve active L2 agent on host %s",
                        agent_host)
            return

        network_id = port['network_id']

        agent_active_ports = l2pop_db.get_agent_network_active_port_count(
            port_context, agent_host, network_id)

        agent_ip = l2pop_db.get_agent_ip(agent)
        segment = context.bottom_bound_segment
        if not self._validate_segment(segment, port['id'], agent):
            return
        other_fdb_entries = self._get_fdb_entries_template(
            segment, agent_ip, network_id)
        other_fdb_ports = other_fdb_entries[network_id]['ports']

        if agent_active_ports == 1 or (l2pop_db.get_agent_uptime(agent) <
                                       cfg.CONF.l2pop.agent_boot_time):
            # First port activated on current agent in this network,
            # we have to provide it with the whole list of fdb entries
            agent_fdb_entries = self._create_agent_fdb(port_context,
                                                       agent,
                                                       segment,
                                                       network_id)

            # And notify other agents to add flooding entry
            other_fdb_ports[agent_ip].append(const.FLOODING_ENTRY)

            if agent_fdb_entries[network_id]['ports'].keys():
                self.L2populationAgentNotify.add_fdb_entries(
                    self.rpc_ctx, agent_fdb_entries, agent_host)

        # Notify other agents to add fdb rule for current port
        if (port['device_owner'] != const.DEVICE_OWNER_DVR_INTERFACE and
            not l3_hamode_db.is_ha_router_port(
                port_context, port['device_owner'], port['device_id'])):
            other_fdb_ports[agent_ip] += self._get_port_fdb_entries(port)

        self.L2populationAgentNotify.add_fdb_entries(self.rpc_ctx,
                                                     other_fdb_entries)
Пример #11
0
    def notify_l2pop_port_wiring(self, port_id, rpc_context,
                                 status, host, agent_restarted=None):
        """Notify the L2pop driver that a port has been wired/unwired.

        The L2pop driver uses this notification to broadcast forwarding
        entries to other agents on the same network as the port for port_id.
        """
        plugin = directory.get_plugin()
        l2pop_driver = plugin.mechanism_manager.mech_drivers.get(
                'l2population')
        if not l2pop_driver:
            return
        port = ml2_db.get_port(rpc_context, port_id)
        if not port:
            return
        port_context = plugin.get_bound_port_context(
                rpc_context, port_id, host)
        if not port_context:
            # port deleted
            return
        # NOTE: DVR ports are already handled and updated through l2pop
        # and so we don't need to update it again here. But, l2pop did not
        # handle DVR ports while restart neutron-*-agent, we need to handle
        # it here.
        if agent_restarted is None:
            agent_restarted = l2pop_driver.obj.agent_restarted(port_context)
        if (port['device_owner'] == n_const.DEVICE_OWNER_DVR_INTERFACE and
                not agent_restarted):
            return
        port = port_context.current
        if (port['device_owner'] != n_const.DEVICE_OWNER_DVR_INTERFACE and
                status == n_const.PORT_STATUS_ACTIVE and
                port[portbindings.HOST_ID] != host and
                not l3_hamode_db.is_ha_router_port(rpc_context,
                                                   port['device_owner'],
                                                   port['device_id'])):
            # don't setup ACTIVE forwarding entries unless bound to this
            # host or if it's an HA or DVR port (which is special-cased in
            # the mech driver)
            return
        port_context.current['status'] = status
        port_context.current[portbindings.HOST_ID] = host
        if status == n_const.PORT_STATUS_ACTIVE:
            l2pop_driver.obj.update_port_up(port_context, agent_restarted)
        else:
            l2pop_driver.obj.update_port_down(port_context)
Пример #12
0
 def update_port_postcommit(self, context):
     port = context.current
     orig = context.original
     plugin_context = context._plugin_context
     if l3_hamode_db.is_ha_router_port(plugin_context, port['device_owner'],
                                       port['device_id']):
         return
     diff_ips = self._get_diff_ips(orig, port)
     if diff_ips:
         self._fixed_ips_changed(context, orig, port, diff_ips)
     if port['device_owner'] == const.DEVICE_OWNER_DVR_INTERFACE:
         if context.status == const.PORT_STATUS_ACTIVE:
             self.update_port_up(context)
         if context.status == const.PORT_STATUS_DOWN:
             agent_host = context.host
             fdb_entries = self._get_agent_fdb(
                 plugin_context, context.bottom_bound_segment, port,
                 agent_host)
             self.L2populationAgentNotify.remove_fdb_entries(
                 self.rpc_ctx, fdb_entries)
     elif (context.host != context.original_host and
           context.original_status == const.PORT_STATUS_ACTIVE and
           context.status == const.PORT_STATUS_DOWN):
         # The port has been migrated. Send notification about port
         # removal from old host.
         fdb_entries = self._get_agent_fdb(
             plugin_context, context.original_bottom_bound_segment,
             orig, context.original_host)
         self.L2populationAgentNotify.remove_fdb_entries(
             self.rpc_ctx, fdb_entries)
     elif context.status != context.original_status:
         if context.status == const.PORT_STATUS_ACTIVE:
             self.update_port_up(context)
         elif context.status == const.PORT_STATUS_DOWN:
             fdb_entries = self._get_agent_fdb(
                 plugin_context, context.bottom_bound_segment, port,
                 context.host)
             self.L2populationAgentNotify.remove_fdb_entries(
                 self.rpc_ctx, fdb_entries)
Пример #13
0
 def update_port_postcommit(self, context):
     port = context.current
     orig = context.original
     plugin_context = context._plugin_context
     if l3_hamode_db.is_ha_router_port(plugin_context, port['device_owner'],
                                       port['device_id']):
         return
     diff_ips = self._get_diff_ips(orig, port)
     if diff_ips:
         self._fixed_ips_changed(context, orig, port, diff_ips)
     if port['device_owner'] == const.DEVICE_OWNER_DVR_INTERFACE:
         if context.status == const.PORT_STATUS_ACTIVE:
             self.update_port_up(context)
         if context.status == const.PORT_STATUS_DOWN:
             agent_host = context.host
             fdb_entries = self._get_agent_fdb(
                 plugin_context, context.bottom_bound_segment, port,
                 agent_host)
             self.L2populationAgentNotify.remove_fdb_entries(
                 self.rpc_ctx, fdb_entries)
     elif (context.host != context.original_host and
           context.original_status == const.PORT_STATUS_ACTIVE and
           context.status == const.PORT_STATUS_DOWN):
         # The port has been migrated. Send notification about port
         # removal from old host.
         fdb_entries = self._get_agent_fdb(
             plugin_context, context.original_bottom_bound_segment,
             orig, context.original_host)
         self.L2populationAgentNotify.remove_fdb_entries(
             self.rpc_ctx, fdb_entries)
     elif context.status != context.original_status:
         if context.status == const.PORT_STATUS_ACTIVE:
             self.update_port_up(context)
         elif context.status == const.PORT_STATUS_DOWN:
             fdb_entries = self._get_agent_fdb(
                 plugin_context, context.bottom_bound_segment, port,
                 context.host)
             self.L2populationAgentNotify.remove_fdb_entries(
                 self.rpc_ctx, fdb_entries)
Пример #14
0
 def notify_ha_port_status(self, port_id, rpc_context,
                           status, host, port=None):
     plugin = manager.NeutronManager.get_plugin()
     l2pop_driver = plugin.mechanism_manager.mech_drivers.get(
             'l2population')
     if not l2pop_driver:
         return
     if not port:
         port = ml2_db.get_port(rpc_context.session, port_id)
         if not port:
             return
     is_ha_port = l3_hamode_db.is_ha_router_port(port['device_owner'],
                                                 port['device_id'])
     if is_ha_port:
         port_context = plugin.get_bound_port_context(
                 rpc_context, port_id)
         port_context.current['status'] = status
         port_context.current[portbindings.HOST_ID] = host
         if status == n_const.PORT_STATUS_ACTIVE:
             l2pop_driver.obj.update_port_up(port_context)
         else:
             l2pop_driver.obj.update_port_down(port_context)