Merge "Update project version for Chlorine release train"
authorGuillaume Lambert <guillaume.lambert@orange.com>
Thu, 30 Jun 2022 12:25:12 +0000 (12:25 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 30 Jun 2022 12:25:12 +0000 (12:25 +0000)
16 files changed:
docs/conf.yaml
lighty/src/main/java/io/lighty/controllers/tpce/module/TransportPCEImpl.java
networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/PortMappingListener.java
networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmTopology.java
networkmodel/src/test/java/org/opendaylight/transportpce/networkmodel/listeners/PortMappingListenerTest.java [new file with mode: 0644]
servicehandler/src/main/java/org/opendaylight/transportpce/servicehandler/ModelMappingUtils.java
servicehandler/src/main/java/org/opendaylight/transportpce/servicehandler/ServiceInput.java
servicehandler/src/main/java/org/opendaylight/transportpce/servicehandler/listeners/NetworkModelListenerImpl.java
servicehandler/src/main/java/org/opendaylight/transportpce/servicehandler/listeners/ServiceListener.java
servicehandler/src/main/java/org/opendaylight/transportpce/servicehandler/validation/ServiceCreateValidation.java
servicehandler/src/main/java/org/opendaylight/transportpce/servicehandler/validation/checks/ServicehandlerServiceResiliencyCheck.java [new file with mode: 0644]
servicehandler/src/main/resources/OSGI-INF/blueprint/servicehandler-blueprint.xml
servicehandler/src/test/java/org/opendaylight/transportpce/servicehandler/listeners/NetworkModelListenerImplTest.java [new file with mode: 0644]
servicehandler/src/test/java/org/opendaylight/transportpce/servicehandler/listeners/ServiceListenerTest.java
servicehandler/src/test/java/org/opendaylight/transportpce/servicehandler/validation/checks/CheckCoherencyServiceResiliencyTest.java [new file with mode: 0644]
tests/transportpce_tests/hybrid/test01_device_change_notifications.py

index 26f40bc9d41b77e55258b17364905753ad81b05c..dbe9639d25e4e1a22874cd8b159cd7c759fe4608 100644 (file)
@@ -1,3 +1,3 @@
 project_cfg: opendaylight
 project: Transport PCE
-version: Phosphorus
+version: Sulfur
index 37a766d4facab32349ebf0eb6eefaac2fdcf5f02..fb3a8f828100277b2932919a53d8751062bbe377 100644 (file)
@@ -198,13 +198,13 @@ public class TransportPCEImpl extends AbstractLightyModule implements TransportP
             lightyServices.getBindingNotificationPublishService(), networkModelService);
         PceListenerImpl pceListenerImpl = new PceListenerImpl(rendererServiceOperations, pathComputationService,
             lightyServices.getBindingNotificationPublishService(), serviceDataStoreOperations);
-        ServiceListener serviceListener = new ServiceListener(lightyServices.getBindingDataBroker(),
-                lightyServices.getBindingNotificationPublishService());
         NetworkModelListenerImpl networkModelListenerImpl = new NetworkModelListenerImpl(
                 lightyServices.getBindingNotificationPublishService(), serviceDataStoreOperations);
         ServicehandlerImpl servicehandler = new ServicehandlerImpl(lightyServices.getBindingDataBroker(),
             pathComputationService, rendererServiceOperations, lightyServices.getBindingNotificationPublishService(),
             pceListenerImpl, rendererListenerImpl, networkModelListenerImpl, serviceDataStoreOperations);
+        ServiceListener serviceListener = new ServiceListener(servicehandler, serviceDataStoreOperations,
+                lightyServices.getBindingNotificationPublishService());
         servicehandlerProvider = new ServicehandlerProvider(lightyServices.getBindingDataBroker(),
                 lightyServices.getRpcProviderService(), lightyServices.getNotificationService(),
                 serviceDataStoreOperations, pceListenerImpl, serviceListener, rendererListenerImpl,
index c862755bf177f98fa70fe79660e9d8d1dbec72f0..6ae864547dcf70a3a6f60148903f30072d374396 100644 (file)
@@ -11,6 +11,7 @@ import java.util.Collection;
 import java.util.LinkedList;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
+import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
 import org.opendaylight.mdsal.binding.api.DataTreeModification;
 import org.opendaylight.transportpce.networkmodel.service.NetworkModelService;
 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220316.mapping.Mapping;
@@ -33,20 +34,22 @@ public class PortMappingListener implements DataTreeChangeListener<Mapping> {
                 Mapping oldMapping = change.getRootNode().getDataBefore();
                 Mapping newMapping = change.getRootNode().getDataAfter();
                 if (oldMapping.getPortAdminState().equals(newMapping.getPortAdminState())
-                    || oldMapping.getPortOperState().equals(newMapping.getPortOperState())) {
+                        && oldMapping.getPortOperState().equals(newMapping.getPortOperState())) {
                     return;
                 } else {
-                    LinkedList<PathArgument> path = new LinkedList<>();
-                    path.addAll((Collection<? extends PathArgument>) change.getRootPath().getRootIdentifier()
-                        .getPathArguments());
-                    path.removeLast();
-                    InstanceIdentifier<Nodes> portmappintNodeID = InstanceIdentifier.unsafeOf(path);
-                    //                    @SuppressWarnings("unchecked") InstanceIdentifier<Nodes> portmappintNodeID =
-//                        (InstanceIdentifier<Nodes>) InstanceIdentifier.create(path);
-                    String nodeId = InstanceIdentifier.keyOf(portmappintNodeID).getNodeId();
-                    networkModelService.updateOpenRoadmTopologies(nodeId, newMapping);
+                    networkModelService.updateOpenRoadmTopologies(
+                            getNodeIdFromMappingDataTreeIdentifier(change.getRootPath()), newMapping);
                 }
             }
         }
     }
+
+    protected String getNodeIdFromMappingDataTreeIdentifier(DataTreeIdentifier<Mapping> dataTreeIdentifier) {
+        LinkedList<PathArgument> path = new LinkedList<>((Collection<? extends PathArgument>)
+                dataTreeIdentifier.getRootIdentifier().getPathArguments());
+        path.removeLast();
+        InstanceIdentifier<Nodes> portMappingNodeID = InstanceIdentifier.unsafeOf(path);
+        return InstanceIdentifier.keyOf(portMappingNodeID).getNodeId();
+
+    }
 }
index a101315121a1abba0baf215d6b757ebf35197b88..55aa8a869c9565aaa952cbef9d5aa6b2b3a9351a 100644 (file)
@@ -87,13 +87,13 @@ public final class OpenRoadmTopology {
 
         // Check if node is ROADM
         if (NodeTypes.Rdm.getIntValue() == mappingNode.getNodeInfo().getNodeType().getIntValue()) {
-            LOG.info("creating rdm node in openroadmtopology for node {}", mappingNode.getNodeId());
+            LOG.info("creating rdm node in openroadmtopology for node {}",
+                    mappingNode.getNodeId());
             // transform flat mapping list to per degree and per srg mapping lists
             Map<String, List<Mapping>> mapDeg = new HashMap<>();
             Map<String, List<Mapping>> mapSrg = new HashMap<>();
             List<Mapping> mappingList = new ArrayList<>(mappingNode.nonnullMapping().values());
             mappingList.sort(Comparator.comparing(Mapping::getLogicalConnectionPoint));
-
             List<String> nodeShardList = new ArrayList<>();
             for (Mapping mapping : mappingList) {
                 String str = mapping.getLogicalConnectionPoint().split("-")[0];
@@ -102,26 +102,30 @@ public final class OpenRoadmTopology {
                 }
             }
             for (String str : nodeShardList) {
-                List<Mapping> interList = mappingList.stream().filter(x -> x.getLogicalConnectionPoint()
-                    .split("-")[0].equals(str)).collect(Collectors.toList());
+                List<Mapping> interList =
+                        mappingList.stream()
+                                .filter(x -> x.getLogicalConnectionPoint().split("-")[0].equals(str))
+                                .collect(Collectors.toList());
                 if (str.contains("DEG")) {
                     mapDeg.put(str, interList);
                 } else if (str.contains("SRG")) {
-                    mapSrg.put(str,  interList);
+                    mapSrg.put(str, interList);
                 } else {
-                    LOG.error("unknown element");
+                    LOG.error("unknow element");
                 }
             }
             // create degree nodes
             for (Map.Entry<String, List<Mapping>> entry : mapDeg.entrySet()) {
-                NodeBuilder ietfNode = createDegree(entry.getKey(), entry.getValue(), mappingNode.getNodeId(),
-                    mappingNode.getNodeInfo().getNodeClli(), firstMount);
+                NodeBuilder ietfNode =
+                        createDegree(entry.getKey(), entry.getValue(), mappingNode.getNodeId(),
+                                mappingNode.getNodeInfo().getNodeClli(), firstMount);
                 nodes.add(ietfNode.build());
             }
             // create srg nodes
             for (Map.Entry<String, List<Mapping>> entry : mapSrg.entrySet()) {
-                NodeBuilder ietfNode = createSrg(entry.getKey(), entry.getValue(), mappingNode.getNodeId(),
-                    mappingNode.getNodeInfo().getNodeClli(), firstMount);
+                NodeBuilder ietfNode =
+                        createSrg(entry.getKey(), entry.getValue(), mappingNode.getNodeId(),
+                                mappingNode.getNodeInfo().getNodeClli(), firstMount);
                 nodes.add(ietfNode.build());
             }
 
@@ -134,31 +138,33 @@ public final class OpenRoadmTopology {
             return new TopologyShard(nodes, links);
         } else if (NodeTypes.Xpdr.getIntValue() ==  mappingNode.getNodeInfo().getNodeType().getIntValue()) {
             // Check if node is Xpdr is a Transponder
-            List<Mapping> networkMappings = mappingNode.nonnullMapping().values()
-                    .stream().filter(k -> k.getLogicalConnectionPoint()
-                .contains("NETWORK")).collect(Collectors.toList());
+            List<Mapping> networkMappings =
+                    mappingNode.nonnullMapping().values()
+                            .stream().filter(k -> k.getLogicalConnectionPoint().contains("NETWORK"))
+                            .collect(Collectors.toList());
             List<Integer> tpdrList = new ArrayList<>();
             for (Mapping mapping : networkMappings) {
                 List<Mapping> extractedMappings = null;
                 Integer xpdrNb = Integer.parseInt(mapping.getLogicalConnectionPoint().split("XPDR")[1].split("-")[0]);
                 if (!tpdrList.contains(xpdrNb)) {
                     tpdrList.add(xpdrNb);
-                    extractedMappings = mappingNode.nonnullMapping().values().stream().filter(lcp -> lcp
-                        .getLogicalConnectionPoint().contains("XPDR" + xpdrNb)).collect(Collectors.toList());
+                    extractedMappings = mappingNode.nonnullMapping().values().stream()
+                            .filter(lcp -> lcp.getLogicalConnectionPoint().contains("XPDR" + xpdrNb))
+                            .collect(Collectors.toList());
                     NodeBuilder ietfNode;
                     if (mapping.getXponderType() == null
-                        || XpdrNodeTypes.Tpdr.getIntValue() == mapping.getXponderType().getIntValue()) {
+                            || XpdrNodeTypes.Tpdr.getIntValue() == mapping.getXponderType().getIntValue()) {
                         LOG.info("creating xpdr node {} of type Tpdr in openroadm-topology",
-                            mappingNode.getNodeId() + "-XPDR" + xpdrNb);
+                                mappingNode.getNodeId() + "-XPDR" + xpdrNb);
                         ietfNode = createXpdr(mappingNode.getNodeId(), mappingNode.getNodeInfo().getNodeClli(), xpdrNb,
-                            extractedMappings, false);
+                                extractedMappings, false);
                         nodes.add(ietfNode.build());
                     } else if (XpdrNodeTypes.Mpdr.getIntValue() == mapping.getXponderType().getIntValue()
-                        || XpdrNodeTypes.Switch.getIntValue() == mapping.getXponderType().getIntValue()) {
+                            || XpdrNodeTypes.Switch.getIntValue() == mapping.getXponderType().getIntValue()) {
                         LOG.info("creating xpdr node {} of type {} in openroadm-topology",
-                            mappingNode.getNodeId() + "-XPDR" + xpdrNb, mapping.getXponderType().getName());
+                                mappingNode.getNodeId() + "-XPDR" + xpdrNb, mapping.getXponderType().getName());
                         ietfNode = createXpdr(mappingNode.getNodeId(), mappingNode.getNodeInfo().getNodeClli(), xpdrNb,
-                            extractedMappings, true);
+                                extractedMappings, true);
                         nodes.add(ietfNode.build());
                     }
                 }
@@ -174,21 +180,21 @@ public final class OpenRoadmTopology {
     }
 
     private static NodeBuilder createXpdr(String nodeId, String clli, Integer xpdrNb, List<Mapping> mappings,
-        boolean isOtn) {
+                                          boolean isOtn) {
         // Create openroadm-network-topo augmentation to set node type to Xponder
         org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1 ocnNode1 =
-            new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1Builder()
-                    .setNodeType(OpenroadmNodeType.XPONDER)
-                    .setAdministrativeState(AdminStates.InService)
-                    .setOperationalState(State.InService)
-                    .build();
+                new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1Builder()
+                        .setNodeType(OpenroadmNodeType.XPONDER)
+                        .setAdministrativeState(AdminStates.InService)
+                        .setOperationalState(State.InService)
+                        .build();
         // Create ietf node setting supporting-node data
         NodeBuilder ietfNodeBldr = createTopoLayerNode(nodeId, clli);
         // set node-id
         String nodeIdtopo = new StringBuilder().append(nodeId).append("-XPDR").append(xpdrNb).toString();
         ietfNodeBldr.setNodeId(new NodeId(nodeIdtopo))
-            .withKey((new NodeKey(new NodeId(nodeIdtopo))))
-            .addAugmentation(ocnNode1);
+                .withKey((new NodeKey(new NodeId(nodeIdtopo))))
+                .addAugmentation(ocnNode1);
 
         // Create tp-map
         Map<TerminationPointKey, TerminationPoint> tpMap = new HashMap<>();
@@ -198,28 +204,31 @@ public final class OpenRoadmTopology {
                 ietfTpBldr = createTpBldr(m.getLogicalConnectionPoint());
                 // Add openroadm-network-topology tp augmentations
                 org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.TerminationPoint1Builder
-                    ocnTp1Bldr = new org.opendaylight.yang.gen.v1.http
-                        .org.openroadm.common.network.rev211210.TerminationPoint1Builder()
-                        .setAdministrativeState(TopologyUtils.setNetworkAdminState(m.getPortAdminState()))
-                        .setOperationalState(TopologyUtils.setNetworkOperState(m.getPortOperState()));
+                        ocnTp1Bldr = new org.opendaylight.yang.gen.v1.http
+                            .org.openroadm.common.network.rev211210.TerminationPoint1Builder()
+                                .setAdministrativeState(TopologyUtils.setNetworkAdminState(m.getPortAdminState()))
+                                .setOperationalState(TopologyUtils.setNetworkOperState(m.getPortOperState()));
                 if (m.getPortQual().equals("xpdr-network")) {
                     ocnTp1Bldr.setTpType(OpenroadmTpType.XPONDERNETWORK);
                     org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.TerminationPoint1 tpceTp1 =
-                        new org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.TerminationPoint1Builder()
-                            .setAssociatedConnectionMapPort(m.getConnectionMapLcp()).build();
+                            new org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123
+                                    .TerminationPoint1Builder()
+                                    .setAssociatedConnectionMapPort(m.getConnectionMapLcp()).build();
                     ietfTpBldr
-                        .addAugmentation(ocnTp1Bldr.build())
-                        .addAugmentation(tpceTp1);
+                            .addAugmentation(ocnTp1Bldr.build())
+                            .addAugmentation(tpceTp1);
                     TerminationPoint ietfTp = ietfTpBldr.build();
                     tpMap.put(ietfTp.key(),ietfTp);
                 } else if (m.getPortQual().equals("xpdr-client")) {
                     ocnTp1Bldr.setTpType(OpenroadmTpType.XPONDERCLIENT);
                     org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.TerminationPoint1 tpceTp1 =
-                        new org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.TerminationPoint1Builder()
-                            .setAssociatedConnectionMapPort(m.getConnectionMapLcp()).build();
+                        new org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123
+                            .TerminationPoint1Builder()
+                                .setAssociatedConnectionMapPort(m.getConnectionMapLcp())
+                                .build();
                     ietfTpBldr
-                        .addAugmentation(ocnTp1Bldr.build())
-                        .addAugmentation(tpceTp1);
+                            .addAugmentation(ocnTp1Bldr.build())
+                            .addAugmentation(tpceTp1);
                     TerminationPoint ietfTp = ietfTpBldr.build();
                     tpMap.put(ietfTp.key(),ietfTp);
                 }
@@ -228,12 +237,12 @@ public final class OpenRoadmTopology {
                     ietfTpBldr = createTpBldr(m.getLogicalConnectionPoint());
                     org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.TerminationPoint1Builder
                         ocnTp1Bldr = new org.opendaylight.yang.gen.v1.http
-                                .org.openroadm.common.network.rev211210.TerminationPoint1Builder()
-                            .setTpType(OpenroadmTpType.XPONDERNETWORK)
-                            .setAdministrativeState(TopologyUtils.setNetworkAdminState(m.getPortAdminState()))
-                            .setOperationalState(TopologyUtils.setNetworkOperState(m.getPortOperState()));
+                            .org.openroadm.common.network.rev211210.TerminationPoint1Builder()
+                                    .setTpType(OpenroadmTpType.XPONDERNETWORK)
+                                    .setAdministrativeState(TopologyUtils.setNetworkAdminState(m.getPortAdminState()))
+                                    .setOperationalState(TopologyUtils.setNetworkOperState(m.getPortOperState()));
                     ietfTpBldr
-                        .addAugmentation(ocnTp1Bldr.build());
+                            .addAugmentation(ocnTp1Bldr.build());
                     TerminationPoint ietfTp = ietfTpBldr.build();
                     tpMap.put(ietfTp.key(),ietfTp);
                 }
@@ -242,7 +251,8 @@ public final class OpenRoadmTopology {
         // Create ietf node augmentation to support ietf tp-list
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1Builder
             ietfNode1 = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
-                .Node1Builder().setTerminationPoint(tpMap);
+                .Node1Builder()
+                    .setTerminationPoint(tpMap);
         ietfNodeBldr.addAugmentation(ietfNode1.build());
         return ietfNodeBldr;
     }
@@ -283,16 +293,16 @@ public final class OpenRoadmTopology {
         ietfTpBldr = createTpBldr(degNb + "-CTP-TXRX");
         org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.TerminationPoint1 ocnTp1 =
             new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.TerminationPoint1Builder()
-            .setTpType(OpenroadmTpType.DEGREETXRXCTP)
-                    .setAdministrativeState(AdminStates.InService)
-                    .setOperationalState(State.InService)
-                    .build();
+                .setTpType(OpenroadmTpType.DEGREETXRXCTP)
+                .setAdministrativeState(AdminStates.InService)
+                .setOperationalState(State.InService)
+                .build();
         ietfTpBldr.addAugmentation(ocnTp1);
         TerminationPoint ietfTp = ietfTpBldr.build();
         tpMap.put(ietfTp.key(),ietfTp);
         // set degree-attributes
         DegreeAttributesBuilder degAttBldr = new DegreeAttributesBuilder()
-            .setDegreeNumber(Uint16.valueOf(degNb.split("DEG")[1]));
+                .setDegreeNumber(Uint16.valueOf(degNb.split("DEG")[1]));
         if (firstMount) {
             degAttBldr.setAvailFreqMaps(GridUtils.initFreqMaps4FixedGrid2Available());
         }
@@ -307,17 +317,17 @@ public final class OpenRoadmTopology {
         // Create openroadm-common-network augmentation to set node type to DEGREE
         org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1 ocnNode1 =
             new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1Builder()
-            .setNodeType(OpenroadmNodeType.DEGREE)
-                    .setAdministrativeState(AdminStates.InService)
-                    .setOperationalState(State.InService)
-                    .build();
+                .setNodeType(OpenroadmNodeType.DEGREE)
+                .setAdministrativeState(AdminStates.InService)
+                .setOperationalState(State.InService)
+                .build();
         // Create ietf node setting supporting-node data
         return createTopoLayerNode(nodeId, clli)
-            .setNodeId(new NodeId(nodeIdtopo))
-            .withKey((new NodeKey(new NodeId(nodeIdtopo))))
-            .addAugmentation(ontNode1)
-            .addAugmentation(ocnNode1)
-            .addAugmentation(ietfNode1.build());
+                .setNodeId(new NodeId(nodeIdtopo))
+                .withKey((new NodeKey(new NodeId(nodeIdtopo))))
+                .addAugmentation(ontNode1)
+                .addAugmentation(ocnNode1)
+                .addAugmentation(ietfNode1.build());
     }
 
     private static NodeBuilder createSrg(String srgNb, List<Mapping> srgListMap, String nodeId, String clli,
@@ -330,9 +340,9 @@ public final class OpenRoadmTopology {
             // Add openroadm-common-network tp type augmentations
             org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210
                 .TerminationPoint1Builder ocnTp1Bldr = new org.opendaylight.yang.gen.v1.http
-                .org.openroadm.common.network.rev211210.TerminationPoint1Builder()
-                    .setAdministrativeState(TopologyUtils.setNetworkAdminState(m.getPortAdminState()))
-                    .setOperationalState(TopologyUtils.setNetworkOperState(m.getPortOperState()));
+                    .org.openroadm.common.network.rev211210.TerminationPoint1Builder()
+                        .setAdministrativeState(TopologyUtils.setNetworkAdminState(m.getPortAdminState()))
+                        .setOperationalState(TopologyUtils.setNetworkOperState(m.getPortOperState()));
             // Added states to srg port. TODO: add to mapping relation between abstracted and physical node states
             switch (m.getPortDirection()) {
                 case "bidirectional":
@@ -355,21 +365,21 @@ public final class OpenRoadmTopology {
         ietfTpBldr = createTpBldr(srgNb + "-CP-TXRX");
         org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210
             .TerminationPoint1 ocnTp1 = new org.opendaylight.yang.gen.v1
-            .http.org.openroadm.common.network.rev211210.TerminationPoint1Builder()
-                .setTpType(OpenroadmTpType.SRGTXRXCP)
-                .setAdministrativeState(AdminStates.InService)
-                .setOperationalState(State.InService)
-                .build();
+                .http.org.openroadm.common.network.rev211210.TerminationPoint1Builder()
+                    .setTpType(OpenroadmTpType.SRGTXRXCP)
+                    .setAdministrativeState(AdminStates.InService)
+                    .setOperationalState(State.InService)
+                    .build();
         ietfTpBldr.addAugmentation(ocnTp1);
         TerminationPoint ietfTp = ietfTpBldr.build();
         tpMap.put(ietfTp.key(),ietfTp);
         // Create openroadm-common-network augmentation to set node type to SRG
         org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1 ocnNode1 =
             new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1Builder()
-                    .setNodeType(OpenroadmNodeType.SRG)
-                    .setAdministrativeState(AdminStates.InService)
-                    .setOperationalState(State.InService)
-                    .build();
+                .setNodeType(OpenroadmNodeType.SRG)
+                .setAdministrativeState(AdminStates.InService)
+                .setOperationalState(State.InService)
+                .build();
         // set srg-attributes
         SrgAttributesBuilder srgAttrBldr = new SrgAttributesBuilder();
         if (firstMount) {
@@ -384,24 +394,24 @@ public final class OpenRoadmTopology {
         // Create ietf node setting supporting-node data
         String nodeIdtopo = new StringBuilder().append(nodeId).append("-").append(srgNb).toString();
         return createTopoLayerNode(nodeId, clli)
-            .setNodeId(new NodeId(nodeIdtopo))
-            .withKey((new NodeKey(new NodeId(nodeIdtopo))))
-            .addAugmentation(ontNode1)
-            .addAugmentation(ocnNode1)
-            .addAugmentation(ietfNode1.build());
+                .setNodeId(new NodeId(nodeIdtopo))
+                .withKey((new NodeKey(new NodeId(nodeIdtopo))))
+                .addAugmentation(ontNode1)
+                .addAugmentation(ocnNode1)
+                .addAugmentation(ietfNode1.build());
     }
 
     private static NodeBuilder createTopoLayerNode(String nodeId, String clli) {
         // Sets the value of Network-ref and Node-ref as a part of the supporting node
         // attribute
         SupportingNodeBuilder support1bldr = new SupportingNodeBuilder()
-            .withKey(new SupportingNodeKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID), new NodeId(nodeId)))
-            .setNetworkRef(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))
-            .setNodeRef(new NodeId(nodeId));
+                .withKey(new SupportingNodeKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID), new NodeId(nodeId)))
+                .setNetworkRef(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))
+                .setNodeRef(new NodeId(nodeId));
         SupportingNodeBuilder support2bldr = new SupportingNodeBuilder()
-            .withKey(new SupportingNodeKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID), new NodeId(clli)))
-            .setNetworkRef(new NetworkId(NetworkUtils.CLLI_NETWORK_ID))
-            .setNodeRef(new NodeId(clli));
+                .withKey(new SupportingNodeKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID), new NodeId(clli)))
+                .setNetworkRef(new NetworkId(NetworkUtils.CLLI_NETWORK_ID))
+                .setNodeRef(new NodeId(clli));
         Map<SupportingNodeKey, SupportingNode> supportlist = new HashMap<>();
         SupportingNode support1 = support1bldr.build();
         supportlist.put(support1.key(),support1);
@@ -419,17 +429,19 @@ public final class OpenRoadmTopology {
 
     private static LinkBuilder createLink(String srcNode, String destNode, String srcTp, String destTp) {
         //create source link
-        SourceBuilder ietfSrcLinkBldr = new SourceBuilder().setSourceNode(new NodeId(srcNode))
+        SourceBuilder ietfSrcLinkBldr = new SourceBuilder()
+            .setSourceNode(new NodeId(srcNode))
             .setSourceTp(new TpId(srcTp));
         //create destination link
-        DestinationBuilder ietfDestLinkBldr = new DestinationBuilder().setDestNode(new NodeId(destNode))
-            .setDestTp(new TpId(destTp));
+        DestinationBuilder ietfDestLinkBldr = new DestinationBuilder()
+                .setDestNode(new NodeId(destNode))
+                .setDestTp(new TpId(destTp));
         LinkId linkId = LinkIdUtil.buildLinkId(srcNode, srcTp, destNode, destTp);
         return new LinkBuilder()
-            .setSource(ietfSrcLinkBldr.build())
-            .setDestination(ietfDestLinkBldr.build())
-            .setLinkId(linkId)
-            .withKey(new LinkKey(linkId));
+                .setSource(ietfSrcLinkBldr.build())
+                .setDestination(ietfDestLinkBldr.build())
+                .setLinkId(linkId)
+                .withKey(new LinkKey(linkId));
     }
 
     private static List<Link> createNewLinks(List<Node> nodes) {
@@ -444,16 +456,17 @@ public final class OpenRoadmTopology {
                 destNode = nodes.get(j).getNodeId().getValue();
                 // A to Z direction
                 srcTp = nodes.get(i)
-                    .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
-                            .ietf.network.topology.rev180226.Node1.class).nonnullTerminationPoint().values().stream()
-                    .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
-                    .findFirst().get().getTpId().getValue();
+                        .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
+                                .ietf.network.topology.rev180226.Node1.class)
+                        .nonnullTerminationPoint().values().stream()
+                        .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
+                        .findFirst().get().getTpId().getValue();
                 destTp = nodes.get(j)
-                    .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
-                            .ietf.network.topology.rev180226.Node1.class)
-                    .nonnullTerminationPoint().values().stream()
-                    .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
-                    .findFirst().get().getTpId().getValue();
+                        .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
+                                .ietf.network.topology.rev180226.Node1.class)
+                        .nonnullTerminationPoint().values().stream()
+                        .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
+                        .findFirst().get().getTpId().getValue();
                 Link1Builder ocnAzLinkBldr = new Link1Builder();
                 int srcNodeType = nodes.get(i).augmentation(org.opendaylight.yang.gen.v1.http
                         .org.openroadm.common.network.rev211210.Node1.class).getNodeType().getIntValue();
@@ -481,16 +494,24 @@ public final class OpenRoadmTopology {
                 }
                 // Add state to link. Based on the operational state of the TPs at the edge of the link.
                 // Similar to getting srcTp and destTp
-                State srcTpState = nodes.get(i).augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
-                        .ietf.network.topology.rev180226.Node1.class).getTerminationPoint().values().stream()
-                    .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
-                    .findFirst().get().augmentation(org.opendaylight.yang.gen.v1.http
-                            .org.openroadm.common.network.rev211210.TerminationPoint1.class).getOperationalState();
-                State destTpState = nodes.get(j).augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
-                        .ietf.network.topology.rev180226.Node1.class).getTerminationPoint().values().stream()
-                    .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
-                    .findFirst().get().augmentation(org.opendaylight.yang.gen.v1.http
-                            .org.openroadm.common.network.rev211210.TerminationPoint1.class).getOperationalState();
+                State srcTpState = nodes.get(i)
+                        .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
+                            .ietf.network.topology.rev180226.Node1.class)
+                        .getTerminationPoint().values().stream()
+                        .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
+                        .findFirst().get()
+                        .augmentation(org.opendaylight.yang.gen.v1.http
+                                .org.openroadm.common.network.rev211210.TerminationPoint1.class)
+                        .getOperationalState();
+                State destTpState = nodes.get(j)
+                        .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
+                            .ietf.network.topology.rev180226.Node1.class)
+                        .getTerminationPoint().values().stream()
+                        .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
+                        .findFirst().get()
+                        .augmentation(org.opendaylight.yang.gen.v1.http
+                                .org.openroadm.common.network.rev211210.TerminationPoint1.class)
+                        .getOperationalState();
                 if (State.InService.equals(srcTpState) && State.InService.equals(destTpState)) {
                     ocnAzLinkBldr.setAdministrativeState(AdminStates.InService)
                             .setOperationalState(State.InService);
@@ -534,8 +555,9 @@ public final class OpenRoadmTopology {
     public static boolean deleteLinkLinkId(LinkId linkId , NetworkTransactionService networkTransactionService) {
         LOG.info("deleting link for LinkId: {}", linkId.getValue());
         try {
-            InstanceIdentifierBuilder<Link> linkIID = InstanceIdentifier.builder(Networks.class).child(Network.class,
-                new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).augmentation(Network1.class)
+            InstanceIdentifierBuilder<Link> linkIID = InstanceIdentifier.builder(Networks.class)
+                .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
+                .augmentation(Network1.class)
                 .child(Link.class, new LinkKey(linkId));
             java.util.Optional<Link> link =
                     networkTransactionService.read(LogicalDatastoreType.CONFIGURATION,linkIID.build()).get();
@@ -543,17 +565,17 @@ public final class OpenRoadmTopology {
                 LinkBuilder linkBuilder = new LinkBuilder(link.get());
                 org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.Link1Builder link1Builder =
                     new org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.Link1Builder(
-                    linkBuilder.augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210
-                    .Link1.class));
+                        linkBuilder
+                            .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210
+                                .Link1.class));
                 linkBuilder.removeAugmentation(Link1.class)
-                    .addAugmentation(link1Builder.build());
+                        .addAugmentation(link1Builder.build());
                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, linkIID.build(),
                         linkBuilder.build());
                 networkTransactionService.commit().get(1, TimeUnit.SECONDS);
                 return true;
             } else {
-                LOG.error("No link found for given LinkId: {}",
-                        linkId);
+                LOG.error("No link found for given LinkId: {}", linkId);
                 return false;
             }
 
@@ -570,18 +592,19 @@ public final class OpenRoadmTopology {
      * @return InstanceIdentifierBuilder
      */
     public static InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210
-        .TerminationPoint1> createCommonNetworkTerminationPointIIDBuilder(String nodeId, String tpId) {
-        return InstanceIdentifier
-            .builder(Networks.class).child(Network.class, new NetworkKey(
-                    new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
-            .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network
-                    .Node.class, new NodeKey(new NodeId(nodeId)))
-            .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
-            .Node1.class)
-            .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
-                    .network.node.TerminationPoint.class, new TerminationPointKey(new TpId(tpId)))
-            .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210
-                .TerminationPoint1.class);
+            .TerminationPoint1> createCommonNetworkTerminationPointIIDBuilder(String nodeId, String tpId) {
+        return InstanceIdentifier.builder(Networks.class)
+                .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
+                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226
+                         .networks.network.Node.class,
+                    new NodeKey(new NodeId(nodeId)))
+                .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
+                    .Node1.class)
+                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
+                         .network.node.TerminationPoint.class,
+                    new TerminationPointKey(new TpId(tpId)))
+                .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210
+                        .TerminationPoint1.class);
     }
 
     /**
@@ -591,16 +614,17 @@ public final class OpenRoadmTopology {
      * @return InstanceIdentifierBuilder
      */
     public static InstanceIdentifierBuilder<TerminationPoint1> createNetworkTerminationPointIIDBuilder(String nodeId,
-            String tpId) {
-        return InstanceIdentifier
-                .builder(Networks.class).child(Network.class, new NetworkKey(
-                        new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
-                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network
-                        .Node.class, new NodeKey(new NodeId(nodeId)))
+                                                                                                       String tpId) {
+        return InstanceIdentifier.builder(Networks.class)
+                .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
+                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226
+                        .networks.network.Node.class,
+                    new NodeKey(new NodeId(nodeId)))
                 .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
-                .Node1.class)
-                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
-                        .network.node.TerminationPoint.class, new TerminationPointKey(new TpId(tpId)))
+                        .Node1.class)
+                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
+                        .networks.network.node.TerminationPoint.class,
+                    new TerminationPointKey(new TpId(tpId)))
                 .augmentation(TerminationPoint1.class);
     }
 
@@ -610,11 +634,12 @@ public final class OpenRoadmTopology {
      * @return InstanceIdentifier
      */
     public static InstanceIdentifier<Node1> createNetworkNodeIID(String nodeId) {
-        return InstanceIdentifier
-                .builder(Networks.class).child(Network.class, new NetworkKey(
-                        new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
-                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network
-                .Node.class, new NodeKey(new NodeId(nodeId))).augmentation(Node1.class).build();
+        return InstanceIdentifier.builder(Networks.class)
+                .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
+                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226
+                        .networks.network.Node.class,
+                     new NodeKey(new NodeId(nodeId)))
+                .augmentation(Node1.class).build();
     }
 
     /**
@@ -623,12 +648,12 @@ public final class OpenRoadmTopology {
      * @return InstanceIdentifier
      */
     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210
-        .Node1> createCommonNetworkNodeIID(String nodeId) {
-        return InstanceIdentifier
-                .builder(Networks.class).child(Network.class, new NetworkKey(
-                        new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
-                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network
-                        .Node.class, new NodeKey(new NodeId(nodeId)))
+            .Node1> createCommonNetworkNodeIID(String nodeId) {
+        return InstanceIdentifier.builder(Networks.class)
+                .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
+                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226
+                        .networks.network.Node.class,
+                    new NodeKey(new NodeId(nodeId)))
                 .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1.class)
                 .build();
     }
diff --git a/networkmodel/src/test/java/org/opendaylight/transportpce/networkmodel/listeners/PortMappingListenerTest.java b/networkmodel/src/test/java/org/opendaylight/transportpce/networkmodel/listeners/PortMappingListenerTest.java
new file mode 100644 (file)
index 0000000..32ec06a
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2022 Orange.  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.networkmodel.listeners;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collection;
+import java.util.HashSet;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.opendaylight.mdsal.binding.api.DataObjectModification;
+import org.opendaylight.mdsal.binding.api.DataTreeModification;
+import org.opendaylight.transportpce.networkmodel.service.NetworkModelService;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220316.mapping.Mapping;
+
+
+@RunWith(MockitoJUnitRunner.class)
+public class PortMappingListenerTest {
+
+    @Mock
+    private NetworkModelService networkModelService;
+    private PortMappingListener portMappingListenerSpy;
+
+    @Before
+    public void setUp() {
+        portMappingListenerSpy = Mockito.spy(new PortMappingListener(networkModelService));
+        doReturn("NodeID").when(portMappingListenerSpy).getNodeIdFromMappingDataTreeIdentifier(any());
+    }
+
+    @Test
+    public void testOnDataTreeChangedWhenMappingOperAndAdminDidntChange() {
+        final Collection<DataTreeModification<Mapping>> changes = new HashSet<>();
+        @SuppressWarnings("unchecked") final DataTreeModification<Mapping> ch = mock(DataTreeModification.class);
+        changes.add(ch);
+        @SuppressWarnings("unchecked") final DataObjectModification<Mapping> mappingObject =
+                mock(DataObjectModification.class);
+        final Mapping oldMapping = mock(Mapping.class);
+        final Mapping newMapping = mock(Mapping.class);
+
+        when(ch.getRootNode()).thenReturn(mappingObject);
+        when(mappingObject.getDataBefore()).thenReturn(oldMapping);
+        when(mappingObject.getDataAfter()).thenReturn(newMapping);
+        when(oldMapping.getPortAdminState()).thenReturn("InService");
+        when(oldMapping.getPortOperState()).thenReturn("InService");
+        when(newMapping.getPortAdminState()).thenReturn("InService");
+        when(newMapping.getPortOperState()).thenReturn("InService");
+
+        portMappingListenerSpy.onDataTreeChanged(changes);
+        verify(networkModelService, never()).updateOpenRoadmTopologies(anyString(), any(Mapping.class));
+    }
+
+    @Test
+    public void testOnDataTreeChangedWhenMappingAdminChanged() {
+        final Collection<DataTreeModification<Mapping>> changes = new HashSet<>();
+        @SuppressWarnings("unchecked") final DataTreeModification<Mapping> ch = mock(DataTreeModification.class);
+        changes.add(ch);
+        @SuppressWarnings("unchecked") final DataObjectModification<Mapping> mappingObject =
+                mock(DataObjectModification.class);
+        final Mapping oldMapping = mock(Mapping.class);
+        final Mapping newMapping = mock(Mapping.class);
+
+        when(ch.getRootNode()).thenReturn(mappingObject);
+        when(mappingObject.getDataBefore()).thenReturn(oldMapping);
+        when(mappingObject.getDataAfter()).thenReturn(newMapping);
+        when(oldMapping.getPortAdminState()).thenReturn("InService");
+        when(newMapping.getPortAdminState()).thenReturn("OutOfService");
+
+        portMappingListenerSpy.onDataTreeChanged(changes);
+        verify(networkModelService, times(1)).updateOpenRoadmTopologies(anyString(), any(Mapping.class));
+    }
+
+    @Test
+    public void testOnDataTreeChangedWhenMappingOperChanged() {
+        final Collection<DataTreeModification<Mapping>> changes = new HashSet<>();
+        @SuppressWarnings("unchecked") final DataTreeModification<Mapping> ch = mock(DataTreeModification.class);
+        changes.add(ch);
+        @SuppressWarnings("unchecked") final DataObjectModification<Mapping> mappingObject =
+                mock(DataObjectModification.class);
+        final Mapping oldMapping = mock(Mapping.class);
+        final Mapping newMapping = mock(Mapping.class);
+
+        when(ch.getRootNode()).thenReturn(mappingObject);
+        when(mappingObject.getDataBefore()).thenReturn(oldMapping);
+        when(mappingObject.getDataAfter()).thenReturn(newMapping);
+        when(oldMapping.getPortAdminState()).thenReturn("InService");
+        when(oldMapping.getPortOperState()).thenReturn("InService");
+        when(newMapping.getPortAdminState()).thenReturn("InService");
+        when(newMapping.getPortOperState()).thenReturn("OutOfService");
+
+        portMappingListenerSpy.onDataTreeChanged(changes);
+        verify(networkModelService, times(1)).updateOpenRoadmTopologies(anyString(), any(Mapping.class));
+    }
+}
index 5e19d1a831cf8816c676c293141bed1e2ff0cf78..333b66f6a2c1bcd50a2c999c5097c597d82c0d56 100644 (file)
@@ -455,6 +455,7 @@ public final class ModelMappingUtils {
                 .setConnectionType(serviceCreateInput.getConnectionType())
                 .setCustomer(serviceCreateInput.getCustomer())
                 .setCustomerContact(serviceCreateInput.getCustomerContact())
+                .setServiceResiliency(serviceCreateInput.getServiceResiliency())
                 .setHardConstraints(serviceCreateInput.getHardConstraints())
                 .setSoftConstraints(serviceCreateInput.getSoftConstraints())
                 .setSdncRequestHeader(serviceCreateInput.getSdncRequestHeader())
index 6f45e5894792ae5ec153818afb77d8decc4e82ae..a818df60cf14fe2b6f52ebb3204cf3b523c73490 100644 (file)
@@ -12,6 +12,7 @@ import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev2
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.ServiceEndpoint;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.sdnc.request.header.SdncRequestHeader;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.sdnc.request.header.SdncRequestHeaderBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.resiliency.ServiceResiliency;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev211210.routing.constraints.HardConstraints;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev211210.routing.constraints.SoftConstraints;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.ServiceCreateInput;
@@ -43,6 +44,7 @@ public class ServiceInput {
     private ServiceEndpoint serviceZEnd;
     private String customer;
     private String customerContact;
+    private ServiceResiliency serviceResiliency;
     private boolean serviceReconfigure;
 
     public ServiceInput(ServiceCreateInput serviceCreateInput) {
@@ -56,6 +58,7 @@ public class ServiceInput {
         setServiceZEnd(serviceCreateInput.getServiceZEnd());
         setCustomer(serviceCreateInput.getCustomer());
         setCustomerContact(serviceCreateInput.getCustomerContact());
+        setServiceResiliency(serviceCreateInput.getServiceResiliency());
         setServiceReconfigure(false);
     }
 
@@ -73,6 +76,7 @@ public class ServiceInput {
         setServiceZEnd(serviceReconfigureInput.getServiceZEnd());
         setCustomer(serviceReconfigureInput.getCustomer());
         setCustomerContact(serviceReconfigureInput.getCustomerContact());
+        setServiceResiliency(serviceReconfigureInput.getServiceResiliency());
         setServiceReconfigure(true);
     }
 
@@ -93,6 +97,7 @@ public class ServiceInput {
         setServiceZEnd(tempServiceCreateInput.getServiceZEnd());
         setCustomer(tempServiceCreateInput.getCustomer());
         setCustomerContact(tempServiceCreateInput.getCustomerContact());
+        setServiceResiliency(tempServiceCreateInput.getServiceResiliency());
         setServiceReconfigure(false);
     }
 
@@ -107,6 +112,7 @@ public class ServiceInput {
         setServiceZEnd(serviceFeasibilityCheckInput.getServiceZEnd());
         setCustomer(serviceFeasibilityCheckInput.getCustomer());
         setCustomerContact(serviceFeasibilityCheckInput.getCustomerContact());
+        setServiceResiliency(serviceFeasibilityCheckInput.getServiceResiliency());
         setServiceReconfigure(false);
     }
 
@@ -128,7 +134,8 @@ public class ServiceInput {
                 .setServiceAEnd(new ServiceAEndBuilder(serviceAEnd).build())
                 .setServiceZEnd(new ServiceZEndBuilder(serviceZEnd).build())
                 .setCustomer(customer)
-                .setCustomerContact(customerContact);
+                .setCustomerContact(customerContact)
+                .setServiceResiliency(serviceResiliency);
         if (isServiceReconfigure()) {
             serviceCreateInputBuilder.setServiceName(newServiceName);
         } else {
@@ -138,14 +145,20 @@ public class ServiceInput {
     }
 
     public TempServiceCreateInput getTempServiceCreateInput() {
-        return new TempServiceCreateInputBuilder().setCommonId(commonId)
-                .setConnectionType(connectionType).setSdncRequestHeader(sdncRequestHeader)
-                .setHardConstraints(hardConstraints).setSoftConstraints(softConstraints)
+        return new TempServiceCreateInputBuilder()
+                .setCommonId(commonId)
+                .setConnectionType(connectionType)
+                .setSdncRequestHeader(sdncRequestHeader)
+                .setHardConstraints(hardConstraints)
+                .setSoftConstraints(softConstraints)
                 .setServiceAEnd(new org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.temp.service
                         .create.input.ServiceAEndBuilder(serviceAEnd).build())
                 .setServiceZEnd(new org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.temp.service
-                        .create.input.ServiceZEndBuilder(serviceZEnd).build()).setCustomer(customer)
-                .setCustomerContact(customerContact).build();
+                        .create.input.ServiceZEndBuilder(serviceZEnd).build())
+                .setCustomer(customer)
+                .setCustomerContact(customerContact)
+                .setServiceResiliency(serviceResiliency)
+                .build();
     }
 
     public String getServiceName() {
@@ -236,6 +249,14 @@ public class ServiceInput {
         this.newServiceName = newServiceName;
     }
 
+    public void setServiceResiliency(ServiceResiliency serviceResiliency) {
+        this.serviceResiliency = serviceResiliency;
+    }
+
+    public ServiceResiliency getServiceResiliency() {
+        return serviceResiliency;
+    }
+
     public boolean isServiceReconfigure() {
         return serviceReconfigure;
     }
index b1a162a3bf2abc6f5bfbb764bb65fdaaeaf2b824..960a00c3fadccc1ec12cce34c5039e83818caf55 100644 (file)
@@ -18,11 +18,11 @@ import org.opendaylight.mdsal.binding.api.NotificationPublishService;
 import org.opendaylight.transportpce.common.OperationResult;
 import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.TopologyUpdateResult;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.TopologyUpdateResultBuilder;
 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.TransportpceNetworkmodelListener;
 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChanges;
 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChangesKey;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service.list.Services;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.AToZDirection;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.AToZDirectionBuilder;
@@ -59,12 +59,14 @@ public class NetworkModelListenerImpl implements TransportpceNetworkmodelListene
 
     @Override
     public void onTopologyUpdateResult(TopologyUpdateResult notification) {
-        LOG.debug("Topology update notification: {}", notification.toString());
+        LOG.debug("Topology update notification: {}", notification);
         if (compareTopologyUpdateResult(notification)) {
             LOG.warn("TopologyUpdateResult already wired !");
             return;
         }
-        topologyUpdateResult = notification;
+        topologyUpdateResult = new TopologyUpdateResultBuilder()
+                .setTopologyChanges(new HashMap<>(notification.getTopologyChanges()))
+                .build();
         // Update service datastore and service path description
         updateServicePaths(notification);
     }
@@ -73,16 +75,15 @@ public class NetworkModelListenerImpl implements TransportpceNetworkmodelListene
      * Process topology update result.
      * @param notification the result notification.
      */
-    private void updateServicePaths(TopologyUpdateResult notification) {
+    protected void updateServicePaths(TopologyUpdateResult notification) {
         @Nullable
         Map<TopologyChangesKey, TopologyChanges> topologyChanges = notification.getTopologyChanges();
         Optional<ServicePathList> servicePathListOptional = this.serviceDataStoreOperations.getServicePaths();
-        ServicePathList servicePathList = null;
-        if (!servicePathListOptional.isPresent()) {
+        if (servicePathListOptional.isEmpty()) {
             LOG.warn("Enable to retrieve service path list");
             return;
         }
-        servicePathList = servicePathListOptional.get();
+        ServicePathList servicePathList = servicePathListOptional.get();
         for (ServicePaths servicePaths : servicePathList.getServicePaths().values()) {
             String serviceName = servicePaths.getServicePathName();
             PathDescription pathDescription = servicePaths.getPathDescription();
@@ -98,61 +99,54 @@ public class NetworkModelListenerImpl implements TransportpceNetworkmodelListene
             // update service in the datastore. Only path description with all elements in service can have a service
             // in service. Therefore we check if all the states of the path description resources are inService
             Optional<Services> serviceOptional = this.serviceDataStoreOperations.getService(serviceName);
-            Services services = null;
-            if (!serviceOptional.isPresent()) {
+            if (serviceOptional.isEmpty()) {
                 LOG.error("Couldn't retrieve service");
                 continue;
             }
-            services = serviceOptional.get();
+            Services services = serviceOptional.get();
             OperationResult operationResult1 = null;
+            State newState;
             switch (services.getOperationalState()) {
                 case InService:
-                    if (!allElementsinPathinService(updatedAtoZ, updatedZtoA)) {
-                        LOG.debug("Service={} needs to be updated to outOfService", serviceName);
-                        //if (operationResult1 != null && operationResult1.isSuccess()) {
-                        //null check probably no more needed
-                        if (this.serviceDataStoreOperations
-                                .modifyService(serviceName, State.OutOfService, AdminStates.OutOfService)
-                                .isSuccess()) {
-                            LOG.info("Service state of {} correctly updated to outOfService in datastore", serviceName);
-                            continue;
-                        } else {
-                            LOG.error("Service state of {} cannot be updated to outOfService in datastore",
-                                serviceName);
-                        }
+                    if (allElementsinPathinService(updatedAtoZ, updatedZtoA)) {
+                        LOG.debug("Service {} state does not need to be modified", serviceName);
+                        continue;
                     }
+                    newState = State.OutOfService;
                     break;
                 case OutOfService:
-                    if (allElementsinPathinService(updatedAtoZ, updatedZtoA)) {
-                        LOG.debug("Service={} needs to be updated to inService", serviceName);
-                        //if (operationResult1 != null && operationResult1.isSuccess()) {
-                        //null check probably no more needed
-                        if (this.serviceDataStoreOperations
-                                .modifyService(serviceName, State.InService, AdminStates.InService)
-                                .isSuccess()) {
-                            LOG.info("Service state of {} correctly updated to inService in datastore", serviceName);
-                            continue;
-                        } else {
-                            LOG.error("Service state of {} cannot be updated to inService in datastore", serviceName);
-                        }
+                    if (!allElementsinPathinService(updatedAtoZ, updatedZtoA)) {
+                        LOG.debug("Service {} state does not need to be modified", serviceName);
+                        continue;
                     }
+                    newState = State.InService;
                     break;
                 default:
                     LOG.warn("Service {} state not managed", serviceName);
                     continue;
             }
-            LOG.debug("Service {} state does not need to be modified", serviceName);
+
+
+            LOG.debug("Service={} needs to be updated to {}", serviceName, newState);
+            //if (operationResult1 != null && operationResult1.isSuccess()) {
+            //null check probably no more needed
+            if (this.serviceDataStoreOperations
+                    .modifyService(serviceName, newState, services.getAdministrativeState())
+                    .isSuccess()) {
+                LOG.info("Service state of {} correctly updated to {} in datastore", serviceName, newState);
+                continue;
+            }
+            LOG.error("Service state of {} cannot be updated to {} in datastore", serviceName, newState);
+
         }
     }
 
-    private Map<ZToAKey, ZToA> changePathElementStateZA(Map<TopologyChangesKey, TopologyChanges> topologyChanges,
+    protected Map<ZToAKey, ZToA> changePathElementStateZA(Map<TopologyChangesKey, TopologyChanges> topologyChanges,
         PathDescription pathDescription) {
-
         Map<ZToAKey, ZToA> newztoaMap = new HashMap<>(pathDescription.getZToADirection().getZToA());
         List<ZToA> tpResources = pathDescription.getZToADirection().getZToA().values().stream()
-            .filter(ele -> ele.getResource().getResource().implementedInterface().getSimpleName()
-                .equals("TerminationPoint"))
-            .collect(Collectors.toList());
+                .filter(ele -> ele.getResource().getResource() instanceof TerminationPoint)
+                .collect(Collectors.toList());
         for (ZToA ztoA : tpResources) {
             String ztoAid = ztoA.getId();
             State ztoAState = ztoA.getResource().getState();
@@ -177,13 +171,12 @@ public class NetworkModelListenerImpl implements TransportpceNetworkmodelListene
         return newztoaMap;
     }
 
-    private Map<AToZKey, AToZ> changePathElementStateAZ(Map<TopologyChangesKey,
+    protected Map<AToZKey, AToZ> changePathElementStateAZ(Map<TopologyChangesKey,
             TopologyChanges> topologyChanges, PathDescription pathDescription) {
 
         Map<AToZKey, AToZ> newatozMap = new HashMap<>(pathDescription.getAToZDirection().getAToZ());
         List<AToZ> tpResources = pathDescription.getAToZDirection().getAToZ().values().stream()
-            .filter(ele -> ele.getResource().getResource().implementedInterface().getSimpleName()
-                .equals("TerminationPoint"))
+            .filter(ele -> ele.getResource().getResource() instanceof TerminationPoint)
             .collect(Collectors.toList());
         for (AToZ atoZ : tpResources) {
             String atoZid = atoZ.getId();
@@ -223,7 +216,7 @@ public class NetworkModelListenerImpl implements TransportpceNetworkmodelListene
             .build();
     }
 
-    private boolean allElementsinPathinService(Map<AToZKey, AToZ> updatedAtoZ, Map<ZToAKey, ZToA> updatedZtoA) {
+    protected boolean allElementsinPathinService(Map<AToZKey, AToZ> updatedAtoZ, Map<ZToAKey, ZToA> updatedZtoA) {
         boolean allEleminService = true;
         Iterator<AToZ> i1 = updatedAtoZ.values().iterator();
         Iterator<ZToA> i2 = updatedZtoA.values().iterator();
@@ -240,14 +233,8 @@ public class NetworkModelListenerImpl implements TransportpceNetworkmodelListene
     }
 
     private boolean compareTopologyUpdateResult(TopologyUpdateResult notification) {
-        if (topologyUpdateResult == null) {
-            return false;
-        }
-        if (topologyUpdateResult.getTopologyChanges().values()
-                .equals(notification.getTopologyChanges().values())) {
-            return false;
-        }
-        return true;
+        return topologyUpdateResult != null
+                && topologyUpdateResult.getTopologyChanges().equals(notification.getTopologyChanges());
     }
 
     public void setserviceDataStoreOperations(ServiceDataStoreOperations serviceData) {
index c4ee91ea902c5e90680c3e420b9501ae9fecd02a..73702010884f06c062614745e51950879bf21547 100644 (file)
@@ -7,16 +7,41 @@
  */
 package org.opendaylight.transportpce.servicehandler.listeners;
 
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Collection;
-import org.opendaylight.mdsal.binding.api.DataBroker;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 import org.opendaylight.mdsal.binding.api.DataObjectModification;
 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
 import org.opendaylight.mdsal.binding.api.DataTreeModification;
 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
+import org.opendaylight.transportpce.common.ResponseCodes;
+import org.opendaylight.transportpce.servicehandler.ServiceInput;
+import org.opendaylight.transportpce.servicehandler.impl.ServicehandlerImpl;
+import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.Restorable;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.RpcActions;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.sdnc.request.header.SdncRequestHeaderBuilder;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.ServiceCreateInputBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.ServiceCreateOutput;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.ServiceDeleteInputBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.ServiceDeleteOutput;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service.create.input.ServiceAEndBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service.create.input.ServiceZEndBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service.delete.input.ServiceDeleteReqInfo;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service.delete.input.ServiceDeleteReqInfoBuilder;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service.list.Services;
 import org.opendaylight.yang.gen.v1.nbi.notifications.rev210813.PublishNotificationAlarmService;
 import org.opendaylight.yang.gen.v1.nbi.notifications.rev210813.PublishNotificationAlarmServiceBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -24,14 +49,22 @@ public class ServiceListener implements DataTreeChangeListener<Services> {
 
     private static final Logger LOG = LoggerFactory.getLogger(ServiceListener.class);
     private static final String PUBLISHER = "ServiceListener";
-    private final DataBroker dataBroker;
+    private ServicehandlerImpl servicehandlerImpl;
+    private ServiceDataStoreOperations serviceDataStoreOperations;
     private NotificationPublishService notificationPublishService;
+    private Map<String, ServiceInput> mapServiceInputReroute;
+    private final ScheduledExecutorService executor;
 
-    public ServiceListener(final DataBroker dataBroker, NotificationPublishService notificationPublishService) {
-        this.dataBroker = dataBroker;
+    public ServiceListener(ServicehandlerImpl servicehandlerImpl, ServiceDataStoreOperations serviceDataStoreOperations,
+                           NotificationPublishService notificationPublishService) {
+        this.servicehandlerImpl = servicehandlerImpl;
         this.notificationPublishService = notificationPublishService;
+        this.serviceDataStoreOperations = serviceDataStoreOperations;
+        this.executor = MoreExecutors.getExitingScheduledExecutorService(new ScheduledThreadPoolExecutor(4));
+        mapServiceInputReroute = new HashMap<>();
     }
 
+    @Override
     public void onDataTreeChanged(Collection<DataTreeModification<Services>> changes) {
         LOG.info("onDataTreeChanged - {}", this.getClass().getSimpleName());
         for (DataTreeModification<Services> change : changes) {
@@ -39,34 +72,67 @@ public class ServiceListener implements DataTreeChangeListener<Services> {
             if (rootService.getDataBefore() == null) {
                 continue;
             }
-            String serviceName = rootService.getDataBefore().key().getServiceName();
+            String serviceInputName = rootService.getDataBefore().key().getServiceName();
             switch (rootService.getModificationType()) {
                 case DELETE:
-                    LOG.info("Service {} correctly deleted from controller", serviceName);
+                    LOG.info("Service {} correctly deleted from controller", serviceInputName);
+                    if (mapServiceInputReroute.get(serviceInputName) != null) {
+                        serviceRerouteStep2(serviceInputName);
+                    }
                     break;
                 case WRITE:
-                    Services input = rootService.getDataAfter();
-                    if (rootService.getDataBefore().getOperationalState() == State.InService
-                            && rootService.getDataAfter().getOperationalState() == State.OutOfService) {
-                        LOG.info("Service {} is becoming outOfService", serviceName);
+                    Services inputBefore = rootService.getDataBefore();
+                    Services inputAfter = rootService.getDataAfter();
+                    if (inputBefore.getOperationalState() == State.InService
+                            && inputAfter.getOperationalState() == State.OutOfService) {
+                        LOG.info("Service {} is becoming outOfService", serviceInputName);
                         sendNbiNotification(new PublishNotificationAlarmServiceBuilder()
-                                .setServiceName(input.getServiceName())
-                                .setConnectionType(input.getConnectionType())
+                                .setServiceName(inputAfter.getServiceName())
+                                .setConnectionType(inputAfter.getConnectionType())
                                 .setMessage("The service is now outOfService")
                                 .setOperationalState(State.OutOfService)
                                 .setPublisherName(PUBLISHER)
                                 .build());
-                    }
-                    else if (rootService.getDataBefore().getOperationalState() == State.OutOfService
-                            && rootService.getDataAfter().getOperationalState() == State.InService) {
-                        LOG.info("Service {} is becoming InService", serviceName);
+                        if (inputAfter.getAdministrativeState() == AdminStates.InService
+                                && inputAfter.getServiceResiliency() != null
+                                && inputAfter.getServiceResiliency().getResiliency() != null
+                                && inputAfter.getServiceResiliency().getResiliency().equals(Restorable.class)) {
+                            LOG.info("Attempting to reroute the service '{}'...", serviceInputName);
+                            // It is used for hold off time purposes
+                            mapServiceInputReroute.put(serviceInputName, null);
+                            if (inputAfter.getServiceResiliency().getHoldoffTime() != null) {
+                                LOG.info("Waiting hold off time before rerouting...");
+                                executor.schedule(
+                                        () -> {
+                                            if (mapServiceInputReroute.containsKey(serviceInputName)
+                                                    && mapServiceInputReroute.get(serviceInputName) == null) {
+                                                serviceRerouteStep1(serviceInputName);
+                                            } else {
+                                                LOG.info("Cancelling rerouting for service '{}'...", serviceInputName);
+                                            }
+                                        },
+                                        Long.parseLong(String.valueOf(inputAfter.getServiceResiliency()
+                                                .getHoldoffTime())),
+                                        TimeUnit.MILLISECONDS);
+                            } else {
+                                serviceRerouteStep1(serviceInputName);
+                            }
+                        }
+                    } else if (inputAfter.getAdministrativeState() == AdminStates.InService
+                            && inputBefore.getOperationalState() == State.OutOfService
+                            && inputAfter.getOperationalState() == State.InService) {
+                        LOG.info("Service {} is becoming InService", serviceInputName);
                         sendNbiNotification(new PublishNotificationAlarmServiceBuilder()
-                                .setServiceName(input.getServiceName())
-                                .setConnectionType(input.getConnectionType())
+                                .setServiceName(inputAfter.getServiceName())
+                                .setConnectionType(inputAfter.getConnectionType())
                                 .setMessage("The service is now inService")
                                 .setOperationalState(State.InService)
                                 .setPublisherName(PUBLISHER)
                                 .build());
+                        if (mapServiceInputReroute.containsKey(serviceInputName)
+                                && mapServiceInputReroute.get(serviceInputName) == null) {
+                            mapServiceInputReroute.remove(serviceInputName);
+                        }
                     }
                     break;
                 default:
@@ -76,6 +142,79 @@ public class ServiceListener implements DataTreeChangeListener<Services> {
         }
     }
 
+    /**
+     * First step of the reroute : apply a service-delete RPC to the service.
+     *
+     * @param serviceNameToReroute Name of the service
+     */
+    private void serviceRerouteStep1(String serviceNameToReroute) {
+        mapServiceInputReroute.remove(serviceNameToReroute);
+        Optional<Services> serviceOpt = serviceDataStoreOperations.getService(serviceNameToReroute);
+        if (serviceOpt.isEmpty()) {
+            LOG.warn("Service '{}' does not exist in datastore", serviceNameToReroute);
+            return;
+        }
+        Services service = serviceOpt.get();
+        ListenableFuture<RpcResult<ServiceDeleteOutput>> res = this.servicehandlerImpl.serviceDelete(
+                new ServiceDeleteInputBuilder()
+                        .setSdncRequestHeader(new SdncRequestHeaderBuilder(service.getSdncRequestHeader())
+                                .setRpcAction(RpcActions.ServiceDelete)
+                                .build())
+                        .setServiceDeleteReqInfo(new ServiceDeleteReqInfoBuilder()
+                                .setServiceName(serviceNameToReroute)
+                                .setTailRetention(ServiceDeleteReqInfo.TailRetention.No)
+                                .build())
+                        .build());
+        try {
+            String httpResponseCode = res.get().getResult().getConfigurationResponseCommon().getResponseCode();
+            if (httpResponseCode.equals(ResponseCodes.RESPONSE_OK)) {
+                mapServiceInputReroute.put(serviceNameToReroute, new ServiceInput(
+                        new ServiceCreateInputBuilder()
+                                .setServiceName(serviceNameToReroute)
+                                .setCommonId(service.getCommonId())
+                                .setConnectionType(service.getConnectionType())
+                                .setServiceAEnd(new ServiceAEndBuilder(service.getServiceAEnd()).build())
+                                .setServiceZEnd(new ServiceZEndBuilder(service.getServiceZEnd()).build())
+                                .setHardConstraints(service.getHardConstraints())
+                                .setSoftConstraints(service.getSoftConstraints())
+                                .setSdncRequestHeader(service.getSdncRequestHeader())
+                                .setCustomer(service.getCustomer())
+                                .setCustomerContact(service.getCustomerContact())
+                                .setServiceResiliency(service.getServiceResiliency())
+                                .setDueDate(service.getDueDate())
+                                .setOperatorContact(service.getOperatorContact())
+                                .build()));
+                LOG.info("ServiceRerouteStep1 (deletion of the service) in progress");
+            } else {
+                LOG.warn("ServiceRerouteStep1 (deletion of the service) failed '{}' http code ", httpResponseCode);
+            }
+        } catch (ExecutionException | InterruptedException e) {
+            LOG.warn("ServiceRerouteStep1 FAILED ! ", e);
+        }
+    }
+
+    /**
+     * Second step of the reroute : apply a service-create RPC. This method is called after the first step of reroute
+     * when the service has been successfully deleted.
+     *
+     * @param serviceNameToReroute Name of the service
+     */
+    private void serviceRerouteStep2(String serviceNameToReroute) {
+        ListenableFuture<RpcResult<ServiceCreateOutput>> res = this.servicehandlerImpl.serviceCreate(
+                mapServiceInputReroute.get(serviceNameToReroute).getServiceCreateInput());
+        try {
+            String httpResponseCode = res.get().getResult().getConfigurationResponseCommon().getResponseCode();
+            if (httpResponseCode.equals(ResponseCodes.RESPONSE_OK)) {
+                LOG.info("ServiceRerouteStep2 (creation of the new service) in progress");
+            } else {
+                LOG.warn("ServiceRerouteStep2 (creation of the new service) failed '{}' http code ", httpResponseCode);
+            }
+        } catch (ExecutionException | InterruptedException e) {
+            LOG.warn("ServiceRerouteStep2 FAILED ! ", e);
+        }
+        mapServiceInputReroute.remove(serviceNameToReroute);
+    }
+
     /**
      * Send notification to NBI notification in order to publish message.
      *
index 93f80eca1ae333ba1a440e6aacb2a4d01e36de39..ef3fbd420e25e51a5fba6f02eef35803fef28fab 100644 (file)
@@ -14,6 +14,7 @@ import org.opendaylight.transportpce.servicehandler.ServiceInput;
 import org.opendaylight.transportpce.servicehandler.validation.checks.CheckCoherencyHardSoft;
 import org.opendaylight.transportpce.servicehandler.validation.checks.ComplianceCheckResult;
 import org.opendaylight.transportpce.servicehandler.validation.checks.ServicehandlerComplianceCheck;
+import org.opendaylight.transportpce.servicehandler.validation.checks.ServicehandlerServiceResiliencyCheck;
 import org.opendaylight.transportpce.servicehandler.validation.checks.ServicehandlerTxRxCheck;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.ConnectionType;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.RpcActions;
@@ -82,6 +83,18 @@ public final class ServiceCreateValidation {
         } else {
             LOG.warn("Common-id not specified !");
         }
+
+        if (input.getServiceResiliency() != null) {
+            LOG.debug("Service-resiliency specified");
+            ComplianceCheckResult complianceCheckResult = ServicehandlerServiceResiliencyCheck
+                    .check(input.getServiceResiliency());
+            if (complianceCheckResult.hasPassed()) {
+                LOG.debug("Service-resiliency checked !");
+            } else {
+                return OperationResult.failed(complianceCheckResult.getMessage());
+            }
+        }
+
         return OperationResult.ok("Validation successful.");
     }
 
diff --git a/servicehandler/src/main/java/org/opendaylight/transportpce/servicehandler/validation/checks/ServicehandlerServiceResiliencyCheck.java b/servicehandler/src/main/java/org/opendaylight/transportpce/servicehandler/validation/checks/ServicehandlerServiceResiliencyCheck.java
new file mode 100644 (file)
index 0000000..2d5b173
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright © 2022 Orange, 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.servicehandler.validation.checks;
+
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.resiliency.ServiceResiliency;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class to check compliance of service-resiliency input.
+ */
+public final class ServicehandlerServiceResiliencyCheck {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ServicehandlerServiceResiliencyCheck.class);
+    public static final String LOG_ATTRIBUTE_NOT_DEDICATED = "An attribute not dedicated for this type of "
+            + "resiliency was filled";
+    public static final String LOG_RESILIENCY_TYPE_UNMANAGED = "Resiliency unmanaged for compliance check !";
+    public static final String LOG_RESILIENCY_NULL = "Resiliency is null !";
+
+    /**
+     * Function to check coherency of service-resiliency inputs.
+     *
+     * @param serviceResiliency ServiceResiliency to check
+     * @return <code> true </code>  if coherent
+     *         <code> false </code> otherwise
+     */
+    public static ComplianceCheckResult check(ServiceResiliency serviceResiliency) {
+        if (serviceResiliency.getResiliency() != null) {
+            switch (serviceResiliency.getResiliency().getSimpleName()) {
+                case "Unprotected":
+                    return checkUnprotectedResiliency(serviceResiliency);
+
+                case "UnprotectedDiverselyRouted":
+                    return checkUnprotectedDiverselyRoutedResiliency(serviceResiliency);
+
+                case "Protected":
+                    return checkProtectedResiliency(serviceResiliency);
+
+                case "Restorable":
+                case "ExternalTriggerRestorable":
+                    return checkRestorableAndExternalTriggerRestorableResiliency(serviceResiliency);
+
+                default:
+                    LOG.warn(LOG_RESILIENCY_TYPE_UNMANAGED);
+                    return new ComplianceCheckResult(false, LOG_RESILIENCY_TYPE_UNMANAGED);
+            }
+        } else {
+            LOG.warn(LOG_RESILIENCY_NULL);
+            return new ComplianceCheckResult(false, LOG_RESILIENCY_NULL);
+        }
+    }
+
+    private static ComplianceCheckResult checkUnprotectedResiliency(ServiceResiliency serviceResiliency) {
+        return serviceResiliency.getRevertive() == null
+                && serviceResiliency.getWaitToRestore() == null
+                && serviceResiliency.getHoldoffTime() == null
+                && serviceResiliency.getPreCalculatedBackupPathNumber() == null
+                && serviceResiliency.getCoupledService() == null
+                    ? new ComplianceCheckResult(true, "")
+                    : new ComplianceCheckResult(false, LOG_ATTRIBUTE_NOT_DEDICATED);
+    }
+
+    private static ComplianceCheckResult checkUnprotectedDiverselyRoutedResiliency(
+            ServiceResiliency serviceResiliency) {
+        return serviceResiliency.getRevertive() == null
+                && serviceResiliency.getWaitToRestore() == null
+                && serviceResiliency.getHoldoffTime() == null
+                && serviceResiliency.getPreCalculatedBackupPathNumber() == null
+                    ? new ComplianceCheckResult(true, "")
+                    : new ComplianceCheckResult(false, LOG_ATTRIBUTE_NOT_DEDICATED);
+    }
+
+    private static ComplianceCheckResult checkProtectedResiliency(ServiceResiliency serviceResiliency) {
+        return (serviceResiliency.getWaitToRestore() == null
+                || (serviceResiliency.getRevertive() != null && serviceResiliency.getRevertive()))
+                && serviceResiliency.getPreCalculatedBackupPathNumber() == null
+                && serviceResiliency.getCoupledService() == null
+                    ? new ComplianceCheckResult(true, "")
+                    : new ComplianceCheckResult(false, LOG_ATTRIBUTE_NOT_DEDICATED);
+    }
+
+    private static ComplianceCheckResult checkRestorableAndExternalTriggerRestorableResiliency(
+            ServiceResiliency serviceResiliency) {
+        return (serviceResiliency.getWaitToRestore() == null
+                || (serviceResiliency.getRevertive() != null && serviceResiliency.getRevertive()))
+                && serviceResiliency.getCoupledService() == null
+                    ? new ComplianceCheckResult(true, "")
+                    : new ComplianceCheckResult(false, LOG_ATTRIBUTE_NOT_DEDICATED);
+    }
+
+    private ServicehandlerServiceResiliencyCheck() {
+    }
+}
index 5001049e868b30fb8f3800364de56d0d826180a2..affeddf0dd85cd0e7f949feb9c499fb93a02e69c 100644 (file)
@@ -44,7 +44,8 @@ Author: Martial Coulibaly <martial.coulibaly@gfi.com> on behalf of Orange
     </bean>
 
     <bean id="serviceListener" class="org.opendaylight.transportpce.servicehandler.listeners.ServiceListener">
-        <argument ref="dataBroker" />
+        <argument ref="serviceHandlerImpl" />
+        <argument ref="serviceDatastoreOperation" />
         <argument ref="notificationPublishService" />
     </bean>
 
diff --git a/servicehandler/src/test/java/org/opendaylight/transportpce/servicehandler/listeners/NetworkModelListenerImplTest.java b/servicehandler/src/test/java/org/opendaylight/transportpce/servicehandler/listeners/NetworkModelListenerImplTest.java
new file mode 100644 (file)
index 0000000..396efb9
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * Copyright © 2022 Orange, 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.servicehandler.listeners;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.opendaylight.mdsal.binding.api.NotificationPublishService;
+import org.opendaylight.transportpce.common.OperationResult;
+import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.TopologyUpdateResult;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.TopologyUpdateResultBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChanges;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChangesBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChangesKey;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service.list.ServicesBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.AToZDirectionBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.ZToADirectionBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.atoz.direction.AToZ;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.atoz.direction.AToZBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.atoz.direction.AToZKey;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.ztoa.direction.ZToA;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.ztoa.direction.ZToABuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.ztoa.direction.ZToAKey;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.ResourceBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.resource.resource.LinkBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.resource.resource.NodeBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.resource.resource.TerminationPointBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.path.PathDescription;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.path.PathDescriptionBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathListBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
+
+@RunWith(MockitoJUnitRunner.class)
+public class NetworkModelListenerImplTest {
+
+    @Mock
+    private NotificationPublishService notificationPublishService;
+    @Mock
+    private ServiceDataStoreOperations serviceDataStoreOperations;
+    private static PathDescription pathDescription;
+    private NetworkModelListenerImpl networkModelListener;
+
+    @Before
+    public void setUp() {
+        pathDescription = new PathDescriptionBuilder()
+                .setAToZDirection(new AToZDirectionBuilder().setAToZ(new HashMap<>(createMapAtoZ())).build())
+                .setZToADirection(new ZToADirectionBuilder().setZToA(new HashMap<>(createMapZtoA())).build())
+                .build();
+        networkModelListener = new NetworkModelListenerImpl(notificationPublishService,
+                serviceDataStoreOperations);
+    }
+
+    @Test
+    public void testChangePathElementStateZAShouldNotModifyPathDescriptionsElementStates() {
+        Map<TopologyChangesKey, TopologyChanges> topologyChanges = Map.of(
+                new TopologyChangesKey("tpNodeIdA", "TpIdA1"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA1")
+                        .setState(State.InService)
+                        .build(),
+                new TopologyChangesKey("tpNodeIdA", "TpIdA2"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA2")
+                        .setState(State.InService)
+                        .build()
+        );
+
+        assertEquals(pathDescription.getZToADirection().getZToA(),
+                networkModelListener.changePathElementStateZA(topologyChanges, pathDescription));
+    }
+
+    @Test
+    public void testChangePathElementStateZAShouldModifyPathDescriptionsElementStates() {
+        Map<TopologyChangesKey, TopologyChanges> topologyChanges = Map.of(
+                new TopologyChangesKey("tpNodeIdA", "TpIdA1"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA1")
+                        .setState(State.OutOfService)
+                        .build(),
+                new TopologyChangesKey("tpNodeIdA", "TpIdA2"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA2")
+                        .setState(State.OutOfService)
+                        .build());
+
+        Map<ZToAKey, ZToA> ztoamapExpected = pathDescription.getZToADirection().getZToA();
+        ztoamapExpected.computeIfPresent(
+                new ZToAKey("6"),
+                (zToAKey, zToA) -> new ZToABuilder(zToA)
+                        .setResource(new ResourceBuilder(zToA.getResource())
+                                .setState(State.OutOfService)
+                                .build())
+                        .build());
+        ztoamapExpected.computeIfPresent(
+                new ZToAKey("4"),
+                (zToAKey, zToA) -> new ZToABuilder(zToA)
+                        .setResource(new ResourceBuilder(zToA.getResource())
+                                .setState(State.OutOfService)
+                                .build())
+                        .build());
+        assertEquals(ztoamapExpected, networkModelListener.changePathElementStateZA(topologyChanges, pathDescription));
+    }
+
+    @Test
+    public void testChangePathElementStateAZShouldNotModifyPathDescriptionsElementStates() {
+        Map<TopologyChangesKey, TopologyChanges> topologyChanges = Map.of(
+                new TopologyChangesKey("tpNodeIdA", "TpIdA1"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA1")
+                        .setState(State.InService)
+                        .build(),
+                new TopologyChangesKey("tpNodeIdA", "TpIdA2"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA2")
+                        .setState(State.InService)
+                        .build());
+
+        assertEquals(pathDescription.getAToZDirection().getAToZ(),
+                networkModelListener.changePathElementStateAZ(topologyChanges, pathDescription));
+    }
+
+    @Test
+    public void testChangePathElementStateAZShouldModifyPathDescriptionsElementStates() {
+        Map<TopologyChangesKey, TopologyChanges> topologyChanges = Map.of(
+                new TopologyChangesKey("tpNodeIdA", "TpIdA1"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA1")
+                        .setState(State.OutOfService)
+                        .build(),
+                new TopologyChangesKey("tpNodeIdA", "TpIdA2"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA2")
+                        .setState(State.OutOfService)
+                        .build());
+
+        Map<AToZKey, AToZ> atozmapExpected = pathDescription.getAToZDirection().getAToZ();
+        atozmapExpected.computeIfPresent(
+                new AToZKey("0"),
+                (aToZKey, aToZ) -> new AToZBuilder(aToZ)
+                        .setResource(new ResourceBuilder(aToZ.getResource())
+                                .setState(State.OutOfService)
+                                .build())
+                        .build());
+        atozmapExpected.computeIfPresent(
+                new AToZKey("2"),
+                (aToZKey, aToZ) -> new AToZBuilder(aToZ)
+                        .setResource(new ResourceBuilder(aToZ.getResource())
+                                .setState(State.OutOfService)
+                                .build())
+                        .build());
+        assertEquals(atozmapExpected, networkModelListener.changePathElementStateAZ(topologyChanges, pathDescription));
+    }
+
+    @Test
+    public void testAllElementsinPathinServiceShouldReturnFalse() {
+        Map<AToZKey, AToZ> atozmap = pathDescription.getAToZDirection().getAToZ();
+        atozmap.computeIfPresent(
+                new AToZKey("0"),
+                (aToZKey, aToZ) -> new AToZBuilder(aToZ)
+                        .setResource(new ResourceBuilder(aToZ.getResource())
+                                .setState(State.OutOfService)
+                                .build())
+                        .build());
+        Map<ZToAKey, ZToA> ztoamap = pathDescription.getZToADirection().getZToA();
+        ztoamap.computeIfPresent(
+                new ZToAKey("6"),
+                (zToAKey, zToA) -> new ZToABuilder(zToA)
+                        .setResource(new ResourceBuilder(zToA.getResource())
+                                .setState(State.OutOfService)
+                                .build())
+                        .build());
+        assertFalse(networkModelListener.allElementsinPathinService(atozmap, ztoamap));
+    }
+
+    @Test
+    public void testAllElementsinPathinServiceShouldReturnTrue() {
+        assertTrue(networkModelListener.allElementsinPathinService(pathDescription.getAToZDirection().getAToZ(),
+                pathDescription.getZToADirection().getZToA()));
+    }
+
+    @Test
+    public void testUpdateServicePathsShouldNotModifyServiceState() {
+        Map<ServicePathsKey, ServicePaths> servicePathMap = Map.of(new ServicePathsKey("service-path 1"),
+                new ServicePathsBuilder()
+                        .setServicePathName("service-path 1")
+                        .setPathDescription(pathDescription)
+                        .build());
+
+        when(serviceDataStoreOperations.getServicePaths()).thenReturn(Optional.of(new ServicePathListBuilder()
+                .setServicePaths(servicePathMap).build()));
+        when(serviceDataStoreOperations.modifyServicePath(any(PathDescription.class), anyString()))
+                .thenReturn(OperationResult.ok(""));
+        when(serviceDataStoreOperations.getService(anyString())).thenReturn(Optional.of(
+                new ServicesBuilder().setServiceName("serviceTest")
+                        .setOperationalState(State.InService)
+                        .setAdministrativeState(AdminStates.InService)
+                        .build()));
+
+        Map<TopologyChangesKey, TopologyChanges> topologyChanges = Map.of(
+                new TopologyChangesKey("tpNodeIdC", "TpIdC1"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdC")
+                        .setTpId("TpIdC1")
+                        .setState(State.OutOfService)
+                        .build(),
+                new TopologyChangesKey("tpNodeIdA", "TpIdA1"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA1")
+                        .setState(State.InService)
+                        .build());
+
+        networkModelListener.updateServicePaths(new TopologyUpdateResultBuilder()
+                .setTopologyChanges(topologyChanges).build());
+        verify(serviceDataStoreOperations,
+                never()).modifyService(anyString(), any(State.class), any(AdminStates.class));
+    }
+
+    @Test
+    public void testUpdateServicePathsShouldModifyServiceState() {
+        Map<ServicePathsKey, ServicePaths> servicePathMap = Map.of(
+                new ServicePathsKey("service-path 1"),
+                new ServicePathsBuilder()
+                        .setServicePathName("service-path 1")
+                        .setPathDescription(pathDescription)
+                        .build());
+
+        when(serviceDataStoreOperations.getServicePaths()).thenReturn(Optional.of(new ServicePathListBuilder()
+                .setServicePaths(servicePathMap).build()));
+        when(serviceDataStoreOperations.modifyServicePath(any(PathDescription.class), anyString()))
+                .thenReturn(OperationResult.ok(""));
+        when(serviceDataStoreOperations.getService(anyString())).thenReturn(Optional.of(
+                new ServicesBuilder().setServiceName("serviceTest")
+                        .setOperationalState(State.InService)
+                        .setAdministrativeState(AdminStates.InService)
+                        .build()));
+        when(serviceDataStoreOperations.modifyService(anyString(), any(State.class), any(AdminStates.class)))
+                .thenReturn(OperationResult.ok(""));
+
+        Map<TopologyChangesKey, TopologyChanges> topologyChanges = Map.of(
+                new TopologyChangesKey("tpNodeIdA", "TpIdA1"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA1")
+                        .setState(State.OutOfService)
+                        .build());
+
+        networkModelListener.updateServicePaths(new TopologyUpdateResultBuilder()
+                .setTopologyChanges(topologyChanges).build());
+        verify(serviceDataStoreOperations, times(1)).modifyService(anyString(),
+                eq(State.OutOfService), any(AdminStates.class));
+    }
+
+    @Test
+    public void testOnTopologyUpdateResultWhenNeverWired() {
+        NetworkModelListenerImpl networkModelListenerMocked = Mockito.mock(NetworkModelListenerImpl.class);
+        doCallRealMethod().when(networkModelListenerMocked).onTopologyUpdateResult(any(TopologyUpdateResult.class));
+
+        Map<TopologyChangesKey, TopologyChanges> topologyChanges1 = Map.of(
+                new TopologyChangesKey("tpNodeIdA", "TpIdA1"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA1")
+                        .setState(State.OutOfService)
+                        .build());
+        Map<TopologyChangesKey, TopologyChanges> topologyChanges2 = Map.of(
+                new TopologyChangesKey("tpNodeIdC", "TpIdC1"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdC")
+                        .setTpId("TpIdC1")
+                        .setState(State.OutOfService)
+                        .build());
+
+        networkModelListenerMocked.onTopologyUpdateResult(new TopologyUpdateResultBuilder()
+                .setTopologyChanges(topologyChanges1).build());
+        networkModelListenerMocked.onTopologyUpdateResult(new TopologyUpdateResultBuilder()
+                .setTopologyChanges(topologyChanges2).build());
+        verify(networkModelListenerMocked, times(2)).updateServicePaths(
+                any(TopologyUpdateResult.class));
+    }
+
+    @Test
+    public void testOnTopologyUpdateResultWhenAlreadyWired() {
+        NetworkModelListenerImpl networkModelListenerMocked = Mockito.mock(NetworkModelListenerImpl.class);
+        doCallRealMethod().when(networkModelListenerMocked).onTopologyUpdateResult(any(TopologyUpdateResult.class));
+
+        Map<TopologyChangesKey, TopologyChanges> topologyChanges = Map.of(
+                new TopologyChangesKey("tpNodeIdA", "TpIdA1"),
+                new TopologyChangesBuilder()
+                        .setNodeId("tpNodeIdA")
+                        .setTpId("TpIdA1")
+                        .setState(State.OutOfService)
+                        .build());
+        TopologyUpdateResult topologyUpdateResult = new TopologyUpdateResultBuilder()
+                .setTopologyChanges(topologyChanges).build();
+
+        networkModelListenerMocked.onTopologyUpdateResult(topologyUpdateResult);
+        networkModelListenerMocked.onTopologyUpdateResult(topologyUpdateResult);
+        verify(networkModelListenerMocked, times(1)).updateServicePaths(
+                any(TopologyUpdateResult.class));
+    }
+
+    private Map<AToZKey, AToZ> createMapAtoZ() {
+        Map<AToZKey, AToZ> atozmap = new HashMap<>();
+        atozmap.put(
+                new AToZKey("0"),
+                new AToZBuilder()
+                        .setId("0")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new TerminationPointBuilder()
+                                        .setTpNodeId("tpNodeIdA")
+                                        .setTpId("TpIdA1")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        atozmap.put(
+                new AToZKey("1"),
+                new AToZBuilder()
+                        .setId("1")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new NodeBuilder()
+                                        .setNodeId("NodeIdA")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        atozmap.put(
+                new AToZKey("2"),
+                new AToZBuilder()
+                        .setId("2")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new TerminationPointBuilder()
+                                        .setTpNodeId("tpNodeIdA")
+                                        .setTpId("TpIdA2")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        atozmap.put(
+                new AToZKey("3"),
+                new AToZBuilder()
+                        .setId("3")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new LinkBuilder()
+                                        .setLinkId("LinkIdAZ")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        atozmap.put(
+                new AToZKey("4"),
+                new AToZBuilder()
+                        .setId("4")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new TerminationPointBuilder()
+                                        .setTpNodeId("tpNodeIdZ")
+                                        .setTpId("TpIdZ2")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        atozmap.put(
+                new AToZKey("5"),
+                new AToZBuilder()
+                        .setId("5")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new NodeBuilder()
+                                        .setNodeId("NodeIdZ")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        atozmap.put(
+                new AToZKey("6"),
+                new AToZBuilder()
+                        .setId("6")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new TerminationPointBuilder()
+                                        .setTpNodeId("tpNodeIdZ")
+                                        .setTpId("TpIdZ1")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        return atozmap;
+    }
+
+    private Map<ZToAKey, ZToA> createMapZtoA() {
+        Map<ZToAKey, ZToA> ztoamap = new HashMap<>();
+        ztoamap.put(
+                new ZToAKey("0"),
+                new ZToABuilder()
+                        .setId("0")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new TerminationPointBuilder()
+                                        .setTpNodeId("tpNodeIdZ")
+                                        .setTpId("TpIdZ1")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        ztoamap.put(
+                new ZToAKey("1"),
+                new ZToABuilder()
+                        .setId("1")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new NodeBuilder()
+                                        .setNodeId("NodeIdZ")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        ztoamap.put(
+                new ZToAKey("2"),
+                new ZToABuilder()
+                        .setId("2")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new TerminationPointBuilder()
+                                        .setTpNodeId("tpNodeIdZ")
+                                        .setTpId("TpIdZ2")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        ztoamap.put(
+                new ZToAKey("3"),
+                new ZToABuilder()
+                        .setId("3")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new LinkBuilder()
+                                        .setLinkId("LinkIdAZ")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        ztoamap.put(
+                new ZToAKey("4"),
+                new ZToABuilder()
+                        .setId("4")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new TerminationPointBuilder()
+                                        .setTpNodeId("tpNodeIdA")
+                                        .setTpId("TpIdA2")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        ztoamap.put(
+                new ZToAKey("5"),
+                new ZToABuilder()
+                        .setId("5")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new NodeBuilder()
+                                        .setNodeId("NodeIdA")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        ztoamap.put(
+                new ZToAKey("6"),
+                new ZToABuilder()
+                        .setId("6")
+                        .setResource(new ResourceBuilder()
+                                .setResource(new TerminationPointBuilder()
+                                        .setTpNodeId("tpNodeIdA")
+                                        .setTpId("TpIdA1")
+                                        .build())
+                                .setState(State.InService)
+                                .build())
+                        .build());
+        return ztoamap;
+    }
+}
index 5dfe23e79a718c83f2d38c409384be95c7d64102..a18f8da39a6beed57664d7ed06224e532ed4059d 100755 (executable)
@@ -23,10 +23,11 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
-import org.opendaylight.mdsal.binding.api.DataBroker;
 import org.opendaylight.mdsal.binding.api.DataObjectModification;
 import org.opendaylight.mdsal.binding.api.DataTreeModification;
 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
+import org.opendaylight.transportpce.servicehandler.impl.ServicehandlerImpl;
+import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.node.types.rev210528.NodeIdType;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.ConnectionType;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.ServiceAEnd;
@@ -55,7 +56,9 @@ import org.opendaylight.yangtools.yang.common.Uint8;
 public class ServiceListenerTest {
 
     @Mock
-    private DataBroker dataBroker;
+    private ServicehandlerImpl servicehandler;
+    @Mock
+    private ServiceDataStoreOperations serviceDataStoreOperations;
     @Mock
     private NotificationPublishService notificationPublishService;
 
@@ -70,7 +73,8 @@ public class ServiceListenerTest {
 
         when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
         when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
-        ServiceListener listener = new ServiceListener(dataBroker, notificationPublishService);
+        ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
+                notificationPublishService);
         listener.onDataTreeChanged(changes);
         verify(ch, times(1)).getRootNode();
         verify(service, times(1)).getModificationType();
@@ -96,12 +100,13 @@ public class ServiceListenerTest {
         when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
         when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
         when(service.getDataAfter()).thenReturn(serviceDown);
-        ServiceListener listener = new ServiceListener(dataBroker, notificationPublishService);
+        ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
+                notificationPublishService);
         listener.onDataTreeChanged(changes);
         verify(ch, times(1)).getRootNode();
         verify(service, times(1)).getModificationType();
         verify(service, times(3)).getDataBefore();
-        verify(service, times(2)).getDataAfter();
+        verify(service, times(1)).getDataAfter();
         PublishNotificationAlarmService publishNotificationAlarmService =
                 buildNotificationAlarmService(serviceDown, "The service is now outOfService");
         try {
@@ -123,7 +128,8 @@ public class ServiceListenerTest {
 
         when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
         when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
-        ServiceListener listener = new ServiceListener(dataBroker, notificationPublishService);
+        ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
+                notificationPublishService);
         listener.onDataTreeChanged(changes);
         verify(ch, times(1)).getRootNode();
         verify(service, times(2)).getModificationType();
@@ -139,13 +145,13 @@ public class ServiceListenerTest {
     private Services buildService(State state, AdminStates adminStates) {
         ServiceAEnd serviceAEnd = getServiceAEndBuild().build();
         ServiceZEnd serviceZEnd = new ServiceZEndBuilder()
-                    .setClli("clli")
-                    .setServiceFormat(ServiceFormat.OC)
-                    .setServiceRate(Uint32.valueOf(1))
-                    .setNodeId(new NodeIdType("XPONDER-3-2"))
-                    .setTxDirection(Map.of(new TxDirectionKey(getTxDirection().key()),getTxDirection()))
-                    .setRxDirection(Map.of(new RxDirectionKey(getRxDirection().key()), getRxDirection()))
-                    .build();
+                .setClli("clli")
+                .setServiceFormat(ServiceFormat.OC)
+                .setServiceRate(Uint32.valueOf(1))
+                .setNodeId(new NodeIdType("XPONDER-3-2"))
+                .setTxDirection(Map.of(new TxDirectionKey(getTxDirection().key()), getTxDirection()))
+                .setRxDirection(Map.of(new RxDirectionKey(getRxDirection().key()), getRxDirection()))
+                .build();
         ServicesBuilder builtInput = new ServicesBuilder()
                 .setCommonId("commonId")
                 .setConnectionType(ConnectionType.Service)
@@ -165,7 +171,7 @@ public class ServiceListenerTest {
                 .setServiceFormat(ServiceFormat.OC)
                 .setServiceRate(Uint32.valueOf(1))
                 .setNodeId(new NodeIdType("XPONDER-1-2"))
-                .setTxDirection(Map.of(new TxDirectionKey(getTxDirection().key()),getTxDirection()))
+                .setTxDirection(Map.of(new TxDirectionKey(getTxDirection().key()), getTxDirection()))
                 .setRxDirection(Map.of(new RxDirectionKey(getRxDirection().key()), getRxDirection()));
     }
 
diff --git a/servicehandler/src/test/java/org/opendaylight/transportpce/servicehandler/validation/checks/CheckCoherencyServiceResiliencyTest.java b/servicehandler/src/test/java/org/opendaylight/transportpce/servicehandler/validation/checks/CheckCoherencyServiceResiliencyTest.java
new file mode 100644 (file)
index 0000000..22a728e
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2022 Orange, 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.servicehandler.validation.checks;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.Protected;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.Restorable;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.Unprotected;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.UnprotectedDiverselyRouted;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.resiliency.ServiceResiliencyBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.resiliency.service.resiliency.CoupledServiceBuilder;
+import org.opendaylight.yangtools.yang.common.Uint64;
+import org.opendaylight.yangtools.yang.common.Uint8;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CheckCoherencyServiceResiliencyTest {
+
+    @Test
+    public void testCheckWhenResiliencyNull() {
+        ComplianceCheckResult result = ServicehandlerServiceResiliencyCheck.check(
+                new ServiceResiliencyBuilder().setRevertive(true).build());
+
+        Assert.assertFalse(result.hasPassed());
+        Assert.assertEquals(ServicehandlerServiceResiliencyCheck.LOG_RESILIENCY_NULL, result.getMessage());
+    }
+
+    @Test
+    public void testCheckWhenUnprotectedResiliencyWithWrongAttributes() {
+        ServiceResiliencyBuilder input = new ServiceResiliencyBuilder().setResiliency(Unprotected.class);
+
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(input.setRevertive(true).build()).hasPassed());
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setWaitToRestore(Uint64.valueOf(1)).build()).hasPassed());
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setHoldoffTime(Uint64.valueOf(1)).build()).hasPassed());
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setPreCalculatedBackupPathNumber(Uint8.valueOf(1)).build()).hasPassed());
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setCoupledService(new CoupledServiceBuilder().build()).build()).hasPassed());
+    }
+
+    @Test
+    public void testCheckWhenUnprotectedResiliencyWithCorrectAttributes() {
+        Assert.assertTrue(ServicehandlerServiceResiliencyCheck.check(
+                new ServiceResiliencyBuilder()
+                        .setResiliency(Unprotected.class)
+                        .build())
+                .hasPassed());
+    }
+
+    @Test
+    public void testCheckWhenUnprotectedDiverselyRoutedResiliencyWithWrongAttributes() {
+        ServiceResiliencyBuilder input = new ServiceResiliencyBuilder().setResiliency(UnprotectedDiverselyRouted.class);
+
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(input.setRevertive(true).build()).hasPassed());
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setWaitToRestore(Uint64.valueOf(1)).build()).hasPassed());
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setHoldoffTime(Uint64.valueOf(1)).build()).hasPassed());
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setPreCalculatedBackupPathNumber(Uint8.valueOf(1)).build()).hasPassed());
+    }
+
+    @Test
+    public void testCheckWhenUnprotectedDiverselyRoutedResiliencyWithCorrectAttributes() {
+        Assert.assertTrue(ServicehandlerServiceResiliencyCheck.check(
+                new ServiceResiliencyBuilder().setResiliency(UnprotectedDiverselyRouted.class)
+                        .setCoupledService(new CoupledServiceBuilder().build()).build()).hasPassed());
+    }
+
+    @Test
+    public void testCheckWhenProtectedResiliencyWithWrongAttributes() {
+        ServiceResiliencyBuilder input = new ServiceResiliencyBuilder().setResiliency(Protected.class);
+
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setWaitToRestore(Uint64.valueOf(1)).setRevertive(false).build()).hasPassed());
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setPreCalculatedBackupPathNumber(Uint8.valueOf(1)).build()).hasPassed());
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setCoupledService(new CoupledServiceBuilder().build()).build()).hasPassed());
+    }
+
+    @Test
+    public void testCheckWhenProtectedResiliencyWithCorrectAttributes() {
+        Assert.assertTrue(ServicehandlerServiceResiliencyCheck.check(
+                new ServiceResiliencyBuilder()
+                        .setResiliency(Protected.class)
+                        .setRevertive(true)
+                        .setWaitToRestore(Uint64.valueOf(1))
+                        .setHoldoffTime(Uint64.valueOf(1))
+                        .build())
+                .hasPassed());
+    }
+
+    @Test
+    public void testCheckWhenRestorableOrExternalTriggerRestorableResiliencyWithWrongAttributes() {
+        ServiceResiliencyBuilder input = new ServiceResiliencyBuilder().setResiliency(Restorable.class);
+
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setWaitToRestore(Uint64.valueOf(1)).setRevertive(false).build()).hasPassed());
+        Assert.assertFalse(ServicehandlerServiceResiliencyCheck.check(
+                input.setCoupledService(new CoupledServiceBuilder().build()).build()).hasPassed());
+    }
+
+    @Test
+    public void testCheckWhenRestorableOrExternalTriggerRestorableResiliencyWithCorrectAttributes() {
+        Assert.assertTrue(ServicehandlerServiceResiliencyCheck.check(
+                new ServiceResiliencyBuilder()
+                        .setResiliency(Restorable.class)
+                        .setRevertive(true)
+                        .setWaitToRestore(Uint64.valueOf(1))
+                        .setHoldoffTime(Uint64.valueOf(1))
+                        .setPreCalculatedBackupPathNumber(Uint8.valueOf(1))
+                        .build())
+                .hasPassed());
+    }
+}
index 2d68f7b0354fa71542c4eab789578a1889061e92..ef39cb2625d8d3688c72be2c4f07932136ea1a48 100644 (file)
@@ -259,7 +259,7 @@ class TransportPCEFulltesting(unittest.TestCase):
         self.assertEqual(response.status_code, requests.codes.ok)
         res = response.json()
         self.assertEqual(res['services'][0]['operational-state'], 'outOfService')
-        self.assertEqual(res['services'][0]['administrative-state'], 'outOfService')
+        self.assertEqual(res['services'][0]['administrative-state'], 'inService')
         time.sleep(1)
 
     def test_17_restore_status_line_port_xpdra(self):