2 * Copyright © 2017 AT&T and others. All rights reserved.
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
8 package org.opendaylight.transportpce.renderer.provisiondevice;
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;
77 public class RendererServiceOperationsImpl implements RendererServiceOperations {
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;
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;
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));
111 public ListenableFuture<ServiceImplementationRequestOutput>
112 serviceImplementation(ServiceImplementationRequestInput input) {
113 LOG.info("Calling service impl request {}", input.getServiceName());
114 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
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().getServiceRate().intValue() == 400))
128 && ((input.getServiceAEnd().getServiceFormat().getName().equals("Ethernet"))
129 || (input.getServiceAEnd().getServiceFormat().getName().equals("OC")))) {
130 LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
131 input.getServiceAEnd().getServiceFormat(), input.getServiceAEnd().getServiceRate());
132 if (!createServicepathInput(input)) {
133 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
136 } else { // This implies, service-rate is 1 or 10G
137 // This includes the lower-order odu (1G, 10G) and this is A-Z side
138 LOG.info("RPC implementation for LO-ODU");
139 String serviceRate = ""; // Assuming service at A-side and Z-side has same service rate
140 if (input.getServiceAEnd().getServiceRate() != null) {
141 serviceRate = input.getServiceAEnd().getServiceRate().toString() + "G";
143 LOG.info("Start rendering for {} service with {} rate and {} format",
144 input.getServiceName(), serviceRate,
145 input.getServiceAEnd().getServiceFormat());
147 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
148 .rendererCreateOtnServiceInput(input.getServiceName(),
149 input.getServiceAEnd().getServiceFormat().getName(),
150 serviceRate, (PathDescription) input.getPathDescription(), true);
151 // Rollback should be same for all conditions, so creating a new one
152 RollbackProcessor rollbackProcessor = new RollbackProcessor();
153 List<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
154 otnServicePathInputAtoZ, null);
155 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
156 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
157 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
158 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
161 LOG.info("OTN rendering result size {}", otnRenderingResults.size());
165 LOG.info("RPC implementation for {}", input.getConnectionType());
166 if ((input.getServiceAEnd().getOtuServiceRate() != null)
167 && (input.getServiceAEnd().getOtuServiceRate().equals(OTU4.class))) {
168 // For the service of OTU4 infrastructure
169 // First create the OCH and OTU interfaces
170 String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
171 if (!createServicepathInput(input)) {
172 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
176 if ((input.getServiceAEnd().getOduServiceRate() != null)
177 && (input.getServiceAEnd().getOduServiceRate().equals(ODU4.class))) {
178 // For the service of OTU4 infrastructure
179 String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
180 LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
181 input.getServiceAEnd().getOduServiceRate(), serviceRate);
182 // Now start rendering ODU4 interface
184 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
185 .rendererCreateOtnServiceInput(input.getServiceName(),
186 input.getServiceAEnd().getServiceFormat().getName(),
188 input.getPathDescription(), true);
190 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
191 .rendererCreateOtnServiceInput(input.getServiceName(),
192 input.getServiceZEnd().getServiceFormat().getName(),
194 input.getPathDescription(), false);
195 // Rollback should be same for all conditions, so creating a new one
196 RollbackProcessor rollbackProcessor = new RollbackProcessor();
197 List<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
198 otnServicePathInputAtoZ, otnServicePathInputZtoA);
199 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
200 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
201 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
202 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
205 LOG.info("OTN rendering result size {}", otnRenderingResults.size());
209 LOG.warn("Unsupported connection type {}", input.getConnectionType());
211 sendNotificationsWithPathDescription(
212 ServicePathNotificationTypes.ServiceImplementationRequest,
213 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL,
214 input.getPathDescription());
215 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
216 OPERATION_SUCCESSFUL);
222 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
223 String serviceName = input.getServiceName();
224 LOG.info("Calling service delete request {}", serviceName);
225 return executor.submit(new Callable<ServiceDeleteOutput>() {
228 public ServiceDeleteOutput call() throws Exception {
229 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
230 RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
231 // Obtain path description
233 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service
234 .path.PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
235 PathDescription pathDescription;
236 if (pathDescriptionOpt.isPresent()) {
237 pathDescription = pathDescriptionOpt.get();
239 LOG.error("Unable to get path description for service {}!", serviceName);
240 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
241 RpcStatusEx.Failed, "Unable to get path description for service");
242 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
245 switch (service.getConnectionType()) {
248 if ((ServiceFormat.Ethernet.equals(service.getServiceAEnd().getServiceFormat())
249 || ServiceFormat.OC.equals(service.getServiceAEnd().getServiceFormat()))
250 && Uint32.valueOf("100").equals(service.getServiceAEnd().getServiceRate())) {
251 if (!manageServicePathDeletion(serviceName, pathDescription)) {
252 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
256 if (ServiceFormat.Ethernet.equals(service.getServiceAEnd().getServiceFormat())
257 && (Uint32.valueOf("10").equals(service.getServiceAEnd().getServiceRate())
258 || Uint32.valueOf("1").equals(service.getServiceAEnd().getServiceRate()))) {
259 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service)) {
260 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
266 if (ServiceFormat.OTU.equals(service.getServiceAEnd().getServiceFormat())) {
267 if (!manageServicePathDeletion(serviceName, pathDescription)) {
268 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
271 } else if (ServiceFormat.ODU.equals(service.getServiceAEnd().getServiceFormat())) {
272 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service)) {
273 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
279 LOG.error("Unmanaged connection-type for deletion of service {}", serviceName);
282 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
287 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
288 value = "UPM_UNCALLED_PRIVATE_METHOD",
289 justification = "call in call() method")
290 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
291 throws InterruptedException, ExecutionException, TimeoutException {
292 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
293 Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
294 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
295 return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
298 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
299 value = "UPM_UNCALLED_PRIVATE_METHOD",
300 justification = "call in call() method")
301 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
302 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
303 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
304 .service.path.PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
305 .child(ServicePaths.class, new ServicePathsKey(serviceName))
306 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
307 .service.path.PathDescription.class);
308 ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
310 LOG.debug("Getting path description for service {}", serviceName);
311 return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
312 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
313 } catch (InterruptedException | ExecutionException | TimeoutException e) {
314 LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
316 return Optional.empty();
320 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
321 value = "UPM_UNCALLED_PRIVATE_METHOD",
322 justification = "call in call() method")
323 private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
324 ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
325 LOG.info(RENDERING_DEVICES_A_Z_MSG);
326 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
327 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
328 RENDERING_DEVICES_A_Z_MSG);
329 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
330 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
331 ServicePathDirection.A_TO_Z));
333 LOG.info("Rendering devices Z-A");
334 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
335 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
336 RENDERING_DEVICES_Z_A_MSG);
337 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
338 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
339 ServicePathDirection.Z_TO_A));
340 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
341 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
343 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
345 LOG.info("Waiting for A-Z and Z-A device renderers ...");
346 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
347 } catch (InterruptedException | ExecutionException | TimeoutException e) {
348 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
349 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
350 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
351 DEVICE_RENDERING_ROLL_BACK_MSG);
352 //FIXME we can't do rollback here, because we don't have rendering results.
353 return renderingResults;
356 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
357 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
358 this.deviceRenderer));
359 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
360 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
361 this.deviceRenderer));
362 return renderingResults;
365 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
366 value = "UPM_UNCALLED_PRIVATE_METHOD",
367 justification = "call in call() method")
368 private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
369 OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA) {
370 LOG.info(RENDERING_DEVICES_A_Z_MSG);
371 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
372 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
373 RENDERING_DEVICES_A_Z_MSG);
374 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
375 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ));
376 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture;
377 if (otnServicePathZtoA != null) {
378 LOG.info("Rendering devices Z-A");
379 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
380 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
381 RENDERING_DEVICES_Z_A_MSG);
382 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
383 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA));
384 renderingCombinedFuture = Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
386 renderingCombinedFuture = Futures.allAsList(atozrenderingFuture);
388 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
390 LOG.info("Waiting for A-Z and Z-A device renderers ...");
391 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
392 } catch (InterruptedException | ExecutionException | TimeoutException e) {
393 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
394 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
395 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
396 DEVICE_RENDERING_ROLL_BACK_MSG);
397 //FIXME we can't do rollback here, because we don't have rendering results.
398 return otnRenderingResults;
400 for (int i = 0; i < otnRenderingResults.size(); i++) {
401 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("DeviceTask n° " + i + 1,
402 ! otnRenderingResults.get(i).isSuccess(), otnRenderingResults.get(i).getRenderedNodeInterfaces(),
403 this.deviceRenderer));
405 return otnRenderingResults;
408 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
409 value = "UPM_UNCALLED_PRIVATE_METHOD",
410 justification = "call in call() method")
411 private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
412 ServicePowerSetupInput powerSetupInputZtoA) {
413 LOG.info("Olm power setup A-Z");
414 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
415 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
416 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
417 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
419 LOG.info("OLM power setup Z-A");
420 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
421 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
422 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
423 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
424 ListenableFuture<List<OLMRenderingResult>> olmFutures =
425 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
427 List<OLMRenderingResult> olmResults;
429 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
430 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
431 } catch (InterruptedException | ExecutionException | TimeoutException e) {
432 LOG.warn(OLM_ROLL_BACK_MSG, e);
433 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
434 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
436 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
437 this.olmService, powerSetupInputAtoZ));
438 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
439 this.olmService, powerSetupInputZtoA));
443 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
444 this.olmService, powerSetupInputAtoZ));
445 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
446 this.olmService, powerSetupInputZtoA));
449 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
450 value = "UPM_UNCALLED_PRIVATE_METHOD",
451 justification = "call in call() method")
452 private boolean isServiceActivated(String nodeId, String tpId) {
453 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
454 for (int i = 0; i < 3; i++) {
455 List<Measurements> measurements = getMeasurements(nodeId, tpId);
456 if ((measurements != null) && verifyPreFecBer(measurements)) {
458 } else if (measurements == null) {
459 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
463 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
464 } catch (InterruptedException ex) {
465 Thread.currentThread().interrupt();
469 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
473 private List<Measurements> getMeasurements(String nodeId, String tp) {
474 GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder();
475 getPmIpBldr.setNodeId(nodeId);
476 getPmIpBldr.setGranularity(PmGranularity._15min);
477 ResourceIdentifierBuilder rsrcBldr = new ResourceIdentifierBuilder();
478 rsrcBldr.setResourceName(tp + "-OTU");
479 getPmIpBldr.setResourceIdentifier(rsrcBldr.build());
480 getPmIpBldr.setResourceType(ResourceTypeEnum.Interface);
483 Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
484 RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
485 GetPmOutput getPmOutput = getPmRpcResult.getResult();
486 if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
487 LOG.info("successfully finished calling OLM's get PM");
488 return getPmOutput.getMeasurements();
491 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
494 } catch (ExecutionException | InterruptedException e) {
495 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
500 private boolean verifyPreFecBer(List<Measurements> measurements) {
501 double preFecCorrectedErrors = Double.MIN_VALUE;
502 double fecUncorrectableBlocks = Double.MIN_VALUE;
504 for (Measurements measurement : measurements) {
505 if (measurement.getPmparameterName().equals("preFECCorrectedErrors")) {
506 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
508 if (measurement.getPmparameterName().equals("FECUncorrectableBlocks")) {
509 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
513 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
514 fecUncorrectableBlocks);
516 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
517 LOG.error("Data has uncorrectable errors, BER test failed");
520 double numOfBitsPerSecond = 112000000000d;
521 double threshold = 0.00002d;
522 double result = preFecCorrectedErrors / numOfBitsPerSecond;
523 LOG.info("PreFEC value is {}", Double.toString(result));
524 return result <= threshold;
528 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
529 value = "UPM_UNCALLED_PRIVATE_METHOD",
530 justification = "call in call() method")
531 private boolean createServicepathInput(ServiceImplementationRequestInput input) {
532 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
533 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription());
534 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
535 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription());
536 // Rollback should be same for all conditions, so creating a new one
537 RollbackProcessor rollbackProcessor = new RollbackProcessor();
538 List<DeviceRenderingResult> renderingResults =
539 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
540 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
541 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
542 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
545 ServicePowerSetupInput olmPowerSetupInputAtoZ =
546 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input);
547 ServicePowerSetupInput olmPowerSetupInputZtoA =
548 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input);
549 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
550 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
551 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
552 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
555 // run service activation test twice - once on source node and once on
557 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
558 if ((nodes == null) || (nodes.isEmpty())) {
562 Nodes sourceNode = nodes.get(0);
563 Nodes destNode = nodes.get(nodes.size() - 1);
566 if (sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
567 srcNetworkTp = sourceNode.getDestTp();
569 srcNetworkTp = sourceNode.getSrcTp();
571 if (destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
572 dstNetowrkTp = destNode.getDestTp();
574 dstNetowrkTp = destNode.getSrcTp();
576 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
577 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
578 rollbackProcessor.rollbackAll();
579 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
580 input.getServiceName(), RpcStatusEx.Failed,
581 "Service activation test failed.");
584 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
585 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription());
589 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
590 value = "UPM_UNCALLED_PRIVATE_METHOD",
591 justification = "call in call() method")
592 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription) {
593 ServicePathInputData servicePathInputDataAtoZ =
594 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription);
595 ServicePathInputData servicePathInputDataZtoA =
596 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription);
597 // OLM turn down power
599 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
600 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
601 RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
602 ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
603 // TODO add some flag rather than string
604 if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
605 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
606 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
607 "Service power turndown failed on A-to-Z path for service");
610 LOG.debug("Turning down power on Z-to-A path");
611 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
612 "Turning down power on Z-to-A path");
613 ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
614 // TODO add some flag rather than string
615 if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
616 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
617 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
618 "Service power turndown failed on Z-to-A path for service");
621 } catch (InterruptedException | ExecutionException | TimeoutException e) {
622 LOG.error("Error while turning down power!", e);
625 // delete service path with renderer
626 LOG.info("Deleting service path via renderer");
627 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
628 "Deleting service path via renderer");
629 deviceRenderer.deleteServicePath(servicePathInputDataAtoZ.getServicePathInput());
630 deviceRenderer.deleteServicePath(servicePathInputDataZtoA.getServicePathInput());
631 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
632 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL,pathDescription);
636 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
637 value = "UPM_UNCALLED_PRIVATE_METHOD",
638 justification = "call in call() method")
639 private boolean manageOtnServicePathDeletion(String serviceName, PathDescription pathDescription,
641 OtnServicePathInput ospi = null;
642 if (ConnectionType.Infrastructure.equals(service.getConnectionType())) {
643 ospi = ModelMappingUtils.rendererCreateOtnServiceInput(
644 serviceName, service.getServiceAEnd().getServiceFormat().getName(), "100G", pathDescription, true);
645 } else if (ConnectionType.Service.equals(service.getConnectionType())) {
646 ospi = ModelMappingUtils.rendererCreateOtnServiceInput(serviceName,
647 service.getServiceAEnd().getServiceFormat().getName(),
648 service.getServiceAEnd().getServiceRate().toString() + "G", pathDescription, true);
650 LOG.info("Deleting otn-service path {} via renderer", serviceName);
651 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
652 "Deleting otn-service path via renderer");
653 OtnServicePathOutput result = otnDeviceRenderer.deleteOtnServicePath(ospi);
654 if (result.getSuccess()) {
655 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
656 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription);
664 * Send renderer notification.
665 * @param servicePathNotificationTypes ServicePathNotificationTypes
666 * @param serviceName String
667 * @param rpcStatusEx RpcStatusEx
668 * @param message String
670 private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
671 RpcStatusEx rpcStatusEx, String message) {
672 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
678 * Send renderer notification with path description information.
679 * @param servicePathNotificationTypes ServicePathNotificationTypes
680 * @param serviceName String
681 * @param rpcStatusEx RpcStatusEx
682 * @param message String
683 * @param pathDescription PathDescription
685 private void sendNotificationsWithPathDescription(ServicePathNotificationTypes servicePathNotificationTypes,
686 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription) {
687 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
693 * Build notification containing path description information.
694 * @param servicePathNotificationTypes ServicePathNotificationTypes
695 * @param serviceName String
696 * @param rpcStatusEx RpcStatusEx
697 * @param message String
698 * @param pathDescription PathDescription
699 * @return notification with RendererRpcResultSp type.
701 private RendererRpcResultSp buildNotification(ServicePathNotificationTypes servicePathNotificationTypes,
702 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription) {
703 RendererRpcResultSpBuilder builder = new RendererRpcResultSpBuilder()
704 .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx)
705 .setStatusMessage(message);
706 if (pathDescription != null) {
707 builder.setAToZDirection(pathDescription.getAToZDirection())
708 .setZToADirection(pathDescription.getZToADirection());
710 return builder.build();
714 * Send renderer notification.
715 * @param notification Notification
717 private void send(Notification notification) {
719 LOG.info("Sending notification {}", notification);
720 notificationPublishService.putNotification(notification);
721 } catch (InterruptedException e) {
722 LOG.info("notification offer rejected: ", e);
723 Thread.currentThread().interrupt();