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.NotificationPublishService;
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.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.OtnDeviceRenderingTask;
43 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor;
44 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackResultMessage;
45 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.History;
46 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.TransactionHistory;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.Action;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathInput;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev220630.OtnLinkType;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmInputBuilder;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmOutput;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerSetupInput;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownInputBuilder;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownOutput;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.TransportpceOlmService;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.get.pm.output.Measurements;
57 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.RendererRpcResultSp;
58 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.RendererRpcResultSpBuilder;
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.binding.Notification;
83 import org.opendaylight.yangtools.yang.common.Uint32;
84 import org.osgi.service.component.annotations.Activate;
85 import org.osgi.service.component.annotations.Component;
86 import org.osgi.service.component.annotations.Reference;
87 import org.slf4j.Logger;
88 import org.slf4j.LoggerFactory;
91 @Component(immediate = true)
92 public class RendererServiceOperationsImpl implements RendererServiceOperations {
94 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
95 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
96 "Device rendering was not successful! Rendering will be rolled back.";
97 private static final String OLM_ROLL_BACK_MSG =
98 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
99 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
100 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
101 private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path";
102 private static final String FAILED = "Failed";
103 private static final String OPERATION_FAILED = "Operation Failed";
104 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
105 private static final int NUMBER_OF_THREADS = 4;
107 private final DeviceRendererService deviceRenderer;
108 private final OtnDeviceRendererService otnDeviceRenderer;
109 private final TransportpceOlmService olmService;
110 private final DataBroker dataBroker;
111 private final NotificationPublishService notificationPublishService;
112 private final PortMapping portMapping;
113 private ListeningExecutorService executor;
116 public RendererServiceOperationsImpl(@Reference DeviceRendererService deviceRenderer,
117 @Reference OtnDeviceRendererService otnDeviceRenderer,
118 @Reference TransportpceOlmService olmService,
119 @Reference DataBroker dataBroker,
120 @Reference NotificationPublishService notificationPublishService,
121 @Reference PortMapping portMapping) {
122 this.deviceRenderer = deviceRenderer;
123 this.otnDeviceRenderer = otnDeviceRenderer;
124 this.olmService = olmService;
125 this.dataBroker = dataBroker;
126 this.notificationPublishService = notificationPublishService;
127 this.portMapping = portMapping;
128 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
129 LOG.debug("RendererServiceOperationsImpl instantiated");
133 public ListenableFuture<ServiceImplementationRequestOutput>
134 serviceImplementation(ServiceImplementationRequestInput input, boolean isTempService) {
135 LOG.info("Calling service impl request {}", input.getServiceName());
136 LOG.debug("Check if it is temp-service {}", isTempService);
137 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
140 public ServiceImplementationRequestOutput call() throws Exception {
142 ServicePathNotificationTypes.ServiceImplementationRequest,
143 input.getServiceName(),
145 "Service compliant, submitting service implementation Request ...");
146 Uint32 serviceRate = getServiceRate(input);
147 LOG.info("Using {}G rate", serviceRate);
148 org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221
149 .network.Nodes mappingNode =
150 portMapping.isNodeExist(input.getServiceAEnd().getNodeId())
151 ? portMapping.getNode(input.getServiceAEnd().getNodeId())
153 String serviceType = ServiceTypes.getServiceType(
154 input.getServiceAEnd().getServiceFormat().getName(),
157 && NodeTypes.Xpdr.equals(mappingNode.getNodeInfo().getNodeType())
158 && input.getServiceAEnd().getTxDirection() != null
159 && input.getServiceAEnd().getTxDirection().getPort() != null
160 && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null
161 ? portMapping.getMapping(input.getServiceAEnd().getNodeId(),
162 input.getServiceAEnd().getTxDirection().getPort().getPortName())
164 //TODO a Map might be more indicated here
165 switch (serviceType) {
166 case StringConstants.SERVICE_TYPE_100GE_T:
167 case StringConstants.SERVICE_TYPE_400GE:
168 case StringConstants.SERVICE_TYPE_OTU4:
169 case StringConstants.SERVICE_TYPE_OTUC2:
170 case StringConstants.SERVICE_TYPE_OTUC3:
171 case StringConstants.SERVICE_TYPE_OTUC4:
172 LOG.debug("Check temp service {}", isTempService);
173 if (!manageServicePathCreation(input, serviceType, isTempService)) {
174 return ModelMappingUtils
175 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
178 case StringConstants.SERVICE_TYPE_1GE:
179 case StringConstants.SERVICE_TYPE_10GE:
180 case StringConstants.SERVICE_TYPE_100GE_M:
181 case StringConstants.SERVICE_TYPE_100GE_S:
182 case StringConstants.SERVICE_TYPE_ODU4:
183 case StringConstants.SERVICE_TYPE_ODUC2:
184 case StringConstants.SERVICE_TYPE_ODUC3:
185 case StringConstants.SERVICE_TYPE_ODUC4:
186 if (!manageOtnServicePathCreation(input, serviceType, serviceRate)) {
187 return ModelMappingUtils
188 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
192 LOG.error("unsupported service-type");
193 return ModelMappingUtils
194 .createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
196 return ModelMappingUtils
197 .createServiceImplResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
203 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
204 String serviceName = input.getServiceName();
205 LOG.info("Calling service delete request {}", serviceName);
206 return executor.submit(new Callable<ServiceDeleteOutput>() {
209 public ServiceDeleteOutput call() throws Exception {
211 ServicePathNotificationTypes.ServiceDelete,
214 "Service compliant, submitting service delete Request ...");
215 // Obtain path description
217 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
218 .service.path.PathDescription> pathDescriptionOpt =
219 getPathDescriptionFromDatastore(serviceName);
220 if (pathDescriptionOpt.isEmpty()) {
221 LOG.error("Unable to get path description for service {}!", serviceName);
223 ServicePathNotificationTypes.ServiceDelete,
226 "Unable to get path description for service");
227 return ModelMappingUtils
228 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
230 PathDescription pathDescription = pathDescriptionOpt.orElseThrow();
232 ServiceTypes.getServiceType(
233 service.getServiceAEnd().getServiceFormat().getName(),
234 service.getServiceAEnd().getServiceRate(),
235 service.getServiceAEnd().getTxDirection() == null
236 || service.getServiceAEnd().getTxDirection().values().stream().findFirst().orElseThrow()
238 || service.getServiceAEnd().getTxDirection().values().stream().findFirst().orElseThrow()
239 .getPort().getPortName() == null
241 : portMapping.getMapping(
242 service.getServiceAEnd().getNodeId().getValue(),
243 service.getServiceAEnd().getTxDirection().values().stream().findFirst()
244 .orElseThrow().getPort().getPortName()));
245 switch (serviceType) {
246 case StringConstants.SERVICE_TYPE_100GE_T:
247 case StringConstants.SERVICE_TYPE_400GE:
248 case StringConstants.SERVICE_TYPE_OTU4:
249 case StringConstants.SERVICE_TYPE_OTUC2:
250 case StringConstants.SERVICE_TYPE_OTUC3:
251 case StringConstants.SERVICE_TYPE_OTUC4:
252 if (!manageServicePathDeletion(serviceName, pathDescription, serviceType)) {
253 return ModelMappingUtils
254 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
257 case StringConstants.SERVICE_TYPE_1GE:
258 case StringConstants.SERVICE_TYPE_10GE:
259 case StringConstants.SERVICE_TYPE_100GE_M:
260 case StringConstants.SERVICE_TYPE_100GE_S:
261 case StringConstants.SERVICE_TYPE_ODU4:
262 case StringConstants.SERVICE_TYPE_ODUC2:
263 case StringConstants.SERVICE_TYPE_ODUC3:
264 case StringConstants.SERVICE_TYPE_ODUC4:
265 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service, serviceType)) {
266 return ModelMappingUtils
267 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
271 LOG.error("unsupported service-type");
272 return ModelMappingUtils
273 .createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED);
275 return ModelMappingUtils
276 .createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
282 value = "UPM_UNCALLED_PRIVATE_METHOD",
283 justification = "call in call() method")
284 private Uint32 getServiceRate(ServiceImplementationRequestInput input) {
285 if (input.getServiceAEnd() == null) {
286 LOG.warn("Unable to get service-rate for service {}", input.getServiceName());
289 if (input.getServiceAEnd().getServiceRate() != null) {
290 return input.getServiceAEnd().getServiceRate();
292 LOG.warn("Input should have rate if you are using 200 or 300G");
293 // TODO: missing 200, and 300G rates here, OTUCn cannot always be 400G
294 Map<ServiceFormat, Map<String, Uint32>> formatRateMap = Map.of(
295 ServiceFormat.OTU, Map.of(
296 "OTUCn", Uint32.valueOf(400),
297 "OTU4", Uint32.valueOf(100),
298 "OTU2", Uint32.valueOf(10),
299 "OTU2e", Uint32.valueOf(10)),
300 ServiceFormat.ODU, Map.of(
301 "ODUCn",Uint32.valueOf(400),
302 "ODU4", Uint32.valueOf(100),
303 "ODU2", Uint32.valueOf(10),
304 "ODU2e", Uint32.valueOf(10),
305 "ODU0", Uint32.valueOf(1)));
306 if (!formatRateMap.containsKey(input.getServiceAEnd().getServiceFormat())) {
307 LOG.warn("Unable to get service-rate for service {} - unsupported service format {}",
308 input.getServiceName(), input.getServiceAEnd().getServiceFormat());
312 ServiceFormat.OTU.getName().equals(input.getServiceAEnd().getServiceFormat().getName())
313 ? input.getServiceAEnd().getOtuServiceRate().toString().split("\\{")[0]
314 : input.getServiceAEnd().getOduServiceRate().toString().split("\\{")[0];
315 if (!formatRateMap.get(input.getServiceAEnd().getServiceFormat()).containsKey(serviceName)) {
316 LOG.warn("Unable to get service-rate for service {} - unsupported service name {}",
317 input.getServiceName(), serviceName);
321 .get(input.getServiceAEnd().getServiceFormat())
326 value = "UPM_UNCALLED_PRIVATE_METHOD",
327 justification = "call in call() method")
328 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
329 throws InterruptedException, ExecutionException, TimeoutException {
330 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
331 return this.olmService
332 .servicePowerTurndown(
333 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build())
334 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS)
339 value = "UPM_UNCALLED_PRIVATE_METHOD",
340 justification = "call in call() method")
341 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
342 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
343 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
344 .service.path.PathDescription> pathDescriptionIID =
345 InstanceIdentifier.create(ServicePathList.class)
346 .child(ServicePaths.class, new ServicePathsKey(serviceName))
347 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
348 .service.path.PathDescription.class);
350 LOG.debug("Getting path description for service {}", serviceName);
351 return this.dataBroker.newReadOnlyTransaction()
352 .read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
353 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
354 } catch (InterruptedException | ExecutionException | TimeoutException e) {
355 LOG.warn("Exception while getting path description from datastore {} for service {}!",
356 pathDescriptionIID, serviceName, e);
357 return Optional.empty();
362 value = "UPM_UNCALLED_PRIVATE_METHOD",
363 justification = "call in call() method")
364 private List<DeviceRenderingResult> deviceRendering(
365 RollbackProcessor rollbackProcessor,
366 ServicePathInputData servicePathDataAtoZ,
367 ServicePathInputData servicePathDataZtoA) {
369 //TODO atozrenderingFuture & ztoarenderingFuture & renderingCombinedFuture used only once
370 // Do notifications & LOG.info deserve this ?
371 LOG.info(RENDERING_DEVICES_A_Z_MSG);
373 ServicePathNotificationTypes.ServiceImplementationRequest,
374 servicePathDataAtoZ.getServicePathInput().getServiceName(),
376 RENDERING_DEVICES_A_Z_MSG);
378 History transactionHistory = new TransactionHistory();
379 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
380 this.executor.submit(
381 new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ, ServicePathDirection.A_TO_Z,
382 transactionHistory));
384 LOG.info(RENDERING_DEVICES_Z_A_MSG);
386 ServicePathNotificationTypes.ServiceImplementationRequest,
387 servicePathDataZtoA.getServicePathInput().getServiceName(),
389 RENDERING_DEVICES_Z_A_MSG);
390 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
391 this.executor.submit(
392 new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA, ServicePathDirection.Z_TO_A,
393 transactionHistory));
395 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
396 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
398 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
400 LOG.info("Waiting for A-Z and Z-A device renderers ...");
401 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
402 } catch (InterruptedException | ExecutionException | TimeoutException e) {
403 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
405 ServicePathNotificationTypes.ServiceImplementationRequest,
406 servicePathDataAtoZ.getServicePathInput().getServiceName(),
408 DEVICE_RENDERING_ROLL_BACK_MSG);
409 //FIXME we can't do rollback here, because we don't have rendering results.
410 return renderingResults;
413 rollbackProcessor.addTask(
414 new NetworkDeviceRenderingRollbackTask(
415 "RollbackTransactionHistoryTask",
417 ! (renderingResults.get(0).isSuccess() && renderingResults.get(1).isSuccess()),
419 new RollbackResultMessage()
423 return renderingResults;
427 value = "UPM_UNCALLED_PRIVATE_METHOD",
428 justification = "call in call() method")
429 private List<OtnDeviceRenderingResult> otnDeviceRendering(
430 RollbackProcessor rollbackProcessor,
431 OtnServicePathInput otnServicePathAtoZ,
432 OtnServicePathInput otnServicePathZtoA,
433 String serviceType) {
435 //TODO atozrenderingFuture & ztoarenderingFuture & renderingCombinedFuture used only once
436 // Do notifications & LOG.info deserve this ?
437 LOG.info(RENDERING_DEVICES_A_Z_MSG);
439 ServicePathNotificationTypes.ServiceImplementationRequest,
440 otnServicePathAtoZ.getServiceName(),
442 RENDERING_DEVICES_A_Z_MSG);
443 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
444 this.executor.submit(
445 new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ, serviceType));
447 LOG.info(RENDERING_DEVICES_Z_A_MSG);
449 ServicePathNotificationTypes.ServiceImplementationRequest,
450 otnServicePathZtoA.getServiceName(),
452 RENDERING_DEVICES_Z_A_MSG);
453 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
454 this.executor.submit(
455 new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA, serviceType));
457 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
458 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
459 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
461 LOG.info("Waiting for A-Z and Z-A device renderers ...");
462 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
463 } catch (InterruptedException | ExecutionException | TimeoutException e) {
464 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
466 ServicePathNotificationTypes.ServiceImplementationRequest,
467 otnServicePathAtoZ.getServiceName(),
469 DEVICE_RENDERING_ROLL_BACK_MSG);
470 //FIXME we can't do rollback here, because we don't have rendering results.
471 return otnRenderingResults;
473 for (int i = 0; i < otnRenderingResults.size(); i++) {
474 rollbackProcessor.addTask(
475 new DeviceRenderingRollbackTask(
476 "DeviceTask n° " + i + 1,
477 ! otnRenderingResults.get(i).isSuccess(),
478 otnRenderingResults.get(i).getRenderedNodeInterfaces(),
479 this.deviceRenderer));
481 return otnRenderingResults;
485 value = "UPM_UNCALLED_PRIVATE_METHOD",
486 justification = "call in call() method")
487 private void olmPowerSetup(
488 RollbackProcessor rollbackProcessor,
489 ServicePowerSetupInput powerSetupInputAtoZ,
490 ServicePowerSetupInput powerSetupInputZtoA, boolean isTempService) {
492 //TODO olmPowerSetupFutureAtoZ & olmPowerSetupFutureZtoA & olmFutures used only once
493 // Do notifications & LOG.info deserve this ?
494 //TODO use constants for LOG.info & notifications common messages
495 // if the service create is a temp-service, OLM will be skipped
497 LOG.info("For temp-service create OLM is not computed and skipped");
500 LOG.info("Olm power setup A-Z");
502 ServicePathNotificationTypes.ServiceImplementationRequest,
503 powerSetupInputAtoZ.getServiceName(),
505 "Olm power setup A-Z");
506 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ =
507 this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
509 LOG.info("OLM power setup Z-A");
511 ServicePathNotificationTypes.ServiceImplementationRequest,
512 powerSetupInputAtoZ.getServiceName(),
514 "Olm power setup Z-A");
515 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA =
516 this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
517 ListenableFuture<List<OLMRenderingResult>> olmFutures =
518 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
520 List<OLMRenderingResult> olmResults;
522 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
523 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
524 } catch (InterruptedException | ExecutionException | TimeoutException e) {
525 LOG.warn(OLM_ROLL_BACK_MSG, e);
527 ServicePathNotificationTypes.ServiceImplementationRequest,
528 powerSetupInputAtoZ.getServiceName(),
531 rollbackProcessor.addTask(
532 new OlmPowerSetupRollbackTask("AtoZOLMTask", true, this.olmService, powerSetupInputAtoZ));
533 rollbackProcessor.addTask(
534 new OlmPowerSetupRollbackTask("ZtoAOLMTask", true, this.olmService, powerSetupInputZtoA));
537 rollbackProcessor.addTask(
538 new OlmPowerSetupRollbackTask(
540 !olmResults.get(0).isSuccess(),
542 powerSetupInputAtoZ));
543 rollbackProcessor.addTask(
544 new OlmPowerSetupRollbackTask(
546 !olmResults.get(1).isSuccess(),
548 powerSetupInputZtoA));
552 value = "UPM_UNCALLED_PRIVATE_METHOD",
553 justification = "call in call() method")
554 private boolean isServiceActivated(String nodeId, String tpId) {
555 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
556 for (int i = 0; i < 3; i++) {
557 List<Measurements> measurements = getMeasurements(nodeId, tpId);
558 if (measurements == null) {
559 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
562 if (verifyPreFecBer(measurements)) {
566 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
567 } catch (InterruptedException ex) {
568 Thread.currentThread().interrupt();
571 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
575 private List<Measurements> getMeasurements(String nodeId, String tp) {
577 GetPmOutput getPmOutput =
580 new GetPmInputBuilder()
582 .setGranularity(PmGranularity._15min)
583 .setResourceIdentifier(new ResourceIdentifierBuilder().setResourceName(tp + "-OTU").build())
584 .setResourceType(ResourceTypeEnum.Interface)
588 if ((getPmOutput == null) || (getPmOutput.getNodeId() == null)) {
589 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
591 LOG.info("successfully finished calling OLM's get PM");
592 return getPmOutput.getMeasurements();
596 } catch (ExecutionException | InterruptedException e) {
597 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
602 private boolean verifyPreFecBer(List<Measurements> measurements) {
603 double preFecCorrectedErrors = Double.MIN_VALUE;
604 double fecUncorrectableBlocks = Double.MIN_VALUE;
606 for (Measurements measurement : measurements) {
607 switch (measurement.getPmparameterName()) {
608 case "preFECCorrectedErrors":
609 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
611 case "FECUncorrectableBlocks":
612 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
619 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}",
620 preFecCorrectedErrors, fecUncorrectableBlocks);
622 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
623 LOG.error("Data has uncorrectable errors, BER test failed");
627 double numOfBitsPerSecond = 112000000000d;
628 double threshold = 0.00002d;
629 double result = preFecCorrectedErrors / numOfBitsPerSecond;
630 LOG.info("PreFEC value is {}", Double.toString(result));
631 return result <= threshold;
635 value = "UPM_UNCALLED_PRIVATE_METHOD",
636 justification = "call in call() method")
637 private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType,
638 boolean isTempService) {
639 ServicePathInputData servicePathInputDataAtoZ =
641 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create);
642 ServicePathInputData servicePathInputDataZtoA =
644 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create);
645 // Rollback should be same for all conditions, so creating a new one
646 RollbackProcessor rollbackProcessor = new RollbackProcessor();
647 List<DeviceRenderingResult> renderingResults =
648 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
649 if (rollbackProcessor.rollbackAllIfNecessary() > 0 || renderingResults.isEmpty()) {
651 ServicePathNotificationTypes.ServiceImplementationRequest,
652 input.getServiceName(),
654 DEVICE_RENDERING_ROLL_BACK_MSG);
659 //olmPowerSetupInputAtoZ,
660 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input),
661 //olmPowerSetupInputZtoA
662 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input), isTempService);
663 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
665 ServicePathNotificationTypes.ServiceImplementationRequest,
666 input.getServiceName(),
671 // run service activation test twice - once on source node and once on
673 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
674 if ((nodes == null) || (nodes.isEmpty())) {
678 Nodes sourceNode = nodes.get(0);
679 Nodes destNode = nodes.get(nodes.size() - 1);
680 String srcNetworkTp =
681 sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
682 ? sourceNode.getDestTp()
683 : sourceNode.getSrcTp();
684 String dstNetowrkTp =
685 destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
686 ? destNode.getDestTp()
687 : destNode.getSrcTp();
689 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
690 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
691 rollbackProcessor.rollbackAll();
693 ServicePathNotificationTypes.ServiceImplementationRequest,
694 input.getServiceName(),
696 "Service activation test failed.");
699 sendNotificationsWithPathDescription(
700 ServicePathNotificationTypes.ServiceImplementationRequest,
701 input.getServiceName(),
702 RpcStatusEx.Successful,
703 OPERATION_SUCCESSFUL,
704 input.getPathDescription(),
706 renderingResults.stream()
707 .flatMap(rr -> rr.getOtnLinkTps().stream())
708 .collect(Collectors.toList())),
715 value = "UPM_UNCALLED_PRIVATE_METHOD",
716 justification = "call in call() method")
717 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType)
718 throws InterruptedException {
719 ServicePathInputData servicePathInputDataAtoZ =
720 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete);
721 ServicePathInputData servicePathInputDataZtoA =
722 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete);
723 // OLM turn down power
725 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
727 ServicePathNotificationTypes.ServiceDelete,
730 TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
731 // TODO add some flag rather than string
733 olmPowerTurndown(servicePathInputDataAtoZ)
735 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
737 ServicePathNotificationTypes.ServiceDelete,
740 "Service power turndown failed on A-to-Z path for service");
743 LOG.debug("Turning down power on Z-to-A path");
745 ServicePathNotificationTypes.ServiceDelete,
748 "Turning down power on Z-to-A path");
749 // TODO add some flag rather than string
751 olmPowerTurndown(servicePathInputDataZtoA)
753 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
755 ServicePathNotificationTypes.ServiceDelete,
758 "Service power turndown failed on Z-to-A path for service");
761 } catch (InterruptedException | ExecutionException | TimeoutException e) {
762 LOG.error("Error while turning down power!", e);
765 // delete service path with renderer
766 LOG.info("Deleting service path via renderer");
768 ServicePathNotificationTypes.ServiceDelete,
771 "Deleting service path via renderer");
772 sendNotificationsWithPathDescription(
773 ServicePathNotificationTypes.ServiceDelete,
775 RpcStatusEx.Successful,
776 OPERATION_SUCCESSFUL,
780 new RollbackProcessor(),
781 servicePathInputDataAtoZ,
782 servicePathInputDataZtoA)
784 .flatMap(rr -> rr.getOtnLinkTps().stream())
785 .collect(Collectors.toList())),
792 value = "UPM_UNCALLED_PRIVATE_METHOD",
793 justification = "call in call() method")
794 private boolean manageOtnServicePathCreation(
795 ServiceImplementationRequestInput input,
797 Uint32 serviceRate) {
798 // Rollback should be same for all conditions, so creating a new one
799 RollbackProcessor rollbackProcessor = new RollbackProcessor();
800 List<OtnDeviceRenderingResult> renderingResults =
805 .rendererCreateOtnServiceInput(
806 input.getServiceName(),
808 input.getServiceAEnd().getServiceFormat().getName(),
810 input.getPathDescription(),
814 .rendererCreateOtnServiceInput(
815 input.getServiceName(),
817 input.getServiceZEnd().getServiceFormat().getName(),
819 input.getPathDescription(),
822 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
823 rollbackProcessor.rollbackAll();
825 ServicePathNotificationTypes.ServiceImplementationRequest,
826 input.getServiceName(),
828 DEVICE_RENDERING_ROLL_BACK_MSG);
831 sendNotificationsWithPathDescription(
832 ServicePathNotificationTypes.ServiceImplementationRequest,
833 input.getServiceName(),
834 RpcStatusEx.Successful, OPERATION_SUCCESSFUL,
835 input.getPathDescription(),
837 renderingResults.stream()
838 .flatMap(rr -> rr.getOtnLinkTps().stream())
839 .collect(Collectors.toList())),
841 ModelMappingUtils.getLinksFromServicePathDescription(input.getPathDescription()),
848 value = "UPM_UNCALLED_PRIVATE_METHOD",
849 justification = "call in call() method")
850 private boolean manageOtnServicePathDeletion(
852 PathDescription pathDescription,
854 String serviceType) {
855 LOG.info("Deleting otn-service path {} via renderer", serviceName);
857 ServicePathNotificationTypes.ServiceDelete,
860 "Deleting otn-service path via renderer");
861 List<OtnDeviceRenderingResult> renderingResults =
863 new RollbackProcessor(),
866 .rendererCreateOtnServiceInput(
869 service.getServiceAEnd().getServiceFormat().getName(),
870 service.getServiceAEnd().getServiceRate(),
875 .rendererCreateOtnServiceInput(
878 service.getServiceZEnd().getServiceFormat().getName(),
879 service.getServiceAEnd().getServiceRate(),
883 sendNotificationsWithPathDescription(
884 ServicePathNotificationTypes.ServiceDelete,
886 RpcStatusEx.Successful,
887 OPERATION_SUCCESSFUL,
890 renderingResults.stream()
891 .flatMap(rr -> rr.getOtnLinkTps().stream())
892 .collect(Collectors.toList())),
894 ModelMappingUtils.getLinksFromServicePathDescription(pathDescription),
901 * Send renderer notification.
902 * @param servicePathNotificationTypes ServicePathNotificationTypes
903 * @param serviceName String
904 * @param rpcStatusEx RpcStatusEx
905 * @param message String
907 private void sendNotifications(
908 ServicePathNotificationTypes servicePathNotificationTypes,
910 RpcStatusEx rpcStatusEx,
913 buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
914 null, null, null, null));
918 * Send renderer notification with path description information.
919 * @param servicePathNotificationTypes ServicePathNotificationTypes
920 * @param serviceName String
921 * @param rpcStatusEx RpcStatusEx
922 * @param message String
923 * @param pathDescription PathDescription
925 private void sendNotificationsWithPathDescription(
926 ServicePathNotificationTypes servicePathNotificationTypes,
928 RpcStatusEx rpcStatusEx,
930 PathDescription pathDescription,
932 Set<String> supportedLinks,
933 String serviceType) {
935 buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
936 pathDescription, notifLink, supportedLinks, serviceType));
940 * Build notification containing path description information.
941 * @param servicePathNotificationTypes ServicePathNotificationTypes
942 * @param serviceName String
943 * @param rpcStatusEx RpcStatusEx
944 * @param message String
945 * @param pathDescription PathDescription
946 * @return notification with RendererRpcResultSp type.
948 private RendererRpcResultSp buildNotification(
949 ServicePathNotificationTypes servicePathNotificationTypes,
951 RpcStatusEx rpcStatusEx,
953 PathDescription pathDescription,
955 Set<String> supportedLinks,
956 String serviceType) {
957 RendererRpcResultSpBuilder builder =
958 new RendererRpcResultSpBuilder()
959 .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx)
960 .setStatusMessage(message)
961 .setServiceType(serviceType);
962 if (pathDescription != null) {
964 .setAToZDirection(pathDescription.getAToZDirection())
965 .setZToADirection(pathDescription.getZToADirection());
967 if (notifLink != null) {
968 builder.setLink(notifLink);
970 if (supportedLinks != null) {
971 builder.setLinkId(supportedLinks);
973 return builder.build();
977 * Send renderer notification.
978 * @param notification Notification
980 private void send(Notification<?> notification) {
982 LOG.info("Sending notification {}", notification);
983 notificationPublishService.putNotification(notification);
984 } catch (InterruptedException e) {
985 LOG.info("notification offer rejected: ", e);
986 Thread.currentThread().interrupt();
990 private Link createLinkForNotif(List<LinkTp> otnLinkTerminationPoints) {
992 otnLinkTerminationPoints == null || otnLinkTerminationPoints.size() != 2
996 new ATerminationBuilder()
997 .setNodeId(otnLinkTerminationPoints.get(0).getNodeId())
998 .setTpId(otnLinkTerminationPoints.get(0).getTpId())
1001 new ZTerminationBuilder()
1002 .setNodeId(otnLinkTerminationPoints.get(1).getNodeId())
1003 .setTpId(otnLinkTerminationPoints.get(1).getTpId())
1008 private Set<String> getSupportedLinks(Set<String> allSupportLinks, String serviceType) {
1009 //TODO a Map might be more indicated here
1010 switch (serviceType) {
1011 case StringConstants.SERVICE_TYPE_10GE:
1012 case StringConstants.SERVICE_TYPE_1GE:
1013 return allSupportLinks.stream()
1014 .filter(lk -> lk.startsWith(OtnLinkType.ODTU4.getName())).collect(Collectors.toSet());
1015 case StringConstants.SERVICE_TYPE_100GE_M:
1016 return allSupportLinks.stream()
1017 .filter(lk -> lk.startsWith(OtnLinkType.ODUC4.getName())).collect(Collectors.toSet());
1018 case StringConstants.SERVICE_TYPE_ODU4:
1019 case StringConstants.SERVICE_TYPE_100GE_S:
1020 return allSupportLinks.stream()
1021 .filter(lk -> lk.startsWith(OtnLinkType.OTU4.getName())).collect(Collectors.toSet());
1022 case StringConstants.SERVICE_TYPE_ODUC4:
1023 return allSupportLinks.stream()
1024 .filter(lk -> lk.startsWith(OtnLinkType.OTUC4.getName())).collect(Collectors.toSet());