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");
}
}
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();
}
}
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));
}
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);
}
}
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()));
}
}
Aggregations