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.OlmPowerSetupRollbackTask;
40 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupTask;
41 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OtnDeviceRenderingTask;
42 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.Action;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathInput;
45 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev220630.OtnLinkType;
46 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmInputBuilder;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmOutput;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerSetupInput;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownInputBuilder;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownOutput;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.TransportpceOlmService;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.get.pm.output.Measurements;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteInput;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteOutput;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestInput;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestOutput;
57 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ATerminationBuilder;
58 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ZTerminationBuilder;
59 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.Link;
60 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.LinkBuilder;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev191129.ServiceFormat;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.Services;
65 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.PathDescription;
66 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.RpcStatusEx;
67 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.ServicePathNotificationTypes;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
70 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
71 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.PmGranularity;
72 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.link.tp.LinkTp;
73 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.olm.get.pm.input.ResourceIdentifierBuilder;
74 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.optical.renderer.nodes.Nodes;
75 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
76 import org.opendaylight.yangtools.yang.common.Uint32;
77 import org.osgi.service.component.annotations.Activate;
78 import org.osgi.service.component.annotations.Component;
79 import org.osgi.service.component.annotations.Reference;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
84 @Component(immediate = true)
85 public class RendererServiceOperationsImpl implements RendererServiceOperations {
87 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
88 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
89 "Device rendering was not successful! Rendering will be rolled back.";
90 private static final String OLM_ROLL_BACK_MSG =
91 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
92 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
93 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
94 private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path";
95 private static final String FAILED = "Failed";
96 private static final String OPERATION_FAILED = "Operation Failed";
97 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
98 private static final int NUMBER_OF_THREADS = 4;
100 private final DeviceRendererService deviceRenderer;
101 private final OtnDeviceRendererService otnDeviceRenderer;
102 private final TransportpceOlmService olmService;
103 private final DataBroker dataBroker;
104 private final Notification notification;
105 private final PortMapping portMapping;
106 private ListeningExecutorService executor;
109 public RendererServiceOperationsImpl(@Reference DeviceRendererService deviceRenderer,
110 @Reference OtnDeviceRendererService otnDeviceRenderer,
111 @Reference TransportpceOlmService olmService,
112 @Reference DataBroker dataBroker,
113 @Reference Notification notification,
114 @Reference PortMapping portMapping) {
115 this.deviceRenderer = deviceRenderer;
116 this.otnDeviceRenderer = otnDeviceRenderer;
117 this.olmService = olmService;
118 this.dataBroker = dataBroker;
119 this.notification = notification;
120 this.portMapping = portMapping;
121 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
122 LOG.debug("RendererServiceOperationsImpl instantiated");
126 public ListenableFuture<ServiceImplementationRequestOutput>
127 serviceImplementation(ServiceImplementationRequestInput input, boolean isTempService) {
128 LOG.info("Calling service impl request {}", input.getServiceName());
129 LOG.debug("Check if it is temp-service {}", isTempService);
130 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
133 public ServiceImplementationRequestOutput call() throws Exception {
135 ServicePathNotificationTypes.ServiceImplementationRequest,
136 input.getServiceName(),
138 "Service compliant, submitting service implementation Request ...");
139 Uint32 serviceRate = getServiceRate(input);
140 LOG.info("Using {}G rate", serviceRate);
141 org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221
142 .network.Nodes mappingNode =
143 portMapping.isNodeExist(input.getServiceAEnd().getNodeId())
144 ? portMapping.getNode(input.getServiceAEnd().getNodeId())
146 String serviceType = ServiceTypes.getServiceType(
147 input.getServiceAEnd().getServiceFormat().getName(),
150 && NodeTypes.Xpdr.equals(mappingNode.getNodeInfo().getNodeType())
151 && input.getServiceAEnd().getTxDirection() != null
152 && input.getServiceAEnd().getTxDirection().getPort() != null
153 && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null
154 ? portMapping.getMapping(input.getServiceAEnd().getNodeId(),
155 input.getServiceAEnd().getTxDirection().getPort().getPortName())
157 //TODO a Map might be more indicated here
158 switch (serviceType) {
159 case StringConstants.SERVICE_TYPE_100GE_T:
160 case StringConstants.SERVICE_TYPE_400GE:
161 case StringConstants.SERVICE_TYPE_OTU4:
162 case StringConstants.SERVICE_TYPE_OTUC2:
163 case StringConstants.SERVICE_TYPE_OTUC3:
164 case StringConstants.SERVICE_TYPE_OTUC4:
165 LOG.debug("Check temp service {}", isTempService);
166 if (!manageServicePathCreation(input, serviceType, isTempService)) {
167 return ModelMappingUtils
168 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
171 case StringConstants.SERVICE_TYPE_1GE:
172 case StringConstants.SERVICE_TYPE_10GE:
173 case StringConstants.SERVICE_TYPE_100GE_M:
174 case StringConstants.SERVICE_TYPE_100GE_S:
175 case StringConstants.SERVICE_TYPE_ODU4:
176 case StringConstants.SERVICE_TYPE_ODUC2:
177 case StringConstants.SERVICE_TYPE_ODUC3:
178 case StringConstants.SERVICE_TYPE_ODUC4:
179 if (!manageOtnServicePathCreation(input, serviceType, serviceRate)) {
180 return ModelMappingUtils
181 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
185 LOG.error("unsupported service-type");
186 return ModelMappingUtils
187 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
189 return ModelMappingUtils
190 .createServiceImplResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
196 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
197 String serviceName = input.getServiceName();
198 LOG.info("Calling service delete request {}", serviceName);
199 return executor.submit(new Callable<ServiceDeleteOutput>() {
202 public ServiceDeleteOutput call() throws Exception {
204 ServicePathNotificationTypes.ServiceDelete,
207 "Service compliant, submitting service delete Request ...");
208 // Obtain path description
210 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
211 .service.path.PathDescription> pathDescriptionOpt =
212 getPathDescriptionFromDatastore(serviceName);
213 if (pathDescriptionOpt.isEmpty()) {
214 LOG.error("Unable to get path description for service {}!", serviceName);
216 ServicePathNotificationTypes.ServiceDelete,
219 "Unable to get path description for service");
220 return ModelMappingUtils
221 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
223 PathDescription pathDescription = pathDescriptionOpt.orElseThrow();
225 ServiceTypes.getServiceType(
226 service.getServiceAEnd().getServiceFormat().getName(),
227 service.getServiceAEnd().getServiceRate(),
228 service.getServiceAEnd().getTxDirection() == null
229 || service.getServiceAEnd().getTxDirection().values().stream().findFirst().orElseThrow()
231 || service.getServiceAEnd().getTxDirection().values().stream().findFirst().orElseThrow()
232 .getPort().getPortName() == null
234 : portMapping.getMapping(
235 service.getServiceAEnd().getNodeId().getValue(),
236 service.getServiceAEnd().getTxDirection().values().stream().findFirst()
237 .orElseThrow().getPort().getPortName()));
238 switch (serviceType) {
239 case StringConstants.SERVICE_TYPE_100GE_T:
240 case StringConstants.SERVICE_TYPE_400GE:
241 case StringConstants.SERVICE_TYPE_OTU4:
242 case StringConstants.SERVICE_TYPE_OTUC2:
243 case StringConstants.SERVICE_TYPE_OTUC3:
244 case StringConstants.SERVICE_TYPE_OTUC4:
245 if (!manageServicePathDeletion(serviceName, pathDescription, serviceType)) {
246 return ModelMappingUtils
247 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
250 case StringConstants.SERVICE_TYPE_1GE:
251 case StringConstants.SERVICE_TYPE_10GE:
252 case StringConstants.SERVICE_TYPE_100GE_M:
253 case StringConstants.SERVICE_TYPE_100GE_S:
254 case StringConstants.SERVICE_TYPE_ODU4:
255 case StringConstants.SERVICE_TYPE_ODUC2:
256 case StringConstants.SERVICE_TYPE_ODUC3:
257 case StringConstants.SERVICE_TYPE_ODUC4:
258 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service, serviceType)) {
259 return ModelMappingUtils
260 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
264 LOG.error("unsupported service-type");
265 return ModelMappingUtils
266 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
268 return ModelMappingUtils
269 .createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
275 value = "UPM_UNCALLED_PRIVATE_METHOD",
276 justification = "call in call() method")
277 private Uint32 getServiceRate(ServiceImplementationRequestInput input) {
278 if (input.getServiceAEnd() == null) {
279 LOG.warn("Unable to get service-rate for service {}", input.getServiceName());
282 if (input.getServiceAEnd().getServiceRate() != null) {
283 return input.getServiceAEnd().getServiceRate();
285 LOG.warn("Input should have rate if you are using 200 or 300G");
286 // TODO: missing 200, and 300G rates here, OTUCn cannot always be 400G
287 Map<ServiceFormat, Map<String, Uint32>> formatRateMap = Map.of(
288 ServiceFormat.OTU, Map.of(
289 "OTUCn", Uint32.valueOf(400),
290 "OTU4", Uint32.valueOf(100),
291 "OTU2", Uint32.valueOf(10),
292 "OTU2e", Uint32.valueOf(10)),
293 ServiceFormat.ODU, Map.of(
294 "ODUCn",Uint32.valueOf(400),
295 "ODU4", Uint32.valueOf(100),
296 "ODU2", Uint32.valueOf(10),
297 "ODU2e", Uint32.valueOf(10),
298 "ODU0", Uint32.valueOf(1)));
299 if (!formatRateMap.containsKey(input.getServiceAEnd().getServiceFormat())) {
300 LOG.warn("Unable to get service-rate for service {} - unsupported service format {}",
301 input.getServiceName(), input.getServiceAEnd().getServiceFormat());
305 ServiceFormat.OTU.getName().equals(input.getServiceAEnd().getServiceFormat().getName())
306 ? input.getServiceAEnd().getOtuServiceRate().toString().split("\\{")[0]
307 : input.getServiceAEnd().getOduServiceRate().toString().split("\\{")[0];
308 if (!formatRateMap.get(input.getServiceAEnd().getServiceFormat()).containsKey(serviceName)) {
309 LOG.warn("Unable to get service-rate for service {} - unsupported service name {}",
310 input.getServiceName(), serviceName);
314 .get(input.getServiceAEnd().getServiceFormat())
319 value = "UPM_UNCALLED_PRIVATE_METHOD",
320 justification = "call in call() method")
321 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
322 throws InterruptedException, ExecutionException, TimeoutException {
323 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
324 return this.olmService
325 .servicePowerTurndown(
326 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build())
327 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS)
332 value = "UPM_UNCALLED_PRIVATE_METHOD",
333 justification = "call in call() method")
334 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
335 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
336 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
337 .service.path.PathDescription> pathDescriptionIID =
338 InstanceIdentifier.create(ServicePathList.class)
339 .child(ServicePaths.class, new ServicePathsKey(serviceName))
340 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
341 .service.path.PathDescription.class);
343 LOG.debug("Getting path description for service {}", serviceName);
344 return this.dataBroker.newReadOnlyTransaction()
345 .read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
346 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
347 } catch (InterruptedException | ExecutionException | TimeoutException e) {
348 LOG.warn("Exception while getting path description from datastore {} for service {}!",
349 pathDescriptionIID, serviceName, e);
350 return Optional.empty();
355 value = "UPM_UNCALLED_PRIVATE_METHOD",
356 justification = "call in call() method")
357 private List<DeviceRenderingResult> deviceRendering(
358 RollbackProcessor rollbackProcessor,
359 ServicePathInputData servicePathDataAtoZ,
360 ServicePathInputData servicePathDataZtoA) {
362 //TODO atozrenderingFuture & ztoarenderingFuture & renderingCombinedFuture used only once
363 // Do notifications & LOG.info deserve this ?
364 LOG.info(RENDERING_DEVICES_A_Z_MSG);
366 ServicePathNotificationTypes.ServiceImplementationRequest,
367 servicePathDataAtoZ.getServicePathInput().getServiceName(),
369 RENDERING_DEVICES_A_Z_MSG);
370 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
371 this.executor.submit(
372 new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ, ServicePathDirection.A_TO_Z));
374 LOG.info(RENDERING_DEVICES_Z_A_MSG);
376 ServicePathNotificationTypes.ServiceImplementationRequest,
377 servicePathDataZtoA.getServicePathInput().getServiceName(),
379 RENDERING_DEVICES_Z_A_MSG);
380 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
381 this.executor.submit(
382 new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA, ServicePathDirection.Z_TO_A));
384 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
385 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
387 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
389 LOG.info("Waiting for A-Z and Z-A device renderers ...");
390 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
391 } catch (InterruptedException | ExecutionException | TimeoutException e) {
392 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
394 ServicePathNotificationTypes.ServiceImplementationRequest,
395 servicePathDataAtoZ.getServicePathInput().getServiceName(),
397 DEVICE_RENDERING_ROLL_BACK_MSG);
398 //FIXME we can't do rollback here, because we don't have rendering results.
399 return renderingResults;
402 rollbackProcessor.addTask(
403 new DeviceRenderingRollbackTask(
405 ! renderingResults.get(0).isSuccess(),
406 renderingResults.get(0).getRenderedNodeInterfaces(),
407 this.deviceRenderer));
408 rollbackProcessor.addTask(
409 new DeviceRenderingRollbackTask("ZtoADeviceTask",
410 ! renderingResults.get(1).isSuccess(),
411 renderingResults.get(1).getRenderedNodeInterfaces(),
412 this.deviceRenderer));
413 return renderingResults;
417 value = "UPM_UNCALLED_PRIVATE_METHOD",
418 justification = "call in call() method")
419 private List<OtnDeviceRenderingResult> otnDeviceRendering(
420 RollbackProcessor rollbackProcessor,
421 OtnServicePathInput otnServicePathAtoZ,
422 OtnServicePathInput otnServicePathZtoA,
423 String serviceType) {
425 //TODO atozrenderingFuture & ztoarenderingFuture & renderingCombinedFuture used only once
426 // Do notifications & LOG.info deserve this ?
427 LOG.info(RENDERING_DEVICES_A_Z_MSG);
429 ServicePathNotificationTypes.ServiceImplementationRequest,
430 otnServicePathAtoZ.getServiceName(),
432 RENDERING_DEVICES_A_Z_MSG);
433 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
434 this.executor.submit(
435 new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ, serviceType));
437 LOG.info(RENDERING_DEVICES_Z_A_MSG);
439 ServicePathNotificationTypes.ServiceImplementationRequest,
440 otnServicePathZtoA.getServiceName(),
442 RENDERING_DEVICES_Z_A_MSG);
443 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
444 this.executor.submit(
445 new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA, serviceType));
447 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
448 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
449 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
451 LOG.info("Waiting for A-Z and Z-A device renderers ...");
452 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
453 } catch (InterruptedException | ExecutionException | TimeoutException e) {
454 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
456 ServicePathNotificationTypes.ServiceImplementationRequest,
457 otnServicePathAtoZ.getServiceName(),
459 DEVICE_RENDERING_ROLL_BACK_MSG);
460 //FIXME we can't do rollback here, because we don't have rendering results.
461 return otnRenderingResults;
463 for (int i = 0; i < otnRenderingResults.size(); i++) {
464 rollbackProcessor.addTask(
465 new DeviceRenderingRollbackTask(
466 "DeviceTask n° " + i + 1,
467 ! otnRenderingResults.get(i).isSuccess(),
468 otnRenderingResults.get(i).getRenderedNodeInterfaces(),
469 this.deviceRenderer));
471 return otnRenderingResults;
475 value = "UPM_UNCALLED_PRIVATE_METHOD",
476 justification = "call in call() method")
477 private void olmPowerSetup(
478 RollbackProcessor rollbackProcessor,
479 ServicePowerSetupInput powerSetupInputAtoZ,
480 ServicePowerSetupInput powerSetupInputZtoA, boolean isTempService) {
482 //TODO olmPowerSetupFutureAtoZ & olmPowerSetupFutureZtoA & olmFutures used only once
483 // Do notifications & LOG.info deserve this ?
484 //TODO use constants for LOG.info & notifications common messages
485 // if the service create is a temp-service, OLM will be skipped
487 LOG.info("For temp-service create OLM is not computed and skipped");
490 LOG.info("Olm power setup A-Z");
492 ServicePathNotificationTypes.ServiceImplementationRequest,
493 powerSetupInputAtoZ.getServiceName(),
495 "Olm power setup A-Z");
496 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ =
497 this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
499 LOG.info("OLM power setup Z-A");
501 ServicePathNotificationTypes.ServiceImplementationRequest,
502 powerSetupInputAtoZ.getServiceName(),
504 "Olm power setup Z-A");
505 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA =
506 this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
507 ListenableFuture<List<OLMRenderingResult>> olmFutures =
508 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
510 List<OLMRenderingResult> olmResults;
512 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
513 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
514 } catch (InterruptedException | ExecutionException | TimeoutException e) {
515 LOG.warn(OLM_ROLL_BACK_MSG, e);
517 ServicePathNotificationTypes.ServiceImplementationRequest,
518 powerSetupInputAtoZ.getServiceName(),
521 rollbackProcessor.addTask(
522 new OlmPowerSetupRollbackTask("AtoZOLMTask", true, this.olmService, powerSetupInputAtoZ));
523 rollbackProcessor.addTask(
524 new OlmPowerSetupRollbackTask("ZtoAOLMTask", true, this.olmService, powerSetupInputZtoA));
527 rollbackProcessor.addTask(
528 new OlmPowerSetupRollbackTask(
530 !olmResults.get(0).isSuccess(),
532 powerSetupInputAtoZ));
533 rollbackProcessor.addTask(
534 new OlmPowerSetupRollbackTask(
536 !olmResults.get(1).isSuccess(),
538 powerSetupInputZtoA));
542 value = "UPM_UNCALLED_PRIVATE_METHOD",
543 justification = "call in call() method")
544 private boolean isServiceActivated(String nodeId, String tpId) {
545 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
546 for (int i = 0; i < 3; i++) {
547 List<Measurements> measurements = getMeasurements(nodeId, tpId);
548 if (measurements == null) {
549 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
552 if (verifyPreFecBer(measurements)) {
556 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
557 } catch (InterruptedException ex) {
558 Thread.currentThread().interrupt();
561 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
565 private List<Measurements> getMeasurements(String nodeId, String tp) {
567 GetPmOutput getPmOutput =
570 new GetPmInputBuilder()
572 .setGranularity(PmGranularity._15min)
573 .setResourceIdentifier(new ResourceIdentifierBuilder().setResourceName(tp + "-OTU").build())
574 .setResourceType(ResourceTypeEnum.Interface)
578 if ((getPmOutput == null) || (getPmOutput.getNodeId() == null)) {
579 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
581 LOG.info("successfully finished calling OLM's get PM");
582 return getPmOutput.getMeasurements();
586 } catch (ExecutionException | InterruptedException e) {
587 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
592 private boolean verifyPreFecBer(List<Measurements> measurements) {
593 double preFecCorrectedErrors = Double.MIN_VALUE;
594 double fecUncorrectableBlocks = Double.MIN_VALUE;
596 for (Measurements measurement : measurements) {
597 switch (measurement.getPmparameterName()) {
598 case "preFECCorrectedErrors":
599 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
601 case "FECUncorrectableBlocks":
602 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
609 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}",
610 preFecCorrectedErrors, fecUncorrectableBlocks);
612 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
613 LOG.error("Data has uncorrectable errors, BER test failed");
617 double numOfBitsPerSecond = 112000000000d;
618 double threshold = 0.00002d;
619 double result = preFecCorrectedErrors / numOfBitsPerSecond;
620 LOG.info("PreFEC value is {}", Double.toString(result));
621 return result <= threshold;
625 value = "UPM_UNCALLED_PRIVATE_METHOD",
626 justification = "call in call() method")
627 private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType,
628 boolean isTempService) {
629 ServicePathInputData servicePathInputDataAtoZ =
631 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create);
632 ServicePathInputData servicePathInputDataZtoA =
634 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create);
635 // Rollback should be same for all conditions, so creating a new one
636 RollbackProcessor rollbackProcessor = new RollbackProcessor();
637 List<DeviceRenderingResult> renderingResults =
638 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
639 if (rollbackProcessor.rollbackAllIfNecessary() > 0 || renderingResults.isEmpty()) {
641 ServicePathNotificationTypes.ServiceImplementationRequest,
642 input.getServiceName(),
644 DEVICE_RENDERING_ROLL_BACK_MSG);
649 //olmPowerSetupInputAtoZ,
650 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input),
651 //olmPowerSetupInputZtoA
652 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input), isTempService);
653 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
655 ServicePathNotificationTypes.ServiceImplementationRequest,
656 input.getServiceName(),
661 // run service activation test twice - once on source node and once on
663 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
664 if ((nodes == null) || (nodes.isEmpty())) {
668 Nodes sourceNode = nodes.get(0);
669 Nodes destNode = nodes.get(nodes.size() - 1);
670 String srcNetworkTp =
671 sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
672 ? sourceNode.getDestTp()
673 : sourceNode.getSrcTp();
674 String dstNetowrkTp =
675 destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
676 ? destNode.getDestTp()
677 : destNode.getSrcTp();
679 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
680 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
681 rollbackProcessor.rollbackAll();
683 ServicePathNotificationTypes.ServiceImplementationRequest,
684 input.getServiceName(),
686 "Service activation test failed.");
689 sendNotificationsWithPathDescription(
690 ServicePathNotificationTypes.ServiceImplementationRequest,
691 input.getServiceName(),
692 RpcStatusEx.Successful,
693 OPERATION_SUCCESSFUL,
694 input.getPathDescription(),
696 renderingResults.stream()
697 .flatMap(rr -> rr.getOtnLinkTps().stream())
698 .collect(Collectors.toList())),
705 value = "UPM_UNCALLED_PRIVATE_METHOD",
706 justification = "call in call() method")
707 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType)
708 throws InterruptedException {
709 ServicePathInputData servicePathInputDataAtoZ =
710 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete);
711 ServicePathInputData servicePathInputDataZtoA =
712 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete);
713 // OLM turn down power
715 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
717 ServicePathNotificationTypes.ServiceDelete,
720 TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
721 // TODO add some flag rather than string
723 olmPowerTurndown(servicePathInputDataAtoZ)
725 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
727 ServicePathNotificationTypes.ServiceDelete,
730 "Service power turndown failed on A-to-Z path for service");
733 LOG.debug("Turning down power on Z-to-A path");
735 ServicePathNotificationTypes.ServiceDelete,
738 "Turning down power on Z-to-A path");
739 // TODO add some flag rather than string
741 olmPowerTurndown(servicePathInputDataZtoA)
743 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
745 ServicePathNotificationTypes.ServiceDelete,
748 "Service power turndown failed on Z-to-A path for service");
751 } catch (InterruptedException | ExecutionException | TimeoutException e) {
752 LOG.error("Error while turning down power!", e);
755 // delete service path with renderer
756 LOG.info("Deleting service path via renderer");
758 ServicePathNotificationTypes.ServiceDelete,
761 "Deleting service path via renderer");
762 sendNotificationsWithPathDescription(
763 ServicePathNotificationTypes.ServiceDelete,
765 RpcStatusEx.Successful,
766 OPERATION_SUCCESSFUL,
770 new RollbackProcessor(),
771 servicePathInputDataAtoZ,
772 servicePathInputDataZtoA)
774 .flatMap(rr -> rr.getOtnLinkTps().stream())
775 .collect(Collectors.toList())),
782 value = "UPM_UNCALLED_PRIVATE_METHOD",
783 justification = "call in call() method")
784 private boolean manageOtnServicePathCreation(
785 ServiceImplementationRequestInput input,
787 Uint32 serviceRate) {
788 // Rollback should be same for all conditions, so creating a new one
789 RollbackProcessor rollbackProcessor = new RollbackProcessor();
790 List<OtnDeviceRenderingResult> renderingResults =
795 .rendererCreateOtnServiceInput(
796 input.getServiceName(),
798 input.getServiceAEnd().getServiceFormat().getName(),
800 input.getPathDescription(),
804 .rendererCreateOtnServiceInput(
805 input.getServiceName(),
807 input.getServiceZEnd().getServiceFormat().getName(),
809 input.getPathDescription(),
812 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
813 rollbackProcessor.rollbackAll();
815 ServicePathNotificationTypes.ServiceImplementationRequest,
816 input.getServiceName(),
818 DEVICE_RENDERING_ROLL_BACK_MSG);
821 sendNotificationsWithPathDescription(
822 ServicePathNotificationTypes.ServiceImplementationRequest,
823 input.getServiceName(),
824 RpcStatusEx.Successful, OPERATION_SUCCESSFUL,
825 input.getPathDescription(),
827 renderingResults.stream()
828 .flatMap(rr -> rr.getOtnLinkTps().stream())
829 .collect(Collectors.toList())),
831 ModelMappingUtils.getLinksFromServicePathDescription(input.getPathDescription()),
838 value = "UPM_UNCALLED_PRIVATE_METHOD",
839 justification = "call in call() method")
840 private boolean manageOtnServicePathDeletion(
842 PathDescription pathDescription,
844 String serviceType) {
845 LOG.info("Deleting otn-service path {} via renderer", serviceName);
847 ServicePathNotificationTypes.ServiceDelete,
850 "Deleting otn-service path via renderer");
851 List<OtnDeviceRenderingResult> renderingResults =
853 new RollbackProcessor(),
856 .rendererCreateOtnServiceInput(
859 service.getServiceAEnd().getServiceFormat().getName(),
860 service.getServiceAEnd().getServiceRate(),
865 .rendererCreateOtnServiceInput(
868 service.getServiceZEnd().getServiceFormat().getName(),
869 service.getServiceAEnd().getServiceRate(),
873 sendNotificationsWithPathDescription(
874 ServicePathNotificationTypes.ServiceDelete,
876 RpcStatusEx.Successful,
877 OPERATION_SUCCESSFUL,
880 renderingResults.stream()
881 .flatMap(rr -> rr.getOtnLinkTps().stream())
882 .collect(Collectors.toList())),
884 ModelMappingUtils.getLinksFromServicePathDescription(pathDescription),
891 * Send renderer notification.
892 * @param servicePathNotificationTypes ServicePathNotificationTypes
893 * @param serviceName String
894 * @param rpcStatusEx RpcStatusEx
895 * @param message String
897 private void sendNotifications(
898 ServicePathNotificationTypes servicePathNotificationTypes,
900 RpcStatusEx rpcStatusEx,
904 servicePathNotificationTypes,
912 * Send renderer notification with path description information.
913 * @param servicePathNotificationTypes ServicePathNotificationTypes
914 * @param serviceName String
915 * @param rpcStatusEx RpcStatusEx
916 * @param message String
917 * @param pathDescription PathDescription
919 private void sendNotificationsWithPathDescription(
920 ServicePathNotificationTypes servicePathNotificationTypes,
922 RpcStatusEx rpcStatusEx,
924 PathDescription pathDescription,
926 Set<String> supportedLinks,
927 String serviceType) {
930 notification.buildNotification(
931 servicePathNotificationTypes,
943 private Link createLinkForNotif(List<LinkTp> otnLinkTerminationPoints) {
945 otnLinkTerminationPoints == null || otnLinkTerminationPoints.size() != 2
949 new ATerminationBuilder()
950 .setNodeId(otnLinkTerminationPoints.get(0).getNodeId())
951 .setTpId(otnLinkTerminationPoints.get(0).getTpId())
954 new ZTerminationBuilder()
955 .setNodeId(otnLinkTerminationPoints.get(1).getNodeId())
956 .setTpId(otnLinkTerminationPoints.get(1).getTpId())
961 private Set<String> getSupportedLinks(Set<String> allSupportLinks, String serviceType) {
962 //TODO a Map might be more indicated here
963 switch (serviceType) {
964 case StringConstants.SERVICE_TYPE_10GE:
965 case StringConstants.SERVICE_TYPE_1GE:
966 return allSupportLinks.stream()
967 .filter(lk -> lk.startsWith(OtnLinkType.ODTU4.getName())).collect(Collectors.toSet());
968 case StringConstants.SERVICE_TYPE_100GE_M:
969 return allSupportLinks.stream()
970 .filter(lk -> lk.startsWith(OtnLinkType.ODUC4.getName())).collect(Collectors.toSet());
971 case StringConstants.SERVICE_TYPE_ODU4:
972 case StringConstants.SERVICE_TYPE_100GE_S:
973 return allSupportLinks.stream()
974 .filter(lk -> lk.startsWith(OtnLinkType.OTU4.getName())).collect(Collectors.toSet());
975 case StringConstants.SERVICE_TYPE_ODUC4:
976 return allSupportLinks.stream()
977 .filter(lk -> lk.startsWith(OtnLinkType.OTUC4.getName())).collect(Collectors.toSet());