def remove_subports(self, context, trunk_id, subports): """Remove one or more subports from trunk.""" subports = subports['sub_ports'] with db_api.CONTEXT_WRITER.using(context): trunk = self._get_trunk(context, trunk_id) original_trunk = copy.deepcopy(trunk) rules.trunk_can_be_managed(context, trunk) subports_validator = rules.SubPortsValidator( self._segmentation_types, subports) # the subports are being removed, therefore we do not need to # enforce any specific trunk rules, other than basic validation # of the request body. subports = subports_validator.validate( context, basic_validation=True, trunk_validation=False) current_subports = {p.port_id: p for p in trunk.sub_ports} removed_subports = [] for subport in subports: subport_obj = current_subports.pop(subport['port_id'], None) if not subport_obj: raise trunk_exc.SubPortNotFound(trunk_id=trunk_id, port_id=subport['port_id']) subport_obj.delete() removed_subports.append(subport_obj) del trunk.sub_ports[:] trunk.sub_ports.extend(current_subports.values()) # NOTE(status_police): the trunk status should transition to # DOWN irrespective of the status in which it is in to allow # the user to resolve potential conflicts due to prior add_subports # operations. # Should a trunk be in DOWN or BUILD state (e.g. when dealing # with multiple concurrent requests), the status is still forced # to DOWN. See add_subports() for more details. trunk.update(status=constants.TRUNK_DOWN_STATUS) payload = events.DBEventPayload(context, resource_id=trunk_id, states=(original_trunk, trunk,), metadata={ 'subports': removed_subports }) if removed_subports: registry.publish(resources.SUBPORTS, events.PRECOMMIT_DELETE, self, payload=payload) if removed_subports: payload = events.DBEventPayload(context, resource_id=trunk_id, states=(original_trunk, trunk,), metadata={ 'subports': removed_subports }) registry.publish( resources.SUBPORTS, events.AFTER_DELETE, self, payload=payload) return trunk
def remove_subports(self, context, trunk_id, subports): """Remove one or more subports from the trunk.""" LOG.debug("Removing subports %s from trunk %s", subports, trunk_id) trunk = self._get_trunk(context, trunk_id) original_trunk = copy.deepcopy(trunk) subports = subports['sub_ports'] subports = self.validate_subports(context, subports, trunk, basic_validation=True, trunk_validation=False) removed_subports = [] rules.trunk_can_be_managed(context, trunk) # The trunk should not be in the ERROR_STATUS if trunk.status == trunk_const.ERROR_STATUS: raise trunk_exc.TrunkInErrorState(trunk_id=trunk_id) else: # The trunk will transition to DOWN and subsequently to ACTIVE # when a subport is removed. trunk.update(status=trunk_const.DOWN_STATUS) current_subports = {p.port_id: p for p in trunk.sub_ports} # Ensure that all sub-ports to be removed are actually present for subport in subports: if subport['port_id'] not in current_subports: raise trunk_exc.SubPortNotFound(trunk_id=trunk_id, port_id=subport['port_id']) with neutron_db_api.context_manager.writer.using(context): for subport in subports: subport_obj = current_subports.pop(subport['port_id']) subport_obj.delete() removed_subports.append(subport_obj) if removed_subports: del trunk.sub_ports[:] trunk.sub_ports.extend(current_subports.values()) payload = callbacks.TrunkPayload(context, trunk_id, current_trunk=trunk, original_trunk=original_trunk, subports=removed_subports) registry.notify(trunk_const.SUBPORTS, events.PRECOMMIT_DELETE, self, payload=payload) self.send_subport_update_to_etcd(context, trunk) if removed_subports: registry.notify(trunk_const.SUBPORTS, events.AFTER_DELETE, self, payload=payload) return trunk
def remove_subports(self, context, trunk_id, subports): """Remove one or more subports from trunk.""" subports = subports['sub_ports'] with db_api.autonested_transaction(context.session): trunk = self._get_trunk(context, trunk_id) original_trunk = copy.deepcopy(trunk) rules.trunk_can_be_managed(context, trunk) subports_validator = rules.SubPortsValidator( self._segmentation_types, subports) # the subports are being removed, therefore we do not need to # enforce any specific trunk rules, other than basic validation # of the request body. subports = subports_validator.validate(context, basic_validation=True, trunk_validation=False) current_subports = {p.port_id: p for p in trunk.sub_ports} removed_subports = [] for subport in subports: subport_obj = current_subports.pop(subport['port_id'], None) if not subport_obj: raise trunk_exc.SubPortNotFound(trunk_id=trunk_id, port_id=subport['port_id']) subport_obj.delete() removed_subports.append(subport_obj) del trunk.sub_ports[:] trunk.sub_ports.extend(current_subports.values()) payload = callbacks.TrunkPayload(context, trunk_id, current_trunk=trunk, original_trunk=original_trunk, subports=removed_subports) if removed_subports: registry.notify(constants.SUBPORTS, events.PRECOMMIT_DELETE, self, payload=payload) if removed_subports: registry.notify(constants.SUBPORTS, events.AFTER_DELETE, self, payload=payload) return trunk
def remove_subports(self, context, trunk_id, subports): """Remove one or more subports from the trunk. param: subports: {u'sub_ports': [{u'port_id': u'fa006724-dbca-4e7f-bb6b-ec70162eb681'}]} """ LOG.debug("Removing subports %s from trunk %s", subports, trunk_id) trunk = self._get_trunk(context, trunk_id) original_trunk = copy.deepcopy(trunk) # key-value data corresponding to original trunk original_trunk_data = self._get_trunk_data(trunk) # ID's of subports to remove subports_to_remove = [pid['port_id'] for pid in subports['sub_ports']] LOG.debug('trunk subports to remove: %s', subports_to_remove) subports = subports['sub_ports'] subports = self.validate_subports(context, subports, trunk, basic_validation=True, trunk_validation=False) removed_subports = [] rules.trunk_can_be_managed(context, trunk) # The trunk should not be in the ERROR_STATUS if trunk.status == trunk_const.ERROR_STATUS: raise trunk_exc.TrunkInErrorState(trunk_id=trunk_id) else: # The trunk will transition to DOWN and subsequently to ACTIVE # when a subport is removed. trunk.update(status=trunk_const.DOWN_STATUS) current_subports = {p.port_id: p for p in trunk.sub_ports} # Ensure that all sub-ports to be removed are actually present for subport in subports: if subport['port_id'] not in current_subports: raise trunk_exc.SubPortNotFound(trunk_id=trunk_id, port_id=subport['port_id']) with db_context_writer.using(context): for subport in subports: subport_obj = current_subports.pop(subport['port_id']) subport_obj.delete() removed_subports.append(subport_obj) if removed_subports: del trunk.sub_ports[:] trunk.sub_ports.extend(current_subports.values()) payload = callbacks.TrunkPayload(context, trunk_id, current_trunk=trunk, original_trunk=original_trunk, subports=removed_subports) registry.notify(trunk_const.SUBPORTS, events.PRECOMMIT_DELETE, self, payload=payload) self.send_subport_update_to_etcd(context, trunk) # Subport data to remove subports = [ subport for subport in original_trunk_data['sub_ports'] if subport['port_id'] in subports_to_remove ] original_trunk_data['sub_ports'] = subports trunk_data = self.add_data_to_subports(context, original_trunk_data) # Remove all remote-group subport keys from etcd LOG.debug('trunk data with subports to remove: %s', trunk_data) for subport_data in trunk_data['sub_ports']: self._write_remote_group_journal(context, subport_data, remove_key=True) if removed_subports: registry.notify(trunk_const.SUBPORTS, events.AFTER_DELETE, self, payload=payload) return trunk