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.renderer.rev210618.RendererRpcResultSp;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.RendererRpcResultSpBuilder;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceDeleteInput;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceDeleteOutput;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceImplementationRequestInput;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.ServiceImplementationRequestOutput;
57 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.link._for.notif.ATerminationBuilder;
58 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.link._for.notif.ZTerminationBuilder;
59 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.renderer.rpc.result.sp.Link;
60 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.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.pm.types.rev161014.PmGranularity;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
66 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.PathDescription;
67 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.ServicePathNotificationTypes;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
70 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
71 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
72 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTp;
73 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.olm.get.pm.input.ResourceIdentifierBuilder;
74 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.optical.renderer.nodes.Nodes;
75 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
76 import org.opendaylight.yangtools.yang.binding.Notification;
77 import org.opendaylight.yangtools.yang.common.RpcResult;
78 import org.opendaylight.yangtools.yang.common.Uint32;
79 import org.slf4j.Logger;
80 import org.slf4j.LoggerFactory;
83 public class RendererServiceOperationsImpl implements RendererServiceOperations {
85 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
86 "Device rendering was not successful! Rendering will be rolled back.";
87 private static final String OLM_ROLL_BACK_MSG =
88 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
89 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
90 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
91 private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path";
92 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
93 private static final String FAILED = "Failed";
94 private static final String OPERATION_FAILED = "Operation Failed";
95 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
96 private static final int NUMBER_OF_THREADS = 4;
98 private final DeviceRendererService deviceRenderer;
99 private final OtnDeviceRendererService otnDeviceRenderer;
100 private final TransportpceOlmService olmService;
101 private final DataBroker dataBroker;
102 private final NotificationPublishService notificationPublishService;
103 private final PortMapping portMapping;
104 private ListeningExecutorService executor;
106 public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer,
107 OtnDeviceRendererService otnDeviceRenderer, TransportpceOlmService olmService,
108 DataBroker dataBroker, NotificationPublishService notificationPublishService, PortMapping portMapping) {
109 this.deviceRenderer = deviceRenderer;
110 this.otnDeviceRenderer = otnDeviceRenderer;
111 this.olmService = olmService;
112 this.dataBroker = dataBroker;
113 this.notificationPublishService = notificationPublishService;
114 this.portMapping = portMapping;
115 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
119 public ListenableFuture<ServiceImplementationRequestOutput>
120 serviceImplementation(ServiceImplementationRequestInput input) {
121 LOG.info("Calling service impl request {}", input.getServiceName());
122 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
125 public ServiceImplementationRequestOutput call() throws Exception {
126 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(),
127 RpcStatusEx.Pending, "Service compliant, submitting service implementation Request ...");
128 Uint32 serviceRate = getServiceRate(input);
129 String serviceType = ServiceTypes.getServiceType(
130 input.getServiceAEnd().getServiceFormat().getName(),
132 (NodeTypes.Xpdr.equals(portMapping.getNode(input.getServiceAEnd().getNodeId())
133 .getNodeInfo().getNodeType())
134 && input.getServiceAEnd().getTxDirection() != null
135 && input.getServiceAEnd().getTxDirection().getPort() != null
136 && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null)
137 ? portMapping.getMapping(input.getServiceAEnd().getNodeId(),
138 input.getServiceAEnd().getTxDirection().getPort().getPortName())
141 switch (serviceType) {
142 case StringConstants.SERVICE_TYPE_100GE_T:
143 case StringConstants.SERVICE_TYPE_400GE:
144 case StringConstants.SERVICE_TYPE_OTU4:
145 case StringConstants.SERVICE_TYPE_OTUC4:
146 if (!manageServicePathCreation(input, serviceType)) {
147 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
151 case StringConstants.SERVICE_TYPE_1GE:
152 case StringConstants.SERVICE_TYPE_10GE:
153 case StringConstants.SERVICE_TYPE_100GE_M:
154 case StringConstants.SERVICE_TYPE_ODU4:
155 case StringConstants.SERVICE_TYPE_ODUC4:
156 if (!manageOtnServicePathCreation(input, serviceType, serviceRate)) {
157 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
162 LOG.error("unsupported service-type");
163 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
166 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
167 OPERATION_SUCCESSFUL);
173 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
174 String serviceName = input.getServiceName();
175 LOG.info("Calling service delete request {}", serviceName);
176 return executor.submit(new Callable<ServiceDeleteOutput>() {
179 public ServiceDeleteOutput call() throws Exception {
180 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
181 RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
182 // Obtain path description
184 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service
185 .path.PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
186 if (pathDescriptionOpt.isEmpty()) {
187 LOG.error("Unable to get path description for service {}!", serviceName);
188 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
189 RpcStatusEx.Failed, "Unable to get path description for service");
190 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
193 PathDescription pathDescription = pathDescriptionOpt.get();
194 String serviceType = ServiceTypes.getServiceType(service.getServiceAEnd().getServiceFormat().getName(),
195 service.getServiceAEnd().getServiceRate(), portMapping.getMapping(service.getServiceAEnd()
196 .getNodeId().getValue(), service.getServiceAEnd().getTxDirection().getPort().getPortName()));
197 switch (serviceType) {
198 case StringConstants.SERVICE_TYPE_100GE_T:
199 case StringConstants.SERVICE_TYPE_400GE:
200 case StringConstants.SERVICE_TYPE_OTU4:
201 case StringConstants.SERVICE_TYPE_OTUC4:
202 if (!manageServicePathDeletion(serviceName, pathDescription, serviceType)) {
203 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
207 case StringConstants.SERVICE_TYPE_1GE:
208 case StringConstants.SERVICE_TYPE_10GE:
209 case StringConstants.SERVICE_TYPE_100GE_M:
210 case StringConstants.SERVICE_TYPE_ODU4:
211 case StringConstants.SERVICE_TYPE_ODUC4:
212 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service, serviceType)) {
213 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
218 LOG.error("unsupported service-type");
219 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
222 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
227 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
228 value = "UPM_UNCALLED_PRIVATE_METHOD",
229 justification = "call in call() method")
230 private Uint32 getServiceRate(ServiceImplementationRequestInput input) {
231 if (input.getServiceAEnd() == null) {
232 LOG.warn("Unable to get service-rate for service {}", input.getServiceName());
235 if (input.getServiceAEnd().getServiceRate() != null) {
236 return input.getServiceAEnd().getServiceRate();
238 Map<ServiceFormat, Map<String, Uint32>> formatRateMap = Map.of(
239 ServiceFormat.OTU, Map.of(
240 "OTUCn", Uint32.valueOf(400),
241 "OTU4", Uint32.valueOf(100),
242 "OTU2", Uint32.valueOf(10),
243 "OTU2e", Uint32.valueOf(10)),
244 ServiceFormat.ODU, Map.of(
245 "ODUCn",Uint32.valueOf(400),
246 "ODU4", Uint32.valueOf(100),
247 "ODU2", Uint32.valueOf(10),
248 "ODU2e", Uint32.valueOf(10),
249 "ODU0", Uint32.valueOf(1)));
250 if (!formatRateMap.containsKey(input.getServiceAEnd().getServiceFormat())) {
251 LOG.warn("Unable to get service-rate for service {} - unsupported service format {}",
252 input.getServiceName(), input.getServiceAEnd().getServiceFormat());
256 ServiceFormat.OTU.equals(input.getServiceAEnd().getServiceFormat())
257 ? input.getServiceAEnd().getOtuServiceRate().getSimpleName()
258 : input.getServiceAEnd().getOduServiceRate().getSimpleName();
259 if (!formatRateMap.get(input.getServiceAEnd().getServiceFormat()).containsKey(serviceName)) {
260 LOG.warn("Unable to get service-rate for service {} - unsupported service name {}",
261 input.getServiceName(), serviceName);
264 return formatRateMap.get(input.getServiceAEnd().getServiceFormat()).get(serviceName);
267 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
268 value = "UPM_UNCALLED_PRIVATE_METHOD",
269 justification = "call in call() method")
270 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
271 throws InterruptedException, ExecutionException, TimeoutException {
272 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
273 Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
274 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
275 return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
278 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
279 value = "UPM_UNCALLED_PRIVATE_METHOD",
280 justification = "call in call() method")
281 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
282 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
283 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
284 .service.path.PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
285 .child(ServicePaths.class, new ServicePathsKey(serviceName))
286 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
287 .service.path.PathDescription.class);
288 ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
290 LOG.debug("Getting path description for service {}", serviceName);
291 return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
292 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
293 } catch (InterruptedException | ExecutionException | TimeoutException e) {
294 LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
296 return Optional.empty();
300 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
301 value = "UPM_UNCALLED_PRIVATE_METHOD",
302 justification = "call in call() method")
303 private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
304 ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
305 LOG.info(RENDERING_DEVICES_A_Z_MSG);
306 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
307 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
308 RENDERING_DEVICES_A_Z_MSG);
309 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
310 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
311 ServicePathDirection.A_TO_Z));
313 LOG.info("Rendering devices Z-A");
314 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
315 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
316 RENDERING_DEVICES_Z_A_MSG);
317 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
318 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
319 ServicePathDirection.Z_TO_A));
320 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
321 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
323 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
325 LOG.info("Waiting for A-Z and Z-A device renderers ...");
326 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
327 } catch (InterruptedException | ExecutionException | TimeoutException e) {
328 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
329 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
330 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
331 DEVICE_RENDERING_ROLL_BACK_MSG);
332 //FIXME we can't do rollback here, because we don't have rendering results.
333 return renderingResults;
336 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
337 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
338 this.deviceRenderer));
339 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
340 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
341 this.deviceRenderer));
342 return renderingResults;
345 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
346 value = "UPM_UNCALLED_PRIVATE_METHOD",
347 justification = "call in call() method")
348 private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
349 OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA) {
350 LOG.info(RENDERING_DEVICES_A_Z_MSG);
351 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
352 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
353 RENDERING_DEVICES_A_Z_MSG);
354 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
355 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ));
356 LOG.info(RENDERING_DEVICES_Z_A_MSG);
357 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
358 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
359 RENDERING_DEVICES_Z_A_MSG);
360 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
361 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA));
362 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
363 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
364 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
366 LOG.info("Waiting for A-Z and Z-A device renderers ...");
367 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
368 } catch (InterruptedException | ExecutionException | TimeoutException e) {
369 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
370 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
371 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
372 DEVICE_RENDERING_ROLL_BACK_MSG);
373 //FIXME we can't do rollback here, because we don't have rendering results.
374 return otnRenderingResults;
376 for (int i = 0; i < otnRenderingResults.size(); i++) {
377 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("DeviceTask n° " + i + 1,
378 ! otnRenderingResults.get(i).isSuccess(), otnRenderingResults.get(i).getRenderedNodeInterfaces(),
379 this.deviceRenderer));
381 return otnRenderingResults;
384 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
385 value = "UPM_UNCALLED_PRIVATE_METHOD",
386 justification = "call in call() method")
387 private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
388 ServicePowerSetupInput powerSetupInputZtoA) {
389 LOG.info("Olm power setup A-Z");
390 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
391 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
392 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
393 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
395 LOG.info("OLM power setup Z-A");
396 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
397 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
398 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
399 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
400 ListenableFuture<List<OLMRenderingResult>> olmFutures =
401 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
403 List<OLMRenderingResult> olmResults;
405 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
406 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
407 } catch (InterruptedException | ExecutionException | TimeoutException e) {
408 LOG.warn(OLM_ROLL_BACK_MSG, e);
409 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
410 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
412 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
413 this.olmService, powerSetupInputAtoZ));
414 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
415 this.olmService, powerSetupInputZtoA));
419 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
420 this.olmService, powerSetupInputAtoZ));
421 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
422 this.olmService, powerSetupInputZtoA));
425 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
426 value = "UPM_UNCALLED_PRIVATE_METHOD",
427 justification = "call in call() method")
428 private boolean isServiceActivated(String nodeId, String tpId) {
429 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
430 for (int i = 0; i < 3; i++) {
431 List<Measurements> measurements = getMeasurements(nodeId, tpId);
432 if (measurements == null) {
433 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
436 if (verifyPreFecBer(measurements)) {
440 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
441 } catch (InterruptedException ex) {
442 Thread.currentThread().interrupt();
445 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
449 private List<Measurements> getMeasurements(String nodeId, String tp) {
450 GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder()
452 .setGranularity(PmGranularity._15min)
453 .setResourceIdentifier(new ResourceIdentifierBuilder().setResourceName(tp + "-OTU").build())
454 .setResourceType(ResourceTypeEnum.Interface);
457 Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
458 RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
459 GetPmOutput getPmOutput = getPmRpcResult.getResult();
460 if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
461 LOG.info("successfully finished calling OLM's get PM");
462 return getPmOutput.getMeasurements();
465 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
468 } catch (ExecutionException | InterruptedException e) {
469 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
474 private boolean verifyPreFecBer(List<Measurements> measurements) {
475 double preFecCorrectedErrors = Double.MIN_VALUE;
476 double fecUncorrectableBlocks = Double.MIN_VALUE;
478 for (Measurements measurement : measurements) {
479 switch (measurement.getPmparameterName()) {
480 case "preFECCorrectedErrors":
481 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
483 case "FECUncorrectableBlocks":
484 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
491 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
492 fecUncorrectableBlocks);
494 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
495 LOG.error("Data has uncorrectable errors, BER test failed");
499 double numOfBitsPerSecond = 112000000000d;
500 double threshold = 0.00002d;
501 double result = preFecCorrectedErrors / numOfBitsPerSecond;
502 LOG.info("PreFEC value is {}", Double.toString(result));
503 return result <= threshold;
506 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
507 value = "UPM_UNCALLED_PRIVATE_METHOD",
508 justification = "call in call() method")
509 private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType) {
510 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
511 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create);
512 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
513 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create);
514 // Rollback should be same for all conditions, so creating a new one
515 RollbackProcessor rollbackProcessor = new RollbackProcessor();
516 List<DeviceRenderingResult> renderingResults =
517 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
518 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
519 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
520 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
523 ServicePowerSetupInput olmPowerSetupInputAtoZ =
524 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input);
525 ServicePowerSetupInput olmPowerSetupInputZtoA =
526 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input);
527 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
528 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
529 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
530 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
533 // run service activation test twice - once on source node and once on
535 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
536 if ((nodes == null) || (nodes.isEmpty())) {
540 Nodes sourceNode = nodes.get(0);
541 Nodes destNode = nodes.get(nodes.size() - 1);
542 String srcNetworkTp =
543 sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
544 ? sourceNode.getDestTp()
545 : sourceNode.getSrcTp();
546 String dstNetowrkTp =
547 destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
548 ? destNode.getDestTp()
549 : destNode.getSrcTp();
551 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
552 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
553 rollbackProcessor.rollbackAll();
554 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
555 input.getServiceName(), RpcStatusEx.Failed,
556 "Service activation test failed.");
559 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
560 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
561 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
563 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
564 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
565 notifLink, serviceType);
569 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
570 value = "UPM_UNCALLED_PRIVATE_METHOD",
571 justification = "call in call() method")
572 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType)
573 throws InterruptedException {
574 ServicePathInputData servicePathInputDataAtoZ =
575 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete);
576 ServicePathInputData servicePathInputDataZtoA =
577 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete);
578 // OLM turn down power
580 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
581 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
582 RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
583 ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
584 // TODO add some flag rather than string
585 if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
586 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
587 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
588 "Service power turndown failed on A-to-Z path for service");
591 LOG.debug("Turning down power on Z-to-A path");
592 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
593 "Turning down power on Z-to-A path");
594 ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
595 // TODO add some flag rather than string
596 if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
597 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
598 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
599 "Service power turndown failed on Z-to-A path for service");
602 } catch (InterruptedException | ExecutionException | TimeoutException e) {
603 LOG.error("Error while turning down power!", e);
606 // delete service path with renderer
607 LOG.info("Deleting service path via renderer");
608 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
609 "Deleting service path via renderer");
610 RollbackProcessor rollbackProcessor = new RollbackProcessor();
611 List<DeviceRenderingResult> renderingResults =
612 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
613 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
614 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
615 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
617 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
618 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, serviceType);
622 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
623 value = "UPM_UNCALLED_PRIVATE_METHOD",
624 justification = "call in call() method")
625 private boolean manageOtnServicePathCreation(ServiceImplementationRequestInput input, String serviceType,
626 Uint32 serviceRate) {
628 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
629 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
630 input.getServiceAEnd().getServiceFormat().getName(),
632 input.getPathDescription(), true);
634 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
635 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
636 input.getServiceZEnd().getServiceFormat().getName(),
638 input.getPathDescription(), false);
639 // Rollback should be same for all conditions, so creating a new one
640 RollbackProcessor rollbackProcessor = new RollbackProcessor();
641 List<OtnDeviceRenderingResult> renderingResults =
642 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA);
643 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
644 rollbackProcessor.rollbackAll();
645 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
646 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
649 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
650 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
651 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
653 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
654 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
655 notifLink, serviceType);
659 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
660 value = "UPM_UNCALLED_PRIVATE_METHOD",
661 justification = "call in call() method")
662 private boolean manageOtnServicePathDeletion(String serviceName, PathDescription pathDescription,
663 Services service, String serviceType) {
665 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
666 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
667 service.getServiceAEnd().getServiceFormat().getName(),
668 service.getServiceAEnd().getServiceRate(),
669 pathDescription, true);
671 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
672 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
673 service.getServiceZEnd().getServiceFormat().getName(),
674 service.getServiceAEnd().getServiceRate(),
675 pathDescription, false);
676 LOG.info("Deleting otn-service path {} via renderer", serviceName);
677 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
678 "Deleting otn-service path via renderer");
680 RollbackProcessor rollbackProcessor = new RollbackProcessor();
681 List<OtnDeviceRenderingResult> renderingResults =
682 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA);
684 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
685 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
686 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
688 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
689 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, serviceType);
694 * Send renderer notification.
695 * @param servicePathNotificationTypes ServicePathNotificationTypes
696 * @param serviceName String
697 * @param rpcStatusEx RpcStatusEx
698 * @param message String
700 private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
701 RpcStatusEx rpcStatusEx, String message) {
702 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
708 * Send renderer notification with path description information.
709 * @param servicePathNotificationTypes ServicePathNotificationTypes
710 * @param serviceName String
711 * @param rpcStatusEx RpcStatusEx
712 * @param message String
713 * @param pathDescription PathDescription
715 private void sendNotificationsWithPathDescription(ServicePathNotificationTypes servicePathNotificationTypes,
716 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
717 Link notifLink, String serviceType) {
718 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
719 pathDescription, notifLink, serviceType);
724 * Build notification containing path description information.
725 * @param servicePathNotificationTypes ServicePathNotificationTypes
726 * @param serviceName String
727 * @param rpcStatusEx RpcStatusEx
728 * @param message String
729 * @param pathDescription PathDescription
730 * @return notification with RendererRpcResultSp type.
732 private RendererRpcResultSp buildNotification(ServicePathNotificationTypes servicePathNotificationTypes,
733 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
734 Link notifLink, String serviceType) {
735 RendererRpcResultSpBuilder builder = new RendererRpcResultSpBuilder()
736 .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx)
737 .setStatusMessage(message)
738 .setServiceType(serviceType);
739 if (pathDescription != null) {
740 builder.setAToZDirection(pathDescription.getAToZDirection())
741 .setZToADirection(pathDescription.getZToADirection());
743 if (notifLink != null) {
744 builder.setLink(notifLink);
746 return builder.build();
750 * Send renderer notification.
751 * @param notification Notification
753 private void send(Notification notification) {
755 LOG.info("Sending notification {}", notification);
756 notificationPublishService.putNotification(notification);
757 } catch (InterruptedException e) {
758 LOG.info("notification offer rejected: ", e);
759 Thread.currentThread().interrupt();
763 private Link createLinkForNotif(List<LinkTp> otnLinkTerminationPoints) {
764 if (otnLinkTerminationPoints == null || otnLinkTerminationPoints.size() != 2) {
767 return new LinkBuilder()
768 .setATermination(new ATerminationBuilder()
769 .setNodeId(otnLinkTerminationPoints.get(0).getNodeId())
770 .setTpId(otnLinkTerminationPoints.get(0).getTpId())
772 .setZTermination(new ZTerminationBuilder()
773 .setNodeId(otnLinkTerminationPoints.get(1).getNodeId())
774 .setTpId(otnLinkTerminationPoints.get(1).getTpId())