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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
15 import java.util.ArrayList;
16 import java.util.List;
18 import java.util.Optional;
20 import java.util.concurrent.Callable;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.Executors;
23 import java.util.concurrent.TimeUnit;
24 import java.util.concurrent.TimeoutException;
25 import java.util.stream.Collectors;
26 import org.opendaylight.mdsal.binding.api.DataBroker;
27 import org.opendaylight.mdsal.binding.api.RpcService;
28 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
29 import org.opendaylight.transportpce.common.ResponseCodes;
30 import org.opendaylight.transportpce.common.StringConstants;
31 import org.opendaylight.transportpce.common.Timeouts;
32 import org.opendaylight.transportpce.common.mapping.PortMapping;
33 import org.opendaylight.transportpce.common.service.ServiceTypes;
34 import org.opendaylight.transportpce.renderer.ModelMappingUtils;
35 import org.opendaylight.transportpce.renderer.ServicePathInputData;
36 import org.opendaylight.transportpce.renderer.provisiondevice.notification.Notification;
37 import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection;
38 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingRollbackTask;
39 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingTask;
40 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.NetworkDeviceRenderingRollbackTask;
41 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupRollbackTask;
42 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupTask;
43 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerTurnDownTask;
44 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OtnDeviceRenderingTask;
45 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor;
46 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackResultMessage;
47 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.History;
48 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.TransactionHistory;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.Action;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathInput;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev220630.OtnLinkType;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPm;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmInputBuilder;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmOutput;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerSetup;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerSetupInput;
57 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndown;
58 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.get.pm.output.Measurements;
59 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteInput;
60 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteOutput;
61 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestInput;
62 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestOutput;
63 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ATerminationBuilder;
64 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ZTerminationBuilder;
65 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.Link;
66 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.LinkBuilder;
67 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
68 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
69 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev191129.ServiceFormat;
70 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.Services;
71 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.PathDescription;
72 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.RpcStatusEx;
73 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.ServicePathNotificationTypes;
74 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
75 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
76 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
77 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.PmGranularity;
78 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.link.tp.LinkTp;
79 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.olm.get.pm.input.ResourceIdentifierBuilder;
80 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.optical.renderer.nodes.Nodes;
81 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
82 import org.opendaylight.yangtools.yang.common.Uint32;
83 import org.osgi.service.component.annotations.Activate;
84 import org.osgi.service.component.annotations.Component;
85 import org.osgi.service.component.annotations.Reference;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
90 @Component(immediate = true)
91 public class RendererServiceOperationsImpl implements RendererServiceOperations {
93 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
94 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
95 "Device rendering was not successful! Rendering will be rolled back.";
96 private static final String OLM_ROLL_BACK_MSG =
97 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
98 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
99 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
100 private static final String ATOZPATH = "A-to-Z";
101 private static final String ZTOAPATH = "Z-to-A";
102 private static final String OPERATION_FAILED = "Operation Failed";
103 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
104 private static final int NUMBER_OF_THREADS = 4;
106 private final DeviceRendererService deviceRenderer;
107 private final OtnDeviceRendererService otnDeviceRenderer;
108 private final DataBroker dataBroker;
109 private final Notification notification;
110 private final PortMapping portMapping;
111 private final RpcService rpcService;
112 private ListeningExecutorService executor;
115 public RendererServiceOperationsImpl(@Reference DeviceRendererService deviceRenderer,
116 @Reference OtnDeviceRendererService otnDeviceRenderer,
117 @Reference DataBroker dataBroker,
118 @Reference Notification notification,
119 @Reference PortMapping portMapping,
120 @Reference RpcService rpcService) {
121 this.deviceRenderer = deviceRenderer;
122 this.otnDeviceRenderer = otnDeviceRenderer;
123 this.dataBroker = dataBroker;
124 this.notification = notification;
125 this.portMapping = portMapping;
126 this.rpcService = rpcService;
127 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
128 LOG.debug("RendererServiceOperationsImpl instantiated");
132 public ListenableFuture<ServiceImplementationRequestOutput>
133 serviceImplementation(ServiceImplementationRequestInput input, boolean isTempService) {
134 LOG.info("Calling service impl request {}", input.getServiceName());
135 LOG.debug("Check if it is temp-service {}", isTempService);
136 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
139 public ServiceImplementationRequestOutput call() throws Exception {
141 ServicePathNotificationTypes.ServiceImplementationRequest,
142 input.getServiceName(),
144 "Service compliant, submitting service implementation Request ...");
145 Uint32 serviceRate = getServiceRate(input);
146 LOG.info("Using {}G rate", serviceRate);
147 org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221
148 .network.Nodes mappingNode =
149 portMapping.isNodeExist(input.getServiceAEnd().getNodeId())
150 ? portMapping.getNode(input.getServiceAEnd().getNodeId())
152 String serviceType = ServiceTypes.getServiceType(
153 input.getServiceAEnd().getServiceFormat().getName(),
156 && NodeTypes.Xpdr.equals(mappingNode.getNodeInfo().getNodeType())
157 && input.getServiceAEnd().getTxDirection() != null
158 && input.getServiceAEnd().getTxDirection().getPort() != null
159 && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null
160 ? portMapping.getMapping(input.getServiceAEnd().getNodeId(),
161 input.getServiceAEnd().getTxDirection().getPort().getPortName())
163 //TODO a Map might be more indicated here
164 switch (serviceType) {
165 case StringConstants.SERVICE_TYPE_100GE_T:
166 case StringConstants.SERVICE_TYPE_400GE:
167 case StringConstants.SERVICE_TYPE_OTU4:
168 case StringConstants.SERVICE_TYPE_OTUC2:
169 case StringConstants.SERVICE_TYPE_OTUC3:
170 case StringConstants.SERVICE_TYPE_OTUC4:
171 LOG.debug("Check temp service {}", isTempService);
172 if (!manageServicePathCreation(input, serviceType, isTempService)) {
173 return ModelMappingUtils
174 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
177 case StringConstants.SERVICE_TYPE_1GE:
178 case StringConstants.SERVICE_TYPE_10GE:
179 case StringConstants.SERVICE_TYPE_100GE_M:
180 case StringConstants.SERVICE_TYPE_100GE_S:
181 case StringConstants.SERVICE_TYPE_ODU4:
182 case StringConstants.SERVICE_TYPE_ODUC2:
183 case StringConstants.SERVICE_TYPE_ODUC3:
184 case StringConstants.SERVICE_TYPE_ODUC4:
185 if (!manageOtnServicePathCreation(input, serviceType, serviceRate)) {
186 return ModelMappingUtils
187 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
191 LOG.error("unsupported service-type");
192 return ModelMappingUtils
193 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
195 return ModelMappingUtils
196 .createServiceImplResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
202 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
203 String serviceName = input.getServiceName();
204 LOG.info("Calling service delete request {}", serviceName);
205 return executor.submit(new Callable<ServiceDeleteOutput>() {
208 public ServiceDeleteOutput call() throws Exception {
210 ServicePathNotificationTypes.ServiceDelete,
213 "Service compliant, submitting service delete Request ...");
214 // Obtain path description
216 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
217 .service.path.PathDescription> pathDescriptionOpt =
218 getPathDescriptionFromDatastore(serviceName);
219 if (pathDescriptionOpt.isEmpty()) {
220 LOG.error("Unable to get path description for service {}!", serviceName);
222 ServicePathNotificationTypes.ServiceDelete,
225 "Unable to get path description for service");
226 return ModelMappingUtils
227 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
229 PathDescription pathDescription = pathDescriptionOpt.orElseThrow();
231 ServiceTypes.getServiceType(
232 service.getServiceAEnd().getServiceFormat().getName(),
233 service.getServiceAEnd().getServiceRate(),
234 service.getServiceAEnd().getTxDirection() == null
235 || service.getServiceAEnd().getTxDirection().values().stream().findFirst().orElseThrow()
237 || service.getServiceAEnd().getTxDirection().values().stream().findFirst().orElseThrow()
238 .getPort().getPortName() == null
240 : portMapping.getMapping(
241 service.getServiceAEnd().getNodeId().getValue(),
242 service.getServiceAEnd().getTxDirection().values().stream().findFirst()
243 .orElseThrow().getPort().getPortName()));
244 switch (serviceType) {
245 case StringConstants.SERVICE_TYPE_100GE_T:
246 case StringConstants.SERVICE_TYPE_400GE:
247 case StringConstants.SERVICE_TYPE_OTU4:
248 case StringConstants.SERVICE_TYPE_OTUC2:
249 case StringConstants.SERVICE_TYPE_OTUC3:
250 case StringConstants.SERVICE_TYPE_OTUC4:
251 if (!manageServicePathDeletion(serviceName, pathDescription, serviceType)) {
252 return ModelMappingUtils
253 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
256 case StringConstants.SERVICE_TYPE_1GE:
257 case StringConstants.SERVICE_TYPE_10GE:
258 case StringConstants.SERVICE_TYPE_100GE_M:
259 case StringConstants.SERVICE_TYPE_100GE_S:
260 case StringConstants.SERVICE_TYPE_ODU4:
261 case StringConstants.SERVICE_TYPE_ODUC2:
262 case StringConstants.SERVICE_TYPE_ODUC3:
263 case StringConstants.SERVICE_TYPE_ODUC4:
264 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service, serviceType)) {
265 return ModelMappingUtils
266 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
270 LOG.error("unsupported service-type");
271 return ModelMappingUtils
272 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
274 return ModelMappingUtils
275 .createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
281 value = "UPM_UNCALLED_PRIVATE_METHOD",
282 justification = "call in call() method")
283 private Uint32 getServiceRate(ServiceImplementationRequestInput input) {
284 if (input.getServiceAEnd() == null) {
285 LOG.warn("Unable to get service-rate for service {}", input.getServiceName());
288 if (input.getServiceAEnd().getServiceRate() != null) {
289 return input.getServiceAEnd().getServiceRate();
291 LOG.warn("Input should have rate if you are using 200 or 300G");
292 // TODO: missing 200, and 300G rates here, OTUCn cannot always be 400G
293 Map<ServiceFormat, Map<String, Uint32>> formatRateMap = Map.of(
294 ServiceFormat.OTU, Map.of(
295 "OTUCn", Uint32.valueOf(400),
296 "OTU4", Uint32.valueOf(100),
297 "OTU2", Uint32.valueOf(10),
298 "OTU2e", Uint32.valueOf(10)),
299 ServiceFormat.ODU, Map.of(
300 "ODUCn",Uint32.valueOf(400),
301 "ODU4", Uint32.valueOf(100),
302 "ODU2", Uint32.valueOf(10),
303 "ODU2e", Uint32.valueOf(10),
304 "ODU0", Uint32.valueOf(1)));
305 if (!formatRateMap.containsKey(input.getServiceAEnd().getServiceFormat())) {
306 LOG.warn("Unable to get service-rate for service {} - unsupported service format {}",
307 input.getServiceName(), input.getServiceAEnd().getServiceFormat());
311 ServiceFormat.OTU.getName().equals(input.getServiceAEnd().getServiceFormat().getName())
312 ? input.getServiceAEnd().getOtuServiceRate().toString().split("\\{")[0]
313 : input.getServiceAEnd().getOduServiceRate().toString().split("\\{")[0];
314 if (!formatRateMap.get(input.getServiceAEnd().getServiceFormat()).containsKey(serviceName)) {
315 LOG.warn("Unable to get service-rate for service {} - unsupported service name {}",
316 input.getServiceName(), serviceName);
320 .get(input.getServiceAEnd().getServiceFormat())
325 value = "UPM_UNCALLED_PRIVATE_METHOD",
326 justification = "call in call() method")
327 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
328 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
329 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
330 .service.path.PathDescription> pathDescriptionIID =
331 InstanceIdentifier.create(ServicePathList.class)
332 .child(ServicePaths.class, new ServicePathsKey(serviceName))
333 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
334 .service.path.PathDescription.class);
336 LOG.debug("Getting path description for service {}", serviceName);
337 return this.dataBroker.newReadOnlyTransaction()
338 .read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
339 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
340 } catch (InterruptedException | ExecutionException | TimeoutException e) {
341 LOG.warn("Exception while getting path description from datastore {} for service {}!",
342 pathDescriptionIID, serviceName, e);
343 return Optional.empty();
348 value = "UPM_UNCALLED_PRIVATE_METHOD",
349 justification = "call in call() method")
350 private List<DeviceRenderingResult> deviceRendering(
351 RollbackProcessor rollbackProcessor,
352 ServicePathInputData servicePathDataAtoZ,
353 ServicePathInputData servicePathDataZtoA) {
355 //TODO atozrenderingFuture & ztoarenderingFuture & renderingCombinedFuture used only once
356 // Do notifications & LOG.info deserve this ?
357 LOG.info(RENDERING_DEVICES_A_Z_MSG);
359 ServicePathNotificationTypes.ServiceImplementationRequest,
360 servicePathDataAtoZ.getServicePathInput().getServiceName(),
362 RENDERING_DEVICES_A_Z_MSG);
364 History transactionHistory = new TransactionHistory();
365 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
366 this.executor.submit(
367 new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ, ServicePathDirection.A_TO_Z,
368 transactionHistory));
370 LOG.info(RENDERING_DEVICES_Z_A_MSG);
372 ServicePathNotificationTypes.ServiceImplementationRequest,
373 servicePathDataZtoA.getServicePathInput().getServiceName(),
375 RENDERING_DEVICES_Z_A_MSG);
376 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
377 this.executor.submit(
378 new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA, ServicePathDirection.Z_TO_A,
379 transactionHistory));
381 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
382 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
384 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
386 LOG.info("Waiting for A-Z and Z-A device renderers ...");
387 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
388 } catch (InterruptedException | ExecutionException | TimeoutException e) {
389 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
391 ServicePathNotificationTypes.ServiceImplementationRequest,
392 servicePathDataAtoZ.getServicePathInput().getServiceName(),
394 DEVICE_RENDERING_ROLL_BACK_MSG);
395 //FIXME we can't do rollback here, because we don't have rendering results.
396 return renderingResults;
399 rollbackProcessor.addTask(
400 new NetworkDeviceRenderingRollbackTask(
401 "RollbackTransactionHistoryTask",
403 ! (renderingResults.get(0).isSuccess() && renderingResults.get(1).isSuccess()),
405 new RollbackResultMessage()
409 return renderingResults;
413 value = "UPM_UNCALLED_PRIVATE_METHOD",
414 justification = "call in call() method")
415 private List<OtnDeviceRenderingResult> otnDeviceRendering(
416 RollbackProcessor rollbackProcessor,
417 OtnServicePathInput otnServicePathAtoZ,
418 OtnServicePathInput otnServicePathZtoA,
419 String serviceType) {
421 //TODO atozrenderingFuture & ztoarenderingFuture & renderingCombinedFuture used only once
422 // Do notifications & LOG.info deserve this ?
423 LOG.info(RENDERING_DEVICES_A_Z_MSG);
425 ServicePathNotificationTypes.ServiceImplementationRequest,
426 otnServicePathAtoZ.getServiceName(),
428 RENDERING_DEVICES_A_Z_MSG);
429 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
430 this.executor.submit(
431 new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ, serviceType));
433 LOG.info(RENDERING_DEVICES_Z_A_MSG);
435 ServicePathNotificationTypes.ServiceImplementationRequest,
436 otnServicePathZtoA.getServiceName(),
438 RENDERING_DEVICES_Z_A_MSG);
439 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
440 this.executor.submit(
441 new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA, serviceType));
443 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
444 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
445 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
447 LOG.info("Waiting for A-Z and Z-A device renderers ...");
448 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
449 } catch (InterruptedException | ExecutionException | TimeoutException e) {
450 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
452 ServicePathNotificationTypes.ServiceImplementationRequest,
453 otnServicePathAtoZ.getServiceName(),
455 DEVICE_RENDERING_ROLL_BACK_MSG);
456 //FIXME we can't do rollback here, because we don't have rendering results.
457 return otnRenderingResults;
459 for (int i = 0; i < otnRenderingResults.size(); i++) {
460 rollbackProcessor.addTask(
461 new DeviceRenderingRollbackTask(
462 "DeviceTask n° " + i + 1,
463 ! otnRenderingResults.get(i).isSuccess(),
464 otnRenderingResults.get(i).getRenderedNodeInterfaces(),
465 this.deviceRenderer));
467 return otnRenderingResults;
471 value = "UPM_UNCALLED_PRIVATE_METHOD",
472 justification = "call in call() method")
473 private void olmPowerSetup(
474 RollbackProcessor rollbackProcessor,
475 ServicePowerSetupInput powerSetupInputAtoZ,
476 ServicePowerSetupInput powerSetupInputZtoA, boolean isTempService) {
478 //TODO olmPowerSetupFutureAtoZ & olmPowerSetupFutureZtoA & olmFutures used only once
479 // Do notifications & LOG.info deserve this ?
480 //TODO use constants for LOG.info & notifications common messages
481 // if the service create is a temp-service, OLM will be skipped
483 LOG.info("For temp-service create OLM is not computed and skipped");
486 LOG.info("Olm power setup A-Z");
488 ServicePathNotificationTypes.ServiceImplementationRequest,
489 powerSetupInputAtoZ.getServiceName(),
491 "Olm power setup A-Z");
492 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ =
493 this.executor.submit(
494 new OlmPowerSetupTask(rpcService.getRpc(ServicePowerSetup.class), powerSetupInputAtoZ));
496 LOG.info("OLM power setup Z-A");
498 ServicePathNotificationTypes.ServiceImplementationRequest,
499 powerSetupInputAtoZ.getServiceName(),
501 "Olm power setup Z-A");
502 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA =
503 this.executor.submit(
504 new OlmPowerSetupTask(rpcService.getRpc(ServicePowerSetup.class), powerSetupInputZtoA));
505 ListenableFuture<List<OLMRenderingResult>> olmFutures =
506 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
508 List<OLMRenderingResult> olmResults;
510 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
511 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
512 } catch (InterruptedException | ExecutionException | TimeoutException e) {
513 LOG.warn(OLM_ROLL_BACK_MSG, e);
515 ServicePathNotificationTypes.ServiceImplementationRequest,
516 powerSetupInputAtoZ.getServiceName(),
519 rollbackProcessor.addTask(
520 new OlmPowerSetupRollbackTask("AtoZOLMTask", true, rpcService.getRpc(ServicePowerTurndown.class),
521 powerSetupInputAtoZ));
522 rollbackProcessor.addTask(
523 new OlmPowerSetupRollbackTask("ZtoAOLMTask", true, rpcService.getRpc(ServicePowerTurndown.class),
524 powerSetupInputZtoA));
527 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask(
528 "AtoZOLMTask", !olmResults.get(0).isSuccess(), rpcService.getRpc(ServicePowerTurndown.class),
529 powerSetupInputAtoZ));
530 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask(
531 "ZtoAOLMTask", !olmResults.get(1).isSuccess(), rpcService.getRpc(ServicePowerTurndown.class),
532 powerSetupInputZtoA));
536 value = "UPM_UNCALLED_PRIVATE_METHOD",
537 justification = "call in call() method")
538 private boolean isServiceActivated(String nodeId, String tpId) {
539 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
540 if (!NodeTypes.Xpdr.equals(portMapping.getNode(nodeId).getNodeInfo().getNodeType())) {
541 LOG.info("Device {} is not xponder, can't verify PreFEC", nodeId);
544 for (int i = 0; i < 3; i++) {
545 List<Measurements> measurements = getMeasurements(nodeId, tpId);
546 if (measurements == null) {
547 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
550 if (verifyPreFecBer(measurements)) {
554 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
555 } catch (InterruptedException ex) {
556 Thread.currentThread().interrupt();
559 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
563 private List<Measurements> getMeasurements(String nodeId, String tp) {
565 GetPmOutput getPmOutput = rpcService.getRpc(GetPm.class).invoke(
566 new GetPmInputBuilder()
568 .setGranularity(PmGranularity._15min)
569 .setResourceIdentifier(new ResourceIdentifierBuilder().setResourceName(tp + "-OTU").build())
570 .setResourceType(ResourceTypeEnum.Interface)
574 if ((getPmOutput == null) || (getPmOutput.getNodeId() == null)) {
575 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
577 LOG.info("successfully finished calling OLM's get PM");
578 return getPmOutput.getMeasurements();
582 } catch (ExecutionException | InterruptedException e) {
583 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
588 private boolean verifyPreFecBer(List<Measurements> measurements) {
589 double preFecCorrectedErrors = Double.MIN_VALUE;
590 double fecUncorrectableBlocks = Double.MIN_VALUE;
592 for (Measurements measurement : measurements) {
593 switch (measurement.getPmparameterName()) {
594 case "preFECCorrectedErrors":
595 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
597 case "FECUncorrectableBlocks":
598 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
605 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}",
606 preFecCorrectedErrors, fecUncorrectableBlocks);
608 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
609 LOG.error("Data has uncorrectable errors, BER test failed");
613 double numOfBitsPerSecond = 112000000000d;
614 double threshold = 0.00002d;
615 double result = preFecCorrectedErrors / numOfBitsPerSecond;
616 LOG.info("PreFEC value is {}", Double.toString(result));
617 return result <= threshold;
621 value = "UPM_UNCALLED_PRIVATE_METHOD",
622 justification = "call in call() method")
623 private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType,
624 boolean isTempService) {
625 ServicePathInputData servicePathInputDataAtoZ =
627 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create);
628 ServicePathInputData servicePathInputDataZtoA =
630 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create);
631 // Rollback should be same for all conditions, so creating a new one
632 RollbackProcessor rollbackProcessor = new RollbackProcessor();
633 List<DeviceRenderingResult> renderingResults =
634 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
635 if (rollbackProcessor.rollbackAllIfNecessary() > 0 || renderingResults.isEmpty()) {
637 ServicePathNotificationTypes.ServiceImplementationRequest,
638 input.getServiceName(),
640 DEVICE_RENDERING_ROLL_BACK_MSG);
645 //olmPowerSetupInputAtoZ,
646 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input),
647 //olmPowerSetupInputZtoA
648 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input), isTempService);
649 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
651 ServicePathNotificationTypes.ServiceImplementationRequest,
652 input.getServiceName(),
657 // run service activation test twice - once on source node and once on
659 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
660 if ((nodes == null) || (nodes.isEmpty())) {
664 Nodes sourceNode = nodes.get(0);
665 Nodes destNode = nodes.get(nodes.size() - 1);
666 String srcNetworkTp =
667 sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
668 ? sourceNode.getDestTp()
669 : sourceNode.getSrcTp();
670 String dstNetowrkTp =
671 destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
672 ? destNode.getDestTp()
673 : destNode.getSrcTp();
675 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
676 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
677 rollbackProcessor.rollbackAll();
679 ServicePathNotificationTypes.ServiceImplementationRequest,
680 input.getServiceName(),
682 "Service activation test failed.");
685 sendNotificationsWithPathDescription(
686 ServicePathNotificationTypes.ServiceImplementationRequest,
687 input.getServiceName(),
688 RpcStatusEx.Successful,
689 OPERATION_SUCCESSFUL,
690 input.getPathDescription(),
692 renderingResults.stream()
693 .flatMap(rr -> rr.getOtnLinkTps().stream())
694 .collect(Collectors.toList())),
701 value = "UPM_UNCALLED_PRIVATE_METHOD",
702 justification = "call in call() method")
703 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType)
704 throws InterruptedException {
705 ServicePathInputData servicePathInputDataAtoZ =
706 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete);
707 ServicePathInputData servicePathInputDataZtoA =
708 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete);
710 ListenableFuture<OLMRenderingResult> olmPowerTurnDownFutureAtoZ = this.executor.submit(
711 new OlmPowerTurnDownTask(serviceName, ATOZPATH, servicePathInputDataAtoZ, notification, rpcService));
713 ListenableFuture<OLMRenderingResult> olmPowerTurnDownFutureZtoA = this.executor.submit(
714 new OlmPowerTurnDownTask(serviceName, ZTOAPATH, servicePathInputDataZtoA, notification, rpcService));
716 ListenableFuture<List<OLMRenderingResult>> olmPowerTurnDownFutures =
717 Futures.allAsList(olmPowerTurnDownFutureAtoZ, olmPowerTurnDownFutureZtoA);
719 List<OLMRenderingResult> olmRenderingResults;
720 // OLM turn down power
722 LOG.info("Waiting for A-Z and Z-A OLM power turn down ...");
723 olmRenderingResults = olmPowerTurnDownFutures.get(
724 Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS
726 } catch (InterruptedException | ExecutionException | TimeoutException e) {
727 LOG.error("Error while turning down power!", e);
730 if (!olmRenderingResults.get(0).isSuccess() || !olmRenderingResults.get(1).isSuccess()) {
731 LOG.error("Error while turning down power!");
734 LOG.info("OLM power successfully turned down!");
735 // delete service path with renderer
736 LOG.info("Deleting service path via renderer");
738 ServicePathNotificationTypes.ServiceDelete,
741 "Deleting service path via renderer");
742 sendNotificationsWithPathDescription(
743 ServicePathNotificationTypes.ServiceDelete,
745 RpcStatusEx.Successful,
746 OPERATION_SUCCESSFUL,
750 new RollbackProcessor(),
751 servicePathInputDataAtoZ,
752 servicePathInputDataZtoA)
754 .flatMap(rr -> rr.getOtnLinkTps().stream())
755 .collect(Collectors.toList())),
762 value = "UPM_UNCALLED_PRIVATE_METHOD",
763 justification = "call in call() method")
764 private boolean manageOtnServicePathCreation(
765 ServiceImplementationRequestInput input,
767 Uint32 serviceRate) {
768 // Rollback should be same for all conditions, so creating a new one
769 RollbackProcessor rollbackProcessor = new RollbackProcessor();
770 List<OtnDeviceRenderingResult> renderingResults =
775 .rendererCreateOtnServiceInput(
776 input.getServiceName(),
778 input.getServiceAEnd().getServiceFormat().getName(),
780 input.getPathDescription(),
784 .rendererCreateOtnServiceInput(
785 input.getServiceName(),
787 input.getServiceZEnd().getServiceFormat().getName(),
789 input.getPathDescription(),
792 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
793 rollbackProcessor.rollbackAll();
795 ServicePathNotificationTypes.ServiceImplementationRequest,
796 input.getServiceName(),
798 DEVICE_RENDERING_ROLL_BACK_MSG);
801 sendNotificationsWithPathDescription(
802 ServicePathNotificationTypes.ServiceImplementationRequest,
803 input.getServiceName(),
804 RpcStatusEx.Successful, OPERATION_SUCCESSFUL,
805 input.getPathDescription(),
807 renderingResults.stream()
808 .flatMap(rr -> rr.getOtnLinkTps().stream())
809 .collect(Collectors.toList())),
811 ModelMappingUtils.getLinksFromServicePathDescription(input.getPathDescription()),
818 value = "UPM_UNCALLED_PRIVATE_METHOD",
819 justification = "call in call() method")
820 private boolean manageOtnServicePathDeletion(
822 PathDescription pathDescription,
824 String serviceType) {
825 LOG.info("Deleting otn-service path {} via renderer", serviceName);
827 ServicePathNotificationTypes.ServiceDelete,
830 "Deleting otn-service path via renderer");
831 List<OtnDeviceRenderingResult> renderingResults =
833 new RollbackProcessor(),
836 .rendererCreateOtnServiceInput(
839 service.getServiceAEnd().getServiceFormat().getName(),
840 service.getServiceAEnd().getServiceRate(),
845 .rendererCreateOtnServiceInput(
848 service.getServiceZEnd().getServiceFormat().getName(),
849 service.getServiceAEnd().getServiceRate(),
853 sendNotificationsWithPathDescription(
854 ServicePathNotificationTypes.ServiceDelete,
856 RpcStatusEx.Successful,
857 OPERATION_SUCCESSFUL,
860 renderingResults.stream()
861 .flatMap(rr -> rr.getOtnLinkTps().stream())
862 .collect(Collectors.toList())),
864 ModelMappingUtils.getLinksFromServicePathDescription(pathDescription),
871 * Send renderer notification.
872 * @param servicePathNotificationTypes ServicePathNotificationTypes
873 * @param serviceName String
874 * @param rpcStatusEx RpcStatusEx
875 * @param message String
877 private void sendNotifications(
878 ServicePathNotificationTypes servicePathNotificationTypes,
880 RpcStatusEx rpcStatusEx,
884 servicePathNotificationTypes,
892 * Send renderer notification with path description information.
893 * @param servicePathNotificationTypes ServicePathNotificationTypes
894 * @param serviceName String
895 * @param rpcStatusEx RpcStatusEx
896 * @param message String
897 * @param pathDescription PathDescription
899 private void sendNotificationsWithPathDescription(
900 ServicePathNotificationTypes servicePathNotificationTypes,
902 RpcStatusEx rpcStatusEx,
904 PathDescription pathDescription,
906 Set<String> supportedLinks,
907 String serviceType) {
910 notification.buildNotification(
911 servicePathNotificationTypes,
923 private Link createLinkForNotif(List<LinkTp> otnLinkTerminationPoints) {
925 otnLinkTerminationPoints == null || otnLinkTerminationPoints.size() != 2
929 new ATerminationBuilder()
930 .setNodeId(otnLinkTerminationPoints.get(0).getNodeId())
931 .setTpId(otnLinkTerminationPoints.get(0).getTpId())
934 new ZTerminationBuilder()
935 .setNodeId(otnLinkTerminationPoints.get(1).getNodeId())
936 .setTpId(otnLinkTerminationPoints.get(1).getTpId())
941 private Set<String> getSupportedLinks(Set<String> allSupportLinks, String serviceType) {
942 //TODO a Map might be more indicated here
943 switch (serviceType) {
944 case StringConstants.SERVICE_TYPE_10GE:
945 case StringConstants.SERVICE_TYPE_1GE:
946 return allSupportLinks.stream()
947 .filter(lk -> lk.startsWith(OtnLinkType.ODTU4.getName())).collect(Collectors.toSet());
948 case StringConstants.SERVICE_TYPE_100GE_M:
949 return allSupportLinks.stream()
950 .filter(lk -> lk.startsWith(OtnLinkType.ODUC4.getName())).collect(Collectors.toSet());
951 case StringConstants.SERVICE_TYPE_ODU4:
952 case StringConstants.SERVICE_TYPE_100GE_S:
953 return allSupportLinks.stream()
954 .filter(lk -> lk.startsWith(OtnLinkType.OTU4.getName())).collect(Collectors.toSet());
955 case StringConstants.SERVICE_TYPE_ODUC4:
956 return allSupportLinks.stream()
957 .filter(lk -> lk.startsWith(OtnLinkType.OTUC4.getName())).collect(Collectors.toSet());