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 java.util.ArrayList;
15 import java.util.List;
17 import java.util.Optional;
18 import java.util.concurrent.Callable;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.Executors;
21 import java.util.concurrent.Future;
22 import java.util.concurrent.TimeUnit;
23 import java.util.concurrent.TimeoutException;
24 import org.opendaylight.mdsal.binding.api.DataBroker;
25 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
26 import org.opendaylight.mdsal.binding.api.ReadTransaction;
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.servicepath.ServicePathDirection;
36 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingRollbackTask;
37 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingTask;
38 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupRollbackTask;
39 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupTask;
40 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OtnDeviceRenderingTask;
41 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor;
42 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev210618.Action;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev210618.OtnServicePathInput;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmInputBuilder;
45 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmOutput;
46 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerSetupInput;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownInputBuilder;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownOutput;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.TransportpceOlmService;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.get.pm.output.Measurements;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mapping.Mapping;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.RendererRpcResultSp;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.RendererRpcResultSpBuilder;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteInput;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteOutput;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestInput;
57 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestOutput;
58 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ATerminationBuilder;
59 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ZTerminationBuilder;
60 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.Link;
61 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.LinkBuilder;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat;
66 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
67 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.PathDescription;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.ServicePathNotificationTypes;
70 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
71 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
72 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
73 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTp;
74 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.olm.get.pm.input.ResourceIdentifierBuilder;
75 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.optical.renderer.nodes.Nodes;
76 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
77 import org.opendaylight.yangtools.yang.binding.Notification;
78 import org.opendaylight.yangtools.yang.common.RpcResult;
79 import org.opendaylight.yangtools.yang.common.Uint32;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
84 public class RendererServiceOperationsImpl implements RendererServiceOperations {
86 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
87 "Device rendering was not successful! Rendering will be rolled back.";
88 private static final String OLM_ROLL_BACK_MSG =
89 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
90 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
91 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
92 private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path";
93 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
94 private static final String FAILED = "Failed";
95 private static final String OPERATION_FAILED = "Operation Failed";
96 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
97 private static final int NUMBER_OF_THREADS = 4;
99 private final DeviceRendererService deviceRenderer;
100 private final OtnDeviceRendererService otnDeviceRenderer;
101 private final TransportpceOlmService olmService;
102 private final DataBroker dataBroker;
103 private final NotificationPublishService notificationPublishService;
104 private final PortMapping portMapping;
105 private ListeningExecutorService executor;
107 public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer,
108 OtnDeviceRendererService otnDeviceRenderer, TransportpceOlmService olmService,
109 DataBroker dataBroker, NotificationPublishService notificationPublishService, PortMapping portMapping) {
110 this.deviceRenderer = deviceRenderer;
111 this.otnDeviceRenderer = otnDeviceRenderer;
112 this.olmService = olmService;
113 this.dataBroker = dataBroker;
114 this.notificationPublishService = notificationPublishService;
115 this.portMapping = portMapping;
116 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
120 public ListenableFuture<ServiceImplementationRequestOutput>
121 serviceImplementation(ServiceImplementationRequestInput input) {
122 LOG.info("Calling service impl request {}", input.getServiceName());
123 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
126 public ServiceImplementationRequestOutput call() throws Exception {
127 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(),
128 RpcStatusEx.Pending, "Service compliant, submitting service implementation Request ...");
129 Uint32 serviceRate = getServiceRate(input);
130 String serviceType = ServiceTypes.getServiceType(
131 input.getServiceAEnd().getServiceFormat().getName(),
133 (NodeTypes.Xpdr.equals(portMapping.getNode(input.getServiceAEnd().getNodeId())
134 .getNodeInfo().getNodeType())
135 && input.getServiceAEnd().getTxDirection() != null
136 && input.getServiceAEnd().getTxDirection().getPort() != null
137 && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null)
138 ? portMapping.getMapping(input.getServiceAEnd().getNodeId(),
139 input.getServiceAEnd().getTxDirection().getPort().getPortName())
142 switch (serviceType) {
143 case StringConstants.SERVICE_TYPE_100GE_T:
144 case StringConstants.SERVICE_TYPE_400GE:
145 case StringConstants.SERVICE_TYPE_OTU4:
146 case StringConstants.SERVICE_TYPE_OTUC4:
147 if (!manageServicePathCreation(input, serviceType)) {
148 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
152 case StringConstants.SERVICE_TYPE_1GE:
153 case StringConstants.SERVICE_TYPE_10GE:
154 case StringConstants.SERVICE_TYPE_100GE_M:
155 case StringConstants.SERVICE_TYPE_100GE_S:
156 case StringConstants.SERVICE_TYPE_ODU4:
157 case StringConstants.SERVICE_TYPE_ODUC4:
158 if (!manageOtnServicePathCreation(input, serviceType, serviceRate)) {
159 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
164 LOG.error("unsupported service-type");
165 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
168 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
169 OPERATION_SUCCESSFUL);
175 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
176 String serviceName = input.getServiceName();
177 LOG.info("Calling service delete request {}", serviceName);
178 return executor.submit(new Callable<ServiceDeleteOutput>() {
181 public ServiceDeleteOutput call() throws Exception {
182 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
183 RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
184 // Obtain path description
186 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service
187 .path.PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
188 if (pathDescriptionOpt.isEmpty()) {
189 LOG.error("Unable to get path description for service {}!", serviceName);
190 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
191 RpcStatusEx.Failed, "Unable to get path description for service");
192 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
195 PathDescription pathDescription = pathDescriptionOpt.get();
196 Mapping mapping = portMapping.getMapping(service.getServiceAEnd().getNodeId().getValue(),
197 service.getServiceAEnd().getTxDirection().getPort().getPortName());
198 String serviceType = ServiceTypes.getServiceType(service.getServiceAEnd().getServiceFormat().getName(),
199 service.getServiceAEnd().getServiceRate(), mapping);
200 switch (serviceType) {
201 case StringConstants.SERVICE_TYPE_100GE_T:
202 case StringConstants.SERVICE_TYPE_400GE:
203 case StringConstants.SERVICE_TYPE_OTU4:
204 case StringConstants.SERVICE_TYPE_OTUC4:
205 if (!manageServicePathDeletion(serviceName, pathDescription, serviceType)) {
206 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
210 case StringConstants.SERVICE_TYPE_1GE:
211 case StringConstants.SERVICE_TYPE_10GE:
212 case StringConstants.SERVICE_TYPE_100GE_M:
213 case StringConstants.SERVICE_TYPE_100GE_S:
214 case StringConstants.SERVICE_TYPE_ODU4:
215 case StringConstants.SERVICE_TYPE_ODUC4:
216 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service, serviceType)) {
217 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
222 LOG.error("unsupported service-type");
223 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
226 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
231 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
232 value = "UPM_UNCALLED_PRIVATE_METHOD",
233 justification = "call in call() method")
234 private Uint32 getServiceRate(ServiceImplementationRequestInput input) {
235 if (input.getServiceAEnd() == null) {
236 LOG.warn("Unable to get service-rate for service {}", input.getServiceName());
239 if (input.getServiceAEnd().getServiceRate() != null) {
240 return input.getServiceAEnd().getServiceRate();
242 Map<ServiceFormat, Map<String, Uint32>> formatRateMap = Map.of(
243 ServiceFormat.OTU, Map.of(
244 "OTUCn", Uint32.valueOf(400),
245 "OTU4", Uint32.valueOf(100),
246 "OTU2", Uint32.valueOf(10),
247 "OTU2e", Uint32.valueOf(10)),
248 ServiceFormat.ODU, Map.of(
249 "ODUCn",Uint32.valueOf(400),
250 "ODU4", Uint32.valueOf(100),
251 "ODU2", Uint32.valueOf(10),
252 "ODU2e", Uint32.valueOf(10),
253 "ODU0", Uint32.valueOf(1)));
254 if (!formatRateMap.containsKey(input.getServiceAEnd().getServiceFormat())) {
255 LOG.warn("Unable to get service-rate for service {} - unsupported service format {}",
256 input.getServiceName(), input.getServiceAEnd().getServiceFormat());
260 ServiceFormat.OTU.equals(input.getServiceAEnd().getServiceFormat())
261 ? input.getServiceAEnd().getOtuServiceRate().getSimpleName()
262 : input.getServiceAEnd().getOduServiceRate().getSimpleName();
263 if (!formatRateMap.get(input.getServiceAEnd().getServiceFormat()).containsKey(serviceName)) {
264 LOG.warn("Unable to get service-rate for service {} - unsupported service name {}",
265 input.getServiceName(), serviceName);
268 return formatRateMap.get(input.getServiceAEnd().getServiceFormat()).get(serviceName);
271 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
272 value = "UPM_UNCALLED_PRIVATE_METHOD",
273 justification = "call in call() method")
274 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
275 throws InterruptedException, ExecutionException, TimeoutException {
276 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
277 Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
278 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
279 return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
282 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
283 value = "UPM_UNCALLED_PRIVATE_METHOD",
284 justification = "call in call() method")
285 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
286 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
287 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
288 .service.path.PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
289 .child(ServicePaths.class, new ServicePathsKey(serviceName))
290 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
291 .service.path.PathDescription.class);
292 ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
294 LOG.debug("Getting path description for service {}", serviceName);
295 return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
296 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
297 } catch (InterruptedException | ExecutionException | TimeoutException e) {
298 LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
300 return Optional.empty();
304 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
305 value = "UPM_UNCALLED_PRIVATE_METHOD",
306 justification = "call in call() method")
307 private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
308 ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
309 LOG.info(RENDERING_DEVICES_A_Z_MSG);
310 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
311 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
312 RENDERING_DEVICES_A_Z_MSG);
313 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
314 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
315 ServicePathDirection.A_TO_Z));
317 LOG.info("Rendering devices Z-A");
318 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
319 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
320 RENDERING_DEVICES_Z_A_MSG);
321 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
322 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
323 ServicePathDirection.Z_TO_A));
324 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
325 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
327 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
329 LOG.info("Waiting for A-Z and Z-A device renderers ...");
330 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
331 } catch (InterruptedException | ExecutionException | TimeoutException e) {
332 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
333 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
334 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
335 DEVICE_RENDERING_ROLL_BACK_MSG);
336 //FIXME we can't do rollback here, because we don't have rendering results.
337 return renderingResults;
340 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
341 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
342 this.deviceRenderer));
343 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
344 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
345 this.deviceRenderer));
346 return renderingResults;
349 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
350 value = "UPM_UNCALLED_PRIVATE_METHOD",
351 justification = "call in call() method")
352 private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
353 OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA, String serviceType) {
354 LOG.info(RENDERING_DEVICES_A_Z_MSG);
355 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
356 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
357 RENDERING_DEVICES_A_Z_MSG);
358 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
359 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ, serviceType));
360 LOG.info(RENDERING_DEVICES_Z_A_MSG);
361 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
362 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
363 RENDERING_DEVICES_Z_A_MSG);
364 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
365 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA, serviceType));
366 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
367 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
368 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
370 LOG.info("Waiting for A-Z and Z-A device renderers ...");
371 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
372 } catch (InterruptedException | ExecutionException | TimeoutException e) {
373 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
374 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
375 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
376 DEVICE_RENDERING_ROLL_BACK_MSG);
377 //FIXME we can't do rollback here, because we don't have rendering results.
378 return otnRenderingResults;
380 for (int i = 0; i < otnRenderingResults.size(); i++) {
381 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("DeviceTask n° " + i + 1,
382 ! otnRenderingResults.get(i).isSuccess(), otnRenderingResults.get(i).getRenderedNodeInterfaces(),
383 this.deviceRenderer));
385 return otnRenderingResults;
388 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
389 value = "UPM_UNCALLED_PRIVATE_METHOD",
390 justification = "call in call() method")
391 private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
392 ServicePowerSetupInput powerSetupInputZtoA) {
393 LOG.info("Olm power setup A-Z");
394 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
395 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
396 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
397 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
399 LOG.info("OLM power setup Z-A");
400 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
401 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
402 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
403 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
404 ListenableFuture<List<OLMRenderingResult>> olmFutures =
405 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
407 List<OLMRenderingResult> olmResults;
409 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
410 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
411 } catch (InterruptedException | ExecutionException | TimeoutException e) {
412 LOG.warn(OLM_ROLL_BACK_MSG, e);
413 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
414 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
416 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
417 this.olmService, powerSetupInputAtoZ));
418 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
419 this.olmService, powerSetupInputZtoA));
423 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
424 this.olmService, powerSetupInputAtoZ));
425 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
426 this.olmService, powerSetupInputZtoA));
429 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
430 value = "UPM_UNCALLED_PRIVATE_METHOD",
431 justification = "call in call() method")
432 private boolean isServiceActivated(String nodeId, String tpId) {
433 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
434 for (int i = 0; i < 3; i++) {
435 List<Measurements> measurements = getMeasurements(nodeId, tpId);
436 if (measurements == null) {
437 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
440 if (verifyPreFecBer(measurements)) {
444 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
445 } catch (InterruptedException ex) {
446 Thread.currentThread().interrupt();
449 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
453 private List<Measurements> getMeasurements(String nodeId, String tp) {
454 GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder()
456 .setGranularity(PmGranularity._15min)
457 .setResourceIdentifier(new ResourceIdentifierBuilder().setResourceName(tp + "-OTU").build())
458 .setResourceType(ResourceTypeEnum.Interface);
461 Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
462 RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
463 GetPmOutput getPmOutput = getPmRpcResult.getResult();
464 if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
465 LOG.info("successfully finished calling OLM's get PM");
466 return getPmOutput.getMeasurements();
469 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
472 } catch (ExecutionException | InterruptedException e) {
473 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
478 private boolean verifyPreFecBer(List<Measurements> measurements) {
479 double preFecCorrectedErrors = Double.MIN_VALUE;
480 double fecUncorrectableBlocks = Double.MIN_VALUE;
482 for (Measurements measurement : measurements) {
483 switch (measurement.getPmparameterName()) {
484 case "preFECCorrectedErrors":
485 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
487 case "FECUncorrectableBlocks":
488 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
495 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
496 fecUncorrectableBlocks);
498 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
499 LOG.error("Data has uncorrectable errors, BER test failed");
503 double numOfBitsPerSecond = 112000000000d;
504 double threshold = 0.00002d;
505 double result = preFecCorrectedErrors / numOfBitsPerSecond;
506 LOG.info("PreFEC value is {}", Double.toString(result));
507 return result <= threshold;
510 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
511 value = "UPM_UNCALLED_PRIVATE_METHOD",
512 justification = "call in call() method")
513 private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType) {
514 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
515 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create);
516 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
517 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create);
518 // Rollback should be same for all conditions, so creating a new one
519 RollbackProcessor rollbackProcessor = new RollbackProcessor();
520 List<DeviceRenderingResult> renderingResults =
521 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
522 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
523 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
524 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
527 ServicePowerSetupInput olmPowerSetupInputAtoZ =
528 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input);
529 ServicePowerSetupInput olmPowerSetupInputZtoA =
530 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input);
531 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
532 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
533 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
534 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
537 // run service activation test twice - once on source node and once on
539 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
540 if ((nodes == null) || (nodes.isEmpty())) {
544 Nodes sourceNode = nodes.get(0);
545 Nodes destNode = nodes.get(nodes.size() - 1);
546 String srcNetworkTp =
547 sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
548 ? sourceNode.getDestTp()
549 : sourceNode.getSrcTp();
550 String dstNetowrkTp =
551 destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
552 ? destNode.getDestTp()
553 : destNode.getSrcTp();
555 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
556 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
557 rollbackProcessor.rollbackAll();
558 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
559 input.getServiceName(), RpcStatusEx.Failed,
560 "Service activation test failed.");
563 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
564 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
565 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
567 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
568 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
569 notifLink, null, serviceType);
573 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
574 value = "UPM_UNCALLED_PRIVATE_METHOD",
575 justification = "call in call() method")
576 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType)
577 throws InterruptedException {
578 ServicePathInputData servicePathInputDataAtoZ =
579 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete);
580 ServicePathInputData servicePathInputDataZtoA =
581 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete);
582 // OLM turn down power
584 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
585 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
586 RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
587 ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
588 // TODO add some flag rather than string
589 if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
590 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
591 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
592 "Service power turndown failed on A-to-Z path for service");
595 LOG.debug("Turning down power on Z-to-A path");
596 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
597 "Turning down power on Z-to-A path");
598 ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
599 // TODO add some flag rather than string
600 if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
601 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
602 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
603 "Service power turndown failed on Z-to-A path for service");
606 } catch (InterruptedException | ExecutionException | TimeoutException e) {
607 LOG.error("Error while turning down power!", e);
610 // delete service path with renderer
611 LOG.info("Deleting service path via renderer");
612 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
613 "Deleting service path via renderer");
614 RollbackProcessor rollbackProcessor = new RollbackProcessor();
615 List<DeviceRenderingResult> renderingResults =
616 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
617 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
618 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
619 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
621 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
622 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, null, serviceType);
626 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
627 value = "UPM_UNCALLED_PRIVATE_METHOD",
628 justification = "call in call() method")
629 private boolean manageOtnServicePathCreation(ServiceImplementationRequestInput input, String serviceType,
630 Uint32 serviceRate) {
632 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
633 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
634 input.getServiceAEnd().getServiceFormat().getName(),
636 input.getPathDescription(), true);
638 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
639 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
640 input.getServiceZEnd().getServiceFormat().getName(),
642 input.getPathDescription(), false);
643 // Rollback should be same for all conditions, so creating a new one
644 RollbackProcessor rollbackProcessor = new RollbackProcessor();
645 List<OtnDeviceRenderingResult> renderingResults =
646 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA, serviceType);
647 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
648 rollbackProcessor.rollbackAll();
649 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
650 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
653 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
654 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
655 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
656 List<String> supportedLinks = (notifLink == null && !otnLinkTerminationPoints.isEmpty())
657 ? ModelMappingUtils.getLinksFromServicePathDescription(input.getPathDescription())
660 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
661 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
662 notifLink, supportedLinks, serviceType);
666 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
667 value = "UPM_UNCALLED_PRIVATE_METHOD",
668 justification = "call in call() method")
669 private boolean manageOtnServicePathDeletion(String serviceName, PathDescription pathDescription,
670 Services service, String serviceType) {
672 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
673 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
674 service.getServiceAEnd().getServiceFormat().getName(),
675 service.getServiceAEnd().getServiceRate(),
676 pathDescription, true);
678 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
679 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
680 service.getServiceZEnd().getServiceFormat().getName(),
681 service.getServiceAEnd().getServiceRate(),
682 pathDescription, false);
683 LOG.info("Deleting otn-service path {} via renderer", serviceName);
684 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
685 "Deleting otn-service path via renderer");
687 RollbackProcessor rollbackProcessor = new RollbackProcessor();
688 List<OtnDeviceRenderingResult> renderingResults =
689 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA, serviceType);
691 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
692 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
693 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
694 List<String> supportedLinks = (notifLink == null && !otnLinkTerminationPoints.isEmpty())
695 ? ModelMappingUtils.getLinksFromServicePathDescription(pathDescription)
698 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
699 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, supportedLinks,
705 * Send renderer notification.
706 * @param servicePathNotificationTypes ServicePathNotificationTypes
707 * @param serviceName String
708 * @param rpcStatusEx RpcStatusEx
709 * @param message String
711 private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
712 RpcStatusEx rpcStatusEx, String message) {
713 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
714 null, null, null, null);
719 * Send renderer notification with path description information.
720 * @param servicePathNotificationTypes ServicePathNotificationTypes
721 * @param serviceName String
722 * @param rpcStatusEx RpcStatusEx
723 * @param message String
724 * @param pathDescription PathDescription
726 private void sendNotificationsWithPathDescription(ServicePathNotificationTypes servicePathNotificationTypes,
727 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
728 Link notifLink, List<String> supportedLinks, String serviceType) {
729 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
730 pathDescription, notifLink, supportedLinks, serviceType);
735 * Build notification containing path description information.
736 * @param servicePathNotificationTypes ServicePathNotificationTypes
737 * @param serviceName String
738 * @param rpcStatusEx RpcStatusEx
739 * @param message String
740 * @param pathDescription PathDescription
741 * @return notification with RendererRpcResultSp type.
743 private RendererRpcResultSp buildNotification(ServicePathNotificationTypes servicePathNotificationTypes,
744 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
745 Link notifLink, List<String> supportedLinks, String serviceType) {
746 RendererRpcResultSpBuilder builder = new RendererRpcResultSpBuilder()
747 .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx)
748 .setStatusMessage(message)
749 .setServiceType(serviceType);
750 if (pathDescription != null) {
751 builder.setAToZDirection(pathDescription.getAToZDirection())
752 .setZToADirection(pathDescription.getZToADirection());
754 if (notifLink != null) {
755 builder.setLink(notifLink);
757 if (supportedLinks != null) {
758 builder.setLinkId(supportedLinks);
760 return builder.build();
764 * Send renderer notification.
765 * @param notification Notification
767 private void send(Notification notification) {
769 LOG.info("Sending notification {}", notification);
770 notificationPublishService.putNotification(notification);
771 } catch (InterruptedException e) {
772 LOG.info("notification offer rejected: ", e);
773 Thread.currentThread().interrupt();
777 private Link createLinkForNotif(List<LinkTp> otnLinkTerminationPoints) {
778 if (otnLinkTerminationPoints == null || otnLinkTerminationPoints.size() != 2) {
781 return new LinkBuilder()
782 .setATermination(new ATerminationBuilder()
783 .setNodeId(otnLinkTerminationPoints.get(0).getNodeId())
784 .setTpId(otnLinkTerminationPoints.get(0).getTpId())
786 .setZTermination(new ZTerminationBuilder()
787 .setNodeId(otnLinkTerminationPoints.get(1).getNodeId())
788 .setTpId(otnLinkTerminationPoints.get(1).getTpId())