package org.opendaylight.transportpce.pce;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestInput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRerouteRequestInput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
return new PceComplianceCheckResult(result, message);
}
+ public static PceComplianceCheckResult check(PathComputationRerouteRequestInput input) {
+ if (input == null) {
+ return new PceComplianceCheckResult(false, "");
+ }
+ if (input.getEndpoints() == null
+ || input.getEndpoints().getAEndTp() == null
+ || input.getEndpoints().getZEndTp() == null) {
+ String message = "At least one of the termination points is missing";
+ LOG.debug(message);
+ return new PceComplianceCheckResult(false, message);
+ }
+ return new PceComplianceCheckResult(true, "");
+ }
+
}
import org.opendaylight.transportpce.pce.networkanalyzer.PceResult;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestInput;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestInputBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.path.computation.reroute.request.input.Endpoints;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.service.path.rpc.result.PathDescriptionBuilder;
import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev211210.routing.constraints.HardConstraints;
import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.AToZDirection;
* Class for Sending
* PCE requests :
* - path-computation-request
+ * - path-computation-reroute
* - cancel-resource-reserve.
* @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
*
private String responseCode;
private final GnpyConsumer gnpyConsumer;
private PortMapping portMapping;
+ // Define the termination points whose reserved status is not taken into account during the pruning process
+ private Endpoints endpoints;
public PceSendingPceRPCs(GnpyConsumer gnpyConsumer) {
setPathDescription(null);
this.gnpyConsumer = gnpyConsumer;
}
- public PceSendingPceRPCs(PathComputationRequestInput input,
- NetworkTransactionService networkTransaction, GnpyConsumer gnpyConsumer, PortMapping portMapping) {
+ public PceSendingPceRPCs(PathComputationRequestInput input, NetworkTransactionService networkTransaction,
+ GnpyConsumer gnpyConsumer, PortMapping portMapping) {
this.gnpyConsumer = gnpyConsumer;
setPathDescription(null);
-
// TODO compliance check to check that input is not empty
this.input = input;
this.networkTransaction = networkTransaction;
this.portMapping = portMapping;
+ this.endpoints = null;
+ }
+
+ public PceSendingPceRPCs(PathComputationRequestInput input, NetworkTransactionService networkTransaction,
+ GnpyConsumer gnpyConsumer, PortMapping portMapping,
+ Endpoints endpoints) {
+ this.gnpyConsumer = gnpyConsumer;
+ setPathDescription(null);
+ this.input = input;
+ this.networkTransaction = networkTransaction;
+ this.portMapping = portMapping;
+ this.endpoints = endpoints;
}
public void cancelResourceReserve() {
public void pathComputationWithConstraints(PceConstraints hardConstraints, PceConstraints softConstraints) {
- PceCalculation nwAnalizer =
- new PceCalculation(input, networkTransaction, hardConstraints, softConstraints, rc, portMapping);
+ PceCalculation nwAnalizer = new PceCalculation(input, networkTransaction, hardConstraints, softConstraints, rc,
+ portMapping, endpoints);
nwAnalizer.retrievePceNetwork();
rc = nwAnalizer.getReturnStructure();
String serviceType = nwAnalizer.getServiceType();
public ListenableFuture<RpcResult<CancelResourceReserveOutput>>
cancelResourceReserve(CancelResourceReserveInput input) {
LOG.info("RPC cancelResourceReserve request received");
- CancelResourceReserveOutput output = null;
try {
- output = this.pathComputationService.cancelResourceReserve(input).get();
+ return RpcResultBuilder
+ .success(
+ this.pathComputationService.cancelResourceReserve(input).get())
+ .buildFuture();
} catch (InterruptedException | ExecutionException e) {
LOG.error("RPC cancelResourceReserve failed !", e);
+ return RpcResultBuilder.success((CancelResourceReserveOutput) null).buildFuture();
}
- return RpcResultBuilder.success(output).buildFuture();
}
@Override
pathComputationRequest(PathComputationRequestInput input) {
LOG.info("RPC path computation request received");
LOG.debug("input parameters are : input = {}", input);
- PathComputationRequestOutput output = null;
try {
- output = this.pathComputationService.pathComputationRequest(input).get();
+ return RpcResultBuilder
+ .success(
+ this.pathComputationService.pathComputationRequest(input).get())
+ .buildFuture();
} catch (InterruptedException | ExecutionException e) {
LOG.error("RPC path computation request failed !", e);
}
- return RpcResultBuilder.success(output).buildFuture();
+ return RpcResultBuilder.success((PathComputationRequestOutput) null).buildFuture();
}
@Override
- public ListenableFuture<RpcResult<PathComputationRerouteRequestOutput>>
- pathComputationRerouteRequest(PathComputationRerouteRequestInput input) {
+ public ListenableFuture<RpcResult<PathComputationRerouteRequestOutput>> pathComputationRerouteRequest(
+ PathComputationRerouteRequestInput input) {
LOG.info("RPC path computation reroute request received");
LOG.debug("input parameters are : input = {}", input);
- return null;
+ try {
+ return RpcResultBuilder
+ .success(
+ this.pathComputationService.pathComputationRerouteRequest(input).get())
+ .buildFuture();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("RPC path computation request failed !", e);
+ return RpcResultBuilder.success((PathComputationRerouteRequestOutput) null).buildFuture();
+ }
}
}
import org.opendaylight.transportpce.pce.PceComplianceCheck;
import org.opendaylight.transportpce.pce.constraints.PceConstraints;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestInput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.path.computation.reroute.request.input.Endpoints;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220316.mc.capabilities.McCapabilities;
import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Link1;
import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1;
private List<LinkId> linksToExclude = new ArrayList<>();
private PceResult returnStructure;
private PortMapping portMapping;
+ // Define the termination points whose reserved status is not taken into account during the pruning process
+ private Endpoints endpoints;
private enum ConstraintTypes {
NONE, HARD_EXCLUDE, HARD_INCLUDE, HARD_DIVERSITY, SOFT_EXCLUDE, SOFT_INCLUDE, SOFT_DIVERSITY;
private MappingUtils mappingUtils;
public PceCalculation(PathComputationRequestInput input, NetworkTransactionService networkTransactionService,
- PceConstraints pceHardConstraints, PceConstraints pceSoftConstraints, PceResult rc,
- PortMapping portMapping) {
+ PceConstraints pceHardConstraints, PceConstraints pceSoftConstraints, PceResult rc,
+ PortMapping portMapping) {
this.input = input;
this.networkTransactionService = networkTransactionService;
this.returnStructure = rc;
+ this.pceHardConstraints = pceHardConstraints;
+ this.mappingUtils = new MappingUtilsImpl(networkTransactionService.getDataBroker());
+ this.portMapping = portMapping;
+ this.endpoints = null;
+ parseInput();
+ }
+ public PceCalculation(PathComputationRequestInput input, NetworkTransactionService networkTransactionService,
+ PceConstraints pceHardConstraints, PceConstraints pceSoftConstraints, PceResult rc,
+ PortMapping portMapping, Endpoints endpoints) {
+ this.input = input;
+ this.networkTransactionService = networkTransactionService;
+ this.returnStructure = rc;
this.pceHardConstraints = pceHardConstraints;
this.mappingUtils = new MappingUtilsImpl(networkTransactionService.getDataBroker());
this.portMapping = portMapping;
+ this.endpoints = endpoints;
parseInput();
}
PceOpticalNode pceNode = new PceOpticalNode(deviceNodeId, this.serviceType, portMapping, node, nodeType,
mappingUtils.getOpenRoadmVersion(deviceNodeId), getSlotWidthGranularity(deviceNodeId, node.getNodeId()),
getCentralFreqGranularity(deviceNodeId, node.getNodeId()));
+ if (endpoints != null) {
+ pceNode.setEndpoints(endpoints);
+ }
pceNode.validateAZxponder(anodeId, znodeId, input.getServiceAEnd().getServiceFormat());
pceNode.initFrequenciesBitSet();
import org.opendaylight.transportpce.common.fixedflex.GridConstant;
import org.opendaylight.transportpce.common.mapping.PortMapping;
import org.opendaylight.transportpce.pce.SortPortsByName;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.path.computation.reroute.request.input.Endpoints;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220316.mapping.Mapping;
import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.TerminationPoint1;
import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
private String version;
private BigDecimal slotWidthGranularity;
private BigDecimal centralFreqGranularity;
+ private Endpoints endpoints;
public PceOpticalNode(String deviceNodeId, String serviceType, PortMapping portMapping, Node node,
OpenroadmNodeType nodeType, String version, BigDecimal slotWidthGranularity,
LOG.warn("initXndrTps: XPONDER tp = {} is OOS/degraded", tp.getTpId().getValue());
continue;
}
- org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.TerminationPoint1 nttp1 = tp
- .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210
- .TerminationPoint1.class);
- if (nttp1 != null && nttp1.getXpdrNetworkAttributes().getWavelength() != null) {
- this.usedXpndrNWTps.add(tp.getTpId().getValue());
- LOG.debug("initXndrTps: XPONDER tp = {} is used", tp.getTpId().getValue());
- continue;
+ if (endpoints == null
+ || (!endpoints.getAEndTp().equals(tp.getTpId().getValue())
+ && !endpoints.getZEndTp().equals(tp.getTpId().getValue()))) {
+ org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.TerminationPoint1 nttp1 =
+ tp.augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210
+ .TerminationPoint1.class);
+ if (nttp1 != null && nttp1.getXpdrNetworkAttributes().getWavelength() != null) {
+ this.usedXpndrNWTps.add(tp.getTpId().getValue());
+ LOG.debug("initXndrTps: XPONDER tp = {} is used", tp.getTpId().getValue());
+ continue;
+ }
}
// find Client of this network TP
if (cntp1.getAssociatedConnectionMapTp() != null) {
return centralFreqGranularity;
}
+ public void setEndpoints(Endpoints endpoints) {
+ this.endpoints = endpoints;
+ }
+
}
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.CancelResourceReserveOutput;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestInput;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestOutput;
+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.PathComputationRerouteRequestOutput;
/**
* Path Computation Service.
*/
ListenableFuture<PathComputationRequestOutput> pathComputationRequest(PathComputationRequestInput input);
+ /**
+ * Requests a path computation in order to reroute a service.
+ *
+ * @param input PathComputationRerouteRequestInput data
+ * @return output PathComputationRerouteRequestOutput data
+ */
+ ListenableFuture<PathComputationRerouteRequestOutput> pathComputationRerouteRequest(
+ PathComputationRerouteRequestInput input);
+
}
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.CancelResourceReserveOutput;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.CancelResourceReserveOutputBuilder;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestInput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestInputBuilder;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestOutput;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestOutputBuilder;
+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.PathComputationRerouteRequestOutput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRerouteRequestOutputBuilder;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.ServicePathRpcResult;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.ServicePathRpcResultBuilder;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.gnpy.GnpyResponse;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.gnpy.GnpyResponseBuilder;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.gnpy.gnpy.response.response.type.NoPathCaseBuilder;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.gnpy.gnpy.response.response.type.PathCaseBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.path.computation.request.input.ServiceAEndBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.path.computation.request.input.ServiceZEndBuilder;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.path.performance.PathPropertiesBuilder;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.path.performance.path.properties.PathMetric;
import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.path.performance.path.properties.PathMetricBuilder;
import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.RpcStatusEx;
import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.ServicePathNotificationTypes;
import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.response.parameters.sp.ResponseParametersBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.handler.header.ServiceHandlerHeaderBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
});
}
+ @Override
+ public ListenableFuture<PathComputationRerouteRequestOutput> pathComputationRerouteRequest(
+ PathComputationRerouteRequestInput input) {
+ return executor.submit(() -> {
+ PathComputationRerouteRequestOutputBuilder output = new PathComputationRerouteRequestOutputBuilder();
+ ConfigurationResponseCommonBuilder configurationResponseCommon = new ConfigurationResponseCommonBuilder()
+ .setRequestId("none");
+ PceComplianceCheckResult check = PceComplianceCheck.check(input);
+ if (!check.hasPassed()) {
+ LOG.error("Path not calculated, path computation reroute request not compliant : {}",
+ check.getMessage());
+ configurationResponseCommon
+ .setAckFinalIndicator("Yes")
+ .setResponseCode("Path not calculated")
+ .setResponseMessage(check.getMessage());
+ return output
+ .setConfigurationResponseCommon(configurationResponseCommon.build())
+ .build();
+ }
+ PathComputationRequestInput pathComputationInput = new PathComputationRequestInputBuilder()
+ .setServiceName("no_name")
+ .setServiceHandlerHeader(new ServiceHandlerHeaderBuilder().setRequestId("none").build())
+ .setServiceAEnd(new ServiceAEndBuilder(input.getServiceAEnd()).build())
+ .setServiceZEnd(new ServiceZEndBuilder(input.getServiceZEnd()).build())
+ .setHardConstraints(input.getHardConstraints())
+ .setPceRoutingMetric(input.getPceRoutingMetric())
+ .setResourceReserve(false)
+ .setSoftConstraints(input.getSoftConstraints())
+ .setRoutingMetric(input.getRoutingMetric())
+ .build();
+ PceSendingPceRPCs sendingPCE = new PceSendingPceRPCs(pathComputationInput, networkTransactionService,
+ gnpyConsumer, portMapping, input.getEndpoints());
+ sendingPCE.pathComputation();
+ String message = sendingPCE.getMessage();
+ String responseCode = sendingPCE.getResponseCode();
+ LOG.info("PCE response: {} {}", message, responseCode);
+ return output.setConfigurationResponseCommon(
+ configurationResponseCommon
+ .setAckFinalIndicator("Yes")
+ .setResponseCode(responseCode)
+ .setResponseMessage(message)
+ .build())
+ .build();
+ });
+ }
+
public GnpyResponse generateGnpyResponse(Response responseGnpy, String pathDir) {
if (responseGnpy == null) {
return new GnpyResponseBuilder()
.build();
}
+ public static org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808
+ .path.computation.reroute.request.input.ServiceAEnd createServiceAEndReroute(ServiceEndpoint serviceAEnd) {
+ return new org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808
+ .path.computation.reroute.request.input.ServiceAEndBuilder()
+ .setClli(serviceAEnd.getClli())
+ .setNodeId(serviceAEnd.getNodeId().getValue())
+ .setRxDirection(createRxDirection(serviceAEnd.getRxDirection().values().stream().findFirst().get()))
+ .setServiceFormat(serviceAEnd.getServiceFormat())
+ .setServiceRate(serviceAEnd.getServiceRate())
+ .setTxDirection(createTxDirection(serviceAEnd.getTxDirection().values().stream().findFirst().get()))
+ .build();
+ }
+
public static ServiceZEnd createServiceZEnd(ServiceEndpoint serviceZEnd) {
return new ServiceZEndBuilder()
.setClli(serviceZEnd.getClli())
.build();
}
+ public static org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808
+ .path.computation.reroute.request.input.ServiceZEnd createServiceZEndReroute(ServiceEndpoint serviceZEnd) {
+ return new org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808
+ .path.computation.reroute.request.input.ServiceZEndBuilder()
+ .setClli(serviceZEnd.getClli())
+ .setNodeId(serviceZEnd.getNodeId().getValue())
+ .setRxDirection(createRxDirection(serviceZEnd.getRxDirection().values().stream().findFirst().get()))
+ .setServiceFormat(serviceZEnd.getServiceFormat())
+ .setServiceRate(serviceZEnd.getServiceRate())
+ .setTxDirection(createTxDirection(serviceZEnd.getTxDirection().values().stream().findFirst().get()))
+ .build();
+ }
+
public static RxDirection createRxDirection(
org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210
.service.endpoint.RxDirection rxDirection) {
*/
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;
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;
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;
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<>();
}
&& 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...");
&& 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()
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.
*
<argument ref="serviceHandlerImpl" />
<argument ref="serviceDatastoreOperation" />
<argument ref="notificationPublishService" />
+ <argument ref="pathComputationService" />
</bean>
<bean id="rendererListener" class="org.opendaylight.transportpce.servicehandler.listeners.RendererListenerImpl">
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.mdsal.binding.api.NotificationPublishService;
import org.opendaylight.transportpce.common.ResponseCodes;
+import org.opendaylight.transportpce.pce.service.PathComputationService;
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;
private ServiceDataStoreOperations serviceDataStoreOperations;
@Mock
private NotificationPublishService notificationPublishService;
+ @Mock
+ private PathComputationService pathComputationService;
@Test
public void testOnDataTreeChangedWhenDeleteService() {
when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
- notificationPublishService);
+ notificationPublishService, pathComputationService);
listener.onDataTreeChanged(changes);
verify(ch, times(1)).getRootNode();
verify(service, times(1)).getModificationType();
when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
when(service.getDataAfter()).thenReturn(serviceDown);
ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
- notificationPublishService);
+ notificationPublishService, pathComputationService);
listener.onDataTreeChanged(changes);
verify(ch, times(1)).getRootNode();
verify(service, times(1)).getModificationType();
when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
- notificationPublishService);
+ notificationPublishService, pathComputationService);
listener.onDataTreeChanged(changes);
verify(ch, times(1)).getRootNode();
verify(service, times(2)).getModificationType();
.build())
.build())
.buildFuture());
- ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
- notificationPublishService);
+ ServiceListener listener = Mockito.spy(new ServiceListener(servicehandler, serviceDataStoreOperations,
+ notificationPublishService, pathComputationService));
+ Mockito.doReturn(true).when(listener).serviceRerouteCheck(any());
+
listener.onDataTreeChanged(changes);
verify(ch, times(1)).getRootNode();
verify(service, times(1)).getModificationType();
when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
when(service.getDataAfter()).thenReturn(serviceAfter);
ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
- notificationPublishService);
+ notificationPublishService, pathComputationService);
listener.onDataTreeChanged(changes);
verify(ch, times(1)).getRootNode();
verify(service, times(1)).getModificationType();