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