use of org.openkilda.wfm.topology.flow.model.FlowPathPair in project open-kilda by telstra.
the class CompleteFlowPathRemovalAction method perform.
@Override
protected void perform(State from, State to, Event event, FlowDeleteContext context, FlowDeleteFsm stateMachine) {
Flow flow = transactionManager.doInTransaction(() -> {
Flow foundFlow = getFlow(stateMachine.getFlowId());
Stream.of(foundFlow.getForwardPath(), foundFlow.getReversePath()).map(FlowPath::getFlowMirrorPointsSet).flatMap(Collection::stream).forEach(mirrorPoints -> {
Set<Long> cookies = new HashSet<>();
mirrorPoints.getMirrorPaths().forEach(mirrorPath -> {
cookies.add(mirrorPath.getCookie().getFlowEffectiveId());
flowMirrorPathRepository.remove(mirrorPath);
});
stateMachine.getFlowMirrorPathResources().add(FlowMirrorPathResources.builder().flowPathId(mirrorPoints.getFlowPathId()).mirrorSwitchId(mirrorPoints.getMirrorSwitchId()).unmaskedCookies(cookies).build());
flowMirrorPointsRepository.remove(mirrorPoints);
});
return foundFlow;
});
// Iterate to remove each path in a dedicated transaction.
flow.getPathIds().forEach(pathId -> {
Optional<FlowPath> deletedPath = flowPathRepository.remove(pathId);
deletedPath.ifPresent(path -> {
updateIslsForFlowPath(path);
saveRemovalActionWithDumpToHistory(stateMachine, flow, new FlowPathPair(path, path));
});
});
}
use of org.openkilda.wfm.topology.flow.model.FlowPathPair in project open-kilda by telstra.
the class AllocateProtectedResourcesAction method allocate.
@Override
protected void allocate(FlowUpdateFsm stateMachine) throws RecoverableException, UnroutableFlowException, ResourceAllocationException {
String flowId = stateMachine.getFlowId();
Set<String> flowIds = Sets.newHashSet(flowId);
if (stateMachine.getBulkUpdateFlowIds() != null) {
flowIds.addAll(stateMachine.getBulkUpdateFlowIds());
}
log.debug("Finding protected path ids for flows {}", flowIds);
List<PathId> pathIdsToReuse = new ArrayList<>(flowPathRepository.findActualPathIdsByFlowIds(flowIds));
pathIdsToReuse.addAll(stateMachine.getRejectedPaths());
Flow tmpFlow = getFlow(flowId);
FlowPathPair oldPaths = new FlowPathPair(tmpFlow.getProtectedForwardPath(), tmpFlow.getProtectedReversePath());
FlowPath primaryForward = getFlowPath(tmpFlow, stateMachine.getNewPrimaryForwardPath());
FlowPath primaryReverse = getFlowPath(tmpFlow, stateMachine.getNewPrimaryReversePath());
Predicate<GetPathsResult> testNonOverlappingPath = path -> (primaryForward == null || !flowPathBuilder.arePathsOverlapped(path.getForward(), primaryForward)) && (primaryReverse == null || !flowPathBuilder.arePathsOverlapped(path.getReverse(), primaryReverse));
PathId newForwardPathId = resourcesManager.generatePathId(flowId);
PathId newReversePathId = resourcesManager.generatePathId(flowId);
log.debug("Finding a new protected path for flow {}", flowId);
GetPathsResult allocatedPaths = allocatePathPair(tmpFlow, newForwardPathId, newReversePathId, false, pathIdsToReuse, oldPaths, true, stateMachine.getSharedBandwidthGroupId(), testNonOverlappingPath);
if (allocatedPaths == null) {
throw new ResourceAllocationException("Unable to allocate a path");
}
if (!testNonOverlappingPath.test(allocatedPaths)) {
stateMachine.saveActionToHistory("Couldn't find non overlapping protected path");
} else {
log.debug("New protected paths have been allocated: {}", allocatedPaths);
stateMachine.setNewProtectedForwardPath(newForwardPathId);
stateMachine.setNewProtectedReversePath(newReversePathId);
stateMachine.setBackUpProtectedPathComputationWayUsed(allocatedPaths.isBackUpPathComputationWayUsed());
log.debug("Allocating resources for a new protected path of flow {}", flowId);
FlowResources flowResources = allocateFlowResources(tmpFlow, newForwardPathId, newReversePathId);
stateMachine.setNewProtectedResources(flowResources);
FlowPathPair createdPaths = createFlowPathPair(flowId, flowResources, allocatedPaths, false, stateMachine.getSharedBandwidthGroupId());
log.debug("New protected path has been created: {}", createdPaths);
saveAllocationActionWithDumpsToHistory(stateMachine, tmpFlow, "protected", createdPaths);
}
}
use of org.openkilda.wfm.topology.flow.model.FlowPathPair in project open-kilda by telstra.
the class CompleteFlowPathRemovalAction method removeOldProtectedFlowPaths.
private void removeOldProtectedFlowPaths(Flow originalFlow, FlowUpdateFsm stateMachine) {
PathId oldProtectedForwardPathId = stateMachine.getOldProtectedForwardPath();
PathId oldProtectedReversePathId = stateMachine.getOldProtectedReversePath();
if (oldProtectedForwardPathId != null || oldProtectedReversePathId != null) {
FlowPath oldProtectedForward = flowPathRepository.remove(oldProtectedForwardPathId).orElse(null);
FlowPath oldProtectedReverse = flowPathRepository.remove(oldProtectedReversePathId).orElse(null);
FlowPathPair removedPaths = null;
if (oldProtectedForward != null) {
if (oldProtectedReverse != null) {
log.debug("Removed the flow paths {} / {}", oldProtectedForward, oldProtectedReverse);
removedPaths = new FlowPathPair(oldProtectedForward, oldProtectedReverse);
updateIslsForFlowPath(removedPaths.getForward(), removedPaths.getReverse());
} else {
log.debug("Removed the flow path {} (no reverse pair)", oldProtectedForward);
// TODO: History dumps require paired paths, fix it to support any (without opposite one).
removedPaths = new FlowPathPair(oldProtectedForward, oldProtectedForward);
updateIslsForFlowPath(removedPaths.getForward());
}
} else if (oldProtectedReverse != null) {
log.debug("Removed the flow path {} (no forward pair)", oldProtectedReverse);
// TODO: History dumps require paired paths, fix it to support any (without opposite one).
removedPaths = new FlowPathPair(oldProtectedReverse, oldProtectedReverse);
updateIslsForFlowPath(removedPaths.getReverse());
}
if (removedPaths != null) {
saveRemovalActionWithDumpToHistory(stateMachine, originalFlow, removedPaths);
}
}
}
use of org.openkilda.wfm.topology.flow.model.FlowPathPair in project open-kilda by telstra.
the class CompleteFlowPathRemovalAction method removeOldPrimaryFlowPaths.
private void removeOldPrimaryFlowPaths(Flow originalFlow, FlowUpdateFsm stateMachine) {
PathId oldPrimaryForwardPathId = stateMachine.getOldPrimaryForwardPath();
PathId oldPrimaryReversePathId = stateMachine.getOldPrimaryReversePath();
if (oldPrimaryForwardPathId != null || oldPrimaryReversePathId != null) {
FlowPath oldPrimaryForward = flowPathRepository.remove(oldPrimaryForwardPathId).orElse(null);
FlowPath oldPrimaryReverse = flowPathRepository.remove(oldPrimaryReversePathId).orElse(null);
FlowPathPair removedPaths = null;
if (oldPrimaryForward != null) {
if (oldPrimaryReverse != null) {
log.debug("Removed the flow paths {} / {}", oldPrimaryForward, oldPrimaryReverse);
removedPaths = new FlowPathPair(oldPrimaryForward, oldPrimaryReverse);
updateIslsForFlowPath(removedPaths.getForward(), removedPaths.getReverse());
} else {
log.debug("Removed the flow path {} (no reverse pair)", oldPrimaryForward);
// TODO: History dumps require paired paths, fix it to support any (without opposite one).
removedPaths = new FlowPathPair(oldPrimaryForward, oldPrimaryForward);
updateIslsForFlowPath(removedPaths.getForward());
}
} else if (oldPrimaryReverse != null) {
log.debug("Removed the flow path {} (no forward pair)", oldPrimaryReverse);
// TODO: History dumps require paired paths, fix it to support any (without opposite one).
removedPaths = new FlowPathPair(oldPrimaryReverse, oldPrimaryReverse);
updateIslsForFlowPath(removedPaths.getReverse());
}
if (removedPaths != null) {
saveRemovalActionWithDumpToHistory(stateMachine, originalFlow, removedPaths);
}
}
}
use of org.openkilda.wfm.topology.flow.model.FlowPathPair in project open-kilda by telstra.
the class BaseResourceAllocationAction method allocatePathPair.
@SneakyThrows
protected GetPathsResult allocatePathPair(Flow flow, PathId newForwardPathId, PathId newReversePathId, boolean forceToIgnoreBandwidth, List<PathId> pathsToReuseBandwidth, FlowPathPair oldPaths, boolean allowOldPaths, String sharedBandwidthGroupId, Predicate<GetPathsResult> whetherCreatePathSegments) throws RecoverableException, UnroutableFlowException, ResourceAllocationException {
// Lazy initialisable map with reused bandwidth...
Supplier<Map<IslEndpoints, Long>> reuseBandwidthPerIsl = Suppliers.memoize(() -> {
Map<IslEndpoints, Long> result = new HashMap<>();
if (pathsToReuseBandwidth != null && !pathsToReuseBandwidth.isEmpty()) {
pathsToReuseBandwidth.stream().map(pathId -> flow.getPath(pathId).orElse(flowPathRepository.findById(pathId).orElse(null))).filter(Objects::nonNull).flatMap(path -> path.getSegments().stream()).forEach(segment -> {
IslEndpoints isl = new IslEndpoints(segment.getSrcSwitchId().toString(), segment.getSrcPort(), segment.getDestSwitchId().toString(), segment.getDestPort());
result.put(isl, result.getOrDefault(isl, 0L) + segment.getBandwidth());
});
}
return result;
});
RetryPolicy<GetPathsResult> pathAllocationRetryPolicy = new RetryPolicy<GetPathsResult>().handle(RecoverableException.class).handle(ResourceAllocationException.class).handle(UnroutableFlowException.class).handle(PersistenceException.class).onRetry(e -> log.warn("Failure in path allocation. Retrying #{}...", e.getAttemptCount(), e.getLastFailure())).onRetriesExceeded(e -> log.warn("Failure in path allocation. No more retries", e.getFailure())).withMaxRetries(pathAllocationRetriesLimit);
if (pathAllocationRetryDelay > 0) {
pathAllocationRetryPolicy.withDelay(Duration.ofMillis(pathAllocationRetryDelay));
}
try {
return Failsafe.with(pathAllocationRetryPolicy).get(() -> {
GetPathsResult potentialPath;
if (forceToIgnoreBandwidth) {
boolean originalIgnoreBandwidth = flow.isIgnoreBandwidth();
flow.setIgnoreBandwidth(true);
potentialPath = pathComputer.getPath(flow);
flow.setIgnoreBandwidth(originalIgnoreBandwidth);
} else {
potentialPath = pathComputer.getPath(flow, pathsToReuseBandwidth);
}
boolean newPathFound = isNotSamePath(potentialPath, oldPaths);
if (allowOldPaths || newPathFound) {
if (!newPathFound) {
log.debug("Found the same path for flow {}. Proceed with recreating it", flow.getFlowId());
}
if (whetherCreatePathSegments.test(potentialPath)) {
boolean ignoreBandwidth = forceToIgnoreBandwidth || flow.isIgnoreBandwidth();
List<PathSegment> forwardSegments = flowPathBuilder.buildPathSegments(newForwardPathId, potentialPath.getForward(), flow.getBandwidth(), ignoreBandwidth, sharedBandwidthGroupId);
List<PathSegment> reverseSegments = flowPathBuilder.buildPathSegments(newReversePathId, potentialPath.getReverse(), flow.getBandwidth(), ignoreBandwidth, sharedBandwidthGroupId);
transactionManager.doInTransaction(() -> {
createPathSegments(forwardSegments, reuseBandwidthPerIsl);
createPathSegments(reverseSegments, reuseBandwidthPerIsl);
});
}
return potentialPath;
}
return null;
});
} catch (FailsafeException ex) {
throw ex.getCause();
}
}
Aggregations