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.common.api.LogicalDatastoreType;
28 import org.opendaylight.transportpce.common.ResponseCodes;
29 import org.opendaylight.transportpce.common.StringConstants;
30 import org.opendaylight.transportpce.common.Timeouts;
31 import org.opendaylight.transportpce.common.mapping.PortMapping;
32 import org.opendaylight.transportpce.common.service.ServiceTypes;
33 import org.opendaylight.transportpce.renderer.ModelMappingUtils;
34 import org.opendaylight.transportpce.renderer.ServicePathInputData;
35 import org.opendaylight.transportpce.renderer.provisiondevice.notification.Notification;
36 import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection;
37 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingRollbackTask;
38 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingTask;
39 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.NetworkDeviceRenderingRollbackTask;
40 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupRollbackTask;
41 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupTask;
42 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerTurnDownTask;
43 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OtnDeviceRenderingTask;
44 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor;
45 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackResultMessage;
46 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.History;
47 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.TransactionHistory;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.Action;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathInput;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev220630.OtnLinkType;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmInputBuilder;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmOutput;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerSetupInput;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.TransportpceOlmService;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.get.pm.output.Measurements;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteInput;
57 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteOutput;
58 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestInput;
59 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestOutput;
60 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ATerminationBuilder;
61 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ZTerminationBuilder;
62 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.Link;
63 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.LinkBuilder;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
66 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev191129.ServiceFormat;
67 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.Services;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.PathDescription;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.RpcStatusEx;
70 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.ServicePathNotificationTypes;
71 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
72 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
73 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
74 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.PmGranularity;
75 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.link.tp.LinkTp;
76 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.olm.get.pm.input.ResourceIdentifierBuilder;
77 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.optical.renderer.nodes.Nodes;
78 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
79 import org.opendaylight.yangtools.yang.common.Uint32;
80 import org.osgi.service.component.annotations.Activate;
81 import org.osgi.service.component.annotations.Component;
82 import org.osgi.service.component.annotations.Reference;
83 import org.slf4j.Logger;
84 import org.slf4j.LoggerFactory;
87 @Component(immediate = true)
88 public class RendererServiceOperationsImpl implements RendererServiceOperations {
90 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
91 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
92 "Device rendering was not successful! Rendering will be rolled back.";
93 private static final String OLM_ROLL_BACK_MSG =
94 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
95 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
96 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
97 private static final String ATOZPATH = "A-to-Z";
98 private static final String ZTOAPATH = "Z-to-A";
99 private static final String OPERATION_FAILED = "Operation Failed";
100 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
101 private static final int NUMBER_OF_THREADS = 4;
103 private final DeviceRendererService deviceRenderer;
104 private final OtnDeviceRendererService otnDeviceRenderer;
105 private final TransportpceOlmService olmService;
106 private final DataBroker dataBroker;
107 private final Notification notification;
108 private final PortMapping portMapping;
109 private ListeningExecutorService executor;
112 public RendererServiceOperationsImpl(@Reference DeviceRendererService deviceRenderer,
113 @Reference OtnDeviceRendererService otnDeviceRenderer,
114 @Reference TransportpceOlmService olmService,
115 @Reference DataBroker dataBroker,
116 @Reference Notification notification,
117 @Reference PortMapping portMapping) {
118 this.deviceRenderer = deviceRenderer;
119 this.otnDeviceRenderer = otnDeviceRenderer;
120 this.olmService = olmService;
121 this.dataBroker = dataBroker;
122 this.notification = notification;
123 this.portMapping = portMapping;
124 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
125 LOG.debug("RendererServiceOperationsImpl instantiated");
129 public ListenableFuture<ServiceImplementationRequestOutput>
130 serviceImplementation(ServiceImplementationRequestInput input, boolean isTempService) {
131 LOG.info("Calling service impl request {}", input.getServiceName());
132 LOG.debug("Check if it is temp-service {}", isTempService);
133 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
136 public ServiceImplementationRequestOutput call() throws Exception {
138 ServicePathNotificationTypes.ServiceImplementationRequest,
139 input.getServiceName(),
141 "Service compliant, submitting service implementation Request ...");
142 Uint32 serviceRate = getServiceRate(input);
143 LOG.info("Using {}G rate", serviceRate);
144 org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221
145 .network.Nodes mappingNode =
146 portMapping.isNodeExist(input.getServiceAEnd().getNodeId())
147 ? portMapping.getNode(input.getServiceAEnd().getNodeId())
149 String serviceType = ServiceTypes.getServiceType(
150 input.getServiceAEnd().getServiceFormat().getName(),
153 && NodeTypes.Xpdr.equals(mappingNode.getNodeInfo().getNodeType())
154 && input.getServiceAEnd().getTxDirection() != null
155 && input.getServiceAEnd().getTxDirection().getPort() != null
156 && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null
157 ? portMapping.getMapping(input.getServiceAEnd().getNodeId(),
158 input.getServiceAEnd().getTxDirection().getPort().getPortName())
160 //TODO a Map might be more indicated here
161 switch (serviceType) {
162 case StringConstants.SERVICE_TYPE_100GE_T:
163 case StringConstants.SERVICE_TYPE_400GE:
164 case StringConstants.SERVICE_TYPE_OTU4:
165 case StringConstants.SERVICE_TYPE_OTUC2:
166 case StringConstants.SERVICE_TYPE_OTUC3:
167 case StringConstants.SERVICE_TYPE_OTUC4:
168 LOG.debug("Check temp service {}", isTempService);
169 if (!manageServicePathCreation(input, serviceType, isTempService)) {
170 return ModelMappingUtils
171 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
174 case StringConstants.SERVICE_TYPE_1GE:
175 case StringConstants.SERVICE_TYPE_10GE:
176 case StringConstants.SERVICE_TYPE_100GE_M:
177 case StringConstants.SERVICE_TYPE_100GE_S:
178 case StringConstants.SERVICE_TYPE_ODU4:
179 case StringConstants.SERVICE_TYPE_ODUC2:
180 case StringConstants.SERVICE_TYPE_ODUC3:
181 case StringConstants.SERVICE_TYPE_ODUC4:
182 if (!manageOtnServicePathCreation(input, serviceType, serviceRate)) {
183 return ModelMappingUtils
184 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
188 LOG.error("unsupported service-type");
189 return ModelMappingUtils
190 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
192 return ModelMappingUtils
193 .createServiceImplResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
199 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
200 String serviceName = input.getServiceName();
201 LOG.info("Calling service delete request {}", serviceName);
202 return executor.submit(new Callable<ServiceDeleteOutput>() {
205 public ServiceDeleteOutput call() throws Exception {
207 ServicePathNotificationTypes.ServiceDelete,
210 "Service compliant, submitting service delete Request ...");
211 // Obtain path description
213 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
214 .service.path.PathDescription> pathDescriptionOpt =
215 getPathDescriptionFromDatastore(serviceName);
216 if (pathDescriptionOpt.isEmpty()) {
217 LOG.error("Unable to get path description for service {}!", serviceName);
219 ServicePathNotificationTypes.ServiceDelete,
222 "Unable to get path description for service");
223 return ModelMappingUtils
224 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
226 PathDescription pathDescription = pathDescriptionOpt.orElseThrow();
228 ServiceTypes.getServiceType(
229 service.getServiceAEnd().getServiceFormat().getName(),
230 service.getServiceAEnd().getServiceRate(),
231 service.getServiceAEnd().getTxDirection() == null
232 || service.getServiceAEnd().getTxDirection().values().stream().findFirst().orElseThrow()
234 || service.getServiceAEnd().getTxDirection().values().stream().findFirst().orElseThrow()
235 .getPort().getPortName() == null
237 : portMapping.getMapping(
238 service.getServiceAEnd().getNodeId().getValue(),
239 service.getServiceAEnd().getTxDirection().values().stream().findFirst()
240 .orElseThrow().getPort().getPortName()));
241 switch (serviceType) {
242 case StringConstants.SERVICE_TYPE_100GE_T:
243 case StringConstants.SERVICE_TYPE_400GE:
244 case StringConstants.SERVICE_TYPE_OTU4:
245 case StringConstants.SERVICE_TYPE_OTUC2:
246 case StringConstants.SERVICE_TYPE_OTUC3:
247 case StringConstants.SERVICE_TYPE_OTUC4:
248 if (!manageServicePathDeletion(serviceName, pathDescription, serviceType)) {
249 return ModelMappingUtils
250 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
253 case StringConstants.SERVICE_TYPE_1GE:
254 case StringConstants.SERVICE_TYPE_10GE:
255 case StringConstants.SERVICE_TYPE_100GE_M:
256 case StringConstants.SERVICE_TYPE_100GE_S:
257 case StringConstants.SERVICE_TYPE_ODU4:
258 case StringConstants.SERVICE_TYPE_ODUC2:
259 case StringConstants.SERVICE_TYPE_ODUC3:
260 case StringConstants.SERVICE_TYPE_ODUC4:
261 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service, serviceType)) {
262 return ModelMappingUtils
263 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
267 LOG.error("unsupported service-type");
268 return ModelMappingUtils
269 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
271 return ModelMappingUtils
272 .createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
278 value = "UPM_UNCALLED_PRIVATE_METHOD",
279 justification = "call in call() method")
280 private Uint32 getServiceRate(ServiceImplementationRequestInput input) {
281 if (input.getServiceAEnd() == null) {
282 LOG.warn("Unable to get service-rate for service {}", input.getServiceName());
285 if (input.getServiceAEnd().getServiceRate() != null) {
286 return input.getServiceAEnd().getServiceRate();
288 LOG.warn("Input should have rate if you are using 200 or 300G");
289 // TODO: missing 200, and 300G rates here, OTUCn cannot always be 400G
290 Map<ServiceFormat, Map<String, Uint32>> formatRateMap = Map.of(
291 ServiceFormat.OTU, Map.of(
292 "OTUCn", Uint32.valueOf(400),
293 "OTU4", Uint32.valueOf(100),
294 "OTU2", Uint32.valueOf(10),
295 "OTU2e", Uint32.valueOf(10)),
296 ServiceFormat.ODU, Map.of(
297 "ODUCn",Uint32.valueOf(400),
298 "ODU4", Uint32.valueOf(100),
299 "ODU2", Uint32.valueOf(10),
300 "ODU2e", Uint32.valueOf(10),
301 "ODU0", Uint32.valueOf(1)));
302 if (!formatRateMap.containsKey(input.getServiceAEnd().getServiceFormat())) {
303 LOG.warn("Unable to get service-rate for service {} - unsupported service format {}",
304 input.getServiceName(), input.getServiceAEnd().getServiceFormat());
308 ServiceFormat.OTU.getName().equals(input.getServiceAEnd().getServiceFormat().getName())
309 ? input.getServiceAEnd().getOtuServiceRate().toString().split("\\{")[0]
310 : input.getServiceAEnd().getOduServiceRate().toString().split("\\{")[0];
311 if (!formatRateMap.get(input.getServiceAEnd().getServiceFormat()).containsKey(serviceName)) {
312 LOG.warn("Unable to get service-rate for service {} - unsupported service name {}",
313 input.getServiceName(), serviceName);
317 .get(input.getServiceAEnd().getServiceFormat())
322 value = "UPM_UNCALLED_PRIVATE_METHOD",
323 justification = "call in call() method")
324 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
325 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
326 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
327 .service.path.PathDescription> pathDescriptionIID =
328 InstanceIdentifier.create(ServicePathList.class)
329 .child(ServicePaths.class, new ServicePathsKey(serviceName))
330 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
331 .service.path.PathDescription.class);
333 LOG.debug("Getting path description for service {}", serviceName);
334 return this.dataBroker.newReadOnlyTransaction()
335 .read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
336 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
337 } catch (InterruptedException | ExecutionException | TimeoutException e) {
338 LOG.warn("Exception while getting path description from datastore {} for service {}!",
339 pathDescriptionIID, serviceName, e);
340 return Optional.empty();
345 value = "UPM_UNCALLED_PRIVATE_METHOD",
346 justification = "call in call() method")
347 private List<DeviceRenderingResult> deviceRendering(
348 RollbackProcessor rollbackProcessor,
349 ServicePathInputData servicePathDataAtoZ,
350 ServicePathInputData servicePathDataZtoA) {
352 //TODO atozrenderingFuture & ztoarenderingFuture & renderingCombinedFuture used only once
353 // Do notifications & LOG.info deserve this ?
354 LOG.info(RENDERING_DEVICES_A_Z_MSG);
356 ServicePathNotificationTypes.ServiceImplementationRequest,
357 servicePathDataAtoZ.getServicePathInput().getServiceName(),
359 RENDERING_DEVICES_A_Z_MSG);
361 History transactionHistory = new TransactionHistory();
362 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
363 this.executor.submit(
364 new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ, ServicePathDirection.A_TO_Z,
365 transactionHistory));
367 LOG.info(RENDERING_DEVICES_Z_A_MSG);
369 ServicePathNotificationTypes.ServiceImplementationRequest,
370 servicePathDataZtoA.getServicePathInput().getServiceName(),
372 RENDERING_DEVICES_Z_A_MSG);
373 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
374 this.executor.submit(
375 new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA, ServicePathDirection.Z_TO_A,
376 transactionHistory));
378 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
379 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
381 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
383 LOG.info("Waiting for A-Z and Z-A device renderers ...");
384 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
385 } catch (InterruptedException | ExecutionException | TimeoutException e) {
386 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
388 ServicePathNotificationTypes.ServiceImplementationRequest,
389 servicePathDataAtoZ.getServicePathInput().getServiceName(),
391 DEVICE_RENDERING_ROLL_BACK_MSG);
392 //FIXME we can't do rollback here, because we don't have rendering results.
393 return renderingResults;
396 rollbackProcessor.addTask(
397 new NetworkDeviceRenderingRollbackTask(
398 "RollbackTransactionHistoryTask",
400 ! (renderingResults.get(0).isSuccess() && renderingResults.get(1).isSuccess()),
402 new RollbackResultMessage()
406 return renderingResults;
410 value = "UPM_UNCALLED_PRIVATE_METHOD",
411 justification = "call in call() method")
412 private List<OtnDeviceRenderingResult> otnDeviceRendering(
413 RollbackProcessor rollbackProcessor,
414 OtnServicePathInput otnServicePathAtoZ,
415 OtnServicePathInput otnServicePathZtoA,
416 String serviceType) {
418 //TODO atozrenderingFuture & ztoarenderingFuture & renderingCombinedFuture used only once
419 // Do notifications & LOG.info deserve this ?
420 LOG.info(RENDERING_DEVICES_A_Z_MSG);
422 ServicePathNotificationTypes.ServiceImplementationRequest,
423 otnServicePathAtoZ.getServiceName(),
425 RENDERING_DEVICES_A_Z_MSG);
426 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
427 this.executor.submit(
428 new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ, serviceType));
430 LOG.info(RENDERING_DEVICES_Z_A_MSG);
432 ServicePathNotificationTypes.ServiceImplementationRequest,
433 otnServicePathZtoA.getServiceName(),
435 RENDERING_DEVICES_Z_A_MSG);
436 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
437 this.executor.submit(
438 new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA, serviceType));
440 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
441 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
442 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
444 LOG.info("Waiting for A-Z and Z-A device renderers ...");
445 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
446 } catch (InterruptedException | ExecutionException | TimeoutException e) {
447 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
449 ServicePathNotificationTypes.ServiceImplementationRequest,
450 otnServicePathAtoZ.getServiceName(),
452 DEVICE_RENDERING_ROLL_BACK_MSG);
453 //FIXME we can't do rollback here, because we don't have rendering results.
454 return otnRenderingResults;
456 for (int i = 0; i < otnRenderingResults.size(); i++) {
457 rollbackProcessor.addTask(
458 new DeviceRenderingRollbackTask(
459 "DeviceTask n° " + i + 1,
460 ! otnRenderingResults.get(i).isSuccess(),
461 otnRenderingResults.get(i).getRenderedNodeInterfaces(),
462 this.deviceRenderer));
464 return otnRenderingResults;
468 value = "UPM_UNCALLED_PRIVATE_METHOD",
469 justification = "call in call() method")
470 private void olmPowerSetup(
471 RollbackProcessor rollbackProcessor,
472 ServicePowerSetupInput powerSetupInputAtoZ,
473 ServicePowerSetupInput powerSetupInputZtoA, boolean isTempService) {
475 //TODO olmPowerSetupFutureAtoZ & olmPowerSetupFutureZtoA & olmFutures used only once
476 // Do notifications & LOG.info deserve this ?
477 //TODO use constants for LOG.info & notifications common messages
478 // if the service create is a temp-service, OLM will be skipped
480 LOG.info("For temp-service create OLM is not computed and skipped");
483 LOG.info("Olm power setup A-Z");
485 ServicePathNotificationTypes.ServiceImplementationRequest,
486 powerSetupInputAtoZ.getServiceName(),
488 "Olm power setup A-Z");
489 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ =
490 this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
492 LOG.info("OLM power setup Z-A");
494 ServicePathNotificationTypes.ServiceImplementationRequest,
495 powerSetupInputAtoZ.getServiceName(),
497 "Olm power setup Z-A");
498 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA =
499 this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
500 ListenableFuture<List<OLMRenderingResult>> olmFutures =
501 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
503 List<OLMRenderingResult> olmResults;
505 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
506 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
507 } catch (InterruptedException | ExecutionException | TimeoutException e) {
508 LOG.warn(OLM_ROLL_BACK_MSG, e);
510 ServicePathNotificationTypes.ServiceImplementationRequest,
511 powerSetupInputAtoZ.getServiceName(),
514 rollbackProcessor.addTask(
515 new OlmPowerSetupRollbackTask("AtoZOLMTask", true, this.olmService, powerSetupInputAtoZ));
516 rollbackProcessor.addTask(
517 new OlmPowerSetupRollbackTask("ZtoAOLMTask", true, this.olmService, powerSetupInputZtoA));
520 rollbackProcessor.addTask(
521 new OlmPowerSetupRollbackTask(
523 !olmResults.get(0).isSuccess(),
525 powerSetupInputAtoZ));
526 rollbackProcessor.addTask(
527 new OlmPowerSetupRollbackTask(
529 !olmResults.get(1).isSuccess(),
531 powerSetupInputZtoA));
535 value = "UPM_UNCALLED_PRIVATE_METHOD",
536 justification = "call in call() method")
537 private boolean isServiceActivated(String nodeId, String tpId) {
538 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
539 for (int i = 0; i < 3; i++) {
540 List<Measurements> measurements = getMeasurements(nodeId, tpId);
541 if (measurements == null) {
542 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
545 if (verifyPreFecBer(measurements)) {
549 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
550 } catch (InterruptedException ex) {
551 Thread.currentThread().interrupt();
554 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
558 private List<Measurements> getMeasurements(String nodeId, String tp) {
560 GetPmOutput getPmOutput =
563 new GetPmInputBuilder()
565 .setGranularity(PmGranularity._15min)
566 .setResourceIdentifier(new ResourceIdentifierBuilder().setResourceName(tp + "-OTU").build())
567 .setResourceType(ResourceTypeEnum.Interface)
571 if ((getPmOutput == null) || (getPmOutput.getNodeId() == null)) {
572 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
574 LOG.info("successfully finished calling OLM's get PM");
575 return getPmOutput.getMeasurements();
579 } catch (ExecutionException | InterruptedException e) {
580 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
585 private boolean verifyPreFecBer(List<Measurements> measurements) {
586 double preFecCorrectedErrors = Double.MIN_VALUE;
587 double fecUncorrectableBlocks = Double.MIN_VALUE;
589 for (Measurements measurement : measurements) {
590 switch (measurement.getPmparameterName()) {
591 case "preFECCorrectedErrors":
592 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
594 case "FECUncorrectableBlocks":
595 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
602 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}",
603 preFecCorrectedErrors, fecUncorrectableBlocks);
605 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
606 LOG.error("Data has uncorrectable errors, BER test failed");
610 double numOfBitsPerSecond = 112000000000d;
611 double threshold = 0.00002d;
612 double result = preFecCorrectedErrors / numOfBitsPerSecond;
613 LOG.info("PreFEC value is {}", Double.toString(result));
614 return result <= threshold;
618 value = "UPM_UNCALLED_PRIVATE_METHOD",
619 justification = "call in call() method")
620 private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType,
621 boolean isTempService) {
622 ServicePathInputData servicePathInputDataAtoZ =
624 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create);
625 ServicePathInputData servicePathInputDataZtoA =
627 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create);
628 // Rollback should be same for all conditions, so creating a new one
629 RollbackProcessor rollbackProcessor = new RollbackProcessor();
630 List<DeviceRenderingResult> renderingResults =
631 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
632 if (rollbackProcessor.rollbackAllIfNecessary() > 0 || renderingResults.isEmpty()) {
634 ServicePathNotificationTypes.ServiceImplementationRequest,
635 input.getServiceName(),
637 DEVICE_RENDERING_ROLL_BACK_MSG);
642 //olmPowerSetupInputAtoZ,
643 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input),
644 //olmPowerSetupInputZtoA
645 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input), isTempService);
646 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
648 ServicePathNotificationTypes.ServiceImplementationRequest,
649 input.getServiceName(),
654 // run service activation test twice - once on source node and once on
656 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
657 if ((nodes == null) || (nodes.isEmpty())) {
661 Nodes sourceNode = nodes.get(0);
662 Nodes destNode = nodes.get(nodes.size() - 1);
663 String srcNetworkTp =
664 sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
665 ? sourceNode.getDestTp()
666 : sourceNode.getSrcTp();
667 String dstNetowrkTp =
668 destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
669 ? destNode.getDestTp()
670 : destNode.getSrcTp();
672 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
673 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
674 rollbackProcessor.rollbackAll();
676 ServicePathNotificationTypes.ServiceImplementationRequest,
677 input.getServiceName(),
679 "Service activation test failed.");
682 sendNotificationsWithPathDescription(
683 ServicePathNotificationTypes.ServiceImplementationRequest,
684 input.getServiceName(),
685 RpcStatusEx.Successful,
686 OPERATION_SUCCESSFUL,
687 input.getPathDescription(),
689 renderingResults.stream()
690 .flatMap(rr -> rr.getOtnLinkTps().stream())
691 .collect(Collectors.toList())),
698 value = "UPM_UNCALLED_PRIVATE_METHOD",
699 justification = "call in call() method")
700 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType)
701 throws InterruptedException {
702 ServicePathInputData servicePathInputDataAtoZ =
703 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete);
704 ServicePathInputData servicePathInputDataZtoA =
705 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete);
707 ListenableFuture<OLMRenderingResult> olmPowerTurnDownFutureAtoZ =
708 this.executor.submit(
709 new OlmPowerTurnDownTask(
713 servicePathInputDataAtoZ,
718 ListenableFuture<OLMRenderingResult> olmPowerTurnDownFutureZtoA =
719 this.executor.submit(
720 new OlmPowerTurnDownTask(
724 servicePathInputDataZtoA,
729 ListenableFuture<List<OLMRenderingResult>> olmPowerTurnDownFutures =
730 Futures.allAsList(olmPowerTurnDownFutureAtoZ, olmPowerTurnDownFutureZtoA);
732 List<OLMRenderingResult> olmRenderingResults;
733 // OLM turn down power
735 LOG.info("Waiting for A-Z and Z-A OLM power turn down ...");
736 olmRenderingResults = olmPowerTurnDownFutures.get(
737 Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS
739 } catch (InterruptedException | ExecutionException | TimeoutException e) {
740 LOG.error("Error while turning down power!", e);
743 if (!olmRenderingResults.get(0).isSuccess() || !olmRenderingResults.get(1).isSuccess()) {
744 LOG.error("Error while turning down power!");
747 LOG.info("OLM power successfully turned down!");
748 // delete service path with renderer
749 LOG.info("Deleting service path via renderer");
751 ServicePathNotificationTypes.ServiceDelete,
754 "Deleting service path via renderer");
755 sendNotificationsWithPathDescription(
756 ServicePathNotificationTypes.ServiceDelete,
758 RpcStatusEx.Successful,
759 OPERATION_SUCCESSFUL,
763 new RollbackProcessor(),
764 servicePathInputDataAtoZ,
765 servicePathInputDataZtoA)
767 .flatMap(rr -> rr.getOtnLinkTps().stream())
768 .collect(Collectors.toList())),
775 value = "UPM_UNCALLED_PRIVATE_METHOD",
776 justification = "call in call() method")
777 private boolean manageOtnServicePathCreation(
778 ServiceImplementationRequestInput input,
780 Uint32 serviceRate) {
781 // Rollback should be same for all conditions, so creating a new one
782 RollbackProcessor rollbackProcessor = new RollbackProcessor();
783 List<OtnDeviceRenderingResult> renderingResults =
788 .rendererCreateOtnServiceInput(
789 input.getServiceName(),
791 input.getServiceAEnd().getServiceFormat().getName(),
793 input.getPathDescription(),
797 .rendererCreateOtnServiceInput(
798 input.getServiceName(),
800 input.getServiceZEnd().getServiceFormat().getName(),
802 input.getPathDescription(),
805 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
806 rollbackProcessor.rollbackAll();
808 ServicePathNotificationTypes.ServiceImplementationRequest,
809 input.getServiceName(),
811 DEVICE_RENDERING_ROLL_BACK_MSG);
814 sendNotificationsWithPathDescription(
815 ServicePathNotificationTypes.ServiceImplementationRequest,
816 input.getServiceName(),
817 RpcStatusEx.Successful, OPERATION_SUCCESSFUL,
818 input.getPathDescription(),
820 renderingResults.stream()
821 .flatMap(rr -> rr.getOtnLinkTps().stream())
822 .collect(Collectors.toList())),
824 ModelMappingUtils.getLinksFromServicePathDescription(input.getPathDescription()),
831 value = "UPM_UNCALLED_PRIVATE_METHOD",
832 justification = "call in call() method")
833 private boolean manageOtnServicePathDeletion(
835 PathDescription pathDescription,
837 String serviceType) {
838 LOG.info("Deleting otn-service path {} via renderer", serviceName);
840 ServicePathNotificationTypes.ServiceDelete,
843 "Deleting otn-service path via renderer");
844 List<OtnDeviceRenderingResult> renderingResults =
846 new RollbackProcessor(),
849 .rendererCreateOtnServiceInput(
852 service.getServiceAEnd().getServiceFormat().getName(),
853 service.getServiceAEnd().getServiceRate(),
858 .rendererCreateOtnServiceInput(
861 service.getServiceZEnd().getServiceFormat().getName(),
862 service.getServiceAEnd().getServiceRate(),
866 sendNotificationsWithPathDescription(
867 ServicePathNotificationTypes.ServiceDelete,
869 RpcStatusEx.Successful,
870 OPERATION_SUCCESSFUL,
873 renderingResults.stream()
874 .flatMap(rr -> rr.getOtnLinkTps().stream())
875 .collect(Collectors.toList())),
877 ModelMappingUtils.getLinksFromServicePathDescription(pathDescription),
884 * Send renderer notification.
885 * @param servicePathNotificationTypes ServicePathNotificationTypes
886 * @param serviceName String
887 * @param rpcStatusEx RpcStatusEx
888 * @param message String
890 private void sendNotifications(
891 ServicePathNotificationTypes servicePathNotificationTypes,
893 RpcStatusEx rpcStatusEx,
897 servicePathNotificationTypes,
905 * Send renderer notification with path description information.
906 * @param servicePathNotificationTypes ServicePathNotificationTypes
907 * @param serviceName String
908 * @param rpcStatusEx RpcStatusEx
909 * @param message String
910 * @param pathDescription PathDescription
912 private void sendNotificationsWithPathDescription(
913 ServicePathNotificationTypes servicePathNotificationTypes,
915 RpcStatusEx rpcStatusEx,
917 PathDescription pathDescription,
919 Set<String> supportedLinks,
920 String serviceType) {
923 notification.buildNotification(
924 servicePathNotificationTypes,
936 private Link createLinkForNotif(List<LinkTp> otnLinkTerminationPoints) {
938 otnLinkTerminationPoints == null || otnLinkTerminationPoints.size() != 2
942 new ATerminationBuilder()
943 .setNodeId(otnLinkTerminationPoints.get(0).getNodeId())
944 .setTpId(otnLinkTerminationPoints.get(0).getTpId())
947 new ZTerminationBuilder()
948 .setNodeId(otnLinkTerminationPoints.get(1).getNodeId())
949 .setTpId(otnLinkTerminationPoints.get(1).getTpId())
954 private Set<String> getSupportedLinks(Set<String> allSupportLinks, String serviceType) {
955 //TODO a Map might be more indicated here
956 switch (serviceType) {
957 case StringConstants.SERVICE_TYPE_10GE:
958 case StringConstants.SERVICE_TYPE_1GE:
959 return allSupportLinks.stream()
960 .filter(lk -> lk.startsWith(OtnLinkType.ODTU4.getName())).collect(Collectors.toSet());
961 case StringConstants.SERVICE_TYPE_100GE_M:
962 return allSupportLinks.stream()
963 .filter(lk -> lk.startsWith(OtnLinkType.ODUC4.getName())).collect(Collectors.toSet());
964 case StringConstants.SERVICE_TYPE_ODU4:
965 case StringConstants.SERVICE_TYPE_100GE_S:
966 return allSupportLinks.stream()
967 .filter(lk -> lk.startsWith(OtnLinkType.OTU4.getName())).collect(Collectors.toSet());
968 case StringConstants.SERVICE_TYPE_ODUC4:
969 return allSupportLinks.stream()
970 .filter(lk -> lk.startsWith(OtnLinkType.OTUC4.getName())).collect(Collectors.toSet());