Search in sources :

Example 26 with FlowProcessingException

use of org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException in project open-kilda by telstra.

the class ValidateYFlowAction method performWithResponse.

@Override
protected Optional<Message> performWithResponse(State from, State to, Event event, YFlowRerouteContext context, YFlowRerouteFsm stateMachine) {
    boolean isOperationAllowed = featureTogglesRepository.getOrDefault().getModifyYFlowEnabled();
    if (!isOperationAllowed) {
        throw new FlowProcessingException(ErrorType.NOT_PERMITTED, "Y-flow reroute feature is disabled");
    }
    YFlowRerouteRequest request = context.getRerouteRequest();
    String yFlowId = request.getYFlowId();
    Set<IslEndpoint> affectedIsls = new HashSet<>(Optional.ofNullable(request.getAffectedIsl()).orElse(emptySet()));
    dashboardLogger.onYFlowReroute(yFlowId, affectedIsls, request.isForce());
    stateMachine.setAffectedIsls(affectedIsls);
    stateMachine.setRerouteReason(request.getReason());
    stateMachine.setForceReroute(request.isForce());
    stateMachine.setIgnoreBandwidth(request.isIgnoreBandwidth());
    YFlow yFlow = transactionManager.doInTransaction(() -> {
        YFlow result = yFlowRepository.findById(yFlowId).orElseThrow(() -> new FlowProcessingException(ErrorType.NOT_FOUND, format("Y-flow %s not found", yFlowId)));
        if (result.getStatus() == FlowStatus.IN_PROGRESS) {
            throw new FlowProcessingException(ErrorType.REQUEST_INVALID, format("Y-flow %s is in progress now", yFlowId));
        }
        // Keep it, just in case we have to revert it.
        stateMachine.setOriginalYFlowStatus(result.getStatus());
        result.setStatus(FlowStatus.IN_PROGRESS);
        return result;
    });
    Collection<Flow> subFlows = yFlow.getSubFlows().stream().map(YSubFlow::getFlow).collect(Collectors.toList());
    Flow mainAffinitySubFlow = subFlows.stream().filter(flow -> flow.getFlowId().equals(flow.getAffinityGroupId())).findFirst().orElseThrow(() -> new FlowProcessingException(ErrorType.DATA_INVALID, format("Main affinity sub-flow of the y-flow %s not found", yFlowId)));
    stateMachine.setMainAffinityFlowId(mainAffinitySubFlow.getFlowId());
    boolean mainAffinitySubFlowIsAffected = isFlowAffected(mainAffinitySubFlow, affectedIsls);
    Set<String> affectedFlowIds = subFlows.stream().filter(flow -> mainAffinitySubFlowIsAffected || isFlowAffected(flow, affectedIsls)).map(Flow::getFlowId).collect(Collectors.toSet());
    stateMachine.setTargetSubFlowIds(affectedFlowIds);
    stateMachine.saveNewEventToHistory("Y-flow was validated successfully", FlowEventData.Event.REROUTE);
    return Optional.empty();
}
Also used : YFlow(org.openkilda.model.YFlow) IslEndpoint(org.openkilda.model.IslEndpoint) FlowProcessingException(org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException) YFlowRerouteRequest(org.openkilda.messaging.command.yflow.YFlowRerouteRequest) HashSet(java.util.HashSet) Flow(org.openkilda.model.Flow) YFlow(org.openkilda.model.YFlow) YSubFlow(org.openkilda.model.YSubFlow)

Example 27 with FlowProcessingException

use of org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException in project open-kilda by telstra.

the class AllocateYFlowResourcesAction method perform.

@Override
public void perform(S from, S to, E event, C context, T stateMachine) {
    try {
        String yFlowId = stateMachine.getYFlowId();
        YFlowResources newResources;
        // This could be a retry.
        if (stateMachine.getNewResources() != null) {
            newResources = stateMachine.getNewResources();
        } else {
            newResources = new YFlowResources();
            stateMachine.setNewResources(newResources);
        }
        YFlow yFlow = getYFlow(yFlowId);
        SwitchId sharedEndpoint = yFlow.getSharedEndpoint().getSwitchId();
        if (newResources.getSharedEndpointResources() == null) {
            EndpointResources sharedEndpointResources = allocateMeterAsEndpointResources(yFlowId, sharedEndpoint, yFlow.getMaximumBandwidth());
            newResources.setSharedEndpointResources(sharedEndpointResources);
            stateMachine.saveActionToHistory("A new meter was allocated for the y-flow shared endpoint", format("A new meter %s / %s was allocated", sharedEndpointResources.getMeterId(), sharedEndpointResources.getEndpoint()));
        }
        if (newResources.getMainPathYPointResources() == null) {
            List<FlowPath> subFlowsReversePaths = new ArrayList<>();
            yFlow.getSubFlows().forEach(subFlow -> {
                Flow flow = subFlow.getFlow();
                FlowPath path = flow.getReversePath();
                if (path == null) {
                    throw new FlowProcessingException(ErrorType.INTERNAL_ERROR, format("Missing a reverse path for %s sub-flow", flow.getFlowId()));
                } else {
                    subFlowsReversePaths.add(path);
                }
            });
            EndpointResources yPointResources = allocateYPointResources(yFlowId, sharedEndpoint, yFlow.getMaximumBandwidth(), subFlowsReversePaths.toArray(new FlowPath[0]));
            newResources.setMainPathYPointResources(yPointResources);
            stateMachine.saveActionToHistory("A new meter was allocated for the y-flow y-point", format("A new meter %s / %s was allocated", yPointResources.getMeterId(), yPointResources.getEndpoint()));
        }
        if (yFlow.isAllocateProtectedPath() && newResources.getProtectedPathYPointResources() == null) {
            List<FlowPath> subFlowsReversePaths = new ArrayList<>();
            yFlow.getSubFlows().forEach(subFlow -> {
                Flow flow = subFlow.getFlow();
                FlowPath path = flow.getProtectedReversePath();
                if (path == null) {
                    if (flow.getStatus() == FlowStatus.UP) {
                        throw new FlowProcessingException(ErrorType.INTERNAL_ERROR, format("Missing a protected path for %s sub-flow", flow.getFlowId()));
                    } else {
                        log.warn("Sub-flow {} has no expected protected path and status {}", flow.getFlowId(), flow.getStatus());
                    }
                } else {
                    subFlowsReversePaths.add(path);
                }
            });
            if (subFlowsReversePaths.size() > 1) {
                EndpointResources yPointResources = allocateYPointResources(yFlowId, sharedEndpoint, yFlow.getMaximumBandwidth(), subFlowsReversePaths.toArray(new FlowPath[0]));
                newResources.setProtectedPathYPointResources(yPointResources);
                stateMachine.saveActionToHistory("A new meter was allocated for the y-flow protected path y-point", format("A new meter %s / %s was allocated", yPointResources.getMeterId(), yPointResources.getEndpoint()));
            } else {
                stateMachine.saveActionToHistory("Skip meter allocation for the y-flow protected path y-point", "Y-flow protected path y-point can't be found - sub-flow(s) lacks a protected path");
            }
        }
        transactionManager.doInTransaction(() -> {
            YFlow yFlowToUpdate = getYFlow(yFlowId);
            yFlowToUpdate.setYPoint(newResources.getMainPathYPointResources().getEndpoint());
            yFlowToUpdate.setMeterId(newResources.getMainPathYPointResources().getMeterId());
            if (newResources.getProtectedPathYPointResources() != null) {
                yFlowToUpdate.setProtectedPathYPoint(newResources.getProtectedPathYPointResources().getEndpoint());
                yFlowToUpdate.setProtectedPathMeterId(newResources.getProtectedPathYPointResources().getMeterId());
            } else {
                yFlowToUpdate.setProtectedPathYPoint(null);
                yFlowToUpdate.setProtectedPathMeterId(null);
            }
            yFlowToUpdate.setSharedEndpointMeterId(newResources.getSharedEndpointResources().getMeterId());
        });
        notifyStats(stateMachine, newResources);
    } catch (ResourceAllocationException ex) {
        String errorMessage = format("Failed to allocate y-flow resources. %s", ex.getMessage());
        stateMachine.saveErrorToHistory(errorMessage, ex);
        stateMachine.fireError(errorMessage);
    }
}
Also used : YFlow(org.openkilda.model.YFlow) YFlowResources(org.openkilda.wfm.topology.flowhs.model.yflow.YFlowResources) FlowProcessingException(org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException) ArrayList(java.util.ArrayList) SwitchId(org.openkilda.model.SwitchId) EndpointResources(org.openkilda.wfm.topology.flowhs.model.yflow.YFlowResources.EndpointResources) FlowPath(org.openkilda.model.FlowPath) ResourceAllocationException(org.openkilda.wfm.share.flow.resources.ResourceAllocationException) Flow(org.openkilda.model.Flow) YFlow(org.openkilda.model.YFlow)

Example 28 with FlowProcessingException

use of org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException in project open-kilda by telstra.

the class FlowValidateAction method performWithResponse.

@Override
protected Optional<Message> performWithResponse(State from, State to, Event event, FlowCreateContext context, FlowCreateFsm stateMachine) throws FlowProcessingException {
    RequestedFlow request = context.getTargetFlow();
    dashboardLogger.onFlowCreate(request.getFlowId(), request.getSrcSwitch(), request.getSrcPort(), request.getSrcVlan(), request.getDestSwitch(), request.getDestPort(), request.getDestVlan(), request.getDiverseFlowId(), request.getBandwidth());
    boolean isOperationAllowed = featureTogglesRepository.getOrDefault().getCreateFlowEnabled();
    if (!isOperationAllowed) {
        throw new FlowProcessingException(ErrorType.NOT_PERMITTED, "Flow create feature is disabled");
    }
    if (flowRepository.exists(request.getFlowId())) {
        throw new FlowProcessingException(ErrorType.ALREADY_EXISTS, format("Flow %s already exists", request.getFlowId()));
    }
    if (yFlowRepository.exists(request.getFlowId())) {
        throw new FlowProcessingException(ErrorType.ALREADY_EXISTS, format("Y-flow %s already exists", request.getFlowId()));
    }
    try {
        flowValidator.validate(request);
    } catch (InvalidFlowException e) {
        throw new FlowProcessingException(e.getType(), e.getMessage(), e);
    } catch (UnavailableFlowEndpointException e) {
        throw new FlowProcessingException(ErrorType.DATA_INVALID, e.getMessage(), e);
    }
    stateMachine.setTargetFlow(request);
    if (event != Event.RETRY) {
        stateMachine.saveNewEventToHistory("Flow was validated successfully", FlowEventData.Event.CREATE);
    } else {
        // no need to save a new event into DB, it should already exist there.
        stateMachine.saveActionToHistory("Flow was validated successfully");
    }
    return Optional.empty();
}
Also used : UnavailableFlowEndpointException(org.openkilda.wfm.topology.flowhs.validation.UnavailableFlowEndpointException) FlowProcessingException(org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException) RequestedFlow(org.openkilda.wfm.topology.flowhs.model.RequestedFlow) InvalidFlowException(org.openkilda.wfm.topology.flowhs.validation.InvalidFlowException)

Example 29 with FlowProcessingException

use of org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException in project open-kilda by telstra.

the class YFlowUpdateService method handlePartialUpdateRequest.

/**
 * Handles request for y-flow patch updating.
 *
 * @param key command identifier.
 * @param request request data.
 */
public void handlePartialUpdateRequest(@NonNull String key, @NonNull CommandContext commandContext, @NonNull YFlowPartialUpdateRequest request) throws DuplicateKeyException {
    YFlowRequest target;
    if (request.getYFlowId() != null) {
        YFlow yFlow = yFlowRepository.findById(request.getYFlowId()).orElse(null);
        target = YFlowRequestMapper.INSTANCE.toYFlowRequest(yFlow);
    } else {
        throw new FlowProcessingException(ErrorType.REQUEST_INVALID, "Need to specify the y-flow id");
    }
    if (target == null) {
        throw new FlowProcessingException(ErrorType.NOT_FOUND, format("Y-flow was not found by the specified y-flow id: %s", request.getYFlowId()));
    }
    if (request.getSharedEndpoint() != null) {
        if (target.getSharedEndpoint() == null) {
            target.setSharedEndpoint(new FlowEndpoint(request.getSharedEndpoint().getSwitchId(), request.getSharedEndpoint().getPortNumber()));
        } else {
            SwitchId switchId = Optional.ofNullable(request.getSharedEndpoint().getSwitchId()).orElse(target.getSharedEndpoint().getSwitchId());
            int portNumber = Optional.ofNullable(request.getSharedEndpoint().getPortNumber()).orElse(target.getSharedEndpoint().getPortNumber());
            target.setSharedEndpoint(new FlowEndpoint(switchId, portNumber));
        }
    }
    Optional.ofNullable(request.getMaximumBandwidth()).ifPresent(target::setMaximumBandwidth);
    Optional.ofNullable(request.getPathComputationStrategy()).ifPresent(target::setPathComputationStrategy);
    Optional.ofNullable(request.getEncapsulationType()).ifPresent(target::setEncapsulationType);
    Optional.ofNullable(request.getMaxLatency()).ifPresent(target::setMaxLatency);
    Optional.ofNullable(request.getMaxLatencyTier2()).ifPresent(target::setMaxLatencyTier2);
    Optional.ofNullable(request.getIgnoreBandwidth()).ifPresent(target::setIgnoreBandwidth);
    Optional.ofNullable(request.getPeriodicPings()).ifPresent(target::setPeriodicPings);
    Optional.ofNullable(request.getPinned()).ifPresent(target::setPinned);
    Optional.ofNullable(request.getPriority()).ifPresent(target::setPriority);
    Optional.ofNullable(request.getStrictBandwidth()).ifPresent(target::setStrictBandwidth);
    Optional.ofNullable(request.getDescription()).ifPresent(target::setDescription);
    Optional.ofNullable(request.getAllocateProtectedPath()).ifPresent(target::setAllocateProtectedPath);
    Optional.ofNullable(request.getDiverseFlowId()).ifPresent(target::setDiverseFlowId);
    if (request.getSubFlows() != null && !request.getSubFlows().isEmpty()) {
        Map<String, SubFlowDto> stringSubFlowDtoMap;
        if (target.getSubFlows() != null) {
            stringSubFlowDtoMap = target.getSubFlows().stream().collect(Collectors.toMap(SubFlowDto::getFlowId, Function.identity()));
        } else {
            throw new FlowProcessingException(ErrorType.INTERNAL_ERROR, format("Sub-flows for y-flow %s not found", target.getYFlowId()));
        }
        List<SubFlowDto> subFlows = new ArrayList<>();
        for (SubFlowPartialUpdateDto subFlowPartialUpdate : request.getSubFlows()) {
            SubFlowDto subFlow = stringSubFlowDtoMap.get(subFlowPartialUpdate.getFlowId());
            if (subFlow != null) {
                if (subFlowPartialUpdate.getEndpoint() != null) {
                    if (subFlow.getEndpoint() == null) {
                        subFlow.setEndpoint(new FlowEndpoint(subFlowPartialUpdate.getEndpoint().getSwitchId(), subFlowPartialUpdate.getEndpoint().getPortNumber(), subFlowPartialUpdate.getEndpoint().getVlanId(), subFlowPartialUpdate.getEndpoint().getInnerVlanId()));
                    } else {
                        SwitchId switchId = Optional.ofNullable(subFlowPartialUpdate.getEndpoint().getSwitchId()).orElse(subFlow.getEndpoint().getSwitchId());
                        int portNumber = Optional.ofNullable(subFlowPartialUpdate.getEndpoint().getPortNumber()).orElse(subFlow.getEndpoint().getPortNumber());
                        int vlanId = Optional.ofNullable(subFlowPartialUpdate.getEndpoint().getVlanId()).orElse(subFlow.getEndpoint().getOuterVlanId());
                        int innerVlanId = Optional.ofNullable(subFlowPartialUpdate.getEndpoint().getInnerVlanId()).orElse(subFlow.getEndpoint().getInnerVlanId());
                        subFlow.setEndpoint(new FlowEndpoint(switchId, portNumber, vlanId, innerVlanId));
                    }
                }
                if (subFlowPartialUpdate.getSharedEndpoint() != null) {
                    if (subFlow.getSharedEndpoint() == null) {
                        subFlow.setSharedEndpoint(new SubFlowSharedEndpointEncapsulation(subFlowPartialUpdate.getSharedEndpoint().getVlanId(), subFlowPartialUpdate.getSharedEndpoint().getInnerVlanId()));
                    } else {
                        int vlanId = Optional.ofNullable(subFlowPartialUpdate.getSharedEndpoint().getVlanId()).orElse(subFlow.getSharedEndpoint().getVlanId());
                        int innerVlanId = Optional.ofNullable(subFlowPartialUpdate.getSharedEndpoint().getInnerVlanId()).orElse(subFlow.getSharedEndpoint().getInnerVlanId());
                        subFlow.setSharedEndpoint(new SubFlowSharedEndpointEncapsulation(vlanId, innerVlanId));
                    }
                }
                Optional.ofNullable(subFlowPartialUpdate.getDescription()).ifPresent(subFlow::setDescription);
                subFlows.add(subFlow);
            } else {
                throw new FlowProcessingException(ErrorType.REQUEST_INVALID, format("There is no sub-flows with sub-flow id: %s", subFlowPartialUpdate.getFlowId()));
            }
        }
        target.setSubFlows(subFlows);
    }
    target.setType(Type.UPDATE);
    handleRequest(key, commandContext, target);
}
Also used : YFlow(org.openkilda.model.YFlow) FlowProcessingException(org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException) ArrayList(java.util.ArrayList) SwitchId(org.openkilda.model.SwitchId) SubFlowSharedEndpointEncapsulation(org.openkilda.messaging.command.yflow.SubFlowSharedEndpointEncapsulation) SubFlowDto(org.openkilda.messaging.command.yflow.SubFlowDto) YFlowRequest(org.openkilda.messaging.command.yflow.YFlowRequest) FlowEndpoint(org.openkilda.model.FlowEndpoint) FlowEndpoint(org.openkilda.model.FlowEndpoint) SubFlowPartialUpdateDto(org.openkilda.messaging.command.yflow.SubFlowPartialUpdateDto)

Example 30 with FlowProcessingException

use of org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException in project open-kilda by telstra.

the class UpdateFlowAction method getOrCreateDiverseFlowGroupId.

private String getOrCreateDiverseFlowGroupId(String diverseFlowId) throws FlowProcessingException {
    log.debug("Getting flow diverse group for flow with id {}", diverseFlowId);
    String flowId = yFlowRepository.findById(diverseFlowId).map(Stream::of).orElseGet(Stream::empty).map(YFlow::getSubFlows).flatMap(Collection::stream).map(YSubFlow::getFlow).filter(flow -> flow.getFlowId().equals(flow.getAffinityGroupId())).map(Flow::getFlowId).findFirst().orElse(diverseFlowId);
    return flowRepository.getOrCreateDiverseFlowGroupId(flowId).orElseThrow(() -> new FlowProcessingException(ErrorType.NOT_FOUND, format("Flow %s not found", flowId)));
}
Also used : YFlow(org.openkilda.model.YFlow) Message(org.openkilda.messaging.Message) HistoryMapper(org.openkilda.wfm.share.mappers.HistoryMapper) NbTrackableWithHistorySupportAction(org.openkilda.wfm.topology.flowhs.fsm.common.actions.NbTrackableWithHistorySupportAction) Flow(org.openkilda.model.Flow) EndpointUpdate(org.openkilda.wfm.topology.flowhs.fsm.update.FlowUpdateFsm.EndpointUpdate) Objects(org.apache.storm.shade.com.google.common.base.Objects) YFlow(org.openkilda.model.YFlow) DumpType(org.openkilda.wfm.share.history.model.FlowDumpData.DumpType) PersistenceManager(org.openkilda.persistence.PersistenceManager) DetectConnectedDevices(org.openkilda.model.DetectConnectedDevices) Switch(org.openkilda.model.Switch) YSubFlow(org.openkilda.model.YSubFlow) ErrorType(org.openkilda.messaging.error.ErrorType) FlowLoopOperation(org.openkilda.wfm.topology.flowhs.fsm.update.FlowUpdateFsm.FlowLoopOperation) Collection(java.util.Collection) FlowUpdateFsm(org.openkilda.wfm.topology.flowhs.fsm.update.FlowUpdateFsm) State(org.openkilda.wfm.topology.flowhs.fsm.update.FlowUpdateFsm.State) RequestedFlowMapper(org.openkilda.wfm.topology.flowhs.mapper.RequestedFlowMapper) String.format(java.lang.String.format) Event(org.openkilda.wfm.topology.flowhs.fsm.update.FlowUpdateFsm.Event) YFlowRepository(org.openkilda.persistence.repositories.YFlowRepository) RepositoryFactory(org.openkilda.persistence.repositories.RepositoryFactory) FlowProcessingException(org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException) Slf4j(lombok.extern.slf4j.Slf4j) Stream(java.util.stream.Stream) FlowUpdateContext(org.openkilda.wfm.topology.flowhs.fsm.update.FlowUpdateContext) FlowDumpData(org.openkilda.wfm.share.history.model.FlowDumpData) Optional(java.util.Optional) RequestedFlow(org.openkilda.wfm.topology.flowhs.model.RequestedFlow) SwitchRepository(org.openkilda.persistence.repositories.SwitchRepository) FlowProcessingException(org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException) Stream(java.util.stream.Stream) YSubFlow(org.openkilda.model.YSubFlow) Flow(org.openkilda.model.Flow) YFlow(org.openkilda.model.YFlow) YSubFlow(org.openkilda.model.YSubFlow) RequestedFlow(org.openkilda.wfm.topology.flowhs.model.RequestedFlow)

Aggregations

FlowProcessingException (org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException)40 Flow (org.openkilda.model.Flow)24 YFlow (org.openkilda.model.YFlow)20 YSubFlow (org.openkilda.model.YSubFlow)11 SwitchId (org.openkilda.model.SwitchId)7 CommandContext (org.openkilda.wfm.CommandContext)7 FlowEndpoint (org.openkilda.model.FlowEndpoint)6 PathId (org.openkilda.model.PathId)6 RequestedFlow (org.openkilda.wfm.topology.flowhs.model.RequestedFlow)6 InvalidFlowException (org.openkilda.wfm.topology.flowhs.validation.InvalidFlowException)6 UnavailableFlowEndpointException (org.openkilda.wfm.topology.flowhs.validation.UnavailableFlowEndpointException)6 ArrayList (java.util.ArrayList)5 YFlowRequest (org.openkilda.messaging.command.yflow.YFlowRequest)5 Switch (org.openkilda.model.Switch)5 SubFlowDto (org.openkilda.messaging.command.yflow.SubFlowDto)4 SubFlowSharedEndpointEncapsulation (org.openkilda.messaging.command.yflow.SubFlowSharedEndpointEncapsulation)4 FlowMirrorPath (org.openkilda.model.FlowMirrorPath)4 FlowMirrorPoints (org.openkilda.model.FlowMirrorPoints)4 FlowPath (org.openkilda.model.FlowPath)4 InfoMessage (org.openkilda.messaging.info.InfoMessage)3