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;
16 import java.util.Optional;
17 import java.util.concurrent.Callable;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.Executors;
20 import java.util.concurrent.Future;
21 import java.util.concurrent.TimeUnit;
22 import java.util.concurrent.TimeoutException;
23 import org.opendaylight.mdsal.binding.api.DataBroker;
24 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
25 import org.opendaylight.mdsal.binding.api.ReadTransaction;
26 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
27 import org.opendaylight.transportpce.common.OperationResult;
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.renderer.ModelMappingUtils;
32 import org.opendaylight.transportpce.renderer.NetworkModelWavelengthService;
33 import org.opendaylight.transportpce.renderer.ServicePathInputData;
34 import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection;
35 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingRollbackTask;
36 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingTask;
37 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupRollbackTask;
38 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupTask;
39 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OtnDeviceRenderingTask;
40 import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor;
41 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev200128.OtnServicePathInput;
42 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev200128.OtnServicePathOutput;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.GetPmInputBuilder;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.GetPmOutput;
45 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerSetupInput;
46 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerTurndownInputBuilder;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerTurndownOutput;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.TransportpceOlmService;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.get.pm.output.Measurements;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceDeleteInput;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceDeleteOutput;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceImplementationRequestInput;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceImplementationRequestOutput;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceRpcResultSp;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceRpcResultSpBuilder;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ConnectionType;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev181130.ODU4;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev181130.OTU4;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
63 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev200629.PathDescription;
64 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx;
65 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.ServicePathNotificationTypes;
66 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
67 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.olm.get.pm.input.ResourceIdentifierBuilder;
70 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.olm.renderer.input.Nodes;
71 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
72 import org.opendaylight.yangtools.yang.common.RpcResult;
73 import org.opendaylight.yangtools.yang.common.Uint32;
74 import org.slf4j.Logger;
75 import org.slf4j.LoggerFactory;
78 public class RendererServiceOperationsImpl implements RendererServiceOperations {
80 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
81 "Device rendering was not successful! Rendering will be rolled back.";
82 private static final String OLM_ROLL_BACK_MSG =
83 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
84 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
85 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
86 private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path";
87 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
88 private static final String FAILED = "Failed";
89 private static final String OPERATION_FAILED = "Operation Failed";
90 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
91 private static final int NUMBER_OF_THREADS = 4;
93 private final DeviceRendererService deviceRenderer;
94 private final OtnDeviceRendererService otnDeviceRenderer;
95 private final TransportpceOlmService olmService;
96 private final DataBroker dataBroker;
97 private final NotificationPublishService notificationPublishService;
98 private ListeningExecutorService executor;
99 private NetworkModelWavelengthService networkModelWavelengthService;
100 private ServiceRpcResultSp notification = null;
102 public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer,
103 OtnDeviceRendererService otnDeviceRenderer, TransportpceOlmService olmService,
104 DataBroker dataBroker, NetworkModelWavelengthService networkModelWavelengthService,
105 NotificationPublishService notificationPublishService) {
106 this.deviceRenderer = deviceRenderer;
107 this.otnDeviceRenderer = otnDeviceRenderer;
108 this.olmService = olmService;
109 this.dataBroker = dataBroker;
110 this.networkModelWavelengthService = networkModelWavelengthService;
111 this.notificationPublishService = notificationPublishService;
112 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
115 private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
116 RpcStatusEx rpcStatusEx, String message) {
117 this.notification = new ServiceRpcResultSpBuilder()
118 .setNotificationType(servicePathNotificationTypes)
119 .setServiceName(serviceName)
120 .setStatus(rpcStatusEx)
121 .setStatusMessage(message)
124 notificationPublishService.putNotification(this.notification);
125 } catch (InterruptedException e) {
126 LOG.info("notification offer rejected: ", e);
131 public ListenableFuture<ServiceImplementationRequestOutput>
132 serviceImplementation(ServiceImplementationRequestInput input) {
133 LOG.info("Calling service impl request {}", input.getServiceName());
134 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
137 public ServiceImplementationRequestOutput call() throws Exception {
138 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(),
139 RpcStatusEx.Pending, "Service compliant, submitting service implementation Request ...");
140 // Here is the switch statement that distinguishes on the connection-type
141 LOG.info("Connection-type is {} for {}", input.getConnectionType(), input.getServiceName());
142 switch (input.getConnectionType()) {
143 case Service: case RoadmLine: // This takes into account of Ethernet 100G, 1G, 10G and ODU4
144 LOG.info("RPC implementation for {}", input.getConnectionType());
145 if (((input.getServiceAEnd().getServiceRate() != null)
146 && (input.getServiceAEnd().getServiceRate().intValue() == 100))
147 && ((input.getServiceAEnd().getServiceFormat().getName().equals("Ethernet"))
148 || (input.getServiceAEnd().getServiceFormat().getName().equals("OC")))) {
149 LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
150 input.getServiceAEnd().getServiceFormat(), input.getServiceAEnd().getServiceRate());
151 if (!createServicepathInput(input)) {
152 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
155 } else { // This implies, service-rate is 1 or 10G
156 // This includes the lower-order odu (1G, 10G) and this is A-Z side
157 LOG.info("RPC implementation for LO-ODU");
158 String serviceRate = ""; // Assuming service at A-side and Z-side has same service rate
159 if (input.getServiceAEnd().getServiceRate() != null) {
160 serviceRate = input.getServiceAEnd().getServiceRate().toString() + "G";
162 LOG.info("Start rendering for {} service with {} rate and {} format",
163 input.getServiceName(), serviceRate,
164 input.getServiceAEnd().getServiceFormat());
166 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
167 .rendererCreateOtnServiceInput(input.getServiceName(),
168 input.getServiceAEnd().getServiceFormat().getName(),
169 serviceRate, (PathDescription) input.getPathDescription(), true);
170 // Rollback should be same for all conditions, so creating a new one
171 RollbackProcessor rollbackProcessor = new RollbackProcessor();
172 List<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
173 otnServicePathInputAtoZ, null);
174 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
175 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
176 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
177 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
180 LOG.info("OTN rendering result size {}", otnRenderingResults.size());
181 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
182 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL);
186 LOG.info("RPC implementation for {}", input.getConnectionType());
187 if ((input.getServiceAEnd().getOtuServiceRate() != null)
188 && (input.getServiceAEnd().getOtuServiceRate().equals(OTU4.class))) {
189 // For the service of OTU4 infrastructure
190 // First create the OCH and OTU interfaces
191 String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
192 if (!createServicepathInput(input)) {
193 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
197 if ((input.getServiceAEnd().getOduServiceRate() != null)
198 && (input.getServiceAEnd().getOduServiceRate().equals(ODU4.class))) {
199 // For the service of OTU4 infrastructure
200 // First create the OCH and OTU interfaces
201 String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
202 LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
203 input.getServiceAEnd().getOduServiceRate(), serviceRate);
204 // Now start rendering ODU4 interface
206 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
207 .rendererCreateOtnServiceInput(input.getServiceName(),
208 input.getServiceAEnd().getServiceFormat().getName(),
210 input.getPathDescription(), true);
212 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
213 .rendererCreateOtnServiceInput(input.getServiceName(),
214 input.getServiceZEnd().getServiceFormat().getName(),
216 input.getPathDescription(), false);
217 // Rollback should be same for all conditions, so creating a new one
218 RollbackProcessor rollbackProcessor = new RollbackProcessor();
219 List<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
220 otnServicePathInputAtoZ, otnServicePathInputZtoA);
221 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
222 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
223 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
224 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
227 LOG.info("OTN rendering result size {}", otnRenderingResults.size());
228 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
229 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL);
233 LOG.warn("Unsupported connection type {}", input.getConnectionType());
235 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
236 OPERATION_SUCCESSFUL);
242 @SuppressWarnings("checkstyle:IllegalCatch")
243 public OperationResult reserveResource(PathDescription pathDescription) {
246 LOG.info("Reserving resources in network model");
247 networkModelWavelengthService.useWavelengths(pathDescription);
248 } catch (Exception e) {
249 LOG.warn("Reserving resources in network model failed");
250 return OperationResult.failed("Resources reserve failed in network model");
252 return OperationResult.ok("Resources reserved successfully in network model");
256 @SuppressWarnings("checkstyle:IllegalCatch")
257 public OperationResult freeResource(PathDescription pathDescription) {
260 networkModelWavelengthService.freeWavelengths(pathDescription);
261 } catch (Exception e) {
262 return OperationResult.failed("Resources reserve failed in network model");
264 return OperationResult.ok("Resources reserved successfully in network model");
268 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input, Services service) {
269 String serviceName = input.getServiceName();
270 LOG.info("Calling service delete request {}", serviceName);
271 return executor.submit(new Callable<ServiceDeleteOutput>() {
274 public ServiceDeleteOutput call() throws Exception {
275 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
276 RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
277 // Obtain path description
279 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service
280 .path.PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
281 PathDescription pathDescription;
282 if (pathDescriptionOpt.isPresent()) {
283 pathDescription = pathDescriptionOpt.get();
285 LOG.error("Unable to get path description for service {}!", serviceName);
286 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
287 RpcStatusEx.Failed, "Unable to get path description for service");
288 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
291 switch (service.getConnectionType()) {
294 if ((ServiceFormat.Ethernet.equals(service.getServiceAEnd().getServiceFormat())
295 || ServiceFormat.OC.equals(service.getServiceAEnd().getServiceFormat()))
296 && Uint32.valueOf("100").equals(service.getServiceAEnd().getServiceRate())) {
297 if (!manageServicePathDeletion(serviceName, pathDescription)) {
298 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
302 if (ServiceFormat.Ethernet.equals(service.getServiceAEnd().getServiceFormat())
303 && (Uint32.valueOf("10").equals(service.getServiceAEnd().getServiceRate())
304 || Uint32.valueOf("1").equals(service.getServiceAEnd().getServiceRate()))) {
305 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service)) {
306 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
312 if (ServiceFormat.OTU.equals(service.getServiceAEnd().getServiceFormat())) {
313 if (!manageServicePathDeletion(serviceName, pathDescription)) {
314 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
317 } else if (ServiceFormat.ODU.equals(service.getServiceAEnd().getServiceFormat())) {
318 if (!manageOtnServicePathDeletion(serviceName, pathDescription, service)) {
319 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
325 LOG.error("Unmanaged connection-type for deletion of service {}", serviceName);
328 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
333 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
334 value = "UPM_UNCALLED_PRIVATE_METHOD",
335 justification = "call in call() method")
336 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
337 throws InterruptedException, ExecutionException, TimeoutException {
338 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
339 Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
340 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
341 return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
344 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
345 value = "UPM_UNCALLED_PRIVATE_METHOD",
346 justification = "call in call() method")
347 private Optional<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
348 .service.path.PathDescription> getPathDescriptionFromDatastore(String serviceName) {
349 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
350 .service.path.PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
351 .child(ServicePaths.class, new ServicePathsKey(serviceName))
352 .child(org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128
353 .service.path.PathDescription.class);
354 ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
356 LOG.debug("Getting path description for service {}", serviceName);
357 return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
358 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
359 } catch (InterruptedException | ExecutionException | TimeoutException e) {
360 LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
362 return Optional.empty();
366 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
367 value = "UPM_UNCALLED_PRIVATE_METHOD",
368 justification = "call in call() method")
369 private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
370 ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
371 LOG.info(RENDERING_DEVICES_A_Z_MSG);
372 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
373 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
374 RENDERING_DEVICES_A_Z_MSG);
375 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
376 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
377 ServicePathDirection.A_TO_Z));
379 LOG.info("Rendering devices Z-A");
380 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
381 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
382 RENDERING_DEVICES_Z_A_MSG);
383 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
384 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
385 ServicePathDirection.Z_TO_A));
386 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
387 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
389 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
391 LOG.info("Waiting for A-Z and Z-A device renderers ...");
392 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
393 } catch (InterruptedException | ExecutionException | TimeoutException e) {
394 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
395 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
396 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
397 DEVICE_RENDERING_ROLL_BACK_MSG);
398 //FIXME we can't do rollback here, because we don't have rendering results.
399 return renderingResults;
402 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
403 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
404 this.deviceRenderer));
405 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
406 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
407 this.deviceRenderer));
408 return renderingResults;
411 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
412 value = "UPM_UNCALLED_PRIVATE_METHOD",
413 justification = "call in call() method")
414 private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
415 OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA) {
416 LOG.info(RENDERING_DEVICES_A_Z_MSG);
417 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
418 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
419 RENDERING_DEVICES_A_Z_MSG);
420 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
421 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ));
422 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture;
423 if (otnServicePathZtoA != null) {
424 LOG.info("Rendering devices Z-A");
425 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
426 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
427 RENDERING_DEVICES_Z_A_MSG);
428 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
429 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA));
430 renderingCombinedFuture = Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
432 renderingCombinedFuture = Futures.allAsList(atozrenderingFuture);
434 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
436 LOG.info("Waiting for A-Z and Z-A device renderers ...");
437 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
438 } catch (InterruptedException | ExecutionException | TimeoutException e) {
439 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
440 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
441 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
442 DEVICE_RENDERING_ROLL_BACK_MSG);
443 //FIXME we can't do rollback here, because we don't have rendering results.
444 return otnRenderingResults;
446 for (int i = 0; i < otnRenderingResults.size(); i++) {
447 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("DeviceTask n° " + i + 1,
448 ! otnRenderingResults.get(i).isSuccess(), otnRenderingResults.get(i).getRenderedNodeInterfaces(),
449 this.deviceRenderer));
451 return otnRenderingResults;
454 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
455 value = "UPM_UNCALLED_PRIVATE_METHOD",
456 justification = "call in call() method")
457 private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
458 ServicePowerSetupInput powerSetupInputZtoA) {
459 LOG.info("Olm power setup A-Z");
460 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
461 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
462 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
463 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
465 LOG.info("OLM power setup Z-A");
466 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
467 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
468 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
469 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
470 ListenableFuture<List<OLMRenderingResult>> olmFutures =
471 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
473 List<OLMRenderingResult> olmResults;
475 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
476 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
477 } catch (InterruptedException | ExecutionException | TimeoutException e) {
478 LOG.warn(OLM_ROLL_BACK_MSG, e);
479 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
480 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
482 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
483 this.olmService, powerSetupInputAtoZ));
484 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
485 this.olmService, powerSetupInputZtoA));
489 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
490 this.olmService, powerSetupInputAtoZ));
491 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
492 this.olmService, powerSetupInputZtoA));
495 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
496 value = "UPM_UNCALLED_PRIVATE_METHOD",
497 justification = "call in call() method")
498 private boolean isServiceActivated(String nodeId, String tpId) {
499 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
500 for (int i = 0; i < 3; i++) {
501 List<Measurements> measurements = getMeasurements(nodeId, tpId);
502 if ((measurements != null) && verifyPreFecBer(measurements)) {
504 } else if (measurements == null) {
505 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
509 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
510 } catch (InterruptedException ex) {
511 Thread.currentThread().interrupt();
515 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
519 private List<Measurements> getMeasurements(String nodeId, String tp) {
520 GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder();
521 getPmIpBldr.setNodeId(nodeId);
522 getPmIpBldr.setGranularity(PmGranularity._15min);
523 ResourceIdentifierBuilder rsrcBldr = new ResourceIdentifierBuilder();
524 rsrcBldr.setResourceName(tp + "-OTU");
525 getPmIpBldr.setResourceIdentifier(rsrcBldr.build());
526 getPmIpBldr.setResourceType(ResourceTypeEnum.Interface);
529 Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
530 RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
531 GetPmOutput getPmOutput = getPmRpcResult.getResult();
532 if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
533 LOG.info("successfully finished calling OLM's get PM");
534 return getPmOutput.getMeasurements();
537 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
540 } catch (ExecutionException | InterruptedException e) {
541 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
546 private boolean verifyPreFecBer(List<Measurements> measurements) {
547 double preFecCorrectedErrors = Double.MIN_VALUE;
548 double fecUncorrectableBlocks = Double.MIN_VALUE;
550 for (Measurements measurement : measurements) {
551 if (measurement.getPmparameterName().equals("preFECCorrectedErrors")) {
552 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
554 if (measurement.getPmparameterName().equals("FECUncorrectableBlocks")) {
555 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
559 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
560 fecUncorrectableBlocks);
562 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
563 LOG.error("Data has uncorrectable errors, BER test failed");
566 double numOfBitsPerSecond = 112000000000d;
567 double threshold = 0.00002d;
568 double result = preFecCorrectedErrors / numOfBitsPerSecond;
569 LOG.info("PreFEC value is {}", Double.toString(result));
570 return result <= threshold;
574 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
575 value = "UPM_UNCALLED_PRIVATE_METHOD",
576 justification = "call in call() method")
577 private boolean createServicepathInput(ServiceImplementationRequestInput input) {
578 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
579 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription());
580 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
581 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription());
582 // Rollback should be same for all conditions, so creating a new one
583 RollbackProcessor rollbackProcessor = new RollbackProcessor();
584 List<DeviceRenderingResult> renderingResults =
585 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
586 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
587 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
588 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
591 ServicePowerSetupInput olmPowerSetupInputAtoZ =
592 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(), input);
593 ServicePowerSetupInput olmPowerSetupInputZtoA =
594 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(), input);
595 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
596 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
597 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
598 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
601 // run service activation test twice - once on source node and once on
603 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
604 if ((nodes == null) || (nodes.isEmpty())) {
608 Nodes sourceNode = nodes.get(0);
609 Nodes destNode = nodes.get(nodes.size() - 1);
612 if (sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
613 srcNetworkTp = sourceNode.getDestTp();
615 srcNetworkTp = sourceNode.getSrcTp();
617 if (destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
618 dstNetowrkTp = destNode.getDestTp();
620 dstNetowrkTp = destNode.getSrcTp();
622 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
623 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
624 rollbackProcessor.rollbackAll();
625 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
626 input.getServiceName(), RpcStatusEx.Failed,
627 "Service activation test failed.");
630 // If Service activation is success update Network ModelMappingUtils
631 networkModelWavelengthService.useWavelengths(input.getPathDescription());
632 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
633 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL);
637 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
638 value = "UPM_UNCALLED_PRIVATE_METHOD",
639 justification = "call in call() method")
640 private boolean manageServicePathDeletion(String serviceName, PathDescription pathDescription) {
641 ServicePathInputData servicePathInputDataAtoZ =
642 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription);
643 ServicePathInputData servicePathInputDataZtoA =
644 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription);
645 // OLM turn down power
647 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
648 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName,
649 RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
650 ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
651 // TODO add some flag rather than string
652 if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
653 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
654 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
655 "Service power turndown failed on A-to-Z path for service");
658 LOG.debug("Turning down power on Z-to-A path");
659 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
660 "Turning down power on Z-to-A path");
661 ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
662 // TODO add some flag rather than string
663 if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
664 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
665 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Failed,
666 "Service power turndown failed on Z-to-A path for service");
669 } catch (InterruptedException | ExecutionException | TimeoutException e) {
670 LOG.error("Error while turning down power!", e);
673 // delete service path with renderer
674 LOG.info("Deleting service path via renderer");
675 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
676 "Deleting service path via renderer");
677 deviceRenderer.deleteServicePath(servicePathInputDataAtoZ.getServicePathInput());
678 deviceRenderer.deleteServicePath(servicePathInputDataZtoA.getServicePathInput());
679 networkModelWavelengthService.freeWavelengths(pathDescription);
680 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Successful,
681 OPERATION_SUCCESSFUL);
685 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
686 value = "UPM_UNCALLED_PRIVATE_METHOD",
687 justification = "call in call() method")
688 private boolean manageOtnServicePathDeletion(String serviceName, PathDescription pathDescription,
690 OtnServicePathInput ospi = null;
691 if (ConnectionType.Infrastructure.equals(service.getConnectionType())) {
692 ospi = ModelMappingUtils.rendererCreateOtnServiceInput(
693 serviceName, service.getServiceAEnd().getServiceFormat().getName(), "100G", pathDescription, true);
694 } else if (ConnectionType.Service.equals(service.getConnectionType())) {
695 ospi = ModelMappingUtils.rendererCreateOtnServiceInput(serviceName,
696 service.getServiceAEnd().getServiceFormat().getName(),
697 service.getServiceAEnd().getServiceRate().toString() + "G", pathDescription, true);
699 LOG.info("Deleting otn-service path {} via renderer", serviceName);
700 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Pending,
701 "Deleting otn-service path via renderer");
702 OtnServicePathOutput result = otnDeviceRenderer.deleteOtnServicePath(ospi);
703 if (result.isSuccess()) {
704 sendNotifications(ServicePathNotificationTypes.ServiceDelete, serviceName, RpcStatusEx.Successful,
705 OPERATION_SUCCESSFUL);