Search in sources :

Example 41 with YFlow

use of org.openkilda.model.YFlow 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 42 with YFlow

use of org.openkilda.model.YFlow in project open-kilda by telstra.

the class InstallNewMetersAction method perform.

@Override
protected void perform(State from, State to, Event event, YFlowRerouteContext context, YFlowRerouteFsm stateMachine) {
    stateMachine.clearPendingAndRetriedAndFailedCommands();
    String yFlowId = stateMachine.getYFlowId();
    YFlow yFlow = getYFlow(yFlowId);
    Collection<InstallSpeakerCommandsRequest> commands = buildYFlowInstallCommands(yFlow, stateMachine.getCommandContext());
    if (commands.isEmpty()) {
        stateMachine.saveActionToHistory("No need to install y-flow meters");
        stateMachine.fire(Event.YFLOW_METERS_INSTALLED);
    } else {
        // emitting
        commands.forEach(command -> {
            stateMachine.getCarrier().sendSpeakerRequest(command);
            stateMachine.addInstallSpeakerCommand(command.getCommandId(), command);
            stateMachine.addPendingCommand(command.getCommandId(), command.getSwitchId());
        });
        stateMachine.saveActionToHistory("Commands for installing y-flow rules have been sent");
    }
}
Also used : YFlow(org.openkilda.model.YFlow) InstallSpeakerCommandsRequest(org.openkilda.floodlight.api.request.rulemanager.InstallSpeakerCommandsRequest)

Example 43 with YFlow

use of org.openkilda.model.YFlow in project open-kilda by telstra.

the class RerouteService method rerouteInactiveFlows.

/**
 * Handles reroute on ISL up events.
 *
 * @param sender transport sender
 * @param correlationId correlation id to pass through
 * @param command origin command
 */
@TimedExecution("reroute_inactive_flows")
public void rerouteInactiveFlows(MessageSender sender, String correlationId, RerouteInactiveFlows command) {
    PathNode pathNode = command.getPathNode();
    int port = pathNode.getPortNo();
    SwitchId switchId = pathNode.getSwitchId();
    Map<String, FlowThrottlingData> flowsForReroute = transactionManager.doInTransaction(() -> {
        Map<String, FlowThrottlingData> forReroute = new HashMap<>();
        Map<Flow, Set<PathId>> flowsForRerouting = getInactiveFlowsForRerouting();
        for (Entry<Flow, Set<PathId>> entry : flowsForRerouting.entrySet()) {
            Flow flow = entry.getKey();
            Set<IslEndpoint> allAffectedIslEndpoints = new HashSet<>();
            for (FlowPath flowPath : flow.getPaths()) {
                Set<IslEndpoint> affectedIslEndpoints = new HashSet<>();
                PathSegment firstSegment = null;
                int failedSegmentsCount = 0;
                for (PathSegment pathSegment : flowPath.getSegments()) {
                    if (firstSegment == null) {
                        firstSegment = pathSegment;
                    }
                    if (pathSegment.isFailed()) {
                        affectedIslEndpoints.add(new IslEndpoint(pathSegment.getSrcSwitchId(), pathSegment.getSrcPort()));
                        affectedIslEndpoints.add(new IslEndpoint(pathSegment.getDestSwitchId(), pathSegment.getDestPort()));
                        if (pathSegment.containsNode(switchId, port)) {
                            pathSegment.setFailed(false);
                            pathSegmentRepository.updateFailedStatus(flowPath, pathSegment, false);
                        } else {
                            failedSegmentsCount++;
                        }
                    }
                }
                if (flowPath.getStatus().equals(FlowPathStatus.INACTIVE) && failedSegmentsCount == 0) {
                    updateFlowPathStatus(flowPath, FlowPathStatus.ACTIVE);
                    // force reroute of failed path only (required due to inaccurate path/segment state management)
                    if (affectedIslEndpoints.isEmpty() && firstSegment != null) {
                        affectedIslEndpoints.add(new IslEndpoint(firstSegment.getSrcSwitchId(), firstSegment.getSrcPort()));
                    }
                }
                allAffectedIslEndpoints.addAll(affectedIslEndpoints);
            }
            FlowStatus flowStatus = flow.computeFlowStatus();
            String flowStatusInfo = null;
            if (!FlowStatus.UP.equals(flowStatus)) {
                flowStatusInfo = command.getReason();
            }
            flowRepository.updateStatusSafe(flow, flowStatus, flowStatusInfo);
            if (flow.isPinned()) {
                log.info("Skipping reroute command for pinned flow {}", flow.getFlowId());
            } else if (flow.getYFlow() != null) {
                YFlow yFlow = flow.getYFlow();
                log.info("Create reroute command (attempt to restore inactive flows) request for {} " + "(affected ISL endpoints: {})", yFlow.getYFlowId(), allAffectedIslEndpoints);
                FlowThrottlingData flowThrottlingData = getFlowThrottlingDataBuilder(yFlow).correlationId(correlationId).affectedIsl(allAffectedIslEndpoints).force(false).effectivelyDown(true).reason(command.getReason()).build();
                sender.emitRerouteCommand(yFlow.getYFlowId(), flowThrottlingData);
            } else {
                log.info("Create reroute command (attempt to restore inactive flows) request for {} (affected ISL " + "endpoints: {})", flow.getFlowId(), allAffectedIslEndpoints);
                FlowThrottlingData flowThrottlingData = getFlowThrottlingDataBuilder(flow).correlationId(correlationId).affectedIsl(allAffectedIslEndpoints).force(false).effectivelyDown(true).reason(command.getReason()).build();
                forReroute.put(flow.getFlowId(), flowThrottlingData);
            }
        }
        return forReroute;
    });
    for (Entry<String, FlowThrottlingData> entry : flowsForReroute.entrySet()) {
        log.info("Produce reroute (attempt to restore inactive flows) request for {} (affected ISL endpoints: {})", entry.getKey(), entry.getValue().getAffectedIsl());
        sender.emitRerouteCommand(entry.getKey(), entry.getValue());
    }
}
Also used : YFlow(org.openkilda.model.YFlow) IslEndpoint(org.openkilda.model.IslEndpoint) HashSet(java.util.HashSet) Collectors.toSet(java.util.stream.Collectors.toSet) Set(java.util.Set) HashMap(java.util.HashMap) SwitchId(org.openkilda.model.SwitchId) PathSegment(org.openkilda.model.PathSegment) PathNode(org.openkilda.messaging.info.event.PathNode) IslEndpoint(org.openkilda.model.IslEndpoint) FlowStatus(org.openkilda.model.FlowStatus) Flow(org.openkilda.model.Flow) YFlow(org.openkilda.model.YFlow) FlowThrottlingData(org.openkilda.wfm.topology.reroute.model.FlowThrottlingData) FlowPath(org.openkilda.model.FlowPath) HashSet(java.util.HashSet) TimedExecution(org.openkilda.wfm.share.metrics.TimedExecution)

Example 44 with YFlow

use of org.openkilda.model.YFlow in project open-kilda by telstra.

the class RerouteService method processRerouteRequest.

/**
 * Process manual y-flow reroute request.
 */
public void processRerouteRequest(MessageSender sender, String correlationId, YFlowRerouteRequest request) {
    Optional<YFlow> flow = yFlowRepository.findById(request.getYFlowId());
    FlowThrottlingData flowThrottlingData = getFlowThrottlingDataBuilder(flow.orElse(null)).correlationId(correlationId).affectedIsl(request.getAffectedIsl()).force(request.isForce()).reason(request.getReason()).build();
    sender.emitManualRerouteCommand(request.getYFlowId(), flowThrottlingData);
}
Also used : YFlow(org.openkilda.model.YFlow) FlowThrottlingData(org.openkilda.wfm.topology.reroute.model.FlowThrottlingData)

Example 45 with YFlow

use of org.openkilda.model.YFlow in project open-kilda by telstra.

the class RerouteService method rerouteAffectedFlows.

/**
 * Handles reroute on ISL down events.
 *
 * @param sender transport sender
 * @param correlationId correlation id to pass through
 * @param command origin command
 */
@TimedExecution("reroute_affected_flows")
public void rerouteAffectedFlows(MessageSender sender, String correlationId, RerouteAffectedFlows command) {
    // TODO(surabujin): need better/more detailed representation of failed ISL
    PathNode pathNode = command.getPathNode();
    int port = pathNode.getPortNo();
    SwitchId switchId = pathNode.getSwitchId();
    final IslEndpoint affectedIsl = new IslEndpoint(switchId, port);
    RerouteResult rerouteResult = transactionManager.doInTransaction(() -> {
        RerouteResult result = new RerouteResult();
        Collection<FlowPath> affectedFlowPaths = getAffectedFlowPaths(pathNode.getSwitchId(), pathNode.getPortNo());
        // swapping affected primary paths with available protected
        List<FlowPath> pathsForSwapping = getPathsForSwapping(affectedFlowPaths);
        for (FlowPath path : pathsForSwapping) {
            result.flowIdsForSwapPaths.add(path.getFlowId());
        }
        for (FlowWithAffectedPaths entry : groupPathsForRerouting(affectedFlowPaths)) {
            Flow flow = entry.getFlow();
            boolean rerouteRequired = updateFlowPathsStateForFlow(switchId, port, entry.getAffectedPaths());
            FlowStatus flowStatus = flow.computeFlowStatus();
            String flowStatusInfo = null;
            if (!FlowStatus.UP.equals(flowStatus)) {
                flowStatusInfo = command.getReason();
            }
            flowRepository.updateStatusSafe(flow, flowStatus, flowStatusInfo);
            if (rerouteRequired) {
                if (flow.getYFlow() != null) {
                    result.yFlowsForReroute.add(flow.getYFlow());
                } else {
                    result.flowsForReroute.add(flow);
                }
            }
        }
        Set<Flow> affectedPinnedFlows = groupAffectedPinnedFlows(affectedFlowPaths);
        for (Flow flow : affectedPinnedFlows) {
            List<FlowPath> flowPaths = new ArrayList<>(flow.getPaths());
            updateFlowPathsStateForFlow(switchId, port, flowPaths);
            if (flow.getStatus() != FlowStatus.DOWN) {
                flowDashboardLogger.onFlowStatusUpdate(flow.getFlowId(), FlowStatus.DOWN);
                flowRepository.updateStatusSafe(flow, FlowStatus.DOWN, command.getReason());
            }
        }
        return result;
    });
    for (String flowId : rerouteResult.flowIdsForSwapPaths) {
        sender.emitPathSwapCommand(correlationId, flowId, command.getReason());
    }
    for (Flow flow : rerouteResult.flowsForReroute) {
        FlowThrottlingData flowThrottlingData = getFlowThrottlingDataBuilder(flow).correlationId(correlationId).affectedIsl(Collections.singleton(affectedIsl)).force(false).effectivelyDown(true).reason(command.getReason()).build();
        sender.emitRerouteCommand(flow.getFlowId(), flowThrottlingData);
    }
    for (YFlow yFlow : rerouteResult.yFlowsForReroute) {
        FlowThrottlingData flowThrottlingData = getFlowThrottlingDataBuilder(yFlow).correlationId(correlationId).affectedIsl(Collections.singleton(affectedIsl)).force(false).effectivelyDown(true).reason(command.getReason()).build();
        sender.emitRerouteCommand(yFlow.getYFlowId(), flowThrottlingData);
    }
}
Also used : YFlow(org.openkilda.model.YFlow) IslEndpoint(org.openkilda.model.IslEndpoint) ArrayList(java.util.ArrayList) SwitchId(org.openkilda.model.SwitchId) PathNode(org.openkilda.messaging.info.event.PathNode) IslEndpoint(org.openkilda.model.IslEndpoint) FlowStatus(org.openkilda.model.FlowStatus) Flow(org.openkilda.model.Flow) YFlow(org.openkilda.model.YFlow) FlowThrottlingData(org.openkilda.wfm.topology.reroute.model.FlowThrottlingData) FlowPath(org.openkilda.model.FlowPath) TimedExecution(org.openkilda.wfm.share.metrics.TimedExecution)

Aggregations

YFlow (org.openkilda.model.YFlow)74 Flow (org.openkilda.model.Flow)30 SwitchId (org.openkilda.model.SwitchId)29 YSubFlow (org.openkilda.model.YSubFlow)26 FlowProcessingException (org.openkilda.wfm.topology.flowhs.exception.FlowProcessingException)19 Test (org.junit.Test)12 YFlowRequest (org.openkilda.messaging.command.yflow.YFlowRequest)12 ArrayList (java.util.ArrayList)11 FlowStatus (org.openkilda.model.FlowStatus)10 CommandContext (org.openkilda.wfm.CommandContext)10 AbstractYFlowTest (org.openkilda.wfm.topology.flowhs.service.AbstractYFlowTest)10 FlowPath (org.openkilda.model.FlowPath)9 FlowEndpoint (org.openkilda.model.FlowEndpoint)8 InstallSpeakerCommandsRequest (org.openkilda.floodlight.api.request.rulemanager.InstallSpeakerCommandsRequest)6 Switch (org.openkilda.model.Switch)6 HashSet (java.util.HashSet)5 DeleteSpeakerCommandsRequest (org.openkilda.floodlight.api.request.rulemanager.DeleteSpeakerCommandsRequest)5 SharedEndpoint (org.openkilda.model.YFlow.SharedEndpoint)5 Collection (java.util.Collection)4 HashMap (java.util.HashMap)4