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.common.mapping.PortMapping;
31 import org.opendaylight.transportpce.common.service.ServiceTypes;
32 import org.opendaylight.transportpce.renderer.ModelMappingUtils;
33 import org.opendaylight.transportpce.renderer.ServicePathInputData;
34 import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection;
35 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingRollbackTask;
36 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingTask;
37 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupRollbackTask;
38 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupTask;
39 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OtnDeviceRenderingTask;
40 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor;
41 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev210618.OtnServicePathInput;
42 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev210618.OtnServicePathOutput;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.GetPmInputBuilder;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.GetPmOutput;
45 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerSetupInput;
46 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerTurndownInputBuilder;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerTurndownOutput;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.TransportpceOlmService;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.get.pm.output.Measurements;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210426.mapping.Mapping;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.RendererRpcResultSp;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.RendererRpcResultSpBuilder;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceDeleteInput;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceDeleteOutput;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceImplementationRequestInput;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev201125.ServiceImplementationRequestOutput;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ConnectionType;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
63 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.PathDescription;
64 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx;
65 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.ServicePathNotificationTypes;
66 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
67 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev201211.olm.get.pm.input.ResourceIdentifierBuilder;
70 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev201211.olm.renderer.input.Nodes;
71 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
72 import org.opendaylight.yangtools.yang.binding.Notification;
73 import org.opendaylight.yangtools.yang.common.RpcResult;
74 import org.opendaylight.yangtools.yang.common.Uint32;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
79 public class RendererServiceOperationsImpl implements RendererServiceOperations {
81 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
82 "Device rendering was not successful! Rendering will be rolled back.";
83 private static final String OLM_ROLL_BACK_MSG =
84 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
85 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
86 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
87 private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path";
88 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
89 private static final String FAILED = "Failed";
90 private static final String OPERATION_FAILED = "Operation Failed";
91 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
92 private static final int NUMBER_OF_THREADS = 4;
94 private final DeviceRendererService deviceRenderer;
95 private final OtnDeviceRendererService otnDeviceRenderer;
96 private final TransportpceOlmService olmService;
97 private final DataBroker dataBroker;
98 private final NotificationPublishService notificationPublishService;
99 private final PortMapping portMapping;
100 private ListeningExecutorService executor;
102 public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer,
103 OtnDeviceRendererService otnDeviceRenderer, TransportpceOlmService olmService,
104 DataBroker dataBroker, NotificationPublishService notificationPublishService, PortMapping portMapping) {
105 this.deviceRenderer = deviceRenderer;
106 this.otnDeviceRenderer = otnDeviceRenderer;
107 this.olmService = olmService;
108 this.dataBroker = dataBroker;
109 this.notificationPublishService = notificationPublishService;
110 this.portMapping = portMapping;
111 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
115 public ListenableFuture<ServiceImplementationRequestOutput>
116 serviceImplementation(ServiceImplementationRequestInput input) {
117 LOG.info("Calling service impl request {}", input.getServiceName());
118 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
121 public ServiceImplementationRequestOutput call() throws Exception {
122 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(),
123 RpcStatusEx.Pending, "Service compliant, submitting service implementation Request ...");
124 Uint32 serviceRate = getServiceRate(input);
126 if (NodeTypes.Xpdr.equals(portMapping.getNode(input.getServiceAEnd().getNodeId())
127 .getNodeInfo().getNodeType())
128 && input.getServiceAEnd().getTxDirection() != null
129 && input.getServiceAEnd().getTxDirection().getPort() != null
130 && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null) {
131 Mapping mapping = portMapping.getMapping(input.getServiceAEnd().getNodeId(),
132 input.getServiceAEnd().getTxDirection().getPort().getPortName());
133 serviceType = ServiceTypes.getServiceType(input.getServiceAEnd().getServiceFormat().getName(),
134 serviceRate, mapping);
136 serviceType = ServiceTypes.getServiceType(input.getServiceAEnd().getServiceFormat().getName(),
140 switch (serviceType) {
141 case StringConstants.SERVICE_TYPE_100GE_T:
142 case StringConstants.SERVICE_TYPE_400GE:
143 case StringConstants.SERVICE_TYPE_OTU4:
144 case StringConstants.SERVICE_TYPE_OTUC4:
145 if (!createServicepathInput(input)) {
146 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
150 case StringConstants.SERVICE_TYPE_1GE:
151 case StringConstants.SERVICE_TYPE_10GE:
152 case StringConstants.SERVICE_TYPE_ODU4:
153 case StringConstants.SERVICE_TYPE_ODUC4:
155 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
156 .rendererCreateOtnServiceInput(input.getServiceName(),
157 input.getServiceAEnd().getServiceFormat().getName(),
159 input.getPathDescription(), true);
161 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
162 .rendererCreateOtnServiceInput(input.getServiceName(),
163 input.getServiceZEnd().getServiceFormat().getName(),
165 input.getPathDescription(), false);
166 // Rollback should be same for all conditions, so creating a new one
167 RollbackProcessor rollbackProcessor = new RollbackProcessor();
168 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA);
169 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
170 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
171 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
172 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
177 LOG.error("unsupported service-type");
181 sendNotificationsWithPathDescription(
182 ServicePathNotificationTypes.ServiceImplementationRequest,
183 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL,
184 input.getPathDescription());
185 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
186 OPERATION_SUCCESSFUL);
192 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
193 String serviceName = input.getServiceName();
194 LOG.info("Calling service delete request {}", serviceName);
195 return executor.submit(new Callable<ServiceDeleteOutput>() {
198 public ServiceDeleteOutput call() throws Exception {
199 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
200 RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
201 // Obtain path description
203 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service
204 .path.PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
205 PathDescription pathDescription;
206 if (pathDescriptionOpt.isPresent()) {
207 pathDescription = pathDescriptionOpt.get();
209 LOG.error("Unable to get path description for service {}!", serviceName);
210 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
211 RpcStatusEx.Failed, "Unable to get path description for service");
212 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
215 String serviceType = ServiceTypes.getServiceType(service.getServiceAEnd().getServiceFormat().getName(),
216 service.getServiceAEnd().getServiceRate(), null);
217 switch (serviceType) {
218 case StringConstants.SERVICE_TYPE_100GE_T:
219 case StringConstants.SERVICE_TYPE_400GE:
220 case StringConstants.SERVICE_TYPE_OTU4:
221 case StringConstants.SERVICE_TYPE_OTUC4:
222 if (!manageServicePathDeletion(serviceName, pathDescription)) {
223 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
227 case StringConstants.SERVICE_TYPE_1GE:
228 case StringConstants.SERVICE_TYPE_10GE:
229 case StringConstants.SERVICE_TYPE_ODU4:
230 case StringConstants.SERVICE_TYPE_ODUC4:
231 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service)) {
232 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
237 LOG.error("unsupported service-type");
240 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
245 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
246 value = "UPM_UNCALLED_PRIVATE_METHOD",
247 justification = "call in call() method")
248 private Uint32 getServiceRate(ServiceImplementationRequestInput input) {
249 if (input.getServiceAEnd() == null) {
250 LOG.warn("Unable to get service-rate for service {}", input.getServiceName());
253 if (input.getServiceAEnd().getServiceRate() != null) {
254 return input.getServiceAEnd().getServiceRate();
256 if (ServiceFormat.OTU.equals(input.getServiceAEnd().getServiceFormat())
257 && input.getServiceAEnd().getOtuServiceRate() != null) {
258 switch (input.getServiceAEnd().getOtuServiceRate().getSimpleName()) {
260 return Uint32.valueOf(400);
262 return Uint32.valueOf(100);
265 return Uint32.valueOf(10);
267 LOG.warn("otu-service-rate {} not managed yet", input.getServiceAEnd().getOtuServiceRate()
271 } else if (ServiceFormat.ODU.equals(input.getServiceAEnd().getServiceFormat())
272 && input.getServiceAEnd().getOduServiceRate() != null) {
273 switch (input.getServiceAEnd().getOduServiceRate().getSimpleName()) {
275 return Uint32.valueOf(400);
277 return Uint32.valueOf(100);
280 return Uint32.valueOf(10);
282 return Uint32.valueOf(1);
284 LOG.warn("odu-service-rate {} not managed yet", input.getServiceAEnd().getOduServiceRate()
289 LOG.warn("Unable to get service-rate for service {} - otu-service-rate should not be null",
290 input.getServiceName());
295 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
296 value = "UPM_UNCALLED_PRIVATE_METHOD",
297 justification = "call in call() method")
298 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
299 throws InterruptedException, ExecutionException, TimeoutException {
300 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
301 Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
302 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
303 return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
306 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
307 value = "UPM_UNCALLED_PRIVATE_METHOD",
308 justification = "call in call() method")
309 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
310 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
311 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
312 .service.path.PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
313 .child(ServicePaths.class, new ServicePathsKey(serviceName))
314 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
315 .service.path.PathDescription.class);
316 ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
318 LOG.debug("Getting path description for service {}", serviceName);
319 return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
320 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
321 } catch (InterruptedException | ExecutionException | TimeoutException e) {
322 LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
324 return Optional.empty();
328 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
329 value = "UPM_UNCALLED_PRIVATE_METHOD",
330 justification = "call in call() method")
331 private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
332 ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
333 LOG.info(RENDERING_DEVICES_A_Z_MSG);
334 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
335 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
336 RENDERING_DEVICES_A_Z_MSG);
337 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
338 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
339 ServicePathDirection.A_TO_Z));
341 LOG.info("Rendering devices Z-A");
342 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
343 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
344 RENDERING_DEVICES_Z_A_MSG);
345 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
346 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
347 ServicePathDirection.Z_TO_A));
348 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
349 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
351 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
353 LOG.info("Waiting for A-Z and Z-A device renderers ...");
354 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
355 } catch (InterruptedException | ExecutionException | TimeoutException e) {
356 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
357 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
358 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
359 DEVICE_RENDERING_ROLL_BACK_MSG);
360 //FIXME we can't do rollback here, because we don't have rendering results.
361 return renderingResults;
364 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
365 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
366 this.deviceRenderer));
367 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
368 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
369 this.deviceRenderer));
370 return renderingResults;
373 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
374 value = "UPM_UNCALLED_PRIVATE_METHOD",
375 justification = "call in call() method")
376 private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
377 OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA) {
378 LOG.info(RENDERING_DEVICES_A_Z_MSG);
379 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
380 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
381 RENDERING_DEVICES_A_Z_MSG);
382 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
383 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ));
384 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture;
385 if (otnServicePathZtoA != null) {
386 LOG.info("Rendering devices Z-A");
387 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
388 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
389 RENDERING_DEVICES_Z_A_MSG);
390 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
391 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA));
392 renderingCombinedFuture = Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
394 renderingCombinedFuture = Futures.allAsList(atozrenderingFuture);
396 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
398 LOG.info("Waiting for A-Z and Z-A device renderers ...");
399 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
400 } catch (InterruptedException | ExecutionException | TimeoutException e) {
401 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
402 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
403 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
404 DEVICE_RENDERING_ROLL_BACK_MSG);
405 //FIXME we can't do rollback here, because we don't have rendering results.
406 return otnRenderingResults;
408 for (int i = 0; i < otnRenderingResults.size(); i++) {
409 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("DeviceTask n° " + i + 1,
410 ! otnRenderingResults.get(i).isSuccess(), otnRenderingResults.get(i).getRenderedNodeInterfaces(),
411 this.deviceRenderer));
413 return otnRenderingResults;
416 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
417 value = "UPM_UNCALLED_PRIVATE_METHOD",
418 justification = "call in call() method")
419 private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
420 ServicePowerSetupInput powerSetupInputZtoA) {
421 LOG.info("Olm power setup A-Z");
422 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
423 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
424 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
425 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
427 LOG.info("OLM power setup Z-A");
428 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
429 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
430 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
431 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
432 ListenableFuture<List<OLMRenderingResult>> olmFutures =
433 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
435 List<OLMRenderingResult> olmResults;
437 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
438 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
439 } catch (InterruptedException | ExecutionException | TimeoutException e) {
440 LOG.warn(OLM_ROLL_BACK_MSG, e);
441 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
442 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
444 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
445 this.olmService, powerSetupInputAtoZ));
446 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
447 this.olmService, powerSetupInputZtoA));
451 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
452 this.olmService, powerSetupInputAtoZ));
453 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
454 this.olmService, powerSetupInputZtoA));
457 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
458 value = "UPM_UNCALLED_PRIVATE_METHOD",
459 justification = "call in call() method")
460 private boolean isServiceActivated(String nodeId, String tpId) {
461 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
462 for (int i = 0; i < 3; i++) {
463 List<Measurements> measurements = getMeasurements(nodeId, tpId);
464 if ((measurements != null) && verifyPreFecBer(measurements)) {
466 } else if (measurements == null) {
467 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
471 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
472 } catch (InterruptedException ex) {
473 Thread.currentThread().interrupt();
477 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
481 private List<Measurements> getMeasurements(String nodeId, String tp) {
482 GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder();
483 getPmIpBldr.setNodeId(nodeId);
484 getPmIpBldr.setGranularity(PmGranularity._15min);
485 ResourceIdentifierBuilder rsrcBldr = new ResourceIdentifierBuilder();
486 rsrcBldr.setResourceName(tp + "-OTU");
487 getPmIpBldr.setResourceIdentifier(rsrcBldr.build());
488 getPmIpBldr.setResourceType(ResourceTypeEnum.Interface);
491 Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
492 RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
493 GetPmOutput getPmOutput = getPmRpcResult.getResult();
494 if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
495 LOG.info("successfully finished calling OLM's get PM");
496 return getPmOutput.getMeasurements();
499 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
502 } catch (ExecutionException | InterruptedException e) {
503 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
508 private boolean verifyPreFecBer(List<Measurements> measurements) {
509 double preFecCorrectedErrors = Double.MIN_VALUE;
510 double fecUncorrectableBlocks = Double.MIN_VALUE;
512 for (Measurements measurement : measurements) {
513 if (measurement.getPmparameterName().equals("preFECCorrectedErrors")) {
514 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
516 if (measurement.getPmparameterName().equals("FECUncorrectableBlocks")) {
517 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
521 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
522 fecUncorrectableBlocks);
524 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
525 LOG.error("Data has uncorrectable errors, BER test failed");
528 double numOfBitsPerSecond = 112000000000d;
529 double threshold = 0.00002d;
530 double result = preFecCorrectedErrors / numOfBitsPerSecond;
531 LOG.info("PreFEC value is {}", Double.toString(result));
532 return result <= threshold;
536 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
537 value = "UPM_UNCALLED_PRIVATE_METHOD",
538 justification = "call in call() method")
539 private boolean createServicepathInput(ServiceImplementationRequestInput input) {
540 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
541 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription());
542 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
543 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription());
544 // Rollback should be same for all conditions, so creating a new one
545 RollbackProcessor rollbackProcessor = new RollbackProcessor();
546 List<DeviceRenderingResult> renderingResults =
547 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
548 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
549 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
550 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
553 ServicePowerSetupInput olmPowerSetupInputAtoZ =
554 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input);
555 ServicePowerSetupInput olmPowerSetupInputZtoA =
556 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input);
557 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
558 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
559 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
560 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
563 // run service activation test twice - once on source node and once on
565 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
566 if ((nodes == null) || (nodes.isEmpty())) {
570 Nodes sourceNode = nodes.get(0);
571 Nodes destNode = nodes.get(nodes.size() - 1);
574 if (sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
575 srcNetworkTp = sourceNode.getDestTp();
577 srcNetworkTp = sourceNode.getSrcTp();
579 if (destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
580 dstNetowrkTp = destNode.getDestTp();
582 dstNetowrkTp = destNode.getSrcTp();
584 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
585 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
586 rollbackProcessor.rollbackAll();
587 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
588 input.getServiceName(), RpcStatusEx.Failed,
589 "Service activation test failed.");
592 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
593 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription());
597 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
598 value = "UPM_UNCALLED_PRIVATE_METHOD",
599 justification = "call in call() method")
600 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription) {
601 ServicePathInputData servicePathInputDataAtoZ =
602 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription);
603 ServicePathInputData servicePathInputDataZtoA =
604 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription);
605 // OLM turn down power
607 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
608 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
609 RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
610 ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
611 // TODO add some flag rather than string
612 if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
613 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
614 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
615 "Service power turndown failed on A-to-Z path for service");
618 LOG.debug("Turning down power on Z-to-A path");
619 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
620 "Turning down power on Z-to-A path");
621 ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
622 // TODO add some flag rather than string
623 if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
624 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
625 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
626 "Service power turndown failed on Z-to-A path for service");
629 } catch (InterruptedException | ExecutionException | TimeoutException e) {
630 LOG.error("Error while turning down power!", e);
633 // delete service path with renderer
634 LOG.info("Deleting service path via renderer");
635 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
636 "Deleting service path via renderer");
637 deviceRenderer.deleteServicePath(servicePathInputDataAtoZ.getServicePathInput());
638 deviceRenderer.deleteServicePath(servicePathInputDataZtoA.getServicePathInput());
639 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
640 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL,pathDescription);
644 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
645 value = "UPM_UNCALLED_PRIVATE_METHOD",
646 justification = "call in call() method")
647 private boolean manageOtnServicePathDeletion(String serviceName, PathDescription pathDescription,
649 OtnServicePathInput ospi = null;
650 if (ConnectionType.Infrastructure.equals(service.getConnectionType())) {
651 ospi = ModelMappingUtils.rendererCreateOtnServiceInput(
652 serviceName, service.getServiceAEnd().getServiceFormat().getName(), Uint32.valueOf(100),
653 pathDescription, true);
654 } else if (ConnectionType.Service.equals(service.getConnectionType())) {
655 ospi = ModelMappingUtils.rendererCreateOtnServiceInput(serviceName,
656 service.getServiceAEnd().getServiceFormat().getName(),
657 service.getServiceAEnd().getServiceRate(), pathDescription, true);
659 LOG.info("Deleting otn-service path {} via renderer", serviceName);
660 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
661 "Deleting otn-service path via renderer");
662 OtnServicePathOutput result = otnDeviceRenderer.deleteOtnServicePath(ospi);
663 if (result.getSuccess()) {
664 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
665 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription);
673 * Send renderer notification.
674 * @param servicePathNotificationTypes ServicePathNotificationTypes
675 * @param serviceName String
676 * @param rpcStatusEx RpcStatusEx
677 * @param message String
679 private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
680 RpcStatusEx rpcStatusEx, String message) {
681 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
687 * Send renderer notification with path description information.
688 * @param servicePathNotificationTypes ServicePathNotificationTypes
689 * @param serviceName String
690 * @param rpcStatusEx RpcStatusEx
691 * @param message String
692 * @param pathDescription PathDescription
694 private void sendNotificationsWithPathDescription(ServicePathNotificationTypes servicePathNotificationTypes,
695 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription) {
696 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
702 * Build notification containing path description information.
703 * @param servicePathNotificationTypes ServicePathNotificationTypes
704 * @param serviceName String
705 * @param rpcStatusEx RpcStatusEx
706 * @param message String
707 * @param pathDescription PathDescription
708 * @return notification with RendererRpcResultSp type.
710 private RendererRpcResultSp buildNotification(ServicePathNotificationTypes servicePathNotificationTypes,
711 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription) {
712 RendererRpcResultSpBuilder builder = new RendererRpcResultSpBuilder()
713 .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx)
714 .setStatusMessage(message);
715 if (pathDescription != null) {
716 builder.setAToZDirection(pathDescription.getAToZDirection())
717 .setZToADirection(pathDescription.getZToADirection());
719 return builder.build();
723 * Send renderer notification.
724 * @param notification Notification
726 private void send(Notification notification) {
728 LOG.info("Sending notification {}", notification);
729 notificationPublishService.putNotification(notification);
730 } catch (InterruptedException e) {
731 LOG.info("notification offer rejected: ", e);
732 Thread.currentThread().interrupt();