def add_subports(self, context, trunk_id, subports): """Add one or more subports to trunk.""" with db_api.autonested_transaction(context.session): trunk = self._get_trunk(context, trunk_id) # Check for basic validation since the request body here is not # automatically validated by the API layer. subports = subports['sub_ports'] subports_validator = rules.SubPortsValidator( self._segmentation_types, subports, trunk['port_id']) subports = subports_validator.validate(context, basic_validation=True) added_subports = [] rules.trunk_can_be_managed(context, trunk) original_trunk = copy.deepcopy(trunk) # NOTE(status_police): the trunk status should transition to # DOWN (and finally in ACTIVE or ERROR), only if it is not in # ERROR status already. A user should attempt to resolve the ERROR # condition before adding more subports to the trunk. Should a # trunk be in DOWN or BUILD state (e.g. when dealing with # multiple concurrent requests), the status is still forced to # DOWN and thus can potentially overwrite an interleaving state # change to ACTIVE. Eventually the driver should bring the status # back to ACTIVE or ERROR. if trunk.status == constants.ERROR_STATUS: raise trunk_exc.TrunkInErrorState(trunk_id=trunk_id) else: trunk.update(status=constants.DOWN_STATUS) for subport in subports: obj = trunk_objects.SubPort( context=context, trunk_id=trunk_id, port_id=subport['port_id'], segmentation_type=subport['segmentation_type'], segmentation_id=subport['segmentation_id']) obj.create() trunk['sub_ports'].append(obj) added_subports.append(obj) payload = callbacks.TrunkPayload(context, trunk_id, current_trunk=trunk, original_trunk=original_trunk, subports=added_subports) if added_subports: registry.notify(resources.SUBPORTS, events.PRECOMMIT_CREATE, self, payload=payload) if added_subports: registry.notify(resources.SUBPORTS, events.AFTER_CREATE, self, payload=payload) return trunk
def _unset_trunk(self, trunk): _vsdclient = self.plugin_driver.vsdclient ctx = n_ctx.get_admin_context() try: subnet_mapping = db.get_subnet_l2dom_by_port_id( ctx.session, trunk.port_id) _vsdclient.delete_trunk(trunk, subnet_mapping) except Exception as ex: LOG.error("Failed to delete trunk: %s", ex) trunk.update(status=t_consts.TRUNK_ERROR_STATUS) raise t_exc.TrunkInErrorState(trunk_id=trunk.id)
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 add_subports(self, context, trunk_id, subports): """Add one or more subports to a trunk.""" LOG.debug("Adding subports %s to trunk %s", subports, trunk_id) trunk = self._get_trunk(context, trunk_id) subports = subports['sub_ports'] subports = self.validate_subports(context, subports, trunk, basic_validation=True) added_subports = [] rules.trunk_can_be_managed(context, trunk) original_trunk = copy.deepcopy(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 added. trunk.update(status=trunk_const.DOWN_STATUS) with db_context_writer.using(context): for subport in subports: subport_obj = trunk_objects.SubPort( context=context, trunk_id=trunk_id, port_id=subport['port_id'], segmentation_type=subport['segmentation_type'], segmentation_id=subport['segmentation_id']) subport_obj.create() trunk['sub_ports'].append(subport_obj) added_subports.append(subport_obj) payload = callbacks.TrunkPayload(context, trunk_id, current_trunk=trunk, original_trunk=original_trunk, subports=added_subports) if added_subports: registry.notify(trunk_const.SUBPORTS, events.PRECOMMIT_CREATE, self, payload=payload) self.send_subport_update_to_etcd(context, trunk) if added_subports: registry.notify(trunk_const.SUBPORTS, events.AFTER_CREATE, 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