Fix deprecated warnings caused by YangTools update
[transportpce.git] / renderer / src / main / java / org / opendaylight / transportpce / renderer / provisiondevice / RendererServiceOperationsImpl.java
index d116f6941739f794635a7dfe1967f26959b1e917..baa04add60517d236ce63724abad4a5e2d8252d6 100644 (file)
@@ -7,33 +7,37 @@
  */
 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.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.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.openroadminterfaces.OpenRoadmInterfacesImpl;
 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.device.renderer.rev200128.OtnServicePathInput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev200128.OtnServicePathOutput;
 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;
@@ -41,26 +45,44 @@ import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev17
 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.rev201125.RendererRpcResultSp;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.RendererRpcResultSpBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceDeleteInput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceDeleteOutput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceImplementationRequestInput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceImplementationRequestOutput;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ConnectionType;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODU4;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OTU4;
 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.rev170426.service.path.PathDescription;
-import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceDeleteInput;
-import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceDeleteOutput;
-import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestInput;
-import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestOutput;
-import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServicePathList;
-import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.service.path.list.ServicePaths;
-import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.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.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.rev201210.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.rev201211.olm.get.pm.input.ResourceIdentifierBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev201211.olm.renderer.input.Nodes;
 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";
@@ -68,140 +90,221 @@ 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 ListeningExecutorService executor;
-    private NetworkModelWavelengthService networkModelWavelengthService;
 
-    public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer, TransportpceOlmService olmService,
-            DataBroker dataBroker, NetworkModelWavelengthService networkModelWavelengthService) {
+    public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer,
+            OtnDeviceRendererService otnDeviceRenderer, TransportpceOlmService olmService,
+            DataBroker dataBroker, NotificationPublishService notificationPublishService) {
         this.deviceRenderer = deviceRenderer;
+        this.otnDeviceRenderer = otnDeviceRenderer;
         this.olmService = olmService;
         this.dataBroker = dataBroker;
-        this.networkModelWavelengthService = networkModelWavelengthService;
+        this.notificationPublishService = notificationPublishService;
         this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
     }
 
     @Override
-    public ServiceImplementationRequestOutput serviceImplementation(ServiceImplementationRequestInput input) {
-        LOG.info("Calling service impl request {} {}", input.getServiceName());
-        RollbackProcessor rollbackProcessor = new RollbackProcessor();
-
-        ServicePathInputData servicePathInputDataAtoZ
-                = ModelMappingUtils.rendererCreateServiceInputAToZ(input.getServiceName(),
-                        input.getPathDescription());
-        ServicePathInputData servicePathInputDataZtoA
-                = ModelMappingUtils.rendererCreateServiceInputZToA(input.getServiceName(),
+    public ListenableFuture<ServiceImplementationRequestOutput>
+            serviceImplementation(ServiceImplementationRequestInput input) {
+        LOG.info("Calling service impl request {}", input.getServiceName());
+        return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
+
+            @Override
+            public ServiceImplementationRequestOutput call() throws Exception {
+                sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(),
+                        RpcStatusEx.Pending, "Service compliant, submitting service implementation Request ...");
+                // Here is the switch statement that distinguishes on the connection-type
+                LOG.info("Connection-type is {} for {}", input.getConnectionType(), input.getServiceName());
+                switch (input.getConnectionType()) {
+                    case Service: case RoadmLine: // This takes into account of Ethernet 100G, 1G, 10G and ODU4
+                        LOG.info("RPC implementation for {}", input.getConnectionType());
+                        if (((input.getServiceAEnd().getServiceRate() != null)
+                            && (input.getServiceAEnd().getServiceRate().intValue() == 100))
+                            && ((input.getServiceAEnd().getServiceFormat().getName().equals("Ethernet"))
+                                || (input.getServiceAEnd().getServiceFormat().getName().equals("OC")))) {
+                            LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
+                                input.getServiceAEnd().getServiceFormat(), input.getServiceAEnd().getServiceRate());
+                            if (!createServicepathInput(input)) {
+                                return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
+                                    OPERATION_FAILED);
+                            }
+                        } else { // This implies, service-rate is 1 or 10G
+                            // This includes the lower-order odu (1G, 10G) and this is A-Z side
+                            LOG.info("RPC implementation for LO-ODU");
+                            String serviceRate = ""; // Assuming service at A-side and Z-side has same service rate
+                            if (input.getServiceAEnd().getServiceRate() != null) {
+                                serviceRate = input.getServiceAEnd().getServiceRate().toString() + "G";
+                            }
+                            LOG.info("Start rendering for {} service with {} rate and {} format",
+                                input.getServiceName(), serviceRate,
+                                input.getServiceAEnd().getServiceFormat());
+                            // This is A-Z side
+                            OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
+                                .rendererCreateOtnServiceInput(input.getServiceName(),
+                                    input.getServiceAEnd().getServiceFormat().getName(),
+                                    serviceRate, (PathDescription) input.getPathDescription(), true);
+                            // Rollback should be same for all conditions, so creating a new one
+                            RollbackProcessor rollbackProcessor = new RollbackProcessor();
+                            List<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
+                                otnServicePathInputAtoZ, null);
+                            if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
+                                sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
+                                    input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
+                                return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
+                                    OPERATION_FAILED);
+                            }
+                            LOG.info("OTN rendering result size {}", otnRenderingResults.size());
+                        }
+                        break;
+                    case Infrastructure:
+                        LOG.info("RPC implementation for {}", input.getConnectionType());
+                        if ((input.getServiceAEnd().getOtuServiceRate() != null)
+                            && (input.getServiceAEnd().getOtuServiceRate().equals(OTU4.class))) {
+                            // For the service of OTU4 infrastructure
+                            // First create the OCH and OTU interfaces
+                            String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
+                            if (!createServicepathInput(input)) {
+                                return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
+                                    OPERATION_FAILED);
+                            }
+                        }
+                        if ((input.getServiceAEnd().getOduServiceRate() != null)
+                            && (input.getServiceAEnd().getOduServiceRate().equals(ODU4.class))) {
+                            // For the service of OTU4 infrastructure
+                            String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
+                            LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
+                                input.getServiceAEnd().getOduServiceRate(), serviceRate);
+                            // Now start rendering ODU4 interface
+                            // This is A-Z side
+                            OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
+                                .rendererCreateOtnServiceInput(input.getServiceName(),
+                                    input.getServiceAEnd().getServiceFormat().getName(),
+                                    serviceRate,
+                                    input.getPathDescription(), true);
+                            // This is Z-A side
+                            OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
+                                .rendererCreateOtnServiceInput(input.getServiceName(),
+                                    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<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
+                                otnServicePathInputAtoZ, otnServicePathInputZtoA);
+                            if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
+                                sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
+                                    input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
+                                return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
+                                    OPERATION_FAILED);
+                            }
+                            LOG.info("OTN rendering result size {}", otnRenderingResults.size());
+                        }
+                        break;
+                    default:
+                        LOG.warn("Unsupported connection type {}", input.getConnectionType());
+                }
+                sendNotificationsWithPathDescription(
+                        ServicePathNotificationTypes.ServiceImplementationRequest,
+                        input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL,
                         input.getPathDescription());
-        List<DeviceRenderingResult> renderingResults = deviceRendering(rollbackProcessor, servicePathInputDataAtoZ,
-                servicePathInputDataZtoA);
-        if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
-            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) {
-            return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
-        }
-
-        // run service activation test twice - once on source node and once on destination node
-        List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
-        Nodes sourceNode = nodes.get(0);
-        Nodes destNode = nodes.get(nodes.size() - 1);
-
-        String srcNetworkTp;
-        String dstNetowrkTp;
-
-        if (sourceNode.getDestTp().contains(OpenRoadmInterfacesImpl.NETWORK_TOKEN)) {
-            srcNetworkTp = sourceNode.getDestTp();
-        } else {
-            srcNetworkTp = sourceNode.getSrcTp();
-        }
-        if (destNode.getDestTp().contains(OpenRoadmInterfacesImpl.NETWORK_TOKEN)) {
-            dstNetowrkTp = destNode.getDestTp();
-        } else {
-            dstNetowrkTp = destNode.getSrcTp();
-        }
-
-        if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
-                || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
-            rollbackProcessor.rollbackAll();
-            return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
-        }
-
-        //If Service activation is success update Network ModelMappingUtils
-        this.networkModelWavelengthService.useWavelengths(input.getPathDescription());
-
-        return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
+                return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
+                    OPERATION_SUCCESSFUL);
+            }
+        });
     }
 
     @Override
-    public ServiceDeleteOutput serviceDelete(ServiceDeleteInput input) {
+    public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
         String serviceName = input.getServiceName();
-
-        // Obtain path description
-        Optional<PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
-        PathDescription pathDescription;
-        if (pathDescriptionOpt.isPresent()) {
-            pathDescription = pathDescriptionOpt.get();
-        } else {
-            LOG.error("Unable to get path description for service {}!", serviceName);
-            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");
-            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);
-                return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
-            }
-
-            LOG.debug("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);
-                return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
+        LOG.info("Calling service delete request {}", serviceName);
+        return executor.submit(new Callable<ServiceDeleteOutput>() {
+
+            @Override
+            public ServiceDeleteOutput call() throws Exception {
+                sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
+                        RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
+                // Obtain path description
+                Optional<
+                    org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service
+                    .path.PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
+                PathDescription pathDescription;
+                if (pathDescriptionOpt.isPresent()) {
+                    pathDescription = pathDescriptionOpt.get();
+                } else {
+                    LOG.error("Unable to get path description for service {}!", serviceName);
+                    sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
+                            RpcStatusEx.Failed, "Unable to get path description for service");
+                    return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
+                            OPERATION_FAILED);
+                }
+                switch (service.getConnectionType()) {
+                    case RoadmLine:
+                    case Service:
+                        if ((ServiceFormat.Ethernet.equals(service.getServiceAEnd().getServiceFormat())
+                                || ServiceFormat.OC.equals(service.getServiceAEnd().getServiceFormat()))
+                            && Uint32.valueOf("100").equals(service.getServiceAEnd().getServiceRate())) {
+                            if (!manageServicePathDeletion(serviceName, pathDescription)) {
+                                return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
+                                    OPERATION_FAILED);
+                            }
+                        }
+                        if (ServiceFormat.Ethernet.equals(service.getServiceAEnd().getServiceFormat())
+                            && (Uint32.valueOf("10").equals(service.getServiceAEnd().getServiceRate())
+                                || Uint32.valueOf("1").equals(service.getServiceAEnd().getServiceRate()))) {
+                            if (!manageOtnServicePathDeletion(serviceName, pathDescription, service)) {
+                                return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
+                                    OPERATION_FAILED);
+                            }
+                        }
+                        break;
+                    case Infrastructure:
+                        if (ServiceFormat.OTU.equals(service.getServiceAEnd().getServiceFormat())) {
+                            if (!manageServicePathDeletion(serviceName, pathDescription)) {
+                                return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
+                                    OPERATION_FAILED);
+                            }
+                        } else if (ServiceFormat.ODU.equals(service.getServiceAEnd().getServiceFormat())) {
+                            if (!manageOtnServicePathDeletion(serviceName, pathDescription, service)) {
+                                return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
+                                    OPERATION_FAILED);
+                            }
+                        }
+                        break;
+                    default:
+                        LOG.error("Unmanaged connection-type for deletion of service {}", serviceName);
+                        break;
+                    }
+                return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
             }
-        } catch (InterruptedException | ExecutionException | TimeoutException e) {
-            LOG.error("Error while turning down power!", e);
-            return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
-        }
-
-        // delete service path with renderer
-        LOG.debug("Deleting service path via renderer");
-        this.deviceRenderer.deleteServicePath(servicePathInputDataAtoZ.getServicePathInput());
-        this.deviceRenderer.deleteServicePath(servicePathInputDataZtoA.getServicePathInput());
-
-        this.networkModelWavelengthService.freeWavelengths(pathDescription);
-
-        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 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<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
                 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
         return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
     }
 
-    private Optional<PathDescription> getPathDescriptionFromDatastore(String serviceName) {
-        InstanceIdentifier<PathDescription> 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<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
+        .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
+        InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
+            .service.path.PathDescription> 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)
@@ -209,18 +312,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<DeviceRenderingResult> 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_MSG);
         ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
                 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
                         ServicePathDirection.A_TO_Z));
 
         LOG.info("Rendering devices Z-A");
+        sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
+                servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
+                RENDERING_DEVICES_Z_A_MSG);
         ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
                 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
                         ServicePathDirection.Z_TO_A));
@@ -232,10 +344,11 @@ 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_ROLL_BACK_MSG);
             //FIXME we can't do rollback here, because we don't have rendering results.
-            //rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask", true));
-            //rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask", true));
             return renderingResults;
         }
 
@@ -248,13 +361,63 @@ 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<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
+        OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA) {
+        LOG.info(RENDERING_DEVICES_A_Z_MSG);
+        sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
+            otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
+            RENDERING_DEVICES_A_Z_MSG);
+        ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
+            this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ));
+        ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture;
+        if (otnServicePathZtoA != null) {
+            LOG.info("Rendering devices Z-A");
+            sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
+                otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
+                RENDERING_DEVICES_Z_A_MSG);
+            ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
+                this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA));
+            renderingCombinedFuture = Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
+        } else {
+            renderingCombinedFuture = Futures.allAsList(atozrenderingFuture);
+        }
+        List<OtnDeviceRenderingResult> 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");
+        sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
+                powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
         ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
                 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
 
         LOG.info("OLM power setup Z-A");
+        sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
+                powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
         ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
                 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
         ListenableFuture<List<OLMRenderingResult>> olmFutures =
@@ -265,7 +428,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_ROLL_BACK_MSG);
             rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
                     this.olmService, powerSetupInputAtoZ));
             rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
@@ -279,6 +445,9 @@ 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++) {
@@ -315,8 +484,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);
             }
@@ -327,7 +496,6 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations
         return null;
     }
 
-
     private boolean verifyPreFecBer(List<Measurements> measurements) {
         double preFecCorrectedErrors = Double.MIN_VALUE;
         double fecUncorrectableBlocks = Double.MIN_VALUE;
@@ -356,4 +524,203 @@ public class RendererServiceOperationsImpl implements RendererServiceOperations
         }
     }
 
+    @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
+        value = "UPM_UNCALLED_PRIVATE_METHOD",
+        justification = "call in call() method")
+    private boolean createServicepathInput(ServiceImplementationRequestInput input) {
+        ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
+            .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription());
+        ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
+            .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription());
+        // Rollback should be same for all conditions, so creating a new one
+        RollbackProcessor rollbackProcessor = new RollbackProcessor();
+        List<DeviceRenderingResult> 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> 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;
+        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 false;
+        }
+        sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
+            input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription());
+        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) {
+        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_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");
+        deviceRenderer.deleteServicePath(servicePathInputDataAtoZ.getServicePathInput());
+        deviceRenderer.deleteServicePath(servicePathInputDataZtoA.getServicePathInput());
+        sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
+                serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL,pathDescription);
+        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) {
+        OtnServicePathInput ospi = null;
+        if (ConnectionType.Infrastructure.equals(service.getConnectionType())) {
+            ospi = ModelMappingUtils.rendererCreateOtnServiceInput(
+                serviceName, service.getServiceAEnd().getServiceFormat().getName(), "100G", pathDescription, true);
+        } else if (ConnectionType.Service.equals(service.getConnectionType())) {
+            ospi = ModelMappingUtils.rendererCreateOtnServiceInput(serviceName,
+                service.getServiceAEnd().getServiceFormat().getName(),
+                service.getServiceAEnd().getServiceRate().toString() + "G", pathDescription, true);
+        }
+        LOG.info("Deleting otn-service path {} via renderer", serviceName);
+        sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
+                "Deleting otn-service path via renderer");
+        OtnServicePathOutput result = otnDeviceRenderer.deleteOtnServicePath(ospi);
+        if (result.getSuccess()) {
+            sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
+                    serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * 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);
+        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) {
+        Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
+                pathDescription);
+        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) {
+        RendererRpcResultSpBuilder builder = new RendererRpcResultSpBuilder()
+                .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx)
+                .setStatusMessage(message);
+        if (pathDescription != null) {
+            builder.setAToZDirection(pathDescription.getAToZDirection())
+                    .setZToADirection(pathDescription.getZToADirection());
+        }
+        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();
+        }
+    }
+
 }