Search in sources :

Example 1 with RerouteError

use of org.openkilda.messaging.info.reroute.error.RerouteError in project open-kilda by telstra.

the class RerouteQueueService method processRerouteResult.

/**
 * Process reroute result. Check fail reason, decide if retry is needed and schedule it if yes.
 *
 * @param rerouteResultInfoData reroute result
 * @param correlationId correlation id
 */
public void processRerouteResult(RerouteResultInfoData rerouteResultInfoData, String correlationId) {
    String flowId = rerouteResultInfoData.getFlowId();
    RerouteQueue rerouteQueue = getRerouteQueue(flowId);
    FlowThrottlingData inProgress = rerouteQueue.getInProgress();
    if (inProgress == null || !Objects.equals(inProgress.getCorrelationId(), correlationId)) {
        log.error("Skipped unexpected reroute result for flow {} with correlation id {}.", flowId, correlationId);
        return;
    }
    carrier.cancelTimeout(correlationId);
    if (rerouteResultInfoData.isSuccess()) {
        FlowThrottlingData toSend = rerouteQueue.processPending();
        sendRerouteRequest(flowId, toSend);
    } else {
        RerouteError rerouteError = rerouteResultInfoData.getRerouteError();
        if (isRetryRequired(flowId, rerouteError, rerouteResultInfoData.isYFlow())) {
            injectRetry(flowId, rerouteQueue, rerouteError instanceof NoPathFoundError);
        } else {
            FlowThrottlingData toSend = rerouteQueue.processPending();
            sendRerouteRequest(flowId, toSend);
        }
    }
}
Also used : NoPathFoundError(org.openkilda.messaging.info.reroute.error.NoPathFoundError) FlowThrottlingData(org.openkilda.wfm.topology.reroute.model.FlowThrottlingData) RerouteQueue(org.openkilda.wfm.topology.reroute.model.RerouteQueue) RerouteError(org.openkilda.messaging.info.reroute.error.RerouteError)

Example 2 with RerouteError

use of org.openkilda.messaging.info.reroute.error.RerouteError in project open-kilda by telstra.

the class YFlowRerouteServiceTest method shouldFailIfNoResourcesAvailable.

@Test
public void shouldFailIfNoResourcesAvailable() throws UnroutableFlowException, RecoverableException, ResourceAllocationException, DuplicateKeyException {
    // given
    YFlowRequest createYFlowRequest = createYFlow();
    YFlowRerouteRequest request = new YFlowRerouteRequest(createYFlowRequest.getYFlowId(), "reason");
    preparePathComputationForReroute("test_flow_1", buildFirstSubFlowPathPairWithNewTransit());
    preparePathComputationForReroute("test_flow_2", buildSecondSubFlowPathPairWithNewTransit());
    prepareYPointComputation(SWITCH_SHARED, SWITCH_FIRST_EP, SWITCH_SECOND_EP, SWITCH_NEW_TRANSIT);
    doThrow(new ResourceAllocationException(injectedErrorMessage)).when(flowResourcesManager).allocateMeter(eq("test_successful_yflow"), eq(SWITCH_NEW_TRANSIT));
    // when
    processRerouteRequestAndSpeakerCommands(request);
    verifyYFlowStatus(request.getYFlowId(), FlowStatus.UP);
    verify(flowResourcesManager, times(METER_ALLOCATION_RETRIES_LIMIT + 1)).allocateMeter(eq("test_successful_yflow"), eq(SWITCH_NEW_TRANSIT));
    verify(yFlowRerouteHubCarrier).sendYFlowRerouteResultStatus(eq(createYFlowRequest.getYFlowId()), eq(new RerouteError("Failed to allocate y-flow resources. Unit-test injected failure")), anyString());
}
Also used : YFlowRerouteRequest(org.openkilda.messaging.command.yflow.YFlowRerouteRequest) RerouteError(org.openkilda.messaging.info.reroute.error.RerouteError) ResourceAllocationException(org.openkilda.wfm.share.flow.resources.ResourceAllocationException) YFlowRequest(org.openkilda.messaging.command.yflow.YFlowRequest) Test(org.junit.Test) AbstractYFlowTest(org.openkilda.wfm.topology.flowhs.service.AbstractYFlowTest)

Example 3 with RerouteError

use of org.openkilda.messaging.info.reroute.error.RerouteError in project open-kilda by telstra.

the class ValidateFlowAction method performWithResponse.

@TimedExecution("fsm.validate_flow")
@Override
protected Optional<Message> performWithResponse(State from, State to, Event event, FlowRerouteContext context, FlowRerouteFsm stateMachine) {
    String flowId = stateMachine.getFlowId();
    Set<IslEndpoint> affectedIsl = new HashSet<>(Optional.ofNullable(context.getAffectedIsl()).orElse(emptySet()));
    dashboardLogger.onFlowPathReroute(flowId, affectedIsl, context.isForceReroute());
    String rerouteReason = context.getRerouteReason();
    stateMachine.saveNewEventToHistory("Started flow validation", FlowEventData.Event.REROUTE, rerouteReason == null ? FlowEventData.Initiator.NB : FlowEventData.Initiator.AUTO, rerouteReason == null ? null : "Reason: " + rerouteReason);
    stateMachine.setRerouteReason(rerouteReason);
    Flow flow = transactionManager.doInTransaction(() -> {
        Flow foundFlow = getFlow(flowId);
        if (foundFlow.getStatus() == FlowStatus.IN_PROGRESS) {
            String message = format("Flow %s is in progress now", flowId);
            stateMachine.setRerouteError(new RerouteError(message));
            throw new FlowProcessingException(ErrorType.REQUEST_INVALID, message);
        }
        if (!foundFlow.getSrcSwitch().isActive()) {
            String message = format("Flow's %s src switch is not active", flowId);
            stateMachine.setRerouteError(new RerouteError(message));
            throw new FlowProcessingException(ErrorType.UNPROCESSABLE_REQUEST, message);
        }
        if (!foundFlow.getDestSwitch().isActive()) {
            String message = format("Flow's %s dest switch is not active", flowId);
            stateMachine.setRerouteError(new RerouteError(message));
            throw new FlowProcessingException(ErrorType.UNPROCESSABLE_REQUEST, message);
        }
        stateMachine.setOriginalFlowStatus(foundFlow.getStatus());
        stateMachine.setOriginalFlowStatusInfo(foundFlow.getStatusInfo());
        stateMachine.setOriginalEncapsulationType(foundFlow.getEncapsulationType());
        stateMachine.setOriginalPathComputationStrategy(foundFlow.getPathComputationStrategy());
        stateMachine.setRecreateIfSamePath(!foundFlow.isActive() || context.isForceReroute());
        stateMachine.setOriginalFlow(RequestedFlowMapper.INSTANCE.toRequestedFlow(foundFlow));
        stateMachine.setPeriodicPingsEnabled(foundFlow.isPeriodicPings());
        if (foundFlow.getTargetPathComputationStrategy() != null) {
            foundFlow.setPathComputationStrategy(foundFlow.getTargetPathComputationStrategy());
            foundFlow.setTargetPathComputationStrategy(null);
        }
        foundFlow.setStatus(FlowStatus.IN_PROGRESS);
        return foundFlow;
    });
    if (featureTogglesRepository.getOrDefault().getFlowsRerouteUsingDefaultEncapType()) {
        stateMachine.setNewEncapsulationType(kildaConfigurationRepository.getOrDefault().getFlowEncapsulationType());
    }
    boolean reroutePrimary;
    boolean rerouteProtected;
    if (affectedIsl.isEmpty()) {
        // no know affected ISLs
        reroutePrimary = true;
        rerouteProtected = true;
    } else {
        reroutePrimary = checkIsPathAffected(flow.getForwardPath(), affectedIsl) || checkIsPathAffected(flow.getReversePath(), affectedIsl);
        rerouteProtected = checkIsPathAffected(flow.getProtectedForwardPath(), affectedIsl) || checkIsPathAffected(flow.getProtectedReversePath(), affectedIsl);
    }
    // check protected path presence
    rerouteProtected &= flow.isAllocateProtectedPath();
    if (!reroutePrimary && !rerouteProtected) {
        throw new FlowProcessingException(ErrorType.NOT_FOUND, format("No paths of the flow %s are affected by failure on %s", flowId, affectedIsl.stream().map(IslEndpoint::toString).collect(Collectors.joining(","))));
    }
    if (reroutePrimary) {
        log.info("Reroute for the flow {} will affect primary paths: {} / {}", flowId, flow.getForwardPathId(), flow.getReversePathId());
    }
    if (rerouteProtected) {
        log.info("Reroute for the flow {} will affect protected paths: {} / {}", flowId, flow.getProtectedForwardPathId(), flow.getProtectedReversePathId());
    }
    stateMachine.setReroutePrimary(reroutePrimary);
    stateMachine.setRerouteProtected(rerouteProtected);
    stateMachine.setEffectivelyDown(context.isEffectivelyDown());
    if (stateMachine.isRerouteProtected() && flow.isPinned()) {
        throw new FlowProcessingException(ErrorType.REQUEST_INVALID, format("Flow %s is pinned, fail to reroute its protected paths", flowId));
    }
    stateMachine.setAffectedIsls(context.getAffectedIsl());
    stateMachine.setForceReroute(context.isForceReroute());
    stateMachine.setIgnoreBandwidth(context.isIgnoreBandwidth());
    stateMachine.saveActionToHistory("Flow was validated successfully");
    return Optional.empty();
}
Also used : IslEndpoint(org.openkilda.model.IslEndpoint) FlowProcessingException(org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException) RerouteError(org.openkilda.messaging.info.reroute.error.RerouteError) HashSet(java.util.HashSet) Flow(org.openkilda.model.Flow) TimedExecution(org.openkilda.wfm.share.metrics.TimedExecution)

Example 4 with RerouteError

use of org.openkilda.messaging.info.reroute.error.RerouteError in project open-kilda by telstra.

the class YFlowRerouteServiceTest method shouldFailIfNoPathAvailableForSecondSubFlow.

@Test
public void shouldFailIfNoPathAvailableForSecondSubFlow() throws UnroutableFlowException, RecoverableException, DuplicateKeyException {
    // given
    YFlowRequest createYFlowRequest = createYFlow();
    YFlowRerouteRequest request = new YFlowRerouteRequest(createYFlowRequest.getYFlowId(), "reason");
    preparePathComputationForReroute("test_flow_1", buildFirstSubFlowPathPairWithNewTransit());
    when(pathComputer.getPath(buildFlowIdArgumentMatch("test_flow_2"), any())).thenThrow(new UnroutableFlowException(injectedErrorMessage));
    prepareYPointComputation(SWITCH_SHARED, SWITCH_FIRST_EP, SWITCH_SECOND_EP, SWITCH_NEW_TRANSIT);
    // when
    processRerouteRequestAndSpeakerCommands(request, FlowStatus.IN_PROGRESS, FlowStatus.IN_PROGRESS, FlowStatus.UP);
    verifyNorthboundErrorResponse(yFlowRerouteHubCarrier, ErrorType.NOT_FOUND);
    verifyYFlowStatus(request.getYFlowId(), FlowStatus.DEGRADED, FlowStatus.UP, FlowStatus.DOWN);
    verify(yFlowRerouteHubCarrier).sendYFlowRerouteResultStatus(eq(createYFlowRequest.getYFlowId()), eq(new RerouteError("Failed to reroute sub-flows [test_flow_2] of y-flow test_successful_yflow")), anyString());
}
Also used : UnroutableFlowException(org.openkilda.pce.exception.UnroutableFlowException) YFlowRerouteRequest(org.openkilda.messaging.command.yflow.YFlowRerouteRequest) RerouteError(org.openkilda.messaging.info.reroute.error.RerouteError) YFlowRequest(org.openkilda.messaging.command.yflow.YFlowRequest) Test(org.junit.Test) AbstractYFlowTest(org.openkilda.wfm.topology.flowhs.service.AbstractYFlowTest)

Example 5 with RerouteError

use of org.openkilda.messaging.info.reroute.error.RerouteError in project open-kilda by telstra.

the class YFlowRerouteServiceTest method shouldFailOnTimeoutDuringMeterInstallation.

@Test
public void shouldFailOnTimeoutDuringMeterInstallation() throws UnroutableFlowException, RecoverableException, DuplicateKeyException, UnknownKeyException {
    // given
    YFlowRequest createYFlowRequest = createYFlow();
    YFlowRerouteRequest request = new YFlowRerouteRequest(createYFlowRequest.getYFlowId(), "reason");
    preparePathComputationForReroute("test_flow_1", buildFirstSubFlowPathPairWithNewTransit());
    preparePathComputationForReroute("test_flow_2", buildSecondSubFlowPathPairWithNewTransit());
    prepareYPointComputation(SWITCH_SHARED, SWITCH_FIRST_EP, SWITCH_SECOND_EP, SWITCH_NEW_TRANSIT);
    YFlowRerouteService service = makeYFlowRerouteService(0);
    // when
    service.handleRequest(request.getYFlowId(), new CommandContext(), request);
    verifyYFlowStatus(request.getYFlowId(), FlowStatus.IN_PROGRESS);
    // and
    handleSpeakerCommandsAndTimeoutInstall(service, request.getYFlowId());
    // then
    verifyNorthboundSuccessResponse(yFlowRerouteHubCarrier, YFlowRerouteResponse.class);
    verifyYFlowStatus(request.getYFlowId(), FlowStatus.UP);
    verifyAffinity(request.getYFlowId());
    verify(yFlowRerouteHubCarrier).sendYFlowRerouteResultStatus(eq(createYFlowRequest.getYFlowId()), eq(new RerouteError("Timeout event has been received")), anyString());
}
Also used : CommandContext(org.openkilda.wfm.CommandContext) YFlowRerouteRequest(org.openkilda.messaging.command.yflow.YFlowRerouteRequest) RerouteError(org.openkilda.messaging.info.reroute.error.RerouteError) YFlowRequest(org.openkilda.messaging.command.yflow.YFlowRequest) Test(org.junit.Test) AbstractYFlowTest(org.openkilda.wfm.topology.flowhs.service.AbstractYFlowTest)

Aggregations

RerouteError (org.openkilda.messaging.info.reroute.error.RerouteError)8 Test (org.junit.Test)5 YFlowRequest (org.openkilda.messaging.command.yflow.YFlowRequest)5 YFlowRerouteRequest (org.openkilda.messaging.command.yflow.YFlowRerouteRequest)5 AbstractYFlowTest (org.openkilda.wfm.topology.flowhs.service.AbstractYFlowTest)5 UnroutableFlowException (org.openkilda.pce.exception.UnroutableFlowException)2 CommandContext (org.openkilda.wfm.CommandContext)2 HashSet (java.util.HashSet)1 NoPathFoundError (org.openkilda.messaging.info.reroute.error.NoPathFoundError)1 Flow (org.openkilda.model.Flow)1 IslEndpoint (org.openkilda.model.IslEndpoint)1 ResourceAllocationException (org.openkilda.wfm.share.flow.resources.ResourceAllocationException)1 TimedExecution (org.openkilda.wfm.share.metrics.TimedExecution)1 FlowProcessingException (org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException)1 FlowThrottlingData (org.openkilda.wfm.topology.reroute.model.FlowThrottlingData)1 RerouteQueue (org.openkilda.wfm.topology.reroute.model.RerouteQueue)1