Implement Subnet Capability query functionality
[so.git] / mso-api-handlers / mso-api-handler-infra / src / main / java / org / onap / so / apihandlerinfra / Onap3gppServiceInstances.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2020 Wipro Limited.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.so.apihandlerinfra;
22
23 import java.sql.Timestamp;
24 import java.util.HashMap;
25 import java.util.UUID;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.function.Function;
32 import javax.ws.rs.Consumes;
33 import javax.ws.rs.DELETE;
34 import javax.ws.rs.GET;
35 import javax.ws.rs.POST;
36 import javax.ws.rs.PUT;
37 import javax.ws.rs.Path;
38 import javax.ws.rs.PathParam;
39 import javax.ws.rs.Produces;
40 import javax.ws.rs.container.ContainerRequestContext;
41 import javax.ws.rs.core.Context;
42 import javax.ws.rs.core.MediaType;
43 import javax.ws.rs.core.Response;
44 import org.apache.http.HttpStatus;
45 import org.onap.logging.filter.base.ErrorCode;
46 import org.onap.so.apihandler.camundabeans.CamundaResponse;
47 import org.onap.so.apihandler.common.CamundaClient;
48 import org.onap.so.apihandler.common.ErrorNumbers;
49 import org.onap.so.apihandler.common.RequestClientParameter;
50 import org.onap.so.apihandler.common.ResponseBuilder;
51 import org.onap.so.apihandler.common.ResponseHandler;
52 import org.onap.so.apihandlerinfra.exceptions.ApiException;
53 import org.onap.so.apihandlerinfra.exceptions.BPMNFailureException;
54 import org.onap.so.apihandlerinfra.exceptions.RequestDbFailureException;
55 import org.onap.so.apihandlerinfra.exceptions.ValidateException;
56 import org.onap.so.apihandlerinfra.logging.ErrorLoggerInfo;
57 import org.onap.so.apihandlerinfra.onap3gppserviceinstancebeans.ActivateOrDeactivate3gppService;
58 import org.onap.so.apihandlerinfra.onap3gppserviceinstancebeans.Allocate3gppService;
59 import org.onap.so.apihandlerinfra.onap3gppserviceinstancebeans.DeAllocate3gppService;
60 import org.onap.so.apihandlerinfra.onap3gppserviceinstancebeans.Modify3gppService;
61 import org.onap.so.apihandlerinfra.onap3gppserviceinstancebeans.QuerySubnetCapability;
62 import org.onap.so.apihandlerinfra.onap3gppserviceinstancebeans.SubnetTypes;
63 import org.onap.so.constants.Status;
64 import org.onap.so.db.catalog.beans.Service;
65 import org.onap.so.db.catalog.beans.ServiceRecipe;
66 import org.onap.so.db.catalog.client.CatalogDbClient;
67 import org.onap.so.logger.LogConstants;
68 import org.onap.so.logger.LoggingAnchor;
69 import org.onap.so.logger.MessageEnum;
70 import org.onap.so.serviceinstancebeans.ModelType;
71 import org.slf4j.Logger;
72 import org.slf4j.LoggerFactory;
73 import org.slf4j.MDC;
74 import org.springframework.beans.factory.annotation.Autowired;
75 import org.springframework.http.ResponseEntity;
76 import org.springframework.stereotype.Component;
77 import com.fasterxml.jackson.core.JsonProcessingException;
78 import com.fasterxml.jackson.databind.ObjectMapper;
79 import com.fasterxml.jackson.core.type.TypeReference;
80 import io.swagger.v3.oas.annotations.OpenAPIDefinition;
81 import io.swagger.v3.oas.annotations.Operation;
82 import io.swagger.v3.oas.annotations.info.Info;
83 import io.swagger.v3.oas.annotations.media.ArraySchema;
84 import io.swagger.v3.oas.annotations.media.Content;
85 import io.swagger.v3.oas.annotations.media.Schema;
86 import io.swagger.v3.oas.annotations.responses.ApiResponse;
87 import org.onap.so.db.request.beans.InfraActiveRequests;
88 import org.onap.so.db.request.client.RequestsDbClient;
89
90 @Component
91 @Path("/onap/so/infra/onap3gppServiceInstances")
92 @OpenAPIDefinition(info = @Info(title = "/onap/so/infra/onap3gppServiceInstances",
93         description = "API Requests for 3GPP Service Instances"))
94 public class Onap3gppServiceInstances {
95
96     private static final Logger logger = LoggerFactory.getLogger(Onap3gppServiceInstances.class);
97
98     private static final String MSO_PROP_APIHANDLER_INFRA = "MSO_PROP_APIHANDLER_INFRA";
99
100     private static final String END_OF_THE_TRANSACTION = "End of the transaction, the final response is: ";
101
102     private static final String SAVE_TO_DB = "save instance to db";
103
104     private static String uriPrefix = "/onap3gppServiceInstances/";
105
106     @Autowired
107     private MsoRequest msoRequest;
108
109     @Autowired
110     private CatalogDbClient catalogDbClient;
111
112     @Autowired
113     private RequestsDbClient requestsDbClient;
114
115     @Autowired
116     private RequestHandlerUtils requestHandlerUtils;
117
118     @Autowired
119     private ResponseBuilder builder;
120
121     @Autowired
122     private CamundaClient camundaClient;
123
124     @Autowired
125     private ResponseHandler responseHandler;
126
127     /**
128      * POST Requests for 3GPP Service create Instance on a version provided
129      *
130      * @throws ApiException
131      */
132
133     @POST
134     @Path("/{version:[vV][1]}/allocate")
135     @Consumes(MediaType.APPLICATION_JSON)
136     @Produces(MediaType.APPLICATION_JSON)
137     @Operation(description = "Create a 3GPP Service Instance on a version provided", responses = @ApiResponse(
138             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
139     public Response createServiceInstance(Allocate3gppService request, @PathParam("version") String version,
140             @Context ContainerRequestContext requestContext) throws ApiException {
141         String requestId = requestHandlerUtils.getRequestId(requestContext);
142         return processServiceInstanceRequest(request, Action.createInstance, version, requestId, null,
143                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
144     }
145
146     /**
147      * PUT Requests for 3GPP Service update Instance on a version provided
148      *
149      * @throws ApiException
150      */
151
152     @PUT
153     @Path("/{version:[vV][1]}/modify")
154     @Consumes(MediaType.APPLICATION_JSON)
155     @Produces(MediaType.APPLICATION_JSON)
156     @Operation(description = "Modify a 3GPP Service Instance on a version provided", responses = @ApiResponse(
157             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
158     public Response updateServiceInstance(Modify3gppService request, @PathParam("version") String version,
159             @Context ContainerRequestContext requestContext) throws ApiException {
160         String requestId = requestHandlerUtils.getRequestId(requestContext);
161         HashMap<String, String> instanceIdMap = new HashMap<>();
162         instanceIdMap.put("serviceInstanceId", request.getServiceInstanceID());
163         return updateServiceInstances(request, Action.updateInstance, version, requestId, instanceIdMap,
164                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
165     }
166
167     /**
168      * DELETE Requests for 3GPP Service delete Instance on a specified version
169      *
170      * @throws ApiException
171      */
172
173     @DELETE
174     @Path("/{version:[vV][1]}/deAllocate")
175     @Consumes(MediaType.APPLICATION_JSON)
176     @Produces(MediaType.APPLICATION_JSON)
177     @Operation(description = "Terminate/Deallocate a 3GPP Service Instance on a version provided",
178             responses = @ApiResponse(
179                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
180     public Response deleteServiceInstance(DeAllocate3gppService request, @PathParam("version") String version,
181             @Context ContainerRequestContext requestContext) throws ApiException {
182         String requestId = requestHandlerUtils.getRequestId(requestContext);
183         HashMap<String, String> instanceIdMap = new HashMap<>();
184         instanceIdMap.put("serviceInstanceId", request.getServiceInstanceID());
185         return deleteServiceInstances(request, Action.deleteInstance, version, requestId, instanceIdMap,
186                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
187     }
188
189     /**
190      * POST Requests for 3GPP Service Activate on a specified version
191      *
192      * @throws ApiException
193      */
194
195     @POST
196     @Path("/{version:[vV][1]}/activate")
197     @Consumes(MediaType.APPLICATION_JSON)
198     @Produces(MediaType.APPLICATION_JSON)
199     @Operation(description = "Activate a 3GPP Service Instance on a version provided", responses = @ApiResponse(
200             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
201     public Response activateServiceInstance(ActivateOrDeactivate3gppService request,
202             @PathParam("version") String version, @Context ContainerRequestContext requestContext) throws ApiException {
203         String requestId = requestHandlerUtils.getRequestId(requestContext);
204         HashMap<String, String> instanceIdMap = new HashMap<>();
205         instanceIdMap.put("serviceInstanceId", request.getServiceInstanceID());
206         return activateOrDeactivateServiceInstances(request, Action.activateInstance, version, requestId, instanceIdMap,
207                 requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
208     }
209
210     /**
211      * POST Requests for 3GPP Service DeActivate on a specified version
212      *
213      * @throws ApiException
214      */
215
216     @POST
217     @Path("/{version:[vV][1]}/deActivate")
218     @Consumes(MediaType.APPLICATION_JSON)
219     @Produces(MediaType.APPLICATION_JSON)
220     @Operation(description = "Deactivate a 3GPP Service Instance on a version provided", responses = @ApiResponse(
221             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
222     public Response deActivateServiceInstance(ActivateOrDeactivate3gppService request,
223             @PathParam("version") String version, @Context ContainerRequestContext requestContext) throws ApiException {
224         String requestId = requestHandlerUtils.getRequestId(requestContext);
225         HashMap<String, String> instanceIdMap = new HashMap<>();
226         instanceIdMap.put("serviceInstanceId", request.getServiceInstanceID());
227         return activateOrDeactivateServiceInstances(request, Action.deactivateInstance, version, requestId,
228                 instanceIdMap, requestHandlerUtils.getRequestUri(requestContext, uriPrefix));
229     }
230
231     /**
232      *
233      * GET requests for slice subnet capabilities on a specified version
234      *
235      * @param version
236      * @return
237      * @throws ApiException
238      */
239     @GET
240     @Path("/{version:[vV][1]}/subnetCapabilityQuery")
241     @Operation(description = "Provides subnet capability based on subnet types", responses = @ApiResponse(
242             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
243     @Produces(MediaType.APPLICATION_JSON)
244     @Consumes(MediaType.APPLICATION_JSON)
245     public Response getSliceSubnetCapabilities(QuerySubnetCapability request, @PathParam("version") String version)
246             throws ApiException {
247         logger.debug("Request received {}", request);
248         List<SubnetTypes> subnetTypes = request.getSubnetTypes();
249         return getSubnetCapabilities(subnetTypes, version);
250     }
251
252     /**
253      * Process allocate service request and send request to corresponding workflow
254      *
255      * @param request
256      * @param action
257      * @param version
258      * @return
259      * @throws ApiException
260      */
261     private Response processServiceInstanceRequest(Allocate3gppService request, Action action, String version,
262             String requestId, HashMap<String, String> instanceIdMap, String requestUri) throws ApiException {
263         String defaultServiceModelName = "COMMON_SS_DEFAULT";
264         String requestScope = ModelType.service.name();
265         String apiVersion = version.substring(1);
266         String serviceRequestJson = toString.apply(request);
267         if (serviceRequestJson != null) {
268             InfraActiveRequests currentActiveReq = createRequestObject(request, action, requestId, Status.IN_PROGRESS,
269                     requestScope, serviceRequestJson);
270             String instanceName = request.getName();
271             requestHandlerUtils.checkForDuplicateRequests(action, instanceIdMap, requestScope, currentActiveReq,
272                     instanceName);
273             try {
274                 requestsDbClient.save(currentActiveReq);
275             } catch (Exception e) {
276                 logger.error("Exception occurred", e);
277                 ErrorLoggerInfo errorLoggerInfo =
278                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
279                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
280                 throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(),
281                         HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
282                                 .errorInfo(errorLoggerInfo).build();
283             }
284
285             RecipeLookupResult recipeLookupResult;
286             try {
287                 recipeLookupResult =
288                         getServiceInstanceOrchestrationURI(request.getModelUuid(), action, defaultServiceModelName);
289             } catch (Exception e) {
290                 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ACCESS_EXC.toString(), MSO_PROP_APIHANDLER_INFRA,
291                         ErrorCode.AvailabilityError.getValue(), "Exception while communciate with Catalog DB", e);
292                 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
293                         MsoException.ServiceException, "No communication to catalog DB " + e.getMessage(),
294                         ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
295                 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
296                 return response;
297             }
298
299             if (recipeLookupResult == null) {
300                 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND.toString(),
301                         MSO_PROP_APIHANDLER_INFRA, ErrorCode.DataError.getValue(), "No recipe found in DB");
302                 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
303                         MsoException.ServiceException, "Recipe does not exist in catalog DB",
304                         ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null, version);
305                 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
306                 return response;
307             }
308
309             String serviceInstanceType = request.getSubscriptionServiceType();
310             RequestClientParameter parameter;
311             try {
312                 parameter = new RequestClientParameter.Builder().setRequestId(requestId).setBaseVfModule(false)
313                         .setRecipeTimeout(recipeLookupResult.getRecipeTimeout()).setRequestAction(action.name())
314                         .setServiceInstanceId(null).setServiceType(serviceInstanceType)
315                         .setRequestDetails(serviceRequestJson).setApiVersion(version).setALaCarte(false)
316                         .setRecipeParamXsd(recipeLookupResult.getRecipeParamXsd()).setApiVersion(apiVersion).build();
317             } catch (Exception e) {
318                 logger.error("Exception occurred", e);
319                 ErrorLoggerInfo errorLoggerInfo =
320                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.SchemaError)
321                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
322                 throw new ValidateException.Builder("Unable to generate RequestClientParamter object" + e.getMessage(),
323                         HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER).errorInfo(errorLoggerInfo)
324                                 .build();
325             }
326             return postBPELRequest(currentActiveReq, parameter, recipeLookupResult.getOrchestrationURI(), requestScope);
327         } else {
328             Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR,
329                     MsoException.ServiceException, "JsonProcessingException occurred - serviceRequestJson is null",
330                     ErrorNumbers.SVC_BAD_PARAMETER, null, version);
331             return response;
332         }
333     }
334
335     /**
336      * process modify service request and call corresponding workflow
337      *
338      * @param request
339      * @param action
340      * @param version
341      * @return
342      * @throws ApiException
343      */
344     private Response updateServiceInstances(Modify3gppService request, Action action, String version, String requestId,
345             HashMap<String, String> instanceIdMap, String requestUri) throws ApiException {
346         String defaultServiceModelName = "COMMON_SS_DEFAULT";
347         String requestScope = ModelType.service.name();
348         String apiVersion = version.substring(1);
349         String serviceRequestJson = toString.apply(request);
350         if (serviceRequestJson != null) {
351             InfraActiveRequests currentActiveReq = createRequestObject(request, action, requestId, Status.IN_PROGRESS,
352                     requestScope, serviceRequestJson);
353             String instanceName = request.getName();
354             requestHandlerUtils.checkForDuplicateRequests(action, instanceIdMap, requestScope, currentActiveReq,
355                     instanceName);
356             try {
357                 requestsDbClient.save(currentActiveReq);
358             } catch (Exception e) {
359                 logger.error("Exception occurred", e);
360                 ErrorLoggerInfo errorLoggerInfo =
361                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
362                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
363                 throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(),
364                         HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
365                                 .errorInfo(errorLoggerInfo).build();
366             }
367
368             RecipeLookupResult recipeLookupResult;
369             try {
370                 recipeLookupResult = getServiceInstanceOrchestrationURI(null, action, defaultServiceModelName);
371             } catch (Exception e) {
372                 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ACCESS_EXC.toString(), MSO_PROP_APIHANDLER_INFRA,
373                         ErrorCode.AvailabilityError.getValue(), "Exception while communciate with Catalog DB", e);
374                 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
375                         MsoException.ServiceException, "No communication to catalog DB " + e.getMessage(),
376                         ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
377                 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
378                 return response;
379             }
380
381             if (recipeLookupResult == null) {
382                 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND.toString(),
383                         MSO_PROP_APIHANDLER_INFRA, ErrorCode.DataError.getValue(), "No recipe found in DB");
384                 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
385                         MsoException.ServiceException, "Recipe does not exist in catalog DB",
386                         ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null, version);
387                 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
388                 return response;
389             }
390
391             String serviceInstanceType = request.getSubscriptionServiceType();
392             String serviceInstanceId = request.getServiceInstanceID();
393             RequestClientParameter parameter;
394             try {
395                 parameter = new RequestClientParameter.Builder().setRequestId(requestId).setBaseVfModule(false)
396                         .setRecipeTimeout(recipeLookupResult.getRecipeTimeout()).setRequestAction(action.name())
397                         .setServiceInstanceId(serviceInstanceId).setServiceType(serviceInstanceType)
398                         .setRequestDetails(serviceRequestJson).setApiVersion(version).setALaCarte(false)
399                         .setRecipeParamXsd(recipeLookupResult.getRecipeParamXsd()).setApiVersion(apiVersion).build();
400             } catch (Exception e) {
401                 logger.error("Exception occurred", e);
402                 ErrorLoggerInfo errorLoggerInfo =
403                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.SchemaError)
404                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
405                 throw new ValidateException.Builder("Unable to generate RequestClientParamter object" + e.getMessage(),
406                         HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER).errorInfo(errorLoggerInfo)
407                                 .build();
408             }
409             return postBPELRequest(currentActiveReq, parameter, recipeLookupResult.getOrchestrationURI(), requestScope);
410
411         } else {
412             Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR,
413                     MsoException.ServiceException, "JsonProcessingException occurred - serviceRequestJson is null",
414                     ErrorNumbers.SVC_BAD_PARAMETER, null, version);
415             return response;
416         }
417     }
418
419     /**
420      * process delete service instance request and call corresponding workflow
421      *
422      * @param request
423      * @param action
424      * @param version
425      * @return
426      * @throws ApiException
427      */
428     private Response deleteServiceInstances(DeAllocate3gppService request, Action action, String version,
429             String requestId, HashMap<String, String> instanceIdMap, String requestUri) throws ApiException {
430         String defaultServiceModelName = "COMMON_SS_DEFAULT";
431         String requestScope = ModelType.service.name();
432         String apiVersion = version.substring(1);
433         String serviceRequestJson = toString.apply(request);
434         if (serviceRequestJson != null) {
435             InfraActiveRequests currentActiveReq = createRequestObject(request, action, requestId, Status.IN_PROGRESS,
436                     requestScope, serviceRequestJson);
437             requestHandlerUtils.checkForDuplicateRequests(action, instanceIdMap, requestScope, currentActiveReq, null);
438             try {
439                 requestsDbClient.save(currentActiveReq);
440             } catch (Exception e) {
441                 logger.error("Exception occurred", e);
442                 ErrorLoggerInfo errorLoggerInfo =
443                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
444                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
445                 throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(),
446                         HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
447                                 .errorInfo(errorLoggerInfo).build();
448             }
449             RecipeLookupResult recipeLookupResult;
450             try {
451                 recipeLookupResult = getServiceInstanceOrchestrationURI(null, action, defaultServiceModelName);
452             } catch (Exception e) {
453                 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ACCESS_EXC.toString(), MSO_PROP_APIHANDLER_INFRA,
454                         ErrorCode.AvailabilityError.getValue(), "Exception while communciate with Catalog DB", e);
455                 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
456                         MsoException.ServiceException, "No communication to catalog DB " + e.getMessage(),
457                         ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
458                 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
459                 return response;
460             }
461
462             if (recipeLookupResult == null) {
463                 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND.toString(),
464                         MSO_PROP_APIHANDLER_INFRA, ErrorCode.DataError.getValue(), "No recipe found in DB");
465                 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
466                         MsoException.ServiceException, "Recipe does not exist in catalog DB",
467                         ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null, version);
468                 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
469                 return response;
470             }
471
472             String serviceInstanceType = request.getSubscriptionServiceType();
473             String serviceInstanceId = request.getServiceInstanceID();
474             RequestClientParameter parameter;
475             try {
476                 parameter = new RequestClientParameter.Builder().setRequestId(requestId).setBaseVfModule(false)
477                         .setRecipeTimeout(recipeLookupResult.getRecipeTimeout()).setRequestAction(action.name())
478                         .setServiceInstanceId(serviceInstanceId).setServiceType(serviceInstanceType)
479                         .setRequestDetails(serviceRequestJson).setApiVersion(version).setALaCarte(false)
480                         .setRecipeParamXsd(recipeLookupResult.getRecipeParamXsd()).setApiVersion(apiVersion).build();
481             } catch (Exception e) {
482                 logger.error("Exception occurred", e);
483                 ErrorLoggerInfo errorLoggerInfo =
484                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.SchemaError)
485                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
486                 throw new ValidateException.Builder("Unable to generate RequestClientParamter object" + e.getMessage(),
487                         HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER).errorInfo(errorLoggerInfo)
488                                 .build();
489             }
490             return postBPELRequest(currentActiveReq, parameter, recipeLookupResult.getOrchestrationURI(), requestScope);
491         } else {
492             Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR,
493                     MsoException.ServiceException, "JsonProcessingException occurred - serviceRequestJson is null",
494                     ErrorNumbers.SVC_BAD_PARAMETER, null, version);
495             return response;
496         }
497     }
498
499     /**
500      * process activate/deactivate service request and call corresponding workflow
501      *
502      * @param request the request object for activate/deactivate service
503      * @param action the action for the service
504      * @param version
505      * @return
506      * @throws ApiException
507      */
508     private Response activateOrDeactivateServiceInstances(ActivateOrDeactivate3gppService request, Action action,
509             String version, String requestId, HashMap<String, String> instanceIdMap, String requestUri)
510             throws ApiException {
511         String defaultServiceModelName = "COMMON_SS_DEFAULT";
512         String requestScope = ModelType.service.name();
513         String apiVersion = version.substring(1);
514         String serviceRequestJson = toString.apply(request);
515         if (serviceRequestJson != null) {
516             InfraActiveRequests currentActiveReq = createRequestObject(request, action, requestId, Status.IN_PROGRESS,
517                     requestScope, serviceRequestJson);
518             if (action == Action.activateInstance) {
519                 requestHandlerUtils.checkForDuplicateRequests(action, instanceIdMap, requestScope, currentActiveReq,
520                         request.getServiceInstanceID());
521             } else {
522                 requestHandlerUtils.checkForDuplicateRequests(action, instanceIdMap, requestScope, currentActiveReq,
523                         null);
524             }
525             try {
526                 requestsDbClient.save(currentActiveReq);
527             } catch (Exception e) {
528                 logger.error("Exception occurred", e);
529                 ErrorLoggerInfo errorLoggerInfo =
530                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
531                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
532                 throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(),
533                         HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
534                                 .errorInfo(errorLoggerInfo).build();
535             }
536             RecipeLookupResult recipeLookupResult;
537             try {
538                 recipeLookupResult = getServiceInstanceOrchestrationURI(null, action, defaultServiceModelName);
539             } catch (Exception e) {
540                 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ACCESS_EXC.toString(), MSO_PROP_APIHANDLER_INFRA,
541                         ErrorCode.AvailabilityError.getValue(), "Exception while communciate with Catalog DB", e);
542                 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
543                         MsoException.ServiceException, "No communication to catalog DB " + e.getMessage(),
544                         ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
545                 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
546                 return response;
547             }
548
549             if (recipeLookupResult == null) {
550                 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND.toString(),
551                         MSO_PROP_APIHANDLER_INFRA, ErrorCode.DataError.getValue(), "No recipe found in DB");
552                 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
553                         MsoException.ServiceException, "Recipe does not exist in catalog DB",
554                         ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null, version);
555                 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
556                 return response;
557             }
558
559             String serviceInstanceType = request.getSubscriptionServiceType();
560             String serviceInstanceId = request.getServiceInstanceID();
561             RequestClientParameter parameter;
562             try {
563                 parameter = new RequestClientParameter.Builder().setRequestId(requestId).setBaseVfModule(false)
564                         .setRecipeTimeout(recipeLookupResult.getRecipeTimeout()).setRequestAction(action.name())
565                         .setServiceInstanceId(serviceInstanceId).setServiceType(serviceInstanceType)
566                         .setRequestDetails(serviceRequestJson).setApiVersion(version).setALaCarte(false)
567                         .setRecipeParamXsd(recipeLookupResult.getRecipeParamXsd()).setApiVersion(apiVersion).build();
568             } catch (Exception e) {
569                 logger.error("Exception occurred", e);
570                 ErrorLoggerInfo errorLoggerInfo =
571                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.SchemaError)
572                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
573                 throw new ValidateException.Builder("Unable to generate RequestClientParamter object" + e.getMessage(),
574                         HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER).errorInfo(errorLoggerInfo)
575                                 .build();
576             }
577             return postBPELRequest(currentActiveReq, parameter, recipeLookupResult.getOrchestrationURI(), requestScope);
578         } else {
579             Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR,
580                     MsoException.ServiceException, "JsonProcessingException occurred - serviceRequestJson is null",
581                     ErrorNumbers.SVC_BAD_PARAMETER, null, version);
582             return response;
583         }
584     }
585
586     // To be implemented for fetching Subnet capabilities
587     private Response getSubnetCapabilities(List<SubnetTypes> subnetTypes, String version) throws ApiException {
588         ObjectMapper oMapper = new ObjectMapper();
589         InputStream inputStream = TypeReference.class.getResourceAsStream("/subnetCapability.json");
590         Map<String, Object> subnetCapability = new HashMap<>();
591         try {
592             subnetCapability = oMapper.readValue(inputStream, Map.class);
593         } catch (Exception e) {
594             logger.debug("Exception while reading subnet capability value from json", e);
595         }
596         Map<String, Object> responseMap = new HashMap<>();
597         for (SubnetTypes value : subnetTypes) {
598             if (subnetCapability.containsKey(value.toString())) {
599                 responseMap.put(value.toString(), subnetCapability.get(value.toString()));
600             }
601         }
602         String response = null;
603         try {
604             response = oMapper.writeValueAsString(responseMap);
605         } catch (JsonProcessingException e) {
606             logger.debug("Exception while converting subnet capability object to String {}", e);
607         }
608         return builder.buildResponse(HttpStatus.SC_OK, null, response, version);
609     }
610
611     /**
612      * Getting recipes from catalogDb
613      *
614      * @param serviceModelUUID the service model version uuid
615      * @param action the action for the service
616      * @param defaultServiceModelName default service name
617      * @return the service recipe result
618      */
619     private RecipeLookupResult getServiceInstanceOrchestrationURI(String serviceModelUUID, Action action,
620             String defaultServiceModelName) {
621
622         RecipeLookupResult recipeLookupResult = getServiceURI(serviceModelUUID, action, defaultServiceModelName);
623
624         if (recipeLookupResult != null) {
625             logger.debug("Orchestration URI is: " + recipeLookupResult.getOrchestrationURI() + ", recipe Timeout is: "
626                     + Integer.toString(recipeLookupResult.getRecipeTimeout()));
627         } else {
628             logger.debug("No matching recipe record found");
629         }
630         return recipeLookupResult;
631     }
632
633     /**
634      * Getting recipes from catalogDb If Service recipe is not set, use default recipe, if set , use special recipe.
635      *
636      * @param serviceModelUUID the service version uuid
637      * @param action the action of the service.
638      * @param defaultServiceModelName default service name
639      * @return the service recipe result.
640      */
641     private RecipeLookupResult getServiceURI(String serviceModelUUID, Action action, String defaultServiceModelName) {
642
643         Service defaultServiceRecord =
644                 catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
645         // set recipe as default generic recipe
646         ServiceRecipe recipe =
647                 catalogDbClient.getFirstByServiceModelUUIDAndAction(defaultServiceRecord.getModelUUID(), action.name());
648         // check the service special recipe
649         if (null != serviceModelUUID && !serviceModelUUID.isEmpty()) {
650             ServiceRecipe serviceSpecialRecipe =
651                     catalogDbClient.getFirstByServiceModelUUIDAndAction(serviceModelUUID, action.name());
652             if (null != serviceSpecialRecipe) {
653                 // set service special recipe.
654                 recipe = serviceSpecialRecipe;
655             }
656         }
657
658         if (recipe == null) {
659             return null;
660         }
661         return new RecipeLookupResult(recipe.getOrchestrationUri(), recipe.getRecipeTimeout(), recipe.getParamXsd());
662
663     }
664
665     Function<Object, String> toString = serviceRequest -> {
666         ObjectMapper mapper = new ObjectMapper();
667         String requestAsString = null;
668         try {
669             requestAsString = mapper.writeValueAsString(serviceRequest);
670         } catch (JsonProcessingException e) {
671             logger.debug("Exception while converting service request object to String {}", e);
672         }
673         return requestAsString;
674     };
675
676     public InfraActiveRequests createRequestObject(Object request, Action action, String requestId, Status status,
677             String requestScope, String requestJson) {
678         InfraActiveRequests aq = new InfraActiveRequests();
679         try {
680             String networkType = null;
681             String serviceInstanceName = null;
682             String serviceInstanceId = null;
683             if (action.name().equals("createInstance")) {
684                 networkType = ((Allocate3gppService) request).getNetworkType();
685                 serviceInstanceName = ((Allocate3gppService) request).getName();
686                 aq.setServiceInstanceName(serviceInstanceName);
687             } else if (action.name().equals("updateInstance")) {
688                 networkType = ((Modify3gppService) request).getNetworkType();
689                 serviceInstanceName = ((Modify3gppService) request).getName();
690                 serviceInstanceId = ((Modify3gppService) request).getServiceInstanceID();
691                 aq.setServiceInstanceName(serviceInstanceName);
692                 aq.setServiceInstanceId(serviceInstanceId);
693             } else if (action.name().equals("deleteInstance")) {
694                 networkType = ((DeAllocate3gppService) request).getNetworkType();
695                 serviceInstanceId = ((DeAllocate3gppService) request).getServiceInstanceID();
696                 aq.setServiceInstanceId(serviceInstanceId);
697             } else if (action.name().equals("activateInstance")) {
698                 networkType = ((ActivateOrDeactivate3gppService) request).getNetworkType();
699                 serviceInstanceId = ((ActivateOrDeactivate3gppService) request).getServiceInstanceID();
700                 aq.setServiceInstanceName(serviceInstanceId); // setting serviceInstanceId as serviceInstanceName
701                                                               // -->serviceInstanceName shouldn't be null for action -
702                                                               // activateInstance duplicateRequests check
703                 aq.setServiceInstanceId(serviceInstanceId);
704             } else if (action.name().equals("deactivateInstance")) {
705                 networkType = ((ActivateOrDeactivate3gppService) request).getNetworkType();
706                 serviceInstanceId = ((ActivateOrDeactivate3gppService) request).getServiceInstanceID();
707                 aq.setServiceInstanceId(serviceInstanceId);
708             }
709
710             aq.setRequestId(requestId);
711             aq.setRequestAction(action.toString());
712             aq.setRequestUrl(MDC.get(LogConstants.HTTP_URL));
713             Timestamp startTimeStamp = new Timestamp(System.currentTimeMillis());
714             aq.setStartTime(startTimeStamp);
715             aq.setRequestScope(requestScope);
716             aq.setRequestBody(requestJson);
717             aq.setRequestStatus(status.toString());
718             aq.setLastModifiedBy(Constants.MODIFIED_BY_APIHANDLER);
719             aq.setNetworkType(networkType);
720         } catch (Exception e) {
721             logger.error("Exception when creation record request", e);
722
723             if (!status.equals(Status.FAILED)) {
724                 throw e;
725             }
726         }
727         return aq;
728     }
729
730     private Response postBPELRequest(InfraActiveRequests currentActiveReq, RequestClientParameter parameter,
731             String orchestrationURI, String requestScope) throws ApiException {
732         ResponseEntity<String> response =
733                 requestHandlerUtils.postRequest(currentActiveReq, parameter, orchestrationURI);
734         logger.debug("BPEL response : " + response);
735         int bpelStatus = responseHandler.setStatus(response.getStatusCodeValue());
736         String jsonResponse;
737         try {
738             responseHandler.acceptedResponse(response);
739             CamundaResponse camundaResponse = responseHandler.getCamundaResponse(response);
740             String responseBody = camundaResponse.getResponse();
741             if ("Success".equalsIgnoreCase(camundaResponse.getMessage())) {
742                 jsonResponse = responseBody;
743             } else {
744                 BPMNFailureException bpmnException =
745                         new BPMNFailureException.Builder(String.valueOf(bpelStatus) + responseBody, bpelStatus,
746                                 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).build();
747                 requestHandlerUtils.updateStatus(currentActiveReq, Status.FAILED, bpmnException.getMessage());
748                 throw bpmnException;
749             }
750         } catch (ApiException e) {
751             requestHandlerUtils.updateStatus(currentActiveReq, Status.FAILED, e.getMessage());
752             throw e;
753         }
754         return builder.buildResponse(HttpStatus.SC_ACCEPTED, parameter.getRequestId(), jsonResponse,
755                 parameter.getApiVersion());
756     }
757 }
758
759