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.Action;
42 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev210618.OtnServicePathInput;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmInputBuilder;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmOutput;
45 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerSetupInput;
46 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownInputBuilder;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownOutput;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.TransportpceOlmService;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.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.rev210618.RendererRpcResultSp;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.RendererRpcResultSpBuilder;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceDeleteInput;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceDeleteOutput;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceImplementationRequestInput;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceImplementationRequestOutput;
57 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.link._for.notif.ATerminationBuilder;
58 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.link._for.notif.ZTerminationBuilder;
59 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.renderer.rpc.result.sp.Link;
60 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.renderer.rpc.result.sp.LinkBuilder;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
66 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.PathDescription;
67 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.ServicePathNotificationTypes;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
70 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
71 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
72 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTp;
73 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.olm.get.pm.input.ResourceIdentifierBuilder;
74 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.optical.renderer.nodes.Nodes;
75 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
76 import org.opendaylight.yangtools.yang.binding.Notification;
77 import org.opendaylight.yangtools.yang.common.RpcResult;
78 import org.opendaylight.yangtools.yang.common.Uint32;
79 import org.slf4j.Logger;
80 import org.slf4j.LoggerFactory;
83 public class RendererServiceOperationsImpl implements RendererServiceOperations {
85 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
86 "Device rendering was not successful! Rendering will be rolled back.";
87 private static final String OLM_ROLL_BACK_MSG =
88 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
89 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
90 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
91 private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path";
92 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
93 private static final String FAILED = "Failed";
94 private static final String OPERATION_FAILED = "Operation Failed";
95 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
96 private static final int NUMBER_OF_THREADS = 4;
98 private final DeviceRendererService deviceRenderer;
99 private final OtnDeviceRendererService otnDeviceRenderer;
100 private final TransportpceOlmService olmService;
101 private final DataBroker dataBroker;
102 private final NotificationPublishService notificationPublishService;
103 private final PortMapping portMapping;
104 private ListeningExecutorService executor;
106 public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer,
107 OtnDeviceRendererService otnDeviceRenderer, TransportpceOlmService olmService,
108 DataBroker dataBroker, NotificationPublishService notificationPublishService, PortMapping portMapping) {
109 this.deviceRenderer = deviceRenderer;
110 this.otnDeviceRenderer = otnDeviceRenderer;
111 this.olmService = olmService;
112 this.dataBroker = dataBroker;
113 this.notificationPublishService = notificationPublishService;
114 this.portMapping = portMapping;
115 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
119 public ListenableFuture<ServiceImplementationRequestOutput>
120 serviceImplementation(ServiceImplementationRequestInput input) {
121 LOG.info("Calling service impl request {}", input.getServiceName());
122 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
125 public ServiceImplementationRequestOutput call() throws Exception {
126 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(),
127 RpcStatusEx.Pending, "Service compliant, submitting service implementation Request ...");
128 Uint32 serviceRate = getServiceRate(input);
130 if (NodeTypes.Xpdr.equals(portMapping.getNode(input.getServiceAEnd().getNodeId())
131 .getNodeInfo().getNodeType())
132 && input.getServiceAEnd().getTxDirection() != null
133 && input.getServiceAEnd().getTxDirection().getPort() != null
134 && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null) {
135 Mapping mapping = portMapping.getMapping(input.getServiceAEnd().getNodeId(),
136 input.getServiceAEnd().getTxDirection().getPort().getPortName());
137 serviceType = ServiceTypes.getServiceType(input.getServiceAEnd().getServiceFormat().getName(),
138 serviceRate, mapping);
140 serviceType = ServiceTypes.getServiceType(input.getServiceAEnd().getServiceFormat().getName(),
144 switch (serviceType) {
145 case StringConstants.SERVICE_TYPE_100GE_T:
146 case StringConstants.SERVICE_TYPE_400GE:
147 case StringConstants.SERVICE_TYPE_OTU4:
148 case StringConstants.SERVICE_TYPE_OTUC4:
149 if (!manageServicePathCreation(input, serviceType)) {
150 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
154 case StringConstants.SERVICE_TYPE_1GE:
155 case StringConstants.SERVICE_TYPE_10GE:
156 case StringConstants.SERVICE_TYPE_100GE_M:
157 case StringConstants.SERVICE_TYPE_ODU4:
158 case StringConstants.SERVICE_TYPE_ODUC4:
159 if (!manageOtnServicePathCreation(input, serviceType, serviceRate)) {
160 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
165 LOG.error("unsupported service-type");
168 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
169 OPERATION_SUCCESSFUL);
175 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
176 String serviceName = input.getServiceName();
177 LOG.info("Calling service delete request {}", serviceName);
178 return executor.submit(new Callable<ServiceDeleteOutput>() {
181 public ServiceDeleteOutput call() throws Exception {
182 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
183 RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
184 // Obtain path description
186 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service
187 .path.PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
188 PathDescription pathDescription;
189 if (pathDescriptionOpt.isPresent()) {
190 pathDescription = pathDescriptionOpt.get();
192 LOG.error("Unable to get path description for service {}!", serviceName);
193 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
194 RpcStatusEx.Failed, "Unable to get path description for service");
195 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
198 String serviceType = ServiceTypes.getServiceType(service.getServiceAEnd().getServiceFormat().getName(),
199 service.getServiceAEnd().getServiceRate(), null);
200 switch (serviceType) {
201 case StringConstants.SERVICE_TYPE_100GE_T:
202 case StringConstants.SERVICE_TYPE_400GE:
203 case StringConstants.SERVICE_TYPE_OTU4:
204 case StringConstants.SERVICE_TYPE_OTUC4:
205 if (!manageServicePathDeletion(serviceName, pathDescription, serviceType)) {
206 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
210 case StringConstants.SERVICE_TYPE_1GE:
211 case StringConstants.SERVICE_TYPE_10GE:
212 case StringConstants.SERVICE_TYPE_100GE_M:
213 case StringConstants.SERVICE_TYPE_ODU4:
214 case StringConstants.SERVICE_TYPE_ODUC4:
215 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service, serviceType)) {
216 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
221 LOG.error("unsupported service-type");
224 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
229 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
230 value = "UPM_UNCALLED_PRIVATE_METHOD",
231 justification = "call in call() method")
232 private Uint32 getServiceRate(ServiceImplementationRequestInput input) {
233 if (input.getServiceAEnd() == null) {
234 LOG.warn("Unable to get service-rate for service {}", input.getServiceName());
237 if (input.getServiceAEnd().getServiceRate() != null) {
238 return input.getServiceAEnd().getServiceRate();
240 if (ServiceFormat.OTU.equals(input.getServiceAEnd().getServiceFormat())
241 && input.getServiceAEnd().getOtuServiceRate() != null) {
242 switch (input.getServiceAEnd().getOtuServiceRate().getSimpleName()) {
244 return Uint32.valueOf(400);
246 return Uint32.valueOf(100);
249 return Uint32.valueOf(10);
251 LOG.warn("otu-service-rate {} not managed yet", input.getServiceAEnd().getOtuServiceRate()
255 } else if (ServiceFormat.ODU.equals(input.getServiceAEnd().getServiceFormat())
256 && input.getServiceAEnd().getOduServiceRate() != null) {
257 switch (input.getServiceAEnd().getOduServiceRate().getSimpleName()) {
259 return Uint32.valueOf(400);
261 return Uint32.valueOf(100);
264 return Uint32.valueOf(10);
266 return Uint32.valueOf(1);
268 LOG.warn("odu-service-rate {} not managed yet", input.getServiceAEnd().getOduServiceRate()
273 LOG.warn("Unable to get service-rate for service {} - otu-service-rate should not be null",
274 input.getServiceName());
279 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
280 value = "UPM_UNCALLED_PRIVATE_METHOD",
281 justification = "call in call() method")
282 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
283 throws InterruptedException, ExecutionException, TimeoutException {
284 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
285 Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
286 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
287 return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
290 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
291 value = "UPM_UNCALLED_PRIVATE_METHOD",
292 justification = "call in call() method")
293 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
294 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
295 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
296 .service.path.PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
297 .child(ServicePaths.class, new ServicePathsKey(serviceName))
298 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
299 .service.path.PathDescription.class);
300 ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
302 LOG.debug("Getting path description for service {}", serviceName);
303 return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
304 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
305 } catch (InterruptedException | ExecutionException | TimeoutException e) {
306 LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
308 return Optional.empty();
312 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
313 value = "UPM_UNCALLED_PRIVATE_METHOD",
314 justification = "call in call() method")
315 private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
316 ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
317 LOG.info(RENDERING_DEVICES_A_Z_MSG);
318 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
319 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
320 RENDERING_DEVICES_A_Z_MSG);
321 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
322 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
323 ServicePathDirection.A_TO_Z));
325 LOG.info("Rendering devices Z-A");
326 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
327 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
328 RENDERING_DEVICES_Z_A_MSG);
329 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
330 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
331 ServicePathDirection.Z_TO_A));
332 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
333 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
335 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
337 LOG.info("Waiting for A-Z and Z-A device renderers ...");
338 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
339 } catch (InterruptedException | ExecutionException | TimeoutException e) {
340 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
341 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
342 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
343 DEVICE_RENDERING_ROLL_BACK_MSG);
344 //FIXME we can't do rollback here, because we don't have rendering results.
345 return renderingResults;
348 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
349 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
350 this.deviceRenderer));
351 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
352 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
353 this.deviceRenderer));
354 return renderingResults;
357 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
358 value = "UPM_UNCALLED_PRIVATE_METHOD",
359 justification = "call in call() method")
360 private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
361 OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA) {
362 LOG.info(RENDERING_DEVICES_A_Z_MSG);
363 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
364 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
365 RENDERING_DEVICES_A_Z_MSG);
366 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
367 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ));
368 LOG.info("Rendering devices Z-A");
369 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
370 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
371 RENDERING_DEVICES_Z_A_MSG);
372 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
373 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA));
374 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
375 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
376 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
378 LOG.info("Waiting for A-Z and Z-A device renderers ...");
379 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
380 } catch (InterruptedException | ExecutionException | TimeoutException e) {
381 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
382 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
383 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
384 DEVICE_RENDERING_ROLL_BACK_MSG);
385 //FIXME we can't do rollback here, because we don't have rendering results.
386 return otnRenderingResults;
388 for (int i = 0; i < otnRenderingResults.size(); i++) {
389 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("DeviceTask n° " + i + 1,
390 ! otnRenderingResults.get(i).isSuccess(), otnRenderingResults.get(i).getRenderedNodeInterfaces(),
391 this.deviceRenderer));
393 return otnRenderingResults;
396 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
397 value = "UPM_UNCALLED_PRIVATE_METHOD",
398 justification = "call in call() method")
399 private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
400 ServicePowerSetupInput powerSetupInputZtoA) {
401 LOG.info("Olm power setup A-Z");
402 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
403 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
404 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
405 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
407 LOG.info("OLM power setup Z-A");
408 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
409 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
410 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
411 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
412 ListenableFuture<List<OLMRenderingResult>> olmFutures =
413 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
415 List<OLMRenderingResult> olmResults;
417 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
418 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
419 } catch (InterruptedException | ExecutionException | TimeoutException e) {
420 LOG.warn(OLM_ROLL_BACK_MSG, e);
421 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
422 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
424 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
425 this.olmService, powerSetupInputAtoZ));
426 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
427 this.olmService, powerSetupInputZtoA));
431 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
432 this.olmService, powerSetupInputAtoZ));
433 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
434 this.olmService, powerSetupInputZtoA));
437 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
438 value = "UPM_UNCALLED_PRIVATE_METHOD",
439 justification = "call in call() method")
440 private boolean isServiceActivated(String nodeId, String tpId) {
441 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
442 for (int i = 0; i < 3; i++) {
443 List<Measurements> measurements = getMeasurements(nodeId, tpId);
444 if ((measurements != null) && verifyPreFecBer(measurements)) {
446 } else if (measurements == null) {
447 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
451 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
452 } catch (InterruptedException ex) {
453 Thread.currentThread().interrupt();
457 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
461 private List<Measurements> getMeasurements(String nodeId, String tp) {
462 GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder();
463 getPmIpBldr.setNodeId(nodeId);
464 getPmIpBldr.setGranularity(PmGranularity._15min);
465 ResourceIdentifierBuilder rsrcBldr = new ResourceIdentifierBuilder();
466 rsrcBldr.setResourceName(tp + "-OTU");
467 getPmIpBldr.setResourceIdentifier(rsrcBldr.build());
468 getPmIpBldr.setResourceType(ResourceTypeEnum.Interface);
471 Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
472 RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
473 GetPmOutput getPmOutput = getPmRpcResult.getResult();
474 if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
475 LOG.info("successfully finished calling OLM's get PM");
476 return getPmOutput.getMeasurements();
479 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
482 } catch (ExecutionException | InterruptedException e) {
483 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
488 private boolean verifyPreFecBer(List<Measurements> measurements) {
489 double preFecCorrectedErrors = Double.MIN_VALUE;
490 double fecUncorrectableBlocks = Double.MIN_VALUE;
492 for (Measurements measurement : measurements) {
493 if (measurement.getPmparameterName().equals("preFECCorrectedErrors")) {
494 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
496 if (measurement.getPmparameterName().equals("FECUncorrectableBlocks")) {
497 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
501 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
502 fecUncorrectableBlocks);
504 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
505 LOG.error("Data has uncorrectable errors, BER test failed");
508 double numOfBitsPerSecond = 112000000000d;
509 double threshold = 0.00002d;
510 double result = preFecCorrectedErrors / numOfBitsPerSecond;
511 LOG.info("PreFEC value is {}", Double.toString(result));
512 return result <= threshold;
516 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
517 value = "UPM_UNCALLED_PRIVATE_METHOD",
518 justification = "call in call() method")
519 private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType) {
520 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
521 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create);
522 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
523 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create);
524 // Rollback should be same for all conditions, so creating a new one
525 RollbackProcessor rollbackProcessor = new RollbackProcessor();
526 List<DeviceRenderingResult> renderingResults =
527 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
528 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
529 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
530 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
533 ServicePowerSetupInput olmPowerSetupInputAtoZ =
534 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input);
535 ServicePowerSetupInput olmPowerSetupInputZtoA =
536 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input);
537 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
538 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
539 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
540 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
543 // run service activation test twice - once on source node and once on
545 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
546 if ((nodes == null) || (nodes.isEmpty())) {
550 Nodes sourceNode = nodes.get(0);
551 Nodes destNode = nodes.get(nodes.size() - 1);
554 if (sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
555 srcNetworkTp = sourceNode.getDestTp();
557 srcNetworkTp = sourceNode.getSrcTp();
559 if (destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
560 dstNetowrkTp = destNode.getDestTp();
562 dstNetowrkTp = destNode.getSrcTp();
564 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
565 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
566 rollbackProcessor.rollbackAll();
567 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
568 input.getServiceName(), RpcStatusEx.Failed,
569 "Service activation test failed.");
572 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
573 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
574 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
576 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
577 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
578 notifLink, serviceType);
582 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
583 value = "UPM_UNCALLED_PRIVATE_METHOD",
584 justification = "call in call() method")
585 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType)
586 throws InterruptedException {
587 ServicePathInputData servicePathInputDataAtoZ =
588 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete);
589 ServicePathInputData servicePathInputDataZtoA =
590 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete);
591 // OLM turn down power
593 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
594 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
595 RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
596 ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
597 // TODO add some flag rather than string
598 if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
599 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
600 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
601 "Service power turndown failed on A-to-Z path for service");
604 LOG.debug("Turning down power on Z-to-A path");
605 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
606 "Turning down power on Z-to-A path");
607 ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
608 // TODO add some flag rather than string
609 if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
610 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
611 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
612 "Service power turndown failed on Z-to-A path for service");
615 } catch (InterruptedException | ExecutionException | TimeoutException e) {
616 LOG.error("Error while turning down power!", e);
619 // delete service path with renderer
620 LOG.info("Deleting service path via renderer");
621 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
622 "Deleting service path via renderer");
623 RollbackProcessor rollbackProcessor = new RollbackProcessor();
624 List<DeviceRenderingResult> renderingResults =
625 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
626 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
627 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
628 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
630 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
631 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, serviceType);
635 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
636 value = "UPM_UNCALLED_PRIVATE_METHOD",
637 justification = "call in call() method")
638 private boolean manageOtnServicePathCreation(ServiceImplementationRequestInput input, String serviceType,
639 Uint32 serviceRate) {
641 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
642 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
643 input.getServiceAEnd().getServiceFormat().getName(),
645 input.getPathDescription(), true);
647 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
648 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
649 input.getServiceZEnd().getServiceFormat().getName(),
651 input.getPathDescription(), false);
652 // Rollback should be same for all conditions, so creating a new one
653 RollbackProcessor rollbackProcessor = new RollbackProcessor();
654 List<OtnDeviceRenderingResult> renderingResults =
655 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA);
656 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
657 rollbackProcessor.rollbackAll();
658 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
659 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
662 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
663 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
664 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
666 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
667 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
668 notifLink, serviceType);
672 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
673 value = "UPM_UNCALLED_PRIVATE_METHOD",
674 justification = "call in call() method")
675 private boolean manageOtnServicePathDeletion(String serviceName, PathDescription pathDescription,
676 Services service, String serviceType) {
678 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
679 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
680 service.getServiceAEnd().getServiceFormat().getName(),
681 service.getServiceAEnd().getServiceRate(),
682 pathDescription, true);
684 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
685 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
686 service.getServiceZEnd().getServiceFormat().getName(),
687 service.getServiceAEnd().getServiceRate(),
688 pathDescription, false);
689 LOG.info("Deleting otn-service path {} via renderer", serviceName);
690 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
691 "Deleting otn-service path via renderer");
693 RollbackProcessor rollbackProcessor = new RollbackProcessor();
694 List<OtnDeviceRenderingResult> renderingResults =
695 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA);
697 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
698 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
699 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
701 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
702 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, serviceType);
707 * Send renderer notification.
708 * @param servicePathNotificationTypes ServicePathNotificationTypes
709 * @param serviceName String
710 * @param rpcStatusEx RpcStatusEx
711 * @param message String
713 private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
714 RpcStatusEx rpcStatusEx, String message) {
715 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
721 * Send renderer notification with path description information.
722 * @param servicePathNotificationTypes ServicePathNotificationTypes
723 * @param serviceName String
724 * @param rpcStatusEx RpcStatusEx
725 * @param message String
726 * @param pathDescription PathDescription
728 private void sendNotificationsWithPathDescription(ServicePathNotificationTypes servicePathNotificationTypes,
729 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
730 Link notifLink, String serviceType) {
731 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
732 pathDescription, notifLink, serviceType);
737 * Build notification containing path description information.
738 * @param servicePathNotificationTypes ServicePathNotificationTypes
739 * @param serviceName String
740 * @param rpcStatusEx RpcStatusEx
741 * @param message String
742 * @param pathDescription PathDescription
743 * @return notification with RendererRpcResultSp type.
745 private RendererRpcResultSp buildNotification(ServicePathNotificationTypes servicePathNotificationTypes,
746 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
747 Link notifLink, String serviceType) {
748 RendererRpcResultSpBuilder builder = new RendererRpcResultSpBuilder()
749 .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx)
750 .setStatusMessage(message)
751 .setServiceType(serviceType);
752 if (pathDescription != null) {
753 builder.setAToZDirection(pathDescription.getAToZDirection())
754 .setZToADirection(pathDescription.getZToADirection());
756 if (notifLink != null) {
757 builder.setLink(notifLink);
759 return builder.build();
763 * Send renderer notification.
764 * @param notification Notification
766 private void send(Notification notification) {
768 LOG.info("Sending notification {}", notification);
769 notificationPublishService.putNotification(notification);
770 } catch (InterruptedException e) {
771 LOG.info("notification offer rejected: ", e);
772 Thread.currentThread().interrupt();
776 private Link createLinkForNotif(List<LinkTp> otnLinkTerminationPoints) {
777 if (otnLinkTerminationPoints.size() != 2 || otnLinkTerminationPoints.isEmpty()) {
780 return new LinkBuilder()
781 .setATermination(new ATerminationBuilder()
782 .setNodeId(otnLinkTerminationPoints.get(0).getNodeId())
783 .setTpId(otnLinkTerminationPoints.get(0).getTpId())
785 .setZTermination(new ZTerminationBuilder()
786 .setNodeId(otnLinkTerminationPoints.get(1).getNodeId())
787 .setTpId(otnLinkTerminationPoints.get(1).getTpId())