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: case RoadmLine: // 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)
140 && (input.getServiceAEnd().getServiceRate().intValue() == 100))
141 && ((input.getServiceAEnd().getServiceFormat().getName().equals("Ethernet"))
142 || (input.getServiceAEnd().getServiceFormat().getName().equals("OC")))) {
143 LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
144 input.getServiceAEnd().getServiceFormat(), input.getServiceAEnd().getServiceRate());
145 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
146 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription());
147 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
148 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription());
149 // Rollback should be same for all conditions, so creating a new one
150 RollbackProcessor rollbackProcessor = new RollbackProcessor();
151 List<DeviceRenderingResult> renderingResults =
152 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
153 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
154 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
155 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
156 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
159 ServicePowerSetupInput olmPowerSetupInputAtoZ =
160 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(),
162 ServicePowerSetupInput olmPowerSetupInputZtoA =
163 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(),
165 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
166 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
167 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
168 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
169 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
172 // run service activation test twice - once on source node and once on
174 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
175 if ((nodes == null) || (nodes.isEmpty())) {
176 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
179 Nodes sourceNode = nodes.get(0);
180 Nodes destNode = nodes.get(nodes.size() - 1);
183 if (sourceNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
184 srcNetworkTp = sourceNode.getDestTp();
186 srcNetworkTp = sourceNode.getSrcTp();
188 if (destNode.getDestTp().contains(StringConstants.NETWORK_TOKEN)) {
189 dstNetowrkTp = destNode.getDestTp();
191 dstNetowrkTp = destNode.getSrcTp();
193 if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp)
194 || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) {
195 rollbackProcessor.rollbackAll();
196 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
197 input.getServiceName(), RpcStatusEx.Failed,
198 "Service activation test failed.");
199 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
202 // If Service activation is success update Network ModelMappingUtils
203 networkModelWavelengthService.useWavelengths(input.getPathDescription());
204 } else { // This implies, service-rate is 1 or 10G
205 // This includes the lower-order odu (1 G, 10 G) and
206 LOG.info("RPC implementation for LO-ODU");
207 String serviceRate = ""; // Assuming service at A-side and Z-side has same service rate
208 if (input.getServiceAEnd().getServiceRate() != null) {
209 serviceRate = input.getServiceAEnd().getServiceRate().toString() + "G";
211 LOG.info("Start rendering for {} service with {} rate and {} format",
212 input.getServiceName(), serviceRate,
213 input.getServiceAEnd().getServiceFormat());
214 // TODO: Need to create OCH-OTU4 interfaces by calling service-path input without src-tp
216 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
217 .rendererCreateOtnServiceInput(input.getServiceName(),
218 input.getServiceAEnd().getServiceFormat().getName(),
219 serviceRate, input.getPathDescription(), true);
221 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
222 .rendererCreateOtnServiceInput(input.getServiceName(),
223 input.getServiceZEnd().getServiceFormat().getName(),
224 serviceRate, input.getPathDescription(), false);
225 // Rollback should be same for all conditions, so creating a new one
226 RollbackProcessor rollbackProcessor = new RollbackProcessor();
227 List<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
228 otnServicePathInputAtoZ, otnServicePathInputZtoA);
229 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
230 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
231 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
232 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
235 LOG.info("OTN rendering result size {}", otnRenderingResults.size());
237 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
238 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL);
241 LOG.info("RPC implementation for {}", input.getConnectionType());
242 if ((input.getServiceAEnd().getOtuServiceRate() != null)
243 && (input.getServiceAEnd().getOtuServiceRate().equals(OTU4.class))) {
244 // For the service of OTU4 infrastructure
245 // First create the OCH and OTU interfaces
246 String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
247 LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
248 input.getServiceAEnd().getOtuServiceRate(), serviceRate);
249 // First render OCH and OTU interfaces
250 ServicePathInputData servicePathInputDataAtoZ = ModelMappingUtils
251 .rendererCreateServiceInputAToZ(input.getServiceName(), input.getPathDescription());
252 ServicePathInputData servicePathInputDataZtoA = ModelMappingUtils
253 .rendererCreateServiceInputZToA(input.getServiceName(), input.getPathDescription());
254 // Rollback should be same for all conditions, so creating a new one
255 RollbackProcessor rollbackProcessor = new RollbackProcessor();
256 List<DeviceRenderingResult> renderingResults =
257 deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, servicePathInputDataZtoA);
258 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
259 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
260 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
261 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
264 LOG.info("Starting the OLM power setup");
265 ServicePowerSetupInput olmPowerSetupInputAtoZ =
266 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(0).getOlmList(),
268 ServicePowerSetupInput olmPowerSetupInputZtoA =
269 ModelMappingUtils.createServicePowerSetupInput(renderingResults.get(1).getOlmList(),
271 olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA);
272 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
273 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
274 input.getServiceName(), RpcStatusEx.Failed, OLM_ROLL_BACK_MSG);
275 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
278 // run service activation test twice - once on source node and once on
280 List<Nodes> nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes();
281 if ((nodes == null) || (nodes.isEmpty())) {
282 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
285 Nodes srcNode = nodes.get(0);
286 Nodes tgtNode = nodes.get(nodes.size() - 1); // destination node or target node
287 String srcNetworkTp = srcNode.getDestTp(); // In this case srcNode only has destTp
288 String tgtNetowrkTp = tgtNode.getSrcTp(); // tgtNode node only has srcTp
290 if (!isServiceActivated(srcNode.getNodeId(), srcNetworkTp)
291 || !isServiceActivated(tgtNode.getNodeId(), tgtNetowrkTp)) {
292 rollbackProcessor.rollbackAll();
293 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
294 input.getServiceName(), RpcStatusEx.Failed,
295 "Service activation test failed.");
296 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
300 if ((input.getServiceAEnd().getOduServiceRate() != null)
301 && (input.getServiceAEnd().getOduServiceRate().equals(ODU4.class))) {
302 // For the service of OTU4 infrastructure
303 // First create the OCH and OTU interfaces
304 String serviceRate = "100G"; // For OtnDeviceRendererServiceImpl
305 LOG.info("Service format for {} is {} and rate is {}", input.getServiceName(),
306 input.getServiceAEnd().getOduServiceRate(), serviceRate);
307 // Now start rendering ODU4 interface
308 String serviceFormat = "ODU"; // Since we need to create ODU4 Ttp interfaces as well
310 OtnServicePathInput otnServicePathInputAtoZ = ModelMappingUtils
311 .rendererCreateOtnServiceInput(input.getServiceName(),
312 serviceFormat, serviceRate, input.getPathDescription(), true);
314 OtnServicePathInput otnServicePathInputZtoA = ModelMappingUtils
315 .rendererCreateOtnServiceInput(input.getServiceName(),
316 input.getServiceZEnd().getServiceFormat().getName(),
317 serviceRate, input.getPathDescription(), false);
318 // Rollback should be same for all conditions, so creating a new one
319 RollbackProcessor rollbackProcessor = new RollbackProcessor();
320 List<OtnDeviceRenderingResult> otnRenderingResults = otnDeviceRendering(rollbackProcessor,
321 otnServicePathInputAtoZ, otnServicePathInputZtoA);
322 if (rollbackProcessor.rollbackAllIfNecessary() > 0) {
323 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
324 input.getServiceName(), RpcStatusEx.Failed, DEVICE_RENDERING_ROLL_BACK_MSG);
325 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED,
328 LOG.info("OTN rendering result size {}", otnRenderingResults.size());
329 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
330 input.getServiceName(), RpcStatusEx.Successful, OPERATION_SUCCESSFUL);
334 LOG.warn("Unsupported connection type {}", input.getConnectionType());
336 return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK,
337 OPERATION_SUCCESSFUL);
344 @SuppressWarnings("checkstyle:IllegalCatch")
345 public OperationResult reserveResource(PathDescription pathDescription) {
348 LOG.info("Reserving resources in network model");
349 networkModelWavelengthService.useWavelengths(pathDescription);
350 } catch (Exception e) {
351 LOG.warn("Reserving resources in network model failed");
352 return OperationResult.failed("Resources reserve failed in network model");
354 return OperationResult.ok("Resources reserved successfully in network model");
358 @SuppressWarnings("checkstyle:IllegalCatch")
359 public OperationResult freeResource(PathDescription pathDescription) {
362 networkModelWavelengthService.freeWavelengths(pathDescription);
363 } catch (Exception e) {
364 return OperationResult.failed("Resources reserve failed in network model");
366 return OperationResult.ok("Resources reserved successfully in network model");
370 public ListenableFuture<ServiceDeleteOutput> serviceDelete(ServiceDeleteInput input) {
371 String serviceName = input.getServiceName();
372 LOG.info("Calling service delete request {}", input.getServiceName());
373 return executor.submit(new Callable<ServiceDeleteOutput>() {
376 public ServiceDeleteOutput call() throws Exception {
377 sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(),
378 RpcStatusEx.Pending, "Service compliant, submitting service delete Request ...");
379 // Obtain path description
380 Optional<PathDescription> pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName);
381 PathDescription pathDescription;
382 if (pathDescriptionOpt.isPresent()) {
383 pathDescription = pathDescriptionOpt.get();
385 LOG.error("Unable to get path description for service {}!", serviceName);
386 sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(),
387 RpcStatusEx.Failed, "Unable to get path description for service");
388 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
391 ServicePathInputData servicePathInputDataAtoZ =
392 ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription);
393 ServicePathInputData servicePathInputDataZtoA =
394 ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription);
395 // OLM turn down power
397 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
398 sendNotifications(ServicePathNotificationTypes.ServiceDelete,
399 input.getServiceName(), RpcStatusEx.Pending, TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
400 ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ);
401 // TODO add some flag rather than string
402 if (FAILED.equals(atozPowerTurndownOutput.getResult())) {
403 LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName);
404 sendNotifications(ServicePathNotificationTypes.ServiceDelete,
405 input.getServiceName(), RpcStatusEx.Failed,
406 "Service power turndown failed on A-to-Z path for service");
407 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
410 LOG.debug("Turning down power on Z-to-A path");
411 sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(),
412 RpcStatusEx.Pending, "Turning down power on Z-to-A path");
413 ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA);
414 // TODO add some flag rather than string
415 if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) {
416 LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName);
417 sendNotifications(ServicePathNotificationTypes.ServiceDelete,
418 input.getServiceName(), RpcStatusEx.Failed,
419 "Service power turndown failed on Z-to-A path for service");
420 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
423 } catch (InterruptedException | ExecutionException | TimeoutException e) {
424 LOG.error("Error while turning down power!", e);
425 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED,
428 // delete service path with renderer
429 LOG.debug("Deleting service path via renderer");
430 sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(),
431 RpcStatusEx.Pending, "Deleting service path via renderer");
432 deviceRenderer.deleteServicePath(servicePathInputDataAtoZ.getServicePathInput());
433 deviceRenderer.deleteServicePath(servicePathInputDataZtoA.getServicePathInput());
434 networkModelWavelengthService.freeWavelengths(pathDescription);
435 sendNotifications(ServicePathNotificationTypes.ServiceDelete, input.getServiceName(),
436 RpcStatusEx.Successful, OPERATION_SUCCESSFUL);
437 return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL);
444 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
445 value = "UPM_UNCALLED_PRIVATE_METHOD",
446 justification = "call in call() method")
447 private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData)
448 throws InterruptedException, ExecutionException, TimeoutException {
449 LOG.debug(TURNING_DOWN_POWER_ON_A_TO_Z_PATH_MSG);
450 Future<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
451 new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
452 return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
455 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
456 value = "UPM_UNCALLED_PRIVATE_METHOD",
457 justification = "call in call() method")
458 private Optional<PathDescription> getPathDescriptionFromDatastore(String serviceName) {
459 InstanceIdentifier<PathDescription> pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class)
460 .child(ServicePaths.class, new ServicePathsKey(serviceName)).child(PathDescription.class);
461 ReadTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction();
463 LOG.debug("Getting path description for service {}", serviceName);
464 return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID)
465 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
466 } catch (InterruptedException | ExecutionException | TimeoutException e) {
467 LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID,
469 return Optional.empty();
473 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
474 value = "UPM_UNCALLED_PRIVATE_METHOD",
475 justification = "call in call() method")
476 private List<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
477 ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
478 LOG.info(RENDERING_DEVICES_A_Z_MSG);
479 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
480 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
481 RENDERING_DEVICES_A_Z_MSG);
482 ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
483 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
484 ServicePathDirection.A_TO_Z));
486 LOG.info("Rendering devices Z-A");
487 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
488 servicePathDataZtoA.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
489 RENDERING_DEVICES_Z_A_MSG);
490 ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
491 this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
492 ServicePathDirection.Z_TO_A));
493 ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
494 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
496 List<DeviceRenderingResult> renderingResults = new ArrayList<>(2);
498 LOG.info("Waiting for A-Z and Z-A device renderers ...");
499 renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
500 } catch (InterruptedException | ExecutionException | TimeoutException e) {
501 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
502 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
503 servicePathDataAtoZ.getServicePathInput().getServiceName(), RpcStatusEx.Pending,
504 DEVICE_RENDERING_ROLL_BACK_MSG);
505 //FIXME we can't do rollback here, because we don't have rendering results.
506 return renderingResults;
509 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
510 ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(),
511 this.deviceRenderer));
512 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
513 ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(),
514 this.deviceRenderer));
515 return renderingResults;
518 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
519 value = "UPM_UNCALLED_PRIVATE_METHOD",
520 justification = "call in call() method")
521 private List<OtnDeviceRenderingResult> otnDeviceRendering(RollbackProcessor rollbackProcessor,
522 OtnServicePathInput otnServicePathAtoZ, OtnServicePathInput otnServicePathZtoA) {
523 LOG.info(RENDERING_DEVICES_A_Z_MSG);
524 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
525 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
526 RENDERING_DEVICES_A_Z_MSG);
527 ListenableFuture<OtnDeviceRenderingResult> atozrenderingFuture =
528 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathAtoZ));
530 LOG.info("Rendering devices Z-A");
531 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
532 otnServicePathZtoA.getServiceName(), RpcStatusEx.Pending,
533 RENDERING_DEVICES_Z_A_MSG);
534 ListenableFuture<OtnDeviceRenderingResult> ztoarenderingFuture =
535 this.executor.submit(new OtnDeviceRenderingTask(this.otnDeviceRenderer, otnServicePathZtoA));
536 ListenableFuture<List<OtnDeviceRenderingResult>> renderingCombinedFuture =
537 Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
539 List<OtnDeviceRenderingResult> otnRenderingResults = new ArrayList<>(2);
541 LOG.info("Waiting for A-Z and Z-A device renderers ...");
542 otnRenderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS);
543 } catch (InterruptedException | ExecutionException | TimeoutException e) {
544 LOG.warn(DEVICE_RENDERING_ROLL_BACK_MSG, e);
545 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
546 otnServicePathAtoZ.getServiceName(), RpcStatusEx.Pending,
547 DEVICE_RENDERING_ROLL_BACK_MSG);
548 //FIXME we can't do rollback here, because we don't have rendering results.
549 return otnRenderingResults;
552 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask",
553 ! otnRenderingResults.get(0).isSuccess(), otnRenderingResults.get(0).getRenderedNodeInterfaces(),
554 this.deviceRenderer));
555 rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask",
556 ! otnRenderingResults.get(1).isSuccess(), otnRenderingResults.get(1).getRenderedNodeInterfaces(),
557 this.deviceRenderer));
560 return otnRenderingResults;
564 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
565 value = "UPM_UNCALLED_PRIVATE_METHOD",
566 justification = "call in call() method")
567 private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ,
568 ServicePowerSetupInput powerSetupInputZtoA) {
569 LOG.info("Olm power setup A-Z");
570 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
571 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup A-Z");
572 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureAtoZ
573 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
575 LOG.info("OLM power setup Z-A");
576 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
577 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending, "Olm power setup Z-A");
578 ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
579 = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
580 ListenableFuture<List<OLMRenderingResult>> olmFutures =
581 Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
583 List<OLMRenderingResult> olmResults;
585 LOG.info("Waiting for A-Z and Z-A OLM power setup ...");
586 olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS);
587 } catch (InterruptedException | ExecutionException | TimeoutException e) {
588 LOG.warn(OLM_ROLL_BACK_MSG, e);
589 sendNotifications(ServicePathNotificationTypes.ServiceImplementationRequest,
590 powerSetupInputAtoZ.getServiceName(), RpcStatusEx.Pending,
592 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true,
593 this.olmService, powerSetupInputAtoZ));
594 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true,
595 this.olmService, powerSetupInputZtoA));
599 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(),
600 this.olmService, powerSetupInputAtoZ));
601 rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(),
602 this.olmService, powerSetupInputZtoA));
605 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
606 value = "UPM_UNCALLED_PRIVATE_METHOD",
607 justification = "call in call() method")
608 private boolean isServiceActivated(String nodeId, String tpId) {
609 LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId);
610 for (int i = 0; i < 3; i++) {
611 List<Measurements> measurements = getMeasurements(nodeId, tpId);
612 if ((measurements != null) && verifyPreFecBer(measurements)) {
614 } else if (measurements == null) {
615 LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId);
619 Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME);
620 } catch (InterruptedException ex) {
621 Thread.currentThread().interrupt();
625 LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId);
629 private List<Measurements> getMeasurements(String nodeId, String tp) {
630 GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder();
631 getPmIpBldr.setNodeId(nodeId);
632 getPmIpBldr.setGranularity(PmGranularity._15min);
633 ResourceIdentifierBuilder rsrcBldr = new ResourceIdentifierBuilder();
634 rsrcBldr.setResourceName(tp + "-OTU");
635 getPmIpBldr.setResourceIdentifier(rsrcBldr.build());
636 getPmIpBldr.setResourceType(ResourceTypeEnum.Interface);
639 Future<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
640 RpcResult<GetPmOutput> getPmRpcResult = getPmFuture.get();
641 GetPmOutput getPmOutput = getPmRpcResult.getResult();
642 if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) {
643 LOG.info("successfully finished calling OLM's get PM");
644 return getPmOutput.getMeasurements();
647 LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp);
650 } catch (ExecutionException | InterruptedException e) {
651 LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e);
657 private boolean verifyPreFecBer(List<Measurements> measurements) {
658 double preFecCorrectedErrors = Double.MIN_VALUE;
659 double fecUncorrectableBlocks = Double.MIN_VALUE;
661 for (Measurements measurement : measurements) {
662 if (measurement.getPmparameterName().equals("preFECCorrectedErrors")) {
663 preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue());
665 if (measurement.getPmparameterName().equals("FECUncorrectableBlocks")) {
666 fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue());
670 LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors,
671 fecUncorrectableBlocks);
673 if (fecUncorrectableBlocks > Double.MIN_VALUE) {
674 LOG.error("Data has uncorrectable errors, BER test failed");
677 double numOfBitsPerSecond = 112000000000d;
678 double threshold = 0.00002d;
679 double result = preFecCorrectedErrors / numOfBitsPerSecond;
680 LOG.info("PreFEC value is {}", Double.toString(result));
681 return result <= threshold;