def dvr_deletens_if_no_port(self, context, port_id):
        """Delete the DVR namespace if no dvr serviced port exists."""
        admin_context = context.elevated()
        router_ids = self.get_dvr_routers_by_portid(admin_context, port_id)
        port_host = ml2_db.get_port_binding_host(port_id)
        if not router_ids:
            LOG.debug(
                "No namespaces available for this DVR port %(port)s " "on host %(host)s",
                {"port": port_id, "host": port_host},
            )
            return []
        removed_router_info = []
        for router_id in router_ids:
            subnet_ids = self.get_subnet_ids_on_router(admin_context, router_id)
            port_exists_on_subnet = False
            for subnet in subnet_ids:
                if self.check_ports_active_on_host_and_subnet(admin_context, port_host, port_id, subnet):
                    port_exists_on_subnet = True
                    break

            if port_exists_on_subnet:
                continue
            filter_rtr = {"device_id": [router_id], "device_owner": [q_const.DEVICE_OWNER_DVR_INTERFACE]}
            int_ports = self._core_plugin.get_ports(admin_context, filters=filter_rtr)
            for prt in int_ports:
                dvr_binding = ml2_db.get_dvr_port_binding_by_host(context.session, prt["id"], port_host)
                if dvr_binding:
                    # unbind this port from router
                    dvr_binding["router_id"] = None
                    dvr_binding.update(dvr_binding)
            agent = self._get_agent_by_type_and_host(context, q_const.AGENT_TYPE_L3, port_host)
            info = {"router_id": router_id, "host": port_host, "agent_id": str(agent.id)}
            removed_router_info.append(info)
            LOG.debug("Router namespace %(router_id)s on host %(host)s " "to be deleted", info)
        return removed_router_info
예제 #2
0
    def update_dvr_port_binding(self, context, id, port):
        attrs = port['port']
        need_port_update_notify = False

        host = attrs and attrs.get(portbindings.HOST_ID)
        host_set = attributes.is_attr_set(host)

        if not host_set:
            LOG.error(_("No Host supplied to bind DVR Port %s"), id)
            return

        binding = db.get_dvr_port_binding_by_host(port_id=id, host=host,
                                                  session=None)
        if ((not binding) or
                (binding.vif_type == portbindings.VIF_TYPE_BINDING_FAILED)):
            session = context.session
            with session.begin(subtransactions=True):
                if (not binding):
                    binding = db.ensure_dvr_port_binding(session, id,
                                                         host,
                                                         attrs['device_id'])
                orig_port = super(Ml2Plugin, self).get_port(context, id)
                network = self.get_network(context, orig_port['network_id'])
                mech_context = driver_context.PortContext(self,
                    context, orig_port, network,
                    original_port=orig_port, binding=binding)
                need_port_update_notify |= self._process_dvr_port_binding(
                    mech_context, context, attrs)
예제 #3
0
    def dvr_deletens_if_no_port(self, context, port_id, port_host=None):
        """Delete the DVR namespace if no dvr serviced port exists."""
        admin_context = context.elevated()
        router_ids = self.get_dvr_routers_by_portid(admin_context, port_id)
        if not port_host:
            port_host = ml2_db.get_port_binding_host(admin_context.session,
                                                     port_id)
            if not port_host:
                LOG.debug('Host name not found for port %s', port_id)
                return []

        if not router_ids:
            LOG.debug(
                'No namespaces available for this DVR port %(port)s '
                'on host %(host)s', {
                    'port': port_id,
                    'host': port_host
                })
            return []
        removed_router_info = []
        for router_id in router_ids:
            subnet_ids = self.get_subnet_ids_on_router(admin_context,
                                                       router_id)
            port_exists_on_subnet = False
            for subnet in subnet_ids:
                if self.check_ports_on_host_and_subnet(admin_context,
                                                       port_host, port_id,
                                                       subnet):
                    port_exists_on_subnet = True
                    break

            if port_exists_on_subnet:
                continue
            filter_rtr = {
                'device_id': [router_id],
                'device_owner': [n_const.DEVICE_OWNER_DVR_INTERFACE]
            }
            int_ports = self._core_plugin.get_ports(admin_context,
                                                    filters=filter_rtr)
            for port in int_ports:
                dvr_binding = (ml2_db.get_dvr_port_binding_by_host(
                    context.session, port['id'], port_host))
                if dvr_binding:
                    # unbind this port from router
                    dvr_binding['router_id'] = None
                    dvr_binding.update(dvr_binding)
            agent = self._get_agent_by_type_and_host(context,
                                                     n_const.AGENT_TYPE_L3,
                                                     port_host)
            info = {
                'router_id': router_id,
                'host': port_host,
                'agent_id': str(agent.id)
            }
            removed_router_info.append(info)
            LOG.debug(
                'Router namespace %(router_id)s on host %(host)s '
                'to be deleted', info)
        return removed_router_info
예제 #4
0
 def test_get_dvr_port_binding_by_host_not_found(self):
     port = ml2_db.get_dvr_port_binding_by_host(
         self.ctx.session, 'foo_port_id', 'foo_host_id')
     self.assertIsNone(port)
예제 #5
0
    def get_dvr_routers_to_remove(self, context, deleted_port):
        """Returns info about which routers should be removed

        In case dvr serviceable port was deleted we need to check
        if any dvr routers should be removed from l3 agent on port's host
        """
        if not n_utils.is_dvr_serviced(deleted_port['device_owner']):
            return []

        admin_context = context.elevated()
        port_host = deleted_port[portbindings.HOST_ID]
        subnet_ids = [ip['subnet_id'] for ip in deleted_port['fixed_ips']]
        router_ids = self.get_dvr_routers_by_subnet_ids(
            admin_context, subnet_ids)

        if not router_ids:
            LOG.debug(
                'No DVR routers for this DVR port %(port)s '
                'on host %(host)s', {
                    'port': deleted_port['id'],
                    'host': port_host
                })
            return []
        agent = self._get_agent_by_type_and_host(context,
                                                 n_const.AGENT_TYPE_L3,
                                                 port_host)
        removed_router_info = []
        for router_id in router_ids:
            snat_binding = context.session.query(
                l3agent_sch_db.RouterL3AgentBinding).filter_by(
                    router_id=router_id).filter_by(
                        l3_agent_id=agent.id).first()
            if snat_binding:
                # not removing from the agent hosting SNAT for the router
                continue
            subnet_ids = self.get_subnet_ids_on_router(admin_context,
                                                       router_id)
            if self.check_dvr_serviceable_ports_on_host(
                    admin_context, port_host, subnet_ids):
                continue
            filter_rtr = {
                'device_id': [router_id],
                'device_owner': [n_const.DEVICE_OWNER_DVR_INTERFACE]
            }
            int_ports = self._core_plugin.get_ports(admin_context,
                                                    filters=filter_rtr)
            for port in int_ports:
                dvr_binding = (ml2_db.get_dvr_port_binding_by_host(
                    context.session, port['id'], port_host))
                if dvr_binding:
                    # unbind this port from router
                    dvr_binding['router_id'] = None
                    dvr_binding.update(dvr_binding)

            info = {
                'router_id': router_id,
                'host': port_host,
                'agent_id': str(agent.id)
            }
            removed_router_info.append(info)
            LOG.debug('Router %(router_id)s on host %(host)s to be deleted',
                      info)
        return removed_router_info
예제 #6
0
 def get_dvr_port_binding_by_host(self, context, port_id, host):
     session = context.session
     return db.get_dvr_port_binding_by_host(port_id, host,
                                            session)
예제 #7
0
    def update_port_status(self, context, port_id, status, host=None):
        updated = False
        session = context.session
        # REVISIT: Serialize this operation with a semaphore to prevent
        # undesired eventlet yields leading to 'lock wait timeout' errors
        with contextlib.nested(lockutils.lock('db-access'),
                               session.begin(subtransactions=True)):
            port = db.get_port(session, port_id)
            if not port:
                LOG.warning(_("Port %(port)s updated up by agent not found"),
                            {'port': port_id})
                return False
            if port['device_owner'] == const.DEVICE_OWNER_DVR_INTERFACE:
                binding = db.get_dvr_port_binding_by_host(port_id=port['id'],
                                                          host=host,
                                                          session=session)
                if not binding:
                    LOG.error(_("Binding info for port %s not found"),
                              port_id)
                    return False
                binding['status'] = status
                binding.update(binding)

        # binding already updated
        with contextlib.nested(lockutils.lock('db-access'),
                               session.begin(subtransactions=True)):
            port = db.get_port(session, port_id)
            if not port:
                LOG.warning(_("Port %(port)s updated up by agent not found"),
                            {'port': port_id})
                return False
            if port['device_owner'] == const.DEVICE_OWNER_DVR_INTERFACE:
                original_port = self._make_port_dict(port)
                network = self.get_network(context,
                                           original_port['network_id'])
                port.status = self._generate_dvr_port_status(session,
                                                             port['id'])
                updated_port = self._make_port_dict(port)
                mech_context = (driver_context.PortContext(
                    self, context, updated_port, network,
                    original_port=original_port,
                    binding=binding))
                self.mechanism_manager.update_port_precommit(mech_context)
                updated = True
            elif port.status != status:
                original_port = self._make_port_dict(port)
                port.status = status
                updated_port = self._make_port_dict(port)
                network = self.get_network(context,
                                           original_port['network_id'])
                mech_context = driver_context.PortContext(
                    self, context, updated_port, network,
                    original_port=original_port)
                self.mechanism_manager.update_port_precommit(mech_context)
                updated = True

        if updated:
            self.mechanism_manager.update_port_postcommit(mech_context)

        if port['device_owner'] == const.DEVICE_OWNER_DVR_INTERFACE:
            self._check_and_delete_dvr_port_binding(mech_context, context)

        return True
예제 #8
0
    def dvr_deletens_if_no_port(self, context, port_id, port_host=None):
        """Delete the DVR namespace if no dvr serviced port exists."""
        admin_context = context.elevated()
        router_ids = self.get_dvr_routers_by_portid(admin_context, port_id)
        if not port_host:
            port_host = ml2_db.get_port_binding_host(admin_context.session,
                                                     port_id)
            if not port_host:
                LOG.debug('Host name not found for port %s', port_id)
                return []

        if not router_ids:
            LOG.debug(
                'No namespaces available for this DVR port %(port)s '
                'on host %(host)s', {
                    'port': port_id,
                    'host': port_host
                })
            return []
        agent = self._get_agent_by_type_and_host(context,
                                                 n_const.AGENT_TYPE_L3,
                                                 port_host)
        removed_router_info = []
        for router_id in router_ids:
            snat_binding = context.session.query(
                CentralizedSnatL3AgentBinding).filter_by(
                    router_id=router_id).filter_by(
                        l3_agent_id=agent.id).first()
            if snat_binding:
                # not removing from the agent hosting SNAT for the router
                continue
            subnet_ids = self.get_subnet_ids_on_router(admin_context,
                                                       router_id)
            if self.check_dvr_serviceable_ports_on_host(admin_context,
                                                        port_host,
                                                        subnet_ids,
                                                        except_port=port_id):
                continue
            filter_rtr = {
                'device_id': [router_id],
                'device_owner': [n_const.DEVICE_OWNER_DVR_INTERFACE]
            }
            int_ports = self._core_plugin.get_ports(admin_context,
                                                    filters=filter_rtr)
            for port in int_ports:
                dvr_binding = (ml2_db.get_dvr_port_binding_by_host(
                    context.session, port['id'], port_host))
                if dvr_binding:
                    # unbind this port from router
                    dvr_binding['router_id'] = None
                    dvr_binding.update(dvr_binding)

            info = {
                'router_id': router_id,
                'host': port_host,
                'agent_id': str(agent.id)
            }
            removed_router_info.append(info)
            LOG.debug(
                'Router namespace %(router_id)s on host %(host)s '
                'to be deleted', info)
        return removed_router_info