package org.opendaylight.unimgr.mef.nrp.impl.decomposer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
import org.jgrapht.Graph;
import org.jgrapht.GraphPath;
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
import org.opendaylight.unimgr.mef.nrp.api.Subrequrest;
import org.opendaylight.unimgr.mef.nrp.api.TapiConstants;
import org.opendaylight.unimgr.mef.nrp.common.NrpDao;
-import org.opendaylight.yang.gen.v1.urn.onf.params.xml.ns.yang.tapi.common.rev171113.OperationalState;
-import org.opendaylight.yang.gen.v1.urn.onf.params.xml.ns.yang.tapi.common.rev171113.PortDirection;
-import org.opendaylight.yang.gen.v1.urn.onf.params.xml.ns.yang.tapi.common.rev171113.Uuid;
-import org.opendaylight.yang.gen.v1.urn.onf.params.xml.ns.yang.tapi.topology.rev171113.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.onf.params.xml.ns.yang.tapi.topology.rev171113.topology.context.Topology;
+import org.opendaylight.unimgr.mef.nrp.common.TapiUtils;
+import org.opendaylight.yang.gen.v1.urn.odl.unimgr.yang.unimgr.ext.rev170531.NodeAdiAugmentation;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev180307.OperationalState;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev180307.PortDirection;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev180307.ServiceInterfacePointRef;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev180307.Uuid;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev180307.connectivity.service.end.point.ServiceInterfacePoint;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev180307.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev180307.topology.context.Topology;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.*;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
/**
+ * Decompose request into sub-requests {@link Subrequrest} for drivers using graph path computation.
* @author bartosz.michalik@amartus.com
*/
class DecompositionAction {
this.broker = broker;
}
+ Function<ServiceInterfacePoint, Uuid> toUuid = s -> s == null ? null : s.getServiceInterfacePointId();
+
List<Subrequrest> decompose() throws FailureResult {
Graph<Vertex, DefaultEdge> graph = prepareData();
+
+
+ Set<String> missingSips = endpoints.stream()
+ .filter(e -> sipToNep.get(toUuid.apply(e.getEndpoint().getServiceInterfacePoint())) == null)
+ .map(e -> toUuid.apply(e.getEndpoint().getServiceInterfacePoint()).getValue())
+ .collect(Collectors.toSet());
+ if (!missingSips.isEmpty()) {
+ throw new FailureResult("Some service interface points not found in the system: "
+ + missingSips.stream().collect(Collectors.joining(",", "[", "]")));
+ }
+
List<Vertex> vertices = endpoints.stream().map(e -> {
- Vertex v = sipToNep.get(e.getEndpoint().getServiceInterfacePoint());
- if((v.dir == PortDirection.OUTPUT && e.getEndpoint().getDirection() != PortDirection.OUTPUT) ||
- (v.dir == PortDirection.INPUT && e.getEndpoint().getDirection() != PortDirection.INPUT)) {
- throw new IllegalArgumentException("Port direction for " + e.getEndpoint().getLocalId() + " incompatible with NEP." +
- "CEP " + e.getEndpoint().getDirection() + " NEP " + v.dir);
+ Vertex vertex = sipToNep.get(toUuid.apply(e.getEndpoint().getServiceInterfacePoint()));
+ if ((vertex.dir == PortDirection.OUTPUT && e.getEndpoint().getDirection() != PortDirection.OUTPUT)
+ || (vertex.dir == PortDirection.INPUT && e.getEndpoint().getDirection() != PortDirection.INPUT)) {
+ throw new IllegalArgumentException("Port direction for "
+ + e.getEndpoint().getLocalId() + " incompatible with NEP."
+ + "CEP " + e.getEndpoint().getDirection() + " NEP " + vertex.dir);
}
- return new Vertex(v, e.getEndpoint().getDirection());
+ return new Vertex(vertex, e.getEndpoint().getDirection());
}).collect(Collectors.toList());
assert vertices.size() > 1;
inV.forEach(i ->
outV.stream().filter(o -> i != o).forEach(o -> {
GraphPath<Vertex, DefaultEdge> path = DijkstraShortestPath.findPathBetween(graph, i, o);
- if(path != null) {
+ if (path != null) {
LOG.debug("Couldn't find path between {} and {}", i, o);
}
paths.add(path);
})
);
- if(paths.stream().anyMatch(Objects::isNull)) {
+ if (paths.stream().anyMatch(Objects::isNull)) {
LOG.info("At least single path between endpoints not found");
return null;
}
- List<Subrequrest> result = paths.stream()
+ List<Subrequrest> result = toSublists(paths);
+ return result.isEmpty() ? null : result;
+ }
+
+ private List<Subrequrest> toSublists(Set<GraphPath<Vertex, DefaultEdge>> paths) {
+ return paths.stream()
.flatMap(gp -> gp.getVertexList().stream()).collect(Collectors.groupingBy(Vertex::getNodeUuid))
.entrySet().stream()
.map(e -> {
- Set<EndPoint> endpoints = e.getValue().stream().map(this::toEndPoint).collect(Collectors.toSet());
- return new Subrequrest(e.getKey(), new ArrayList<>(endpoints));
+ Set<EndPoint> fromVertexes = e.getValue().stream()
+ .map(this::toEndPoint).collect(Collectors.toSet());
+ return new Subrequrest(
+ e.getKey(),
+ new ArrayList<>(fromVertexes),
+ e.getValue().stream().findFirst().get().getActivationDriverId());
}).collect(Collectors.toList());
- return result.isEmpty() ? null : result;
}
- private EndPoint toEndPoint(Vertex v) {
- EndPoint ep = endpoints.stream().filter(e -> e.getEndpoint().getServiceInterfacePoint().equals(v.getSip())).findFirst()
+ private EndPoint toEndPoint(Vertex vertex) {
+ EndPoint ep = endpoints.stream()
+ .filter(e -> e.getEndpoint().getServiceInterfacePoint()
+ .getServiceInterfacePointId().equals(vertex.getSip()))
+ .findFirst()
.orElse(new EndPoint(null, null));
- ep.setSystemNepUuid(v.getUuid());
+ Objects.requireNonNull(vertex.getUuid());
+ ep.setNepRef(TapiUtils.toSysNepRef(vertex.getNodeUuid(), vertex.getUuid()));
return ep;
}
- private final Predicate<Vertex> isInput = v -> v.getDir() == PortDirection.BIDIRECTIONAL|| v.getDir() == PortDirection.INPUT;
- private final Predicate<Vertex> isOutput = v -> v.getDir() == PortDirection.BIDIRECTIONAL || v.getDir() == PortDirection.OUTPUT;
+ private final Predicate<Vertex> isInput = v -> v.getDir() == PortDirection.BIDIRECTIONAL
+ || v.getDir() == PortDirection.INPUT;
+ private final Predicate<Vertex> isOutput = v -> v.getDir() == PortDirection.BIDIRECTIONAL
+ || v.getDir() == PortDirection.OUTPUT;
private void interconnectNode(Graph<Vertex, DefaultEdge> graph, List<Vertex> vertices) {
vertices.forEach(graph::addVertex);
if (topo.getLink() != null) {
topo.getLink().stream()
- .filter(l -> l.getState() != null && OperationalState.ENABLED == l.getState().getOperationalState())
- .forEach(l -> {
- //we probably need to take link bidir/unidir into consideration as well
- List<Vertex> vertices = l.getNodeEdgePoint().stream()
- .map(nep -> graph.vertexSet().stream().filter(v -> v.getUuid().equals(nep)).findFirst())
+ .filter(l -> OperationalState.ENABLED == l.getOperationalState())
+ .forEach(l -> {
+ //we probably need to take link bidir/unidir into consideration as well
+ List<Vertex> vertices = l.getNodeEdgePoint().stream()
+ .map(nep -> graph.vertexSet().stream()
+ .filter(v -> v.getUuid().equals(nep.getOwnedNodeEdgePointId())).findFirst())
.filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());
- interconnectLink(graph, vertices);
- });
+ interconnectLink(graph, vertices);
+ });
}
return graph;
}
}
- private Stream<Vertex> nodeToGraph(Node n) {
- Uuid nodeUuid = n.getUuid();
-
-
- return n.getOwnedNodeEdgePoint().stream()
- .filter(ep -> ep.getLinkPortDirection() != null && ep.getLinkPortDirection() != PortDirection.UNIDENTIFIEDORUNKNOWN)
- .map(nep -> {
- List<Uuid> sips = nep.getMappedServiceInterfacePoint();
- if (sips == null || sips.isEmpty()) {
- return new Vertex(nodeUuid, nep.getUuid(), null, nep.getLinkPortDirection());
- }
- if (sips.size() > 1) {
- LOG.warn("NodeEdgePoint {} have multiple ServiceInterfacePoint mapped, selecting first one", nep.getUuid());
- }
- return new Vertex(nodeUuid, nep.getUuid(), sips.get(0), nep.getLinkPortDirection());
+ private Stream<Vertex> nodeToGraph(Node node) {
+ Uuid nodeUuid = node.getUuid();
+ String activationDriverId = node.augmentation(NodeAdiAugmentation.class).getActivationDriverId();
+
+
+ return node.getOwnedNodeEdgePoint().stream()
+ .filter(ep -> ep.getLinkPortDirection() != null
+ && ep.getLinkPortDirection() != PortDirection.UNIDENTIFIEDORUNKNOWN)
+ .map(nep -> {
+ List<Uuid> sips = Collections.emptyList();
+ if (nep.getMappedServiceInterfacePoint() != null) {
+ sips = nep.getMappedServiceInterfacePoint().stream()
+ .map(ServiceInterfacePointRef::getServiceInterfacePointId)
+ .collect(Collectors.toList());
+ }
+
+ if (sips.isEmpty()) {
+ return new Vertex(nodeUuid, nep.getUuid(), null, nep.getLinkPortDirection(),activationDriverId);
+ }
+ if (sips.size() > 1) {
+ LOG.warn("NodeEdgePoint {} have multiple ServiceInterfacePoint mapped, selecting first one",
+ nep.getUuid());
+ }
+ return new Vertex(nodeUuid, nep.getUuid(), sips.get(0), nep.getLinkPortDirection(),activationDriverId);
- });
+ });
}
class Vertex implements Comparable<Vertex> {
private final Uuid nodeUuid;
private final Uuid uuid;
private final Uuid sip;
+ private final String activationDriverId;
private final PortDirection dir;
Vertex(Vertex px, PortDirection csDir) {
this.uuid = px.uuid;
this.sip = px.sip;
this.dir = csDir;
+ this.activationDriverId = px.activationDriverId;
}
- Vertex(Uuid nodeUuid, Uuid uuid, Uuid sip, PortDirection dir) {
+ Vertex(Uuid nodeUuid, Uuid uuid, Uuid sip, PortDirection dir, String activationDriverId) {
this.sip = sip;
this.dir = dir;
Objects.requireNonNull(nodeUuid);
Objects.requireNonNull(uuid);
+ Objects.requireNonNull(activationDriverId);
+
this.nodeUuid = nodeUuid;
this.uuid = uuid;
+ this.activationDriverId = activationDriverId;
}
Uuid getNodeUuid() {
return sip;
}
+ public String getActivationDriverId() {
+ return activationDriverId;
+ }
+
@Override
- public boolean equals(Object o) {
- if (this == o) {
+ public boolean equals(Object other) {
+ if (this == other) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if (other == null || getClass() != other.getClass()) {
return false;
}
- Vertex vertex = (Vertex) o;
+ Vertex vertex = (Vertex) other;
return Objects.equals(uuid, vertex.uuid);
}
}
@Override
- public int compareTo(Vertex o) {
- if (o == null) {
+ public int compareTo(Vertex other) {
+ if (other == null) {
return -1;
}
- return uuid.getValue().compareTo(o.uuid.getValue());
+ return uuid.getValue().compareTo(other.uuid.getValue());
}
@Override