Implement PCE RPC path-computation-reroute-request
[transportpce.git] / servicehandler / src / main / java / org / opendaylight / transportpce / servicehandler / listeners / ServiceListener.java
index ed6a9a6be3bb1bc02d16cfde87ddf2cb25108b3a..434aa2cb31be964e6e9dcba2f5d47ad352bafbec 100644 (file)
@@ -7,6 +7,9 @@
  */
 package org.opendaylight.transportpce.servicehandler.listeners;
 
+import static org.opendaylight.transportpce.servicehandler.ModelMappingUtils.createServiceAEndReroute;
+import static org.opendaylight.transportpce.servicehandler.ModelMappingUtils.createServiceZEndReroute;
+
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Collection;
@@ -22,9 +25,14 @@ 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.pce.service.PathComputationService;
 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.opendaylight.transportpce.pce.rev220808.PathComputationRerouteRequestInput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRerouteRequestInputBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRerouteRequestOutput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.path.computation.reroute.request.input.EndpointsBuilder;
 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;
@@ -39,6 +47,11 @@ import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service
 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.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.AToZKey;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.resource.resource.TerminationPoint;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.PceMetric;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
 import org.opendaylight.yang.gen.v1.nbi.notifications.rev211013.PublishNotificationAlarmService;
 import org.opendaylight.yang.gen.v1.nbi.notifications.rev211013.PublishNotificationAlarmServiceBuilder;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -52,14 +65,17 @@ public class ServiceListener implements DataTreeChangeListener<Services> {
     private ServicehandlerImpl servicehandlerImpl;
     private ServiceDataStoreOperations serviceDataStoreOperations;
     private NotificationPublishService notificationPublishService;
+    private PathComputationService pathComputationService;
     private Map<String, ServiceInput> mapServiceInputReroute;
     private final ScheduledExecutorService executor;
 
     public ServiceListener(ServicehandlerImpl servicehandlerImpl, ServiceDataStoreOperations serviceDataStoreOperations,
-                           NotificationPublishService notificationPublishService) {
+                           NotificationPublishService notificationPublishService,
+                           PathComputationService pathComputationService) {
         this.servicehandlerImpl = servicehandlerImpl;
         this.notificationPublishService = notificationPublishService;
         this.serviceDataStoreOperations = serviceDataStoreOperations;
+        this.pathComputationService = pathComputationService;
         this.executor = MoreExecutors.getExitingScheduledExecutorService(new ScheduledThreadPoolExecutor(4));
         mapServiceInputReroute = new HashMap<>();
     }
@@ -98,7 +114,11 @@ public class ServiceListener implements DataTreeChangeListener<Services> {
                                 && inputAfter.getServiceResiliency().getResiliency() != null
                                 && inputAfter.getServiceResiliency().getResiliency().equals(Restorable.VALUE)) {
                             LOG.info("Attempting to reroute the service '{}'...", serviceInputName);
-                            // It is used for hold off time purposes
+                            if (!serviceRerouteCheck(inputBefore)) {
+                                LOG.info("No other path available, cancelling reroute process of service '{}'...",
+                                        serviceInputName);
+                                continue;
+                            }
                             mapServiceInputReroute.put(serviceInputName, null);
                             if (inputAfter.getServiceResiliency().getHoldoffTime() != null) {
                                 LOG.info("Waiting hold off time before rerouting...");
@@ -108,7 +128,8 @@ public class ServiceListener implements DataTreeChangeListener<Services> {
                                                     && mapServiceInputReroute.get(serviceInputName) == null) {
                                                 serviceRerouteStep1(serviceInputName);
                                             } else {
-                                                LOG.info("Cancelling rerouting for service '{}'...", serviceInputName);
+                                                LOG.info("Cancelling reroute process of service '{}'...",
+                                                        serviceInputName);
                                             }
                                         },
                                         Long.parseLong(String.valueOf(inputAfter.getServiceResiliency()
@@ -215,6 +236,44 @@ public class ServiceListener implements DataTreeChangeListener<Services> {
         mapServiceInputReroute.remove(serviceNameToReroute);
     }
 
+    /**
+     * Call the PCE RPC path-computation-reroute-request to check if any other path exists.
+     *
+     * @param input Service to be rerouted
+     */
+    protected boolean serviceRerouteCheck(Services input) {
+        Optional<ServicePaths> servicePaths = serviceDataStoreOperations.getServicePath(input.getServiceName());
+        if (servicePaths.isEmpty()) {
+            LOG.warn("Service path of '{}' does not exist in datastore", input.getServiceName());
+            return false;
+        }
+        // Get the network xpdr termination points
+        Map<AToZKey, AToZ> mapaToz = servicePaths.get().getPathDescription().getAToZDirection().getAToZ();
+        String aendtp = ((TerminationPoint) mapaToz.get(new AToZKey(String.valueOf(mapaToz.size() - 3)))
+                .getResource().getResource()).getTpId();
+        String zendtp = ((TerminationPoint) mapaToz.get(new AToZKey("2")).getResource()
+                .getResource()).getTpId();
+        PathComputationRerouteRequestInput inputPC = new PathComputationRerouteRequestInputBuilder()
+                .setHardConstraints(input.getHardConstraints())
+                .setSoftConstraints(input.getSoftConstraints())
+                .setServiceAEnd(createServiceAEndReroute(input.getServiceAEnd()))
+                .setServiceZEnd(createServiceZEndReroute(input.getServiceZEnd()))
+                .setPceRoutingMetric(PceMetric.TEMetric)
+                .setEndpoints(new EndpointsBuilder()
+                        .setAEndTp(aendtp)
+                        .setZEndTp(zendtp)
+                        .build())
+                .build();
+        ListenableFuture<PathComputationRerouteRequestOutput> res =
+                pathComputationService.pathComputationRerouteRequest(inputPC);
+        try {
+            return res.get().getConfigurationResponseCommon().getResponseCode().equals(ResponseCodes.RESPONSE_OK);
+        } catch (ExecutionException | InterruptedException e) {
+            LOG.warn("ServiceRerouteCheck FAILED ! ", e);
+            return false;
+        }
+    }
+
     /**
      * Send notification to NBI notification in order to publish message.
      *