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(), null);
196 switch (serviceType) {
197 case StringConstants.SERVICE_TYPE_100GE_T:
198 case StringConstants.SERVICE_TYPE_400GE:
199 case StringConstants.SERVICE_TYPE_OTU4:
200 case StringConstants.SERVICE_TYPE_OTUC4:
201 if (!manageServicePathDeletion(serviceName, pathDescription, serviceType)) {
202 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
206 case StringConstants.SERVICE_TYPE_1GE:
207 case StringConstants.SERVICE_TYPE_10GE:
208 case StringConstants.SERVICE_TYPE_100GE_M:
209 case StringConstants.SERVICE_TYPE_ODU4:
210 case StringConstants.SERVICE_TYPE_ODUC4:
211 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service, serviceType)) {
212 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
217 LOG.error("unsupported service-type");
218 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
221 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
226 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
227 value = "UPM_UNCALLED_PRIVATE_METHOD",
228 justification = "call in call() method")
229 private Uint32 getServiceRate(ServiceImplementationRequestInput input) {
230 if (input.getServiceAEnd() == null) {
231 LOG.warn("Unable to get service-rate for service {}", input.getServiceName());
234 if (input.getServiceAEnd().getServiceRate() != null) {
235 return input.getServiceAEnd().getServiceRate();
237 Map<ServiceFormat, Map<String, Uint32>> formatRateMap = Map.of(
238 ServiceFormat.OTU, Map.of(
239 "OTUCn", Uint32.valueOf(400),
240 "OTU4", Uint32.valueOf(100),
241 "OTU2", Uint32.valueOf(10),
242 "OTU2e", Uint32.valueOf(10)),
243 ServiceFormat.ODU, Map.of(
244 "ODUCn",Uint32.valueOf(400),
245 "ODU4", Uint32.valueOf(100),
246 "ODU2", Uint32.valueOf(10),
247 "ODU2e", Uint32.valueOf(10),
248 "ODU0", Uint32.valueOf(1)));
249 if (!formatRateMap.containsKey(input.getServiceAEnd().getServiceFormat())) {
250 LOG.warn("Unable to get service-rate for service {} - unsupported service format {}",
251 input.getServiceName(), input.getServiceAEnd().getServiceFormat());
255 ServiceFormat.OTU.equals(input.getServiceAEnd().getServiceFormat())
256 ? input.getServiceAEnd().getOtuServiceRate().getSimpleName()
257 : input.getServiceAEnd().getOduServiceRate().getSimpleName();
258 if (!formatRateMap.get(input.getServiceAEnd().getServiceFormat()).containsKey(serviceName)) {
259 LOG.warn("Unable to get service-rate for service {} - unsupported service name {}",
260 input.getServiceName(), serviceName);
263 return formatRateMap.get(input.getServiceAEnd().getServiceFormat()).get(serviceName);
266 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
267 value = "UPM_UNCALLED_PRIVATE_METHOD",
268 justification = "call in call() method")
269 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
270 throws InterruptedException, ExecutionException, TimeoutException {
271 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
272 Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
273 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
274 return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
277 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
278 value = "UPM_UNCALLED_PRIVATE_METHOD",
279 justification = "call in call() method")
280 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
281 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
282 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
283 .service.path.PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
284 .child(ServicePaths.class, new ServicePathsKey(serviceName))
285 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
286 .service.path.PathDescription.class);
287 ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
289 LOG.debug("Getting path description for service {}", serviceName);
290 return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
291 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
292 } catch (InterruptedException | ExecutionException | TimeoutException e) {
293 LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
295 return Optional.empty();
299 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
300 value = "UPM_UNCALLED_PRIVATE_METHOD",
301 justification = "call in call() method")
302 private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
303 ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
304 LOG.info(RENDERING_DEVICES_A_Z_MSG);
305 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
306 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
307 RENDERING_DEVICES_A_Z_MSG);
308 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
309 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
310 ServicePathDirection.A_TO_Z));
312 LOG.info("Rendering devices Z-A");
313 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
314 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
315 RENDERING_DEVICES_Z_A_MSG);
316 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
317 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
318 ServicePathDirection.Z_TO_A));
319 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
320 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
322 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
324 LOG.info("Waiting for A-Z and Z-A device renderers ...");
325 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
326 } catch (InterruptedException | ExecutionException | TimeoutException e) {
327 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
328 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
329 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
330 DEVICE_RENDERING_ROLL_BACK_MSG);
331 //FIXME we can't do rollback here, because we don't have rendering results.
332 return renderingResults;
335 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
336 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
337 this.deviceRenderer));
338 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
339 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
340 this.deviceRenderer));
341 return renderingResults;
344 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
345 value = "UPM_UNCALLED_PRIVATE_METHOD",
346 justification = "call in call() method")
347 private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
348 OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA) {
349 LOG.info(RENDERING_DEVICES_A_Z_MSG);
350 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
351 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
352 RENDERING_DEVICES_A_Z_MSG);
353 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
354 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ));
355 LOG.info("Rendering devices Z-A");
356 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
357 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
358 RENDERING_DEVICES_Z_A_MSG);
359 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
360 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA));
361 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
362 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
363 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
365 LOG.info("Waiting for A-Z and Z-A device renderers ...");
366 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
367 } catch (InterruptedException | ExecutionException | TimeoutException e) {
368 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
369 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
370 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
371 DEVICE_RENDERING_ROLL_BACK_MSG);
372 //FIXME we can't do rollback here, because we don't have rendering results.
373 return otnRenderingResults;
375 for (int i = 0; i < otnRenderingResults.size(); i++) {
376 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("DeviceTask n° " + i + 1,
377 ! otnRenderingResults.get(i).isSuccess(), otnRenderingResults.get(i).getRenderedNodeInterfaces(),
378 this.deviceRenderer));
380 return otnRenderingResults;
383 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
384 value = "UPM_UNCALLED_PRIVATE_METHOD",
385 justification = "call in call() method")
386 private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
387 ServicePowerSetupInput powerSetupInputZtoA) {
388 LOG.info("Olm power setup A-Z");
389 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
390 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
391 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
392 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
394 LOG.info("OLM power setup Z-A");
395 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
396 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
397 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
398 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
399 ListenableFuture<List<OLMRenderingResult>> olmFutures =
400 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
402 List<OLMRenderingResult> olmResults;
404 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
405 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
406 } catch (InterruptedException | ExecutionException | TimeoutException e) {
407 LOG.warn(OLM_ROLL_BACK_MSG, e);
408 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
409 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
411 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
412 this.olmService, powerSetupInputAtoZ));
413 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
414 this.olmService, powerSetupInputZtoA));
418 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
419 this.olmService, powerSetupInputAtoZ));
420 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
421 this.olmService, powerSetupInputZtoA));
424 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
425 value = "UPM_UNCALLED_PRIVATE_METHOD",
426 justification = "call in call() method")
427 private boolean isServiceActivated(String nodeId, String tpId) {
428 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
429 for (int i = 0; i < 3; i++) {
430 List<Measurements> measurements = getMeasurements(nodeId, tpId);
431 if (measurements == null) {
432 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
435 if (verifyPreFecBer(measurements)) {
439 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
440 } catch (InterruptedException ex) {
441 Thread.currentThread().interrupt();
444 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
448 private List<Measurements> getMeasurements(String nodeId, String tp) {
449 GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder()
451 .setGranularity(PmGranularity._15min)
452 .setResourceIdentifier(new ResourceIdentifierBuilder().setResourceName(tp + "-OTU").build())
453 .setResourceType(ResourceTypeEnum.Interface);
456 Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
457 RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
458 GetPmOutput getPmOutput = getPmRpcResult.getResult();
459 if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
460 LOG.info("successfully finished calling OLM's get PM");
461 return getPmOutput.getMeasurements();
464 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
467 } catch (ExecutionException | InterruptedException e) {
468 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
473 private boolean verifyPreFecBer(List<Measurements> measurements) {
474 double preFecCorrectedErrors = Double.MIN_VALUE;
475 double fecUncorrectableBlocks = Double.MIN_VALUE;
477 for (Measurements measurement : measurements) {
478 switch (measurement.getPmparameterName()) {
479 case "preFECCorrectedErrors":
480 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
482 case "FECUncorrectableBlocks":
483 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
490 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
491 fecUncorrectableBlocks);
493 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
494 LOG.error("Data has uncorrectable errors, BER test failed");
498 double numOfBitsPerSecond = 112000000000d;
499 double threshold = 0.00002d;
500 double result = preFecCorrectedErrors / numOfBitsPerSecond;
501 LOG.info("PreFEC value is {}", Double.toString(result));
502 return result <= threshold;
505 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
506 value = "UPM_UNCALLED_PRIVATE_METHOD",
507 justification = "call in call() method")
508 private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType) {
509 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
510 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create);
511 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
512 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create);
513 // Rollback should be same for all conditions, so creating a new one
514 RollbackProcessor rollbackProcessor = new RollbackProcessor();
515 List<DeviceRenderingResult> renderingResults =
516 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
517 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
518 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
519 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
522 ServicePowerSetupInput olmPowerSetupInputAtoZ =
523 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input);
524 ServicePowerSetupInput olmPowerSetupInputZtoA =
525 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input);
526 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
527 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
528 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
529 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
532 // run service activation test twice - once on source node and once on
534 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
535 if ((nodes == null) || (nodes.isEmpty())) {
539 Nodes sourceNode = nodes.get(0);
540 Nodes destNode = nodes.get(nodes.size() - 1);
541 String srcNetworkTp =
542 sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
543 ? sourceNode.getDestTp()
544 : sourceNode.getSrcTp();
545 String dstNetowrkTp =
546 destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
547 ? destNode.getDestTp()
548 : destNode.getSrcTp();
550 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
551 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
552 rollbackProcessor.rollbackAll();
553 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
554 input.getServiceName(), RpcStatusEx.Failed,
555 "Service activation test failed.");
558 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
559 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
560 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
562 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
563 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
564 notifLink, serviceType);
568 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
569 value = "UPM_UNCALLED_PRIVATE_METHOD",
570 justification = "call in call() method")
571 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType)
572 throws InterruptedException {
573 ServicePathInputData servicePathInputDataAtoZ =
574 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete);
575 ServicePathInputData servicePathInputDataZtoA =
576 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete);
577 // OLM turn down power
579 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
580 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
581 RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
582 ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
583 // TODO add some flag rather than string
584 if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
585 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
586 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
587 "Service power turndown failed on A-to-Z path for service");
590 LOG.debug("Turning down power on Z-to-A path");
591 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
592 "Turning down power on Z-to-A path");
593 ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
594 // TODO add some flag rather than string
595 if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
596 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
597 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
598 "Service power turndown failed on Z-to-A path for service");
601 } catch (InterruptedException | ExecutionException | TimeoutException e) {
602 LOG.error("Error while turning down power!", e);
605 // delete service path with renderer
606 LOG.info("Deleting service path via renderer");
607 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
608 "Deleting service path via renderer");
609 RollbackProcessor rollbackProcessor = new RollbackProcessor();
610 List<DeviceRenderingResult> renderingResults =
611 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
612 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
613 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
614 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
616 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
617 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, serviceType);
621 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
622 value = "UPM_UNCALLED_PRIVATE_METHOD",
623 justification = "call in call() method")
624 private boolean manageOtnServicePathCreation(ServiceImplementationRequestInput input, String serviceType,
625 Uint32 serviceRate) {
627 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
628 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
629 input.getServiceAEnd().getServiceFormat().getName(),
631 input.getPathDescription(), true);
633 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
634 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
635 input.getServiceZEnd().getServiceFormat().getName(),
637 input.getPathDescription(), false);
638 // Rollback should be same for all conditions, so creating a new one
639 RollbackProcessor rollbackProcessor = new RollbackProcessor();
640 List<OtnDeviceRenderingResult> renderingResults =
641 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA);
642 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
643 rollbackProcessor.rollbackAll();
644 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
645 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
648 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
649 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
650 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
652 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
653 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
654 notifLink, serviceType);
658 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
659 value = "UPM_UNCALLED_PRIVATE_METHOD",
660 justification = "call in call() method")
661 private boolean manageOtnServicePathDeletion(String serviceName, PathDescription pathDescription,
662 Services service, String serviceType) {
664 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
665 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
666 service.getServiceAEnd().getServiceFormat().getName(),
667 service.getServiceAEnd().getServiceRate(),
668 pathDescription, true);
670 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
671 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
672 service.getServiceZEnd().getServiceFormat().getName(),
673 service.getServiceAEnd().getServiceRate(),
674 pathDescription, false);
675 LOG.info("Deleting otn-service path {} via renderer", serviceName);
676 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
677 "Deleting otn-service path via renderer");
679 RollbackProcessor rollbackProcessor = new RollbackProcessor();
680 List<OtnDeviceRenderingResult> renderingResults =
681 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA);
683 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
684 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
685 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
687 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
688 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, serviceType);
693 * Send renderer notification.
694 * @param servicePathNotificationTypes ServicePathNotificationTypes
695 * @param serviceName String
696 * @param rpcStatusEx RpcStatusEx
697 * @param message String
699 private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
700 RpcStatusEx rpcStatusEx, String message) {
701 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
707 * Send renderer notification with path description information.
708 * @param servicePathNotificationTypes ServicePathNotificationTypes
709 * @param serviceName String
710 * @param rpcStatusEx RpcStatusEx
711 * @param message String
712 * @param pathDescription PathDescription
714 private void sendNotificationsWithPathDescription(ServicePathNotificationTypes servicePathNotificationTypes,
715 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
716 Link notifLink, String serviceType) {
717 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
718 pathDescription, notifLink, serviceType);
723 * Build notification containing path description information.
724 * @param servicePathNotificationTypes ServicePathNotificationTypes
725 * @param serviceName String
726 * @param rpcStatusEx RpcStatusEx
727 * @param message String
728 * @param pathDescription PathDescription
729 * @return notification with RendererRpcResultSp type.
731 private RendererRpcResultSp buildNotification(ServicePathNotificationTypes servicePathNotificationTypes,
732 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
733 Link notifLink, String serviceType) {
734 RendererRpcResultSpBuilder builder = new RendererRpcResultSpBuilder()
735 .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx)
736 .setStatusMessage(message)
737 .setServiceType(serviceType);
738 if (pathDescription != null) {
739 builder.setAToZDirection(pathDescription.getAToZDirection())
740 .setZToADirection(pathDescription.getZToADirection());
742 if (notifLink != null) {
743 builder.setLink(notifLink);
745 return builder.build();
749 * Send renderer notification.
750 * @param notification Notification
752 private void send(Notification notification) {
754 LOG.info("Sending notification {}", notification);
755 notificationPublishService.putNotification(notification);
756 } catch (InterruptedException e) {
757 LOG.info("notification offer rejected: ", e);
758 Thread.currentThread().interrupt();
762 private Link createLinkForNotif(List<LinkTp> otnLinkTerminationPoints) {
763 if (otnLinkTerminationPoints == null || otnLinkTerminationPoints.size() != 2) {
766 return new LinkBuilder()
767 .setATermination(new ATerminationBuilder()
768 .setNodeId(otnLinkTerminationPoints.get(0).getNodeId())
769 .setTpId(otnLinkTerminationPoints.get(0).getTpId())
771 .setZTermination(new ZTerminationBuilder()
772 .setNodeId(otnLinkTerminationPoints.get(1).getNodeId())
773 .setTpId(otnLinkTerminationPoints.get(1).getTpId())