Fix deprecated warnings caused by YangTools update
[transportpce.git] / renderer / src / main / java / org / opendaylight / transportpce / renderer / provisiondevice / RendererServiceOperationsImpl.java
1 /*
2  * Copyright © 2017 AT&T and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.transportpce.renderer.provisiondevice;
9
10 import com.google.common.util.concurrent.Futures;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import com.google.common.util.concurrent.ListeningExecutorService;
13 import com.google.common.util.concurrent.MoreExecutors;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Optional;
17 import java.util.concurrent.Callable;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.Executors;
20 import java.util.concurrent.Future;
21 import java.util.concurrent.TimeUnit;
22 import java.util.concurrent.TimeoutException;
23 import org.opendaylight.mdsal.binding.api.DataBroker;
24 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
25 import org.opendaylight.mdsal.binding.api.ReadTransaction;
26 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
27 import org.opendaylight.transportpce.common.ResponseCodes;
28 import org.opendaylight.transportpce.common.StringConstants;
29 import org.opendaylight.transportpce.common.Timeouts;
30 import org.opendaylight.transportpce.renderer.ModelMappingUtils;
31 import org.opendaylight.transportpce.renderer.ServicePathInputData;
32 import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection;
33 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingRollbackTask;
34 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingTask;
35 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupRollbackTask;
36 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupTask;
37 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OtnDeviceRenderingTask;
38 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor;
39 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev200128.OtnServicePathInput;
40 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev200128.OtnServicePathOutput;
41 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.GetPmInputBuilder;
42 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.GetPmOutput;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerSetupInput;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerTurndownInputBuilder;
45 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerTurndownOutput;
46 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.TransportpceOlmService;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.get.pm.output.Measurements;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.RendererRpcResultSp;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.RendererRpcResultSpBuilder;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceDeleteInput;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceDeleteOutput;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceImplementationRequestInput;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceImplementationRequestOutput;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ConnectionType;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODU4;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OTU4;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
61 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201210.PathDescription;
62 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx;
63 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.ServicePathNotificationTypes;
64 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
65 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
66 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
67 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev201211.olm.get.pm.input.ResourceIdentifierBuilder;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev201211.olm.renderer.input.Nodes;
69 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
70 import org.opendaylight.yangtools.yang.binding.Notification;
71 import org.opendaylight.yangtools.yang.common.RpcResult;
72 import org.opendaylight.yangtools.yang.common.Uint32;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75
76
77 public class RendererServiceOperationsImpl implements RendererServiceOperations {
78
79     private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
80             "Device rendering was not successful! Rendering will be rolled back.";
81     private static final String OLM_ROLL_BACK_MSG =
82             "OLM power setup was not successful! Rendering and OLM will be rolled back.";
83     private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
84     private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
85     private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path";
86     private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
87     private static final String FAILED = "Failed";
88     private static final String OPERATION_FAILED = "Operation Failed";
89     private static final String OPERATION_SUCCESSFUL = "Operation Successful";
90     private static final int NUMBER_OF_THREADS = 4;
91
92     private final DeviceRendererService deviceRenderer;
93     private final OtnDeviceRendererService otnDeviceRenderer;
94     private final TransportpceOlmService olmService;
95     private final DataBroker dataBroker;
96     private final NotificationPublishService notificationPublishService;
97     private ListeningExecutorService executor;
98
99     public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer,
100             OtnDeviceRendererService otnDeviceRenderer, TransportpceOlmService olmService,
101             DataBroker dataBroker, NotificationPublishService notificationPublishService) {
102         this.deviceRenderer = deviceRenderer;
103         this.otnDeviceRenderer = otnDeviceRenderer;
104         this.olmService = olmService;
105         this.dataBroker = dataBroker;
106         this.notificationPublishService = notificationPublishService;
107         this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
108     }
109
110     @Override
111     public ListenableFuture<ServiceImplementationRequestOutput>
112             serviceImplementation(ServiceImplementationRequestInput input) {
113         LOG.info("Calling service impl request {}", input.getServiceName());
114         return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
115
116             @Override
117             public ServiceImplementationRequestOutput call() throws Exception {
118                 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(),
119                         RpcStatusEx.Pending, "Service compliant, submitting service implementation Request ...");
120                 // Here is the switch statement that distinguishes on the connection-type
121                 LOG.info("Connection-type is {} for {}", input.getConnectionType(), input.getServiceName());
122                 switch (input.getConnectionType()) {
123                     case Service: case RoadmLine: // This takes into account of Ethernet 100G, 1G, 10G and ODU4
124                         LOG.info("RPC implementation for {}", input.getConnectionType());
125                         if (((input.getServiceAEnd().getServiceRate() != null)
126                             && (input.getServiceAEnd().getServiceRate().intValue() == 100))
127                             && ((input.getServiceAEnd().getServiceFormat().getName().equals("Ethernet"))
128                                 || (input.getServiceAEnd().getServiceFormat().getName().equals("OC")))) {
129                             LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
130                                 input.getServiceAEnd().getServiceFormat(), input.getServiceAEnd().getServiceRate());
131                             if (!createServicepathInput(input)) {
132                                 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
133                                     OPERATION_FAILED);
134                             }
135                         } else { // This implies, service-rate is 1 or 10G
136                             // This includes the lower-order odu (1G, 10G) and this is A-Z side
137                             LOG.info("RPC implementation for LO-ODU");
138                             String serviceRate = ""; // Assuming service at A-side and Z-side has same service rate
139                             if (input.getServiceAEnd().getServiceRate() != null) {
140                                 serviceRate = input.getServiceAEnd().getServiceRate().toString() + "G";
141                             }
142                             LOG.info("Start rendering for {} service with {} rate and {} format",
143                                 input.getServiceName(), serviceRate,
144                                 input.getServiceAEnd().getServiceFormat());
145                             // This is A-Z side
146                             OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
147                                 .rendererCreateOtnServiceInput(input.getServiceName(),
148                                     input.getServiceAEnd().getServiceFormat().getName(),
149                                     serviceRate, (PathDescription) input.getPathDescription(), true);
150                             // Rollback should be same for all conditions, so creating a new one
151                             RollbackProcessor rollbackProcessor = new RollbackProcessor();
152                             List<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
153                                 otnServicePathInputAtoZ, null);
154                             if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
155                                 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
156                                     input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
157                                 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
158                                     OPERATION_FAILED);
159                             }
160                             LOG.info("OTN rendering result size {}", otnRenderingResults.size());
161                         }
162                         break;
163                     case Infrastructure:
164                         LOG.info("RPC implementation for {}", input.getConnectionType());
165                         if ((input.getServiceAEnd().getOtuServiceRate() != null)
166                             && (input.getServiceAEnd().getOtuServiceRate().equals(OTU4.class))) {
167                             // For the service of OTU4 infrastructure
168                             // First create the OCH and OTU interfaces
169                             String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
170                             if (!createServicepathInput(input)) {
171                                 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
172                                     OPERATION_FAILED);
173                             }
174                         }
175                         if ((input.getServiceAEnd().getOduServiceRate() != null)
176                             && (input.getServiceAEnd().getOduServiceRate().equals(ODU4.class))) {
177                             // For the service of OTU4 infrastructure
178                             String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
179                             LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
180                                 input.getServiceAEnd().getOduServiceRate(), serviceRate);
181                             // Now start rendering ODU4 interface
182                             // This is A-Z side
183                             OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
184                                 .rendererCreateOtnServiceInput(input.getServiceName(),
185                                     input.getServiceAEnd().getServiceFormat().getName(),
186                                     serviceRate,
187                                     input.getPathDescription(), true);
188                             // This is Z-A side
189                             OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
190                                 .rendererCreateOtnServiceInput(input.getServiceName(),
191                                     input.getServiceZEnd().getServiceFormat().getName(),
192                                     serviceRate,
193                                     input.getPathDescription(), false);
194                             // Rollback should be same for all conditions, so creating a new one
195                             RollbackProcessor rollbackProcessor = new RollbackProcessor();
196                             List<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
197                                 otnServicePathInputAtoZ, otnServicePathInputZtoA);
198                             if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
199                                 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
200                                     input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
201                                 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
202                                     OPERATION_FAILED);
203                             }
204                             LOG.info("OTN rendering result size {}", otnRenderingResults.size());
205                         }
206                         break;
207                     default:
208                         LOG.warn("Unsupported connection type {}", input.getConnectionType());
209                 }
210                 sendNotificationsWithPathDescription(
211                         ServicePathNotificationTypes.ServiceImplementationRequest,
212                         input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL,
213                         input.getPathDescription());
214                 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
215                     OPERATION_SUCCESSFUL);
216             }
217         });
218     }
219
220     @Override
221     public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
222         String serviceName = input.getServiceName();
223         LOG.info("Calling service delete request {}", serviceName);
224         return executor.submit(new Callable<ServiceDeleteOutput>() {
225
226             @Override
227             public ServiceDeleteOutput call() throws Exception {
228                 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
229                         RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
230                 // Obtain path description
231                 Optional<
232                     org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service
233                     .path.PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
234                 PathDescription pathDescription;
235                 if (pathDescriptionOpt.isPresent()) {
236                     pathDescription = pathDescriptionOpt.get();
237                 } else {
238                     LOG.error("Unable to get path description for service {}!", serviceName);
239                     sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
240                             RpcStatusEx.Failed, "Unable to get path description for service");
241                     return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
242                             OPERATION_FAILED);
243                 }
244                 switch (service.getConnectionType()) {
245                     case RoadmLine:
246                     case Service:
247                         if ((ServiceFormat.Ethernet.equals(service.getServiceAEnd().getServiceFormat())
248                                 || ServiceFormat.OC.equals(service.getServiceAEnd().getServiceFormat()))
249                             && Uint32.valueOf("100").equals(service.getServiceAEnd().getServiceRate())) {
250                             if (!manageServicePathDeletion(serviceName, pathDescription)) {
251                                 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
252                                     OPERATION_FAILED);
253                             }
254                         }
255                         if (ServiceFormat.Ethernet.equals(service.getServiceAEnd().getServiceFormat())
256                             && (Uint32.valueOf("10").equals(service.getServiceAEnd().getServiceRate())
257                                 || Uint32.valueOf("1").equals(service.getServiceAEnd().getServiceRate()))) {
258                             if (!manageOtnServicePathDeletion(serviceName, pathDescription, service)) {
259                                 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
260                                     OPERATION_FAILED);
261                             }
262                         }
263                         break;
264                     case Infrastructure:
265                         if (ServiceFormat.OTU.equals(service.getServiceAEnd().getServiceFormat())) {
266                             if (!manageServicePathDeletion(serviceName, pathDescription)) {
267                                 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
268                                     OPERATION_FAILED);
269                             }
270                         } else if (ServiceFormat.ODU.equals(service.getServiceAEnd().getServiceFormat())) {
271                             if (!manageOtnServicePathDeletion(serviceName, pathDescription, service)) {
272                                 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
273                                     OPERATION_FAILED);
274                             }
275                         }
276                         break;
277                     default:
278                         LOG.error("Unmanaged connection-type for deletion of service {}", serviceName);
279                         break;
280                     }
281                 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
282             }
283         });
284     }
285
286     @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
287             value = "UPM_UNCALLED_PRIVATE_METHOD",
288             justification = "call in call() method")
289     private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
290             throws InterruptedException, ExecutionException, TimeoutException {
291         LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
292         Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
293                 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
294         return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
295     }
296
297     @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
298             value = "UPM_UNCALLED_PRIVATE_METHOD",
299             justification = "call in call() method")
300     private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
301         .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
302         InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
303             .service.path.PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
304                 .child(ServicePaths.class, new ServicePathsKey(serviceName))
305                 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
306                     .service.path.PathDescription.class);
307         ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
308         try {
309             LOG.debug("Getting path description for service {}", serviceName);
310             return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
311                     .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
312         } catch (InterruptedException | ExecutionException | TimeoutException e) {
313             LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
314                     serviceName, e);
315             return Optional.empty();
316         }
317     }
318
319     @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
320             value = "UPM_UNCALLED_PRIVATE_METHOD",
321             justification = "call in call() method")
322     private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
323             ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
324         LOG.info(RENDERING_DEVICES_A_Z_MSG);
325         sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
326                 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
327                 RENDERING_DEVICES_A_Z_MSG);
328         ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
329                 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
330                         ServicePathDirection.A_TO_Z));
331
332         LOG.info("Rendering devices Z-A");
333         sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
334                 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
335                 RENDERING_DEVICES_Z_A_MSG);
336         ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
337                 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
338                         ServicePathDirection.Z_TO_A));
339         ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
340                 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
341
342         List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
343         try {
344             LOG.info("Waiting for A-Z and Z-A device renderers ...");
345             renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
346         } catch (InterruptedException | ExecutionException | TimeoutException e) {
347             LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
348             sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
349                     servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
350                     DEVICE_RENDERING_ROLL_BACK_MSG);
351             //FIXME we can't do rollback here, because we don't have rendering results.
352             return renderingResults;
353         }
354
355         rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
356                 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
357                 this.deviceRenderer));
358         rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
359                 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
360                 this.deviceRenderer));
361         return renderingResults;
362     }
363
364     @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
365         value = "UPM_UNCALLED_PRIVATE_METHOD",
366         justification = "call in call() method")
367     private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
368         OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA) {
369         LOG.info(RENDERING_DEVICES_A_Z_MSG);
370         sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
371             otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
372             RENDERING_DEVICES_A_Z_MSG);
373         ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
374             this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ));
375         ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture;
376         if (otnServicePathZtoA != null) {
377             LOG.info("Rendering devices Z-A");
378             sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
379                 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
380                 RENDERING_DEVICES_Z_A_MSG);
381             ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
382                 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA));
383             renderingCombinedFuture = Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
384         } else {
385             renderingCombinedFuture = Futures.allAsList(atozrenderingFuture);
386         }
387         List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
388         try {
389             LOG.info("Waiting for A-Z and Z-A device renderers ...");
390             otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
391         } catch (InterruptedException | ExecutionException | TimeoutException e) {
392             LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
393             sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
394                 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
395                 DEVICE_RENDERING_ROLL_BACK_MSG);
396             //FIXME we can't do rollback here, because we don't have rendering results.
397             return otnRenderingResults;
398         }
399         for (int i = 0; i < otnRenderingResults.size(); i++) {
400             rollbackProcessor.addTask(new DeviceRenderingRollbackTask("DeviceTask n° " + i + 1,
401                 ! otnRenderingResults.get(i).isSuccess(), otnRenderingResults.get(i).getRenderedNodeInterfaces(),
402                 this.deviceRenderer));
403         }
404         return otnRenderingResults;
405     }
406
407     @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
408             value = "UPM_UNCALLED_PRIVATE_METHOD",
409             justification = "call in call() method")
410     private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
411             ServicePowerSetupInput powerSetupInputZtoA) {
412         LOG.info("Olm power setup A-Z");
413         sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
414                 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
415         ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
416                 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
417
418         LOG.info("OLM power setup Z-A");
419         sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
420                 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
421         ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
422                 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
423         ListenableFuture<List<OLMRenderingResult>> olmFutures =
424                 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
425
426         List<OLMRenderingResult> olmResults;
427         try {
428             LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
429             olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
430         } catch (InterruptedException | ExecutionException | TimeoutException e) {
431             LOG.warn(OLM_ROLL_BACK_MSG, e);
432             sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
433                     powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
434                     OLM_ROLL_BACK_MSG);
435             rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
436                     this.olmService, powerSetupInputAtoZ));
437             rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
438                     this.olmService, powerSetupInputZtoA));
439             return;
440         }
441
442         rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
443                 this.olmService, powerSetupInputAtoZ));
444         rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
445                 this.olmService, powerSetupInputZtoA));
446     }
447
448     @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
449             value = "UPM_UNCALLED_PRIVATE_METHOD",
450             justification = "call in call() method")
451     private boolean isServiceActivated(String nodeId, String tpId) {
452         LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
453         for (int i = 0; i < 3; i++) {
454             List<Measurements> measurements = getMeasurements(nodeId, tpId);
455             if ((measurements != null) && verifyPreFecBer(measurements)) {
456                 return true;
457             } else if (measurements == null) {
458                 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
459                 return true;
460             } else {
461                 try {
462                     Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
463                 } catch (InterruptedException ex) {
464                     Thread.currentThread().interrupt();
465                 }
466             }
467         }
468         LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
469         return false;
470     }
471
472     private List<Measurements> getMeasurements(String nodeId, String tp) {
473         GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder();
474         getPmIpBldr.setNodeId(nodeId);
475         getPmIpBldr.setGranularity(PmGranularity._15min);
476         ResourceIdentifierBuilder rsrcBldr = new ResourceIdentifierBuilder();
477         rsrcBldr.setResourceName(tp + "-OTU");
478         getPmIpBldr.setResourceIdentifier(rsrcBldr.build());
479         getPmIpBldr.setResourceType(ResourceTypeEnum.Interface);
480
481         try {
482             Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
483             RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
484             GetPmOutput getPmOutput = getPmRpcResult.getResult();
485             if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
486                 LOG.info("successfully finished calling OLM's get PM");
487                 return getPmOutput.getMeasurements();
488                 // may return null
489             } else {
490                 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
491             }
492
493         } catch (ExecutionException | InterruptedException e) {
494             LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
495         }
496         return null;
497     }
498
499     private boolean verifyPreFecBer(List<Measurements> measurements) {
500         double preFecCorrectedErrors = Double.MIN_VALUE;
501         double fecUncorrectableBlocks = Double.MIN_VALUE;
502
503         for (Measurements measurement : measurements) {
504             if (measurement.getPmparameterName().equals("preFECCorrectedErrors")) {
505                 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
506             }
507             if (measurement.getPmparameterName().equals("FECUncorrectableBlocks")) {
508                 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
509             }
510         }
511
512         LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
513                 fecUncorrectableBlocks);
514
515         if (fecUncorrectableBlocks > Double.MIN_VALUE) {
516             LOG.error("Data has uncorrectable errors, BER test failed");
517             return false;
518         } else {
519             double numOfBitsPerSecond = 112000000000d;
520             double threshold = 0.00002d;
521             double result = preFecCorrectedErrors / numOfBitsPerSecond;
522             LOG.info("PreFEC value is {}", Double.toString(result));
523             return result <= threshold;
524         }
525     }
526
527     @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
528         value = "UPM_UNCALLED_PRIVATE_METHOD",
529         justification = "call in call() method")
530     private boolean createServicepathInput(ServiceImplementationRequestInput input) {
531         ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
532             .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription());
533         ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
534             .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription());
535         // Rollback should be same for all conditions, so creating a new one
536         RollbackProcessor rollbackProcessor = new RollbackProcessor();
537         List<DeviceRenderingResult> renderingResults =
538             deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
539         if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
540             sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
541                 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
542             return false;
543         }
544         ServicePowerSetupInput olmPowerSetupInputAtoZ =
545             ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input);
546         ServicePowerSetupInput olmPowerSetupInputZtoA =
547             ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input);
548         olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
549         if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
550             sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
551                 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
552             return false;
553         }
554         // run service activation test twice - once on source node and once on
555         // destination node
556         List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
557         if ((nodes == null) || (nodes.isEmpty())) {
558             return false;
559         }
560
561         Nodes sourceNode = nodes.get(0);
562         Nodes destNode = nodes.get(nodes.size() - 1);
563         String srcNetworkTp;
564         String dstNetowrkTp;
565         if (sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
566             srcNetworkTp = sourceNode.getDestTp();
567         } else {
568             srcNetworkTp = sourceNode.getSrcTp();
569         }
570         if (destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
571             dstNetowrkTp = destNode.getDestTp();
572         } else {
573             dstNetowrkTp = destNode.getSrcTp();
574         }
575         if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
576             || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
577             rollbackProcessor.rollbackAll();
578             sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
579                 input.getServiceName(), RpcStatusEx.Failed,
580                 "Service activation test failed.");
581             return false;
582         }
583         sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
584             input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription());
585         return true;
586     }
587
588     @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
589         value = "UPM_UNCALLED_PRIVATE_METHOD",
590         justification = "call in call() method")
591     private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription) {
592         ServicePathInputData servicePathInputDataAtoZ =
593             ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription);
594         ServicePathInputData servicePathInputDataZtoA =
595             ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription);
596         // OLM turn down power
597         try {
598             LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
599             sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
600                 RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
601             ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
602             // TODO add some flag rather than string
603             if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
604                 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
605                 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
606                         "Service power turndown failed on A-to-Z path for service");
607                 return false;
608             }
609             LOG.debug("Turning down power on Z-to-A path");
610             sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
611                     "Turning down power on Z-to-A path");
612             ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
613             // TODO add some flag rather than string
614             if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
615                 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
616                 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
617                         "Service power turndown failed on Z-to-A path for service");
618                 return false;
619             }
620         } catch (InterruptedException | ExecutionException | TimeoutException e) {
621             LOG.error("Error while turning down power!", e);
622             return false;
623         }
624         // delete service path with renderer
625         LOG.info("Deleting service path via renderer");
626         sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
627                 "Deleting service path via renderer");
628         deviceRenderer.deleteServicePath(servicePathInputDataAtoZ.getServicePathInput());
629         deviceRenderer.deleteServicePath(servicePathInputDataZtoA.getServicePathInput());
630         sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
631                 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL,pathDescription);
632         return true;
633     }
634
635     @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
636         value = "UPM_UNCALLED_PRIVATE_METHOD",
637         justification = "call in call() method")
638     private boolean manageOtnServicePathDeletion(String serviceName, PathDescription pathDescription,
639         Services service) {
640         OtnServicePathInput ospi = null;
641         if (ConnectionType.Infrastructure.equals(service.getConnectionType())) {
642             ospi = ModelMappingUtils.rendererCreateOtnServiceInput(
643                 serviceName, service.getServiceAEnd().getServiceFormat().getName(), "100G", pathDescription, true);
644         } else if (ConnectionType.Service.equals(service.getConnectionType())) {
645             ospi = ModelMappingUtils.rendererCreateOtnServiceInput(serviceName,
646                 service.getServiceAEnd().getServiceFormat().getName(),
647                 service.getServiceAEnd().getServiceRate().toString() + "G", pathDescription, true);
648         }
649         LOG.info("Deleting otn-service path {} via renderer", serviceName);
650         sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
651                 "Deleting otn-service path via renderer");
652         OtnServicePathOutput result = otnDeviceRenderer.deleteOtnServicePath(ospi);
653         if (result.getSuccess()) {
654             sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
655                     serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription);
656             return true;
657         } else {
658             return false;
659         }
660     }
661
662     /**
663      * Send renderer notification.
664      * @param servicePathNotificationTypes ServicePathNotificationTypes
665      * @param serviceName String
666      * @param rpcStatusEx RpcStatusEx
667      * @param message String
668      */
669     private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
670             RpcStatusEx rpcStatusEx, String message) {
671         Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
672                 null);
673         send(notification);
674     }
675
676     /**
677      * Send renderer notification with path description information.
678      * @param servicePathNotificationTypes ServicePathNotificationTypes
679      * @param serviceName String
680      * @param rpcStatusEx RpcStatusEx
681      * @param message String
682      * @param pathDescription PathDescription
683      */
684     private void sendNotificationsWithPathDescription(ServicePathNotificationTypes servicePathNotificationTypes,
685             String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription) {
686         Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
687                 pathDescription);
688         send(notification);
689     }
690
691     /**
692      * Build notification containing path description information.
693      * @param servicePathNotificationTypes ServicePathNotificationTypes
694      * @param serviceName String
695      * @param rpcStatusEx RpcStatusEx
696      * @param message String
697      * @param pathDescription PathDescription
698      * @return notification with RendererRpcResultSp type.
699      */
700     private RendererRpcResultSp buildNotification(ServicePathNotificationTypes servicePathNotificationTypes,
701             String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription) {
702         RendererRpcResultSpBuilder builder = new RendererRpcResultSpBuilder()
703                 .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx)
704                 .setStatusMessage(message);
705         if (pathDescription != null) {
706             builder.setAToZDirection(pathDescription.getAToZDirection())
707                     .setZToADirection(pathDescription.getZToADirection());
708         }
709         return builder.build();
710     }
711
712     /**
713      * Send renderer notification.
714      * @param notification Notification
715      */
716     private void send(Notification notification) {
717         try {
718             LOG.info("Sending notification {}", notification);
719             notificationPublishService.putNotification(notification);
720         } catch (InterruptedException e) {
721             LOG.info("notification offer rejected: ", e);
722             Thread.currentThread().interrupt();
723         }
724     }
725
726 }