2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
6 * ================================================================================
7 * Modifications Copyright (c) 2019 Samsung
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
23 package org.onap.so.apihandlerinfra;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
30 import java.util.Optional;
31 import java.util.UUID;
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.core.MediaType;
41 import javax.ws.rs.core.Response;
42 import org.apache.http.HttpStatus;
43 import org.json.JSONObject;
44 import org.onap.aai.domain.yang.v16.ServiceInstance;
45 import org.onap.aaiclient.client.aai.AAIResourcesClient;
46 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri;
47 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
48 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder;
49 import org.onap.logging.filter.base.ErrorCode;
50 import org.onap.so.apihandler.camundabeans.CamundaResponse;
51 import org.onap.so.apihandler.common.CamundaClient;
52 import org.onap.so.apihandler.common.ErrorNumbers;
53 import org.onap.so.apihandler.common.RequestClientParameter;
54 import org.onap.so.apihandler.common.ResponseBuilder;
55 import org.onap.so.apihandler.common.ResponseHandler;
56 import org.onap.so.apihandlerinfra.e2eserviceinstancebeans.CompareModelsRequest;
57 import org.onap.so.apihandlerinfra.e2eserviceinstancebeans.E2EServiceInstanceDeleteRequest;
58 import org.onap.so.apihandlerinfra.e2eserviceinstancebeans.E2EServiceInstanceRequest;
59 import org.onap.so.apihandlerinfra.e2eserviceinstancebeans.E2EServiceInstanceScaleRequest;
60 import org.onap.so.apihandlerinfra.e2eserviceinstancebeans.E2ESliceServiceActivateRequest;
61 import org.onap.so.apihandlerinfra.e2eserviceinstancebeans.GetE2EServiceInstanceResponse;
62 import org.onap.so.apihandlerinfra.exceptions.ApiException;
63 import org.onap.so.apihandlerinfra.exceptions.BPMNFailureException;
64 import org.onap.so.apihandlerinfra.exceptions.ValidateException;
65 import org.onap.so.apihandlerinfra.logging.ErrorLoggerInfo;
66 import org.onap.so.constants.Status;
67 import org.onap.so.db.catalog.beans.Service;
68 import org.onap.so.db.catalog.beans.ServiceRecipe;
69 import org.onap.so.db.catalog.client.CatalogDbClient;
70 import org.onap.so.db.request.beans.OperationStatus;
71 import org.onap.so.db.request.client.RequestsDbClient;
72 import org.onap.so.logger.LoggingAnchor;
73 import org.onap.so.logger.MessageEnum;
74 import org.onap.so.serviceinstancebeans.ModelInfo;
75 import org.onap.so.serviceinstancebeans.ModelType;
76 import org.onap.so.serviceinstancebeans.RequestDetails;
77 import org.onap.so.serviceinstancebeans.RequestInfo;
78 import org.onap.so.serviceinstancebeans.RequestParameters;
79 import org.onap.so.serviceinstancebeans.ServiceInstancesRequest;
80 import org.onap.so.serviceinstancebeans.SubscriberInfo;
81 import org.slf4j.Logger;
82 import org.slf4j.LoggerFactory;
83 import org.springframework.beans.factory.annotation.Autowired;
84 import org.springframework.http.ResponseEntity;
85 import org.springframework.stereotype.Component;
86 import com.fasterxml.jackson.databind.ObjectMapper;
87 import io.swagger.v3.oas.annotations.OpenAPIDefinition;
88 import io.swagger.v3.oas.annotations.Operation;
89 import io.swagger.v3.oas.annotations.info.Info;
90 import io.swagger.v3.oas.annotations.media.ArraySchema;
91 import io.swagger.v3.oas.annotations.media.Content;
92 import io.swagger.v3.oas.annotations.media.Schema;
93 import io.swagger.v3.oas.annotations.responses.ApiResponse;
96 @Path("/onap/so/infra/e2eServiceInstances")
97 @OpenAPIDefinition(info = @Info(title = "/onap/so/infra/e2eServiceInstances",
98 description = "API Requests for E2E Service Instances"))
100 public class E2EServiceInstances {
102 private HashMap<String, String> instanceIdMap = new HashMap<>();
103 private static final Logger logger = LoggerFactory.getLogger(E2EServiceInstances.class);
105 private static final String MSO_PROP_APIHANDLER_INFRA = "MSO_PROP_APIHANDLER_INFRA";
107 private static final String END_OF_THE_TRANSACTION = "End of the transaction, the final response is: ";
109 private static final String SERVICE_ID = "serviceId";
112 private MsoRequest msoRequest;
115 private RequestsDbClient requestsDbClient;
118 private CatalogDbClient catalogDbClient;
121 private ResponseBuilder builder;
124 private CamundaClient camundaClient;
127 private ResponseHandler responseHandler;
130 * POST Requests for E2E Service create Instance on a version provided
132 * @throws ApiException
136 @Path("/{version:[vV][3-5]}")
137 @Consumes(MediaType.APPLICATION_JSON)
138 @Produces(MediaType.APPLICATION_JSON)
139 @Operation(description = "Create an E2E Service Instance on a version provided", responses = @ApiResponse(
140 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
141 public Response createE2EServiceInstance(String request, @PathParam("version") String version) throws ApiException {
143 return processE2EserviceInstances(request, Action.createInstance, null, version);
147 * PUT Requests for E2E Service update Instance on a version provided
149 * @throws ApiException
153 @Path("/{version:[vV][3-5]}/{serviceId}")
154 @Consumes(MediaType.APPLICATION_JSON)
155 @Produces(MediaType.APPLICATION_JSON)
156 @Operation(description = "Update an E2E Service Instance on a version provided and serviceId",
157 responses = @ApiResponse(
158 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
159 public Response updateE2EServiceInstance(String request, @PathParam("version") String version,
160 @PathParam("serviceId") String serviceId) throws ApiException {
162 instanceIdMap.put(SERVICE_ID, serviceId);
164 return updateE2EserviceInstances(request, Action.updateInstance, version);
168 * DELETE Requests for E2E Service delete Instance on a specified version and serviceId
170 * @throws ApiException
174 @Path("/{version:[vV][3-5]}/{serviceId}")
175 @Consumes(MediaType.APPLICATION_JSON)
176 @Produces(MediaType.APPLICATION_JSON)
177 @Operation(description = "Delete E2E Service Instance on a specified version and serviceId",
178 responses = @ApiResponse(
179 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
180 public Response deleteE2EServiceInstance(String request, @PathParam("version") String version,
181 @PathParam(SERVICE_ID) String serviceId) throws ApiException {
183 instanceIdMap.put(SERVICE_ID, serviceId);
185 return deleteE2EserviceInstances(request, Action.deleteInstance, instanceIdMap, version);
189 * Activate Requests for 5G slice Service on a specified version and serviceId
191 * @throws ApiException
195 @Path("/{version:[vV][3-5]}/{serviceId}/{operationType}")
196 @Consumes(MediaType.APPLICATION_JSON)
197 @Produces(MediaType.APPLICATION_JSON)
198 @Operation(description = "Activate 5G slice Service on a specified version and serviceId", responses = @ApiResponse(
199 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
200 public Response Activate5GSliceServiceInstance(String request, @PathParam("version") String version,
201 @PathParam("operationType") String operationType, @PathParam(SERVICE_ID) String serviceId)
202 throws ApiException {
203 if (operationType.equals("activate")) {
204 instanceIdMap.put("operationType", "activation");
206 instanceIdMap.put("operationType", "deactivation");
208 instanceIdMap.put(SERVICE_ID, serviceId);
209 return Activate5GSliceServiceInstances(request, Action.activateInstance, instanceIdMap, version);
213 @Path("/{version:[vV][3-5]}/{serviceId}/operations/{operationId}")
214 @Operation(description = "Find e2eServiceInstances Requests for a given serviceId and operationId",
215 responses = @ApiResponse(
216 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
217 @Produces(MediaType.APPLICATION_JSON)
218 public Response getE2EServiceInstances(@PathParam(SERVICE_ID) String serviceId,
219 @PathParam("version") String version, @PathParam("operationId") String operationId) {
220 return getE2EServiceInstance(serviceId, operationId, version);
224 * Scale Requests for E2E Service scale Instance on a specified version
226 * @throws ApiException
230 @Path("/{version:[vV][3-5]}/{serviceId}/scale")
231 @Consumes(MediaType.APPLICATION_JSON)
232 @Produces(MediaType.APPLICATION_JSON)
233 @Operation(description = "Scale E2E Service Instance on a specified version", responses = @ApiResponse(
234 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
235 public Response scaleE2EServiceInstance(String request, @PathParam("version") String version,
236 @PathParam(SERVICE_ID) String serviceId) throws ApiException {
238 logger.debug("------------------scale begin------------------");
239 instanceIdMap.put(SERVICE_ID, serviceId);
240 return scaleE2EserviceInstances(request, Action.scaleInstance, version);
244 * GET Requests for Comparing model of service instance with target version
246 * @throws ApiException
250 @Path("/{version:[vV][3-5]}/{serviceId}/modeldifferences")
251 @Consumes(MediaType.APPLICATION_JSON)
252 @Produces(MediaType.APPLICATION_JSON)
254 description = "Find added and deleted resources of target model for the e2eserviceInstance on a given serviceId ",
255 responses = @ApiResponse(
256 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
257 public Response compareModelwithTargetVersion(String request, @PathParam("serviceId") String serviceId,
258 @PathParam("version") String version) throws ApiException {
260 instanceIdMap.put(SERVICE_ID, serviceId);
262 return compareModelwithTargetVersion(request, Action.compareModel, instanceIdMap, version);
265 private Response compareModelwithTargetVersion(String requestJSON, Action action,
266 HashMap<String, String> instanceIdMap, String version) throws ApiException {
268 String requestId = UUID.randomUUID().toString();
270 CompareModelsRequest e2eCompareModelReq;
272 ObjectMapper mapper = new ObjectMapper();
274 e2eCompareModelReq = mapper.readValue(requestJSON, CompareModelsRequest.class);
276 } catch (Exception e) {
278 logger.debug("Mapping of request to JSON object failed : ", e);
279 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_REQUEST,
280 MsoException.ServiceException, "Mapping of request to JSON object failed. " + e.getMessage(),
281 ErrorNumbers.SVC_BAD_PARAMETER, null, version);
282 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_REQUEST_VALIDATION_ERROR.toString(),
283 MSO_PROP_APIHANDLER_INFRA, ErrorCode.SchemaError.getValue(), requestJSON, e);
284 logger.debug(END_OF_THE_TRANSACTION + response.getEntity().toString());
289 return runCompareModelBPMWorkflow(e2eCompareModelReq, requestJSON, requestId, action, version);
293 private Response runCompareModelBPMWorkflow(CompareModelsRequest e2eCompareModelReq, String requestJSON,
294 String requestId, Action action, String version) throws ApiException {
296 // Define RecipeLookupResult info here instead of query DB for efficiency
297 String workflowUrl = "/mso/async/services/CompareModelofE2EServiceInstance";
298 int recipeTimeout = 180;
300 String bpmnRequest = null;
301 RequestClientParameter postParam = null;
303 JSONObject jjo = new JSONObject(requestJSON);
304 bpmnRequest = jjo.toString();
305 String serviceId = instanceIdMap.get(SERVICE_ID);
306 String serviceType = e2eCompareModelReq.getServiceType();
307 postParam = new RequestClientParameter.Builder().setRequestId(requestId).setBaseVfModule(false)
308 .setRecipeTimeout(recipeTimeout).setRequestAction(action.name()).setServiceInstanceId(serviceId)
309 .setServiceType(serviceType).setRequestDetails(bpmnRequest).setALaCarte(false).build();
310 } catch (Exception e) {
311 Response resp = msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_GATEWAY,
312 MsoException.ServiceException, "Failed calling bpmn " + e.getMessage(),
313 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
314 logger.error("", MessageEnum.APIH_BPEL_COMMUNICATE_ERROR, MSO_PROP_APIHANDLER_INFRA, "", "",
315 ErrorCode.AvailabilityError, "Exception while communicate with BPMN engine", e);
316 logger.debug(END_OF_THE_TRANSACTION + resp.getEntity().toString());
319 return postRequest(workflowUrl, postParam, version);
322 private Response getE2EServiceInstance(String serviceId, String operationId, String version) {
324 GetE2EServiceInstanceResponse e2eServiceResponse = new GetE2EServiceInstanceResponse();
326 String apiVersion = version.substring(1);
328 OperationStatus operationStatus;
331 operationStatus = requestsDbClient.getOneByServiceIdAndOperationId(serviceId, operationId);
332 } catch (Exception e) {
333 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ACCESS_EXC.toString(), MSO_PROP_APIHANDLER_INFRA,
334 ErrorCode.AvailabilityError.getValue(),
335 "Exception while communciate with Request DB - Infra Request Lookup", e);
337 msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND, MsoException.ServiceException,
338 e.getMessage(), ErrorNumbers.NO_COMMUNICATION_TO_REQUESTS_DB, null, version);
339 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
344 if (operationStatus == null) {
345 Response resp = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NO_CONTENT,
346 MsoException.ServiceException, "E2E serviceId " + serviceId + " is not found in DB",
347 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, null, version);
348 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_BPEL_COMMUNICATE_ERROR.toString(),
349 MSO_PROP_APIHANDLER_INFRA, ErrorCode.BusinessProcessError.getValue(),
350 "Null response from RequestDB when searching by serviceId");
351 logger.debug(END_OF_THE_TRANSACTION + resp.getEntity());
356 e2eServiceResponse.setOperation(operationStatus);
358 return builder.buildResponse(HttpStatus.SC_OK, null, e2eServiceResponse, apiVersion);
361 private Response Activate5GSliceServiceInstances(String requestJSON, Action action,
362 HashMap<String, String> instanceIdMap, String version) throws ApiException {
363 // TODO should be a new one or the same service instance Id
364 E2ESliceServiceActivateRequest e2eActReq;
366 ObjectMapper mapper = new ObjectMapper();
368 e2eActReq = mapper.readValue(requestJSON, E2ESliceServiceActivateRequest.class);
370 } catch (Exception e) {
372 logger.debug("Mapping of request to JSON object failed : ", e);
373 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_REQUEST,
374 MsoException.ServiceException, "Mapping of request to JSON object failed. " + e.getMessage(),
375 ErrorNumbers.SVC_BAD_PARAMETER, null, version);
376 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_REQUEST_VALIDATION_ERROR.toString(),
377 MSO_PROP_APIHANDLER_INFRA, ErrorCode.SchemaError.getValue(), requestJSON, e);
378 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
382 String requestId = UUID.randomUUID().toString();
383 RecipeLookupResult recipeLookupResult;
385 // TODO Get the service template model version uuid from AAI.
386 String modelVersionId = null;
387 AAIResourcesClient client = new AAIResourcesClient();
388 AAIResourceUri url = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business()
389 .customer(e2eActReq.getGlobalSubscriberId()).serviceSubscription(e2eActReq.getServiceType())
390 .serviceInstance(instanceIdMap.get(SERVICE_ID)));
391 Optional<ServiceInstance> serviceInstanceOpt = client.get(ServiceInstance.class, url);
392 if (serviceInstanceOpt.isPresent()) {
393 modelVersionId = serviceInstanceOpt.get().getModelVersionId();
395 recipeLookupResult = getServiceInstanceOrchestrationURI(modelVersionId, action);
396 } catch (Exception e) {
397 logger.error(MessageEnum.APIH_DB_ACCESS_EXC.toString(), MSO_PROP_APIHANDLER_INFRA,
398 ErrorCode.AvailabilityError.getValue(), "Exception while communciate with Catalog DB", e);
400 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
401 MsoException.ServiceException, "No communication to catalog DB " + e.getMessage(),
402 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
404 msoRequest.createErrorRequestRecord(Status.FAILED, requestId,
405 "Exception while communciate with " + "Catalog DB", action, ModelType.service.name(), requestJSON,
407 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
410 if (recipeLookupResult == null) {
411 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND.toString(),
412 MSO_PROP_APIHANDLER_INFRA, ErrorCode.DataError.getValue(), "No recipe found in DB");
413 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
414 MsoException.ServiceException, "Recipe does not exist in catalog DB",
415 ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null, version);
417 msoRequest.createErrorRequestRecord(Status.FAILED, requestId, "Recipe does not exist in catalog DB", action,
418 ModelType.service.name(), requestJSON, null, null);
419 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
423 String bpmnRequest = null;
424 RequestClientParameter postParam = null;
427 JSONObject jjo = new JSONObject(requestJSON);
428 jjo.put("operationId", requestId);
429 bpmnRequest = jjo.toString();
430 String serviceId = instanceIdMap.get(SERVICE_ID);
431 String operationType = instanceIdMap.get("operationType");
432 String serviceInstanceType = e2eActReq.getServiceType();
433 postParam = new RequestClientParameter.Builder().setRequestId(requestId).setBaseVfModule(false)
434 .setRecipeTimeout(recipeLookupResult.getRecipeTimeout()).setRequestAction(action.name())
435 .setServiceInstanceId(serviceId).setOperationType(operationType).setServiceType(serviceInstanceType)
436 .setRequestDetails(bpmnRequest).setApiVersion(version).setALaCarte(false)
437 .setRecipeParamXsd(recipeLookupResult.getRecipeParamXsd()).build();
438 } catch (Exception e) {
439 Response resp = msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_GATEWAY,
440 MsoException.ServiceException, "Failed calling bpmn " + e.getMessage(),
441 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
442 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_BPEL_COMMUNICATE_ERROR.toString(),
443 MSO_PROP_APIHANDLER_INFRA, ErrorCode.AvailabilityError.getValue(),
444 "Exception while communicate with BPMN engine");
445 logger.debug("End of the transaction, the final response is: " + resp.getEntity());
448 return postRequest(recipeLookupResult.getOrchestrationURI(), postParam, version);
451 private Response deleteE2EserviceInstances(String requestJSON, Action action, HashMap<String, String> instanceIdMap,
452 String version) throws ApiException {
453 // TODO should be a new one or the same service instance Id
454 E2EServiceInstanceDeleteRequest e2eDelReq;
456 ObjectMapper mapper = new ObjectMapper();
458 e2eDelReq = mapper.readValue(requestJSON, E2EServiceInstanceDeleteRequest.class);
460 } catch (Exception e) {
462 logger.debug("Mapping of request to JSON object failed : ", e);
463 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_REQUEST,
464 MsoException.ServiceException, "Mapping of request to JSON object failed. " + e.getMessage(),
465 ErrorNumbers.SVC_BAD_PARAMETER, null, version);
466 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_REQUEST_VALIDATION_ERROR.toString(),
467 MSO_PROP_APIHANDLER_INFRA, ErrorCode.SchemaError.getValue(), requestJSON, e);
468 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
472 String requestId = UUID.randomUUID().toString();
473 RecipeLookupResult recipeLookupResult;
475 // TODO Get the service template model version uuid from AAI.
476 String modelVersionId = null;
477 AAIResourcesClient client = new AAIResourcesClient();
478 AAIResourceUri url = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business()
479 .customer(e2eDelReq.getGlobalSubscriberId()).serviceSubscription(e2eDelReq.getServiceType())
480 .serviceInstance(instanceIdMap.get(SERVICE_ID)));
481 Optional<ServiceInstance> serviceInstanceOpt = client.get(ServiceInstance.class, url);
482 if (serviceInstanceOpt.isPresent()) {
483 modelVersionId = serviceInstanceOpt.get().getModelVersionId();
485 recipeLookupResult = getServiceInstanceOrchestrationURI(modelVersionId, action);
486 } catch (Exception e) {
487 logger.error(MessageEnum.APIH_DB_ACCESS_EXC.toString(), MSO_PROP_APIHANDLER_INFRA,
488 ErrorCode.AvailabilityError.getValue(), "Exception while communciate with Catalog DB", e);
490 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
491 MsoException.ServiceException, "No communication to catalog DB " + e.getMessage(),
492 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
494 msoRequest.createErrorRequestRecord(Status.FAILED, requestId,
495 "Exception while communciate with " + "Catalog DB", action, ModelType.service.name(), requestJSON,
497 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
500 if (recipeLookupResult == null) {
501 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND.toString(),
502 MSO_PROP_APIHANDLER_INFRA, ErrorCode.DataError.getValue(), "No recipe found in DB");
503 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
504 MsoException.ServiceException, "Recipe does not exist in catalog DB",
505 ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null, version);
507 msoRequest.createErrorRequestRecord(Status.FAILED, requestId, "Recipe does not exist in catalog DB", action,
508 ModelType.service.name(), requestJSON, null, null);
509 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
512 String bpmnRequest = null;
513 RequestClientParameter clientParam = null;
515 JSONObject jjo = new JSONObject(requestJSON);
516 jjo.put("operationId", requestId);
517 bpmnRequest = jjo.toString();
518 String serviceId = instanceIdMap.get(SERVICE_ID);
519 String serviceInstanceType = e2eDelReq.getServiceType();
520 clientParam = new RequestClientParameter.Builder().setRequestId(requestId).setBaseVfModule(false)
521 .setRecipeTimeout(recipeLookupResult.getRecipeTimeout()).setRequestAction(action.name())
522 .setServiceInstanceId(serviceId).setServiceType(serviceInstanceType).setRequestDetails(bpmnRequest)
523 .setApiVersion(version).setALaCarte(false).setRecipeParamXsd(recipeLookupResult.getRecipeParamXsd())
525 } catch (Exception e) {
526 Response resp = msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_GATEWAY,
527 MsoException.ServiceException, "Failed calling bpmn " + e.getMessage(),
528 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
529 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_BPEL_COMMUNICATE_ERROR.toString(),
530 MSO_PROP_APIHANDLER_INFRA, ErrorCode.AvailabilityError.getValue(),
531 "Exception while communicate with BPMN engine");
532 logger.debug("End of the transaction, the final response is: " + resp.getEntity());
536 return postRequest(recipeLookupResult.getOrchestrationURI(), clientParam, version);
539 private Response updateE2EserviceInstances(String requestJSON, Action action, String version) throws ApiException {
541 String requestId = UUID.randomUUID().toString();
542 E2EServiceInstanceRequest e2eSir;
543 String serviceId = instanceIdMap.get(SERVICE_ID);
545 ObjectMapper mapper = new ObjectMapper();
547 e2eSir = mapper.readValue(requestJSON, E2EServiceInstanceRequest.class);
549 } catch (Exception e) {
551 logger.debug("Mapping of request to JSON object failed : ", e);
552 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_REQUEST,
553 MsoException.ServiceException, "Mapping of request to JSON object failed. " + e.getMessage(),
554 ErrorNumbers.SVC_BAD_PARAMETER, null, version);
555 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_REQUEST_VALIDATION_ERROR.toString(),
556 MSO_PROP_APIHANDLER_INFRA, ErrorCode.SchemaError.getValue(), requestJSON, e);
557 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
561 ServiceInstancesRequest sir = mapReqJsonToSvcInstReq(e2eSir, requestJSON);
562 sir.getRequestDetails().getRequestParameters().setaLaCarte(true);
564 parseRequest(sir, instanceIdMap, action, version, requestJSON, false, requestId);
565 } catch (Exception e) {
566 logger.debug("Validation failed: ", e);
568 msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_REQUEST, MsoException.ServiceException,
569 "Error parsing request. " + e.getMessage(), ErrorNumbers.SVC_BAD_PARAMETER, null, version);
570 if (requestId != null) {
571 logger.debug("Logging failed message to the database");
573 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_REQUEST_VALIDATION_ERROR.toString(),
574 MSO_PROP_APIHANDLER_INFRA, ErrorCode.SchemaError.getValue(), requestJSON, e);
575 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
579 RecipeLookupResult recipeLookupResult;
581 recipeLookupResult = getServiceInstanceOrchestrationURI(e2eSir.getService().getServiceUuid(), action);
582 } catch (Exception e) {
583 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ACCESS_EXC.toString(), MSO_PROP_APIHANDLER_INFRA,
584 ErrorCode.AvailabilityError.getValue(), "Exception while communciate with Catalog DB", e);
585 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
586 MsoException.ServiceException, "No communication to catalog DB " + e.getMessage(),
587 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
589 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
594 if (recipeLookupResult == null) {
595 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND.toString(),
596 MSO_PROP_APIHANDLER_INFRA, ErrorCode.DataError.getValue(), "No recipe found in DB");
597 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
598 MsoException.ServiceException, "Recipe does not exist in catalog DB",
599 ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null, version);
600 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
605 String serviceInstanceType = e2eSir.getService().getServiceType();
606 String sirRequestJson = convertToString(sir);
607 RequestClientParameter postParam = new RequestClientParameter.Builder().setRequestId(requestId)
608 .setBaseVfModule(false).setRecipeTimeout(recipeLookupResult.getRecipeTimeout())
609 .setRequestAction(action.name()).setServiceInstanceId(serviceId).setServiceType(serviceInstanceType)
610 .setRequestDetails(sirRequestJson).setApiVersion(version).setALaCarte(false)
611 .setRecipeParamXsd(recipeLookupResult.getRecipeParamXsd()).build();
613 return postRequest(recipeLookupResult.getOrchestrationURI(), postParam, version);
616 private Response processE2EserviceInstances(String requestJSON, Action action,
617 HashMap<String, String> instanceIdMap, String version) throws ApiException {
619 String requestId = UUID.randomUUID().toString();
620 E2EServiceInstanceRequest e2eSir;
622 MsoRequest msoRequest = new MsoRequest();
623 ObjectMapper mapper = new ObjectMapper();
625 e2eSir = mapper.readValue(requestJSON, E2EServiceInstanceRequest.class);
627 } catch (Exception e) {
629 logger.debug("Mapping of request to JSON object failed : ", e);
630 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_REQUEST,
631 MsoException.ServiceException, "Mapping of request to JSON object failed. " + e.getMessage(),
632 ErrorNumbers.SVC_BAD_PARAMETER, null, version);
633 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_REQUEST_VALIDATION_ERROR.toString(),
634 MSO_PROP_APIHANDLER_INFRA, ErrorCode.SchemaError.getValue(), requestJSON, e);
635 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
639 ServiceInstancesRequest sir = mapReqJsonToSvcInstReq(e2eSir, requestJSON);
640 sir.getRequestDetails().getRequestParameters().setaLaCarte(true);
642 parseRequest(sir, instanceIdMap, action, version, requestJSON, false, requestId);
643 } catch (Exception e) {
644 logger.debug("Validation failed: ", e);
646 msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_REQUEST, MsoException.ServiceException,
647 "Error parsing request. " + e.getMessage(), ErrorNumbers.SVC_BAD_PARAMETER, null, version);
648 if (requestId != null) {
649 logger.debug("Logging failed message to the database");
651 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_REQUEST_VALIDATION_ERROR.toString(),
652 MSO_PROP_APIHANDLER_INFRA, ErrorCode.SchemaError.getValue(), requestJSON, e);
653 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
657 RecipeLookupResult recipeLookupResult;
659 recipeLookupResult = getServiceInstanceOrchestrationURI(e2eSir.getService().getServiceUuid(), action);
660 } catch (Exception e) {
661 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ACCESS_EXC.toString(), MSO_PROP_APIHANDLER_INFRA,
662 ErrorCode.AvailabilityError.getValue(), "Exception while communciate with Catalog DB", e);
663 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
664 MsoException.ServiceException, "No communication to catalog DB " + e.getMessage(),
665 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
666 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
670 if (recipeLookupResult == null) {
671 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND.toString(),
672 MSO_PROP_APIHANDLER_INFRA, ErrorCode.DataError.getValue(), "No recipe found in DB");
673 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
674 MsoException.ServiceException, "Recipe does not exist in catalog DB",
675 ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null, version);
676 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
680 String serviceInstanceType = e2eSir.getService().getServiceType();
682 String serviceId = e2eSir.getService().getServiceId();
683 String sirRequestJson = convertToString(sir);
684 RequestClientParameter parameter = new RequestClientParameter.Builder().setRequestId(requestId)
685 .setBaseVfModule(false).setRecipeTimeout(recipeLookupResult.getRecipeTimeout())
686 .setRequestAction(action.name()).setServiceInstanceId(serviceId).setServiceType(serviceInstanceType)
687 .setRequestDetails(sirRequestJson).setApiVersion(version).setALaCarte(false)
688 .setRecipeParamXsd(recipeLookupResult.getRecipeParamXsd()).build();
690 return postRequest(recipeLookupResult.getOrchestrationURI(), parameter, version);
693 private Response scaleE2EserviceInstances(String requestJSON, Action action, String version) throws ApiException {
695 String requestId = UUID.randomUUID().toString();
696 E2EServiceInstanceScaleRequest e2eScaleReq;
698 ObjectMapper mapper = new ObjectMapper();
700 e2eScaleReq = mapper.readValue(requestJSON, E2EServiceInstanceScaleRequest.class);
702 } catch (Exception e) {
704 logger.debug("Mapping of request to JSON object failed : ", e);
705 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_REQUEST,
706 MsoException.ServiceException, "Mapping of request to JSON object failed. " + e.getMessage(),
707 ErrorNumbers.SVC_BAD_PARAMETER, null, version);
708 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_REQUEST_VALIDATION_ERROR.toString(),
709 MSO_PROP_APIHANDLER_INFRA, ErrorCode.SchemaError.getValue(), requestJSON, e);
710 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
714 RecipeLookupResult recipeLookupResult;
716 // TODO Get the service template model version uuid from AAI.
717 recipeLookupResult = getServiceInstanceOrchestrationURI(null, action);
718 } catch (Exception e) {
719 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ACCESS_EXC.toString(), MSO_PROP_APIHANDLER_INFRA,
720 ErrorCode.AvailabilityError.getValue(), "Exception while communciate with Catalog DB", e);
722 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
723 MsoException.ServiceException, "No communication to catalog DB " + e.getMessage(),
724 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
726 msoRequest.createErrorRequestRecord(Status.FAILED, requestId,
727 "No communication to catalog DB " + e.getMessage(), action, ModelType.service.name(), requestJSON,
729 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
732 if (recipeLookupResult == null) {
733 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND.toString(),
734 MSO_PROP_APIHANDLER_INFRA, ErrorCode.DataError.getValue(), "No recipe found in DB");
736 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_NOT_FOUND,
737 MsoException.ServiceException, "Recipe does not exist in catalog DB",
738 ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null, version);
739 msoRequest.createErrorRequestRecord(Status.FAILED, requestId, "No recipe found in DB", action,
740 ModelType.service.name(), requestJSON, null, null);
741 logger.debug(END_OF_THE_TRANSACTION + response.getEntity());
744 String bpmnRequest = null;
745 RequestClientParameter postParam = null;
747 JSONObject jjo = new JSONObject(requestJSON);
748 jjo.put("operationId", requestId);
749 bpmnRequest = jjo.toString();
750 String serviceId = instanceIdMap.get(SERVICE_ID);
751 String serviceInstanceType = e2eScaleReq.getService().getServiceType();
752 postParam = new RequestClientParameter.Builder().setRequestId(requestId).setBaseVfModule(false)
753 .setRecipeTimeout(recipeLookupResult.getRecipeTimeout()).setRequestAction(action.name())
754 .setServiceInstanceId(serviceId).setServiceType(serviceInstanceType).setRequestDetails(bpmnRequest)
755 .setApiVersion(version).setALaCarte(false).setRecipeParamXsd(recipeLookupResult.getRecipeParamXsd())
757 } catch (Exception e) {
758 Response resp = msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_GATEWAY,
759 MsoException.ServiceException, "Failed creating bpmnRequest " + e.getMessage(),
760 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
762 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_BPEL_COMMUNICATE_ERROR.toString(),
763 MSO_PROP_APIHANDLER_INFRA, ErrorCode.AvailabilityError.getValue(),
764 "Exception while creating bpmnRequest", e);
765 logger.debug(END_OF_THE_TRANSACTION + resp.getEntity());
768 return postRequest(recipeLookupResult.getOrchestrationURI(), postParam, version);
771 protected Response postRequest(String orchestrationURI, RequestClientParameter postParam, String version)
772 throws ApiException {
773 ResponseEntity<String> response = null;
775 response = camundaClient.post(postParam, orchestrationURI);
776 } catch (BPMNFailureException e) {
777 Response resp = msoRequest.buildServiceErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR,
778 MsoException.ServiceException, "Failed calling bpmn " + e.getMessage(),
779 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
780 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_BPEL_COMMUNICATE_ERROR.toString(),
781 MSO_PROP_APIHANDLER_INFRA, ErrorCode.AvailabilityError.getValue(),
782 "Exception while communicate with BPMN engine");
783 logger.debug(END_OF_THE_TRANSACTION + resp.getEntity());
785 } catch (Exception e) {
786 Response resp = msoRequest.buildServiceErrorResponse(HttpStatus.SC_BAD_GATEWAY,
787 MsoException.ServiceException, "Failed calling bpmn " + e.getMessage(),
788 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null, version);
789 logger.error(LoggingAnchor.FOUR, MessageEnum.APIH_BPEL_COMMUNICATE_ERROR.toString(),
790 MSO_PROP_APIHANDLER_INFRA, ErrorCode.AvailabilityError.getValue(),
791 "Exception while communicate with BPMN engine");
792 logger.debug(END_OF_THE_TRANSACTION + resp.getEntity());
795 return bpelStatusUpdate(response, version);
798 private Response bpelStatusUpdate(ResponseEntity<String> responseEntity, String version) throws ApiException {
799 String apiVersion = version.substring(1);
800 responseHandler.acceptedResponse(responseEntity);
801 CamundaResponse camundaResponse = responseHandler.getCamundaResponse(responseEntity);
802 String response = camundaResponse.getResponse();
803 logger.debug(END_OF_THE_TRANSACTION + response);
804 return builder.buildResponse(HttpStatus.SC_ACCEPTED, null, response, apiVersion);
808 * Getting recipes from catalogDb
810 * @param serviceModelUUID the service model version uuid
811 * @param action the action for the service
812 * @return the service recipe result
814 private RecipeLookupResult getServiceInstanceOrchestrationURI(String serviceModelUUID, Action action) {
816 RecipeLookupResult recipeLookupResult = getServiceURI(serviceModelUUID, action);
818 if (recipeLookupResult != null) {
819 logger.debug("Orchestration URI is: " + recipeLookupResult.getOrchestrationURI() + ", recipe Timeout is: "
820 + Integer.toString(recipeLookupResult.getRecipeTimeout()));
822 logger.debug("No matching recipe record found");
824 return recipeLookupResult;
828 * Getting recipes from catalogDb If Service recipe is not set, use default recipe, if set , use special recipe.
830 * @param serviceModelUUID the service version uuid
831 * @param action the action of the service.
832 * @return the service recipe result.
834 private RecipeLookupResult getServiceURI(String serviceModelUUID, Action action) {
836 String defaultServiceModelName = "UUI_DEFAULT";
838 Service defaultServiceRecord =
839 catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
840 // set recipe as default generic recipe
841 ServiceRecipe recipe =
842 catalogDbClient.getFirstByServiceModelUUIDAndAction(defaultServiceRecord.getModelUUID(), action.name());
843 // check the service special recipe
844 if (null != serviceModelUUID && !serviceModelUUID.isEmpty()) {
845 ServiceRecipe serviceSpecialRecipe =
846 catalogDbClient.getFirstByServiceModelUUIDAndAction(serviceModelUUID, action.name());
847 if (null != serviceSpecialRecipe) {
848 // set service special recipe.
849 recipe = serviceSpecialRecipe;
853 if (recipe == null) {
856 return new RecipeLookupResult(recipe.getOrchestrationUri(), recipe.getRecipeTimeout(), recipe.getParamXsd());
861 * Converting E2EServiceInstanceRequest to ServiceInstanceRequest and passing it to camunda engine.
866 private ServiceInstancesRequest mapReqJsonToSvcInstReq(E2EServiceInstanceRequest e2eSir, String requestJSON) {
868 ServiceInstancesRequest sir = new ServiceInstancesRequest();
870 RequestDetails requestDetails = new RequestDetails();
871 ModelInfo modelInfo = new ModelInfo();
874 modelInfo.setModelInvariantId(e2eSir.getService().getServiceInvariantUuid());
876 // modelNameVersionId
877 modelInfo.setModelNameVersionId(e2eSir.getService().getServiceUuid());
879 // String modelInfoValue =
880 // e2eSir.getService().getParameters().getNodeTemplateName();
881 // String[] arrayOfInfo = modelInfoValue.split(":");
882 // String modelName = arrayOfInfo[0];
883 // String modelVersion = arrayOfInfo[1];
885 // TODO: To ensure, if we dont get the values from the UUI
886 String modelName = "voLTE";
887 String modelVersion = "1.0";
889 modelInfo.setModelName(modelName);
892 modelInfo.setModelVersion(modelVersion);
895 modelInfo.setModelType(ModelType.service);
897 // setting modelInfo to requestDetails
898 requestDetails.setModelInfo(modelInfo);
900 SubscriberInfo subscriberInfo = new SubscriberInfo();
902 // globalsubscriberId
903 subscriberInfo.setGlobalSubscriberId(e2eSir.getService().getGlobalSubscriberId());
905 // setting subscriberInfo to requestDetails
906 requestDetails.setSubscriberInfo(subscriberInfo);
908 RequestInfo requestInfo = new RequestInfo();
911 requestInfo.setInstanceName(e2eSir.getService().getName());
914 requestInfo.setSource("UUI");
917 requestInfo.setSuppressRollback(true);
919 // setting requestInfo to requestDetails
920 requestDetails.setRequestInfo(requestInfo);
922 RequestParameters requestParameters = new RequestParameters();
924 // subscriptionServiceType
925 requestParameters.setSubscriptionServiceType("MOG");
928 List<Map<String, Object>> userParamList = new ArrayList<>();
929 Map<String, Object> userParamMap = new HashMap<>();
930 // complete json request updated in the camunda
931 userParamMap.put("UUIRequest", requestJSON);
932 userParamMap.put("ServiceInstanceName", e2eSir.getService().getName());
935 userParamList.add(userParamMap);
936 requestParameters.setUserParams(userParamList);
938 // setting requestParameters to requestDetails
939 requestDetails.setRequestParameters(requestParameters);
941 sir.setRequestDetails(requestDetails);
947 private void parseRequest(ServiceInstancesRequest sir, HashMap<String, String> instanceIdMap, Action action,
948 String version, String requestJSON, Boolean aLaCarte, String requestId) throws ValidateException {
949 int reqVersion = Integer.parseInt(version.substring(1));
951 msoRequest.parse(sir, instanceIdMap, action, version, requestJSON, reqVersion, aLaCarte);
952 } catch (Exception e) {
953 ErrorLoggerInfo errorLoggerInfo =
954 new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
955 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
956 ValidateException validateException =
957 new ValidateException.Builder("Error parsing request: " + e.getMessage(), HttpStatus.SC_BAD_REQUEST,
958 ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
960 msoRequest.createErrorRequestRecord(Status.FAILED, requestId, validateException.getMessage(), action,
961 ModelType.service.name(), requestJSON, null, null);
963 throw validateException;
967 private String convertToString(ServiceInstancesRequest sir) {
968 String returnString = null;
969 // converting to string
970 ObjectMapper mapper = new ObjectMapper();
972 returnString = mapper.writeValueAsString(sir);
973 } catch (IOException e) {
974 logger.debug("Exception while converting ServiceInstancesRequest object to string", e);