From: Javier Errea Date: Mon, 8 Feb 2021 19:30:59 +0000 (+0100) Subject: TAPI Connectivity service RPCs impl X-Git-Tag: 4.0.0~99 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=transportpce.git;a=commitdiff_plain;h=refs%2Fchanges%2F73%2F95073%2F43 TAPI Connectivity service RPCs impl - Connectivity Service RPCs implementation - Population on Connectivity Context: Service and Connection - Added listeners for TAPI module -> as Service Handler module - Modification of TAPI blueprint according to dev. JIRA: TRNSPRTPCE-386 Change-Id: I63cfffe7b3b2387c0f4229c5f9a1a482fa5b4562 Signed-off-by: errea --- diff --git a/lighty/src/main/java/io/lighty/controllers/tpce/module/TransportPCEImpl.java b/lighty/src/main/java/io/lighty/controllers/tpce/module/TransportPCEImpl.java index 07855f03d..bdaedc68f 100644 --- a/lighty/src/main/java/io/lighty/controllers/tpce/module/TransportPCEImpl.java +++ b/lighty/src/main/java/io/lighty/controllers/tpce/module/TransportPCEImpl.java @@ -11,6 +11,7 @@ import io.lighty.core.controller.api.AbstractLightyModule; import io.lighty.core.controller.api.LightyServices; import java.util.Arrays; import java.util.List; +import org.opendaylight.mdsal.binding.api.NotificationService; import org.opendaylight.transportpce.common.crossconnect.CrossConnect; import org.opendaylight.transportpce.common.crossconnect.CrossConnectImpl; import org.opendaylight.transportpce.common.crossconnect.CrossConnectImpl121; @@ -76,6 +77,9 @@ import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOper import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperationsImpl; import org.opendaylight.transportpce.tapi.R2RTapiLinkDiscovery; import org.opendaylight.transportpce.tapi.impl.TapiProvider; +import org.opendaylight.transportpce.tapi.listeners.TapiPceListenerImpl; +import org.opendaylight.transportpce.tapi.listeners.TapiRendererListenerImpl; +import org.opendaylight.transportpce.tapi.listeners.TapiServiceHandlerListenerImpl; import org.opendaylight.transportpce.tapi.topology.TapiNetconfTopologyListener; import org.opendaylight.transportpce.tapi.topology.TapiNetworkModelService; import org.opendaylight.transportpce.tapi.topology.TapiNetworkModelServiceImpl; @@ -199,6 +203,11 @@ public class TransportPCEImpl extends AbstractLightyModule implements TransportP LOG.info("Creating tapi beans ..."); R2RTapiLinkDiscovery tapilinkDiscoveryImpl = new R2RTapiLinkDiscovery(lightyServices.getBindingDataBroker(), deviceTransactionManager); + TapiRendererListenerImpl tapiRendererListenerImpl = new TapiRendererListenerImpl(lightyServices + .getBindingDataBroker()); + TapiPceListenerImpl tapiPceListenerImpl = new TapiPceListenerImpl(lightyServices.getBindingDataBroker()); + TapiServiceHandlerListenerImpl tapiServiceHandlerListener = new TapiServiceHandlerListenerImpl(lightyServices + .getBindingDataBroker()); TransportpceTapinetworkutilsService tapiNetworkutilsServiceImpl = new TapiNetworkUtilsImpl( networkTransaction); TapiNetworkModelService tapiNetworkModelService = new TapiNetworkModelServiceImpl( @@ -207,8 +216,10 @@ public class TransportPCEImpl extends AbstractLightyModule implements TransportP new TapiNetconfTopologyListener(tapiNetworkModelService); TapiPortMappingListener tapiPortMappingListener = new TapiPortMappingListener(tapiNetworkModelService); + tapiProvider = initTapi(lightyServices, servicehandler, networkTransaction, serviceDataStoreOperations, - tapiNetConfTopologyListener, tapiPortMappingListener, tapiNetworkutilsServiceImpl); + tapiNetConfTopologyListener, tapiPortMappingListener, tapiNetworkutilsServiceImpl, tapiPceListenerImpl, + tapiRendererListenerImpl, tapiServiceHandlerListener, lightyServices.getNotificationService()); if(activateNbiNotification) { LOG.info("Creating nbi-notifications beans ..."); nbiNotificationsProvider = new NbiNotificationsProvider( @@ -273,10 +284,14 @@ public class TransportPCEImpl extends AbstractLightyModule implements TransportP ServiceDataStoreOperations serviceDataStoreOperations, TapiNetconfTopologyListener tapiNetConfTopologyListener, TapiPortMappingListener tapiPortMappingListener, - TransportpceTapinetworkutilsService tapiNetworkutilsServiceImpl) { + TransportpceTapinetworkutilsService tapiNetworkutilsServiceImpl, + TapiPceListenerImpl pceListenerImpl, TapiRendererListenerImpl rendererListenerImpl, + TapiServiceHandlerListenerImpl serviceHandlerListenerImpl, + NotificationService notificationService) { return new TapiProvider(lightyServices.getBindingDataBroker(), lightyServices.getRpcProviderService(), servicehandler, serviceDataStoreOperations, new TapiListener(), networkTransaction, - tapiNetConfTopologyListener, tapiPortMappingListener, tapiNetworkutilsServiceImpl); + tapiNetConfTopologyListener, tapiPortMappingListener, tapiNetworkutilsServiceImpl, pceListenerImpl, + rendererListenerImpl, serviceHandlerListenerImpl, notificationService); } /** 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 df390295c..e1d7d056f 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 @@ -9,6 +9,7 @@ package org.opendaylight.transportpce.tapi.connectivity; import java.nio.charset.Charset; import java.util.ArrayList; +import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -28,9 +29,12 @@ 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; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.sdnc.request.header.SdncRequestHeaderBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.endpoint.RxDirectionBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.endpoint.SubrateEthSlaBuilder; 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.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; import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceCreateInput; import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceCreateInputBuilder; @@ -46,6 +50,7 @@ import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdes import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.pce.resource.resource.resource.Node; import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.pce.resource.resource.resource.TerminationPoint; import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths; +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.ForwardingDirection; @@ -61,7 +66,9 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.glob 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.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; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ProtectionRole; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ServiceType; 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; @@ -77,6 +84,10 @@ 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.EndPointKey; 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.node.OwnedNodeEdgePoint; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.edge.point.MappedServiceInterfacePointKey; +import org.opendaylight.yangtools.yang.common.Uint16; import org.opendaylight.yangtools.yang.common.Uint32; import org.opendaylight.yangtools.yang.common.Uint64; import org.slf4j.Logger; @@ -100,6 +111,8 @@ public final class ConnectivityUtils { private static final String OTSI_MC = "OTSi_MEDIA_CHANNEL"; private static final String TP = "TerminationPoint"; private static final String NODE = "Node"; + private final Uuid tapiTopoUuid = new Uuid(UUID.nameUUIDFromBytes(TopologyUtils.T0_FULL_MULTILAYER + .getBytes(Charset.forName("UTF-8"))).toString()); private static final Logger LOG = LoggerFactory.getLogger(ConnectivityUtils.class); private final ServiceDataStoreOperations serviceDataStoreOperations; @@ -109,6 +122,7 @@ public final class ConnectivityUtils { .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey, 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<>(); // TODO -> handle cases for which node id is ROADM-A1 and not ROADMA01 or XPDR-A1 and not XPDRA01 public ConnectivityUtils(ServiceDataStoreOperations serviceDataStoreOperations, @@ -280,6 +294,8 @@ public final class ConnectivityUtils { .setLifecycleState(LifecycleState.INSTALLED) .setUuid(new Uuid(UUID.nameUUIDFromBytes(service.getServiceName().getBytes(Charset.forName("UTF-8"))) .toString())) + .setServiceLayer(mapServiceLayer(serviceAEnd.getServiceFormat())) + .setServiceType(ServiceType.POINTTOPOINTCONNECTIVITY) .setConnectivityDirection(ForwardingDirection.BIDIRECTIONAL) .setName(Map.of(name.key(), name)) .setConnection(connMap) @@ -287,6 +303,21 @@ public final class ConnectivityUtils { .build(); } + private LayerProtocolName mapServiceLayer(ServiceFormat serviceFormat) { + switch (serviceFormat) { + case OC: + case OTU: + return LayerProtocolName.PHOTONICMEDIA; + case ODU: + return LayerProtocolName.ODU; + case Ethernet: + return LayerProtocolName.DSR; + default: + LOG.info("Service layer mapping not supported for {}", serviceFormat.getName()); + } + return null; + } + private Map createConnectionsFromService( org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.ServiceAEnd serviceAEnd, @@ -876,10 +907,18 @@ public final class ConnectivityUtils { default: LOG.error("Service Format not supported"); } + 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())) + .build(); return endPointBuilder .setServiceInterfacePoint(new ServiceInterfacePointBuilder() .setServiceInterfacePointUuid(sipUuid) .build()) + .setName(Map.of(name.key(), name)) .setAdministrativeState(AdministrativeState.UNLOCKED) .setDirection(PortDirection.BIDIRECTIONAL) .setLifecycleState(LifecycleState.INSTALLED) @@ -924,10 +963,18 @@ public final class ConnectivityUtils { default: LOG.error("Service Format not supported"); } + 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())) + .build(); return endPointBuilder .setServiceInterfacePoint(new ServiceInterfacePointBuilder() .setServiceInterfacePointUuid(sipUuid) .build()) + .setName(Map.of(name.key(), name)) .setAdministrativeState(AdministrativeState.UNLOCKED) .setDirection(PortDirection.BIDIRECTIONAL) .setLifecycleState(LifecycleState.INSTALLED) @@ -1121,4 +1168,344 @@ public final class ConnectivityUtils { return nodeid.matches("[A-Z]{5}-[A-Z0-9]{2}-.*") ? String.join("-", nodeid.split("-")[0], nodeid.split("-")[1]) : nodeid.split("-")[0]; } + + public ServiceCreateInput createORServiceInput(CreateConnectivityServiceInput input, Uuid serviceUuid) { + // TODO: not taking into account all the constraints. Only using EndPoints and Connectivity Constraint. + Map + endPointMap = input.getEndPoint(); + ConnectivityConstraint constraint = input.getConnectivityConstraint(); + ConnectionType connType = null; + ServiceFormat serviceFormat = null; + String nodeAid = String.join("+", endPointMap.values().stream().findFirst().get().getLocalId(), DSR); + String nodeZid = String.join("+", endPointMap.values().stream().skip(1).findFirst().get().getLocalId(), DSR); + LOG.debug("Node a = {}", nodeAid); + LOG.debug("Node z = {}", nodeZid); + switch (constraint.getServiceLayer().getIntValue()) { + case 0: + LOG.info("ODU"); + connType = ConnectionType.Infrastructure; + serviceFormat = ServiceFormat.ODU; + break; + case 2: + LOG.info("DSR"); + connType = ConnectionType.Service; + serviceFormat = ServiceFormat.Ethernet; + break; + case 3: + LOG.info("PHOTONIC"); + connType = getConnectionTypePhtnc(endPointMap.values()); + serviceFormat = getServiceFormatPhtnc(endPointMap.values()); + if (serviceFormat.equals(ServiceFormat.OC)) { + nodeAid = String.join("+", endPointMap.values().stream().findFirst().get().getLocalId(), + PHTNC_MEDIA); + nodeZid = String.join("+", endPointMap.values().stream().skip(1).findFirst().get().getLocalId(), + PHTNC_MEDIA); + } else { + nodeAid = String.join("+", endPointMap.values().stream().findFirst().get().getLocalId(), OTSI); + nodeZid = String.join("+", endPointMap.values().stream().skip(1).findFirst().get().getLocalId(), + OTSI); + } + LOG.debug("Node a photonic = {}", nodeAid); + LOG.debug("Node z photonic = {}", nodeZid); + break; + default: + LOG.info("Service type {} not supported", constraint.getServiceLayer().getName()); + } + // Requested Capacity for connectivity service + 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); + ServiceZEnd serviceZEnd = tapiEndPointToServiceZPoint(endPointMap.values().stream().skip(1).findFirst().get(), + serviceFormat, nodeZid, capacity); + if (serviceAEnd == null || serviceZEnd == null) { + LOG.error("Couldnt map endpoints to service end"); + return null; + } + LOG.info("Service a end = {}", serviceAEnd); + LOG.info("Service z end = {}", serviceZEnd); + return new ServiceCreateInputBuilder() + .setServiceAEnd(serviceAEnd) + .setServiceZEnd(serviceZEnd) + .setConnectionType(connType) + .setServiceName(serviceUuid.getValue()) + .setCommonId("common id") + .setSdncRequestHeader(new SdncRequestHeaderBuilder().setRequestId("request-1") + .setRpcAction(RpcActions.ServiceCreate).setNotificationUrl("notification url") + .setRequestSystemId("appname") + .build()) + .setCustomer("customer") + .setDueDate(DateAndTime.getDefaultInstance("2018-06-15T00:00:01Z")) + .setOperatorContact("pw1234") + .build(); + } + + 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) { + // 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. + Uuid sipUuid = endPoint.getServiceInterfacePoint().getServiceInterfacePointUuid(); + // Todo -> need to find the NEP associated to that SIP + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(nodeZid.getBytes(Charset.forName("UTF-8"))).toString()); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node node = + this.tapiContext.getTapiNode(this.tapiTopoUuid, nodeUuid); + if (node == null) { + LOG.error("Node not found in datastore"); + return null; + } + // TODO -> in case of a DSR service, for some requests we need the NETWORK PORT and not the CLIENT although the + // connection is between 2 CLIENT ports. Otherwise it will not work... + OwnedNodeEdgePoint nep = null; + for (OwnedNodeEdgePoint onep : node.getOwnedNodeEdgePoint().values()) { + if (onep.getMappedServiceInterfacePoint() == null) { + continue; + } + if (onep.getMappedServiceInterfacePoint().containsKey(new MappedServiceInterfacePointKey(sipUuid))) { + nep = onep; + break; + } + } + if (nep == null) { + LOG.error("Nep not found in datastore"); + return null; + } + String nodeName = endPoint.getName().values().stream().findFirst().get().getValue(); + String nodeid = String.join("-", nodeName.split("-")[0], nodeName.split("-")[1]); + String nepName = nep.getName().values().stream().findFirst().get().getValue(); + String txPortDeviceName = nepName.split("\\+")[0]; + String txPortName = nepName.split("\\+")[2]; + String rxPortDeviceName = txPortDeviceName; + String rxPortName = txPortName; + LOG.debug("Node z id = {}, txportDeviceName = {}, txPortName = {}", nodeid, txPortDeviceName, txPortName); + LOG.debug("Node z id = {}, rxportDeviceName = {}, rxPortName = {}", nodeid, rxPortDeviceName, rxPortName); + if (serviceFormat.equals(ServiceFormat.ODU)) { + // TODO --> populate network map + populateNetworkMap(nodeid, txPortName); + } + if (serviceFormat.equals(ServiceFormat.Ethernet)) { + // TODO --> choose from network Map un network port which hasnt been used yet by another service. + // Set boolean to true and update txportName and so on + String updTxName = findFreeConfiguredNetworkPort(nodeid); + if (updTxName != null) { + txPortName = updTxName; + rxPortName = txPortName; + } + } + // TODO --> get clli from datastore? + String clli = "NodeSC"; + LOG.info("Node z id = {}, txportDeviceName = {}, txPortName = {}", nodeid, txPortDeviceName, txPortName); + LOG.info("Node z id = {}, rxportDeviceName = {}, rxPortName = {}", nodeid, rxPortDeviceName, rxPortName); + ServiceZEndBuilder serviceZEndBuilder = new ServiceZEndBuilder() + .setClli(clli) + .setNodeId(new NodeIdType(nodeid)) + .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) + .setPortName(txPortName) + .setPortRack(PORT_RACK_VALUE) + .setPortShelf("00") + .setPortType(PORT_TYPE) + .build()) + .setLgx(new LgxBuilder() + .setLgxDeviceName(LGX_DEVICE_NAME) + .setLgxPortName(LGX_PORT_NAME) + .setLgxPortRack(PORT_RACK_VALUE) + .setLgxPortShelf("00") + .build()) + .build()) + .setRxDirection(new RxDirectionBuilder() + .setPort(new PortBuilder() + .setPortDeviceName(rxPortDeviceName) + .setPortName(rxPortName) + .setPortRack(PORT_RACK_VALUE) + .setPortShelf("00") + .setPortType(PORT_TYPE) + .build()) + .setLgx(new LgxBuilder() + .setLgxDeviceName(LGX_DEVICE_NAME) + .setLgxPortName(LGX_PORT_NAME) + .setLgxPortRack(PORT_RACK_VALUE) + .setLgxPortShelf("00") + .build()) + .build()); + if (serviceFormat.equals(ServiceFormat.ODU)) { + serviceZEndBuilder.setOduServiceRate(ODU4.class); + } + if (serviceFormat.equals(ServiceFormat.OTU)) { + serviceZEndBuilder.setOtuServiceRate(OTU4.class); + } + 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) { + // 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. + Uuid sipUuid = endPoint.getServiceInterfacePoint().getServiceInterfacePointUuid(); + // Todo -> need to find the NEP associated to that SIP + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(nodeAid.getBytes(Charset.forName("UTF-8"))).toString()); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node node = + this.tapiContext.getTapiNode(this.tapiTopoUuid, nodeUuid); + if (node == null) { + LOG.error("Node not found in datastore"); + return null; + } + // TODO -> in case of a DSR service, for some requests we need the NETWORK PORT and not the CLIENT although the + // connection is between 2 CLIENT ports. Otherwise it will not work... + OwnedNodeEdgePoint nep = null; + for (OwnedNodeEdgePoint onep : node.getOwnedNodeEdgePoint().values()) { + if (onep.getMappedServiceInterfacePoint() == null) { + continue; + } + if (onep.getMappedServiceInterfacePoint().containsKey(new MappedServiceInterfacePointKey(sipUuid))) { + nep = onep; + break; + } + } + if (nep == null) { + LOG.error("Nep not found in datastore"); + return null; + } + String nodeName = endPoint.getName().values().stream().findFirst().get().getValue(); + String nodeid = String.join("-", nodeName.split("-")[0], nodeName.split("-")[1]); + String nepName = nep.getName().values().stream().findFirst().get().getValue(); + String txPortDeviceName = nepName.split("\\+")[0]; + String txPortName = nepName.split("\\+")[2]; + String rxPortDeviceName = txPortDeviceName; + String rxPortName = txPortName; + LOG.debug("Node a id = {}, txportDeviceName = {}, txPortName = {}", nodeid, txPortDeviceName, txPortName); + LOG.debug("Node a id = {}, rxportDeviceName = {}, rxPortName = {}", nodeid, rxPortDeviceName, rxPortName); + if (serviceFormat.equals(ServiceFormat.ODU)) { + // TODO --> populate network map + populateNetworkMap(nodeid, txPortName); + } + if (serviceFormat.equals(ServiceFormat.Ethernet)) { + // TODO --> choose from network Map un network port which hasnt been used yet by another service. + // Set boolean to true and update txportName and so on + String updTxName = findFreeConfiguredNetworkPort(nodeid); + if (updTxName != null) { + txPortName = updTxName; + rxPortName = txPortName; + } + } + // TODO --> get clli from datastore? + String clli = "NodeSA"; + LOG.info("Node a id = {}, txportDeviceName = {}, txPortName = {}", nodeid, txPortDeviceName, txPortName); + LOG.info("Node a id = {}, rxportDeviceName = {}, rxPortName = {}", nodeid, rxPortDeviceName, rxPortName); + ServiceAEndBuilder serviceAEndBuilder = new ServiceAEndBuilder() + .setClli(clli) + .setNodeId(new NodeIdType(nodeid)) + .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) + .setPortName(txPortName) + .setPortRack(PORT_RACK_VALUE) + .setPortShelf("00") + .setPortType(PORT_TYPE) + .build()) + .setLgx(new LgxBuilder() + .setLgxDeviceName(LGX_DEVICE_NAME) + .setLgxPortName(LGX_PORT_NAME) + .setLgxPortRack(PORT_RACK_VALUE) + .setLgxPortShelf("00") + .build()) + .build()) + .setRxDirection(new RxDirectionBuilder() + .setPort(new PortBuilder() + .setPortDeviceName(rxPortDeviceName) + .setPortName(rxPortName) + .setPortRack(PORT_RACK_VALUE) + .setPortShelf("00") + .setPortType(PORT_TYPE) + .build()) + .setLgx(new LgxBuilder() + .setLgxDeviceName(LGX_DEVICE_NAME) + .setLgxPortName(LGX_PORT_NAME) + .setLgxPortRack(PORT_RACK_VALUE) + .setLgxPortShelf("00") + .build()) + .build()); + if (serviceFormat.equals(ServiceFormat.ODU)) { + serviceAEndBuilder.setOduServiceRate(ODU4.class); + } + if (serviceFormat.equals(ServiceFormat.OTU)) { + serviceAEndBuilder.setOtuServiceRate(OTU4.class); + } + return serviceAEndBuilder.build(); + } + + private String findFreeConfiguredNetworkPort(String nodeid) { + if (!this.networkMap.containsKey(nodeid)) { + return null; + } + Map netMap = this.networkMap.get(nodeid); + for (Map.Entry entry : netMap.entrySet()) { + if (!entry.getValue()) { + this.networkMap.get(nodeid).put(entry.getKey(), true); + return entry.getKey(); + } + } + return null; + } + + private void populateNetworkMap(String nodeid, String txPortName) { + Map netMap = new HashMap<>(); + netMap.put(txPortName, false); + if (!this.networkMap.containsKey(nodeid)) { + this.networkMap.put(nodeid, netMap); + } else if (!this.networkMap.get(nodeid).containsKey(txPortName)) { + this.networkMap.get(nodeid).putAll(netMap); + } + } + + private ConnectionType getConnectionTypePhtnc(Collection endPoints) { + if (endPoints.stream().anyMatch(ep -> ep.getName().values().stream() + .anyMatch(name -> name.getValue().contains("ROADM")))) { + // EndPoints are ROADMs + return ConnectionType.RoadmLine; + } + // EndPoints ar not ROADMs -> XPDR, MUXPDR, SWTICHPDR + return ConnectionType.Infrastructure; + } + + private ServiceFormat getServiceFormatPhtnc(Collection endPoints) { + if (endPoints.stream().anyMatch(ep -> ep.getName().values().stream() + .anyMatch(name -> name.getValue().contains("ROADM")))) { + // EndPoints are ROADMs + return ServiceFormat.OC; + } + // EndPoints ar not ROADMs -> XPDR, MUXPDR, SWTICHPDR + return ServiceFormat.OTU; + } } diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/connectivity/TapiConnectivityImpl.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/connectivity/TapiConnectivityImpl.java index 6172e5435..7011804a8 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/connectivity/TapiConnectivityImpl.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/connectivity/TapiConnectivityImpl.java @@ -8,44 +8,76 @@ package org.opendaylight.transportpce.tapi.connectivity; import com.google.common.util.concurrent.ListenableFuture; +import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.concurrent.ExecutionException; import org.opendaylight.transportpce.common.OperationResult; -import org.opendaylight.transportpce.tapi.utils.GenericServiceEndpoint; -import org.opendaylight.transportpce.tapi.utils.MappingUtils; +import org.opendaylight.transportpce.common.ResponseCodes; +import org.opendaylight.transportpce.tapi.listeners.TapiPceListenerImpl; +import org.opendaylight.transportpce.tapi.listeners.TapiRendererListenerImpl; +import org.opendaylight.transportpce.tapi.listeners.TapiServiceHandlerListenerImpl; +import org.opendaylight.transportpce.tapi.utils.TapiContext; import org.opendaylight.transportpce.tapi.validation.CreateConnectivityServiceValidation; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.RpcActions; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.sdnc.request.header.SdncRequestHeaderBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.OrgOpenroadmServiceService; import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceCreateInput; import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceCreateOutput; +import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceDeleteInputBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceDeleteOutput; +import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.delete.input.ServiceDeleteReqInfo; +import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.delete.input.ServiceDeleteReqInfoBuilder; +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.ForwardingDirection; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LifecycleState; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.OperationalState; 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.capacity.BandwidthProfileBuilder; +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.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; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.CreateConnectivityServiceOutput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.CreateConnectivityServiceOutputBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.DeleteConnectivityServiceInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.DeleteConnectivityServiceOutput; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.DeleteConnectivityServiceOutputBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionDetailsInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionDetailsOutput; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionDetailsOutputBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionEndPointDetailsInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionEndPointDetailsOutput; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectionEndPointDetailsOutputBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceDetailsInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceDetailsOutput; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceDetailsOutputBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceListInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceListOutput; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.GetConnectivityServiceListOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ServiceType; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.TapiConnectivityService; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.UpdateConnectivityServiceInput; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.UpdateConnectivityServiceOutput; +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.connectivity.context.Connection; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityService; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceBuilder; -import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.Connection; -import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.ConnectionBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.EndPoint; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.EndPointBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.EndPointKey; +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.output.ServiceBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.get.connection.details.output.ConnectionBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.get.connection.end.point.details.output.ConnectionEndPointBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.get.connectivity.service.list.output.Service; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.get.connectivity.service.list.output.ServiceKey; +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; @@ -59,115 +91,250 @@ public class TapiConnectivityImpl implements TapiConnectivityService { private static final Logger LOG = LoggerFactory.getLogger(TapiConnectivityImpl.class); private OrgOpenroadmServiceService serviceHandler; + private final TapiContext tapiContext; + private final ConnectivityUtils connectivityUtils; + private TapiPceListenerImpl pceListenerImpl; + private TapiRendererListenerImpl rendererListenerImpl; + private TapiServiceHandlerListenerImpl serviceHandlerListenerImpl; - public TapiConnectivityImpl(OrgOpenroadmServiceService serviceHandler) { + public TapiConnectivityImpl(OrgOpenroadmServiceService serviceHandler, TapiContext tapiContext, + ConnectivityUtils connectivityUtils, TapiPceListenerImpl pceListenerImpl, + TapiRendererListenerImpl rendererListenerImpl, + TapiServiceHandlerListenerImpl serviceHandlerListenerImpl) { LOG.info("inside TapiImpl constructor"); this.serviceHandler = serviceHandler; + this.tapiContext = tapiContext; + this.connectivityUtils = connectivityUtils; + this.pceListenerImpl = pceListenerImpl; + this.rendererListenerImpl = rendererListenerImpl; + this.serviceHandlerListenerImpl = serviceHandlerListenerImpl; } @Override public ListenableFuture> createConnectivityService( - CreateConnectivityServiceInput input) { + CreateConnectivityServiceInput input) { + // TODO: later version of TAPI models include Name as an input parameter in connectivity.yang LOG.info("RPC create-connectivity received: {}", input.getEndPoint()); + Uuid serviceUuid = new Uuid(UUID.randomUUID().toString()); + this.pceListenerImpl.setInput(input); + this.pceListenerImpl.setServiceUuid(serviceUuid); + this.rendererListenerImpl.setServiceUuid(serviceUuid); + ListenableFuture> output = null; OperationResult validationResult = CreateConnectivityServiceValidation.validateCreateConnectivityServiceRequest( - input); + input); if (validationResult.isSuccess()) { LOG.info("input parameter of RPC create-connectivity are being handled"); - // check uuid of SIP in the map - Map map = MappingUtils.getMap(); - - if (map.containsKey(input.getEndPoint().values().stream().findFirst().get() - .getServiceInterfacePoint().getServiceInterfacePointUuid()) - && map.containsKey(input.getEndPoint().values().stream().skip(1).findFirst().get() - .getServiceInterfacePoint() - .getServiceInterfacePointUuid())) { - ServiceCreateInput sci = ConnectivityUtils.buildServiceCreateInput( - map.get(input.getEndPoint().values().stream().findFirst().get() - .getServiceInterfacePoint() - .getServiceInterfacePointUuid()), - map.get(input.getEndPoint().values().stream().skip(1).findFirst().get() - .getServiceInterfacePoint() - .getServiceInterfacePointUuid())); - ListenableFuture> output = this.serviceHandler.serviceCreate(sci); + // check uuid of SIP in tapi context + Map sipMap = this.tapiContext.getTapiContext() + .getServiceInterfacePoint(); + if (sipMap == null) { + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "SIP list is empty").buildFuture(); + } + if (sipMap.containsKey(new ServiceInterfacePointKey(input.getEndPoint().values().stream().findFirst().get() + .getServiceInterfacePoint().getServiceInterfacePointUuid())) + && sipMap.containsKey(new ServiceInterfacePointKey(input.getEndPoint().values().stream().skip(1) + .findFirst().get().getServiceInterfacePoint().getServiceInterfacePointUuid()))) { + LOG.info("SIPs found in sipMap"); + ServiceCreateInput sci = this.connectivityUtils.createORServiceInput(input, serviceUuid); + if (sci == null) { + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "Couldnt map Service create input").buildFuture(); + } + LOG.info("Service Create input = {}", sci); + output = this.serviceHandler.serviceCreate(sci); if (!output.isDone()) { - return RpcResultBuilder.failed().buildFuture(); + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "Service create RPC failed").buildFuture(); } } else { LOG.error("Unknown UUID"); + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "SIPs do not exist in tapi context").buildFuture(); } - } - - Map endPointList = new HashMap<>(); - EndPoint endpoint1 = new EndPointBuilder() - .setLocalId(UUID.randomUUID().toString()) - .setServiceInterfacePoint(new ServiceInterfacePointBuilder().setServiceInterfacePointUuid(new Uuid(UUID - .randomUUID().toString())).build()) - .build(); - EndPoint endpoint2 = new EndPointBuilder() - .setLocalId(UUID.randomUUID().toString()) - .setServiceInterfacePoint(new ServiceInterfacePointBuilder().setServiceInterfacePointUuid(new Uuid(UUID - .randomUUID().toString())).build()) - .build(); - endPointList.put(endpoint1.key(), endpoint1); - endPointList.put(endpoint2.key(), endpoint2); - Connection connection = new ConnectionBuilder().setConnectionUuid(new Uuid(UUID.randomUUID().toString())) + try { + if (output == null) { + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "Failed to create service").buildFuture(); + } + LOG.info("Service create request was successful"); + if (output.get().getResult().getConfigurationResponseCommon().getResponseCode() + .equals(ResponseCodes.RESPONSE_FAILED)) { + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "Failed to create service").buildFuture(); + } + LOG.info("Output of service request = {}", output.get().getResult()); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Error checking response code of service create", e); + } + // Connections and states should be created/updated when the pce and renderer are done :) + Map endPointList = createEndPoints(input.getEndPoint()); + Name name = new NameBuilder() + .setValueName("Connectivity Service Name") + .setValue(serviceUuid.getValue()) .build(); ConnectivityService service = new ConnectivityServiceBuilder() - .setUuid(new Uuid(UUID.randomUUID().toString())) - .build(); - Name serviceName = new NameBuilder().setValueName("Service Name").setValue("SENDATE Service 1").build(); - CreateConnectivityServiceOutput output = new CreateConnectivityServiceOutputBuilder() - .setService(new ServiceBuilder(service) - .setUuid(new Uuid(UUID.randomUUID().toString())) - .setName(Map.of(serviceName.key(), serviceName)) - .setServiceLayer(input.getEndPoint().values().stream().findFirst().get().getLayerProtocolName()) - .setEndPoint(endPointList) - .setConnection(Map.of(connection.key(), connection)) - .build()) + .setUuid(serviceUuid) + .setAdministrativeState(AdministrativeState.LOCKED) + .setOperationalState(OperationalState.DISABLED) + .setLifecycleState(LifecycleState.PLANNED) + .setServiceLayer(input.getConnectivityConstraint().getServiceLayer()) + .setServiceType(ServiceType.POINTTOPOINTCONNECTIVITY) + .setConnectivityDirection(ForwardingDirection.BIDIRECTIONAL) + .setName(Map.of(name.key(), name)) + .setConnection(new HashMap<>()) + .setEndPoint(endPointList) .build(); - return RpcResultBuilder.success(output).buildFuture(); + // add to tapi context + this.tapiContext.updateConnectivityContext(Map.of(service.key(), service), new HashMap<>()); + LOG.info("Created locked service in Datastore. Waiting for PCE and Renderer to complete tasks..."); + // return ConnectivityServiceCreateOutput + return RpcResultBuilder.success(new CreateConnectivityServiceOutputBuilder() + .setService(new ServiceBuilder(service).build()).build()).buildFuture(); + } + + private Map createEndPoints( + Map endPoints) { + Map endPointMap = new HashMap<>(); + for (org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.create.connectivity.service.input.EndPoint ep: + endPoints.values()) { + EndPoint endpoint = new EndPointBuilder() + .setServiceInterfacePoint(new ServiceInterfacePointBuilder() + .setServiceInterfacePointUuid(ep.getServiceInterfacePoint().getServiceInterfacePointUuid()) + .build()) + .setName(ep.getName()) + .setAdministrativeState(ep.getAdministrativeState()) + .setDirection(ep.getDirection()) + .setLifecycleState(ep.getLifecycleState()) + .setOperationalState(ep.getOperationalState()) + .setLayerProtocolName(ep.getLayerProtocolName()) + .setCapacity(new CapacityBuilder() + .setTotalSize(new TotalSizeBuilder().build()) + .setBandwidthProfile(new BandwidthProfileBuilder().build()) // TODO: implement bandwidth profile + .build()) + .setProtectionRole(ep.getProtectionRole()) + .setRole(ep.getRole()) + .setLocalId(ep.getLocalId()) + .build(); + endPointMap.put(endpoint.key(), endpoint); + } + return endPointMap; } @Override public ListenableFuture> getConnectivityServiceDetails( - GetConnectivityServiceDetailsInput input) { + GetConnectivityServiceDetailsInput input) { // TODO Auto-generated method stub - return null; + Uuid serviceUuid = new Uuid(input.getServiceIdOrName()); + ConnectivityService service = this.tapiContext.getConnectivityService(serviceUuid); + if (service == null) { + LOG.error("Service {} doesnt exist in tapi context", input.getServiceIdOrName()); + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "Service doesnt exist in datastore").buildFuture(); + } + return RpcResultBuilder.success(new GetConnectivityServiceDetailsOutputBuilder().setService( + new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.get.connectivity.service.details.output.ServiceBuilder( + service).build()).build()).buildFuture(); } @Override public ListenableFuture> updateConnectivityService( - UpdateConnectivityServiceInput input) { - // TODO Auto-generated method stub + UpdateConnectivityServiceInput input) { + // TODO Auto-generated method stub. More complicated as it depends on what needs to be updated... left aside return null; } @Override public ListenableFuture> getConnectionDetails( - GetConnectionDetailsInput input) { + GetConnectionDetailsInput input) { // TODO Auto-generated method stub - return null; + Uuid connectionUuid = new Uuid(UUID.nameUUIDFromBytes(input.getConnectionIdOrName() + .getBytes(Charset.forName("UTF-8"))).toString()); + Connection connection = this.tapiContext.getConnection(connectionUuid); + if (connection == null) { + LOG.error("Connection {} doesnt exist in tapi context", input.getConnectionIdOrName()); + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "Connection doesnt exist in datastore").buildFuture(); + } + return RpcResultBuilder.success(new GetConnectionDetailsOutputBuilder().setConnection( + new ConnectionBuilder(connection).build()).build()).buildFuture(); } @Override public ListenableFuture> deleteConnectivityService( - DeleteConnectivityServiceInput input) { + DeleteConnectivityServiceInput input) { //TODO Auto-generated method stub - return null; + // TODO add try + Uuid serviceUuid = new Uuid(input.getServiceIdOrName()); + this.tapiContext.deleteConnectivityService(serviceUuid); + ListenableFuture> output = + this.serviceHandler.serviceDelete(new ServiceDeleteInputBuilder() + .setServiceDeleteReqInfo(new ServiceDeleteReqInfoBuilder() + .setServiceName(input.getServiceIdOrName()) + .setTailRetention(ServiceDeleteReqInfo.TailRetention.No) + .build()) + .setSdncRequestHeader(new SdncRequestHeaderBuilder() + .setRequestId("request-1") + .setRpcAction(RpcActions.ServiceDelete) + .setNotificationUrl("notification url") + .setRequestSystemId("appname") + .build()) + .build()); + if (output == null) { + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "Failed to delete Link").buildFuture(); + } + LOG.info("Service is being deleted and devices are being rolled back"); + return RpcResultBuilder.success(new DeleteConnectivityServiceOutputBuilder().build()).buildFuture(); } @Override public ListenableFuture> getConnectivityServiceList( - GetConnectivityServiceListInput input) { + GetConnectivityServiceListInput input) { // TODO Auto-generated method stub - return null; + Map connMap = this.tapiContext.getConnectivityServices(); + if (connMap == null) { + LOG.error("No services in tapi context"); + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "No services exist in datastore").buildFuture(); + } + + Map serviceMap = new HashMap<>(); + for (ConnectivityService connectivityService: connMap.values()) { + Service service = new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.get.connectivity.service.list.output.ServiceBuilder( + connectivityService).build(); + serviceMap.put(service.key(), service); + } + return RpcResultBuilder.success(new GetConnectivityServiceListOutputBuilder().setService(serviceMap) + .build()).buildFuture(); } @Override public ListenableFuture> getConnectionEndPointDetails( - GetConnectionEndPointDetailsInput input) { + GetConnectionEndPointDetailsInput input) { // TODO Auto-generated method stub - return null; + Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(input.getTopologyIdOrName() + .getBytes(Charset.forName("UTF-8"))).toString()); + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(input.getNodeIdOrName() + .getBytes(Charset.forName("UTF-8"))).toString()); + Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes(input.getNepIdOrName() + .getBytes(Charset.forName("UTF-8"))).toString()); + Uuid cepUuid = new Uuid(UUID.nameUUIDFromBytes(input.getCepIdOrName() + .getBytes(Charset.forName("UTF-8"))).toString()); + ConnectionEndPoint cep = this.tapiContext.getTapiCEP(topoUuid, nodeUuid, nepUuid, cepUuid); + if (cep == null) { + LOG.error("Cep doesnt exist in tapi context"); + return RpcResultBuilder.failed().withError(RpcError.ErrorType.RPC, + "No cep with given Uuid exists in datastore").buildFuture(); + } + return RpcResultBuilder.success(new GetConnectionEndPointDetailsOutputBuilder().setConnectionEndPoint( + new ConnectionEndPointBuilder(cep).build()).build()).buildFuture(); } } 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 dc30a57eb..720ac4d72 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 @@ -11,6 +11,7 @@ import java.util.HashMap; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.binding.api.DataTreeIdentifier; +import org.opendaylight.mdsal.binding.api.NotificationService; import org.opendaylight.mdsal.binding.api.RpcProviderService; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.transportpce.common.InstanceIdentifiers; @@ -18,6 +19,9 @@ import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations; import org.opendaylight.transportpce.tapi.connectivity.ConnectivityUtils; import org.opendaylight.transportpce.tapi.connectivity.TapiConnectivityImpl; +import org.opendaylight.transportpce.tapi.listeners.TapiPceListenerImpl; +import org.opendaylight.transportpce.tapi.listeners.TapiRendererListenerImpl; +import org.opendaylight.transportpce.tapi.listeners.TapiServiceHandlerListenerImpl; import org.opendaylight.transportpce.tapi.topology.TapiNetconfTopologyListener; import org.opendaylight.transportpce.tapi.topology.TapiPortMappingListener; import org.opendaylight.transportpce.tapi.topology.TapiTopologyImpl; @@ -25,8 +29,11 @@ import org.opendaylight.transportpce.tapi.topology.TopologyUtils; import org.opendaylight.transportpce.tapi.utils.TapiContext; import org.opendaylight.transportpce.tapi.utils.TapiInitialORMapping; import org.opendaylight.transportpce.tapi.utils.TapiListener; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev200128.TransportpcePceListener; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210315.Network; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210315.network.Nodes; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.TransportpceRendererListener; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.TransportpceServicehandlerListener; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.tapinetworkutils.rev210408.TransportpceTapinetworkutilsService; import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.OrgOpenroadmServiceService; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.TapiConnectivityService; @@ -58,6 +65,9 @@ public class TapiProvider { private ObjectRegistration tapiNetworkutilsServiceRpcRegistration; private ListenerRegistration dataTreeChangeListenerRegistration; private ListenerRegistration mappingListenerListenerRegistration; + private ListenerRegistration pcelistenerRegistration; + private ListenerRegistration rendererlistenerRegistration; + private ListenerRegistration servicehandlerlistenerRegistration; private final OrgOpenroadmServiceService serviceHandler; private final ServiceDataStoreOperations serviceDataStoreOperations; private final TapiListener tapiListener; @@ -65,12 +75,18 @@ public class TapiProvider { private TapiPortMappingListener tapiPortMappingListener; private final NetworkTransactionService networkTransactionService; private final TransportpceTapinetworkutilsService tapiNetworkUtils; + private TapiPceListenerImpl pceListenerImpl; + private TapiRendererListenerImpl rendererListenerImpl; + private TapiServiceHandlerListenerImpl serviceHandlerListenerImpl; + private final NotificationService notificationService; public TapiProvider(DataBroker dataBroker, RpcProviderService rpcProviderService, OrgOpenroadmServiceService serviceHandler, ServiceDataStoreOperations serviceDataStoreOperations, TapiListener tapiListener, NetworkTransactionService networkTransactionService, TapiNetconfTopologyListener topologyListener, TapiPortMappingListener tapiPortMappingListener, - TransportpceTapinetworkutilsService tapiNetworkUtils) { + TransportpceTapinetworkutilsService tapiNetworkUtils, TapiPceListenerImpl pceListenerImpl, + TapiRendererListenerImpl rendererListenerImpl, TapiServiceHandlerListenerImpl serviceHandlerListenerImpl, + NotificationService notificationService) { this.dataBroker = dataBroker; this.rpcProviderService = rpcProviderService; this.serviceHandler = serviceHandler; @@ -80,6 +96,10 @@ public class TapiProvider { this.topologyListener = topologyListener; this.tapiPortMappingListener = tapiPortMappingListener; this.tapiNetworkUtils = tapiNetworkUtils; + this.pceListenerImpl = pceListenerImpl; + this.rendererListenerImpl = rendererListenerImpl; + this.serviceHandlerListenerImpl = serviceHandlerListenerImpl; + this.notificationService = notificationService; } /** @@ -98,7 +118,8 @@ public class TapiProvider { tapiInitialORMapping.performTopoInitialMapping(); tapiInitialORMapping.performServInitialMapping(); - TapiConnectivityImpl tapi = new TapiConnectivityImpl(this.serviceHandler); + TapiConnectivityImpl tapi = new TapiConnectivityImpl(this.serviceHandler, tapiContext, connectivityUtils, + pceListenerImpl, rendererListenerImpl, serviceHandlerListenerImpl); TapiTopologyImpl topo = new TapiTopologyImpl(this.dataBroker, tapiContext, topologyUtils); rpcRegistration = rpcProviderService.registerRpcImplementation(TapiConnectivityService.class, tapi); rpcProviderService.registerRpcImplementation(TapiTopologyService.class, topo); @@ -115,6 +136,11 @@ public class TapiProvider { InstanceIdentifier sipIID = InstanceIdentifier.create(ServiceInterfacePoints.class); dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create( LogicalDatastoreType.CONFIGURATION, sipIID), tapiListener); + // Notification Listener + pcelistenerRegistration = notificationService.registerNotificationListener(pceListenerImpl); + rendererlistenerRegistration = notificationService.registerNotificationListener(rendererListenerImpl); + servicehandlerlistenerRegistration = + notificationService.registerNotificationListener(serviceHandlerListenerImpl); } /** @@ -131,6 +157,9 @@ public class TapiProvider { if (tapiNetworkutilsServiceRpcRegistration != null) { tapiNetworkutilsServiceRpcRegistration.close(); } + pcelistenerRegistration.close(); + rendererlistenerRegistration.close(); + servicehandlerlistenerRegistration.close(); rpcRegistration.close(); } } 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 new file mode 100644 index 000000000..2b9163489 --- /dev/null +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiPceListenerImpl.java @@ -0,0 +1,950 @@ +/* + * Copyright © 2021 Nokia, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.tapi.listeners; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +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.binding.api.DataBroker; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.transportpce.common.network.NetworkTransactionImpl; +import org.opendaylight.transportpce.common.network.NetworkTransactionService; +import org.opendaylight.transportpce.common.network.RequestProcessor; +import org.opendaylight.transportpce.tapi.topology.TopologyUtils; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev200128.ServicePathRpcResult; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev200128.TransportpcePceListener; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev200128.service.path.rpc.result.PathDescription; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev200128.service.path.rpc.result.PathDescriptionBuilder; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.path.description.atoz.direction.AToZ; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.pce.resource.resource.resource.Node; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.pce.resource.resource.resource.TerminationPoint; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx; +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; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.OperationalState; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.PortDirection; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.PortRole; +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.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; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.OwnedNodeEdgePoint1Builder; +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.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; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.Connection; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.ConnectionBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.ConnectionKey; +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.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.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.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TapiPceListenerImpl implements TransportpcePceListener { + + private static final String DSR = "DSR"; + private static final String ODU = "ODU"; + private static final String E_ODU = "eODU"; + private static final String I_ODU = "iODU"; + private static final String OTSI = "OTSi"; + private static final String E_OTSI = "eOTSi"; + private static final String I_OTSI = "iOTSi"; + private static final String PHTNC_MEDIA = "PHOTONIC_MEDIA"; + private static final String MC = "MEDIA_CHANNEL"; + private static final String OTSI_MC = "OTSi_MEDIA_CHANNEL"; + private static final String TP = "TerminationPoint"; + private static final String NODE = "Node"; + private static final Logger LOG = LoggerFactory.getLogger(TapiPceListenerImpl.class); + + private ServicePathRpcResult servicePathRpcResult; + private CreateConnectivityServiceInput input; + private Uuid serviceUuid; + private final DataBroker dataBroker; + private final NetworkTransactionService networkTransactionService; + private final Map + connectionFullMap; // this variable is for complete connection objects + + public TapiPceListenerImpl(DataBroker dataBroker) { + this.connectionFullMap = new HashMap<>(); + this.dataBroker = dataBroker; + this.networkTransactionService = new NetworkTransactionImpl(new RequestProcessor(this.dataBroker)); + } + + @Override + public void onServicePathRpcResult(ServicePathRpcResult notification) { + if (compareServicePathRpcResult(notification)) { + LOG.warn("ServicePathRpcResult already wired !"); + return; + } + servicePathRpcResult = notification; + switch (servicePathRpcResult.getNotificationType().getIntValue()) { + /* path-computation-request. */ + case 1: + onPathComputationResult(notification); + break; + /* cancel-resource-reserve. */ + case 2: + onCancelResourceResult(notification.getServiceName()); + break; + default: + break; + } + } + + /** + * Process path computation request result. + * @param notification the result notification. + */ + private void onPathComputationResult(ServicePathRpcResult notification) { + this.connectionFullMap.clear(); + LOG.info("PCE '{}' Notification received : {}",servicePathRpcResult.getNotificationType().getName(), + notification); + if (servicePathRpcResult.getStatus() == RpcStatusEx.Failed) { + LOG.error("PCE path computation failed !"); + return; + } else if (servicePathRpcResult.getStatus() == RpcStatusEx.Pending) { + LOG.warn("PCE path computation returned a Penging RpcStatusEx code!"); + return; + } else if (servicePathRpcResult.getStatus() != RpcStatusEx.Successful) { + LOG.error("PCE path computation returned an unknown RpcStatusEx code!"); + return; + } + + LOG.info("PCE calculation done OK !"); + if (servicePathRpcResult.getPathDescription() == null) { + LOG.error("'PathDescription' parameter is null "); + return; + } + PathDescription pathDescription = new PathDescriptionBuilder() + .setAToZDirection(servicePathRpcResult.getPathDescription().getAToZDirection()) + .setZToADirection(servicePathRpcResult.getPathDescription().getZToADirection()) + .build(); + LOG.info("PathDescription gets : {}", pathDescription); + if (input == null) { + LOG.error("Input is null !"); + return; + } + // 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, + input.getConnectivityConstraint().getServiceLayer()); + // add connections to connection context and to connectivity context + updateConnectionContextWithConn(this.connectionFullMap, connectionMap, serviceUuid); + } + + private Map createConnectionsAndCepsForService(PathDescription pathDescription, + LayerProtocolName serviceProtName) { + Map connectionServMap = new HashMap<>(); + // build lists with ROADM nodes, XPDR/MUX/SWITCH nodes, ROADM DEG TTPs, ROADM SRG TTPs, XPDR CLIENT TTPs + // and XPDR NETWORK TTPs (if any). From the path description. This will help to build the uuid of the CEPs + // and the connections + String resourceType; + List xpdrClientTplist = new ArrayList<>(); + List xpdrNetworkTplist = new ArrayList<>(); + List rdmAddDropTplist = new ArrayList<>(); + List rdmDegTplist = new ArrayList<>(); + List rdmNodelist = new ArrayList<>(); + List xpdrNodelist = new ArrayList<>(); + for (AToZ elem:pathDescription.getAToZDirection().getAToZ().values().stream() + .sorted(Comparator.comparing(AToZ::getId)).collect(Collectors.toList())) { + resourceType = elem.getResource().getResource().implementedInterface().getSimpleName(); + switch (resourceType) { + case TP: + TerminationPoint tp = (TerminationPoint) elem.getResource().getResource(); + String tpID = tp.getTpId(); + String tpNode; + if (tpID.contains("CLIENT")) { + tpNode = tp.getTpNodeId(); + if (!xpdrClientTplist.contains(String.join("+", tpNode, tpID))) { + xpdrClientTplist.add(String.join("+", tpNode, tpID)); + } + } + if (tpID.contains("NETWORK")) { + tpNode = tp.getTpNodeId(); + if (!xpdrNetworkTplist.contains(String.join("+", tpNode, tpID))) { + xpdrNetworkTplist.add(String.join("+", tpNode, tpID)); + } + } + if (tpID.contains("PP")) { + tpNode = getIdBasedOnModelVersion(tp.getTpNodeId()); + LOG.info("ROADM Node of tp = {}", tpNode); + if (!rdmAddDropTplist.contains(String.join("+", tpNode, tpID))) { + rdmAddDropTplist.add(String.join("+", tpNode, tpID)); + } + } + if (tpID.contains("TTP")) { + tpNode = getIdBasedOnModelVersion(tp.getTpNodeId()); + LOG.info("ROADM Node of tp = {}", tpNode); + if (!rdmDegTplist.contains(String.join("+", tpNode, tpID))) { + rdmDegTplist.add(String.join("+", tpNode, tpID)); + } + } + break; + case NODE: + Node node = (Node) elem.getResource().getResource(); + String nodeId = node.getNodeId(); + if (nodeId.contains("XPDR") || nodeId.contains("SPDR") || nodeId.contains("MXPDR")) { + LOG.info("Node id = {}", nodeId); + if (!xpdrNodelist.contains(nodeId)) { + xpdrNodelist.add(nodeId); // should contain only 2 + } + } + if (nodeId.contains("ROADM")) { + nodeId = getIdBasedOnModelVersion(nodeId); + LOG.info("Node id = {}", nodeId); + if (!rdmNodelist.contains(nodeId)) { + rdmNodelist.add(nodeId); + } + } + break; + default: + LOG.warn("Resource is a {}", resourceType); + } + } + LOG.info("ROADM node list = {}", rdmNodelist.toString()); + LOG.info("ROADM degree list = {}", rdmDegTplist.toString()); + LOG.info("ROADM addrop list = {}", rdmAddDropTplist.toString()); + LOG.info("XPDR node list = {}", xpdrNodelist.toString()); + LOG.info("XPDR network list = {}", xpdrNetworkTplist.toString()); + LOG.info("XPDR client list = {}", xpdrClientTplist.toString()); + // TODO -> for 10GB eth and ODU services there are no ROADMs in path description as they use the OTU link, + // but for 100GB eth all is created at once. Check if the roadm list is empty to determine whether we need + // to trigger all the steps or not + String edgeRoadm1 = ""; + String edgeRoadm2 = ""; + if (!rdmNodelist.isEmpty()) { + edgeRoadm1 = rdmNodelist.get(0); + edgeRoadm2 = rdmNodelist.get(rdmNodelist.size() - 1); + LOG.info("edgeRoadm1 = {}", edgeRoadm1); + LOG.info("edgeRoadm2 = {}", edgeRoadm2); + } + // create corresponding CEPs and Connections. Connections should be added to the corresponding context + // CEPs must be included in the topology context as an augmentation for each ONEP!! + switch (serviceProtName) { + case PHOTONICMEDIA: + // Identify number of ROADMs + // - XC Connection between MC CEPs mapped from MC NEPs (within a roadm) + // - XC Connection between OTSiMC CEPs mapped from OTSiMC NEPs (within a roadm) + // - Top Connection MC betwwen MC CEPs of different roadms + // - Top Connection OTSiMC betwwen OTSiMC CEPs of extreme roadms + connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist, + edgeRoadm1, edgeRoadm2)); + if (!pathDescription.getAToZDirection().getAToZ().values().stream().findFirst().get().getId() + .contains("ROADM")) { + // - XC Connection OTSi betwwen iOTSi y eOTSi of xpdr + // - Top connection OTSi between network ports of xpdrs in the Photonic media layer -> i_OTSi + 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 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 + if (!rdmNodelist.isEmpty()) { + connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist, + edgeRoadm1, edgeRoadm2)); + connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist)); + connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist)); + } + // Top connection in the DSR layer, between client ports of the xpdrs + connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNodelist)); + break; + default: + LOG.error("Service type format {} not supported", serviceProtName.getName()); + } + return connectionServMap; + } + + /** + * Process cancel resource result. + * @param serviceName Service name to build uuid. + */ + private void onCancelResourceResult(String serviceName) { + if (servicePathRpcResult.getStatus() == RpcStatusEx.Failed) { + LOG.info("PCE cancel resource failed !"); + return; + } else if (servicePathRpcResult.getStatus() == RpcStatusEx.Pending) { + LOG.warn("PCE cancel returned a Penging RpcStatusEx code!"); + return; + } else if (servicePathRpcResult.getStatus() != RpcStatusEx.Successful) { + LOG.error("PCE cancel returned an unknown RpcStatusEx code!"); + return; + } + LOG.info("PCE cancel resource done OK !"); + Uuid suuid = new Uuid(UUID.nameUUIDFromBytes(serviceName.getBytes(Charset.forName("UTF-8"))) + .toString()); + // get connections of connectivity service and remove them from tapi context and then remove + // service from context. The CEPs are maintained as they could be reused by another service + ConnectivityService connService = getConnectivityService(suuid); + if (connService == null) { + LOG.error("Service doesnt exist in tapi context"); + return; + } + for (Connection connection:connService.getConnection().values()) { + deleteConnection(connection.getConnectionUuid()); + } + deleteConnectivityService(suuid); + } + + @SuppressFBWarnings( + value = "ES_COMPARING_STRINGS_WITH_EQ", + justification = "false positives, not strings but real object references comparisons") + private Boolean compareServicePathRpcResult(ServicePathRpcResult notification) { + if (servicePathRpcResult == null) { + return false; + } + if (servicePathRpcResult.getNotificationType() != notification.getNotificationType()) { + return false; + } + if (servicePathRpcResult.getServiceName() != notification.getServiceName()) { + return false; + } + if (servicePathRpcResult.getStatus() != notification.getStatus()) { + return false; + } + if (servicePathRpcResult.getStatusMessage() != notification.getStatusMessage()) { + return false; + } + return true; + } + + private Map createXpdrCepsAndConnectionsDsr(List xpdrClientTplist, + List xpdrNodelist) { + Map connServMap = new HashMap<>(); + Map cepMap = new HashMap<>(); + + // Create 1 cep per Xpdr in the CLIENT and a 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, DSR, DSR, LayerProtocolName.DSR); + putXpdrCepInTopologyContext(xpdr, spcXpdrClient, DSR, DSR, netCep1); + + cepMap.put(netCep1.key(), netCep1); + } + + // 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(); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection + connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, DSR, LayerProtocolName.DSR); + this.connectionFullMap.put(connection.key(), connection); + + // ODU top connection that will be added to the service object + Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); + connServMap.put(conn.key(), conn); + + return connServMap; + } + + private Map createXpdrCepsAndConnectionsOdu(List xpdrNetworkTplist, + List xpdrNodelist) { + Map connServMap = new HashMap<>(); + Map cepMap = new HashMap<>(); + // Create 1 cep per Xpdr in the I_ODU and E_ODU, X connection between iODU and eODU and a top + // connection iODU between the xpdrs + for (String xpdr:xpdrNodelist) { + LOG.info("Creating ceps and xc for xpdr {}", xpdr); + String spcXpdrNetwork = xpdrNetworkTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst().get(); + + ConnectionEndPoint netCep1 = createCepXpdr(spcXpdrNetwork, E_ODU, DSR, LayerProtocolName.ODU); + putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, E_ODU, DSR, netCep1); + ConnectionEndPoint netCep2 = createCepXpdr(spcXpdrNetwork, I_ODU, DSR, LayerProtocolName.ODU); + putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, I_ODU, DSR, netCep2); + + cepMap.put(netCep1.key(), netCep1); + cepMap.put(netCep2.key(), netCep2); + + // Create x connection between I_ODU and E_ODU within xpdr + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection + connection = createXCBetweenCeps(netCep1, netCep2, spcXpdrNetwork, spcXpdrNetwork, ODU, + LayerProtocolName.ODU); + 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); + } + + // ODU top connection between edge xpdr e_ODU + String spcXpdr1 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist + .get(0))).findFirst().get(); + String spcXpdr2 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist + .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, E_ODU, LayerProtocolName.ODU); + this.connectionFullMap.put(connection.key(), connection); + + // ODU top connection that will be added to the service object + Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); + connServMap.put(conn.key(), conn); + + return connServMap; + } + + private Map createXpdrCepsAndConnectionsPht(List xpdrNetworkTplist, + List xpdrNodelist) { + Map connServMap = new HashMap<>(); + Map cepMap = new HashMap<>(); + + // create ceps and x connections within xpdr + for (String xpdr:xpdrNodelist) { + LOG.info("Creating ceps and xc for xpdr {}", xpdr); + String spcXpdrNetwork = xpdrNetworkTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst().get(); + // There should be 1 network tp per xpdr + // TODO photonic media model should be updated to have the corresponding CEPs. I will just create + // 3 different MC CEPs giving different IDs to show that they are different + // Create 3 CEPs for each xpdr otsi node and the corresponding cross connection matchin the NEPs + ConnectionEndPoint netCep1 = createCepXpdr(spcXpdrNetwork, PHTNC_MEDIA, OTSI, + LayerProtocolName.PHOTONICMEDIA); + putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, PHTNC_MEDIA, OTSI, netCep1); + ConnectionEndPoint netCep2 = createCepXpdr(spcXpdrNetwork, E_OTSI, OTSI, LayerProtocolName.PHOTONICMEDIA); + putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, E_OTSI, OTSI, netCep2); + ConnectionEndPoint netCep3 = createCepXpdr(spcXpdrNetwork, I_OTSI, OTSI, LayerProtocolName.PHOTONICMEDIA); + putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, I_OTSI, OTSI, netCep3); + cepMap.put(netCep1.key(), netCep1); + cepMap.put(netCep2.key(), netCep2); + cepMap.put(netCep3.key(), netCep3); + + // Create x connection between I_OTSi and E_OTSi within xpdr + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection + connection = createXCBetweenCeps(netCep2, netCep3, spcXpdrNetwork, spcXpdrNetwork, OTSI, + LayerProtocolName.PHOTONICMEDIA); + 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); + } + // OTSi top connection between edge I_OTSI Xpdr + String spcXpdr1 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist + .get(0))).findFirst().get(); + String spcXpdr2 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist + .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, I_OTSI, LayerProtocolName.PHOTONICMEDIA); + this.connectionFullMap.put(connection.key(), connection); + + // OTSi top connection that will be added to the service object + Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); + connServMap.put(conn.key(), conn); + + + return connServMap; + } + + private Map createRoadmCepsAndConnections(List rdmAddDropTplist, + List rdmDegTplist, + List rdmNodelist, + String edgeRoadm1, String edgeRoadm2) { + // TODO: will need to check if things exist already or not + Map connServMap = new HashMap<>(); + Map cepMap = new HashMap<>(); + // create ceps and x connections within roadm + for (String roadm : rdmNodelist) { + LOG.info("Creating ceps and xc for roadm {}", roadm); + String spcRdmAD = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get(); + LOG.info("AD port of ROADm {} = {}", roadm, spcRdmAD); + // There should be only 1 AD and 1 DEG per roadm + // TODO photonic media model should be updated to have the corresponding CEPs. I will just create + // 3 different MC CEPs giving different IDs to show that they are different + // Create 3 CEPs for each AD and DEG and the corresponding cross connections, matching the NEPs + // created in the topology creation + // add CEPs to the topology to the corresponding ONEP + ConnectionEndPoint adCep1 = createCepRoadm(spcRdmAD, PHTNC_MEDIA); + putRdmCepInTopologyContext(roadm, spcRdmAD, PHTNC_MEDIA, adCep1); + ConnectionEndPoint adCep2 = createCepRoadm(spcRdmAD, MC); + putRdmCepInTopologyContext(roadm, spcRdmAD, MC, adCep2); + ConnectionEndPoint adCep3 = createCepRoadm(spcRdmAD, OTSI_MC); + putRdmCepInTopologyContext(roadm, spcRdmAD, OTSI_MC, adCep3); + cepMap.put(adCep1.key(), adCep1); + cepMap.put(adCep2.key(), adCep2); + cepMap.put(adCep3.key(), adCep3); + + String spcRdmDEG = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get(); + LOG.info("Degree port of ROADm {} = {}", roadm, spcRdmDEG); + + ConnectionEndPoint degCep1 = createCepRoadm(spcRdmDEG, PHTNC_MEDIA); + putRdmCepInTopologyContext(roadm, spcRdmDEG, PHTNC_MEDIA, degCep1); + ConnectionEndPoint degCep2 = createCepRoadm(spcRdmDEG, MC); + putRdmCepInTopologyContext(roadm, spcRdmDEG, MC, degCep2); + ConnectionEndPoint degCep3 = createCepRoadm(spcRdmDEG, OTSI_MC); + putRdmCepInTopologyContext(roadm, spcRdmDEG, OTSI_MC, degCep3); + cepMap.put(degCep1.key(), degCep1); + cepMap.put(degCep2.key(), degCep2); + cepMap.put(degCep3.key(), degCep3); + + LOG.info("Going to create cross connections for ROADM {}", roadm); + // Create X connections between MC and OTSi_MC for full map + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection + connection1 = createXCBetweenCeps(adCep2, degCep2, spcRdmAD, spcRdmDEG, MC, + LayerProtocolName.PHOTONICMEDIA); + LOG.info("Cross connection 1 created = {}", connection1.toString()); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection + connection2 = createXCBetweenCeps(adCep3, degCep3, spcRdmAD, spcRdmDEG, OTSI_MC, + LayerProtocolName.PHOTONICMEDIA); + LOG.info("Cross connection 2 created = {}", connection2.toString()); + this.connectionFullMap.put(connection1.key(), connection1); + 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); + } + LOG.info("Going to create top connections betwee 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)) { + LOG.info("Reached last roadm. No more MC connections"); + break; + } + // Current roadm with roadm i + 1 --> MC + String roadm1 = rdmNodelist.get(i); + String spcRdmAD1 = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm1)).findFirst().get(); + String roadm2 = rdmNodelist.get(i + 1); + String spcRdmAD2 = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm2)).findFirst().get(); + LOG.info("Creating top connection from {} to {} between tps: {}-{}", roadm1, roadm2, spcRdmAD1, spcRdmAD2); + + // 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, MC, LayerProtocolName.PHOTONICMEDIA); + this.connectionFullMap.put(connection.key(), connection); + LOG.info("Top connection created = {}", connection.toString()); + + // Create top connections that will be added to the service object + Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); + connServMap.put(conn.key(), conn); + } + + // OTSiMC top connection between edge roadms + LOG.info("Going to created top connection between OTSiMC"); + String spcRdmAD1 = rdmAddDropTplist.stream().filter(adp -> adp.contains(edgeRoadm1)).findFirst().get(); + 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, OTSI_MC, + LayerProtocolName.PHOTONICMEDIA); + this.connectionFullMap.put(connection.key(), connection); + LOG.info("Top connection created = {}", connection.toString()); + + // OTSiMC top connections that will be added to the service object + Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build(); + connServMap.put(conn.key(), conn); + return connServMap; + } + + private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection + createTopConnection(String tp1, String tp2, + Map cepMap, String qual, LayerProtocolName topPortocol) { + // 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 = + cepMap.get(new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey( + new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", tp1.split("\\+")[0], + qual, tp1.split("\\+")[1])).getBytes(Charset.forName("UTF-8"))) + .toString()))); + LOG.info("ADCEP1 = {}", adCep1.toString()); + org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cep1 = + new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder() + .setNodeEdgePointUuid(adCep1.getClientNodeEdgePoint() + .values().stream().findFirst().get().getNodeEdgePointUuid()) + .setTopologyUuid(adCep1.getClientNodeEdgePoint() + .values().stream().findFirst().get().getTopologyUuid()) + .setNodeUuid(adCep1.getClientNodeEdgePoint() + .values().stream().findFirst().get().getNodeUuid()) + .setConnectionEndPointUuid(adCep1.getUuid()) + .build(); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ConnectionEndPoint adCep2 = + cepMap.get(new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey( + new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", tp2.split("\\+")[0], + qual, tp2.split("\\+")[1])).getBytes(Charset.forName("UTF-8"))) + .toString()))); + LOG.info("ADCEP2 = {}", adCep2.toString()); + org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cep2 = + new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder() + .setNodeEdgePointUuid(adCep2.getClientNodeEdgePoint() + .values().stream().findFirst().get().getNodeEdgePointUuid()) + .setTopologyUuid(adCep2.getClientNodeEdgePoint() + .values().stream().findFirst().get().getTopologyUuid()) + .setNodeUuid(adCep2.getClientNodeEdgePoint() + .values().stream().findFirst().get().getNodeUuid()) + .setConnectionEndPointUuid(adCep1.getUuid()) + .build(); + Map ceps = new HashMap<>(); + ceps.put(cep1.key(), cep1); + ceps.put(cep2.key(), cep2); + Name connName = new NameBuilder() + .setValueName("Connection name") + .setValue(String.join("+", "TOP", tp1, tp2, qual)) + .build(); + // TODO: lower connection, supported link....... + return new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder() + .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "TOP", tp1, tp2, qual)) + .getBytes(Charset.forName("UTF-8"))).toString())) + .setName(Map.of(connName.key(), connName)) + .setConnectionEndPoint(ceps) + .setOperationalState(OperationalState.DISABLED) + .setLayerProtocolName(topPortocol) + .setLifecycleState(LifecycleState.POTENTIALAVAILABLE) + .setDirection(ForwardingDirection.BIDIRECTIONAL) + .build(); + } + + private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection + createXCBetweenCeps(ConnectionEndPoint cep1, ConnectionEndPoint cep2, String tp1, String tp2, String qual, + LayerProtocolName xcProtocol) { + LOG.info("Creation cross connection between: {} and {}", tp1, tp2); + LOG.info("Cross connection name = {}", String.join("+", "XC", tp1, tp2, qual)); + LOG.info("CEP1 = {}", cep1.getClientNodeEdgePoint().toString()); + LOG.info("CEP2 = {}", cep2.getClientNodeEdgePoint().toString()); + org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cepServ1 = + new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder() + .setNodeEdgePointUuid(cep1.getClientNodeEdgePoint() + .values().stream().findFirst().get().getNodeEdgePointUuid()) + .setTopologyUuid(cep1.getClientNodeEdgePoint() + .values().stream().findFirst().get().getTopologyUuid()) + .setNodeUuid(cep1.getClientNodeEdgePoint() + .values().stream().findFirst().get().getNodeUuid()) + .setConnectionEndPointUuid(cep1.getUuid()) + .build(); + org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cepServ2 = + new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder() + .setNodeEdgePointUuid(cep2.getClientNodeEdgePoint() + .values().stream().findFirst().get().getNodeEdgePointUuid()) + .setTopologyUuid(cep2.getClientNodeEdgePoint() + .values().stream().findFirst().get().getTopologyUuid()) + .setNodeUuid(cep2.getClientNodeEdgePoint() + .values().stream().findFirst().get().getNodeUuid()) + .setConnectionEndPointUuid(cep2.getUuid()) + .build(); + Map ceps = new HashMap<>(); + ceps.put(cepServ1.key(), cepServ1); + ceps.put(cepServ2.key(), cepServ2); + Name connName = new NameBuilder() + .setValueName("Connection name") + .setValue(String.join("+", "XC", tp1, tp2, qual)) + .build(); + // TODO: lower connection, supported link....... + return new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder() + .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "XC", tp1, tp2, qual)) + .getBytes(Charset.forName("UTF-8"))).toString())) + .setName(Map.of(connName.key(), connName)) + .setConnectionEndPoint(ceps) + .setOperationalState(OperationalState.DISABLED) + .setLayerProtocolName(xcProtocol) + .setLifecycleState(LifecycleState.POTENTIALAVAILABLE) + .setDirection(ForwardingDirection.BIDIRECTIONAL) + .build(); + } + + private ConnectionEndPoint createCepRoadm(String id, String qualifier) { + LOG.info("NEP = {}", String.join("+", id.split("\\+")[0], qualifier, id.split("\\+")[1])); + Name cepName = new NameBuilder() + .setValueName("ConnectionEndPoint name") + .setValue(String.join("+", id.split("\\+")[0], qualifier, + id.split("\\+")[1])) + .build(); + ClientNodeEdgePoint cnep = new ClientNodeEdgePointBuilder() + .setNodeEdgePointUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", id.split("\\+")[0], + qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8"))) + .toString())) + .setNodeUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+",id.split("\\+")[0], + qualifier)).getBytes(Charset.forName("UTF-8"))) + .toString())) + .setTopologyUuid(new Uuid(UUID.nameUUIDFromBytes(TopologyUtils.T0_FULL_MULTILAYER + .getBytes(Charset.forName("UTF-8"))).toString())) + .build(); + // TODO: add augmentation with the corresponding cep-spec (i.e. MC, OTSiMC...) + // TODO: add parent ONEP?? + ConnectionEndPointBuilder cepBldr = new ConnectionEndPointBuilder() + .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", id.split("\\+")[0], + qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8"))) + .toString())) + .setClientNodeEdgePoint(Map.of(cnep.key(), cnep)) + .setName(Map.of(cepName.key(), cepName)) + .setConnectionPortRole(PortRole.SYMMETRIC) + .setConnectionPortDirection(PortDirection.BIDIRECTIONAL) + .setOperationalState(OperationalState.ENABLED) + .setLifecycleState(LifecycleState.INSTALLED) + .setLayerProtocolName(LayerProtocolName.PHOTONICMEDIA); + return cepBldr.build(); + } + + private ConnectionEndPoint createCepXpdr(String id, String qualifier, String nodeLayer, + LayerProtocolName cepProtocol) { + Name cepName = new NameBuilder() + .setValueName("ConnectionEndPoint name") + .setValue(String.join("+", id.split("\\+")[0], qualifier, + id.split("\\+")[1])) + .build(); + ClientNodeEdgePoint cnep = new ClientNodeEdgePointBuilder() + .setNodeEdgePointUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", id.split("\\+")[0], + qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8"))) + .toString())) + .setNodeUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+",id.split("\\+")[0], + nodeLayer)).getBytes(Charset.forName("UTF-8"))) + .toString())) + .setTopologyUuid(new Uuid(UUID.nameUUIDFromBytes(TopologyUtils.T0_FULL_MULTILAYER + .getBytes(Charset.forName("UTF-8"))).toString())) + .build(); + // TODO: add augmentation with the corresponding cep-spec (i.e. MC, OTSiMC...) + // TODO: add parent ONEP?? + ConnectionEndPointBuilder cepBldr = new ConnectionEndPointBuilder() + .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", id.split("\\+")[0], + qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8"))) + .toString())) + .setClientNodeEdgePoint(Map.of(cnep.key(), cnep)) + .setName(Map.of(cepName.key(), cepName)) + .setConnectionPortRole(PortRole.SYMMETRIC) + .setConnectionPortDirection(PortDirection.BIDIRECTIONAL) + .setOperationalState(OperationalState.ENABLED) + .setLifecycleState(LifecycleState.INSTALLED) + .setLayerProtocolName(cepProtocol); + return cepBldr.build(); + } + + private void putRdmCepInTopologyContext(String node, String spcRdmAD, String qual, ConnectionEndPoint cep) { + LOG.info("NEP id before Merge = {}", String.join("+", node, qual, spcRdmAD.split("\\+")[1])); + LOG.info("Node of NEP id before Merge = {}", String.join("+", node, PHTNC_MEDIA)); + // Give uuids so that it is easier to look for things: topology uuid, node uuid, nep uuid, cep + Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TopologyUtils.T0_FULL_MULTILAYER + .getBytes(Charset.forName("UTF-8"))).toString()); + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, PHTNC_MEDIA) + .getBytes(Charset.forName("UTF-8"))).toString()); + Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, qual, spcRdmAD.split("\\+")[1]) + .getBytes(Charset.forName("UTF-8"))).toString()); + updateTopologyWithCep(topoUuid, nodeUuid, nepUuid, cep); + } + + private void putXpdrCepInTopologyContext(String node, String spcXpdrNet, String qual, String nodeLayer, + ConnectionEndPoint cep) { + // Give uuids so that it is easier to look for things: topology uuid, node uuid, nep uuid, cep + Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TopologyUtils.T0_FULL_MULTILAYER + .getBytes(Charset.forName("UTF-8"))).toString()); + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, nodeLayer) + .getBytes(Charset.forName("UTF-8"))).toString()); + Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, qual, spcXpdrNet.split("\\+")[1]) + .getBytes(Charset.forName("UTF-8"))).toString()); + updateTopologyWithCep(topoUuid, nodeUuid, nepUuid, cep); + } + + public void updateTopologyWithCep(Uuid topoUuid, Uuid nodeUuid, Uuid nepUuid, ConnectionEndPoint cep) { + // TODO: verify this is correct. Should we identify the context IID with the context UUID?? + InstanceIdentifier onepIID = 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 optionalOnep = this.networkTransactionService.read( + LogicalDatastoreType.OPERATIONAL, onepIID).get(); + if (!optionalOnep.isPresent()) { + LOG.error("ONEP is not present in datastore"); + return; + } + OwnedNodeEdgePoint onep = optionalOnep.get(); + LOG.info("ONEP found = {}", onep.toString()); + // TODO -> If cep exists -> skip merging to datasore + OwnedNodeEdgePoint1 onep1 = onep.augmentation(OwnedNodeEdgePoint1.class); + if (onep1 != null && onep1.getCepList() != null && onep1.getCepList().getConnectionEndPoint() != null) { + if (onep1.getCepList().getConnectionEndPoint().containsKey( + new org.opendaylight.yang.gen.v1 + .urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(cep.key()))) { + LOG.info("CEP already in topology, skipping merge"); + return; + } + } + // Updated ONEP + CepList cepList = new CepListBuilder().setConnectionEndPoint(Map.of(cep.key(), cep)).build(); + OwnedNodeEdgePoint1 onep1Bldr = new OwnedNodeEdgePoint1Builder().setCepList(cepList).build(); + OwnedNodeEdgePoint newOnep = new OwnedNodeEdgePointBuilder(onep) + .addAugmentation(onep1Bldr) + .build(); + LOG.info("New ONEP is {}", newOnep.toString()); + // merge in datastore + this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, onepIID, + newOnep); + this.networkTransactionService.commit().get(); + LOG.info("CEP added successfully."); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Couldnt update cep in topology", e); + } + } + + private void updateConnectionContextWithConn( + Map connFullMap, + Map connMap, Uuid suuid) { + // TODO: verify this is correct. Should we identify the context IID with the context UUID?? + try { + ConnectivityService connServ = getConnectivityService(suuid); + ConnectivityService updtConnServ = new ConnectivityServiceBuilder(connServ) + .setConnection(connMap) + .build(); + + // Perform the merge operation with the new conn service and the connection context updated + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext + connectivityContext = new ConnectivityContextBuilder() + .setConnectivityService(Map.of(updtConnServ.key(), updtConnServ)) + .setConnection(connFullMap) + .build(); + InstanceIdentifier connectivitycontextIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .build(); + // merge in datastore + this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connectivitycontextIID, + connectivityContext); + this.networkTransactionService.commit().get(); + LOG.info("TAPI connectivity merged successfully."); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to merge TAPI connectivity", e); + } + } + + private ConnectivityService getConnectivityService(Uuid suuid) { + try { + // First read connectivity service with service uuid and update info + InstanceIdentifier connectivityServIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(ConnectivityService.class, new ConnectivityServiceKey(suuid)) + .build(); + + Optional optConnServ = + this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityServIID).get(); + if (!optConnServ.isPresent()) { + LOG.error("Connectivity service not found in tapi context"); + return null; + } + return optConnServ.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Connectivity service not found in tapi context. Error:", e); + return null; + } + } + + private void deleteConnectivityService(Uuid suuid) { + // First read connectivity service with service uuid and update info + InstanceIdentifier connectivityServIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(ConnectivityService.class, new ConnectivityServiceKey(suuid)) + .build(); + try { + this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectivityServIID); + this.networkTransactionService.commit().get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to delete TAPI connectivity service", e); + } + } + + private void deleteConnection(Uuid connectionUuid) { + // First read connectivity service with service uuid and update info + InstanceIdentifier connectionIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection.class, + new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey( + connectionUuid)) + .build(); + try { + this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectionIID); + this.networkTransactionService.commit().get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to delete TAPI connection", e); + } + } + + private String getIdBasedOnModelVersion(String nodeid) { + return nodeid.matches("[A-Z]{5}-[A-Z0-9]{2}-.*") + ? String.join("-", nodeid.split("-")[0], nodeid.split("-")[1]) : nodeid.split("-")[0]; + } + + public void setInput(CreateConnectivityServiceInput input) { + this.input = input; + } + + public void setServiceUuid(Uuid serviceUuid) { + this.serviceUuid = serviceUuid; + } +} diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiRendererListenerImpl.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiRendererListenerImpl.java new file mode 100644 index 000000000..d177caec8 --- /dev/null +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiRendererListenerImpl.java @@ -0,0 +1,282 @@ +/* + * Copyright © 2021 Nokia, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.tapi.listeners; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.nio.charset.Charset; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.transportpce.common.network.NetworkTransactionImpl; +import org.opendaylight.transportpce.common.network.NetworkTransactionService; +import org.opendaylight.transportpce.common.network.RequestProcessor; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.RendererRpcResultSp; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.TransportpceRendererListener; +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.Context; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LifecycleState; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.OperationalState; +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.connectivity.rev181210.Context1; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityService; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.Connection; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TapiRendererListenerImpl implements TransportpceRendererListener { + + private static final Logger LOG = LoggerFactory.getLogger(TapiRendererListenerImpl.class); + private final DataBroker dataBroker; + private Uuid serviceUuid; + private RendererRpcResultSp serviceRpcResultSp; + private final NetworkTransactionService networkTransactionService; + + public TapiRendererListenerImpl(DataBroker dataBroker) { + this.dataBroker = dataBroker; + this.networkTransactionService = new NetworkTransactionImpl(new RequestProcessor(this.dataBroker)); + } + + @Override + public void onRendererRpcResultSp(RendererRpcResultSp notification) { + if (compareServiceRpcResultSp(notification)) { + LOG.warn("ServiceRpcResultSp already wired !"); + return; + } + serviceRpcResultSp = notification; + int notifType = serviceRpcResultSp.getNotificationType().getIntValue(); + LOG.info("Renderer '{}' Notification received : {}", serviceRpcResultSp.getNotificationType().getName(), + notification); + /* service-implementation-request. */ + if (notifType == 3) { + onServiceImplementationResult(notification); + } + } + + /** + * Process service implementation result for serviceName. + * @param notification RendererRpcResultSp + */ + private void onServiceImplementationResult(RendererRpcResultSp notification) { + switch (serviceRpcResultSp.getStatus()) { + case Successful: + onSuccededServiceImplementation(); + break; + case Failed: + onFailedServiceImplementation(notification.getServiceName()); + break; + case Pending: + LOG.warn("Service Implementation still pending according to RpcStatusEx"); + break; + default: + LOG.warn("Service Implementation has an unknown RpcStatusEx code"); + break; + } + } + + /** + * Process succeeded service implementation for service. + */ + private void onSuccededServiceImplementation() { + LOG.info("Service implemented !"); + // TODO: update Connections and Connectivity Service states + ConnectivityService connectivityService = getConnectivityService(this.serviceUuid); + if (connectivityService == null) { + LOG.error("Couldnt retrieve service from datastore"); + return; + } + LOG.info("Connectivity service = {}", connectivityService.toString()); + // TODO --> this throws error because the renderer goes really fast. Is this normal?? + ConnectivityService updtConnServ = new ConnectivityServiceBuilder(connectivityService) + .setAdministrativeState(AdministrativeState.UNLOCKED) + .setLifecycleState(LifecycleState.INSTALLED) + .setOperationalState(OperationalState.ENABLED) + .build(); + for (Connection connection:updtConnServ.getConnection().values()) { + updateConnectionState(connection.getConnectionUuid()); + } + updateConnectivityService(updtConnServ); + } + + /** + * Process failed service implementation for serviceName. + * @param serviceName String + */ + private void onFailedServiceImplementation(String serviceName) { + LOG.error("Renderer implementation failed !"); + LOG.info("PCE cancel resource done OK !"); + Uuid suuid = new Uuid(UUID.nameUUIDFromBytes(serviceName.getBytes(Charset.forName("UTF-8"))) + .toString()); + // get connections of connectivity service and remove them from tapi context and then remove + // service from context. The CEPs are maintained as they could be reused by another service + ConnectivityService connService = getConnectivityService(suuid); + if (connService == null) { + LOG.error("Service doesnt exist in tapi context"); + return; + } + for (Connection connection:connService.getConnection().values()) { + deleteConnection(connection.getConnectionUuid()); + } + deleteConnectivityService(suuid); + } + + @SuppressFBWarnings( + value = "ES_COMPARING_STRINGS_WITH_EQ", + justification = "false positives, not strings but real object references comparisons") + private Boolean compareServiceRpcResultSp(RendererRpcResultSp notification) { + if (serviceRpcResultSp == null) { + return false; + } + if (serviceRpcResultSp.getNotificationType() != notification.getNotificationType()) { + return false; + } + if (serviceRpcResultSp.getServiceName() != notification.getServiceName()) { + return false; + } + if (serviceRpcResultSp.getStatus() != notification.getStatus()) { + return false; + } + if (serviceRpcResultSp.getStatusMessage() != notification.getStatusMessage()) { + return false; + } + return true; + } + + private ConnectivityService getConnectivityService(Uuid suuid) { + // TODO: verify this is correct. Should we identify the context IID with the context UUID?? + try { + // First read connectivity service with service uuid and update info + InstanceIdentifier connectivityServIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(ConnectivityService.class, new ConnectivityServiceKey(suuid)) + .build(); + + Optional optConnServ = + this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityServIID).get(); + if (!optConnServ.isPresent()) { + LOG.error("Connectivity service not found in tapi context"); + return null; + } + return optConnServ.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to merge TAPI connectivity", e); + return null; + } + } + + private void updateConnectionState(Uuid connectionUuid) { + // TODO: verify this is correct. Should we identify the context IID with the context UUID?? + try { + // First read connection with connection uuid and update info + InstanceIdentifier connectionIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection.class, + new ConnectionKey(connectionUuid)) + .build(); + + Optional optConn = + this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectionIID).get(); + if (!optConn.isPresent()) { + LOG.error("Connection not found in tapi context"); + return; + } + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection + newConnection = new ConnectionBuilder(optConn.get()).setLifecycleState(LifecycleState.INSTALLED) + .setOperationalState(OperationalState.ENABLED).build(); + // merge in datastore + this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connectionIID, + newConnection); + this.networkTransactionService.commit().get(); + LOG.info("TAPI connection merged successfully."); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to merge TAPI connection", e); + } + } + + private void updateConnectivityService(ConnectivityService updtConnServ) { + // TODO: verify this is correct. Should we identify the context IID with the context UUID?? + try { + // First read connectivity service with connectivity service uuid and update info + InstanceIdentifier connServIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(ConnectivityService.class, new ConnectivityServiceKey(updtConnServ.getUuid())) + .build(); + + Optional optConnServ = + this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connServIID).get(); + if (!optConnServ.isPresent()) { + LOG.error("Connection not found in tapi context"); + return; + } + ConnectivityService newConnServ = new ConnectivityServiceBuilder(updtConnServ).build(); + // merge in datastore + this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connServIID, + newConnServ); + this.networkTransactionService.commit().get(); + LOG.info("TAPI connectivity service merged successfully."); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to merge TAPI connectivity service", e); + } + } + + private void deleteConnectivityService(Uuid suuid) { + // First read connectivity service with service uuid and update info + InstanceIdentifier connectivityServIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(ConnectivityService.class, new ConnectivityServiceKey(suuid)) + .build(); + try { + this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectivityServIID); + this.networkTransactionService.commit().get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to delete TAPI connectivity service", e); + } + } + + private void deleteConnection(Uuid connectionUuid) { + // First read connectivity service with service uuid and update info + InstanceIdentifier connectionIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection.class, + new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey( + connectionUuid)) + .build(); + try { + this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectionIID); + this.networkTransactionService.commit().get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to delete TAPI connection", e); + } + } + + public void setServiceUuid(Uuid serviceUuid) { + this.serviceUuid = serviceUuid; + } +} diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiServiceHandlerListenerImpl.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiServiceHandlerListenerImpl.java new file mode 100644 index 000000000..03ad2e5e3 --- /dev/null +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiServiceHandlerListenerImpl.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2021 Nokia, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.tapi.listeners; + +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.ServiceRpcResultSh; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.TransportpceServicehandlerListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TapiServiceHandlerListenerImpl implements TransportpceServicehandlerListener { + + private static final Logger LOG = LoggerFactory.getLogger(TapiServiceHandlerListenerImpl.class); + private final DataBroker dataBroker; + + public TapiServiceHandlerListenerImpl(DataBroker dataBroker) { + this.dataBroker = dataBroker; + + } + + @Override + public void onServiceRpcResultSh(ServiceRpcResultSh notification) { + LOG.info("Avoid dataBroker error {}", dataBroker.getClass().getCanonicalName()); + } +} 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 3357519ae..2de29bb51 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 @@ -122,23 +122,23 @@ public class ConvertORTopoToTapiTopo { public void convertNode(Node ietfNode, List networkPorts) { this.ietfNodeId = ietfNode.getNodeId().getValue(); if (ietfNode.augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1.class) - == null) { + == null) { return; } this.ietfNodeType = ietfNode.augmentation( org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1.class).getNodeType(); this.ietfNodeAdminState = ietfNode.augmentation( - org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1.class) + org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1.class) .getAdministrativeState(); this.ietfNodeOperState = ietfNode.augmentation( - org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1.class) + org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1.class) .getOperationalState(); this.oorNetworkPortList = ietfNode.augmentation( - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1.class) + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1.class) .getTerminationPoint().values().stream() .filter(tp -> tp.augmentation(TerminationPoint1.class).getTpType().getIntValue() - == OpenroadmTpType.XPONDERNETWORK.getIntValue() - && networkPorts.contains(tp.getTpId().getValue())) + == OpenroadmTpType.XPONDERNETWORK.getIntValue() + && networkPorts.contains(tp.getTpId().getValue())) .sorted((tp1, tp2) -> tp1.getTpId().getValue().compareTo(tp2.getTpId().getValue())) .collect(Collectors.toList()); if (!OpenroadmNodeType.TPDR.equals(this.ietfNodeType)) { @@ -146,11 +146,11 @@ public class ConvertORTopoToTapiTopo { .values().stream().findFirst().get(); this.oorClientPortList = ietfNode.augmentation( org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1.class) - .getTerminationPoint().values().stream() - .filter(tp -> tp.augmentation(TerminationPoint1.class).getTpType().getIntValue() - == OpenroadmTpType.XPONDERCLIENT.getIntValue()) - .sorted((tp1, tp2) -> tp1.getTpId().getValue().compareTo(tp2.getTpId().getValue())) - .collect(Collectors.toList()); + .getTerminationPoint().values().stream() + .filter(tp -> tp.augmentation(TerminationPoint1.class).getTpType().getIntValue() + == OpenroadmTpType.XPONDERCLIENT.getIntValue()) + .sorted((tp1, tp2) -> tp1.getTpId().getValue().compareTo(tp2.getTpId().getValue())) + .collect(Collectors.toList()); } else { this.oorOduSwitchingPool = createOduSwitchingPoolForTp100G(); List tpList = this.oorOduSwitchingPool.getNonBlockingList().values().stream() @@ -205,13 +205,13 @@ public class ConvertORTopoToTapiTopo { List linksToNotConvert = new ArrayList<>(); LOG.info("creation of {} otn links", otnLinkMap.size() / 2); for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network - .Link otnlink : otnLinkList) { + .Link otnlink : otnLinkList) { if (!linksToNotConvert.contains(otnlink.getLinkId().getValue())) { org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks .network.Link oppositeLink = otnLinkMap.get(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns .yang.ietf.network.topology.rev180226.networks.network.LinkKey(otnlink.augmentation( - org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1.class) - .getOppositeLink())); + org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1.class) + .getOppositeLink())); Link tapiLink = createTapiLink(otnlink, oppositeLink); linksToNotConvert.add(oppositeLink.getLinkId().getValue()); tapiLinks.put(tapiLink.key(), tapiLink); @@ -261,7 +261,7 @@ public class ConvertORTopoToTapiTopo { for (TerminationPoint tp : this.oorNetworkPortList) { TpId tpid1 = tp.getTpId(); TpId tpid2 = new TpId(tp.augmentation( - org.opendaylight.yang.gen.v1.http.transportpce.topology.rev201019.TerminationPoint1.class) + org.opendaylight.yang.gen.v1.http.transportpce.topology.rev201019.TerminationPoint1.class) .getAssociatedConnectionMapPort()); List tpList = new ArrayList<>(); tpList.add(tpid1); @@ -280,7 +280,7 @@ public class ConvertORTopoToTapiTopo { } private List - pruneTapiPhotonicNodes() { + pruneTapiPhotonicNodes() { List prunedTapiPhotonicNodes = new ArrayList<>(); List tapiPhotonicNodes @@ -288,12 +288,11 @@ public class ConvertORTopoToTapiTopo { .filter(n -> LayerProtocolName.PHOTONICMEDIA.equals(n.getLayerProtocolName().get(0))) .collect(Collectors.toList()); for (org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node node - : tapiPhotonicNodes) { + : tapiPhotonicNodes) { Map onepM = new HashMap<>(); for (Map.Entry entry : node.getOwnedNodeEdgePoint().entrySet()) { if (entry.getValue().getName().values().stream() - .filter(name -> name.getValueName().startsWith("eNodeEdgePoint")) - .count() > 0) { + .filter(name -> name.getValueName().startsWith("eNodeEdgePoint")).count() > 0) { onepM.put(entry.getKey(), entry.getValue()); } } @@ -305,7 +304,7 @@ public class ConvertORTopoToTapiTopo { } private Map convertListNodeWithListNepToMapForUuidAndName( - List nodes) { + List nodes) { Map uuidNameMap = new HashMap<>(); for (org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node node : nodes) { for (OwnedNodeEdgePoint nep : node.nonnullOwnedNodeEdgePoint().values()) { @@ -321,7 +320,7 @@ public class ConvertORTopoToTapiTopo { } private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node - createTapiNode(Map nodeNames, List layerProtocols) { + createTapiNode(Map nodeNames, List layerProtocols) { Uuid nodeUuid = null; Map onepl = new HashMap<>(); Map nodeRuleGroupList = new HashMap<>(); @@ -341,23 +340,22 @@ public class ConvertORTopoToTapiTopo { .getValueName(), nodeNames.get(nodeNames.keySet().iterator().next()).getValue()); } return new NodeBuilder() - .setUuid(nodeUuid) - .setName(nodeNames) - .setLayerProtocolName(layerProtocols) - .setAdministrativeState(setTapiAdminState(this.ietfNodeAdminState)) - .setOperationalState(setTapiOperationalState(this.ietfNodeOperState)) - .setLifecycleState(LifecycleState.INSTALLED) - .setOwnedNodeEdgePoint(onepl) - .setNodeRuleGroup(nodeRuleGroupList) - .build(); + .setUuid(nodeUuid) + .setName(nodeNames) + .setLayerProtocolName(layerProtocols) + .setAdministrativeState(setTapiAdminState(this.ietfNodeAdminState)) + .setOperationalState(setTapiOperationalState(this.ietfNodeOperState)) + .setLifecycleState(LifecycleState.INSTALLED) + .setOwnedNodeEdgePoint(onepl) + .setNodeRuleGroup(nodeRuleGroupList) + .build(); } private AdministrativeState setTapiAdminState(AdminStates adminState) { if (adminState == null) { return null; } - return adminState.equals(AdminStates.InService) - ? AdministrativeState.UNLOCKED : AdministrativeState.LOCKED; + return adminState.equals(AdminStates.InService) ? AdministrativeState.UNLOCKED : AdministrativeState.LOCKED; } private AdministrativeState setTapiAdminState(AdminStates adminState1, AdminStates adminState2) { @@ -390,13 +388,13 @@ public class ConvertORTopoToTapiTopo { } private Uuid getNodeUuid4Photonic(Map onepl, - Map nodeRuleGroupList, Map ruleList) { + Map nodeRuleGroupList, Map ruleList) { Uuid nodeUuid; nodeUuid = this.uuidMap.get(String.join("+", this.ietfNodeId, OTSI)); // iNep creation on otsi node for (int i = 0; i < oorNetworkPortList.size(); i++) { Uuid nepUuid1 = new Uuid(UUID.nameUUIDFromBytes( - (String.join("+", this.ietfNodeId, I_OTSI, oorNetworkPortList.get(i).getTpId().getValue())) + (String.join("+", this.ietfNodeId, I_OTSI, oorNetworkPortList.get(i).getTpId().getValue())) .getBytes(Charset.forName("UTF-8"))) .toString()); this.uuidMap.put(String.join("+", this.ietfNodeId, I_OTSI, oorNetworkPortList.get(i).getTpId().getValue()), @@ -414,7 +412,7 @@ public class ConvertORTopoToTapiTopo { // eNep creation on otsi node for (int i = 0; i < oorNetworkPortList.size(); i++) { Uuid nepUuid2 = new Uuid(UUID.nameUUIDFromBytes( - (String.join("+", this.ietfNodeId, E_OTSI, oorNetworkPortList.get(i).getTpId().getValue())) + (String.join("+", this.ietfNodeId, E_OTSI, oorNetworkPortList.get(i).getTpId().getValue())) .getBytes(Charset.forName("UTF-8"))) .toString()); this.uuidMap.put(String.join("+", this.ietfNodeId, E_OTSI, oorNetworkPortList.get(i).getTpId().getValue()), @@ -455,8 +453,8 @@ public class ConvertORTopoToTapiTopo { nepList.put(enep.key(), enep); NodeRuleGroup nodeRuleGroup = new NodeRuleGroupBuilder() .setUuid(new Uuid( - UUID.nameUUIDFromBytes(("otsi node rule group " + count).getBytes(Charset.forName("UTF-8"))) - .toString())) + UUID.nameUUIDFromBytes(("otsi node rule group " + count).getBytes(Charset.forName("UTF-8"))) + .toString())) .setRule(ruleList) .setNodeEdgePoint(nepList) .build(); @@ -467,14 +465,14 @@ public class ConvertORTopoToTapiTopo { } private Uuid getNodeUuid4Dsr(Map onepl, - Map nodeRuleGroupList, Map ruleList) { + Map nodeRuleGroupList, Map ruleList) { Uuid nodeUuid; nodeUuid = this.uuidMap.get(String.join("+", this.ietfNodeId, DSR)); // client nep creation on DSR/ODU node for (int i = 0; i < oorClientPortList.size(); i++) { Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes( (String.join("+", this.ietfNodeId, DSR, oorClientPortList.get(i).getTpId().getValue())) - .getBytes(Charset.forName("UTF-8"))).toString()); + .getBytes(Charset.forName("UTF-8"))).toString()); this.uuidMap.put(String.join("+", this.ietfNodeId, DSR, oorClientPortList.get(i).getTpId().getValue()), nepUuid); NameBuilder nameBldr = new NameBuilder().setValue(oorClientPortList.get(i).getTpId().getValue()); @@ -493,7 +491,7 @@ public class ConvertORTopoToTapiTopo { for (int i = 0; i < oorNetworkPortList.size(); i++) { Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes( (String.join("+", this.ietfNodeId, DSR, oorNetworkPortList.get(i).getTpId().getValue())) - .getBytes(Charset.forName("UTF-8"))).toString()); + .getBytes(Charset.forName("UTF-8"))).toString()); this.uuidMap.put(String.join("+", this.ietfNodeId, DSR, oorNetworkPortList.get(i).getTpId().getValue()), nepUuid); Name onedName = new NameBuilder() @@ -525,8 +523,8 @@ public class ConvertORTopoToTapiTopo { } NodeRuleGroup nodeRuleGroup = new NodeRuleGroupBuilder() .setUuid(new Uuid( - UUID.nameUUIDFromBytes(("dsr node rule group " + count).getBytes(Charset.forName("UTF-8"))) - .toString())) + UUID.nameUUIDFromBytes(("dsr node rule group " + count).getBytes(Charset.forName("UTF-8"))) + .toString())) .setRule(ruleList) .setNodeEdgePoint(nepList) .build(); @@ -537,7 +535,7 @@ public class ConvertORTopoToTapiTopo { } private OwnedNodeEdgePoint createNep(TerminationPoint oorTp, Map nepNames, - LayerProtocolName nepProtocol, LayerProtocolName nodeProtocol, boolean withSip, String keyword) { + LayerProtocolName nepProtocol, LayerProtocolName nodeProtocol, boolean withSip, String keyword) { String key = String.join("+", keyword, oorTp.getTpId().getValue()); OwnedNodeEdgePointBuilder onepBldr = new OwnedNodeEdgePointBuilder() .setUuid(this.uuidMap.get(key)) @@ -550,9 +548,9 @@ public class ConvertORTopoToTapiTopo { .setLinkPortDirection(PortDirection.BIDIRECTIONAL) .setLinkPortRole(PortRole.SYMMETRIC) .setAdministrativeState(setTapiAdminState( - oorTp.augmentation(TerminationPoint1.class).getAdministrativeState())) + oorTp.augmentation(TerminationPoint1.class).getAdministrativeState())) .setOperationalState(setTapiOperationalState( - oorTp.augmentation(TerminationPoint1.class).getOperationalState())) + oorTp.augmentation(TerminationPoint1.class).getOperationalState())) .setLifecycleState(LifecycleState.INSTALLED) .setTerminationDirection(TerminationDirection.BIDIRECTIONAL) .setTerminationState(TerminationState.TERMINATEDBIDIRECTIONAL); @@ -584,7 +582,7 @@ public class ConvertORTopoToTapiTopo { } private Map createNodeRuleGroupForRdmNode(Uuid nodeUuid, - Collection onepl) { + Collection onepl) { Map nepMap = new HashMap<>(); @@ -629,12 +627,12 @@ public class ConvertORTopoToTapiTopo { } private List> createSupportedCepLayerProtocolQualifier(TerminationPoint tp, - LayerProtocolName lpn) { + LayerProtocolName lpn) { Set> sclpqSet = new HashSet<>(); List sicList = new ArrayList<>( tp.augmentation(org.opendaylight.yang.gen.v1.http - .org.openroadm.otn.network.topology.rev200529.TerminationPoint1.class).getTpSupportedInterfaces() - .getSupportedInterfaceCapability().values()); + .org.openroadm.otn.network.topology.rev200529.TerminationPoint1.class).getTpSupportedInterfaces() + .getSupportedInterfaceCapability().values()); for (SupportedInterfaceCapability sic : sicList) { switch (lpn.getName()) { case "DSR": @@ -668,7 +666,7 @@ public class ConvertORTopoToTapiTopo { break; case "PHOTONIC_MEDIA": if (sic.getIfCapType().getSimpleName().equals("IfOCHOTU4ODU4") - || sic.getIfCapType().getSimpleName().equals("IfOCH")) { + || sic.getIfCapType().getSimpleName().equals("IfOCH")) { sclpqSet.add(PHOTONICLAYERQUALIFIEROTSi.class); sclpqSet.add(PHOTONICLAYERQUALIFIEROMS.class); } @@ -705,9 +703,9 @@ public class ConvertORTopoToTapiTopo { .build(); Link transiLink = new LinkBuilder() .setUuid(new Uuid( - UUID.nameUUIDFromBytes((String.join("--", this.ietfNodeId, sourceKey, destKey)) - .getBytes(Charset.forName("UTF-8"))) - .toString())) + UUID.nameUUIDFromBytes((String.join("--", this.ietfNodeId, sourceKey, destKey)) + .getBytes(Charset.forName("UTF-8"))) + .toString())) .setName(Map.of(linkName.key(), linkName)) .setTransitionedLayerProtocolName(Arrays.asList(LayerProtocolName.ODU.getName(), LayerProtocolName.PHOTONICMEDIA.getName())) @@ -720,10 +718,10 @@ public class ConvertORTopoToTapiTopo { } } - private Link createTapiLink(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226 - .networks.network.Link link, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link - oppositeLink) { + private Link createTapiLink(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang + .ietf.network.topology.rev180226.networks.network.Link link, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang + .ietf.network.topology.rev180226.networks.network.Link oppositeLink) { String prefix = link.getLinkId().getValue().split("-")[0]; String sourceNode = link.getSource().getSourceNode().getValue(); String sourceTp = link.getSource().getSourceTp().toString(); @@ -810,9 +808,8 @@ public class ConvertORTopoToTapiTopo { .setValue(link.getLinkId().getValue()) .build(); return new LinkBuilder() - .setUuid(new Uuid( - UUID.nameUUIDFromBytes((link.getLinkId().getValue()) - .getBytes(Charset.forName("UTF-8"))) + .setUuid(new Uuid(UUID.nameUUIDFromBytes((link.getLinkId().getValue()) + .getBytes(Charset.forName("UTF-8"))) .toString())) .setName(Map.of(linkName.key(), linkName)) .setLayerProtocolName(Arrays.asList(LayerProtocolName.ODU)) @@ -866,9 +863,9 @@ public class ConvertORTopoToTapiTopo { .build(); Link omsLink = new LinkBuilder() .setUuid(new Uuid( - UUID.nameUUIDFromBytes((String.join(" and ", photonicEntry.getValue(), rdmEntry.getValue())) - .getBytes(Charset.forName("UTF-8"))) - .toString())) + UUID.nameUUIDFromBytes((String.join(" and ", photonicEntry.getValue(), rdmEntry.getValue())) + .getBytes(Charset.forName("UTF-8"))) + .toString())) .setName(Map.of(linkName.key(), linkName)) .setLayerProtocolName(List.of(LayerProtocolName.PHOTONICMEDIA)) .setNodeEdgePoint(nepMap) @@ -879,7 +876,7 @@ public class ConvertORTopoToTapiTopo { } public Map - getTapiNodes() { + getTapiNodes() { return tapiNodes; } 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 1fc8c5c50..8de4e6faf 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 @@ -182,19 +182,19 @@ public class TapiContext { // 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.connectivity.rev181210.context.ConnectivityContext - connectivityContext = new ConnectivityContextBuilder() - .setConnectivityService(connServMap) - .setConnection(connectionFullMap) - .build(); + connectivityContext = new ConnectivityContextBuilder() + .setConnectivityService(connServMap) + .setConnection(connectionFullMap) + .build(); InstanceIdentifier connectivitycontextIID = + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext> connectivitycontextIID = InstanceIdentifier.builder(Context.class).augmentation(Context1.class) - .child(org.opendaylight.yang.gen.v1.urn - .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) - .build(); + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .build(); // merge in datastore this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connectivitycontextIID, - connectivityContext); + connectivityContext); this.networkTransactionService.commit().get(); LOG.info("TAPI connectivity merged successfully."); } catch (InterruptedException | ExecutionException e) { @@ -354,4 +354,147 @@ public class TapiContext { return null; } } + + public ConnectivityService getConnectivityService(Uuid serviceUuid) { + try { + // First read connectivity service with service uuid and update info + InstanceIdentifier connectivityServIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(ConnectivityService.class, new ConnectivityServiceKey(serviceUuid)) + .build(); + + Optional optConnServ = + this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityServIID).get(); + if (!optConnServ.isPresent()) { + LOG.error("Connectivity service not found in tapi context"); + return null; + } + return optConnServ.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Connectivity service not found in tapi context. Error:", e); + return null; + } + } + + public void deleteConnectivityService(Uuid serviceUuid) { + ConnectivityService connectivityService = getConnectivityService(serviceUuid); + if (connectivityService == null) { + LOG.error("Service doesnt exist in tapi context"); + return; + } + for (org.opendaylight.yang.gen.v1 + .urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.Connection connection: + connectivityService.getConnection().values()) { + deleteConnection(connection.getConnectionUuid()); + } + InstanceIdentifier connectivityServIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(ConnectivityService.class, new ConnectivityServiceKey(serviceUuid)) + .build(); + try { + this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectivityServIID); + this.networkTransactionService.commit().get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to delete Connectivity service", e); + } + } + + private void deleteConnection(Uuid connectionUuid) { + // First read connectivity service with service uuid and update info + InstanceIdentifier connectionIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection.class, + new org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey( + connectionUuid)) + .build(); + try { + this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectionIID); + this.networkTransactionService.commit().get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to delete TAPI Connection", e); + } + } + + public Connection getConnection(Uuid connectionUuid) { + try { + // First read connectivity service with service uuid and update info + InstanceIdentifier connIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .child(Connection.class, new ConnectionKey(connectionUuid)) + .build(); + + Optional optConn = + this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connIID).get(); + if (!optConn.isPresent()) { + LOG.error("Connection not found in tapi context"); + return null; + } + return optConn.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Connection not found in tapi context. Error:", e); + return null; + } + } + + public Map getConnectivityServices() { + try { + // First read connectivity service with service uuid and update info + InstanceIdentifier connectivityContextIID = + InstanceIdentifier.builder(Context.class).augmentation(Context1.class) + .child(org.opendaylight.yang.gen.v1.urn + .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class) + .build(); + + Optional optConnContext = + this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityContextIID) + .get(); + if (!optConnContext.isPresent()) { + LOG.error("Connectivity context not found in tapi context"); + return null; + } + return optConnContext.get().getConnectivityService(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Connectivity context not found in tapi context. Error:", e); + return null; + } + } + + public ConnectionEndPoint getTapiCEP(Uuid topoUuid, Uuid nodeUuid, Uuid nepUuid, Uuid cepUuid) { + 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; + } + if (optNode.get().augmentation(OwnedNodeEdgePoint1.class) == null) { + LOG.error("Node doesnt have ceps"); + return null; + } + return optNode.get().augmentation(OwnedNodeEdgePoint1.class).getCepList().getConnectionEndPoint() + .get(new ConnectionEndPointKey(cepUuid)); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Couldnt read node in topology"); + return null; + } + } } diff --git a/tapi/src/main/resources/OSGI-INF/blueprint/tapi-blueprint.xml b/tapi/src/main/resources/OSGI-INF/blueprint/tapi-blueprint.xml index 70bbc9186..10fe76ca8 100644 --- a/tapi/src/main/resources/OSGI-INF/blueprint/tapi-blueprint.xml +++ b/tapi/src/main/resources/OSGI-INF/blueprint/tapi-blueprint.xml @@ -19,6 +19,9 @@ Author: Gilles Thouenon + + @@ -35,6 +38,18 @@ Author: Gilles Thouenon class="org.opendaylight.transportpce.tapi.utils.TapiListener"> + + + + + + + + + + + + @@ -60,6 +75,10 @@ Author: Gilles Thouenon + + + +