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 for (int i = 0; i < 3; i++) {
541 List<Measurements> measurements = getMeasurements(nodeId, tpId);
542 if (measurements == null) {
543 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
546 if (verifyPreFecBer(measurements)) {
550 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
551 } catch (InterruptedException ex) {
552 Thread.currentThread().interrupt();
555 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
559 private List<Measurements> getMeasurements(String nodeId, String tp) {
561 GetPmOutput getPmOutput = rpcService.getRpc(GetPm.class).invoke(
562 new GetPmInputBuilder()
564 .setGranularity(PmGranularity._15min)
565 .setResourceIdentifier(new ResourceIdentifierBuilder().setResourceName(tp + "-OTU").build())
566 .setResourceType(ResourceTypeEnum.Interface)
570 if ((getPmOutput == null) || (getPmOutput.getNodeId() == null)) {
571 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
573 LOG.info("successfully finished calling OLM's get PM");
574 return getPmOutput.getMeasurements();
578 } catch (ExecutionException | InterruptedException e) {
579 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
584 private boolean verifyPreFecBer(List<Measurements> measurements) {
585 double preFecCorrectedErrors = Double.MIN_VALUE;
586 double fecUncorrectableBlocks = Double.MIN_VALUE;
588 for (Measurements measurement : measurements) {
589 switch (measurement.getPmparameterName()) {
590 case "preFECCorrectedErrors":
591 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
593 case "FECUncorrectableBlocks":
594 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
601 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}",
602 preFecCorrectedErrors, fecUncorrectableBlocks);
604 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
605 LOG.error("Data has uncorrectable errors, BER test failed");
609 double numOfBitsPerSecond = 112000000000d;
610 double threshold = 0.00002d;
611 double result = preFecCorrectedErrors / numOfBitsPerSecond;
612 LOG.info("PreFEC value is {}", Double.toString(result));
613 return result <= threshold;
617 value = "UPM_UNCALLED_PRIVATE_METHOD",
618 justification = "call in call() method")
619 private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType,
620 boolean isTempService) {
621 ServicePathInputData servicePathInputDataAtoZ =
623 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create);
624 ServicePathInputData servicePathInputDataZtoA =
626 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create);
627 // Rollback should be same for all conditions, so creating a new one
628 RollbackProcessor rollbackProcessor = new RollbackProcessor();
629 List<DeviceRenderingResult> renderingResults =
630 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
631 if (rollbackProcessor.rollbackAllIfNecessary() > 0 || renderingResults.isEmpty()) {
633 ServicePathNotificationTypes.ServiceImplementationRequest,
634 input.getServiceName(),
636 DEVICE_RENDERING_ROLL_BACK_MSG);
641 //olmPowerSetupInputAtoZ,
642 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input),
643 //olmPowerSetupInputZtoA
644 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input), isTempService);
645 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
647 ServicePathNotificationTypes.ServiceImplementationRequest,
648 input.getServiceName(),
653 // run service activation test twice - once on source node and once on
655 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
656 if ((nodes == null) || (nodes.isEmpty())) {
660 Nodes sourceNode = nodes.get(0);
661 Nodes destNode = nodes.get(nodes.size() - 1);
662 String srcNetworkTp =
663 sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
664 ? sourceNode.getDestTp()
665 : sourceNode.getSrcTp();
666 String dstNetowrkTp =
667 destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
668 ? destNode.getDestTp()
669 : destNode.getSrcTp();
671 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
672 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
673 rollbackProcessor.rollbackAll();
675 ServicePathNotificationTypes.ServiceImplementationRequest,
676 input.getServiceName(),
678 "Service activation test failed.");
681 sendNotificationsWithPathDescription(
682 ServicePathNotificationTypes.ServiceImplementationRequest,
683 input.getServiceName(),
684 RpcStatusEx.Successful,
685 OPERATION_SUCCESSFUL,
686 input.getPathDescription(),
688 renderingResults.stream()
689 .flatMap(rr -> rr.getOtnLinkTps().stream())
690 .collect(Collectors.toList())),
697 value = "UPM_UNCALLED_PRIVATE_METHOD",
698 justification = "call in call() method")
699 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType)
700 throws InterruptedException {
701 ServicePathInputData servicePathInputDataAtoZ =
702 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete);
703 ServicePathInputData servicePathInputDataZtoA =
704 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete);
706 ListenableFuture<OLMRenderingResult> olmPowerTurnDownFutureAtoZ = this.executor.submit(
707 new OlmPowerTurnDownTask(serviceName, ATOZPATH, servicePathInputDataAtoZ, notification, rpcService));
709 ListenableFuture<OLMRenderingResult> olmPowerTurnDownFutureZtoA = this.executor.submit(
710 new OlmPowerTurnDownTask(serviceName, ZTOAPATH, servicePathInputDataZtoA, notification, rpcService));
712 ListenableFuture<List<OLMRenderingResult>> olmPowerTurnDownFutures =
713 Futures.allAsList(olmPowerTurnDownFutureAtoZ, olmPowerTurnDownFutureZtoA);
715 List<OLMRenderingResult> olmRenderingResults;
716 // OLM turn down power
718 LOG.info("Waiting for A-Z and Z-A OLM power turn down ...");
719 olmRenderingResults = olmPowerTurnDownFutures.get(
720 Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS
722 } catch (InterruptedException | ExecutionException | TimeoutException e) {
723 LOG.error("Error while turning down power!", e);
726 if (!olmRenderingResults.get(0).isSuccess() || !olmRenderingResults.get(1).isSuccess()) {
727 LOG.error("Error while turning down power!");
730 LOG.info("OLM power successfully turned down!");
731 // delete service path with renderer
732 LOG.info("Deleting service path via renderer");
734 ServicePathNotificationTypes.ServiceDelete,
737 "Deleting service path via renderer");
738 sendNotificationsWithPathDescription(
739 ServicePathNotificationTypes.ServiceDelete,
741 RpcStatusEx.Successful,
742 OPERATION_SUCCESSFUL,
746 new RollbackProcessor(),
747 servicePathInputDataAtoZ,
748 servicePathInputDataZtoA)
750 .flatMap(rr -> rr.getOtnLinkTps().stream())
751 .collect(Collectors.toList())),
758 value = "UPM_UNCALLED_PRIVATE_METHOD",
759 justification = "call in call() method")
760 private boolean manageOtnServicePathCreation(
761 ServiceImplementationRequestInput input,
763 Uint32 serviceRate) {
764 // Rollback should be same for all conditions, so creating a new one
765 RollbackProcessor rollbackProcessor = new RollbackProcessor();
766 List<OtnDeviceRenderingResult> renderingResults =
771 .rendererCreateOtnServiceInput(
772 input.getServiceName(),
774 input.getServiceAEnd().getServiceFormat().getName(),
776 input.getPathDescription(),
780 .rendererCreateOtnServiceInput(
781 input.getServiceName(),
783 input.getServiceZEnd().getServiceFormat().getName(),
785 input.getPathDescription(),
788 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
789 rollbackProcessor.rollbackAll();
791 ServicePathNotificationTypes.ServiceImplementationRequest,
792 input.getServiceName(),
794 DEVICE_RENDERING_ROLL_BACK_MSG);
797 sendNotificationsWithPathDescription(
798 ServicePathNotificationTypes.ServiceImplementationRequest,
799 input.getServiceName(),
800 RpcStatusEx.Successful, OPERATION_SUCCESSFUL,
801 input.getPathDescription(),
803 renderingResults.stream()
804 .flatMap(rr -> rr.getOtnLinkTps().stream())
805 .collect(Collectors.toList())),
807 ModelMappingUtils.getLinksFromServicePathDescription(input.getPathDescription()),
814 value = "UPM_UNCALLED_PRIVATE_METHOD",
815 justification = "call in call() method")
816 private boolean manageOtnServicePathDeletion(
818 PathDescription pathDescription,
820 String serviceType) {
821 LOG.info("Deleting otn-service path {} via renderer", serviceName);
823 ServicePathNotificationTypes.ServiceDelete,
826 "Deleting otn-service path via renderer");
827 List<OtnDeviceRenderingResult> renderingResults =
829 new RollbackProcessor(),
832 .rendererCreateOtnServiceInput(
835 service.getServiceAEnd().getServiceFormat().getName(),
836 service.getServiceAEnd().getServiceRate(),
841 .rendererCreateOtnServiceInput(
844 service.getServiceZEnd().getServiceFormat().getName(),
845 service.getServiceAEnd().getServiceRate(),
849 sendNotificationsWithPathDescription(
850 ServicePathNotificationTypes.ServiceDelete,
852 RpcStatusEx.Successful,
853 OPERATION_SUCCESSFUL,
856 renderingResults.stream()
857 .flatMap(rr -> rr.getOtnLinkTps().stream())
858 .collect(Collectors.toList())),
860 ModelMappingUtils.getLinksFromServicePathDescription(pathDescription),
867 * Send renderer notification.
868 * @param servicePathNotificationTypes ServicePathNotificationTypes
869 * @param serviceName String
870 * @param rpcStatusEx RpcStatusEx
871 * @param message String
873 private void sendNotifications(
874 ServicePathNotificationTypes servicePathNotificationTypes,
876 RpcStatusEx rpcStatusEx,
880 servicePathNotificationTypes,
888 * Send renderer notification with path description information.
889 * @param servicePathNotificationTypes ServicePathNotificationTypes
890 * @param serviceName String
891 * @param rpcStatusEx RpcStatusEx
892 * @param message String
893 * @param pathDescription PathDescription
895 private void sendNotificationsWithPathDescription(
896 ServicePathNotificationTypes servicePathNotificationTypes,
898 RpcStatusEx rpcStatusEx,
900 PathDescription pathDescription,
902 Set<String> supportedLinks,
903 String serviceType) {
906 notification.buildNotification(
907 servicePathNotificationTypes,
919 private Link createLinkForNotif(List<LinkTp> otnLinkTerminationPoints) {
921 otnLinkTerminationPoints == null || otnLinkTerminationPoints.size() != 2
925 new ATerminationBuilder()
926 .setNodeId(otnLinkTerminationPoints.get(0).getNodeId())
927 .setTpId(otnLinkTerminationPoints.get(0).getTpId())
930 new ZTerminationBuilder()
931 .setNodeId(otnLinkTerminationPoints.get(1).getNodeId())
932 .setTpId(otnLinkTerminationPoints.get(1).getTpId())
937 private Set<String> getSupportedLinks(Set<String> allSupportLinks, String serviceType) {
938 //TODO a Map might be more indicated here
939 switch (serviceType) {
940 case StringConstants.SERVICE_TYPE_10GE:
941 case StringConstants.SERVICE_TYPE_1GE:
942 return allSupportLinks.stream()
943 .filter(lk -> lk.startsWith(OtnLinkType.ODTU4.getName())).collect(Collectors.toSet());
944 case StringConstants.SERVICE_TYPE_100GE_M:
945 return allSupportLinks.stream()
946 .filter(lk -> lk.startsWith(OtnLinkType.ODUC4.getName())).collect(Collectors.toSet());
947 case StringConstants.SERVICE_TYPE_ODU4:
948 case StringConstants.SERVICE_TYPE_100GE_S:
949 return allSupportLinks.stream()
950 .filter(lk -> lk.startsWith(OtnLinkType.OTU4.getName())).collect(Collectors.toSet());
951 case StringConstants.SERVICE_TYPE_ODUC4:
952 return allSupportLinks.stream()
953 .filter(lk -> lk.startsWith(OtnLinkType.OTUC4.getName())).collect(Collectors.toSet());