X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=renderer%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Ftransportpce%2Frenderer%2Fprovisiondevice%2FRendererServiceOperationsImpl.java;h=a9fd162b0d9c244417ea59362abfaab771403894;hb=b5ee86a522ce3cf5c6216f10647edb08b31c72e9;hp=a8052aa607a0c85fcdc5db192de5bbcb559dfbf4;hpb=0e8ce89d9db4a8e996dfed2918639b0870264a7f;p=transportpce.git diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImpl.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImpl.java index a8052aa60..a9fd162b0 100644 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImpl.java +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImpl.java @@ -7,69 +7,91 @@ */ package org.opendaylight.transportpce.renderer.provisiondevice; -import com.google.common.base.Optional; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; - import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.transportpce.common.OperationResult; +import java.util.stream.Collectors; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.NotificationPublishService; +import org.opendaylight.mdsal.binding.api.ReadTransaction; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.transportpce.common.ResponseCodes; import org.opendaylight.transportpce.common.StringConstants; import org.opendaylight.transportpce.common.Timeouts; +import org.opendaylight.transportpce.common.mapping.PortMapping; +import org.opendaylight.transportpce.common.service.ServiceTypes; import org.opendaylight.transportpce.renderer.ModelMappingUtils; -import org.opendaylight.transportpce.renderer.NetworkModelWavelengthService; import org.opendaylight.transportpce.renderer.ServicePathInputData; import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection; import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingRollbackTask; import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingTask; import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupRollbackTask; import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupTask; +import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OtnDeviceRenderingTask; import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.GetPmInputBuilder; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.GetPmOutput; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerSetupInput; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerTurndownInputBuilder; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerTurndownOutput; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.TransportpceOlmService; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.get.pm.output.Measurements; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev171017.ServiceDeleteInput; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev171017.ServiceDeleteOutput; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev171017.ServiceImplementationRequestInput; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev171017.ServiceImplementationRequestOutput; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev171017.ServiceRpcResultSp; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev171017.ServiceRpcResultSpBuilder; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.Action; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathInput; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmInputBuilder; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmOutput; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerSetupInput; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownInputBuilder; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownOutput; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.TransportpceOlmService; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.get.pm.output.Measurements; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mapping.Mapping; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.RendererRpcResultSp; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.RendererRpcResultSpBuilder; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteInput; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteOutput; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestInput; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestOutput; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ATerminationBuilder; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ZTerminationBuilder; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.Link; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.LinkBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes; import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity; import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum; -import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev171016.RpcStatusEx; -import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev171016.ServicePathNotificationTypes; -import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev171016.service.path.PathDescription; +import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat; +import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.PathDescription; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.ServicePathNotificationTypes; import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList; 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.ServicePathsKey; -import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.get.pm.input.ResourceIdentifierBuilder; -import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.renderer.input.Nodes; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTp; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.olm.get.pm.input.ResourceIdentifierBuilder; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.optical.renderer.nodes.Nodes; +import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev210511.OtnLinkType; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.Notification; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.Uint32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RendererServiceOperationsImpl implements RendererServiceOperations { + private static final String DEVICE_RENDERING_ROLL_BACK_MSG = + "Device rendering was not successful! Rendering will be rolled back."; + private static final String OLM_ROLL_BACK_MSG = + "OLM power setup was not successful! Rendering and OLM will be rolled back."; + private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z"; + private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A"; + private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path"; private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class); private static final String FAILED = "Failed"; private static final String OPERATION_FAILED = "Operation Failed"; @@ -77,217 +99,199 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations private static final int NUMBER_OF_THREADS = 4; private final DeviceRendererService deviceRenderer; + private final OtnDeviceRendererService otnDeviceRenderer; private final TransportpceOlmService olmService; private final DataBroker dataBroker; private final NotificationPublishService notificationPublishService; + private final PortMapping portMapping; private ListeningExecutorService executor; - private NetworkModelWavelengthService networkModelWavelengthService; - private ServiceRpcResultSp notification = null; - public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer, TransportpceOlmService olmService, - DataBroker dataBroker, NetworkModelWavelengthService networkModelWavelengthService, - NotificationPublishService notificationPublishService) { + public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer, + OtnDeviceRendererService otnDeviceRenderer, TransportpceOlmService olmService, + DataBroker dataBroker, NotificationPublishService notificationPublishService, PortMapping portMapping) { this.deviceRenderer = deviceRenderer; + this.otnDeviceRenderer = otnDeviceRenderer; this.olmService = olmService; this.dataBroker = dataBroker; - this.networkModelWavelengthService = networkModelWavelengthService; this.notificationPublishService = notificationPublishService; + this.portMapping = portMapping; this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS)); } - private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName, - RpcStatusEx rpcStatusEx, String message) { - this.notification = new ServiceRpcResultSpBuilder() - .setNotificationType(servicePathNotificationTypes) - .setServiceName(serviceName) - .setStatus(rpcStatusEx) - .setStatusMessage(message) - .build(); - try { - notificationPublishService.putNotification(this.notification); - } catch (InterruptedException e) { - LOG.info("notification offer rejected : ", e.getMessage()); - } - } - @Override public ListenableFuture serviceImplementation(ServiceImplementationRequestInput input) { - LOG.info("Calling service impl request {} {}", input.getServiceName()); + LOG.info("Calling service impl request {}", input.getServiceName()); return executor.submit(new Callable() { @Override public ServiceImplementationRequestOutput call() throws Exception { sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(), RpcStatusEx.Pending, "Service compliant, submitting service implementation Request ..."); - RollbackProcessor rollbackProcessor = new RollbackProcessor(); - ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils - .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription()); - ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils - .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription()); - List renderingResults = - deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA); - if (rollbackProcessor.rollbackAllIfNecessary() > 0) { - sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(), - RpcStatusEx.Failed, "Device rendering was not successful! Rendering will be rolled back."); - return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); - } - ServicePowerSetupInput olmPowerSetupInputAtoZ = - ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input); - ServicePowerSetupInput olmPowerSetupInputZtoA = - ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input); - olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA); - if (rollbackProcessor.rollbackAllIfNecessary() > 0) { - sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(), - RpcStatusEx.Failed, - "OLM power setup was not successful! Rendering and OLM will be rolled back."); - return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); - } - // run service activation test twice - once on source node and once on - // destination node - List nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes(); - Nodes sourceNode = nodes.get(0); - Nodes destNode = nodes.get(nodes.size() - 1); - String srcNetworkTp; - String dstNetowrkTp; - if (sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) { - srcNetworkTp = sourceNode.getDestTp(); - } else { - srcNetworkTp = sourceNode.getSrcTp(); - } - if (destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) { - dstNetowrkTp = destNode.getDestTp(); - } else { - dstNetowrkTp = destNode.getSrcTp(); - } - if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp) - || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) { - rollbackProcessor.rollbackAll(); - sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(), - RpcStatusEx.Failed, "Service activation test failed."); - return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); + Uint32 serviceRate = getServiceRate(input); + String serviceType = ServiceTypes.getServiceType( + input.getServiceAEnd().getServiceFormat().getName(), + serviceRate, + (NodeTypes.Xpdr.equals(portMapping.getNode(input.getServiceAEnd().getNodeId()) + .getNodeInfo().getNodeType()) + && input.getServiceAEnd().getTxDirection() != null + && input.getServiceAEnd().getTxDirection().getPort() != null + && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null) + ? portMapping.getMapping(input.getServiceAEnd().getNodeId(), + input.getServiceAEnd().getTxDirection().getPort().getPortName()) + : null); + + switch (serviceType) { + case StringConstants.SERVICE_TYPE_100GE_T: + case StringConstants.SERVICE_TYPE_400GE: + case StringConstants.SERVICE_TYPE_OTU4: + case StringConstants.SERVICE_TYPE_OTUC4: + if (!manageServicePathCreation(input, serviceType)) { + return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, + OPERATION_FAILED); + } + break; + case StringConstants.SERVICE_TYPE_1GE: + case StringConstants.SERVICE_TYPE_10GE: + case StringConstants.SERVICE_TYPE_100GE_M: + case StringConstants.SERVICE_TYPE_100GE_S: + case StringConstants.SERVICE_TYPE_ODU4: + case StringConstants.SERVICE_TYPE_ODUC4: + if (!manageOtnServicePathCreation(input, serviceType, serviceRate)) { + return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, + OPERATION_FAILED); + } + break; + default: + LOG.error("unsupported service-type"); + return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, + OPERATION_FAILED); } - // If Service activation is success update Network ModelMappingUtils - networkModelWavelengthService.useWavelengths(input.getPathDescription()); - sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(), - RpcStatusEx.Successful, OPERATION_SUCCESSFUL); - return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL); + return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK, + OPERATION_SUCCESSFUL); } }); - - } - - @SuppressWarnings("checkstyle:IllegalCatch") - public OperationResult reserveResource(PathDescription pathDescription) { - - try { - LOG.info("Reserving resources in network model"); - networkModelWavelengthService.useWavelengths(pathDescription); - } catch (Exception e) { - LOG.warn("Reserving resources in network model failed"); - return OperationResult.failed("Resources reserve failed in network model"); - } - return OperationResult.ok("Resources reserved successfully in network model"); - } - - @SuppressWarnings("checkstyle:IllegalCatch") - public OperationResult freeResource(PathDescription pathDescription) { - - try { - networkModelWavelengthService.freeWavelengths(pathDescription); - } catch (Exception e) { - return OperationResult.failed("Resources reserve failed in network model"); - } - return OperationResult.ok("Resources reserved successfully in network model"); } @Override - public ListenableFuture serviceDelete(ServiceDeleteInput input) { + public ListenableFuture serviceDelete(ServiceDeleteInput input, Services service) { String serviceName = input.getServiceName(); - LOG.info("Calling service delete request {} {}", input.getServiceName()); + LOG.info("Calling service delete request {}", serviceName); return executor.submit(new Callable() { @Override public ServiceDeleteOutput call() throws Exception { - sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(), + sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending, "Service compliant, submitting service delete Request ..."); // Obtain path description - Optional pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName); - PathDescription pathDescription; - if (pathDescriptionOpt.isPresent()) { - pathDescription = pathDescriptionOpt.get(); - } else { + Optional< + org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service + .path.PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName); + if (pathDescriptionOpt.isEmpty()) { LOG.error("Unable to get path description for service {}!", serviceName); - sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(), + sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed, "Unable to get path description for service"); return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); } - ServicePathInputData servicePathInputDataAtoZ = - ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription); - ServicePathInputData servicePathInputDataZtoA = - ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription); - // OLM turn down power - try { - LOG.debug("Turning down power on A-to-Z path"); - sendNotifications(ServicePathNotificationTypes.ServiceDelete, - input.getServiceName(), RpcStatusEx.Pending, "Turning down power on A-to-Z path"); - ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ); - // TODO add some flag rather than string - if (FAILED.equals(atozPowerTurndownOutput.getResult())) { - LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName); - sendNotifications(ServicePathNotificationTypes.ServiceDelete, - input.getServiceName(), RpcStatusEx.Failed, - "Service power turndown failed on A-to-Z path for service"); - return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, + PathDescription pathDescription = pathDescriptionOpt.get(); + Mapping mapping = portMapping.getMapping(service.getServiceAEnd().getNodeId().getValue(), + service.getServiceAEnd().getTxDirection().getPort().getPortName()); + String serviceType = ServiceTypes.getServiceType(service.getServiceAEnd().getServiceFormat().getName(), + service.getServiceAEnd().getServiceRate(), mapping); + switch (serviceType) { + case StringConstants.SERVICE_TYPE_100GE_T: + case StringConstants.SERVICE_TYPE_400GE: + case StringConstants.SERVICE_TYPE_OTU4: + case StringConstants.SERVICE_TYPE_OTUC4: + if (!manageServicePathDeletion(serviceName, pathDescription, serviceType)) { + return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); - } - LOG.debug("Turning down power on Z-to-A path"); - sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(), - RpcStatusEx.Pending, "Turning down power on Z-to-A path"); - ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA); - // TODO add some flag rather than string - if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) { - LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName); - sendNotifications(ServicePathNotificationTypes.ServiceDelete, - input.getServiceName(), RpcStatusEx.Failed, - "Service power turndown failed on Z-to-A path for service"); - return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, + } + break; + case StringConstants.SERVICE_TYPE_1GE: + case StringConstants.SERVICE_TYPE_10GE: + case StringConstants.SERVICE_TYPE_100GE_M: + case StringConstants.SERVICE_TYPE_100GE_S: + case StringConstants.SERVICE_TYPE_ODU4: + case StringConstants.SERVICE_TYPE_ODUC4: + if (!manageOtnServicePathDeletion(serviceName, pathDescription, service, serviceType)) { + return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); - } - } catch (InterruptedException | ExecutionException | TimeoutException e) { - LOG.error("Error while turning down power!", e); - return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, + } + break; + default: + LOG.error("unsupported service-type"); + return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); } - // delete service path with renderer - LOG.debug("Deleting service path via renderer"); - sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(), - RpcStatusEx.Pending, "Deleting service path via renderer"); - deviceRenderer.deleteServicePath(servicePathInputDataAtoZ.getServicePathInput()); - deviceRenderer.deleteServicePath(servicePathInputDataZtoA.getServicePathInput()); - networkModelWavelengthService.freeWavelengths(pathDescription); - sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(), - RpcStatusEx.Successful, OPERATION_SUCCESSFUL); return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL); } }); + } - + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "call in call() method") + private Uint32 getServiceRate(ServiceImplementationRequestInput input) { + if (input.getServiceAEnd() == null) { + LOG.warn("Unable to get service-rate for service {}", input.getServiceName()); + return Uint32.ZERO; + } + if (input.getServiceAEnd().getServiceRate() != null) { + return input.getServiceAEnd().getServiceRate(); + } + Map> formatRateMap = Map.of( + ServiceFormat.OTU, Map.of( + "OTUCn", Uint32.valueOf(400), + "OTU4", Uint32.valueOf(100), + "OTU2", Uint32.valueOf(10), + "OTU2e", Uint32.valueOf(10)), + ServiceFormat.ODU, Map.of( + "ODUCn",Uint32.valueOf(400), + "ODU4", Uint32.valueOf(100), + "ODU2", Uint32.valueOf(10), + "ODU2e", Uint32.valueOf(10), + "ODU0", Uint32.valueOf(1))); + if (!formatRateMap.containsKey(input.getServiceAEnd().getServiceFormat())) { + LOG.warn("Unable to get service-rate for service {} - unsupported service format {}", + input.getServiceName(), input.getServiceAEnd().getServiceFormat()); + return Uint32.ZERO; + } + String serviceName = + ServiceFormat.OTU.equals(input.getServiceAEnd().getServiceFormat()) + ? input.getServiceAEnd().getOtuServiceRate().getSimpleName() + : input.getServiceAEnd().getOduServiceRate().getSimpleName(); + if (!formatRateMap.get(input.getServiceAEnd().getServiceFormat()).containsKey(serviceName)) { + LOG.warn("Unable to get service-rate for service {} - unsupported service name {}", + input.getServiceName(), serviceName); + return Uint32.ZERO; + } + return formatRateMap.get(input.getServiceAEnd().getServiceFormat()).get(serviceName); } + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "call in call() method") private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData) throws InterruptedException, ExecutionException, TimeoutException { - LOG.debug("Turning down power on A-to-Z path"); + LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG); Future> powerTurndownFuture = this.olmService.servicePowerTurndown( new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build()); return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult(); } - private Optional getPathDescriptionFromDatastore(String serviceName) { - InstanceIdentifier pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class) - .child(ServicePaths.class, new ServicePathsKey(serviceName)).child(PathDescription.class); - ReadOnlyTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction(); + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "call in call() method") + private Optional getPathDescriptionFromDatastore(String serviceName) { + InstanceIdentifier pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class) + .child(ServicePaths.class, new ServicePathsKey(serviceName)) + .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128 + .service.path.PathDescription.class); + ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction(); try { LOG.debug("Getting path description for service {}", serviceName); return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID) @@ -295,24 +299,27 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations } catch (InterruptedException | ExecutionException | TimeoutException e) { LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID, serviceName, e); - return Optional.absent(); + return Optional.empty(); } } + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "call in call() method") private List deviceRendering(RollbackProcessor rollbackProcessor, ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) { - LOG.info("Rendering devices A-Z"); + LOG.info(RENDERING_DEVICES_A_Z_MSG); sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending, - "Rendering devices A-Z"); + RENDERING_DEVICES_A_Z_MSG); ListenableFuture atozrenderingFuture = this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ, ServicePathDirection.A_TO_Z)); LOG.info("Rendering devices Z-A"); sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, - servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending, - "Rendering devices A-Z"); + servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending, + RENDERING_DEVICES_Z_A_MSG); ListenableFuture ztoarenderingFuture = this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA, ServicePathDirection.Z_TO_A)); @@ -324,10 +331,10 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations LOG.info("Waiting for A-Z and Z-A device renderers ..."); renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { - LOG.warn("Device rendering was not successful! Rendering will be rolled back.", e); + LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e); sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending, - "Device rendering was not successful! Rendering will be rolled back."); + DEVICE_RENDERING_ROLL_BACK_MSG); //FIXME we can't do rollback here, because we don't have rendering results. return renderingResults; } @@ -341,6 +348,48 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations return renderingResults; } + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "call in call() method") + private List otnDeviceRendering(RollbackProcessor rollbackProcessor, + OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA, String serviceType) { + LOG.info(RENDERING_DEVICES_A_Z_MSG); + sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, + otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending, + RENDERING_DEVICES_A_Z_MSG); + ListenableFuture atozrenderingFuture = + this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ, serviceType)); + LOG.info(RENDERING_DEVICES_Z_A_MSG); + sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, + otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending, + RENDERING_DEVICES_Z_A_MSG); + ListenableFuture ztoarenderingFuture = + this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA, serviceType)); + ListenableFuture> renderingCombinedFuture = + Futures.allAsList(atozrenderingFuture, ztoarenderingFuture); + List otnRenderingResults = new ArrayList<>(2); + try { + LOG.info("Waiting for A-Z and Z-A device renderers ..."); + otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e); + sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, + otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending, + DEVICE_RENDERING_ROLL_BACK_MSG); + //FIXME we can't do rollback here, because we don't have rendering results. + return otnRenderingResults; + } + for (int i = 0; i < otnRenderingResults.size(); i++) { + rollbackProcessor.addTask(new DeviceRenderingRollbackTask("DeviceTask n° " + i + 1, + ! otnRenderingResults.get(i).isSuccess(), otnRenderingResults.get(i).getRenderedNodeInterfaces(), + this.deviceRenderer)); + } + return otnRenderingResults; + } + + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "call in call() method") private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ, ServicePowerSetupInput powerSetupInputZtoA) { LOG.info("Olm power setup A-Z"); @@ -362,10 +411,10 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations LOG.info("Waiting for A-Z and Z-A OLM power setup ..."); olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { - LOG.warn("OLM power setup was not successful! Rendering and OLM will be rolled back.", e); + LOG.warn(OLM_ROLL_BACK_MSG, e); sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, - "OLM power setup was not successful! Rendering and OLM will be rolled back."); + OLM_ROLL_BACK_MSG); rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true, this.olmService, powerSetupInputAtoZ)); rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true, @@ -379,21 +428,24 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations this.olmService, powerSetupInputZtoA)); } + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "call in call() method") private boolean isServiceActivated(String nodeId, String tpId) { LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId); for (int i = 0; i < 3; i++) { List measurements = getMeasurements(nodeId, tpId); - if ((measurements != null) && verifyPreFecBer(measurements)) { - return true; - } else if (measurements == null) { + if (measurements == null) { LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId); return true; - } else { - try { - Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } + } + if (verifyPreFecBer(measurements)) { + return true; + } + try { + Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); } } LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId); @@ -401,13 +453,11 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations } private List getMeasurements(String nodeId, String tp) { - GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder(); - getPmIpBldr.setNodeId(nodeId); - getPmIpBldr.setGranularity(PmGranularity._15min); - ResourceIdentifierBuilder rsrcBldr = new ResourceIdentifierBuilder(); - rsrcBldr.setResourceName(tp + "-OTU"); - getPmIpBldr.setResourceIdentifier(rsrcBldr.build()); - getPmIpBldr.setResourceType(ResourceTypeEnum.Interface); + GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder() + .setNodeId(nodeId) + .setGranularity(PmGranularity._15min) + .setResourceIdentifier(new ResourceIdentifierBuilder().setResourceName(tp + "-OTU").build()) + .setResourceType(ResourceTypeEnum.Interface); try { Future> getPmFuture = this.olmService.getPm(getPmIpBldr.build()); @@ -415,7 +465,8 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations GetPmOutput getPmOutput = getPmRpcResult.getResult(); if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) { LOG.info("successfully finished calling OLM's get PM"); - return getPmOutput.getMeasurements(); // may return null + return getPmOutput.getMeasurements(); + // may return null } else { LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp); } @@ -426,17 +477,20 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations return null; } - private boolean verifyPreFecBer(List measurements) { double preFecCorrectedErrors = Double.MIN_VALUE; double fecUncorrectableBlocks = Double.MIN_VALUE; for (Measurements measurement : measurements) { - if (measurement.getPmparameterName().equals("preFECCorrectedErrors")) { - preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue()); - } - if (measurement.getPmparameterName().equals("FECUncorrectableBlocks")) { - fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue()); + switch (measurement.getPmparameterName()) { + case "preFECCorrectedErrors": + preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue()); + break; + case "FECUncorrectableBlocks": + fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue()); + break; + default: + break; } } @@ -446,13 +500,319 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations if (fecUncorrectableBlocks > Double.MIN_VALUE) { LOG.error("Data has uncorrectable errors, BER test failed"); return false; - } else { - double numOfBitsPerSecond = 112000000000d; - double threshold = 0.00002d; - double result = preFecCorrectedErrors / numOfBitsPerSecond; - LOG.info("PreFEC value is {}", Double.toString(result)); - return result <= threshold; } + + double numOfBitsPerSecond = 112000000000d; + double threshold = 0.00002d; + double result = preFecCorrectedErrors / numOfBitsPerSecond; + LOG.info("PreFEC value is {}", Double.toString(result)); + return result <= threshold; } + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "call in call() method") + private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType) { + ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils + .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create); + ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils + .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create); + // Rollback should be same for all conditions, so creating a new one + RollbackProcessor rollbackProcessor = new RollbackProcessor(); + List renderingResults = + deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA); + if (rollbackProcessor.rollbackAllIfNecessary() > 0) { + sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, + input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG); + return false; + } + ServicePowerSetupInput olmPowerSetupInputAtoZ = + ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input); + ServicePowerSetupInput olmPowerSetupInputZtoA = + ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input); + olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA); + if (rollbackProcessor.rollbackAllIfNecessary() > 0) { + sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, + input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG); + return false; + } + // run service activation test twice - once on source node and once on + // destination node + List nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes(); + if ((nodes == null) || (nodes.isEmpty())) { + return false; + } + + Nodes sourceNode = nodes.get(0); + Nodes destNode = nodes.get(nodes.size() - 1); + String srcNetworkTp = + sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN) + ? sourceNode.getDestTp() + : sourceNode.getSrcTp(); + String dstNetowrkTp = + destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN) + ? destNode.getDestTp() + : destNode.getSrcTp(); + + if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp) + || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) { + rollbackProcessor.rollbackAll(); + sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, + input.getServiceName(), RpcStatusEx.Failed, + "Service activation test failed."); + return false; + } + List otnLinkTerminationPoints = new ArrayList<>(); + renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps())); + Link notifLink = createLinkForNotif(otnLinkTerminationPoints); + + sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest, + input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(), + notifLink, null, serviceType); + return true; + } + + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "call in call() method") + private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType) + throws InterruptedException { + ServicePathInputData servicePathInputDataAtoZ = + ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete); + ServicePathInputData servicePathInputDataZtoA = + ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete); + // OLM turn down power + try { + LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG); + sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, + RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG); + ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ); + // TODO add some flag rather than string + if (FAILED.equals(atozPowerTurndownOutput.getResult())) { + LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName); + sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed, + "Service power turndown failed on A-to-Z path for service"); + return false; + } + LOG.debug("Turning down power on Z-to-A path"); + sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending, + "Turning down power on Z-to-A path"); + ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA); + // TODO add some flag rather than string + if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) { + LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName); + sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed, + "Service power turndown failed on Z-to-A path for service"); + return false; + } + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.error("Error while turning down power!", e); + return false; + } + // delete service path with renderer + LOG.info("Deleting service path via renderer"); + sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending, + "Deleting service path via renderer"); + RollbackProcessor rollbackProcessor = new RollbackProcessor(); + List renderingResults = + deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA); + List otnLinkTerminationPoints = new ArrayList<>(); + renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps())); + Link notifLink = createLinkForNotif(otnLinkTerminationPoints); + + sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete, + serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, null, serviceType); + return true; + } + + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "call in call() method") + private boolean manageOtnServicePathCreation(ServiceImplementationRequestInput input, String serviceType, + Uint32 serviceRate) { + // This is A-Z side + OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils + .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create, + input.getServiceAEnd().getServiceFormat().getName(), + serviceRate, + input.getPathDescription(), true); + // This is Z-A side + OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils + .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create, + input.getServiceZEnd().getServiceFormat().getName(), + serviceRate, + input.getPathDescription(), false); + // Rollback should be same for all conditions, so creating a new one + RollbackProcessor rollbackProcessor = new RollbackProcessor(); + List renderingResults = + otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA, serviceType); + if (rollbackProcessor.rollbackAllIfNecessary() > 0) { + rollbackProcessor.rollbackAll(); + sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, + input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG); + return false; + } + List otnLinkTerminationPoints = new ArrayList<>(); + renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps())); + Link notifLink = createLinkForNotif(otnLinkTerminationPoints); + List allSupportLinks = ModelMappingUtils.getLinksFromServicePathDescription(input.getPathDescription()); + List supportedLinks = null; + switch (serviceType) { + case StringConstants.SERVICE_TYPE_ODU4: + case StringConstants.SERVICE_TYPE_100GE_S: + supportedLinks = allSupportLinks.stream() + .filter(lk -> lk.startsWith(OtnLinkType.OTU4.getName())).collect(Collectors.toList()); + break; + case StringConstants.SERVICE_TYPE_ODUC4: + supportedLinks = allSupportLinks.stream() + .filter(lk -> lk.startsWith(OtnLinkType.OTUC4.getName())).collect(Collectors.toList()); + break; + default: + break; + } + + sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest, + input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(), + notifLink, supportedLinks, serviceType); + return true; + } + + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "call in call() method") + private boolean manageOtnServicePathDeletion(String serviceName, PathDescription pathDescription, + Services service, String serviceType) { + // This is A-Z side + OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils + .rendererCreateOtnServiceInput(serviceName, Action.Delete, + service.getServiceAEnd().getServiceFormat().getName(), + service.getServiceAEnd().getServiceRate(), + pathDescription, true); + // This is Z-A side + OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils + .rendererCreateOtnServiceInput(serviceName, Action.Delete, + service.getServiceZEnd().getServiceFormat().getName(), + service.getServiceAEnd().getServiceRate(), + pathDescription, false); + LOG.info("Deleting otn-service path {} via renderer", serviceName); + sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending, + "Deleting otn-service path via renderer"); + + RollbackProcessor rollbackProcessor = new RollbackProcessor(); + List renderingResults = + otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA, serviceType); + + List otnLinkTerminationPoints = new ArrayList<>(); + renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps())); + Link notifLink = createLinkForNotif(otnLinkTerminationPoints); + List allSupportLinks = ModelMappingUtils.getLinksFromServicePathDescription(pathDescription); + List supportedLinks = null; + switch (serviceType) { + case StringConstants.SERVICE_TYPE_ODU4: + case StringConstants.SERVICE_TYPE_100GE_S: + supportedLinks = allSupportLinks.stream() + .filter(lk -> lk.startsWith(OtnLinkType.OTU4.getName())).collect(Collectors.toList()); + break; + case StringConstants.SERVICE_TYPE_ODUC4: + supportedLinks = allSupportLinks.stream() + .filter(lk -> lk.startsWith(OtnLinkType.OTUC4.getName())).collect(Collectors.toList()); + break; + default: + break; + } + + sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete, + serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, supportedLinks, + serviceType); + return true; + } + + /** + * Send renderer notification. + * @param servicePathNotificationTypes ServicePathNotificationTypes + * @param serviceName String + * @param rpcStatusEx RpcStatusEx + * @param message String + */ + private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName, + RpcStatusEx rpcStatusEx, String message) { + Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message, + null, null, null, null); + send(notification); + } + + /** + * Send renderer notification with path description information. + * @param servicePathNotificationTypes ServicePathNotificationTypes + * @param serviceName String + * @param rpcStatusEx RpcStatusEx + * @param message String + * @param pathDescription PathDescription + */ + private void sendNotificationsWithPathDescription(ServicePathNotificationTypes servicePathNotificationTypes, + String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription, + Link notifLink, List supportedLinks, String serviceType) { + Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message, + pathDescription, notifLink, supportedLinks, serviceType); + send(notification); + } + + /** + * Build notification containing path description information. + * @param servicePathNotificationTypes ServicePathNotificationTypes + * @param serviceName String + * @param rpcStatusEx RpcStatusEx + * @param message String + * @param pathDescription PathDescription + * @return notification with RendererRpcResultSp type. + */ + private RendererRpcResultSp buildNotification(ServicePathNotificationTypes servicePathNotificationTypes, + String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription, + Link notifLink, List supportedLinks, String serviceType) { + RendererRpcResultSpBuilder builder = new RendererRpcResultSpBuilder() + .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx) + .setStatusMessage(message) + .setServiceType(serviceType); + if (pathDescription != null) { + builder.setAToZDirection(pathDescription.getAToZDirection()) + .setZToADirection(pathDescription.getZToADirection()); + } + if (notifLink != null) { + builder.setLink(notifLink); + } + if (supportedLinks != null) { + builder.setLinkId(supportedLinks); + } + return builder.build(); + } + + /** + * Send renderer notification. + * @param notification Notification + */ + private void send(Notification notification) { + try { + LOG.info("Sending notification {}", notification); + notificationPublishService.putNotification(notification); + } catch (InterruptedException e) { + LOG.info("notification offer rejected: ", e); + Thread.currentThread().interrupt(); + } + } + + private Link createLinkForNotif(List otnLinkTerminationPoints) { + if (otnLinkTerminationPoints == null || otnLinkTerminationPoints.size() != 2) { + return null; + } + return new LinkBuilder() + .setATermination(new ATerminationBuilder() + .setNodeId(otnLinkTerminationPoints.get(0).getNodeId()) + .setTpId(otnLinkTerminationPoints.get(0).getTpId()) + .build()) + .setZTermination(new ZTerminationBuilder() + .setNodeId(otnLinkTerminationPoints.get(1).getNodeId()) + .setTpId(otnLinkTerminationPoints.get(1).getTpId()) + .build()) + .build(); + } }