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 java.util.stream.Collectors;
25 import org.opendaylight.mdsal.binding.api.DataBroker;
26 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
27 import org.opendaylight.mdsal.binding.api.ReadTransaction;
28 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
29 import org.opendaylight.transportpce.common.ResponseCodes;
30 import org.opendaylight.transportpce.common.StringConstants;
31 import org.opendaylight.transportpce.common.Timeouts;
32 import org.opendaylight.transportpce.common.mapping.PortMapping;
33 import org.opendaylight.transportpce.common.service.ServiceTypes;
34 import org.opendaylight.transportpce.renderer.ModelMappingUtils;
35 import org.opendaylight.transportpce.renderer.ServicePathInputData;
36 import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection;
37 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingRollbackTask;
38 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingTask;
39 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupRollbackTask;
40 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupTask;
41 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OtnDeviceRenderingTask;
42 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.Action;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathInput;
45 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmInputBuilder;
46 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.GetPmOutput;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerSetupInput;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownInputBuilder;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownOutput;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.TransportpceOlmService;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.get.pm.output.Measurements;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mapping.Mapping;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.RendererRpcResultSp;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.RendererRpcResultSpBuilder;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteInput;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceDeleteOutput;
57 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestInput;
58 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.ServiceImplementationRequestOutput;
59 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ATerminationBuilder;
60 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.link._for.notif.ZTerminationBuilder;
61 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.Link;
62 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.LinkBuilder;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
66 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat;
67 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.PathDescription;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx;
70 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.ServicePathNotificationTypes;
71 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
72 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
73 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
74 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.link.tp.LinkTp;
75 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.olm.get.pm.input.ResourceIdentifierBuilder;
76 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.optical.renderer.nodes.Nodes;
77 import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev210511.OtnLinkType;
78 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
79 import org.opendaylight.yangtools.yang.binding.Notification;
80 import org.opendaylight.yangtools.yang.common.RpcResult;
81 import org.opendaylight.yangtools.yang.common.Uint32;
82 import org.slf4j.Logger;
83 import org.slf4j.LoggerFactory;
86 public class RendererServiceOperationsImpl implements RendererServiceOperations {
88 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
89 "Device rendering was not successful! Rendering will be rolled back.";
90 private static final String OLM_ROLL_BACK_MSG =
91 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
92 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
93 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
94 private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path";
95 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
96 private static final String FAILED = "Failed";
97 private static final String OPERATION_FAILED = "Operation Failed";
98 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
99 private static final int NUMBER_OF_THREADS = 4;
101 private final DeviceRendererService deviceRenderer;
102 private final OtnDeviceRendererService otnDeviceRenderer;
103 private final TransportpceOlmService olmService;
104 private final DataBroker dataBroker;
105 private final NotificationPublishService notificationPublishService;
106 private final PortMapping portMapping;
107 private ListeningExecutorService executor;
109 public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer,
110 OtnDeviceRendererService otnDeviceRenderer, TransportpceOlmService olmService,
111 DataBroker dataBroker, NotificationPublishService notificationPublishService, PortMapping portMapping) {
112 this.deviceRenderer = deviceRenderer;
113 this.otnDeviceRenderer = otnDeviceRenderer;
114 this.olmService = olmService;
115 this.dataBroker = dataBroker;
116 this.notificationPublishService = notificationPublishService;
117 this.portMapping = portMapping;
118 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
122 public ListenableFuture<ServiceImplementationRequestOutput>
123 serviceImplementation(ServiceImplementationRequestInput input) {
124 LOG.info("Calling service impl request {}", input.getServiceName());
125 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
128 public ServiceImplementationRequestOutput call() throws Exception {
129 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(),
130 RpcStatusEx.Pending, "Service compliant, submitting service implementation Request ...");
131 Uint32 serviceRate = getServiceRate(input);
132 org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.network.Nodes
133 mappingNode = portMapping.isNodeExist(input.getServiceAEnd().getNodeId())
134 ? portMapping.getNode(input.getServiceAEnd().getNodeId())
136 String serviceType = ServiceTypes.getServiceType(
137 input.getServiceAEnd().getServiceFormat().getName(),
140 && NodeTypes.Xpdr.equals(mappingNode.getNodeInfo().getNodeType())
141 && input.getServiceAEnd().getTxDirection() != null
142 && input.getServiceAEnd().getTxDirection().getPort() != null
143 && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null)
144 ? portMapping.getMapping(input.getServiceAEnd().getNodeId(),
145 input.getServiceAEnd().getTxDirection().getPort().getPortName())
148 switch (serviceType) {
149 case StringConstants.SERVICE_TYPE_100GE_T:
150 case StringConstants.SERVICE_TYPE_400GE:
151 case StringConstants.SERVICE_TYPE_OTU4:
152 case StringConstants.SERVICE_TYPE_OTUC4:
153 if (!manageServicePathCreation(input, serviceType)) {
154 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
158 case StringConstants.SERVICE_TYPE_1GE:
159 case StringConstants.SERVICE_TYPE_10GE:
160 case StringConstants.SERVICE_TYPE_100GE_M:
161 case StringConstants.SERVICE_TYPE_100GE_S:
162 case StringConstants.SERVICE_TYPE_ODU4:
163 case StringConstants.SERVICE_TYPE_ODUC4:
164 if (!manageOtnServicePathCreation(input, serviceType, serviceRate)) {
165 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
170 LOG.error("unsupported service-type");
171 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
174 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
175 OPERATION_SUCCESSFUL);
181 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
182 String serviceName = input.getServiceName();
183 LOG.info("Calling service delete request {}", serviceName);
184 return executor.submit(new Callable<ServiceDeleteOutput>() {
187 public ServiceDeleteOutput call() throws Exception {
188 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
189 RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
190 // Obtain path description
192 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service
193 .path.PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
194 if (pathDescriptionOpt.isEmpty()) {
195 LOG.error("Unable to get path description for service {}!", serviceName);
196 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
197 RpcStatusEx.Failed, "Unable to get path description for service");
198 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
201 PathDescription pathDescription = pathDescriptionOpt.get();
202 Mapping mapping = portMapping.getMapping(service.getServiceAEnd().getNodeId().getValue(),
203 service.getServiceAEnd().getTxDirection().getPort().getPortName());
204 String serviceType = ServiceTypes.getServiceType(service.getServiceAEnd().getServiceFormat().getName(),
205 service.getServiceAEnd().getServiceRate(), mapping);
206 switch (serviceType) {
207 case StringConstants.SERVICE_TYPE_100GE_T:
208 case StringConstants.SERVICE_TYPE_400GE:
209 case StringConstants.SERVICE_TYPE_OTU4:
210 case StringConstants.SERVICE_TYPE_OTUC4:
211 if (!manageServicePathDeletion(serviceName, pathDescription, serviceType)) {
212 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
216 case StringConstants.SERVICE_TYPE_1GE:
217 case StringConstants.SERVICE_TYPE_10GE:
218 case StringConstants.SERVICE_TYPE_100GE_M:
219 case StringConstants.SERVICE_TYPE_100GE_S:
220 case StringConstants.SERVICE_TYPE_ODU4:
221 case StringConstants.SERVICE_TYPE_ODUC4:
222 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service, serviceType)) {
223 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
228 LOG.error("unsupported service-type");
229 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
232 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
237 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
238 value = "UPM_UNCALLED_PRIVATE_METHOD",
239 justification = "call in call() method")
240 private Uint32 getServiceRate(ServiceImplementationRequestInput input) {
241 if (input.getServiceAEnd() == null) {
242 LOG.warn("Unable to get service-rate for service {}", input.getServiceName());
245 if (input.getServiceAEnd().getServiceRate() != null) {
246 return input.getServiceAEnd().getServiceRate();
248 Map<ServiceFormat, Map<String, Uint32>> formatRateMap = Map.of(
249 ServiceFormat.OTU, Map.of(
250 "OTUCn", Uint32.valueOf(400),
251 "OTU4", Uint32.valueOf(100),
252 "OTU2", Uint32.valueOf(10),
253 "OTU2e", Uint32.valueOf(10)),
254 ServiceFormat.ODU, Map.of(
255 "ODUCn",Uint32.valueOf(400),
256 "ODU4", Uint32.valueOf(100),
257 "ODU2", Uint32.valueOf(10),
258 "ODU2e", Uint32.valueOf(10),
259 "ODU0", Uint32.valueOf(1)));
260 if (!formatRateMap.containsKey(input.getServiceAEnd().getServiceFormat())) {
261 LOG.warn("Unable to get service-rate for service {} - unsupported service format {}",
262 input.getServiceName(), input.getServiceAEnd().getServiceFormat());
266 ServiceFormat.OTU.equals(input.getServiceAEnd().getServiceFormat())
267 ? input.getServiceAEnd().getOtuServiceRate().getSimpleName()
268 : input.getServiceAEnd().getOduServiceRate().getSimpleName();
269 if (!formatRateMap.get(input.getServiceAEnd().getServiceFormat()).containsKey(serviceName)) {
270 LOG.warn("Unable to get service-rate for service {} - unsupported service name {}",
271 input.getServiceName(), serviceName);
274 return formatRateMap.get(input.getServiceAEnd().getServiceFormat()).get(serviceName);
277 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
278 value = "UPM_UNCALLED_PRIVATE_METHOD",
279 justification = "call in call() method")
280 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
281 throws InterruptedException, ExecutionException, TimeoutException {
282 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
283 Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
284 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
285 return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
288 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
289 value = "UPM_UNCALLED_PRIVATE_METHOD",
290 justification = "call in call() method")
291 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
292 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
293 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
294 .service.path.PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
295 .child(ServicePaths.class, new ServicePathsKey(serviceName))
296 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
297 .service.path.PathDescription.class);
298 ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
300 LOG.debug("Getting path description for service {}", serviceName);
301 return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
302 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
303 } catch (InterruptedException | ExecutionException | TimeoutException e) {
304 LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
306 return Optional.empty();
310 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
311 value = "UPM_UNCALLED_PRIVATE_METHOD",
312 justification = "call in call() method")
313 private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
314 ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
315 LOG.info(RENDERING_DEVICES_A_Z_MSG);
316 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
317 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
318 RENDERING_DEVICES_A_Z_MSG);
319 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
320 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
321 ServicePathDirection.A_TO_Z));
323 LOG.info("Rendering devices Z-A");
324 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
325 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
326 RENDERING_DEVICES_Z_A_MSG);
327 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
328 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
329 ServicePathDirection.Z_TO_A));
330 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
331 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
333 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
335 LOG.info("Waiting for A-Z and Z-A device renderers ...");
336 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
337 } catch (InterruptedException | ExecutionException | TimeoutException e) {
338 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
339 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
340 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
341 DEVICE_RENDERING_ROLL_BACK_MSG);
342 //FIXME we can't do rollback here, because we don't have rendering results.
343 return renderingResults;
346 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
347 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
348 this.deviceRenderer));
349 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
350 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
351 this.deviceRenderer));
352 return renderingResults;
355 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
356 value = "UPM_UNCALLED_PRIVATE_METHOD",
357 justification = "call in call() method")
358 private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
359 OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA, String serviceType) {
360 LOG.info(RENDERING_DEVICES_A_Z_MSG);
361 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
362 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
363 RENDERING_DEVICES_A_Z_MSG);
364 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
365 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ, serviceType));
366 LOG.info(RENDERING_DEVICES_Z_A_MSG);
367 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
368 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
369 RENDERING_DEVICES_Z_A_MSG);
370 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
371 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA, serviceType));
372 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
373 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
374 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
376 LOG.info("Waiting for A-Z and Z-A device renderers ...");
377 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
378 } catch (InterruptedException | ExecutionException | TimeoutException e) {
379 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
380 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
381 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
382 DEVICE_RENDERING_ROLL_BACK_MSG);
383 //FIXME we can't do rollback here, because we don't have rendering results.
384 return otnRenderingResults;
386 for (int i = 0; i < otnRenderingResults.size(); i++) {
387 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("DeviceTask n° " + i + 1,
388 ! otnRenderingResults.get(i).isSuccess(), otnRenderingResults.get(i).getRenderedNodeInterfaces(),
389 this.deviceRenderer));
391 return otnRenderingResults;
394 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
395 value = "UPM_UNCALLED_PRIVATE_METHOD",
396 justification = "call in call() method")
397 private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
398 ServicePowerSetupInput powerSetupInputZtoA) {
399 LOG.info("Olm power setup A-Z");
400 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
401 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
402 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
403 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
405 LOG.info("OLM power setup Z-A");
406 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
407 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
408 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
409 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
410 ListenableFuture<List<OLMRenderingResult>> olmFutures =
411 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
413 List<OLMRenderingResult> olmResults;
415 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
416 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
417 } catch (InterruptedException | ExecutionException | TimeoutException e) {
418 LOG.warn(OLM_ROLL_BACK_MSG, e);
419 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
420 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
422 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
423 this.olmService, powerSetupInputAtoZ));
424 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
425 this.olmService, powerSetupInputZtoA));
429 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
430 this.olmService, powerSetupInputAtoZ));
431 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
432 this.olmService, powerSetupInputZtoA));
435 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
436 value = "UPM_UNCALLED_PRIVATE_METHOD",
437 justification = "call in call() method")
438 private boolean isServiceActivated(String nodeId, String tpId) {
439 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
440 for (int i = 0; i < 3; i++) {
441 List<Measurements> measurements = getMeasurements(nodeId, tpId);
442 if (measurements == null) {
443 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
446 if (verifyPreFecBer(measurements)) {
450 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
451 } catch (InterruptedException ex) {
452 Thread.currentThread().interrupt();
455 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
459 private List<Measurements> getMeasurements(String nodeId, String tp) {
460 GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder()
462 .setGranularity(PmGranularity._15min)
463 .setResourceIdentifier(new ResourceIdentifierBuilder().setResourceName(tp + "-OTU").build())
464 .setResourceType(ResourceTypeEnum.Interface);
467 Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
468 RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
469 GetPmOutput getPmOutput = getPmRpcResult.getResult();
470 if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
471 LOG.info("successfully finished calling OLM's get PM");
472 return getPmOutput.getMeasurements();
475 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
478 } catch (ExecutionException | InterruptedException e) {
479 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
484 private boolean verifyPreFecBer(List<Measurements> measurements) {
485 double preFecCorrectedErrors = Double.MIN_VALUE;
486 double fecUncorrectableBlocks = Double.MIN_VALUE;
488 for (Measurements measurement : measurements) {
489 switch (measurement.getPmparameterName()) {
490 case "preFECCorrectedErrors":
491 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
493 case "FECUncorrectableBlocks":
494 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
501 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
502 fecUncorrectableBlocks);
504 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
505 LOG.error("Data has uncorrectable errors, BER test failed");
509 double numOfBitsPerSecond = 112000000000d;
510 double threshold = 0.00002d;
511 double result = preFecCorrectedErrors / numOfBitsPerSecond;
512 LOG.info("PreFEC value is {}", Double.toString(result));
513 return result <= threshold;
516 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
517 value = "UPM_UNCALLED_PRIVATE_METHOD",
518 justification = "call in call() method")
519 private boolean manageServicePathCreation(ServiceImplementationRequestInput input, String serviceType) {
520 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
521 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription(), Action.Create);
522 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
523 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription(), Action.Create);
524 // Rollback should be same for all conditions, so creating a new one
525 RollbackProcessor rollbackProcessor = new RollbackProcessor();
526 List<DeviceRenderingResult> renderingResults =
527 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
528 if (rollbackProcessor.rollbackAllIfNecessary() > 0 || renderingResults.isEmpty()) {
529 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
530 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
533 ServicePowerSetupInput olmPowerSetupInputAtoZ =
534 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input);
535 ServicePowerSetupInput olmPowerSetupInputZtoA =
536 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input);
537 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
538 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
539 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
540 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
543 // run service activation test twice - once on source node and once on
545 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
546 if ((nodes == null) || (nodes.isEmpty())) {
550 Nodes sourceNode = nodes.get(0);
551 Nodes destNode = nodes.get(nodes.size() - 1);
552 String srcNetworkTp =
553 sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
554 ? sourceNode.getDestTp()
555 : sourceNode.getSrcTp();
556 String dstNetowrkTp =
557 destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)
558 ? destNode.getDestTp()
559 : destNode.getSrcTp();
561 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
562 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
563 rollbackProcessor.rollbackAll();
564 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
565 input.getServiceName(), RpcStatusEx.Failed,
566 "Service activation test failed.");
569 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
570 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
571 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
573 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
574 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
575 notifLink, null, serviceType);
579 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
580 value = "UPM_UNCALLED_PRIVATE_METHOD",
581 justification = "call in call() method")
582 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription, String serviceType)
583 throws InterruptedException {
584 ServicePathInputData servicePathInputDataAtoZ =
585 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription, Action.Delete);
586 ServicePathInputData servicePathInputDataZtoA =
587 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription, Action.Delete);
588 // OLM turn down power
590 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
591 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
592 RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
593 ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
594 // TODO add some flag rather than string
595 if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
596 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
597 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
598 "Service power turndown failed on A-to-Z path for service");
601 LOG.debug("Turning down power on Z-to-A path");
602 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
603 "Turning down power on Z-to-A path");
604 ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
605 // TODO add some flag rather than string
606 if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
607 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
608 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
609 "Service power turndown failed on Z-to-A path for service");
612 } catch (InterruptedException | ExecutionException | TimeoutException e) {
613 LOG.error("Error while turning down power!", e);
616 // delete service path with renderer
617 LOG.info("Deleting service path via renderer");
618 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
619 "Deleting service path via renderer");
620 RollbackProcessor rollbackProcessor = new RollbackProcessor();
621 List<DeviceRenderingResult> renderingResults =
622 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
623 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
624 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
625 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
627 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
628 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, null, serviceType);
632 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
633 value = "UPM_UNCALLED_PRIVATE_METHOD",
634 justification = "call in call() method")
635 private boolean manageOtnServicePathCreation(ServiceImplementationRequestInput input, String serviceType,
636 Uint32 serviceRate) {
638 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
639 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
640 input.getServiceAEnd().getServiceFormat().getName(),
642 input.getPathDescription(), true);
644 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
645 .rendererCreateOtnServiceInput(input.getServiceName(), Action.Create,
646 input.getServiceZEnd().getServiceFormat().getName(),
648 input.getPathDescription(), false);
649 // Rollback should be same for all conditions, so creating a new one
650 RollbackProcessor rollbackProcessor = new RollbackProcessor();
651 List<OtnDeviceRenderingResult> renderingResults =
652 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA, serviceType);
653 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
654 rollbackProcessor.rollbackAll();
655 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
656 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
659 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
660 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
661 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
662 List<String> allSupportLinks = ModelMappingUtils.getLinksFromServicePathDescription(input.getPathDescription());
663 List<String> supportedLinks = getSupportedLinks(allSupportLinks, serviceType);
665 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceImplementationRequest,
666 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL, input.getPathDescription(),
667 notifLink, supportedLinks, serviceType);
671 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
672 value = "UPM_UNCALLED_PRIVATE_METHOD",
673 justification = "call in call() method")
674 private boolean manageOtnServicePathDeletion(String serviceName, PathDescription pathDescription,
675 Services service, String serviceType) {
677 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
678 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
679 service.getServiceAEnd().getServiceFormat().getName(),
680 service.getServiceAEnd().getServiceRate(),
681 pathDescription, true);
683 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
684 .rendererCreateOtnServiceInput(serviceName, Action.Delete,
685 service.getServiceZEnd().getServiceFormat().getName(),
686 service.getServiceAEnd().getServiceRate(),
687 pathDescription, false);
688 LOG.info("Deleting otn-service path {} via renderer", serviceName);
689 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
690 "Deleting otn-service path via renderer");
692 RollbackProcessor rollbackProcessor = new RollbackProcessor();
693 List<OtnDeviceRenderingResult> renderingResults =
694 otnDeviceRendering(rollbackProcessor, otnServicePathInputAtoZ, otnServicePathInputZtoA, serviceType);
696 List<LinkTp> otnLinkTerminationPoints = new ArrayList<>();
697 renderingResults.forEach(rr -> otnLinkTerminationPoints.addAll(rr.getOtnLinkTps()));
698 Link notifLink = createLinkForNotif(otnLinkTerminationPoints);
699 List<String> allSupportLinks = ModelMappingUtils.getLinksFromServicePathDescription(pathDescription);
700 List<String> supportedLinks = getSupportedLinks(allSupportLinks, serviceType);
702 sendNotificationsWithPathDescription(ServicePathNotificationTypes.ServiceDelete,
703 serviceName, RpcStatusEx.Successful, OPERATION_SUCCESSFUL, pathDescription, notifLink, supportedLinks,
709 * Send renderer notification.
710 * @param servicePathNotificationTypes ServicePathNotificationTypes
711 * @param serviceName String
712 * @param rpcStatusEx RpcStatusEx
713 * @param message String
715 private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
716 RpcStatusEx rpcStatusEx, String message) {
717 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
718 null, null, null, null);
723 * Send renderer notification with path description information.
724 * @param servicePathNotificationTypes ServicePathNotificationTypes
725 * @param serviceName String
726 * @param rpcStatusEx RpcStatusEx
727 * @param message String
728 * @param pathDescription PathDescription
730 private void sendNotificationsWithPathDescription(ServicePathNotificationTypes servicePathNotificationTypes,
731 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
732 Link notifLink, List<String> supportedLinks, String serviceType) {
733 Notification notification = buildNotification(servicePathNotificationTypes, serviceName, rpcStatusEx, message,
734 pathDescription, notifLink, supportedLinks, serviceType);
739 * Build notification containing path description information.
740 * @param servicePathNotificationTypes ServicePathNotificationTypes
741 * @param serviceName String
742 * @param rpcStatusEx RpcStatusEx
743 * @param message String
744 * @param pathDescription PathDescription
745 * @return notification with RendererRpcResultSp type.
747 private RendererRpcResultSp buildNotification(ServicePathNotificationTypes servicePathNotificationTypes,
748 String serviceName, RpcStatusEx rpcStatusEx, String message, PathDescription pathDescription,
749 Link notifLink, List<String> supportedLinks, String serviceType) {
750 RendererRpcResultSpBuilder builder = new RendererRpcResultSpBuilder()
751 .setNotificationType(servicePathNotificationTypes).setServiceName(serviceName).setStatus(rpcStatusEx)
752 .setStatusMessage(message)
753 .setServiceType(serviceType);
754 if (pathDescription != null) {
755 builder.setAToZDirection(pathDescription.getAToZDirection())
756 .setZToADirection(pathDescription.getZToADirection());
758 if (notifLink != null) {
759 builder.setLink(notifLink);
761 if (supportedLinks != null) {
762 builder.setLinkId(supportedLinks);
764 return builder.build();
768 * Send renderer notification.
769 * @param notification Notification
771 private void send(Notification notification) {
773 LOG.info("Sending notification {}", notification);
774 notificationPublishService.putNotification(notification);
775 } catch (InterruptedException e) {
776 LOG.info("notification offer rejected: ", e);
777 Thread.currentThread().interrupt();
781 private Link createLinkForNotif(List<LinkTp> otnLinkTerminationPoints) {
782 if (otnLinkTerminationPoints == null || otnLinkTerminationPoints.size() != 2) {
785 return new LinkBuilder()
786 .setATermination(new ATerminationBuilder()
787 .setNodeId(otnLinkTerminationPoints.get(0).getNodeId())
788 .setTpId(otnLinkTerminationPoints.get(0).getTpId())
790 .setZTermination(new ZTerminationBuilder()
791 .setNodeId(otnLinkTerminationPoints.get(1).getNodeId())
792 .setTpId(otnLinkTerminationPoints.get(1).getTpId())
797 private List<String> getSupportedLinks(List<String> allSupportLinks, String serviceType) {
798 switch (serviceType) {
799 case StringConstants.SERVICE_TYPE_10GE:
800 case StringConstants.SERVICE_TYPE_1GE:
801 return allSupportLinks.stream()
802 .filter(lk -> lk.startsWith(OtnLinkType.ODTU4.getName())).collect(Collectors.toList());
803 case StringConstants.SERVICE_TYPE_100GE_M:
804 return allSupportLinks.stream()
805 .filter(lk -> lk.startsWith(OtnLinkType.ODUC4.getName())).collect(Collectors.toList());
806 case StringConstants.SERVICE_TYPE_ODU4:
807 case StringConstants.SERVICE_TYPE_100GE_S:
808 return allSupportLinks.stream()
809 .filter(lk -> lk.startsWith(OtnLinkType.OTU4.getName())).collect(Collectors.toList());
810 case StringConstants.SERVICE_TYPE_ODUC4:
811 return allSupportLinks.stream()
812 .filter(lk -> lk.startsWith(OtnLinkType.OTUC4.getName())).collect(Collectors.toList());