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.renderer.rev210618.RendererRpcResultSp;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.RendererRpcResultSpBuilder;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceDeleteInput;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceDeleteOutput;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceImplementationRequestInput;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceImplementationRequestOutput;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.link._for.notif.ATerminationBuilder;
57 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.link._for.notif.ZTerminationBuilder;
58 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.renderer.rpc.result.sp.Link;
59 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.renderer.rpc.result.sp.LinkBuilder;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
65 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.PathDescription;
66 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx;
67 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.ServicePathNotificationTypes;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
70 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
71 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTp;
72 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.olm.get.pm.input.ResourceIdentifierBuilder;
73 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.optical.renderer.nodes.Nodes;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
75 import org.opendaylight.yangtools.yang.binding.Notification;
76 import org.opendaylight.yangtools.yang.common.RpcResult;
77 import org.opendaylight.yangtools.yang.common.Uint32;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
82 public class RendererServiceOperationsImpl implements RendererServiceOperations {
84 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
85 "Device rendering was not successful! Rendering will be rolled back.";
86 private static final String OLM_ROLL_BACK_MSG =
87 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
88 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
89 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
90 private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path";
91 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
92 private static final String FAILED = "Failed";
93 private static final String OPERATION_FAILED = "Operation Failed";
94 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
95 private static final int NUMBER_OF_THREADS = 4;
97 private final DeviceRendererService deviceRenderer;
98 private final OtnDeviceRendererService otnDeviceRenderer;
99 private final TransportpceOlmService olmService;
100 private final DataBroker dataBroker;
101 private final NotificationPublishService notificationPublishService;
102 private final PortMapping portMapping;
103 private ListeningExecutorService executor;
105 public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer,
106 OtnDeviceRendererService otnDeviceRenderer, TransportpceOlmService olmService,
107 DataBroker dataBroker, NotificationPublishService notificationPublishService, PortMapping portMapping) {
108 this.deviceRenderer = deviceRenderer;
109 this.otnDeviceRenderer = otnDeviceRenderer;
110 this.olmService = olmService;
111 this.dataBroker = dataBroker;
112 this.notificationPublishService = notificationPublishService;
113 this.portMapping = portMapping;
114 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
118 public ListenableFuture<ServiceImplementationRequestOutput>
119 serviceImplementation(ServiceImplementationRequestInput input) {
120 LOG.info("Calling service impl request {}", input.getServiceName());
121 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
124 public ServiceImplementationRequestOutput call() throws Exception {
125 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(),
126 RpcStatusEx.Pending, "Service compliant, submitting service implementation Request ...");
127 Uint32 serviceRate = getServiceRate(input);
128 String serviceType = ServiceTypes.getServiceType(
129 input.getServiceAEnd().getServiceFormat().getName(),
131 (NodeTypes.Xpdr.equals(portMapping.getNode(input.getServiceAEnd().getNodeId())
132 .getNodeInfo().getNodeType())
133 && input.getServiceAEnd().getTxDirection() != null
134 && input.getServiceAEnd().getTxDirection().getPort() != null
135 && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null)
136 ? portMapping.getMapping(input.getServiceAEnd().getNodeId(),
137 input.getServiceAEnd().getTxDirection().getPort().getPortName())
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 (!manageServicePathCreation(input, serviceType)) {
146 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
150 case StringConstants.SERVICE_TYPE_1GE:
151 case StringConstants.SERVICE_TYPE_10GE:
152 case StringConstants.SERVICE_TYPE_100GE_M:
153 case StringConstants.SERVICE_TYPE_ODU4:
154 case StringConstants.SERVICE_TYPE_ODUC4:
155 if (!manageOtnServicePathCreation(input, serviceType, serviceRate)) {
156 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
161 LOG.error("unsupported service-type");
164 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
165 OPERATION_SUCCESSFUL);
171 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
172 String serviceName = input.getServiceName();
173 LOG.info("Calling service delete request {}", serviceName);
174 return executor.submit(new Callable<ServiceDeleteOutput>() {
177 public ServiceDeleteOutput call() throws Exception {
178 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
179 RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
180 // Obtain path description
182 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service
183 .path.PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
184 if (!pathDescriptionOpt.isPresent()) {
185 LOG.error("Unable to get path description for service {}!", serviceName);
186 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
187 RpcStatusEx.Failed, "Unable to get path description for service");
188 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
191 PathDescription pathDescription = pathDescriptionOpt.get();
192 String serviceType = ServiceTypes.getServiceType(service.getServiceAEnd().getServiceFormat().getName(),
193 service.getServiceAEnd().getServiceRate(), null);
194 switch (serviceType) {
195 case StringConstants.SERVICE_TYPE_100GE_T:
196 case StringConstants.SERVICE_TYPE_400GE:
197 case StringConstants.SERVICE_TYPE_OTU4:
198 case StringConstants.SERVICE_TYPE_OTUC4:
199 if (!manageServicePathDeletion(serviceName, pathDescription, serviceType)) {
200 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
204 case StringConstants.SERVICE_TYPE_1GE:
205 case StringConstants.SERVICE_TYPE_10GE:
206 case StringConstants.SERVICE_TYPE_100GE_M:
207 case StringConstants.SERVICE_TYPE_ODU4:
208 case StringConstants.SERVICE_TYPE_ODUC4:
209 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service, serviceType)) {
210 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
215 LOG.error("unsupported service-type");
218 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
223 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
224 value = "UPM_UNCALLED_PRIVATE_METHOD",
225 justification = "call in call() method")
226 private Uint32 getServiceRate(ServiceImplementationRequestInput input) {
227 if (input.getServiceAEnd() == null) {
228 LOG.warn("Unable to get service-rate for service {}", input.getServiceName());
231 if (input.getServiceAEnd().getServiceRate() != null) {
232 return input.getServiceAEnd().getServiceRate();
234 if (ServiceFormat.OTU.equals(input.getServiceAEnd().getServiceFormat())
235 && input.getServiceAEnd().getOtuServiceRate() != null) {
236 switch (input.getServiceAEnd().getOtuServiceRate().getSimpleName()) {
238 return Uint32.valueOf(400);
240 return Uint32.valueOf(100);
243 return Uint32.valueOf(10);
245 LOG.warn("otu-service-rate {} not managed yet", input.getServiceAEnd().getOtuServiceRate()
249 } else if (ServiceFormat.ODU.equals(input.getServiceAEnd().getServiceFormat())
250 && input.getServiceAEnd().getOduServiceRate() != null) {
251 switch (input.getServiceAEnd().getOduServiceRate().getSimpleName()) {
253 return Uint32.valueOf(400);
255 return Uint32.valueOf(100);
258 return Uint32.valueOf(10);
260 return Uint32.valueOf(1);
262 LOG.warn("odu-service-rate {} not managed yet", input.getServiceAEnd().getOduServiceRate()
267 LOG.warn("Unable to get service-rate for service {} - otu-service-rate should not be null",
268 input.getServiceName());
273 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
274 value = "UPM_UNCALLED_PRIVATE_METHOD",
275 justification = "call in call() method")
276 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
277 throws InterruptedException, ExecutionException, TimeoutException {
278 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
279 Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
280 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
281 return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
284 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
285 value = "UPM_UNCALLED_PRIVATE_METHOD",
286 justification = "call in call() method")
287 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
288 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
289 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
290 .service.path.PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
291 .child(ServicePaths.class, new ServicePathsKey(serviceName))
292 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
293 .service.path.PathDescription.class);
294 ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
296 LOG.debug("Getting path description for service {}", serviceName);
297 return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
298 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
299 } catch (InterruptedException | ExecutionException | TimeoutException e) {
300 LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
302 return Optional.empty();
306 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
307 value = "UPM_UNCALLED_PRIVATE_METHOD",
308 justification = "call in call() method")
309 private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
310 ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
311 LOG.info(RENDERING_DEVICES_A_Z_MSG);
312 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
313 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
314 RENDERING_DEVICES_A_Z_MSG);
315 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
316 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
317 ServicePathDirection.A_TO_Z));
319 LOG.info("Rendering devices Z-A");
320 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
321 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
322 RENDERING_DEVICES_Z_A_MSG);
323 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
324 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
325 ServicePathDirection.Z_TO_A));
326 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
327 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
329 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
331 LOG.info("Waiting for A-Z and Z-A device renderers ...");
332 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
333 } catch (InterruptedException | ExecutionException | TimeoutException e) {
334 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
335 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
336 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
337 DEVICE_RENDERING_ROLL_BACK_MSG);
338 //FIXME we can't do rollback here, because we don't have rendering results.
339 return renderingResults;
342 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
343 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
344 this.deviceRenderer));
345 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
346 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
347 this.deviceRenderer));
348 return renderingResults;
351 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
352 value = "UPM_UNCALLED_PRIVATE_METHOD",
353 justification = "call in call() method")
354 private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
355 OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA) {
356 LOG.info(RENDERING_DEVICES_A_Z_MSG);
357 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
358 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
359 RENDERING_DEVICES_A_Z_MSG);
360 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
361 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ));
362 LOG.info("Rendering devices Z-A");
363 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
364 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
365 RENDERING_DEVICES_Z_A_MSG);
366 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
367 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA));
368 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
369 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
370 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
372 LOG.info("Waiting for A-Z and Z-A device renderers ...");
373 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
374 } catch (InterruptedException | ExecutionException | TimeoutException e) {
375 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
376 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
377 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
378 DEVICE_RENDERING_ROLL_BACK_MSG);
379 //FIXME we can't do rollback here, because we don't have rendering results.
380 return otnRenderingResults;
382 for (int i = 0; i < otnRenderingResults.size(); i++) {
383 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("DeviceTask n° " + i + 1,
384 ! otnRenderingResults.get(i).isSuccess(), otnRenderingResults.get(i).getRenderedNodeInterfaces(),
385 this.deviceRenderer));
387 return otnRenderingResults;
390 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
391 value = "UPM_UNCALLED_PRIVATE_METHOD",
392 justification = "call in call() method")
393 private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
394 ServicePowerSetupInput powerSetupInputZtoA) {
395 LOG.info("Olm power setup A-Z");
396 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
397 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
398 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
399 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
401 LOG.info("OLM power setup Z-A");
402 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
403 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
404 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
405 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
406 ListenableFuture<List<OLMRenderingResult>> olmFutures =
407 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
409 List<OLMRenderingResult> olmResults;
411 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
412 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
413 } catch (InterruptedException | ExecutionException | TimeoutException e) {
414 LOG.warn(OLM_ROLL_BACK_MSG, e);
415 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
416 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
418 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
419 this.olmService, powerSetupInputAtoZ));
420 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
421 this.olmService, powerSetupInputZtoA));
425 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
426 this.olmService, powerSetupInputAtoZ));
427 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
428 this.olmService, powerSetupInputZtoA));
431 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
432 value = "UPM_UNCALLED_PRIVATE_METHOD",
433 justification = "call in call() method")
434 private boolean isServiceActivated(String nodeId, String tpId) {
435 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
436 for (int i = 0; i < 3; i++) {
437 List<Measurements> measurements = getMeasurements(nodeId, tpId);
438 if ((measurements != null) && verifyPreFecBer(measurements)) {
440 } else if (measurements == null) {
441 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
445 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
446 } catch (InterruptedException ex) {
447 Thread.currentThread().interrupt();
451 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
455 private List<Measurements> getMeasurements(String nodeId, String tp) {
456 GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder()
458 .setGranularity(PmGranularity._15min)
459 .setResourceIdentifier(new ResourceIdentifierBuilder().setResourceName(tp + "-OTU").build())
460 .setResourceType(ResourceTypeEnum.Interface);
463 Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
464 RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
465 GetPmOutput getPmOutput = getPmRpcResult.getResult();
466 if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
467 LOG.info("successfully finished calling OLM's get PM");
468 return getPmOutput.getMeasurements();
471 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
474 } catch (ExecutionException | InterruptedException e) {
475 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
480 private boolean verifyPreFecBer(List<Measurements> measurements) {
481 double preFecCorrectedErrors = Double.MIN_VALUE;
482 double fecUncorrectableBlocks = Double.MIN_VALUE;
484 for (Measurements measurement : measurements) {
485 if (measurement.getPmparameterName().equals("preFECCorrectedErrors")) {
486 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
488 if (measurement.getPmparameterName().equals("FECUncorrectableBlocks")) {
489 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
493 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
494 fecUncorrectableBlocks);
496 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
497 LOG.error("Data has uncorrectable errors, BER test failed");
500 double numOfBitsPerSecond = 112000000000d;
501 double threshold = 0.00002d;
502 double result = preFecCorrectedErrors / numOfBitsPerSecond;
503 LOG.info("PreFEC value is {}", Double.toString(result));
504 return result <= threshold;
508 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
509 value = "UPM_UNCALLED_PRIVATE_METHOD",
510 justification = "call in call() method")
511 private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType) {
512 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
513 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create);
514 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
515 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create);
516 // Rollback should be same for all conditions, so creating a new one
517 RollbackProcessor rollbackProcessor = new RollbackProcessor();
518 List<DeviceRenderingResult> renderingResults =
519 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
520 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
521 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
522 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
525 ServicePowerSetupInput olmPowerSetupInputAtoZ =
526 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input);
527 ServicePowerSetupInput olmPowerSetupInputZtoA =
528 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input);
529 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
530 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
531 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
532 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
535 // run service activation test twice - once on source node and once on
537 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
538 if ((nodes == null) || (nodes.isEmpty())) {
542 Nodes sourceNode = nodes.get(0);
543 Nodes destNode = nodes.get(nodes.size() - 1);
544 String srcNetworkTp =
545 sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
546 ? sourceNode.getDestTp()
547 : sourceNode.getSrcTp();
548 String dstNetowrkTp =
549 destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
550 ? destNode.getDestTp()
551 : destNode.getSrcTp();
553 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
554 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
555 rollbackProcessor.rollbackAll();
556 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
557 input.getServiceName(), RpcStatusEx.Failed,
558 "Service activation test failed.");
561 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
562 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
563 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
565 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
566 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
567 notifLink, serviceType);
571 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
572 value = "UPM_UNCALLED_PRIVATE_METHOD",
573 justification = "call in call() method")
574 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType)
575 throws InterruptedException {
576 ServicePathInputData servicePathInputDataAtoZ =
577 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete);
578 ServicePathInputData servicePathInputDataZtoA =
579 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete);
580 // OLM turn down power
582 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
583 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
584 RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
585 ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
586 // TODO add some flag rather than string
587 if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
588 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
589 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
590 "Service power turndown failed on A-to-Z path for service");
593 LOG.debug("Turning down power on Z-to-A path");
594 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
595 "Turning down power on Z-to-A path");
596 ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
597 // TODO add some flag rather than string
598 if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
599 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
600 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
601 "Service power turndown failed on Z-to-A path for service");
604 } catch (InterruptedException | ExecutionException | TimeoutException e) {
605 LOG.error("Error while turning down power!", e);
608 // delete service path with renderer
609 LOG.info("Deleting service path via renderer");
610 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
611 "Deleting service path via renderer");
612 RollbackProcessor rollbackProcessor = new RollbackProcessor();
613 List<DeviceRenderingResult> renderingResults =
614 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
615 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
616 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
617 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
619 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
620 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, serviceType);
624 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
625 value = "UPM_UNCALLED_PRIVATE_METHOD",
626 justification = "call in call() method")
627 private boolean manageOtnServicePathCreation(ServiceImplementationRequestInput input, String serviceType,
628 Uint32 serviceRate) {
630 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
631 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
632 input.getServiceAEnd().getServiceFormat().getName(),
634 input.getPathDescription(), true);
636 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
637 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
638 input.getServiceZEnd().getServiceFormat().getName(),
640 input.getPathDescription(), false);
641 // Rollback should be same for all conditions, so creating a new one
642 RollbackProcessor rollbackProcessor = new RollbackProcessor();
643 List<OtnDeviceRenderingResult> renderingResults =
644 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA);
645 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
646 rollbackProcessor.rollbackAll();
647 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
648 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
651 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
652 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
653 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
655 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
656 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
657 notifLink, serviceType);
661 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
662 value = "UPM_UNCALLED_PRIVATE_METHOD",
663 justification = "call in call() method")
664 private boolean manageOtnServicePathDeletion(String serviceName, PathDescription pathDescription,
665 Services service, String serviceType) {
667 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
668 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
669 service.getServiceAEnd().getServiceFormat().getName(),
670 service.getServiceAEnd().getServiceRate(),
671 pathDescription, true);
673 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
674 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
675 service.getServiceZEnd().getServiceFormat().getName(),
676 service.getServiceAEnd().getServiceRate(),
677 pathDescription, false);
678 LOG.info("Deleting otn-service path {} via renderer", serviceName);
679 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
680 "Deleting otn-service path via renderer");
682 RollbackProcessor rollbackProcessor = new RollbackProcessor();
683 List<OtnDeviceRenderingResult> renderingResults =
684 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA);
686 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
687 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
688 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
690 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
691 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, serviceType);
696 * Send renderer notification.
697 * @param servicePathNotificationTypes ServicePathNotificationTypes
698 * @param serviceName String
699 * @param rpcStatusEx RpcStatusEx
700 * @param message String
702 private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
703 RpcStatusEx rpcStatusEx, String message) {
704 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
710 * Send renderer notification with path description information.
711 * @param servicePathNotificationTypes ServicePathNotificationTypes
712 * @param serviceName String
713 * @param rpcStatusEx RpcStatusEx
714 * @param message String
715 * @param pathDescription PathDescription
717 private void sendNotificationsWithPathDescription(ServicePathNotificationTypes servicePathNotificationTypes,
718 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
719 Link notifLink, String serviceType) {
720 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
721 pathDescription, notifLink, serviceType);
726 * Build notification containing path description information.
727 * @param servicePathNotificationTypes ServicePathNotificationTypes
728 * @param serviceName String
729 * @param rpcStatusEx RpcStatusEx
730 * @param message String
731 * @param pathDescription PathDescription
732 * @return notification with RendererRpcResultSp type.
734 private RendererRpcResultSp buildNotification(ServicePathNotificationTypes servicePathNotificationTypes,
735 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
736 Link notifLink, String serviceType) {
737 RendererRpcResultSpBuilder builder = new RendererRpcResultSpBuilder()
738 .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx)
739 .setStatusMessage(message)
740 .setServiceType(serviceType);
741 if (pathDescription != null) {
742 builder.setAToZDirection(pathDescription.getAToZDirection())
743 .setZToADirection(pathDescription.getZToADirection());
745 if (notifLink != null) {
746 builder.setLink(notifLink);
748 return builder.build();
752 * Send renderer notification.
753 * @param notification Notification
755 private void send(Notification notification) {
757 LOG.info("Sending notification {}", notification);
758 notificationPublishService.putNotification(notification);
759 } catch (InterruptedException e) {
760 LOG.info("notification offer rejected: ", e);
761 Thread.currentThread().interrupt();
765 private Link createLinkForNotif(List<LinkTp> otnLinkTerminationPoints) {
766 if (otnLinkTerminationPoints.size() != 2 || otnLinkTerminationPoints.isEmpty()) {
769 return new LinkBuilder()
770 .setATermination(new ATerminationBuilder()
771 .setNodeId(otnLinkTerminationPoints.get(0).getNodeId())
772 .setTpId(otnLinkTerminationPoints.get(0).getTpId())
774 .setZTermination(new ZTerminationBuilder()
775 .setNodeId(otnLinkTerminationPoints.get(1).getNodeId())
776 .setTpId(otnLinkTerminationPoints.get(1).getTpId())