From: errea Date: Tue, 30 Nov 2021 13:40:55 +0000 (+0100) Subject: TAPI connectivity upgrade X-Git-Tag: 5.0.0~143 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=transportpce.git;a=commitdiff_plain;h=db48b1e815c4f74a008f98f015fffe1bf0a052ca TAPI connectivity upgrade - Implementation of WDM 100GBE service in T-API as an ETH service - Implementation of OTN services for Mxpdr & Swtchpdr use cases - Differentiation between XPDR type with new value in TAPI node Name attribute - Upgrade connection list of connectivity service to include only TOP connections. Cross connections should be referenced inside the Top Connection in the lower connection list attribute - Create switching pool in TAPI node for Tpdr node which reflects the NETWORK to CLIENT port connection map - Adapt tests JIRA: TRNSPRTPCE-577 Signed-off-by: errea Change-Id: I39ef19626285f3131dc997a056de64c799ff26c3 --- diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/connectivity/ConnectivityUtils.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/connectivity/ConnectivityUtils.java index 840c7d515..58c63893d 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/connectivity/ConnectivityUtils.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/connectivity/ConnectivityUtils.java @@ -16,12 +16,20 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations; import org.opendaylight.transportpce.tapi.TapiStringConstants; import org.opendaylight.transportpce.tapi.utils.GenericServiceEndpoint; import org.opendaylight.transportpce.tapi.utils.ServiceEndpointType; import org.opendaylight.transportpce.tapi.utils.TapiContext; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.Network; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mapping.Mapping; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mapping.MappingKey; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.network.Nodes; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.network.NodesKey; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.equipment.types.rev181130.OpticTypes; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.node.types.rev181130.NodeIdType; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ConnectionType; @@ -33,6 +41,7 @@ import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev1 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.endpoint.TxDirectionBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.lgx.LgxBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.port.PortBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmNodeType; import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev181130.ODU4; import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev181130.OTU4; import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat; @@ -53,6 +62,7 @@ import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.AdministrativeState; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.CapacityUnit; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Context; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.ForwardingDirection; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LayerProtocolName; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LifecycleState; @@ -64,6 +74,7 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.capa import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.capacity.TotalSizeBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.Name; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.NameBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.NameKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.tapi.context.ServiceInterfacePoint; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.tapi.context.ServiceInterfacePointKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.CreateConnectivityServiceInput; @@ -72,6 +83,9 @@ 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.cep.list.ConnectionEndPoint; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.LowerConnection; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.LowerConnectionBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.LowerConnectionKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.end.point.ClientNodeEdgePoint; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.end.point.ClientNodeEdgePointBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityService; @@ -85,8 +99,13 @@ 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.connectivity.service.end.point.CapacityBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.end.point.ServiceInterfacePointBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.create.connectivity.service.input.ConnectivityConstraint; +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.node.OwnedNodeEdgePoint; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.edge.point.MappedServiceInterfacePointKey; +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.Topology; +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.common.Uint16; import org.opendaylight.yangtools.yang.common.Uint32; import org.opendaylight.yangtools.yang.common.Uint64; @@ -107,14 +126,17 @@ public final class ConnectivityUtils { org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection> connectionFullMap; // this variable is for complete connection objects private Map> networkMap = new HashMap<>(); + private final NetworkTransactionService networkTransactionService; // TODO -> handle cases for which node id is ROADM-A1 and not ROADMA01 or XPDR-A1 and not XPDRA01 public ConnectivityUtils(ServiceDataStoreOperations serviceDataStoreOperations, - Map sipMap, TapiContext tapiContext) { + Map sipMap, TapiContext tapiContext, + NetworkTransactionService networkTransactionService) { this.serviceDataStoreOperations = serviceDataStoreOperations; this.tapiContext = tapiContext; this.sipMap = sipMap; this.connectionFullMap = new HashMap<>(); + this.networkTransactionService = networkTransactionService; } public static ServiceCreateInput buildServiceCreateInput(GenericServiceEndpoint sepA, GenericServiceEndpoint sepZ) { @@ -278,7 +300,7 @@ public final class ConnectivityUtils { .setLifecycleState(LifecycleState.INSTALLED) .setUuid(new Uuid(UUID.nameUUIDFromBytes(service.getServiceName().getBytes(Charset.forName("UTF-8"))) .toString())) - .setServiceLayer(mapServiceLayer(serviceAEnd.getServiceFormat())) + .setServiceLayer(mapServiceLayer(serviceAEnd.getServiceFormat(), endPoint1, endPoint2)) .setServiceType(ServiceType.POINTTOPOINTCONNECTIVITY) .setConnectivityDirection(ForwardingDirection.BIDIRECTIONAL) .setName(Map.of(name.key(), name)) @@ -287,7 +309,7 @@ public final class ConnectivityUtils { .build(); } - private LayerProtocolName mapServiceLayer(ServiceFormat serviceFormat) { + private LayerProtocolName mapServiceLayer(ServiceFormat serviceFormat, EndPoint endPoint1, EndPoint endPoint2) { switch (serviceFormat) { case OC: case OTU: @@ -295,6 +317,12 @@ public final class ConnectivityUtils { case ODU: return LayerProtocolName.ODU; case Ethernet: + String node1 = endPoint1.getLocalId(); + String node2 = endPoint2.getLocalId(); + if (getOpenroadmType(node1).equals(OpenroadmNodeType.TPDR) + && getOpenroadmType(node2).equals(OpenroadmNodeType.TPDR)) { + return LayerProtocolName.ETH; + } return LayerProtocolName.DSR; default: LOG.info("Service layer mapping not supported for {}", serviceFormat.getName()); @@ -302,6 +330,19 @@ public final class ConnectivityUtils { return null; } + private OpenroadmNodeType getOpenroadmType(String nodeName) { + LOG.info("Node name = {}", nodeName); + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+",nodeName, TapiStringConstants.DSR)) + .getBytes(Charset.forName("UTF-8"))).toString()); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node tapiNode + = this.tapiContext.getTapiNode(this.tapiTopoUuid, nodeUuid); + if (tapiNode != null) { + return OpenroadmNodeType.forName(tapiNode.getName().get(new NameKey("Node Type")) + .getValue()).get(); + } + return null; + } + private Map createConnectionsFromService( org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.ServiceAEnd serviceAEnd, @@ -399,6 +440,8 @@ public final class ConnectivityUtils { // As mentioned above, for 100GbE service creation there are ROADMs in the path description. // What are the configurations needed here? No OTU, ODU... what kind of cross connections is needed? // this needs to be changed + // TODO: OpenROADM getNodeType from the NamesList to verify what needs to be created + OpenroadmNodeType openroadmNodeType = getOpenRoadmNodeType(xpdrNodelist); switch (serviceFormat) { case OC: // Identify number of ROADMs @@ -422,28 +465,35 @@ public final class ConnectivityUtils { connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist)); break; case ODU: - // Check if OC and OTU are created - if (!rdmNodelist.isEmpty()) { - connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist, - edgeRoadm1, edgeRoadm2)); - connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist)); - } // - XC Connection OTSi betwwen iODU and eODU of xpdr // - Top connection in the ODU layer, between xpdr eODU ports (?) connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist)); break; case Ethernet: // Check if OC, OTU and ODU are created - if (!rdmNodelist.isEmpty()) { + if (openroadmNodeType.equals(OpenroadmNodeType.TPDR)) { + LOG.info("WDM ETH service"); connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist, edgeRoadm1, edgeRoadm2)); connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist)); + xpdrClientTplist = getAssociatedClientsPort(xpdrNetworkTplist); + LOG.info("Associated client ports = {}", xpdrClientTplist); + connectionServMap.putAll(createXpdrCepsAndConnectionsEth(xpdrClientTplist, xpdrNodelist, + connectionServMap)); + } + if (openroadmNodeType.equals(OpenroadmNodeType.SWITCH)) { + // TODO: We create both ODU and DSR because there is no ODU service creation for the switch + // - XC Connection OTSi betwwen iODU and eODU of xpdr + // - Top connection in the ODU layer, between xpdr eODU ports (?) connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist)); + connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist, + xpdrNodelist)); + } + if (openroadmNodeType.equals(OpenroadmNodeType.MUXPDR)) { + // TODO: OTN service but mux has 3 steps at rendering. Verify that things exist + connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist, + xpdrNodelist)); } - // Top connection in the DSR layer, between client ports of the xpdrs - // TODO differentiate between 100GbE and OTN 10GbE services - connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist, - xpdrNodelist)); break; default: LOG.error("Service type format not supported"); @@ -451,6 +501,49 @@ public final class ConnectivityUtils { return connectionServMap; } + private Map createXpdrCepsAndConnectionsEth(List xpdrClientTplist, + List xpdrNodelist, + Map lowerConn) { + // TODO: do we need to create cross connection between iODU and eODU?? + // add the lower connections of the previous steps for this kind of service + Map xcMap = new HashMap<>(); + for (Connection lowConn: lowerConn.values()) { + LowerConnection conn = new LowerConnectionBuilder().setConnectionUuid(lowConn.getConnectionUuid()).build(); + xcMap.put(conn.key(), conn); + } + Map connServMap = new HashMap<>(); + Map cepMapDsr = new HashMap<>(); + // Create 1 cep per Xpdr in the CLIENT + // 1 top connection DSR between the CLIENT xpdrs + for (String xpdr:xpdrNodelist) { + LOG.info("Creating ceps and xc for xpdr {}", xpdr); + String spcXpdrClient = xpdrClientTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst().get(); + + ConnectionEndPoint netCep1 = createCepXpdr(spcXpdrClient, TapiStringConstants.DSR, TapiStringConstants.DSR, + LayerProtocolName.DSR); + putXpdrCepInTopologyContext(xpdr, spcXpdrClient, TapiStringConstants.DSR, TapiStringConstants.DSR, netCep1); + + cepMapDsr.put(netCep1.key(), netCep1); + } + String spcXpdr1 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist + .get(0))).findFirst().get(); + String spcXpdr2 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist + .get(xpdrNodelist.size() - 1))).findFirst().get(); + + // DSR top connection between edge xpdr CLIENT DSR + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection + connectionDsr = createTopConnection(spcXpdr1, spcXpdr2, cepMapDsr, TapiStringConstants.DSR, + LayerProtocolName.DSR, xcMap); + this.connectionFullMap.put(connectionDsr.key(), connectionDsr); + + // DSR top connection that will be added to the service object + Connection conn1 = new ConnectionBuilder().setConnectionUuid(connectionDsr.getUuid()).build(); + connServMap.put(conn1.key(), conn1); + + return connServMap; + } + private Map createXpdrCepsAndConnectionsDsr(List xpdrClientTplist, List xpdrNetworkTplist, List xpdrNodelist) { @@ -459,6 +552,9 @@ public final class ConnectivityUtils { ConnectionEndPoint> cepMapDsr = new HashMap<>(); Map cepMapOdu = new HashMap<>(); + // TODO: when upgrading the models to 2.1.3, get the connection inclusion because those connections will + // be added to the lower connection of a top connection + Map xcMap = new HashMap<>(); // Create 1 cep per Xpdr in the CLIENT, 1 cep per Xpdr eODU, 1 XC between eODU and iODE, // 1 top connection between eODU and a top connection DSR between the CLIENT xpdrs @@ -487,8 +583,8 @@ public final class ConnectivityUtils { this.connectionFullMap.put(connection.key(), connection); // Create X connection that will be added to the service object - Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); - connServMap.put(conn.key(), conn); + LowerConnection conn = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); + xcMap.put(conn.key(), conn); } // DSR top connection between edge xpdr CLIENT DSR @@ -499,16 +595,18 @@ public final class ConnectivityUtils { org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connectionOdu = createTopConnection(spcXpdr1, spcXpdr2, cepMapOdu, TapiStringConstants.E_ODU, - LayerProtocolName.ODU); + LayerProtocolName.ODU, xcMap); this.connectionFullMap.put(connectionOdu.key(), connectionOdu); // ODU top connection that will be added to the service object Connection conn = new ConnectionBuilder().setConnectionUuid(connectionOdu.getUuid()).build(); connServMap.put(conn.key(), conn); + LowerConnection lowerConn = new LowerConnectionBuilder().setConnectionUuid(connectionOdu.getUuid()).build(); + xcMap.put(lowerConn.key(), lowerConn); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connectionDsr = createTopConnection(spcXpdr1, spcXpdr2, cepMapDsr, TapiStringConstants.DSR, - LayerProtocolName.DSR); + LayerProtocolName.DSR, xcMap); this.connectionFullMap.put(connectionDsr.key(), connectionDsr); // DSR top connection that will be added to the service object @@ -523,6 +621,10 @@ public final class ConnectivityUtils { Map connServMap = new HashMap<>(); Map cepMap = new HashMap<>(); + // TODO: when upgrading the models to 2.1.3, get the connection inclusion because those connections will + // be added to the lower connection of a top connection + Map xcMap = new HashMap<>(); + // Create 1 cep per Xpdr in the I_ODU and a top // connection iODU between the xpdrs for (String xpdr:xpdrNodelist) { @@ -544,7 +646,7 @@ public final class ConnectivityUtils { .get(xpdrNodelist.size() - 1))).findFirst().get(); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_ODU, - LayerProtocolName.ODU); + LayerProtocolName.ODU, xcMap); this.connectionFullMap.put(connection.key(), connection); // ODU top connection that will be added to the service object @@ -559,6 +661,9 @@ public final class ConnectivityUtils { Map connServMap = new HashMap<>(); Map cepMap = new HashMap<>(); + // TODO: when upgrading the models to 2.1.3, get the connection inclusion because those connections will + // be added to the lower connection of a top connection + Map xcMap = new HashMap<>(); // create ceps and x connections within xpdr for (String xpdr:xpdrNodelist) { @@ -591,8 +696,8 @@ public final class ConnectivityUtils { this.connectionFullMap.put(connection.key(), connection); // Create X connection that will be added to the service object - Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); - connServMap.put(conn.key(), conn); + LowerConnection conn = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); + xcMap.put(conn.key(), conn); } // OTSi top connection between edge I_OTSI Xpdr String spcXpdr1 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist @@ -601,7 +706,7 @@ public final class ConnectivityUtils { .get(xpdrNodelist.size() - 1))).findFirst().get(); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_OTSI, - LayerProtocolName.PHOTONICMEDIA); + LayerProtocolName.PHOTONICMEDIA, xcMap); this.connectionFullMap.put(connection.key(), connection); // OTSi top connection that will be added to the service object @@ -616,10 +721,11 @@ public final class ConnectivityUtils { List rdmDegTplist, List rdmNodelist, String edgeRoadm1, String edgeRoadm2) { - // TODO: will need to check if things exist already or not + // TODO: when the number of roadms between 2 SPDR/XPDR is more thatn 1, we need to refine this code Map connServMap = new HashMap<>(); Map cepMap = new HashMap<>(); + Map xcMap = new HashMap<>(); // create ceps and x connections within roadm for (String roadm : rdmNodelist) { LOG.info("Creating ceps and xc for roadm {}", roadm); @@ -668,10 +774,11 @@ public final class ConnectivityUtils { this.connectionFullMap.put(connection2.key(), connection2); // Create X connections that will be added to the service object - Connection conn1 = new ConnectionBuilder().setConnectionUuid(connection1.getUuid()).build(); - Connection conn2 = new ConnectionBuilder().setConnectionUuid(connection2.getUuid()).build(); - connServMap.put(conn1.key(), conn1); - connServMap.put(conn2.key(), conn2); + LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection1.getUuid()).build(); + LowerConnection conn2 = new LowerConnectionBuilder().setConnectionUuid(connection2.getUuid()).build(); + + xcMap.put(conn1.key(), conn1); + xcMap.put(conn2.key(), conn2); } LOG.info("Going to create top connections betwee roadms"); // create top connections between roadms: MC connections between AD MC CEPs of roadms @@ -690,13 +797,15 @@ public final class ConnectivityUtils { // Create top connections between MC for full map org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.MC, - LayerProtocolName.PHOTONICMEDIA); + LayerProtocolName.PHOTONICMEDIA, xcMap); this.connectionFullMap.put(connection.key(), connection); LOG.info("Top connection created = {}", connection); // Create top connections that will be added to the service object Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); connServMap.put(conn.key(), conn); + LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); + xcMap.put(conn1.key(), conn1); } // OTSiMC top connection between edge roadms @@ -705,7 +814,7 @@ public final class ConnectivityUtils { String spcRdmAD2 = rdmAddDropTplist.stream().filter(adp -> adp.contains(edgeRoadm2)).findFirst().get(); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.OTSI_MC, - LayerProtocolName.PHOTONICMEDIA); + LayerProtocolName.PHOTONICMEDIA, xcMap); this.connectionFullMap.put(connection.key(), connection); LOG.info("Top connection created = {}", connection); @@ -719,7 +828,8 @@ public final class ConnectivityUtils { createTopConnection(String tp1, String tp2, Map cepMap, String qual, LayerProtocolName topPortocol) { + ConnectionEndPoint> cepMap, String qual, LayerProtocolName topPortocol, + Map xcMap) { // find cep for each AD MC of roadm 1 and 2 LOG.info("Top connection name = {}", String.join("+", "TOP", tp1, tp2, qual)); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ConnectionEndPoint adCep1 = @@ -779,6 +889,7 @@ public final class ConnectivityUtils { .setLayerProtocolName(topPortocol) .setLifecycleState(LifecycleState.INSTALLED) .setDirection(ForwardingDirection.BIDIRECTIONAL) + .setLowerConnection(xcMap) .build(); } @@ -929,10 +1040,8 @@ public final class ConnectivityUtils { } org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.local._class.Name name = new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.local._class.NameBuilder() - .setValueName("OpenROADM info") - .setValue(String.join("-", serviceZEnd.getClli(), - serviceZEnd.getTxDirection().getPort().getPortDeviceName(), - serviceZEnd.getTxDirection().getPort().getPortName())) + .setValueName("OpenROADM node id") + .setValue(serviceZEnd.getTxDirection().getPort().getPortDeviceName()) .build(); return endPointBuilder .setServiceInterfacePoint(new ServiceInterfacePointBuilder() @@ -953,7 +1062,7 @@ public final class ConnectivityUtils { .build()) .setProtectionRole(ProtectionRole.WORK) .setRole(PortRole.SYMMETRIC) - .setLocalId(serviceNodeId) + .setLocalId(serviceZEnd.getTxDirection().getPort().getPortDeviceName()) .build(); } @@ -985,10 +1094,8 @@ public final class ConnectivityUtils { } org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.local._class.Name name = new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.local._class.NameBuilder() - .setValueName("OpenROADM info") - .setValue(String.join("-", serviceAEnd.getClli(), - serviceAEnd.getTxDirection().getPort().getPortDeviceName(), - serviceAEnd.getTxDirection().getPort().getPortName())) + .setValueName("OpenROADM node id") + .setValue(serviceAEnd.getTxDirection().getPort().getPortDeviceName()) .build(); return endPointBuilder .setServiceInterfacePoint(new ServiceInterfacePointBuilder() @@ -1009,7 +1116,7 @@ public final class ConnectivityUtils { .build()) .setProtectionRole(ProtectionRole.WORK) .setRole(PortRole.SYMMETRIC) - .setLocalId(serviceNodeId) + .setLocalId(serviceAEnd.getTxDirection().getPort().getPortDeviceName()) .build(); } @@ -1255,9 +1362,9 @@ public final class ConnectivityUtils { Uint64 capacity = input.getConnectivityConstraint().getRequestedCapacity().getTotalSize().getValue(); // map endpoints into service end points. Map the type of service from TAPI to OR ServiceAEnd serviceAEnd = tapiEndPointToServiceAPoint(endPointMap.values().stream().findFirst().get(), - serviceFormat, nodeAid, capacity); + serviceFormat, nodeAid, capacity, constraint.getServiceLayer()); ServiceZEnd serviceZEnd = tapiEndPointToServiceZPoint(endPointMap.values().stream().skip(1).findFirst().get(), - serviceFormat, nodeZid, capacity); + serviceFormat, nodeZid, capacity, constraint.getServiceLayer()); if (serviceAEnd == null || serviceZEnd == null) { LOG.error("Couldnt map endpoints to service end"); return null; @@ -1283,7 +1390,7 @@ public final class ConnectivityUtils { private ServiceZEnd tapiEndPointToServiceZPoint( org.opendaylight.yang.gen.v1.urn .onf.otcc.yang.tapi.connectivity.rev181210.create.connectivity.service.input.EndPoint endPoint, - ServiceFormat serviceFormat, String nodeZid, Uint64 capacity) { + ServiceFormat serviceFormat, String nodeZid, Uint64 capacity, LayerProtocolName serviceLayer) { // TODO -> change way this is being created. The name includes only SPDR-SA1-XPDR1. // Not the rest which is needed in the txPortDeviceName. // It could be obtained from the SIP which has the NEP and includes all the OR name. @@ -1344,13 +1451,6 @@ public final class ConnectivityUtils { .setOpticType(OpticTypes.Gray) .setServiceFormat(serviceFormat) .setServiceRate(Uint32.valueOf(capacity)) - .setSubrateEthSla(new SubrateEthSlaBuilder().setSubrateEthSla( - new org.opendaylight.yang.gen.v1.http - .org.openroadm.common.service.types.rev190531.subrate.eth.sla.SubrateEthSlaBuilder() - .setCommittedBurstSize(Uint16.valueOf(64)) - .setCommittedInfoRate(Uint32.valueOf(100000)) - .build()) - .build()) .setTxDirection(new TxDirectionBuilder() .setPort(new PortBuilder() .setPortDeviceName(txPortDeviceName) @@ -1387,13 +1487,22 @@ public final class ConnectivityUtils { if (serviceFormat.equals(ServiceFormat.OTU)) { serviceZEndBuilder.setOtuServiceRate(OTU4.class); } + if (!serviceLayer.equals(LayerProtocolName.ETH)) { + serviceZEndBuilder + .setSubrateEthSla(new SubrateEthSlaBuilder().setSubrateEthSla(new org.opendaylight.yang.gen.v1.http + .org.openroadm.common.service.types.rev190531.subrate.eth.sla.SubrateEthSlaBuilder() + .setCommittedBurstSize(Uint16.valueOf(64)) + .setCommittedInfoRate(Uint32.valueOf(100000)) + .build()) + .build()); + } return serviceZEndBuilder.build(); } private ServiceAEnd tapiEndPointToServiceAPoint( org.opendaylight.yang.gen.v1.urn .onf.otcc.yang.tapi.connectivity.rev181210.create.connectivity.service.input.EndPoint endPoint, - ServiceFormat serviceFormat, String nodeAid, Uint64 capacity) { + ServiceFormat serviceFormat, String nodeAid, Uint64 capacity, LayerProtocolName serviceLayer) { // TODO -> change way this is being created. The name includes only SPDR-SA1-XPDR1. // Not the rest which is needed in the txPortDeviceName. // It could be obtained from the SIP which has the NEP and includes all the OR name. @@ -1454,13 +1563,6 @@ public final class ConnectivityUtils { .setOpticType(OpticTypes.Gray) .setServiceFormat(serviceFormat) .setServiceRate(Uint32.valueOf(capacity)) - .setSubrateEthSla(new SubrateEthSlaBuilder().setSubrateEthSla( - new org.opendaylight.yang.gen.v1.http - .org.openroadm.common.service.types.rev190531.subrate.eth.sla.SubrateEthSlaBuilder() - .setCommittedBurstSize(Uint16.valueOf(64)) - .setCommittedInfoRate(Uint32.valueOf(100000)) - .build()) - .build()) .setTxDirection(new TxDirectionBuilder() .setPort(new PortBuilder() .setPortDeviceName(txPortDeviceName) @@ -1497,6 +1599,15 @@ public final class ConnectivityUtils { if (serviceFormat.equals(ServiceFormat.OTU)) { serviceAEndBuilder.setOtuServiceRate(OTU4.class); } + if (!serviceLayer.equals(LayerProtocolName.ETH)) { + serviceAEndBuilder + .setSubrateEthSla(new SubrateEthSlaBuilder().setSubrateEthSla(new org.opendaylight.yang.gen.v1.http + .org.openroadm.common.service.types.rev190531.subrate.eth.sla.SubrateEthSlaBuilder() + .setCommittedBurstSize(Uint16.valueOf(64)) + .setCommittedInfoRate(Uint32.valueOf(100000)) + .build()) + .build()); + } return serviceAEndBuilder.build(); } @@ -1566,4 +1677,72 @@ public final class ConnectivityUtils { } return null; } + + private List getAssociatedClientsPort(List xpdrNetworkTplist) { + List clientPortList = new ArrayList<>(); + for (String networkPort:xpdrNetworkTplist) { + String nodeId = String.join("-", networkPort.split("\\+")[0].split("-")[0], + networkPort.split("\\+")[0].split("-")[1]); + String tpId = networkPort.split("\\+")[1]; + InstanceIdentifier mapIID = InstanceIdentifier.builder(Network.class) + .child(Nodes.class, new NodesKey(nodeId)) + .child(Mapping.class, new MappingKey(tpId)).build(); + try { + Optional optMapping = this.networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, + mapIID).get(); + if (!optMapping.isPresent()) { + LOG.error("Couldnt find mapping for port {} of node {}", tpId, nodeId); + } + Mapping mapping = optMapping.get(); + LOG.info("Mapping for node+port {}+{} = {}", nodeId, tpId, mapping); + String key = String.join("+", String.join("-", nodeId, tpId.split("\\-")[0]), + mapping.getConnectionMapLcp()); + LOG.info("Key to be added to list = {}", key); + if (!clientPortList.contains(key)) { + clientPortList.add(key); + } + } catch (InterruptedException | ExecutionException e) { + LOG.error("Couldnt read mapping from datastore", e); + return null; + } + + } + return clientPortList; + } + + private OpenroadmNodeType getOpenRoadmNodeType(List xpdrNodelist) { + List openroadmNodeTypeList = new ArrayList<>(); + for (String xpdrNode:xpdrNodelist) { + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+",xpdrNode, TapiStringConstants.DSR)) + .getBytes(Charset.forName("UTF-8"))).toString()); + InstanceIdentifier nodeIID = InstanceIdentifier.builder( + Context.class).augmentation(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.topology.rev181210.Context1.class).child(TopologyContext.class) + .child(Topology.class, new TopologyKey(this.tapiTopoUuid)) + .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()) { + return null; + } + OpenroadmNodeType openroadmNodeType = OpenroadmNodeType.forName(optNode.get().getName().get( + new NameKey("Node Type")).getValue()).get(); + if (!openroadmNodeTypeList.contains(openroadmNodeType)) { + openroadmNodeTypeList.add(openroadmNodeType); + } + } catch (InterruptedException | ExecutionException e) { + LOG.error("Couldnt read node in topology", e); + return null; + } + } + // TODO for now check that there is only one type, otherwise error + if (openroadmNodeTypeList.size() != 1) { + LOG.error("More than one xpdr type. List = {}", openroadmNodeTypeList); + return null; + } + return openroadmNodeTypeList.get(0); + } } diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/impl/TapiProvider.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/impl/TapiProvider.java index 95a7e9824..aa6de506d 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/impl/TapiProvider.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/impl/TapiProvider.java @@ -128,7 +128,7 @@ public class TapiProvider { TapiLink tapiLink = new TapiLink(this.networkTransactionService); TopologyUtils topologyUtils = new TopologyUtils(this.networkTransactionService, this.dataBroker, tapiLink); ConnectivityUtils connectivityUtils = new ConnectivityUtils(this.serviceDataStoreOperations, new HashMap<>(), - tapiContext); + tapiContext, this.networkTransactionService); TapiInitialORMapping tapiInitialORMapping = new TapiInitialORMapping(topologyUtils, connectivityUtils, tapiContext, this.serviceDataStoreOperations); tapiInitialORMapping.performTopoInitialMapping(); diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiPceListenerImpl.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiPceListenerImpl.java index 17fb65cf2..0e2fc088a 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiPceListenerImpl.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiPceListenerImpl.java @@ -28,6 +28,12 @@ import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev21 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.TransportpcePceListener; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.service.path.rpc.result.PathDescription; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.service.path.rpc.result.PathDescriptionBuilder; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.Network; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mapping.Mapping; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mapping.MappingKey; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.network.Nodes; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.network.NodesKey; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmNodeType; import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.atoz.direction.AToZ; import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.resource.resource.Node; import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.resource.resource.TerminationPoint; @@ -42,6 +48,7 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Port import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Uuid; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.Name; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.NameBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.NameKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.Context1; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.CreateConnectivityServiceInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.OwnedNodeEdgePoint1; @@ -49,6 +56,9 @@ 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.cep.list.ConnectionEndPoint; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.LowerConnection; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.LowerConnectionBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.LowerConnectionKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.end.point.ClientNodeEdgePoint; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.end.point.ClientNodeEdgePointBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityService; @@ -60,6 +70,7 @@ 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.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; @@ -74,6 +85,8 @@ public class TapiPceListenerImpl implements TransportpcePceListener { private static final Logger LOG = LoggerFactory.getLogger(TapiPceListenerImpl.class); + private final Uuid tapiTopoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER + .getBytes(Charset.forName("UTF-8"))).toString()); private ServicePathRpcResult servicePathRpcResult; private CreateConnectivityServiceInput input; private Uuid serviceUuid; @@ -144,6 +157,8 @@ public class TapiPceListenerImpl implements TransportpcePceListener { LOG.error("Input is null !"); return; } + // TODO: check kind of service: based on the device Id of the input, + // verify the type of XPDR and the capacity and determine if it is an OTN service or pure WDM service // Create connections and ceps for the connectivity service. // Connections must be with a locked stated. As the renderer hasnt implemented yet the oc's Map connectionMap = createConnectionsAndCepsForService(pathDescription, @@ -244,6 +259,9 @@ public class TapiPceListenerImpl implements TransportpcePceListener { // As mentioned above, for 100GbE service creation there are ROADMs in the path description. // What are the configurations needed here? No OTU, ODU... what kind of cross connections is needed? // this needs to be changed + + // TODO: OpenROADM getNodeType from the NamesList to verify what needs to be created + OpenroadmNodeType openroadmNodeType = getOpenRoadmNodeType(xpdrNodelist); switch (serviceProtName) { case PHOTONICMEDIA: // Identify number of ROADMs @@ -261,29 +279,46 @@ public class TapiPceListenerImpl implements TransportpcePceListener { } break; case ODU: - // Check if OC and OTU are created - if (!rdmNodelist.isEmpty()) { + LOG.info("OTN ODU service"); + // - XC Connection OTSi between iODU and eODU of xpdr + // - Top connection in the ODU layer, between xpdr iODU ports + connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist)); + break; + case ETH: + LOG.info("WDM service"); + if (openroadmNodeType.equals(OpenroadmNodeType.TPDR)) { + // TODO: WDM service. Only och/otu4 needed and then directly DSR top connection. + // Need to find the associated client ports of the network port + // - Same as for PHOTONIC MEDIA service + // - Do we nedd cross connection in the ODU layer?? + // - Top connection DSR between client ports of the transponder connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist, edgeRoadm1, edgeRoadm2)); connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist)); + xpdrClientTplist = getAssociatedClientsPort(xpdrNetworkTplist); + LOG.info("Associated client ports = {}", xpdrClientTplist); + connectionServMap.putAll(createXpdrCepsAndConnectionsEth(xpdrClientTplist, xpdrNodelist, + connectionServMap)); } - // - XC Connection OTSi betwwen iODU and eODU of xpdr - // - Top connection in the ODU layer, between xpdr iODU ports (?) - connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist)); break; case DSR: - // Check if OC, OTU and ODU are created - // Check if OC, OTU and ODU are created - // TODO differentiate between 100GbE and OTN 10GbE services - if (!rdmNodelist.isEmpty()) { - connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist, - edgeRoadm1, edgeRoadm2)); - connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist)); + LOG.info("OTN XGE/ODUe service"); + // - XC connection between iODU and eODU + // - Top connection between eODU ports + // - Top connection between DSR ports + if (openroadmNodeType.equals(OpenroadmNodeType.SWITCH)) { + // TODO: We create both ODU and DSR because there is no ODU service creation for the switch + // - XC Connection OTSi betwwen iODU and eODU of xpdr + // - Top connection in the ODU layer, between xpdr eODU ports (?) connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist)); + connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist, + xpdrNodelist)); + } + if (openroadmNodeType.equals(OpenroadmNodeType.MUXPDR)) { + // TODO: OTN service but mux has 3 steps at rendering. Verify that things exist + connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist, + xpdrNodelist)); } - // Top connection in the DSR layer, between client ports of the xpdrs - connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist, - xpdrNodelist)); break; default: LOG.error("Service type format {} not supported", serviceProtName.getName()); @@ -344,6 +379,49 @@ public class TapiPceListenerImpl implements TransportpcePceListener { return true; } + private Map createXpdrCepsAndConnectionsEth(List xpdrClientTplist, + List xpdrNodelist, + Map lowerConn) { + // TODO: do we need to create cross connection between iODU and eODU?? + // add the lower connections of the previous steps for this kind of service + Map xcMap = new HashMap<>(); + for (Connection lowConn: lowerConn.values()) { + LowerConnection conn = new LowerConnectionBuilder().setConnectionUuid(lowConn.getConnectionUuid()).build(); + xcMap.put(conn.key(), conn); + } + Map connServMap = new HashMap<>(); + Map cepMapDsr = new HashMap<>(); + // Create 1 cep per Xpdr in the CLIENT + // 1 top connection DSR between the CLIENT xpdrs + for (String xpdr:xpdrNodelist) { + LOG.info("Creating ceps and xc for xpdr {}", xpdr); + String spcXpdrClient = xpdrClientTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst().get(); + + ConnectionEndPoint netCep1 = createCepXpdr(spcXpdrClient, TapiStringConstants.DSR, TapiStringConstants.DSR, + LayerProtocolName.DSR); + putXpdrCepInTopologyContext(xpdr, spcXpdrClient, TapiStringConstants.DSR, TapiStringConstants.DSR, netCep1); + + cepMapDsr.put(netCep1.key(), netCep1); + } + String spcXpdr1 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist + .get(0))).findFirst().get(); + String spcXpdr2 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist + .get(xpdrNodelist.size() - 1))).findFirst().get(); + + // DSR top connection between edge xpdr CLIENT DSR + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection + connectionDsr = createTopConnection(spcXpdr1, spcXpdr2, cepMapDsr, TapiStringConstants.DSR, + LayerProtocolName.DSR, xcMap); + this.connectionFullMap.put(connectionDsr.key(), connectionDsr); + + // DSR top connection that will be added to the service object + Connection conn1 = new ConnectionBuilder().setConnectionUuid(connectionDsr.getUuid()).build(); + connServMap.put(conn1.key(), conn1); + + return connServMap; + } + private Map createXpdrCepsAndConnectionsDsr(List xpdrClientTplist, List xpdrNetworkTplist, List xpdrNodelist) { @@ -352,6 +430,9 @@ public class TapiPceListenerImpl implements TransportpcePceListener { ConnectionEndPoint> cepMapDsr = new HashMap<>(); Map cepMapOdu = new HashMap<>(); + // TODO: when upgrading the models to 2.1.3, get the connection inclusion because those connections will + // be added to the lower connection of a top connection + Map xcMap = new HashMap<>(); // Create 1 cep per Xpdr in the CLIENT, 1 cep per Xpdr eODU, 1 XC between eODU and iODE, // 1 top connection between eODU and a top connection DSR between the CLIENT xpdrs @@ -380,28 +461,31 @@ public class TapiPceListenerImpl implements TransportpcePceListener { this.connectionFullMap.put(connection.key(), connection); // Create X connection that will be added to the service object - Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); - connServMap.put(conn.key(), conn); + LowerConnection conn = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); + xcMap.put(conn.key(), conn); } - // DSR top connection between edge xpdr CLIENT DSR String spcXpdr1 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist .get(0))).findFirst().get(); String spcXpdr2 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist .get(xpdrNodelist.size() - 1))).findFirst().get(); + // eODU top connection between edge xpdr CLIENT eODU org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connectionOdu = createTopConnection(spcXpdr1, spcXpdr2, cepMapOdu, TapiStringConstants.E_ODU, - LayerProtocolName.ODU); + LayerProtocolName.ODU, xcMap); this.connectionFullMap.put(connectionOdu.key(), connectionOdu); - // ODU top connection that will be added to the service object + // ODU top connection that will be added to the service object and also lower connection Connection conn = new ConnectionBuilder().setConnectionUuid(connectionOdu.getUuid()).build(); connServMap.put(conn.key(), conn); + LowerConnection lowerConn = new LowerConnectionBuilder().setConnectionUuid(connectionOdu.getUuid()).build(); + xcMap.put(lowerConn.key(), lowerConn); + // DSR top connection between edge xpdr CLIENT DSR org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connectionDsr = createTopConnection(spcXpdr1, spcXpdr2, cepMapDsr, TapiStringConstants.DSR, - LayerProtocolName.DSR); + LayerProtocolName.DSR, xcMap); this.connectionFullMap.put(connectionDsr.key(), connectionDsr); // DSR top connection that will be added to the service object @@ -416,6 +500,9 @@ public class TapiPceListenerImpl implements TransportpcePceListener { Map connServMap = new HashMap<>(); Map cepMap = new HashMap<>(); + // TODO: when upgrading the models to 2.1.3, get the connection inclusion because those connections will + // be added to the lower connection of a top connection + Map xcMap = new HashMap<>(); // Create 1 cep per Xpdr in the I_ODU and a top // connection iODU between the xpdrs for (String xpdr:xpdrNodelist) { @@ -437,7 +524,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener { .get(xpdrNodelist.size() - 1))).findFirst().get(); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_ODU, - LayerProtocolName.ODU); + LayerProtocolName.ODU, xcMap); this.connectionFullMap.put(connection.key(), connection); // ODU top connection that will be added to the service object @@ -452,6 +539,9 @@ public class TapiPceListenerImpl implements TransportpcePceListener { Map connServMap = new HashMap<>(); Map cepMap = new HashMap<>(); + // TODO: when upgrading the models to 2.1.3, get the connection inclusion because those connections will + // be added to the lower connection of a top connection + Map xcMap = new HashMap<>(); // create ceps and x connections within xpdr for (String xpdr:xpdrNodelist) { @@ -484,8 +574,8 @@ public class TapiPceListenerImpl implements TransportpcePceListener { this.connectionFullMap.put(connection.key(), connection); // Create X connection that will be added to the service object - Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); - connServMap.put(conn.key(), conn); + LowerConnection conn = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); + xcMap.put(conn.key(), conn); } // OTSi top connection between edge I_OTSI Xpdr String spcXpdr1 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist @@ -494,7 +584,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener { .get(xpdrNodelist.size() - 1))).findFirst().get(); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_OTSI, - LayerProtocolName.PHOTONICMEDIA); + LayerProtocolName.PHOTONICMEDIA, xcMap); this.connectionFullMap.put(connection.key(), connection); // OTSi top connection that will be added to the service object @@ -514,6 +604,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener { Map cepMap = new HashMap<>(); // create ceps and x connections within roadm + Map xcMap = new HashMap<>(); for (String roadm : rdmNodelist) { LOG.info("Creating ceps and xc for roadm {}", roadm); String spcRdmAD = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get(); @@ -561,12 +652,13 @@ public class TapiPceListenerImpl implements TransportpcePceListener { this.connectionFullMap.put(connection2.key(), connection2); // Create X connections that will be added to the service object - Connection conn1 = new ConnectionBuilder().setConnectionUuid(connection1.getUuid()).build(); - Connection conn2 = new ConnectionBuilder().setConnectionUuid(connection2.getUuid()).build(); - connServMap.put(conn1.key(), conn1); - connServMap.put(conn2.key(), conn2); + LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection1.getUuid()).build(); + LowerConnection conn2 = new LowerConnectionBuilder().setConnectionUuid(connection2.getUuid()).build(); + + xcMap.put(conn1.key(), conn1); + xcMap.put(conn2.key(), conn2); } - LOG.info("Going to create top connections betwee roadms"); + LOG.info("Going to create top connections between roadms"); // create top connections between roadms: MC connections between AD MC CEPs of roadms for (int i = 0; i < rdmNodelist.size(); i++) { if (rdmNodelist.size() <= (i + 1)) { @@ -583,13 +675,16 @@ public class TapiPceListenerImpl implements TransportpcePceListener { // Create top connections between MC for full map org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.MC, - LayerProtocolName.PHOTONICMEDIA); + LayerProtocolName.PHOTONICMEDIA, xcMap); this.connectionFullMap.put(connection.key(), connection); LOG.info("Top connection created = {}", connection.toString()); - // Create top connections that will be added to the service object + // Create top connections that will be added to the service object and lower + // connection to the next top connection Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); connServMap.put(conn.key(), conn); + LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); + xcMap.put(conn1.key(), conn1); } // OTSiMC top connection between edge roadms @@ -598,7 +693,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener { String spcRdmAD2 = rdmAddDropTplist.stream().filter(adp -> adp.contains(edgeRoadm2)).findFirst().get(); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.OTSI_MC, - LayerProtocolName.PHOTONICMEDIA); + LayerProtocolName.PHOTONICMEDIA, xcMap); this.connectionFullMap.put(connection.key(), connection); LOG.info("Top connection created = {}", connection.toString()); @@ -612,7 +707,8 @@ public class TapiPceListenerImpl implements TransportpcePceListener { createTopConnection(String tp1, String tp2, Map cepMap, String qual, LayerProtocolName topPortocol) { + ConnectionEndPoint> cepMap, String qual, LayerProtocolName topPortocol, + Map xcMap) { // find cep for each AD MC of roadm 1 and 2 LOG.info("Top connection name = {}", String.join("+", "TOP", tp1, tp2, qual)); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ConnectionEndPoint adCep1 = @@ -672,6 +768,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener { .setLayerProtocolName(topPortocol) .setLifecycleState(LifecycleState.POTENTIALAVAILABLE) .setDirection(ForwardingDirection.BIDIRECTIONAL) + .setLowerConnection(xcMap) .build(); } @@ -721,9 +818,9 @@ public class TapiPceListenerImpl implements TransportpcePceListener { .getBytes(Charset.forName("UTF-8"))).toString())) .setName(Map.of(connName.key(), connName)) .setConnectionEndPoint(ceps) - .setOperationalState(OperationalState.DISABLED) + .setOperationalState(OperationalState.ENABLED) .setLayerProtocolName(xcProtocol) - .setLifecycleState(LifecycleState.POTENTIALAVAILABLE) + .setLifecycleState(LifecycleState.INSTALLED) .setDirection(ForwardingDirection.BIDIRECTIONAL) .build(); } @@ -1011,6 +1108,74 @@ public class TapiPceListenerImpl implements TransportpcePceListener { return null; } + private OpenroadmNodeType getOpenRoadmNodeType(List xpdrNodelist) { + List openroadmNodeTypeList = new ArrayList<>(); + for (String xpdrNode:xpdrNodelist) { + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+",xpdrNode, TapiStringConstants.DSR)) + .getBytes(Charset.forName("UTF-8"))).toString()); + InstanceIdentifier nodeIID = InstanceIdentifier.builder( + Context.class).augmentation(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.topology.rev181210.Context1.class).child(TopologyContext.class) + .child(Topology.class, new TopologyKey(this.tapiTopoUuid)) + .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()) { + return null; + } + OpenroadmNodeType openroadmNodeType = OpenroadmNodeType.forName(optNode.get().getName().get( + new NameKey("Node Type")).getValue()).get(); + if (!openroadmNodeTypeList.contains(openroadmNodeType)) { + openroadmNodeTypeList.add(openroadmNodeType); + } + } catch (InterruptedException | ExecutionException e) { + LOG.error("Couldnt read node in topology", e); + return null; + } + } + // TODO for now check that there is only one type, otherwise error + if (openroadmNodeTypeList.size() != 1) { + LOG.error("More than one xpdr type. List = {}", openroadmNodeTypeList); + return null; + } + return openroadmNodeTypeList.get(0); + } + + private List getAssociatedClientsPort(List xpdrNetworkTplist) { + List clientPortList = new ArrayList<>(); + for (String networkPort:xpdrNetworkTplist) { + String nodeId = String.join("-", networkPort.split("\\+")[0].split("-")[0], + networkPort.split("\\+")[0].split("-")[1]); + String tpId = networkPort.split("\\+")[1]; + InstanceIdentifier mapIID = InstanceIdentifier.builder(Network.class) + .child(Nodes.class, new NodesKey(nodeId)) + .child(Mapping.class, new MappingKey(tpId)).build(); + try { + Optional optMapping = this.networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, + mapIID).get(); + if (!optMapping.isPresent()) { + LOG.error("Couldnt find mapping for port {} of node {}", tpId, nodeId); + } + Mapping mapping = optMapping.get(); + LOG.info("Mapping for node+port {}+{} = {}", nodeId, tpId, mapping); + String key = String.join("+", String.join("-", nodeId, tpId.split("\\-")[0]), + mapping.getConnectionMapLcp()); + LOG.info("Key to be added to list = {}", key); + if (!clientPortList.contains(key)) { + clientPortList.add(key); + } + } catch (InterruptedException | ExecutionException e) { + LOG.error("Couldnt read mapping from datastore", e); + return null; + } + + } + return clientPortList; + } + public void setInput(CreateConnectivityServiceInput input) { this.input = input; } diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiFullTopo.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiFullTopo.java index b5c869eb1..0cf7cf835 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiFullTopo.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiFullTopo.java @@ -174,11 +174,14 @@ public class ConvertORTopoToTapiFullTopo { Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", this.ietfNodeId, TapiStringConstants.DSR)).getBytes(Charset.forName("UTF-8"))).toString()); this.uuidMap.put(String.join("+", this.ietfNodeId, TapiStringConstants.DSR), nodeUuid); - Name nameDsr = new NameBuilder().setValueName("dsr/odu node name").setValue( + Name nameDsrNode = new NameBuilder().setValueName("dsr/odu node name").setValue( String.join("+", this.ietfNodeId, TapiStringConstants.DSR)).build(); + Name nameNodeType = new NameBuilder().setValueName("Node Type") + .setValue(this.ietfNodeType.getName()).build(); List dsrLayerProtocols = Arrays.asList(LayerProtocolName.DSR, LayerProtocolName.ODU); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology - .Node dsrNode = createTapiNode(Map.of(nameDsr.key(), nameDsr), dsrLayerProtocols); + .Node dsrNode = createTapiNode(Map.of(nameDsrNode.key(), nameDsrNode, nameNodeType.key(), nameNodeType), + dsrLayerProtocols); LOG.info("DSR Node {} should have {} NEPs and {} SIPs", this.ietfNodeId, this.oorClientPortList.size() + 2 * this.oorNetworkPortList.size(), this.oorClientPortList.size() + this.oorNetworkPortList.size()); @@ -192,11 +195,12 @@ public class ConvertORTopoToTapiFullTopo { nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", this.ietfNodeId, TapiStringConstants.OTSI)) .getBytes(Charset.forName("UTF-8"))).toString()); this.uuidMap.put(String.join("+", this.ietfNodeId, TapiStringConstants.OTSI), nodeUuid); - Name nameOtsi = new NameBuilder().setValueName("otsi node name").setValue( + Name nameOtsiNode = new NameBuilder().setValueName("otsi node name").setValue( String.join("+", this.ietfNodeId, TapiStringConstants.OTSI)).build(); List otsiLayerProtocols = Arrays.asList(LayerProtocolName.PHOTONICMEDIA); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology - .Node otsiNode = createTapiNode(Map.of(nameOtsi.key(), nameOtsi), otsiLayerProtocols); + .Node otsiNode = createTapiNode(Map.of(nameOtsiNode.key(), nameOtsiNode, nameNodeType.key(), nameNodeType), + otsiLayerProtocols); LOG.info("OTSi Node {} should have {} NEPs and {} SIPs", this.ietfNodeId, 3 * this.oorNetworkPortList.size(), this.oorNetworkPortList.size()); LOG.info("OTSi Node {} has {} NEPs and {} SIPs", this.ietfNodeId, @@ -317,6 +321,8 @@ public class ConvertORTopoToTapiFullTopo { public void convertRoadmNode(Node roadm, Network openroadmTopo) { this.ietfNodeId = roadm.getNodeId().getValue(); + this.ietfNodeType = roadm.augmentation( + org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1.class).getNodeType(); Map oneplist = new HashMap<>(); // 1. Get degree and srg nodes to map TPs into NEPs if (openroadmTopo.getNode() == null) { @@ -395,11 +401,14 @@ public class ConvertORTopoToTapiFullTopo { // Names Name nodeNames = new NameBuilder().setValueName("roadm node name") .setValue(String.join("+", roadm.getNodeId().getValue(), TapiStringConstants.PHTNC_MEDIA)).build(); + Name nameNodeType = new NameBuilder().setValueName("Node Type") + .setValue(this.ietfNodeType.getName()).build(); // Protocol Layer List layerProtocols = Arrays.asList(LayerProtocolName.PHOTONICMEDIA); // Build tapi node org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology - .Node roadmNode = createRoadmTapiNode(nodeUuid, nodeNames, layerProtocols, oneplist); + .Node roadmNode = createRoadmTapiNode(nodeUuid, + Map.of(nodeNames.key(), nodeNames, nameNodeType.key(), nameNodeType), layerProtocols, oneplist); // TODO add states corresponding to device config LOG.info("ROADM node {} should have {} NEPs and {} SIPs", roadm.getNodeId().getValue(), numNeps, numSips); LOG.info("ROADM node {} has {} NEPs and {} SIPs", roadm.getNodeId().getValue(), @@ -488,7 +497,7 @@ public class ConvertORTopoToTapiFullTopo { } private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node - createRoadmTapiNode(Uuid nodeUuid, Name nodeNames, List layerProtocols, + createRoadmTapiNode(Uuid nodeUuid, Map nameMap, List layerProtocols, Map oneplist) { // Empty random creation of mandatory fields for avoiding errors.... CostCharacteristic costCharacteristic = new CostCharacteristicBuilder() @@ -505,7 +514,7 @@ public class ConvertORTopoToTapiFullTopo { .build(); return new NodeBuilder() .setUuid(nodeUuid) - .setName(Map.of(nodeNames.key(), nodeNames)) + .setName(nameMap) .setLayerProtocolName(layerProtocols) .setAdministrativeState(AdministrativeState.UNLOCKED) .setOperationalState(OperationalState.ENABLED) diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopo.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopo.java index 79b997d2f..c74bce770 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopo.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopo.java @@ -167,9 +167,12 @@ public class ConvertORTopoToTapiTopo { this.uuidMap.put(String.join("+", this.ietfNodeId, TapiStringConstants.DSR), nodeUuid); Name nameDsr = new NameBuilder().setValueName("dsr/odu node name") .setValue(String.join("+", this.ietfNodeId, TapiStringConstants.DSR)).build(); + Name nameNodeType = new NameBuilder().setValueName("Node Type") + .setValue(this.ietfNodeType.getName()).build(); List dsrLayerProtocols = Arrays.asList(LayerProtocolName.DSR, LayerProtocolName.ODU); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology - .Node dsrNode = createTapiNode(Map.of(nameDsr.key(), nameDsr), dsrLayerProtocols); + .Node dsrNode = createTapiNode(Map.of(nameDsr.key(), nameDsr, nameNodeType.key(), nameNodeType), + dsrLayerProtocols); tapiNodes.put(dsrNode.key(), dsrNode); // node creation [otsi] @@ -181,7 +184,8 @@ public class ConvertORTopoToTapiTopo { .setValue(String.join("+", this.ietfNodeId, TapiStringConstants.OTSI)).build(); List otsiLayerProtocols = Arrays.asList(LayerProtocolName.PHOTONICMEDIA); org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology - .Node otsiNode = createTapiNode(Map.of(nameOtsi.key(), nameOtsi), otsiLayerProtocols); + .Node otsiNode = createTapiNode(Map.of(nameOtsi.key(), nameOtsi, nameNodeType.key(), nameNodeType), + otsiLayerProtocols); tapiNodes.put(otsiNode.key(), otsiNode); // transitional link cration between network nep of DSR/ODU node and iNep of otsi node @@ -251,6 +255,8 @@ public class ConvertORTopoToTapiTopo { .getBytes(Charset.forName("UTF-8"))).toString()); Name nodeName = new NameBuilder().setValueName("otsi node name").setValue(TapiStringConstants.RDM_INFRA) .build(); + Name nameNodeType = new NameBuilder().setValueName("Node Type") + .setValue(OpenroadmNodeType.ROADM.getName()).build(); List nodeLayerProtocols = Arrays.asList(LayerProtocolName.PHOTONICMEDIA); List tapiPhotonicNodes @@ -264,7 +270,7 @@ public class ConvertORTopoToTapiTopo { // build RDM infra node abstraction org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node rdmNode = new NodeBuilder() .setUuid(nodeUuid) - .setName(Map.of(nodeName.key(), nodeName)) + .setName(Map.of(nodeName.key(), nodeName, nameNodeType.key(), nameNodeType)) .setLayerProtocolName(nodeLayerProtocols) .setAdministrativeState(AdministrativeState.UNLOCKED) .setOperationalState(OperationalState.ENABLED) diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiNetworkModelServiceImpl.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiNetworkModelServiceImpl.java index d4a63599e..0e9b5a0c2 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiNetworkModelServiceImpl.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiNetworkModelServiceImpl.java @@ -244,10 +244,12 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { .getBytes(Charset.forName("UTF-8"))).toString()); Name nameDsr = new NameBuilder().setValueName("dsr/odu node name").setValue( String.join("+", nodeId, TapiStringConstants.DSR)).build(); + Name nameNodeType = new NameBuilder().setValueName("Node Type") + .setValue(getNodeType(xponderType)).build(); List dsrLayerProtocols = Arrays.asList(LayerProtocolName.DSR, LayerProtocolName.ODU); - Node dsrNode = createTapiXpdrNode(Map.of(nameDsr.key(), nameDsr), dsrLayerProtocols, - nodeId, nodeUuidDsr, xpdrClMaps, xpdrNetMaps, xponderType, oorOduSwitchingPool); + Node dsrNode = createTapiXpdrNode(Map.of(nameDsr.key(), nameDsr, nameNodeType.key(), nameNodeType), + dsrLayerProtocols, nodeId, nodeUuidDsr, xpdrClMaps, xpdrNetMaps, xponderType, oorOduSwitchingPool); nodeMap.put(dsrNode.key(), dsrNode); @@ -258,8 +260,8 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { Name nameOtsi = new NameBuilder().setValueName("otsi node name").setValue( String.join("+", nodeId, TapiStringConstants.OTSI)).build(); List otsiLayerProtocols = Arrays.asList(LayerProtocolName.PHOTONICMEDIA); - Node otsiNode = createTapiXpdrNode(Map.of(nameOtsi.key(), nameOtsi), otsiLayerProtocols, - nodeId, nodeUuidOtsi, xpdrClMaps, xpdrNetMaps, xponderType, null); + Node otsiNode = createTapiXpdrNode(Map.of(nameOtsi.key(), nameOtsi, nameNodeType.key(), nameNodeType), + otsiLayerProtocols, nodeId, nodeUuidOtsi, xpdrClMaps, xpdrNetMaps, xponderType, null); nodeMap.put(otsiNode.key(), otsiNode); @@ -278,7 +280,7 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { switch (xpdrType) { case 1: // Tpdr - return createTpdrSwitchPool(); + return createTpdrSwitchPool(xpdrNetMaps); case 2: // Mux return createMuxSwitchPool(xpdrClMaps, xpdrNetMaps, xpdrNb); @@ -779,6 +781,8 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { // Names Name nodeNames = new NameBuilder().setValueName("roadm node name") .setValue(String.join("+", orNodeId, TapiStringConstants.PHTNC_MEDIA)).build(); + Name nameNodeType = new NameBuilder().setValueName("Node Type") + .setValue(OpenroadmNodeType.ROADM.getName()).build(); // Protocol Layer List layerProtocols = Arrays.asList(LayerProtocolName.PHOTONICMEDIA); // Empty random creation of mandatory fields for avoiding errors.... @@ -796,7 +800,7 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { .build(); return new NodeBuilder() .setUuid(nodeUuid) - .setName(Map.of(nodeNames.key(), nodeNames)) + .setName(Map.of(nodeNames.key(), nodeNames, nameNodeType.key(), nameNodeType)) .setLayerProtocolName(layerProtocols) .setAdministrativeState(AdministrativeState.UNLOCKED) .setOperationalState(OperationalState.ENABLED) @@ -861,8 +865,28 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { return linkMap; } - private OduSwitchingPools createTpdrSwitchPool() { - return new OduSwitchingPoolsBuilder().build(); + private OduSwitchingPools createTpdrSwitchPool(List xpdrNetMaps) { + Map nblMap = new HashMap<>(); + int count = 1; + for (int i = 1; i <= xpdrNetMaps.size(); i++) { + LOG.info("XPDr net LCP = {}", xpdrNetMaps.get(i - 1).getLogicalConnectionPoint()); + LOG.info("XPDr net associated LCP = {}", xpdrNetMaps.get(i - 1).getConnectionMapLcp()); + TpId tpid1 = new TpId(xpdrNetMaps.get(i - 1).getLogicalConnectionPoint()); + TpId tpid2 = new TpId(xpdrNetMaps.get(i - 1).getConnectionMapLcp()); + List tpList = new ArrayList<>(); + tpList.add(tpid1); + tpList.add(tpid2); + NonBlockingList nbl = new NonBlockingListBuilder() + .setNblNumber(Uint16.valueOf(count)) + .setTpList(tpList) + .build(); + nblMap.put(nbl.key(), nbl); + count++; + } + return new OduSwitchingPoolsBuilder() + .setNonBlockingList(nblMap) + .setSwitchingPoolNumber(Uint16.valueOf(1)) + .build(); } private OduSwitchingPools createSwtchSwitchPool(List xpdrClMaps, List xpdrNetMaps, @@ -980,7 +1004,7 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { OwnedNodeEdgePoint> onepl) { // create NodeRuleGroup if (oorOduSwitchingPool == null) { - LOG.info("TPDR node --> no switching pool"); + LOG.info("No switching pool created for node = {}", nodeId); return new HashMap<>(); } LOG.info("ONEPL = {}", onepl.values()); @@ -1168,6 +1192,21 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { } } + private String getNodeType(XpdrNodeTypes xponderType) { + switch (xponderType.getIntValue()) { + case 1: + return OpenroadmNodeType.TPDR.getName(); + case 2: + return OpenroadmNodeType.MUXPDR.getName(); + case 3: + return OpenroadmNodeType.SWITCH.getName(); + default: + LOG.info("XpdrType {} not supported", xponderType); + break; + } + return null; + } + private void mergeNodeinTopology(Map nodeMap) { // TODO is this merge correct? Should we just merge topology by changing the nodes map?? // TODO: verify this is correct. Should we identify the context IID with the context UUID?? diff --git a/tapi/src/test/java/org/opendaylight/transportpce/tapi/connectivity/TapiConnectivityImplTest.java b/tapi/src/test/java/org/opendaylight/transportpce/tapi/connectivity/TapiConnectivityImplTest.java index e4718c30e..e0e1abdf3 100644 --- a/tapi/src/test/java/org/opendaylight/transportpce/tapi/connectivity/TapiConnectivityImplTest.java +++ b/tapi/src/test/java/org/opendaylight/transportpce/tapi/connectivity/TapiConnectivityImplTest.java @@ -126,7 +126,8 @@ public class TapiConnectivityImplTest extends AbstractTest { tapiContext = new TapiContext(networkTransactionService); topologyUtils = new TopologyUtils(networkTransactionService, getDataStoreContextUtil().getDataBroker(), tapilink); - connectivityUtils = new ConnectivityUtils(serviceDataStoreOperations, new HashMap<>(), tapiContext); + connectivityUtils = new ConnectivityUtils(serviceDataStoreOperations, new HashMap<>(), tapiContext, + networkTransactionService); tapiInitialORMapping = new TapiInitialORMapping(topologyUtils, connectivityUtils, tapiContext, serviceDataStoreOperations); tapiInitialORMapping.performTopoInitialMapping(); diff --git a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToFullTapiTopoTest.java b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToFullTapiTopoTest.java index 6c67a84d3..599357ffa 100644 --- a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToFullTapiTopoTest.java +++ b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToFullTapiTopoTest.java @@ -873,8 +873,8 @@ public class ConvertORTopoToFullTapiTopoTest extends AbstractTest { AdministrativeState.UNLOCKED, node.getAdministrativeState()); assertEquals("life-cycle state should be INSTALLED", LifecycleState.INSTALLED, node.getLifecycleState()); assertEquals("operational state should be ENABLED", OperationalState.ENABLED, node.getOperationalState()); - assertEquals("value-name should be 'dsr/odu node name'", - "dsr/odu node name", node.nonnullName().values().stream().findFirst().get().getValueName()); + assertThat("one value-name should be 'dsr/odu node name'", + new ArrayList<>(node.nonnullName().keySet()), hasItem(new NameKey("dsr/odu node name"))); assertEquals("dsr node should manage 2 protocol layers : dsr and odu", 2, node.getLayerProtocolName().size()); assertThat("dsr node should manage 2 protocol layers : dsr and odu", @@ -994,8 +994,8 @@ public class ConvertORTopoToFullTapiTopoTest extends AbstractTest { if (!otsiNodeType.equals("roadm")) { assertEquals("incorrect node name", nodeId + "+OTSi", node.getName().get( new NameKey("otsi node name")).getValue()); - assertEquals("value-name should be 'dsr/odu node name'", - "otsi node name", node.nonnullName().values().stream().findFirst().get().getValueName()); + assertThat("one value-name should be 'dsr/odu node name'", + new ArrayList<>(node.nonnullName().keySet()), hasItem(new NameKey("otsi node name"))); nepsI = node.nonnullOwnedNodeEdgePoint().values().stream() .filter(n -> n.getName().containsKey(new NameKey("iNodeEdgePoint"))) .sorted((nep1, nep2) -> nep1.getUuid().getValue().compareTo(nep2.getUuid().getValue())) @@ -1011,8 +1011,8 @@ public class ConvertORTopoToFullTapiTopoTest extends AbstractTest { } else { assertEquals("incorrect node name", nodeId + "+PHOTONIC_MEDIA", node.getName().get( new NameKey("roadm node name")).getValue()); - assertEquals("value-name should be 'dsr/odu node name'", - "roadm node name", node.nonnullName().values().stream().findFirst().get().getValueName()); + assertThat("one value-name should be 'dsr/odu node name'", + new ArrayList<>(node.nonnullName().keySet()), hasItem(new NameKey("roadm node name"))); nepsMc = node.nonnullOwnedNodeEdgePoint().values().stream() .filter(n -> n.getName().containsKey(new NameKey("MEDIA_CHANNELNodeEdgePoint"))) .sorted((nep1, nep2) -> nep1.getUuid().getValue().compareTo(nep2.getUuid().getValue())) diff --git a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopoTest.java b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopoTest.java index 961bd593b..6f1789305 100644 --- a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopoTest.java +++ b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopoTest.java @@ -718,8 +718,8 @@ public class ConvertORTopoToTapiTopoTest extends AbstractTest { AdministrativeState.UNLOCKED, node.getAdministrativeState()); assertEquals("life-cycle state should be INSTALLED", LifecycleState.INSTALLED, node.getLifecycleState()); assertEquals("operational state should be ENABLED", OperationalState.ENABLED, node.getOperationalState()); - assertEquals("value-name should be 'dsr/odu node name'", - "dsr/odu node name", node.nonnullName().values().stream().findFirst().get().getValueName()); + assertThat("one value-name should be 'dsr/odu node name'", + new ArrayList<>(node.nonnullName().keySet()), hasItem(new NameKey("dsr/odu node name"))); assertEquals("dsr node should manage 2 protocol layers : dsr and odu", 2, node.getLayerProtocolName().size()); assertThat("dsr node should manage 2 protocol layers : dsr and odu", @@ -819,8 +819,8 @@ public class ConvertORTopoToTapiTopoTest extends AbstractTest { AdministrativeState.UNLOCKED, node.getAdministrativeState()); assertEquals("life-cycle state should be INSTALLED", LifecycleState.INSTALLED, node.getLifecycleState()); assertEquals("operational state should be ENABLED", OperationalState.ENABLED, node.getOperationalState()); - assertEquals("value-name should be 'dsr/odu node name'", - "otsi node name", node.nonnullName().values().stream().findFirst().get().getValueName()); + assertThat("one value-name should be 'dsr/odu node name'", + new ArrayList<>(node.nonnullName().keySet()), hasItem(new NameKey("otsi node name"))); assertEquals("otsi node should manage a single protocol layer : PHOTONIC_MEDIA", 1, node.getLayerProtocolName().size()); assertEquals("otsi node should manage a single protocol layer : PHOTONIC_MEDIA", diff --git a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplTest.java b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplTest.java index 47e64ec0a..920247492 100644 --- a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplTest.java +++ b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplTest.java @@ -112,7 +112,8 @@ public class TapiTopologyImplTest extends AbstractTest { tapiContext = new TapiContext(networkTransactionService); topologyUtils = new TopologyUtils(networkTransactionService, getDataStoreContextUtil().getDataBroker(), tapiLink); - connectivityUtils = new ConnectivityUtils(serviceDataStoreOperations, new HashMap<>(), tapiContext); + connectivityUtils = new ConnectivityUtils(serviceDataStoreOperations, new HashMap<>(), tapiContext, + networkTransactionService); tapiInitialORMapping = new TapiInitialORMapping(topologyUtils, connectivityUtils, tapiContext, serviceDataStoreOperations); tapiInitialORMapping.performTopoInitialMapping(); @@ -186,35 +187,40 @@ public class TapiTopologyImplTest extends AbstractTest { assertEquals("Node list size should be 13", 13, topology.getNode().size()); long nb1 = topology.getNode().values().stream() .filter(node -> node.getLayerProtocolName().contains(LayerProtocolName.DSR)) - .filter(node -> node.getName().values().stream().findFirst().get().getValue().equals("XPDR-A1-XPDR1+DSR")) + .filter(node -> node.getName().get(new NameKey("dsr/odu node name")).getValue() + .equals("XPDR-A1-XPDR1+DSR")) .flatMap(node -> node.getOwnedNodeEdgePoint().values().stream() .filter(nep -> nep.getName().containsKey(new NameKey("100G-tpdr")))) .count(); assertEquals("XPDR-A1-XPDR1 should only have one client nep", 1, nb1); long nb2 = topology.getNode().values().stream() .filter(node -> node.getLayerProtocolName().contains(LayerProtocolName.DSR)) - .filter(node -> node.getName().values().stream().findFirst().get().getValue().equals("SPDR-SA1-XPDR1+DSR")) + .filter(node -> node.getName().get(new NameKey("dsr/odu node name")).getValue() + .equals("SPDR-SA1-XPDR1+DSR")) .flatMap(node -> node.getOwnedNodeEdgePoint().values().stream() .filter(nep -> nep.getName().containsKey(new NameKey("NodeEdgePoint_C")))) .count(); assertEquals("SPDR-SA1-XPDR1 (mux) should have 4 client neps", 4, nb2); long nb3 = topology.getNode().values().stream() .filter(node -> node.getLayerProtocolName().contains(LayerProtocolName.DSR)) - .filter(node -> node.getName().values().stream().findFirst().get().getValue().equals("SPDR-SA1-XPDR1+DSR")) + .filter(node -> node.getName().get(new NameKey("dsr/odu node name")).getValue() + .equals("SPDR-SA1-XPDR1+DSR")) .flatMap(node -> node.getOwnedNodeEdgePoint().values().stream() .filter(nep -> nep.getName().containsKey(new NameKey("iNodeEdgePoint_N")))) .count(); assertEquals("SPDR-SA1-XPDR1 (mux) should have a single network nep", 1, nb3); long nb4 = topology.getNode().values().stream() .filter(node -> node.getLayerProtocolName().contains(LayerProtocolName.DSR)) - .filter(node -> node.getName().values().stream().findFirst().get().getValue().equals("SPDR-SA1-XPDR2+DSR")) + .filter(node -> node.getName().get(new NameKey("dsr/odu node name")).getValue() + .equals("SPDR-SA1-XPDR2+DSR")) .flatMap(node -> node.getOwnedNodeEdgePoint().values().stream() .filter(nep -> nep.getName().containsKey(new NameKey("NodeEdgePoint_C")))) .count(); assertEquals("SPDR-SA1-XPDR2 (switch) should have 4 client neps", 4, nb4); long nb5 = topology.getNode().values().stream() .filter(node -> node.getLayerProtocolName().contains(LayerProtocolName.DSR)) - .filter(node -> node.getName().values().stream().findFirst().get().getValue().equals("SPDR-SA1-XPDR2+DSR")) + .filter(node -> node.getName().get(new NameKey("dsr/odu node name")).getValue() + .equals("SPDR-SA1-XPDR2+DSR")) .flatMap(node -> node.getOwnedNodeEdgePoint().values().stream() .filter(nep -> nep.getName().containsKey(new NameKey("iNodeEdgePoint_N")))) .count(); diff --git a/tests/transportpce_tests/2.2.1/test13_tapi_full_multi_layer.py b/tests/transportpce_tests/2.2.1/test13_tapi_full_multi_layer.py index 2baf41cbd..910ba2899 100644 --- a/tests/transportpce_tests/2.2.1/test13_tapi_full_multi_layer.py +++ b/tests/transportpce_tests/2.2.1/test13_tapi_full_multi_layer.py @@ -431,17 +431,17 @@ class TransportPCEtesting(unittest.TestCase): self.assertEqual(ele['operational-state'], 'ENABLED') self.assertEqual(ele['service-layer'], 'PHOTONIC_MEDIA') nbconnection = len(ele['connection']) - self.assertEqual(nbconnection, 9, 'There should be 9 connections') + self.assertEqual(nbconnection, 3, 'There should be 3 connections') elif ele['uuid'] == self.uuid_services.odu: self.assertEqual(ele['operational-state'], 'ENABLED') self.assertEqual(ele['service-layer'], 'ODU') nbconnection = len(ele['connection']) - self.assertEqual(nbconnection, 1, 'There should be 3 connections') + self.assertEqual(nbconnection, 1, 'There should be 1 connections') elif ele['uuid'] == self.uuid_services.dsr: self.assertEqual(ele['operational-state'], 'ENABLED') self.assertEqual(ele['service-layer'], 'DSR') nbconnection = len(ele['connection']) - self.assertEqual(nbconnection, 4, 'There should be 4 connections') + self.assertEqual(nbconnection, 2, 'There should be 2 connections') else: self.fail("get connectivity service failed") time.sleep(2)