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