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.rev201126.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().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,
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";
142 LOG.info("Start rendering for {} service with {} rate and {} format",
143 input.getServiceName(), serviceRate,
144 input.getServiceAEnd().getServiceFormat());
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,
160 LOG.info("OTN rendering result size {}", otnRenderingResults.size());
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,
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
183 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
184 .rendererCreateOtnServiceInput(input.getServiceName(),
185 input.getServiceAEnd().getServiceFormat().getName(),
187 input.getPathDescription(), true);
189 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
190 .rendererCreateOtnServiceInput(input.getServiceName(),
191 input.getServiceZEnd().getServiceFormat().getName(),
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,
204 LOG.info("OTN rendering result size {}", otnRenderingResults.size());
208 LOG.warn("Unsupported connection type {}", input.getConnectionType());
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);
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>() {
227 public ServiceDeleteOutput call() throws Exception {
228 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
229 RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
230 // Obtain path description
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();
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,
244 switch (service.getConnectionType()) {
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,
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,
265 if (ServiceFormat.OTU.equals(service.getServiceAEnd().getServiceFormat())) {
266 if (!manageServicePathDeletion(serviceName, pathDescription)) {
267 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
270 } else if (ServiceFormat.ODU.equals(service.getServiceAEnd().getServiceFormat())) {
271 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service)) {
272 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
278 LOG.error("Unmanaged connection-type for deletion of service {}", serviceName);
281 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
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();
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();
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,
315 return Optional.empty();
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));
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);
342 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
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;
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;
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);
385 renderingCombinedFuture = Futures.allAsList(atozrenderingFuture);
387 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
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;
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));
404 return otnRenderingResults;
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));
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);
426 List<OLMRenderingResult> olmResults;
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,
435 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
436 this.olmService, powerSetupInputAtoZ));
437 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
438 this.olmService, powerSetupInputZtoA));
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));
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)) {
457 } else if (measurements == null) {
458 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
462 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
463 } catch (InterruptedException ex) {
464 Thread.currentThread().interrupt();
468 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
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);
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();
490 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
493 } catch (ExecutionException | InterruptedException e) {
494 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
499 private boolean verifyPreFecBer(List<Measurements> measurements) {
500 double preFecCorrectedErrors = Double.MIN_VALUE;
501 double fecUncorrectableBlocks = Double.MIN_VALUE;
503 for (Measurements measurement : measurements) {
504 if (measurement.getPmparameterName().equals("preFECCorrectedErrors")) {
505 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
507 if (measurement.getPmparameterName().equals("FECUncorrectableBlocks")) {
508 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
512 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
513 fecUncorrectableBlocks);
515 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
516 LOG.error("Data has uncorrectable errors, BER test failed");
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;
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);
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);
554 // run service activation test twice - once on source node and once on
556 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
557 if ((nodes == null) || (nodes.isEmpty())) {
561 Nodes sourceNode = nodes.get(0);
562 Nodes destNode = nodes.get(nodes.size() - 1);
565 if (sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
566 srcNetworkTp = sourceNode.getDestTp();
568 srcNetworkTp = sourceNode.getSrcTp();
570 if (destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
571 dstNetowrkTp = destNode.getDestTp();
573 dstNetowrkTp = destNode.getSrcTp();
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.");
583 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
584 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription());
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
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");
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");
620 } catch (InterruptedException | ExecutionException | TimeoutException e) {
621 LOG.error("Error while turning down power!", e);
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);
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,
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);
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.isSuccess()) {
654 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
655 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription);
663 * Send renderer notification.
664 * @param servicePathNotificationTypes ServicePathNotificationTypes
665 * @param serviceName String
666 * @param rpcStatusEx RpcStatusEx
667 * @param message String
669 private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
670 RpcStatusEx rpcStatusEx, String message) {
671 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
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
684 private void sendNotificationsWithPathDescription(ServicePathNotificationTypes servicePathNotificationTypes,
685 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription) {
686 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
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.
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());
709 return builder.build();
713 * Send renderer notification.
714 * @param notification Notification
716 private void send(Notification notification) {
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();