def delete_network(self, context, net_id): """Delete a network. :param context: neutron api request context :param id: UUID representing the network to delete. :returns: None :raises: exceptions.NetworkInUse :raises: exceptions.NetworkNotFound :raises: RemoteRestError """ LOG.debug(_("NeutronRestProxyV2: delete_network() called")) # Validate args orig_net = super(NeutronRestProxyV2, self).get_network(context, net_id) filter = {'network_id': [net_id]} ports = self.get_ports(context, filters=filter) # check if there are any tenant owned ports in-use auto_delete_port_owners = db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS only_auto_del = all(p['device_owner'] in auto_delete_port_owners for p in ports) if not only_auto_del: raise exceptions.NetworkInUse(net_id=net_id) with context.session.begin(subtransactions=True): ret_val = super(NeutronRestProxyV2, self).delete_network(context, net_id) self._send_delete_network(orig_net, context) return ret_val
def delete_network(self, context, id): """Delete network and packet_filters associated with the network. Delete network entry from DB and OFC. Then delete packet_filters associated with the network. If the network is the last resource of the tenant, delete unnessary ofc_tenant. """ ports = self.get_ports(context, filters={'network_id': [id]}) # check if there are any tenant owned ports in-use; # consider ports owned by floating ips as auto_delete as if there are # no other tenant owned ports, those floating ips are disassociated # and will be auto deleted with self._process_l3_delete() only_auto_del = all( p['device_owner'] in db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS or p['device_owner'] == const.DEVICE_OWNER_FLOATINGIP for p in ports) if not only_auto_del: raise n_exc.NetworkInUse(net_id=id) self._process_l3_delete(context, id) self.l2mgr.delete_network(context, id, ports) super(NECPluginV2Impl, self).delete_network(context, id)
def delete_network(self, context, id): """Delete network. Deletes the network with the specified network identifier belonging to the specified tenant. """ LOG.debug(_("delete_network() called")) #We first need to check if there are any ports on this network with context.session.begin(): network = self._get_network(context, id) filter = {'network_id': [id]} ports = self.get_ports(context, filters=filter) # check if there are any tenant owned ports in-use prefix = db_base_plugin_v2.AGENT_OWNER_PREFIX only_svc = all(p['device_owner'].startswith(prefix) for p in ports) if not only_svc: raise exc.NetworkInUse(net_id=id) context.session.close() #Network does not have any ports, we can proceed to delete network = self._get_network(context, id) kwargs = {const.NETWORK: network, const.BASE_PLUGIN_REF: self} self._invoke_device_plugins(self._func_name(), [context, id, kwargs]) return super(PluginV2, self).delete_network(context, id)
def delete_network(self, context, id): """Delete network and packet_filters associated with the network. Delete network entry from DB and OFC. Then delete packet_filters associated with the network. If the network is the last resource of the tenant, delete unnessary ofc_tenant. """ LOG.debug(_("NECPluginV2.delete_network() called, id=%s ."), id) net = super(NECPluginV2, self).get_network(context, id) tenant_id = net['tenant_id'] ports = self.get_ports(context, filters={'network_id': [id]}) # check if there are any tenant owned ports in-use only_auto_del = all( p['device_owner'] in db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS for p in ports) if not only_auto_del: raise q_exc.NetworkInUse(net_id=id) # Make sure auto-delete ports on OFC are deleted. _error_ports = [] for port in ports: port = self.deactivate_port(context, port) if port['status'] == OperationalStatus.ERROR: _error_ports.append(port['id']) if _error_ports: reason = (_("Failed to delete port(s)=%s from OFC.") % ','.join(_error_ports)) raise nexc.OFCException(reason=reason) # delete all packet_filters of the network if self.packet_filter_enabled: filters = dict(network_id=[id]) pfs = self.get_packet_filters(context, filters=filters) for pf in pfs: self.delete_packet_filter(context, pf['id']) try: # 'net' parameter is required to lookup old OFC mapping self.ofc.delete_ofc_network(context, id, net) except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc: reason = _("delete_network() failed due to %s") % exc LOG.error(reason) self._update_resource_status(context, "network", net['id'], OperationalStatus.ERROR) raise super(NECPluginV2, self).delete_network(context, id) # delete unnessary ofc_tenant filters = dict(tenant_id=[tenant_id]) nets = super(NECPluginV2, self).get_networks(context, filters=filters) if not nets: try: self.ofc.delete_ofc_tenant(context, tenant_id) except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc: reason = _("delete_ofc_tenant() failed due to %s") % exc LOG.warn(reason)
def delete_network(self, context, id): # REVISIT(rkukura) The super(Ml2Plugin, self).delete_network() # function is not used because it auto-deletes ports and # subnets from the DB without invoking the derived class's # delete_port() or delete_subnet(), preventing mechanism # drivers from being called. This approach should be revisited # when the API layer is reworked during icehouse. session = context.session while True: with session.begin(subtransactions=True): filter = {'network_id': [id]} # Get ports to auto-delete. ports = self.get_ports(context, filters=filter) only_auto_del = all(p['device_owner'] in db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS for p in ports) if not only_auto_del: raise exc.NetworkInUse(net_id=id) # Get subnets to auto-delete. subnets = self.get_subnets(context, filters=filter) if not ports or subnets: network = self.get_network(context, id) mech_context = driver_context.NetworkContext( self, context, network) self.mechanism_manager.delete_network_precommit( mech_context) record = self._get_network(context, id) context.session.delete(record) for segment in mech_context.network_segments: self.type_manager.release_segment(session, segment) # The segment records are deleted via cascade from the # network record, so explicit removal is not necessary. break for port in ports: self.delete_port(context, port['id']) for subnet in subnets: self.delete_subnet(context, subnet['id']) try: self.mechanism_manager.delete_network_postcommit(mech_context) except ml2_exc.MechanismDriverError: # TODO(apech) - One or more mechanism driver failed to # delete the network. Ideally we'd notify the caller of # the fact that an error occurred. pass self.notifier.network_delete(context, id)
def delete_network(self, context, id): """Delete network and packet_filters associated with the network. Delete network entry from DB and OFC. Then delete packet_filters associated with the network. If the network is the last resource of the tenant, delete unnessary ofc_tenant. """ LOG.debug(_("NECPluginV2.delete_network() called, id=%s ."), id) net_db = self._get_network(context, id) tenant_id = net_db['tenant_id'] ports = self.get_ports(context, filters={'network_id': [id]}) # check if there are any tenant owned ports in-use; # consider ports owned by floating ips as auto_delete as if there are # no other tenant owned ports, those floating ips are disassociated # and will be auto deleted with self._process_l3_delete() only_auto_del = all( p['device_owner'] in db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS or p['device_owner'] == const.DEVICE_OWNER_FLOATINGIP for p in ports) if not only_auto_del: raise n_exc.NetworkInUse(net_id=id) self._process_l3_delete(context, id) # Make sure auto-delete ports on OFC are deleted. # If an error occurs during port deletion, # delete_network will be aborted. for port in [ p for p in ports if p['device_owner'] in db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS ]: port = self.deactivate_port(context, port) # delete all packet_filters of the network from the controller for pf in net_db.packetfilters: self.delete_packet_filter(context, pf['id']) if self.ofc.exists_ofc_network(context, id): try: self.ofc.delete_ofc_network(context, id, net_db) except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: with excutils.save_and_reraise_exception(): reason = _("delete_network() failed due to %s") % exc LOG.error(reason) self._update_resource_status(context, "network", net_db['id'], const.NET_STATUS_ERROR) super(NECPluginV2, self).delete_network(context, id) self._cleanup_ofc_tenant(context, tenant_id)
def delete_network(context, id): """Delete a network. : param context: neutron api request context : param id: UUID representing the network to delete. """ LOG.info("delete_network %s for tenant %s" % (id, context.tenant_id)) net = db_api.network_find(context, id=id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=id) if net.ports: raise exceptions.NetworkInUse(net_id=id) net_driver.delete_network(context, id) for subnet in net["subnets"]: subnets._delete_subnet(context, subnet) db_api.network_delete(context, net)
def delete_network(self, context, id): """Delete network and packet_filters associated with the network. Delete network entry from DB and OFC. Then delete packet_filters associated with the network. If the network is the last resource of the tenant, delete unnessary ofc_tenant. """ LOG.debug(_("NECPluginV2.delete_network() called, id=%s ."), id) net_db = self._get_network(context, id) tenant_id = net_db['tenant_id'] ports = self.get_ports(context, filters={'network_id': [id]}) # check if there are any tenant owned ports in-use only_auto_del = all( p['device_owner'] in db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS for p in ports) if not only_auto_del: raise n_exc.NetworkInUse(net_id=id) # Make sure auto-delete ports on OFC are deleted. _error_ports = [] for port in ports: port = self.deactivate_port(context, port) if port['status'] == const.PORT_STATUS_ERROR: _error_ports.append(port['id']) if _error_ports: reason = (_("Failed to delete port(s)=%s from OFC.") % ','.join(_error_ports)) raise nexc.OFCException(reason=reason) # delete all packet_filters of the network from the controller for pf in net_db.packetfilters: self.delete_packet_filter(context, pf['id']) try: self.ofc.delete_ofc_network(context, id, net_db) except (nexc.OFCException, nexc.OFCMappingNotFound) as exc: reason = _("delete_network() failed due to %s") % exc LOG.error(reason) self._update_resource_status(context, "network", net_db['id'], const.NET_STATUS_ERROR) raise super(NECPluginV2, self).delete_network(context, id) self._cleanup_ofc_tenant(context, tenant_id)
def delete_network(self, context, id): with context.session.begin(subtransactions=True): network = self._get_network(context, id) context.session.query( models_v2.Port).filter_by(network_id=id).filter( models_v2.Port.device_owner.in_(AUTO_DELETE_PORT_OWNERS) ).delete(synchronize_session=False) port_in_use = context.session.query( models_v2.Port).filter_by(network_id=id).first() if port_in_use: raise n_exc.NetworkInUse(net_id=id) # clean up subnets subnets = self._get_subnets_by_network(context, id) for subnet in subnets: self.delete_subnet(context, subnet['id']) context.session.delete(network)
def _validate_update_network(self, context, id, network): req_data = network['network'] is_external_set = req_data.get(external_net.EXTERNAL) if not attributes.is_attr_set(is_external_set): return (None, None) neutron_net = self.get_network(context, id) if neutron_net.get(external_net.EXTERNAL) == is_external_set: return (None, None) subnet = self._validate_nuage_sharedresource(context, 'network', id) if subnet and not is_external_set: msg = _('External network with subnets can not be ' 'changed to non-external network') raise nuage_exc.OperationNotSupported(msg=msg) if is_external_set: # Check if there are vm ports attached to this network # If there are, then updating the network is not allowed ports = self.get_ports(context, filters={'network_id': [id]}) for p in ports: if p['device_owner'].startswith( constants.NOVA_PORT_OWNER_PREF): raise n_exc.NetworkInUse(net_id=id) return (is_external_set, subnet)
def delete_network(context, id): """Delete a network. : param context: neutron api request context : param id: UUID representing the network to delete. """ LOG.info("delete_network %s for tenant %s" % (id, context.tenant_id)) with context.session.begin(): net = db_api.network_find(context, None, None, None, False, id=id, scope=db_api.ONE) if not net: raise exceptions.NetworkNotFound(net_id=id) if net.ports: raise exceptions.NetworkInUse(net_id=id) net_driver = registry.DRIVER_REGISTRY.get_driver(net["network_plugin"]) net_driver.delete_network(context, id) for subnet in net["subnets"]: subnets._delete_subnet(context, subnet) db_api.network_delete(context, net)
def delete_network(self, context, id): # REVISIT(rkukura) The super(Ml2Plugin, self).delete_network() # function is not used because it auto-deletes ports and # subnets from the DB without invoking the derived class's # delete_port() or delete_subnet(), preventing mechanism # drivers from being called. This approach should be revisited # when the API layer is reworked during icehouse. LOG.debug(_("Deleting network %s"), id) session = context.session while True: try: with session.begin(subtransactions=True): # Get ports to auto-delete. ports = (session.query(models_v2.Port). enable_eagerloads(False). filter_by(network_id=id). with_lockmode('update').all()) LOG.debug(_("Ports to auto-delete: %s"), ports) only_auto_del = all(p.device_owner in db_base_plugin_v2. AUTO_DELETE_PORT_OWNERS for p in ports) if not only_auto_del: LOG.debug(_("Tenant-owned ports exist")) raise exc.NetworkInUse(net_id=id) # Get subnets to auto-delete. subnets = (session.query(models_v2.Subnet). enable_eagerloads(False). filter_by(network_id=id). with_lockmode('update').all()) LOG.debug(_("Subnets to auto-delete: %s"), subnets) if not (ports or subnets): network = self.get_network(context, id) mech_context = driver_context.NetworkContext(self, context, network) self.mechanism_manager.delete_network_precommit( mech_context) record = self._get_network(context, id) LOG.debug(_("Deleting network record %s"), record) session.delete(record) for segment in mech_context.network_segments: self.type_manager.release_segment(session, segment) # The segment records are deleted via cascade from the # network record, so explicit removal is not necessary. LOG.debug(_("Committing transaction")) break except os_db.exception.DBError as e: if isinstance(e.inner_exception, sql_exc.IntegrityError): msg = _("A concurrent port creation has occurred") LOG.warning(msg) continue else: raise for port in ports: try: self.delete_port(context, port.id) except Exception: LOG.exception(_("Exception auto-deleting port %s"), port.id) raise for subnet in subnets: try: self.delete_subnet(context, subnet.id) except Exception: LOG.exception(_("Exception auto-deleting subnet %s"), subnet.id) raise try: self.mechanism_manager.delete_network_postcommit(mech_context) except ml2_exc.MechanismDriverError: # TODO(apech) - One or more mechanism driver failed to # delete the network. Ideally we'd notify the caller of # the fact that an error occurred. LOG.error(_("mechanism_manager.delete_network_postcommit failed")) self.notifier.network_delete(context, id)
def test_ha_network_is_not_deleted_if_network_in_use(self): self._test_ha_network_is_not_deleted_raise_exception( n_exc.NetworkInUse(net_id="foo_net_id"))
def delete_network(self, context, id): # REVISIT(rkukura) The super(Ml2Plugin, self).delete_network() # function is not used because it auto-deletes ports and # subnets from the DB without invoking the derived class's # delete_port() or delete_subnet(), preventing mechanism # drivers from being called. This approach should be revisited # when the API layer is reworked during icehouse. LOG.debug("Deleting network %s", id) session = context.session attempt = 0 while True: attempt += 1 LOG.info(i18n._LI("Attempt %(attempt)s to delete network %(net)s"), { 'attempt': attempt, 'net': id }) if attempt > 100: raise InfiniteLoopError() try: # REVISIT: Serialize this operation with a semaphore # to prevent deadlock waiting to acquire a DB lock # held by another thread in the same process, leading # to 'lock wait timeout' errors. # # Process L3 first, since, depending on the L3 plugin, it may # involve sending RPC notifications, and/or calling delete_port # on this plugin. # Additionally, a rollback may not be enough to undo the # deletion of a floating IP with certain L3 backends. self._process_l3_delete(context, id) # Using query().with_lockmode isn't necessary. Foreign-key # constraints prevent deletion if concurrent creation happens. with session.begin(subtransactions=True): # Get ports to auto-delete. ports = (session.query( models_v2.Port).enable_eagerloads(False).filter_by( network_id=id).all()) LOG.debug("Ports to auto-delete: %s", ports) only_auto_del = all( p.device_owner in db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS for p in ports) if not only_auto_del: LOG.debug("Tenant-owned ports exist") raise exc.NetworkInUse(net_id=id) # Get subnets to auto-delete. subnets = (session.query( models_v2.Subnet).enable_eagerloads(False).filter_by( network_id=id).all()) LOG.debug("Subnets to auto-delete: %s", subnets) if not (ports or subnets): network = self.get_network(context, id) mech_context = driver_context.NetworkContext( self, context, network) self.mechanism_manager.delete_network_precommit( mech_context) self.type_manager.release_network_segments(session, id) record = self._get_network(context, id) LOG.debug("Deleting network record %s", record) session.delete(record) # The segment records are deleted via cascade from the # network record, so explicit removal is not necessary. LOG.debug("Committing transaction") break port_ids = [port.id for port in ports] subnet_ids = [subnet.id for subnet in subnets] except os_db_exception.DBError as e: with excutils.save_and_reraise_exception() as ctxt: if isinstance(e.inner_exception, sql_exc.IntegrityError): ctxt.reraise = False LOG.warning( i18n._LW("A concurrent port creation has " "occurred")) continue LOG.info(i18n._LI("Auto-deleting ports %(ports)s for network %(net)s"), { 'ports': ports, 'net': id }) self._delete_ports(context, port_ids) LOG.info( i18n._LI("Auto-deleting subnets %(subnets)s for network " "%(net)s"), { 'subnets': subnets, 'net': id }) self._delete_subnets(context, subnet_ids) try: self.mechanism_manager.delete_network_postcommit(mech_context) except ml2_exc.MechanismDriverError: # TODO(apech) - One or more mechanism driver failed to # delete the network. Ideally we'd notify the caller of # the fact that an error occurred. LOG.error( i18n._LE("mechanism_manager.delete_network_postcommit" " failed")) self.notifier.network_delete(context, id)