Search in sources :

Example 66 with CommandContext

use of org.openkilda.wfm.CommandContext in project open-kilda by telstra.

the class RevertNewRulesAction method perform.

@Override
protected void perform(State from, State to, Event event, FlowUpdateContext context, FlowUpdateFsm stateMachine) {
    String flowId = stateMachine.getFlowId();
    Flow flow = getFlow(flowId);
    log.debug("Abandoning all pending commands: {}", stateMachine.getPendingCommands());
    stateMachine.clearPendingAndRetriedAndFailedCommands();
    FlowEncapsulationType encapsulationType = stateMachine.getTargetFlow().getFlowEncapsulationType();
    FlowCommandBuilder commandBuilder = commandBuilderFactory.getBuilder(encapsulationType);
    Collection<FlowSegmentRequestFactory> installCommands = new ArrayList<>();
    // Reinstall old ingress rules that may be overridden by new ingress.
    if (stateMachine.getOldPrimaryForwardPath() != null && stateMachine.getOldPrimaryReversePath() != null) {
        FlowPath oldForward = getFlowPath(flow, stateMachine.getOldPrimaryForwardPath());
        FlowPath oldReverse = getFlowPath(flow, stateMachine.getOldPrimaryReversePath());
        SpeakerRequestBuildContext speakerContext = buildBaseSpeakerContextForInstall(oldForward.getSrcSwitchId(), oldReverse.getSrcSwitchId());
        installCommands.addAll(commandBuilder.buildIngressOnly(stateMachine.getCommandContext(), flow, oldForward, oldReverse, speakerContext));
    }
    // need to clean previous requests
    stateMachine.getIngressCommands().clear();
    SpeakerInstallSegmentEmitter.INSTANCE.emitBatch(stateMachine.getCarrier(), installCommands, stateMachine.getIngressCommands());
    stateMachine.getIngressCommands().forEach((key, value) -> stateMachine.addPendingCommand(key, value.getSwitchId()));
    CommandContext commandContext = stateMachine.getCommandContext();
    // Remove possible installed segments
    MirrorContext mirrorContext = MirrorContext.builder().removeFlowOperation(true).build();
    Collection<FlowSegmentRequestFactory> revertCommands = new ArrayList<>();
    if (stateMachine.getNewPrimaryForwardPath() != null && stateMachine.getNewPrimaryReversePath() != null) {
        FlowPath newForward = getFlowPath(flow, stateMachine.getNewPrimaryForwardPath());
        FlowPath newReverse = getFlowPath(flow, stateMachine.getNewPrimaryReversePath());
        if (stateMachine.getEndpointUpdate().isPartialUpdate()) {
            SpeakerRequestBuildContext speakerRequestBuildContext = getSpeakerRequestBuildContextForRemoval(stateMachine, false);
            Flow oldFlow = RequestedFlowMapper.INSTANCE.toFlow(stateMachine.getOriginalFlow());
            switch(stateMachine.getEndpointUpdate()) {
                case SOURCE:
                    switch(stateMachine.getFlowLoopOperation()) {
                        case NONE:
                            revertCommands.addAll(commandBuilder.buildIngressOnlyOneDirection(commandContext, flow, newForward, newReverse, speakerRequestBuildContext.getForward(), mirrorContext));
                            revertCommands.addAll(commandBuilder.buildEgressOnlyOneDirection(commandContext, oldFlow, newReverse, newForward, mirrorContext));
                            break;
                        case CREATE:
                            revertCommands.addAll(commandBuilder.buildAll(commandContext, flow, newForward, newReverse, speakerRequestBuildContext).stream().filter(f -> f instanceof IngressFlowLoopSegmentRequestFactory || f instanceof TransitFlowLoopSegmentRequestFactory).collect(Collectors.toList()));
                            break;
                        case DELETE:
                        default:
                            // No need to revert rules
                            break;
                    }
                    break;
                case DESTINATION:
                    switch(stateMachine.getFlowLoopOperation()) {
                        case NONE:
                            revertCommands.addAll(commandBuilder.buildIngressOnlyOneDirection(commandContext, flow, newReverse, newForward, speakerRequestBuildContext.getReverse(), mirrorContext));
                            revertCommands.addAll(commandBuilder.buildEgressOnlyOneDirection(commandContext, oldFlow, newForward, newReverse, mirrorContext));
                            break;
                        case CREATE:
                            revertCommands.addAll(commandBuilder.buildAll(commandContext, flow, newForward, newReverse, speakerRequestBuildContext).stream().filter(f -> f instanceof IngressFlowLoopSegmentRequestFactory || f instanceof TransitFlowLoopSegmentRequestFactory).collect(Collectors.toList()));
                            break;
                        case DELETE:
                        default:
                            // No need to revert rules
                            break;
                    }
                    break;
                default:
                    revertCommands.addAll(commandBuilder.buildIngressOnly(commandContext, flow, newForward, newReverse, speakerRequestBuildContext, mirrorContext));
                    revertCommands.addAll(commandBuilder.buildEgressOnly(commandContext, oldFlow, newForward, newReverse, mirrorContext));
                    break;
            }
        } else {
            revertCommands.addAll(commandBuilder.buildAll(stateMachine.getCommandContext(), flow, newForward, newReverse, getSpeakerRequestBuildContextForRemoval(stateMachine, true), mirrorContext));
        }
    }
    if (stateMachine.getNewProtectedForwardPath() != null && stateMachine.getNewProtectedReversePath() != null) {
        FlowPath newForward = getFlowPath(flow, stateMachine.getNewProtectedForwardPath());
        FlowPath newReverse = getFlowPath(flow, stateMachine.getNewProtectedReversePath());
        Flow oldFlow = RequestedFlowMapper.INSTANCE.toFlow(stateMachine.getOriginalFlow());
        if (stateMachine.getEndpointUpdate().isPartialUpdate()) {
            switch(stateMachine.getEndpointUpdate()) {
                case SOURCE:
                    if (stateMachine.getFlowLoopOperation() == NONE) {
                        revertCommands.addAll(commandBuilder.buildEgressOnlyOneDirection(commandContext, oldFlow, newReverse, newForward, mirrorContext));
                    }
                    break;
                case DESTINATION:
                    if (stateMachine.getFlowLoopOperation() == NONE) {
                        revertCommands.addAll(commandBuilder.buildEgressOnlyOneDirection(commandContext, oldFlow, newForward, newReverse, mirrorContext));
                    }
                    break;
                default:
                    revertCommands.addAll(commandBuilder.buildEgressOnly(commandContext, oldFlow, newForward, newReverse, mirrorContext));
                    break;
            }
        } else {
            revertCommands.addAll(commandBuilder.buildAllExceptIngress(stateMachine.getCommandContext(), flow, newForward, newReverse, mirrorContext));
        }
    }
    stateMachine.getRemoveCommands().clear();
    SpeakerRemoveSegmentEmitter.INSTANCE.emitBatch(stateMachine.getCarrier(), revertCommands, stateMachine.getRemoveCommands());
    stateMachine.getRemoveCommands().forEach((key, value) -> stateMachine.addPendingCommand(key, value.getSwitchId()));
    if (stateMachine.getPendingCommands().isEmpty()) {
        stateMachine.saveActionToHistory("No need to remove new rules or re-install original ingress rule");
        stateMachine.fire(Event.RULES_REMOVED);
    } else {
        stateMachine.saveActionToHistory("Commands for removing new rules and re-installing original ingress rule have been sent");
    }
}
Also used : TransitFlowLoopSegmentRequestFactory(org.openkilda.floodlight.api.request.factory.TransitFlowLoopSegmentRequestFactory) MirrorContext(org.openkilda.wfm.share.model.MirrorContext) CommandContext(org.openkilda.wfm.CommandContext) ArrayList(java.util.ArrayList) FlowCommandBuilder(org.openkilda.wfm.topology.flowhs.service.FlowCommandBuilder) FlowEncapsulationType(org.openkilda.model.FlowEncapsulationType) SpeakerRequestBuildContext(org.openkilda.wfm.share.model.SpeakerRequestBuildContext) Flow(org.openkilda.model.Flow) RequestedFlow(org.openkilda.wfm.topology.flowhs.model.RequestedFlow) FlowSegmentRequestFactory(org.openkilda.floodlight.api.request.factory.FlowSegmentRequestFactory) IngressFlowLoopSegmentRequestFactory(org.openkilda.floodlight.api.request.factory.IngressFlowLoopSegmentRequestFactory) FlowPath(org.openkilda.model.FlowPath)

Example 67 with CommandContext

use of org.openkilda.wfm.CommandContext in project open-kilda by telstra.

the class OnSubFlowAllocatedAction method performWithResponse.

@Override
protected Optional<Message> performWithResponse(State from, State to, Event event, YFlowCreateContext context, YFlowCreateFsm stateMachine) {
    String subFlowId = context.getSubFlowId();
    if (!stateMachine.isCreatingSubFlow(subFlowId)) {
        throw new IllegalStateException("Received an event for non-pending sub-flow " + subFlowId);
    }
    String yFlowId = stateMachine.getYFlowId();
    stateMachine.saveActionToHistory("Creating a sub-flow", format("Allocated resources for sub-flow %s of y-flow %s", subFlowId, yFlowId));
    stateMachine.addAllocatedSubFlow(subFlowId);
    SubFlowDto subFlowDto = stateMachine.getTargetFlow().getSubFlows().stream().filter(f -> f.getFlowId().equals(subFlowId)).findAny().orElseThrow(() -> new FlowProcessingException(ErrorType.INTERNAL_ERROR, format("Can't find definition of created sub-flow %s", subFlowId)));
    SubFlowSharedEndpointEncapsulation sharedEndpoint = subFlowDto.getSharedEndpoint();
    FlowEndpoint endpoint = subFlowDto.getEndpoint();
    log.debug("Start creating sub-flow references from {} to y-flow {}", subFlowId, stateMachine.getYFlowId());
    YFlow result = transactionManager.doInTransaction(() -> {
        YFlow yFlow = yFlowRepository.findById(yFlowId).orElseThrow(() -> new FlowProcessingException(ErrorType.INTERNAL_ERROR, format("Y-flow %s not found", yFlowId)));
        Flow flow = flowRepository.findById(subFlowId).orElseThrow(() -> new FlowProcessingException(ErrorType.INTERNAL_ERROR, format("Flow %s not found", subFlowId)));
        YSubFlow subFlow = YSubFlow.builder().yFlow(yFlow).flow(flow).sharedEndpointVlan(sharedEndpoint.getVlanId()).sharedEndpointInnerVlan(sharedEndpoint.getInnerVlanId()).endpointSwitchId(endpoint.getSwitchId()).endpointPort(endpoint.getPortNumber()).endpointVlan(endpoint.getOuterVlanId()).endpointInnerVlan(endpoint.getInnerVlanId()).build();
        yFlow.addSubFlow(subFlow);
        return yFlow;
    });
    if (subFlowId.equals(stateMachine.getMainAffinityFlowId())) {
        stateMachine.getRequestedFlows().forEach(requestedFlow -> {
            String requestedFlowId = requestedFlow.getFlowId();
            if (!requestedFlowId.equals(subFlowId)) {
                stateMachine.addSubFlow(requestedFlowId);
                stateMachine.addCreatingSubFlow(requestedFlowId);
                stateMachine.notifyEventListeners(listener -> listener.onSubFlowProcessingStart(yFlowId, requestedFlowId));
                CommandContext flowContext = stateMachine.getCommandContext().fork(requestedFlowId);
                requestedFlow.setAffinityFlowId(stateMachine.getMainAffinityFlowId());
                flowCreateService.startFlowCreation(flowContext, requestedFlow, yFlowId);
            }
        });
    }
    if (stateMachine.getAllocatedSubFlows().size() == stateMachine.getSubFlows().size()) {
        return Optional.of(buildResponseMessage(result, stateMachine.getCommandContext()));
    } else {
        return Optional.empty();
    }
}
Also used : YFlow(org.openkilda.model.YFlow) FlowEndpoint(org.openkilda.model.FlowEndpoint) CommandContext(org.openkilda.wfm.CommandContext) FlowProcessingException(org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException) SubFlowSharedEndpointEncapsulation(org.openkilda.messaging.command.yflow.SubFlowSharedEndpointEncapsulation) SubFlowDto(org.openkilda.messaging.command.yflow.SubFlowDto) YSubFlow(org.openkilda.model.YSubFlow) Flow(org.openkilda.model.Flow) YFlow(org.openkilda.model.YFlow) YSubFlow(org.openkilda.model.YSubFlow)

Example 68 with CommandContext

use of org.openkilda.wfm.CommandContext in project open-kilda by telstra.

the class SwitchOperationsBolt method updateSwitchUnderMaintenanceFlag.

private List<GetSwitchResponse> updateSwitchUnderMaintenanceFlag(UpdateSwitchUnderMaintenanceRequest request, Tuple tuple) {
    SwitchId switchId = request.getSwitchId();
    boolean underMaintenance = request.isUnderMaintenance();
    boolean evacuate = request.isEvacuate();
    Switch sw;
    try {
        sw = switchOperationsService.updateSwitchUnderMaintenanceFlag(switchId, underMaintenance);
    } catch (SwitchNotFoundException e) {
        throw new MessageException(ErrorType.NOT_FOUND, e.getMessage(), "Switch was not found.");
    }
    if (underMaintenance && evacuate) {
        Collection<FlowPath> paths = flowOperationsService.getFlowPathsForSwitch(switchId);
        Set<IslEndpoint> affectedIslEndpoint = new HashSet<>(switchOperationsService.getSwitchIslEndpoints(switchId));
        String reason = format("evacuated due to switch maintenance %s", switchId);
        for (FlowRerouteRequest reroute : flowOperationsService.makeRerouteRequests(paths, affectedIslEndpoint, reason)) {
            CommandContext forkedContext = getCommandContext().fork(reroute.getFlowId());
            getOutput().emit(StreamType.REROUTE.toString(), tuple, new Values(reroute, forkedContext.getCorrelationId()));
        }
    }
    return Collections.singletonList(new GetSwitchResponse(sw));
}
Also used : IslEndpoint(org.openkilda.model.IslEndpoint) GetSwitchResponse(org.openkilda.messaging.nbtopology.response.GetSwitchResponse) CommandContext(org.openkilda.wfm.CommandContext) Values(org.apache.storm.tuple.Values) SwitchId(org.openkilda.model.SwitchId) SwitchNotFoundException(org.openkilda.wfm.error.SwitchNotFoundException) Switch(org.openkilda.model.Switch) MessageException(org.openkilda.messaging.error.MessageException) FlowRerouteRequest(org.openkilda.messaging.command.flow.FlowRerouteRequest) FlowPath(org.openkilda.model.FlowPath) HashSet(java.util.HashSet)

Example 69 with CommandContext

use of org.openkilda.wfm.CommandContext in project open-kilda by telstra.

the class MessageEncoder method handleInput.

@Override
protected void handleInput(Tuple input) throws Exception {
    MessageData payload = pullPayload(input);
    try {
        CommandContext commandContext = pullContext(input);
        Message message = wrap(commandContext, payload);
        if (payload instanceof FlowRerouteRequest) {
            getOutput().emit(input.getSourceStreamId(), input, new Values(message));
        } else if (payload instanceof SwitchValidateRequest) {
            getOutput().emit(input.getSourceStreamId(), input, new Values(commandContext.getCorrelationId(), message));
        } else if (payload instanceof ErrorData) {
            getOutput().emit(StreamType.ERROR.toString(), input, new Values(null, message));
        }
    } catch (IllegalArgumentException e) {
        log.error(e.getMessage());
        unhandledInput(input);
    }
}
Also used : CommandContext(org.openkilda.wfm.CommandContext) Message(org.openkilda.messaging.Message) MessageData(org.openkilda.messaging.MessageData) Values(org.apache.storm.tuple.Values) FlowRerouteRequest(org.openkilda.messaging.command.flow.FlowRerouteRequest) SwitchValidateRequest(org.openkilda.messaging.command.switches.SwitchValidateRequest) ErrorData(org.openkilda.messaging.error.ErrorData)

Example 70 with CommandContext

use of org.openkilda.wfm.CommandContext in project open-kilda by telstra.

the class FlowOperationsBolt method sendRerouteRequest.

private void sendRerouteRequest(Collection<FlowPath> paths, Set<IslEndpoint> affectedIslEndpoints, String reason) {
    for (FlowRerouteRequest request : flowOperationsService.makeRerouteRequests(paths, affectedIslEndpoints, reason)) {
        CommandContext forkedContext = getCommandContext().fork(request.getFlowId());
        getOutput().emit(StreamType.REROUTE.toString(), getCurrentTuple(), new Values(request, forkedContext.getCorrelationId()));
    }
}
Also used : CommandContext(org.openkilda.wfm.CommandContext) Values(org.apache.storm.tuple.Values) FlowRerouteRequest(org.openkilda.messaging.command.flow.FlowRerouteRequest)

Aggregations

CommandContext (org.openkilda.wfm.CommandContext)95 Test (org.junit.Test)28 Values (org.apache.storm.tuple.Values)27 FlowSegmentRequest (org.openkilda.floodlight.api.request.FlowSegmentRequest)15 Flow (org.openkilda.model.Flow)15 AbstractYFlowTest (org.openkilda.wfm.topology.flowhs.service.AbstractYFlowTest)14 Tuple (org.apache.storm.tuple.Tuple)12 SwitchId (org.openkilda.model.SwitchId)11 YFlow (org.openkilda.model.YFlow)11 BaseSpeakerCommandsRequest (org.openkilda.floodlight.api.request.rulemanager.BaseSpeakerCommandsRequest)9 SpeakerResponse (org.openkilda.floodlight.api.response.SpeakerResponse)9 YFlowRequest (org.openkilda.messaging.command.yflow.YFlowRequest)9 InfoMessage (org.openkilda.messaging.info.InfoMessage)9 TupleImpl (org.apache.storm.tuple.TupleImpl)8 FlowPath (org.openkilda.model.FlowPath)8 ArrayList (java.util.ArrayList)7 FlowRerouteRequest (org.openkilda.messaging.command.flow.FlowRerouteRequest)7 FlowProcessingException (org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException)7 UnknownKeyException (org.openkilda.wfm.topology.flowhs.exception.UnknownKeyException)7 List (java.util.List)6