Bug corrections in ServiceHandler
[transportpce.git] / servicehandler / src / main / java / org / opendaylight / transportpce / servicehandler / impl / ServicehandlerImpl.java
1 /*
2  * Copyright © 2017 Orange, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.transportpce.servicehandler.impl;
9
10 import java.time.OffsetDateTime;
11 import java.time.ZoneOffset;
12 import java.time.format.DateTimeFormatter;
13 import java.util.Optional;
14 import java.util.concurrent.ExecutionException;
15 import java.util.concurrent.Future;
16
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.transportpce.common.OperationResult;
21 import org.opendaylight.transportpce.common.ResponseCodes;
22 import org.opendaylight.transportpce.pce.service.PathComputationService;
23 import org.opendaylight.transportpce.renderer.provisiondevice.RendererServiceOperations;
24 import org.opendaylight.transportpce.servicehandler.ModelMappingUtils;
25 import org.opendaylight.transportpce.servicehandler.service.PCEServiceWrapper;
26 import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
27 import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperationsImpl;
28 import org.opendaylight.transportpce.servicehandler.validation.ServiceCreateValidation;
29 import org.opendaylight.transportpce.servicehandler.validation.checks.ComplianceCheckResult;
30 import org.opendaylight.transportpce.servicehandler.validation.checks.ServicehandlerCompliancyCheck;
31 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev170426.PathComputationRequestOutput;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev161014.RpcActions;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev161014.sdnc.request.header.SdncRequestHeaderBuilder;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.RpcStatus;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.State;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.EquipmentNotificationInput;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.EquipmentNotificationOutput;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.NetworkReOptimizationInput;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.NetworkReOptimizationOutput;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.OrgOpenroadmServiceService;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceCreateInput;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceCreateInputBuilder;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceCreateOutput;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceDeleteInput;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceDeleteInputBuilder;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceDeleteOutput;
47 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceFeasibilityCheckInput;
48 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceFeasibilityCheckOutput;
49 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceList;
50 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceReconfigureInput;
51 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceReconfigureOutput;
52 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceRerouteConfirmInput;
53 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceRerouteConfirmOutput;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceRerouteInput;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceRerouteOutput;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceRerouteOutputBuilder;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceRestorationInput;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceRestorationOutput;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceReversionInput;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceReversionOutput;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceRollInput;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceRollOutput;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.TempServiceCreateInput;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.TempServiceCreateOutput;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.TempServiceDeleteInput;
66 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.TempServiceDeleteOutput;
67 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.service.create.input.ServiceAEndBuilder;
68 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.service.create.input.ServiceZEndBuilder;
69 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.service.delete.input.ServiceDeleteReqInfo.TailRetention;
70 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.service.delete.input.ServiceDeleteReqInfoBuilder;
71 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.service.list.Services;
72 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.service.list.ServicesKey;
73 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestInput;
74 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
75 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
76 import org.opendaylight.yangtools.yang.common.RpcResult;
77 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
80
81
82 /**
83  * Top level service interface providing main OpenROADM controller services.
84  */
85 public class ServicehandlerImpl implements OrgOpenroadmServiceService {
86
87     private static final Logger LOG = LoggerFactory.getLogger(ServicehandlerImpl.class);
88
89     private DataBroker db;
90     private ServiceDataStoreOperations serviceDataStoreOperations;
91     private RendererServiceOperations rendererServiceOperations;
92     private PCEServiceWrapper pceServiceWrapper;
93
94     //TODO: remove private request fields as they are in global scope
95
96     public ServicehandlerImpl(DataBroker databroker, PathComputationService pathComputationService,
97                               RendererServiceOperations rendererServiceOperations) {
98         this.db = databroker;
99         this.rendererServiceOperations = rendererServiceOperations;
100         this.serviceDataStoreOperations = new ServiceDataStoreOperationsImpl(this.db);
101         this.serviceDataStoreOperations.initialize();
102         this.pceServiceWrapper = new PCEServiceWrapper(pathComputationService);
103     }
104
105     @Override
106     public Future<RpcResult<ServiceCreateOutput>> serviceCreate(ServiceCreateInput input) {
107         LOG.info("RPC service creation received");
108         // Validation
109         OperationResult validationResult = ServiceCreateValidation.validateServiceCreateRequest(input);
110         if (! validationResult.isSuccess()) {
111             LOG.warn("Aborting service create because validation of service create request failed: {}",
112                     validationResult.getResultMessage());
113             return ModelMappingUtils.createCreateServiceReply(input, ResponseCodes.FINAL_ACK_YES,
114                     validationResult.getResultMessage(), ResponseCodes.RESPONSE_FAILED);
115         }
116
117         // Starting service create operation
118         LOG.info("Commencing PCE");
119         //TODO: createService service status into datastore
120         PathComputationRequestOutput pceResponse = this.pceServiceWrapper.performPCE(input, true);
121         String pceResponseCode = pceResponse.getConfigurationResponseCommon().getResponseCode();
122         if (!ResponseCodes.RESPONSE_OK.equals(pceResponseCode)) {
123             LOG.info("PCE calculation failed {}", pceResponseCode);
124             return ModelMappingUtils.createCreateServiceReply(input, ResponseCodes.FINAL_ACK_YES,
125                     pceResponse.getConfigurationResponseCommon().getResponseMessage(), ResponseCodes.RESPONSE_FAILED);
126         }
127
128         LOG.info("PCE calculation done OK {}", pceResponseCode);
129
130         OperationResult operationResult = this.serviceDataStoreOperations.createService(input, pceResponse);
131         if (!operationResult.isSuccess()) {
132             String message = "Service status not updated in datastore !";
133             LOG.info(message);
134             return ModelMappingUtils.createCreateServiceReply(input, ResponseCodes.FINAL_ACK_YES, message,
135                     ResponseCodes.RESPONSE_FAILED);
136         }
137
138         OperationResult operationServicePathSaveResult = this.serviceDataStoreOperations.createServicePath(input,
139             pceResponse);
140         if (!operationServicePathSaveResult.isSuccess()) {
141             String message = "Service Path not updated in datastore !";
142             LOG.info(message);
143             return ModelMappingUtils.createCreateServiceReply(input, ResponseCodes.FINAL_ACK_YES, message,
144                     ResponseCodes.RESPONSE_FAILED);
145         }
146
147         ServiceImplementationRequestInput serviceImplementationRequest =
148                 ModelMappingUtils.createServiceImplementationRequest(input, pceResponse);
149         org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426
150             .ServiceImplementationRequestOutput serviceImplementationRequestOutput = this.rendererServiceOperations
151             .serviceImplementation(serviceImplementationRequest);
152         if (ResponseCodes.RESPONSE_OK
153                 .equals(serviceImplementationRequestOutput.getConfigurationResponseCommon().getResponseCode())) {
154             String message = "Service rendered successfully !";
155             LOG.info(message);
156             operationResult = this.serviceDataStoreOperations.modifyService(input.getServiceName(), State.InService,
157                     State.InService);
158             if (!operationResult.isSuccess()) {
159                 LOG.warn("Service status not updated in datastore !");
160             }
161             return ModelMappingUtils.createCreateServiceReply(input, ResponseCodes.FINAL_ACK_YES, message,
162                     ResponseCodes.RESPONSE_OK);
163         } else {
164             String message = "Service rendering has failed !";
165             LOG.warn(message);
166
167             OperationResult deleteServicePathOperationResult =
168                     this.serviceDataStoreOperations.deleteServicePath(input.getServiceName());
169             if (!deleteServicePathOperationResult.isSuccess()) {
170                 LOG.warn("Service path was not removed from datastore!");
171             }
172
173             OperationResult deleteServiceOperationResult =
174                     this.serviceDataStoreOperations.deleteService(input.getServiceName());
175             if (!deleteServiceOperationResult.isSuccess()) {
176                 LOG.warn("Service was not removed from datastore!");
177             }
178
179             return ModelMappingUtils.createCreateServiceReply(input, ResponseCodes.FINAL_ACK_YES, message,
180                     ResponseCodes.RESPONSE_FAILED);
181         }
182     }
183
184     @Override
185     public Future<RpcResult<ServiceDeleteOutput>> serviceDelete(ServiceDeleteInput input) {
186         LOG.info("RPC serviceDelete request received for {}", input.getServiceDeleteReqInfo().getServiceName());
187         String message = "";
188
189         /*
190          * Upon receipt of service-deleteService RPC, service header and sdnc-request
191          * header compliancy are verified.
192          */
193         LOG.info("checking Service Compliancy ...");
194         ComplianceCheckResult serviceHandlerCheckResult = ServicehandlerCompliancyCheck.check(
195                 input.getServiceDeleteReqInfo().getServiceName(),
196                 input.getSdncRequestHeader(), null, RpcActions.ServiceDelete, false, true);
197         if (serviceHandlerCheckResult.hasPassed()) {
198             LOG.info("Service compliant !");
199         } else {
200             LOG.info("Service is not compliant !");
201             return ModelMappingUtils
202                     .createDeleteServiceReply(input, ResponseCodes.FINAL_ACK_YES,
203                             "Service not compliant !", ResponseCodes.RESPONSE_FAILED);
204         }
205
206         //Check presence of service to be deleted
207         String serviceName = input.getServiceDeleteReqInfo().getServiceName();
208         Optional<Services> service = this.serviceDataStoreOperations.getService(serviceName);
209         if (!service.isPresent()) {
210             message = "Service '" + serviceName + "' does not exist in datastore";
211             LOG.error(message);
212             return ModelMappingUtils.createDeleteServiceReply(input, ResponseCodes.FINAL_ACK_YES,
213                     message, ResponseCodes.RESPONSE_FAILED);
214         }
215
216         LOG.debug("Service '{}' present in datastore !", serviceName);
217         org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceDeleteInput
218                 serviceDeleteInput = ModelMappingUtils.createServiceDeleteInput(input);
219         org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426
220             .ServiceDeleteOutput output = this.rendererServiceOperations.serviceDelete(serviceDeleteInput);
221
222         if (!ResponseCodes.RESPONSE_OK
223                 .equals(output.getConfigurationResponseCommon().getResponseCode())) {
224             message = "Service delete failed!";
225             return ModelMappingUtils.createDeleteServiceReply(input, ResponseCodes.FINAL_ACK_YES, message,
226                     ResponseCodes.RESPONSE_FAILED);
227         }
228
229         OperationResult deleteServicePathOperationResult =
230                 this.serviceDataStoreOperations.deleteServicePath(input.getServiceDeleteReqInfo().getServiceName());
231         if (!deleteServicePathOperationResult.isSuccess()) {
232             LOG.warn("Service path was not removed from datastore!");
233         }
234
235         OperationResult deleteServiceOperationResult =
236                 this.serviceDataStoreOperations.deleteService(input.getServiceDeleteReqInfo().getServiceName());
237         if (!deleteServiceOperationResult.isSuccess()) {
238             LOG.warn("Service was not removed from datastore!");
239         }
240
241         return ModelMappingUtils.createDeleteServiceReply(input, ResponseCodes.FINAL_ACK_YES,
242                 "Service delete was successful!", ResponseCodes.RESPONSE_OK);
243     }
244
245     @Override
246     public Future<RpcResult<ServiceFeasibilityCheckOutput>> serviceFeasibilityCheck(
247             ServiceFeasibilityCheckInput input) {
248         throw new UnsupportedOperationException("Not implemented yet");
249     }
250
251     @Override
252     public Future<RpcResult<ServiceReconfigureOutput>> serviceReconfigure(ServiceReconfigureInput input) {
253         throw new UnsupportedOperationException("Not implemented yet");
254     }
255
256     @Override
257     public Future<RpcResult<ServiceRestorationOutput>> serviceRestoration(ServiceRestorationInput input) {
258         throw new UnsupportedOperationException("Not implemented yet");
259     }
260
261     @Override
262     public Future<RpcResult<EquipmentNotificationOutput>> equipmentNotification(EquipmentNotificationInput input) {
263         // TODO Auto-generated method stub
264         return null;
265     }
266
267     @Override
268     public Future<RpcResult<ServiceRerouteConfirmOutput>> serviceRerouteConfirm(ServiceRerouteConfirmInput input) {
269         // TODO Auto-generated method stub
270         return null;
271     }
272
273     @Override
274     public Future<RpcResult<ServiceRerouteOutput>> serviceReroute(ServiceRerouteInput input) {
275         InstanceIdentifier<Services> servicesIID = InstanceIdentifier.create(ServiceList.class)
276                 .child(Services.class, new ServicesKey(input.getServiceName()));
277         ReadOnlyTransaction rtx = this.db.newReadOnlyTransaction();
278         Optional<Services> servicesObject;
279         try {
280             servicesObject = rtx.read(LogicalDatastoreType.OPERATIONAL, servicesIID).get().toJavaUtil();
281             if (servicesObject.isPresent()) {
282                 ServiceDeleteInputBuilder deleteInputBldr = new ServiceDeleteInputBuilder();
283                 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssxxx");
284                 OffsetDateTime offsetDateTime = OffsetDateTime.now(ZoneOffset.UTC);
285                 DateAndTime datetime = new DateAndTime(dtf.format(offsetDateTime));
286                 deleteInputBldr.setServiceDeleteReqInfo(new ServiceDeleteReqInfoBuilder()
287                     .setServiceName(input.getServiceName()).setDueDate(datetime)
288                     .setTailRetention(TailRetention.No).build());
289                 SdncRequestHeaderBuilder sdncBuilder = new SdncRequestHeaderBuilder();
290                 sdncBuilder.setNotificationUrl(servicesObject.get().getSdncRequestHeader().getNotificationUrl());
291                 sdncBuilder.setRequestId(servicesObject.get().getSdncRequestHeader().getRequestId());
292                 sdncBuilder.setRequestSystemId(servicesObject.get().getSdncRequestHeader().getRequestSystemId());
293                 sdncBuilder.setRpcAction(RpcActions.ServiceDelete);
294                 deleteInputBldr.setSdncRequestHeader(sdncBuilder.build());
295                 // Calling delete service
296                 serviceDelete(deleteInputBldr.build());
297                 // Calling create request now
298                 ServiceCreateInputBuilder serviceCreateBldr = new ServiceCreateInputBuilder();
299                 serviceCreateBldr.setServiceName(input.getServiceName() + 2);
300                 serviceCreateBldr.setCommonId(servicesObject.get().getCommonId());
301                 serviceCreateBldr.setConnectionType(servicesObject.get().getConnectionType());
302                 serviceCreateBldr.setCustomer(servicesObject.get().getCustomer());
303                 serviceCreateBldr.setCustomerContact(servicesObject.get().getCustomerContact());
304                 serviceCreateBldr.setDueDate(servicesObject.get().getDueDate());
305                 serviceCreateBldr.setEndDate(servicesObject.get().getEndDate());
306                 serviceCreateBldr.setHardConstraints(servicesObject.get().getHardConstraints());
307                 serviceCreateBldr.setNcCode(servicesObject.get().getNcCode());
308                 serviceCreateBldr.setNciCode(servicesObject.get().getNciCode());
309                 serviceCreateBldr.setOperatorContact(servicesObject.get().getOperatorContact());
310                 serviceCreateBldr.setSdncRequestHeader(servicesObject.get().getSdncRequestHeader());
311                 serviceCreateBldr.setSecondaryNciCode(servicesObject.get().getSecondaryNciCode());
312                 ServiceAEndBuilder serviceAendBuilder = new ServiceAEndBuilder(servicesObject.get().getServiceAEnd());
313                 serviceCreateBldr.setServiceAEnd(serviceAendBuilder.build());
314                 ServiceZEndBuilder serviceZendBuilder = new ServiceZEndBuilder(servicesObject.get().getServiceZEnd());
315                 serviceCreateBldr.setServiceZEnd(serviceZendBuilder.build());
316                 serviceCreateBldr.setSoftConstraints(servicesObject.get().getSoftConstraints());
317                 serviceCreate(serviceCreateBldr.build());
318                 ServiceRerouteOutputBuilder output = new ServiceRerouteOutputBuilder()
319                     .setHardConstraints(null).setSoftConstraints(null).setStatus(
320                     org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.RpcStatus.Successful)
321                     .setStatusMessage("Success");
322                 return RpcResultBuilder.success(output).buildFuture();
323             }
324         } catch (InterruptedException | ExecutionException | NullPointerException e) {
325             LOG.info("Exception caught" , e);
326         }
327         ServiceRerouteOutputBuilder output = new ServiceRerouteOutputBuilder()
328             .setHardConstraints(null).setSoftConstraints(null).setStatus(RpcStatus.Failed).setStatusMessage("Failure");
329
330         return RpcResultBuilder.success(output).buildFuture();
331         // return null;
332     }
333
334     @Override
335     public Future<RpcResult<ServiceReversionOutput>> serviceReversion(ServiceReversionInput input) {
336         // TODO Auto-generated method stub
337         return null;
338     }
339
340     @Override
341     public Future<RpcResult<ServiceRollOutput>> serviceRoll(ServiceRollInput input) {
342         // TODO Auto-generated method stub
343         return null;
344     }
345
346     @Override
347     public Future<RpcResult<NetworkReOptimizationOutput>> networkReOptimization(NetworkReOptimizationInput input) {
348         // TODO Auto-generated method stub
349         return null;
350     }
351
352     @Override
353     public Future<RpcResult<TempServiceDeleteOutput>> tempServiceDelete(TempServiceDeleteInput input) {
354         // TODO Auto-generated method stub
355         return null;
356     }
357
358     @Override
359     public Future<RpcResult<TempServiceCreateOutput>> tempServiceCreate(TempServiceCreateInput input) {
360         // TODO Auto-generated method stub
361         return null;
362     }
363
364 }