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.olm.rev170418.GetPmInputBuilder;
42 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.GetPmOutput;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerSetupInput;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerTurndownInputBuilder;
45 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerTurndownOutput;
46 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.TransportpceOlmService;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.get.pm.output.Measurements;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.OtnServicePathInput;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceDeleteInput;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceDeleteOutput;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceImplementationRequestInput;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceImplementationRequestOutput;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceRpcResultSp;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev200520.ServiceRpcResultSpBuilder;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev181130.ODU4;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev181130.OTU4;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum;
59 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx;
60 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.ServicePathNotificationTypes;
61 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.service.path.PathDescription;
62 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.ServicePathList;
63 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
64 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
65 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.olm.get.pm.input.ResourceIdentifierBuilder;
66 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.olm.renderer.input.Nodes;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.opendaylight.yangtools.yang.common.RpcResult;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
73 public class RendererServiceOperationsImpl implements RendererServiceOperations {
75 private static final String DEVICE_RENDERING_ROLL_BACK_MSG =
76 "Device rendering was not successful! Rendering will be rolled back.";
77 private static final String OLM_ROLL_BACK_MSG =
78 "OLM power setup was not successful! Rendering and OLM will be rolled back.";
79 private static final String RENDERING_DEVICES_A_Z_MSG = "Rendering devices A-Z";
80 private static final String RENDERING_DEVICES_Z_A_MSG = "Rendering device Z-A";
81 private static final String TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG = "Turning down power on A-to-Z path";
82 private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class);
83 private static final String FAILED = "Failed";
84 private static final String OPERATION_FAILED = "Operation Failed";
85 private static final String OPERATION_SUCCESSFUL = "Operation Successful";
86 private static final int NUMBER_OF_THREADS = 4;
88 private final DeviceRendererService deviceRenderer;
89 private final OtnDeviceRendererService otnDeviceRenderer;
90 private final TransportpceOlmService olmService;
91 private final DataBroker dataBroker;
92 private final NotificationPublishService notificationPublishService;
93 private ListeningExecutorService executor;
94 private NetworkModelWavelengthService networkModelWavelengthService;
95 private ServiceRpcResultSp notification = null;
97 public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer,
98 OtnDeviceRendererService otnDeviceRenderer, TransportpceOlmService olmService,
99 DataBroker dataBroker, NetworkModelWavelengthService networkModelWavelengthService,
100 NotificationPublishService notificationPublishService) {
101 this.deviceRenderer = deviceRenderer;
102 this.otnDeviceRenderer = otnDeviceRenderer;
103 this.olmService = olmService;
104 this.dataBroker = dataBroker;
105 this.networkModelWavelengthService = networkModelWavelengthService;
106 this.notificationPublishService = notificationPublishService;
107 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
110 private void sendNotifications(ServicePathNotificationTypes servicePathNotificationTypes, String serviceName,
111 RpcStatusEx rpcStatusEx, String message) {
112 this.notification = new ServiceRpcResultSpBuilder()
113 .setNotificationType(servicePathNotificationTypes)
114 .setServiceName(serviceName)
115 .setStatus(rpcStatusEx)
116 .setStatusMessage(message)
119 notificationPublishService.putNotification(this.notification);
120 } catch (InterruptedException e) {
121 LOG.info("notification offer rejected: ", e);
126 public ListenableFuture<ServiceImplementationRequestOutput>
127 serviceImplementation(ServiceImplementationRequestInput input) {
128 LOG.info("Calling service impl request {}", input.getServiceName());
129 return executor.submit(new Callable<ServiceImplementationRequestOutput>() {
131 public ServiceImplementationRequestOutput call() throws Exception {
132 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest, input.getServiceName(),
133 RpcStatusEx.Pending, "Service compliant, submitting service implementation Request ...");
134 // Here is the switch statement that distinguishes on the connection-type
135 LOG.info("Connection-type is {} for {}", input.getConnectionType(), input.getServiceName());
136 switch (input.getConnectionType()) {
137 case Service: // This takes into account of Ethernet 100G, 1G, 10G and ODU4
138 LOG.info("RPC implementation for {}", input.getConnectionType());
139 if ((input.getServiceAEnd().getServiceRate() != null) // Since service-rate could be null
140 && (input.getServiceAEnd().getServiceRate().intValue() == 100)
141 && (input.getServiceAEnd().getServiceFormat().getName().equals("Ethernet"))) {
142 LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
143 input.getServiceAEnd().getServiceFormat(), input.getServiceAEnd().getServiceRate());
144 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
145 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription());
146 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
147 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription());
148 // Rollback should be same for all conditions, so creating a new one
149 RollbackProcessor rollbackProcessor = new RollbackProcessor();
150 List<DeviceRenderingResult> renderingResults =
151 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
152 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
153 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
154 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
155 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
158 ServicePowerSetupInput olmPowerSetupInputAtoZ =
159 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(),
161 ServicePowerSetupInput olmPowerSetupInputZtoA =
162 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(),
164 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
165 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
166 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
167 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
168 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
171 // run service activation test twice - once on source node and once on
173 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
174 if ((nodes == null) || (nodes.isEmpty())) {
175 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
178 Nodes sourceNode = nodes.get(0);
179 Nodes destNode = nodes.get(nodes.size() - 1);
182 if (sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
183 srcNetworkTp = sourceNode.getDestTp();
185 srcNetworkTp = sourceNode.getSrcTp();
187 if (destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
188 dstNetowrkTp = destNode.getDestTp();
190 dstNetowrkTp = destNode.getSrcTp();
192 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
193 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
194 rollbackProcessor.rollbackAll();
195 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
196 input.getServiceName(), RpcStatusEx.Failed,
197 "Service activation test failed.");
198 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
201 // If Service activation is success update Network ModelMappingUtils
202 networkModelWavelengthService.useWavelengths(input.getPathDescription());
203 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
204 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL);
205 } else { // This implies, service-rate is 1 or 10G
206 // This includes the lower-order odu (1 G, 10 G) and
207 LOG.info("RPC implementation for LO-ODU");
208 String serviceRate = ""; // Assuming service at A-side and Z-side has same service rate
209 if (input.getServiceAEnd().getServiceRate() != null) {
210 serviceRate = input.getServiceAEnd().getServiceRate().toString() + "G";
212 LOG.info("Start rendering for {} service with {} rate and {} format",
213 input.getServiceName(), serviceRate,
214 input.getServiceAEnd().getServiceFormat());
215 // TODO: Need to create OCH-OTU4 interfaces by calling service-path input without src-tp
217 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
218 .rendererCreateOtnServiceInput(input.getServiceName(),
219 input.getServiceAEnd().getServiceFormat().getName(),
220 serviceRate, input.getPathDescription(), true);
222 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
223 .rendererCreateOtnServiceInput(input.getServiceName(),
224 input.getServiceZEnd().getServiceFormat().getName(),
225 serviceRate, input.getPathDescription(), false);
226 // Rollback should be same for all conditions, so creating a new one
227 RollbackProcessor rollbackProcessor = new RollbackProcessor();
228 List<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
229 otnServicePathInputAtoZ, otnServicePathInputZtoA);
230 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
231 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
232 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
233 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
236 LOG.info("OTN rendering result size {}", otnRenderingResults.size());
237 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
238 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL);
242 LOG.info("RPC implementation for {}", input.getConnectionType());
243 if ((input.getServiceAEnd().getOtuServiceRate() != null)
244 && (input.getServiceAEnd().getOtuServiceRate().equals(OTU4.class))) {
245 // For the service of OTU4 infrastructure
246 // First create the OCH and OTU interfaces
247 String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
248 LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
249 input.getServiceAEnd().getOtuServiceRate(), serviceRate);
250 // First render OCH and OTU interfaces
251 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
252 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription());
253 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
254 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription());
255 // Rollback should be same for all conditions, so creating a new one
256 RollbackProcessor rollbackProcessor = new RollbackProcessor();
257 List<DeviceRenderingResult> renderingResults =
258 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
259 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
260 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
261 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
262 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
265 LOG.info("Starting the OLM power setup");
266 ServicePowerSetupInput olmPowerSetupInputAtoZ =
267 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(),
269 ServicePowerSetupInput olmPowerSetupInputZtoA =
270 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(),
272 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
273 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
274 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
275 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
276 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
279 // run service activation test twice - once on source node and once on
281 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
282 if ((nodes == null) || (nodes.isEmpty())) {
283 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
286 Nodes srcNode = nodes.get(0);
287 Nodes tgtNode = nodes.get(nodes.size() - 1); // destination node or target node
288 String srcNetworkTp = srcNode.getDestTp(); // In this case srcNode only has destTp
289 String tgtNetowrkTp = tgtNode.getSrcTp(); // tgtNode node only has srcTp
291 if (!isServiceActivated(srcNode.getNodeId(), srcNetworkTp)
292 || !isServiceActivated(tgtNode.getNodeId(), tgtNetowrkTp)) {
293 rollbackProcessor.rollbackAll();
294 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
295 input.getServiceName(), RpcStatusEx.Failed,
296 "Service activation test failed.");
297 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
301 if ((input.getServiceAEnd().getOduServiceRate() != null)
302 && (input.getServiceAEnd().getOduServiceRate().equals(ODU4.class))) {
303 // For the service of OTU4 infrastructure
304 // First create the OCH and OTU interfaces
305 String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
306 LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
307 input.getServiceAEnd().getOtuServiceRate(), serviceRate);
308 // Now start rendering ODU4 interface
309 String serviceFormat = "ODU"; // Since we need to create ODU4 Ttp interfaces as well
311 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
312 .rendererCreateOtnServiceInput(input.getServiceName(),
313 serviceFormat, serviceRate, input.getPathDescription(), true);
315 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
316 .rendererCreateOtnServiceInput(input.getServiceName(),
317 input.getServiceZEnd().getServiceFormat().getName(),
318 serviceRate, input.getPathDescription(), false);
319 // Rollback should be same for all conditions, so creating a new one
320 RollbackProcessor rollbackProcessor = new RollbackProcessor();
321 List<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
322 otnServicePathInputAtoZ, otnServicePathInputZtoA);
323 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
324 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
325 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
326 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
329 LOG.info("OTN rendering result size {}", otnRenderingResults.size());
330 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
331 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL);
335 LOG.warn("Unsupported connection type {}", input.getConnectionType());
337 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
338 OPERATION_SUCCESSFUL);
345 @SuppressWarnings("checkstyle:IllegalCatch")
346 public OperationResult reserveResource(PathDescription pathDescription) {
349 LOG.info("Reserving resources in network model");
350 networkModelWavelengthService.useWavelengths(pathDescription);
351 } catch (Exception e) {
352 LOG.warn("Reserving resources in network model failed");
353 return OperationResult.failed("Resources reserve failed in network model");
355 return OperationResult.ok("Resources reserved successfully in network model");
359 @SuppressWarnings("checkstyle:IllegalCatch")
360 public OperationResult freeResource(PathDescription pathDescription) {
363 networkModelWavelengthService.freeWavelengths(pathDescription);
364 } catch (Exception e) {
365 return OperationResult.failed("Resources reserve failed in network model");
367 return OperationResult.ok("Resources reserved successfully in network model");
371 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input) {
372 String serviceName = input.getServiceName();
373 LOG.info("Calling service delete request {}", input.getServiceName());
374 return executor.submit(new Callable<ServiceDeleteOutput>() {
377 public ServiceDeleteOutput call() throws Exception {
378 sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(),
379 RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
380 // Obtain path description
381 Optional<PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
382 PathDescription pathDescription;
383 if (pathDescriptionOpt.isPresent()) {
384 pathDescription = pathDescriptionOpt.get();
386 LOG.error("Unable to get path description for service {}!", serviceName);
387 sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(),
388 RpcStatusEx.Failed, "Unable to get path description for service");
389 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
392 ServicePathInputData servicePathInputDataAtoZ =
393 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription);
394 ServicePathInputData servicePathInputDataZtoA =
395 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription);
396 // OLM turn down power
398 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
399 sendNotifications(ServicePathNotificationTypes.ServiceDelete,
400 input.getServiceName(), RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
401 ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
402 // TODO add some flag rather than string
403 if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
404 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
405 sendNotifications(ServicePathNotificationTypes.ServiceDelete,
406 input.getServiceName(), RpcStatusEx.Failed,
407 "Service power turndown failed on A-to-Z path for service");
408 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
411 LOG.debug("Turning down power on Z-to-A path");
412 sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(),
413 RpcStatusEx.Pending, "Turning down power on Z-to-A path");
414 ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
415 // TODO add some flag rather than string
416 if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
417 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
418 sendNotifications(ServicePathNotificationTypes.ServiceDelete,
419 input.getServiceName(), RpcStatusEx.Failed,
420 "Service power turndown failed on Z-to-A path for service");
421 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
424 } catch (InterruptedException | ExecutionException | TimeoutException e) {
425 LOG.error("Error while turning down power!", e);
426 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
429 // delete service path with renderer
430 LOG.debug("Deleting service path via renderer");
431 sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(),
432 RpcStatusEx.Pending, "Deleting service path via renderer");
433 deviceRenderer.deleteServicePath(servicePathInputDataAtoZ.getServicePathInput());
434 deviceRenderer.deleteServicePath(servicePathInputDataZtoA.getServicePathInput());
435 networkModelWavelengthService.freeWavelengths(pathDescription);
436 sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(),
437 RpcStatusEx.Successful, OPERATION_SUCCESSFUL);
438 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
445 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
446 value = "UPM_UNCALLED_PRIVATE_METHOD",
447 justification = "call in call() method")
448 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
449 throws InterruptedException, ExecutionException, TimeoutException {
450 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
451 Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
452 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
453 return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
456 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
457 value = "UPM_UNCALLED_PRIVATE_METHOD",
458 justification = "call in call() method")
459 private Optional<PathDescription> getPathDescriptionFromDatastore(String serviceName) {
460 InstanceIdentifier<PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
461 .child(ServicePaths.class, new ServicePathsKey(serviceName)).child(PathDescription.class);
462 ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
464 LOG.debug("Getting path description for service {}", serviceName);
465 return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
466 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
467 } catch (InterruptedException | ExecutionException | TimeoutException e) {
468 LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
470 return Optional.empty();
474 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
475 value = "UPM_UNCALLED_PRIVATE_METHOD",
476 justification = "call in call() method")
477 private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
478 ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
479 LOG.info(RENDERING_DEVICES_A_Z_MSG);
480 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
481 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
482 RENDERING_DEVICES_A_Z_MSG);
483 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
484 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
485 ServicePathDirection.A_TO_Z));
487 LOG.info("Rendering devices Z-A");
488 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
489 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
490 RENDERING_DEVICES_Z_A_MSG);
491 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
492 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
493 ServicePathDirection.Z_TO_A));
494 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
495 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
497 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
499 LOG.info("Waiting for A-Z and Z-A device renderers ...");
500 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
501 } catch (InterruptedException | ExecutionException | TimeoutException e) {
502 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
503 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
504 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
505 DEVICE_RENDERING_ROLL_BACK_MSG);
506 //FIXME we can't do rollback here, because we don't have rendering results.
507 return renderingResults;
510 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
511 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
512 this.deviceRenderer));
513 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
514 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
515 this.deviceRenderer));
516 return renderingResults;
519 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
520 value = "UPM_UNCALLED_PRIVATE_METHOD",
521 justification = "call in call() method")
522 private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
523 OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA) {
524 LOG.info(RENDERING_DEVICES_A_Z_MSG);
525 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
526 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
527 RENDERING_DEVICES_A_Z_MSG);
528 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
529 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ));
531 LOG.info("Rendering devices Z-A");
532 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
533 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
534 RENDERING_DEVICES_Z_A_MSG);
535 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
536 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA));
537 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
538 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
540 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
542 LOG.info("Waiting for A-Z and Z-A device renderers ...");
543 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
544 } catch (InterruptedException | ExecutionException | TimeoutException e) {
545 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
546 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
547 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
548 DEVICE_RENDERING_ROLL_BACK_MSG);
549 //FIXME we can't do rollback here, because we don't have rendering results.
550 return otnRenderingResults;
553 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
554 ! otnRenderingResults.get(0).isSuccess(), otnRenderingResults.get(0).getRenderedNodeInterfaces(),
555 this.deviceRenderer));
556 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
557 ! otnRenderingResults.get(1).isSuccess(), otnRenderingResults.get(1).getRenderedNodeInterfaces(),
558 this.deviceRenderer));
561 return otnRenderingResults;
565 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
566 value = "UPM_UNCALLED_PRIVATE_METHOD",
567 justification = "call in call() method")
568 private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
569 ServicePowerSetupInput powerSetupInputZtoA) {
570 LOG.info("Olm power setup A-Z");
571 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
572 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
573 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
574 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
576 LOG.info("OLM power setup Z-A");
577 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
578 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
579 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
580 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
581 ListenableFuture<List<OLMRenderingResult>> olmFutures =
582 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
584 List<OLMRenderingResult> olmResults;
586 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
587 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
588 } catch (InterruptedException | ExecutionException | TimeoutException e) {
589 LOG.warn(OLM_ROLL_BACK_MSG, e);
590 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
591 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
593 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
594 this.olmService, powerSetupInputAtoZ));
595 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
596 this.olmService, powerSetupInputZtoA));
600 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
601 this.olmService, powerSetupInputAtoZ));
602 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
603 this.olmService, powerSetupInputZtoA));
606 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
607 value = "UPM_UNCALLED_PRIVATE_METHOD",
608 justification = "call in call() method")
609 private boolean isServiceActivated(String nodeId, String tpId) {
610 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
611 for (int i = 0; i < 3; i++) {
612 List<Measurements> measurements = getMeasurements(nodeId, tpId);
613 if ((measurements != null) && verifyPreFecBer(measurements)) {
615 } else if (measurements == null) {
616 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
620 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
621 } catch (InterruptedException ex) {
622 Thread.currentThread().interrupt();
626 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
630 private List<Measurements> getMeasurements(String nodeId, String tp) {
631 GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder();
632 getPmIpBldr.setNodeId(nodeId);
633 getPmIpBldr.setGranularity(PmGranularity._15min);
634 ResourceIdentifierBuilder rsrcBldr = new ResourceIdentifierBuilder();
635 rsrcBldr.setResourceName(tp + "-OTU");
636 getPmIpBldr.setResourceIdentifier(rsrcBldr.build());
637 getPmIpBldr.setResourceType(ResourceTypeEnum.Interface);
640 Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
641 RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
642 GetPmOutput getPmOutput = getPmRpcResult.getResult();
643 if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
644 LOG.info("successfully finished calling OLM's get PM");
645 return getPmOutput.getMeasurements();
648 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
651 } catch (ExecutionException | InterruptedException e) {
652 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
658 private boolean verifyPreFecBer(List<Measurements> measurements) {
659 double preFecCorrectedErrors = Double.MIN_VALUE;
660 double fecUncorrectableBlocks = Double.MIN_VALUE;
662 for (Measurements measurement : measurements) {
663 if (measurement.getPmparameterName().equals("preFECCorrectedErrors")) {
664 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
666 if (measurement.getPmparameterName().equals("FECUncorrectableBlocks")) {
667 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
671 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
672 fecUncorrectableBlocks);
674 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
675 LOG.error("Data has uncorrectable errors, BER test failed");
678 double numOfBitsPerSecond = 112000000000d;
679 double threshold = 0.00002d;
680 double result = preFecCorrectedErrors / numOfBitsPerSecond;
681 LOG.info("PreFEC value is {}", Double.toString(result));
682 return result <= threshold;