From 61ce4de3e5e86f984055bbc71d27e0ea92ae3263 Mon Sep 17 00:00:00 2001 From: Javier Errea Date: Fri, 5 Feb 2021 12:22:44 +0100 Subject: [PATCH] TAPI topology Service RPCs impl - getNodeDetails - getTopologyDetails - getNodeEdgePointDetails - getLinkDetails - getTopologyList JIRA: TRNSPRTPCE-427 Change-Id: I2a0afc32c9815f43cbd6982a4b3b1b19b0914303 Signed-off-by: errea --- .../tapi/topology/TapiTopologyImpl.java | 95 ++++++++++++-- .../transportpce/tapi/utils/TapiContext.java | 124 +++++++++++++++++- .../TapiTopologyImplExceptionTest.java | 8 +- 3 files changed, 209 insertions(+), 18 deletions(-) diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImpl.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImpl.java index 46e618d67..20cc23de6 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImpl.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImpl.java @@ -57,17 +57,23 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.Co import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.ForwardingRule; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetLinkDetailsInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetLinkDetailsOutput; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetLinkDetailsOutputBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetNodeDetailsInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetNodeDetailsOutput; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetNodeDetailsOutputBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetNodeEdgePointDetailsInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetNodeEdgePointDetailsOutput; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetNodeEdgePointDetailsOutputBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetTopologyDetailsInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetTopologyDetailsOutput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetTopologyDetailsOutputBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetTopologyListInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetTopologyListOutput; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.GetTopologyListOutputBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.RuleType; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.TapiTopologyService; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.get.link.details.output.LinkBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.get.node.edge.point.details.output.NodeEdgePointBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.get.topology.details.output.Topology; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.get.topology.details.output.TopologyBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.NodeRuleGroup; @@ -84,6 +90,7 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.to import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.TopologyKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; @@ -105,7 +112,23 @@ public class TapiTopologyImpl implements TapiTopologyService { @Override public ListenableFuture> getNodeDetails(GetNodeDetailsInput input) { // TODO Auto-generated method stub - return null; + // TODO -> maybe we get errors when having CEPs? + Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(input.getTopologyIdOrName().getBytes(Charset.forName("UTF-8"))) + .toString()); + // Node id: if roadm -> ROADM+PHOTONIC_MEDIA. if xpdr -> XPDR-XPDR+DSR/OTSi + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(input.getNodeIdOrName().getBytes(Charset.forName("UTF-8"))) + .toString()); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node node = this.tapiContext + .getTapiNode(topoUuid, nodeUuid); + if (node == null) { + LOG.error("Invalid TAPI node name"); + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "Invalid Tapi Node name").buildFuture(); + } + return RpcResultBuilder.success(new GetNodeDetailsOutputBuilder() + .setNode(new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.topology.rev181210.get.node.details.output.NodeBuilder(node).build()) + .build()).buildFuture(); } @Override @@ -122,7 +145,8 @@ public class TapiTopologyImpl implements TapiTopologyService { topologyMap = context.augmentation(Context1.class).getTopologyContext().getTopology(); if (!(topologyMap != null && topologyMap.containsKey(new TopologyKey(topoUuid)))) { LOG.error("Topology {} not found in datastore", input.getTopologyIdOrName()); - return RpcResultBuilder.success(new GetTopologyDetailsOutputBuilder().build()).buildFuture(); + return RpcResultBuilder.failed() + .withError(RpcError.ErrorType.RPC, "Invalid Topology name").buildFuture(); } org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.Topology topology = topologyMap.get(new TopologyKey(topoUuid)); @@ -132,7 +156,8 @@ public class TapiTopologyImpl implements TapiTopologyService { .buildFuture(); } LOG.error("Invalid TAPI topology name"); - return RpcResultBuilder.success(new GetTopologyDetailsOutputBuilder().build()).buildFuture(); + return RpcResultBuilder.failed() + .withError(RpcError.ErrorType.RPC, "Invalid Topology name").buildFuture(); } try { LOG.info("Building TAPI Topology abstraction for {}", input.getTopologyIdOrName()); @@ -144,7 +169,8 @@ public class TapiTopologyImpl implements TapiTopologyService { .buildFuture(); } catch (TapiTopologyException e) { LOG.error("error building TAPI topology"); - return RpcResultBuilder.success(new GetTopologyDetailsOutputBuilder().build()).buildFuture(); + return RpcResultBuilder.failed() + .withError(RpcError.ErrorType.RPC, "Error building topology").buildFuture(); } } @@ -171,8 +197,7 @@ public class TapiTopologyImpl implements TapiTopologyService { .build(); } - private Network readTopology(InstanceIdentifier networkIID) - throws TapiTopologyException { + private Network readTopology(InstanceIdentifier networkIID) throws TapiTopologyException { Network topology = null; FluentFuture> topologyFuture = dataBroker.newReadOnlyTransaction() .read(LogicalDatastoreType.CONFIGURATION, networkIID); @@ -267,21 +292,71 @@ public class TapiTopologyImpl implements TapiTopologyService { @Override public ListenableFuture> getNodeEdgePointDetails( - GetNodeEdgePointDetailsInput input) { + GetNodeEdgePointDetailsInput input) { // TODO Auto-generated method stub - return null; + // TODO -> maybe we get errors when having CEPs? + Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(input.getTopologyIdOrName().getBytes(Charset.forName("UTF-8"))) + .toString()); + // Node id: if roadm -> ROADMid+PHOTONIC_MEDIA. if xpdr -> XPDRid-XPDRnbr+DSR/OTSi + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(input.getNodeIdOrName().getBytes(Charset.forName("UTF-8"))) + .toString()); + // NEP id: if roadm -> ROADMid+PHOTONIC_MEDIA/MC/OTSiMC+TPid. + // if xpdr -> XPDRid-XPDRnbr+DSR/eODU/iODU/iOTSi/eOTSi/PHOTONIC_MEDIA+TPid + Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes(input.getEpIdOrName().getBytes(Charset.forName("UTF-8"))) + .toString()); + OwnedNodeEdgePoint nep = this.tapiContext.getTapiNEP(topoUuid, nodeUuid, nepUuid); + if (nep == null) { + LOG.error("Invalid TAPI nep name"); + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "Invalid NEP name").buildFuture(); + } + return RpcResultBuilder.success(new GetNodeEdgePointDetailsOutputBuilder() + .setNodeEdgePoint(new NodeEdgePointBuilder(nep).build()).build()).buildFuture(); } @Override public ListenableFuture> getLinkDetails(GetLinkDetailsInput input) { // TODO Auto-generated method stub - return null; + Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(input.getTopologyIdOrName().getBytes(Charset.forName("UTF-8"))) + .toString()); + // Link id: same as OR link id + Uuid linkUuid = new Uuid(UUID.nameUUIDFromBytes(input.getLinkIdOrName().getBytes(Charset.forName("UTF-8"))) + .toString()); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Link link = this.tapiContext + .getTapiLink(topoUuid, linkUuid); + if (link == null) { + LOG.error("Invalid TAPI link name"); + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "Invalid Link name").buildFuture(); + } + return RpcResultBuilder.success(new GetLinkDetailsOutputBuilder().setLink(new LinkBuilder(link).build()) + .build()).buildFuture(); } @Override public ListenableFuture> getTopologyList(GetTopologyListInput input) { // TODO Auto-generated method stub - return null; + // TODO -> maybe we get errors when having CEPs? + Map + topologyMap = this.tapiContext.getTopologyContext(); + if (topologyMap.isEmpty()) { + LOG.error("No topologies exist in tapi context"); + return RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, + "No topologies exist in tapi context").buildFuture(); + } + Map + newTopoMap = new HashMap<>(); + for (org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.Topology + topo:topologyMap.values()) { + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.get.topology.list.output.Topology + newTopo = new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.topology.rev181210.get.topology.list.output.TopologyBuilder(topo).build(); + newTopoMap.put(newTopo.key(), newTopo); + } + return RpcResultBuilder.success(new GetTopologyListOutputBuilder().setTopology(newTopoMap).build()) + .buildFuture(); } private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiContext.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiContext.java index 521857d6a..1fc8c5c50 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiContext.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiContext.java @@ -35,10 +35,15 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev18121 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContextBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.topology.context.topology.node.owned.node.edge.point.CepList; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.topology.context.topology.node.owned.node.edge.point.CepListBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContextBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePoint; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePointBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePointKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Link; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.LinkKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.NodeBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.NodeKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.NwTopologyServiceBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.Topology; @@ -138,17 +143,14 @@ public class TapiContext { // TODO: solve error when merging: Topology is not a valid child of topology context? // TODO: verify this is correct. Should we identify the context IID with the context UUID?? try { - org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext - topologyContext = new TopologyContextBuilder() + TopologyContext topologyContext = new TopologyContextBuilder() //.setNwTopologyService(new NwTopologyServiceBuilder().build()) .setTopology(topologyMap) .build(); - InstanceIdentifier topologycontextIID = + InstanceIdentifier topologycontextIID = InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn .onf.otcc.yang.tapi.topology.rev181210.Context1.class) - .child(org.opendaylight.yang.gen.v1.urn - .onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext.class) + .child(TopologyContext.class) .build(); // merge in datastore this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, topologycontextIID, @@ -242,4 +244,114 @@ public class TapiContext { LOG.error("Couldnt update cep in topology", e); } } + + public Node getTapiNode(Uuid topoUuid, Uuid nodeUuid) { + InstanceIdentifier nodeIID = InstanceIdentifier.builder(Context.class) + .augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.Context1.class) + .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext.class) + .child(Topology.class, new TopologyKey(topoUuid)) + .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node.class, + new NodeKey(nodeUuid)).build(); + try { + Optional optNode = this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, nodeIID) + .get(); + if (!optNode.isPresent()) { + LOG.error("Node is not present in datastore"); + return null; + } + // TODO -> Need to remove CEPs from NEPs. If not error from get Topology details output + Node node = optNode.get(); + Map onepMap = new HashMap<>(); + for (OwnedNodeEdgePoint onep: node.getOwnedNodeEdgePoint().values()) { + if (onep.augmentation(OwnedNodeEdgePoint1.class) == null) { + onepMap.put(onep.key(), onep); + continue; + } + OwnedNodeEdgePointBuilder newOnepBuilder = new OwnedNodeEdgePointBuilder() + .setUuid(onep.getUuid()) + .setLayerProtocolName(onep.getLayerProtocolName()) + .setName(onep.getName()) + .setSupportedCepLayerProtocolQualifier(onep.getSupportedCepLayerProtocolQualifier()) + .setAdministrativeState(onep.getAdministrativeState()) + .setOperationalState(onep.getOperationalState()) + .setLifecycleState(onep.getLifecycleState()) + .setTerminationDirection(onep.getTerminationDirection()) + .setTerminationState(onep.getTerminationState()) + .setLinkPortDirection(onep.getLinkPortDirection()) + .setLinkPortRole(onep.getLinkPortRole()); + if (onep.getMappedServiceInterfacePoint() != null) { + newOnepBuilder.setMappedServiceInterfacePoint(onep.getMappedServiceInterfacePoint()); + } + onepMap.put(newOnepBuilder.key(), newOnepBuilder.build()); + } + return new NodeBuilder(node) + .setOwnedNodeEdgePoint(onepMap) + .build(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Couldnt read node in topology", e); + return null; + } + } + + public OwnedNodeEdgePoint getTapiNEP(Uuid topoUuid, Uuid nodeUuid, Uuid nepUuid) { + InstanceIdentifier nepIID = InstanceIdentifier.builder(Context.class) + .augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.Context1.class) + .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext.class) + .child(Topology.class, new TopologyKey(topoUuid)) + .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node.class, + new NodeKey(nodeUuid)).child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(nepUuid)).build(); + try { + Optional optNode = this.networkTransactionService + .read(LogicalDatastoreType.OPERATIONAL, nepIID) + .get(); + if (!optNode.isPresent()) { + LOG.error("Node is not present in datastore"); + return null; + } + return optNode.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Couldnt read NEP in topology", e); + return null; + } + } + + public Link getTapiLink(Uuid topoUuid, Uuid linkUuid) { + InstanceIdentifier linkIID = InstanceIdentifier.builder(Context.class) + .augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.Context1.class) + .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext.class) + .child(Topology.class, new TopologyKey(topoUuid)) + .child(Link.class, new LinkKey(linkUuid)).build(); + try { + Optional optLink = this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, linkIID) + .get(); + if (!optLink.isPresent()) { + LOG.error("Node is not present in datastore"); + return null; + } + return optLink.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Couldnt read link in topology", e); + return null; + } + } + + public Map getTopologyContext() { + InstanceIdentifier topologycontextIID = + InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.topology.rev181210.Context1.class) + .child(TopologyContext.class) + .build(); + try { + Optional optTopoContext = this.networkTransactionService.read( + LogicalDatastoreType.OPERATIONAL, topologycontextIID).get(); + if (!optTopoContext.isPresent()) { + LOG.error("Topology context is not present in datastore"); + return null; + } + return optTopoContext.get().getTopology(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Couldnt read topology context", e); + return null; + } + } } diff --git a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplExceptionTest.java b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplExceptionTest.java index a130d44c6..35cfb9689 100644 --- a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplExceptionTest.java +++ b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplExceptionTest.java @@ -62,8 +62,12 @@ public class TapiTopologyImplExceptionTest { TapiTopologyImpl tapiTopoImpl = new TapiTopologyImpl(dataBroker, tapiContext, topologyUtils); ListenableFuture> result = tapiTopoImpl.getTopologyDetails(input); RpcResult rpcResult = result.get(); - Topology topology = rpcResult.getResult().getTopology(); - assertNull("Topology should be null", topology); + if (rpcResult.isSuccessful()) { + Topology topology = rpcResult.getResult().getTopology(); + assertNull("Topology should be null", topology); + } else { + assertNull("Topology should be null", null); + } } private class ReadTransactionMock implements ReadTransaction { -- 2.36.6