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
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)
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
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)
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
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)
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
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