From 6e9f3c472f75ae226f489db060b2f12f6b6e551c Mon Sep 17 00:00:00 2001 From: Seshu-Kumar-M <seshu.kumar.m@huawei.com> Date: Fri, 15 Sep 2017 15:23:17 +0530 Subject: Service for VoLTE usecase IssueId:SO-135 Change-Id: I7cd247400c91a4a9d2fa9b10b917d1657f27c361 Signed-off-by: Seshu-Kumar-M <seshu.kumar.m@huawei.com> --- .../mso/apihandlerinfra/E2EServiceInstances.java | 438 +++++++++++++++++++++ 1 file changed, 438 insertions(+) create mode 100644 mso-api-handlers/mso-api-handler-infra/src/main/java/org/openecomp/mso/apihandlerinfra/E2EServiceInstances.java (limited to 'mso-api-handlers/mso-api-handler-infra/src/main/java') diff --git a/mso-api-handlers/mso-api-handler-infra/src/main/java/org/openecomp/mso/apihandlerinfra/E2EServiceInstances.java b/mso-api-handlers/mso-api-handler-infra/src/main/java/org/openecomp/mso/apihandlerinfra/E2EServiceInstances.java new file mode 100644 index 0000000000..bcab58201a --- /dev/null +++ b/mso-api-handlers/mso-api-handler-infra/src/main/java/org/openecomp/mso/apihandlerinfra/E2EServiceInstances.java @@ -0,0 +1,438 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.mso.apihandlerinfra; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.codehaus.jackson.map.ObjectMapper; +import org.openecomp.mso.apihandler.common.ErrorNumbers; +import org.openecomp.mso.apihandler.common.RequestClient; +import org.openecomp.mso.apihandler.common.RequestClientFactory; +import org.openecomp.mso.apihandler.common.ResponseHandler; +import org.openecomp.mso.apihandlerinfra.serviceinstancebeans.E2EServiceInstanceRequest; +import org.openecomp.mso.db.catalog.CatalogDatabase; +import org.openecomp.mso.db.catalog.beans.Service; +import org.openecomp.mso.db.catalog.beans.ServiceRecipe; +import org.openecomp.mso.logger.MessageEnum; +import org.openecomp.mso.logger.MsoAlarmLogger; +import org.openecomp.mso.logger.MsoLogger; +import org.openecomp.mso.properties.MsoJavaProperties; +import org.openecomp.mso.requestsdb.InfraActiveRequests; +import org.openecomp.mso.requestsdb.RequestsDatabase; +import org.openecomp.mso.utils.UUIDChecker; + +@Path("/") +public class E2EServiceInstances { + + private HashMap<String, String> instanceIdMap = new HashMap<String, String>(); + + private static MsoLogger msoLogger = MsoLogger + .getMsoLogger(MsoLogger.Catalog.APIH); + + private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger(); + + public final static String MSO_PROP_APIHANDLER_INFRA = "MSO_PROP_APIHANDLER_INFRA"; + + private static MsoJavaProperties props = MsoPropertiesUtils + .loadMsoProperties(); + + public E2EServiceInstances() { + } + + @POST + @Path("e2eServiceInstances/{version:[vV][2-3]}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createE2EServiceInstance(String request, + @PathParam("version") String version) { + + Response response = E2EserviceInstances(request, Action.createInstance, + null, version); + + return response; + } + + @DELETE + @Path("e2eServiceInstances/{version:[vV][2-3]}/{serviceId}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response deleteE2EServiceInstance(String request, + @PathParam("version") String version) { + + Response response = E2EserviceInstances(request, Action.deleteInstance, + null, version); + + return response; + } + + private Response E2EserviceInstances(String requestJSON, Action action, + HashMap<String, String> instanceIdMap, String version) { + + String requestId = UUIDChecker.generateUUID(msoLogger); + long startTime = System.currentTimeMillis(); + msoLogger.debug("requestId is: " + requestId); + E2EServiceInstanceRequest sir = null; + MsoRequest msoRequest = new MsoRequest(requestId); + ObjectMapper mapper = new ObjectMapper(); + try { + sir = mapper.readValue(requestJSON, E2EServiceInstanceRequest.class); + } catch (Exception e) { + + msoLogger.debug("Mapping of request to JSON object failed : ", e); + Response response = msoRequest.buildServiceErrorResponse( + HttpStatus.SC_BAD_REQUEST, + MsoException.ServiceException, + "Mapping of request to JSON object failed. " + + e.getMessage(), ErrorNumbers.SVC_BAD_PARAMETER, + null); + msoLogger.error(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, + MSO_PROP_APIHANDLER_INFRA, "", "", + MsoLogger.ErrorCode.SchemaError, requestJSON, e); + msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.SchemaError, + "Mapping of request to JSON object failed"); + msoLogger.debug("End of the transaction, the final response is: " + + (String) response.getEntity()); + return response; + } + + InfraActiveRequests dup = null; + String instanceName = sir.getService().getName(); + String requestScope = sir.getService().getName(); + + try { + if (!(instanceName == null && requestScope.equals("E2EService") && action == Action.createInstance)) { + dup = (RequestsDatabase.getInstance()) + .checkInstanceNameDuplicate(instanceIdMap, + instanceName, requestScope); + } + } catch (Exception e) { + msoLogger.error(MessageEnum.APIH_DUPLICATE_CHECK_EXC, + MSO_PROP_APIHANDLER_INFRA, "", "", + MsoLogger.ErrorCode.DataError, + "Error during duplicate check ", e); + + Response response = msoRequest.buildServiceErrorResponse( + HttpStatus.SC_INTERNAL_SERVER_ERROR, + MsoException.ServiceException, e.getMessage(), + ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, null); + + msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.DBAccessError, + "Error during duplicate check"); + msoLogger.debug("End of the transaction, the final response is: " + + (String) response.getEntity()); + return response; + } + + if (dup != null) { + // Found the duplicate record. Return the appropriate error. + String instance = null; + if (instanceName != null) { + instance = instanceName; + } else { + instance = instanceIdMap.get(requestScope + "InstanceId"); + } + String dupMessage = "Error: Locked instance - This " + + requestScope + + " (" + + instance + + ") " + + "already has a request being worked with a status of " + + dup.getRequestStatus() + + " (RequestId - " + + dup.getRequestId() + + "). The existing request must finish or be cleaned up before proceeding."; + + Response response = msoRequest.buildServiceErrorResponse( + HttpStatus.SC_CONFLICT, MsoException.ServiceException, + dupMessage, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, null); + + msoLogger + .warn(MessageEnum.APIH_DUPLICATE_FOUND, dupMessage, "", "", + MsoLogger.ErrorCode.SchemaError, + "Duplicate request - Subscriber already has a request for this service"); + msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.Conflict, dupMessage); + msoLogger.debug("End of the transaction, the final response is: " + + (String) response.getEntity()); + return response; + } + + CatalogDatabase db = null; + try { + db = CatalogDatabase.getInstance(); + ; + } catch (Exception e) { + msoLogger.error(MessageEnum.APIH_DB_ACCESS_EXC, + MSO_PROP_APIHANDLER_INFRA, "", "", + MsoLogger.ErrorCode.AvailabilityError, + "Exception while communciate with Catalog DB", e); + msoRequest + .setStatus(org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED); + Response response = msoRequest.buildServiceErrorResponse( + HttpStatus.SC_NOT_FOUND, MsoException.ServiceException, + "No communication to catalog DB " + e.getMessage(), + ErrorNumbers.SVC_NO_SERVER_RESOURCES, null); + alarmLogger.sendAlarm("MsoDatabaseAccessError", + MsoAlarmLogger.CRITICAL, Messages.errors + .get(ErrorNumbers.NO_COMMUNICATION_TO_CATALOG_DB)); + msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.DBAccessError, + "Exception while communciate with DB"); + msoLogger.debug("End of the transaction, the final response is: " + + (String) response.getEntity()); + return response; + } + + RecipeLookupResult recipeLookupResult = null; + + try { + recipeLookupResult = getServiceInstanceOrchestrationURI(db, sir, action); + + } catch (Exception e) { + msoLogger.error(MessageEnum.APIH_DB_ACCESS_EXC, + MSO_PROP_APIHANDLER_INFRA, "", "", + MsoLogger.ErrorCode.DataError, + "Exception while querying Catalog DB", e); + msoRequest + .setStatus(org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED); + Response response = msoRequest.buildServiceErrorResponse( + HttpStatus.SC_NOT_FOUND, + MsoException.ServiceException, + "Recipe could not be retrieved from catalog DB " + + e.getMessage(), + ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null); + alarmLogger.sendAlarm("MsoDatabaseAccessError", + MsoAlarmLogger.CRITICAL, + Messages.errors.get(ErrorNumbers.ERROR_FROM_CATALOG_DB)); + msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.DBAccessError, + "Exception while querying Catalog DB"); + msoLogger.debug("End of the transaction, the final response is: " + + (String) response.getEntity()); + db.close(); + return response; + } + + if (recipeLookupResult == null) { + msoLogger.error(MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND, + MSO_PROP_APIHANDLER_INFRA, "", "", + MsoLogger.ErrorCode.DataError, "No recipe found in DB"); + msoRequest + .setStatus(org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED); + Response response = msoRequest.buildServiceErrorResponse( + HttpStatus.SC_NOT_FOUND, MsoException.ServiceException, + "Recipe does not exist in catalog DB", + ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null); + msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.DataNotFound, + "No recipe found in DB"); + msoLogger.debug("End of the transaction, the final response is: " + + (String) response.getEntity()); + db.close(); + return response; + } + + RequestClient requestClient = null; + HttpResponse response = null; + long subStartTime = System.currentTimeMillis(); + try { + requestClient = RequestClientFactory.getRequestClient( + recipeLookupResult.getOrchestrationURI(), props); + // Capture audit event + msoLogger + .debug("MSO API Handler Posting call to BPEL engine for url: " + + requestClient.getUrl()); + + // System.out.println("URL : " + requestClient.getUrl()); + + response = requestClient + .post(requestId, false, + recipeLookupResult.getRecipeTimeout(), + action.name(), null, null, null, null, null, null, + null, null, null, requestJSON); + + msoLogger.recordMetricEvent(subStartTime, + MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, + "Successfully received response from BPMN engine", "BPMN", + recipeLookupResult.getOrchestrationURI(), null); + } catch (Exception e) { + msoLogger.recordMetricEvent(subStartTime, + MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.CommunicationError, + "Exception while communicate with BPMN engine", "BPMN", + recipeLookupResult.getOrchestrationURI(), null); + Response resp = msoRequest.buildServiceErrorResponse( + HttpStatus.SC_BAD_GATEWAY, MsoException.ServiceException, + "Failed calling bpmn " + e.getMessage(), + ErrorNumbers.SVC_NO_SERVER_RESOURCES, null); + alarmLogger.sendAlarm("MsoConfigurationError", + MsoAlarmLogger.CRITICAL, + Messages.errors.get(ErrorNumbers.NO_COMMUNICATION_TO_BPEL)); + msoLogger.error(MessageEnum.APIH_BPEL_COMMUNICATE_ERROR, + MSO_PROP_APIHANDLER_INFRA, "", "", + MsoLogger.ErrorCode.AvailabilityError, + "Exception while communicate with BPMN engine"); + msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.CommunicationError, + "Exception while communicate with BPMN engine"); + msoLogger.debug("End of the transaction, the final response is: " + + (String) resp.getEntity()); + return resp; + } + + if (response == null) { + Response resp = msoRequest.buildServiceErrorResponse( + HttpStatus.SC_BAD_GATEWAY, MsoException.ServiceException, + "bpelResponse is null", + ErrorNumbers.SVC_NO_SERVER_RESOURCES, null); + msoLogger.error(MessageEnum.APIH_BPEL_COMMUNICATE_ERROR, + MSO_PROP_APIHANDLER_INFRA, "", "", + MsoLogger.ErrorCode.BusinessProcesssError, + "Null response from BPEL"); + msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.InternalError, + "Null response from BPMN"); + msoLogger.debug("End of the transaction, the final response is: " + + (String) resp.getEntity()); + return resp; + } + + ResponseHandler respHandler = new ResponseHandler(response, + requestClient.getType()); + int bpelStatus = respHandler.getStatus(); + + // BPEL accepted the request, the request is in progress + if (bpelStatus == HttpStatus.SC_ACCEPTED) { + String camundaJSONResponseBody = respHandler.getResponseBody(); + msoLogger.debug("Received from Camunda: " + camundaJSONResponseBody); + (RequestsDatabase.getInstance()).updateInfraStatus(requestId, + Status.IN_PROGRESS.toString(), + Constants.PROGRESS_REQUEST_IN_PROGRESS, + Constants.MODIFIED_BY_APIHANDLER); + + msoLogger.recordAuditEvent(startTime, + MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, + "BPMN accepted the request, the request is in progress"); + msoLogger.debug("End of the transaction, the final response is: " + + (String) camundaJSONResponseBody); + return Response.status(HttpStatus.SC_ACCEPTED) + .entity(camundaJSONResponseBody).build(); + } else { + List<String> variables = new ArrayList<String>(); + variables.add(bpelStatus + ""); + String camundaJSONResponseBody = respHandler.getResponseBody(); + if (camundaJSONResponseBody != null + && !camundaJSONResponseBody.isEmpty()) { + Response resp = msoRequest.buildServiceErrorResponse( + bpelStatus, MsoException.ServiceException, + "Request Failed due to BPEL error with HTTP Status= %1 " + + '\n' + camundaJSONResponseBody, + ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, variables); + msoLogger.error(MessageEnum.APIH_BPEL_RESPONSE_ERROR, + requestClient.getUrl(), "", "", + MsoLogger.ErrorCode.BusinessProcesssError, + "Response from BPEL engine is failed with HTTP Status=" + + bpelStatus); + msoLogger.recordAuditEvent(startTime, + MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.InternalError, + "Response from BPMN engine is failed"); + msoLogger + .debug("End of the transaction, the final response is: " + + (String) resp.getEntity()); + return resp; + } else { + Response resp = msoRequest + .buildServiceErrorResponse( + bpelStatus, + MsoException.ServiceException, + "Request Failed due to BPEL error with HTTP Status= %1", + ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, + variables); + msoLogger.error(MessageEnum.APIH_BPEL_RESPONSE_ERROR, + requestClient.getUrl(), "", "", + MsoLogger.ErrorCode.BusinessProcesssError, + "Response from BPEL engine is empty"); + msoLogger.recordAuditEvent(startTime, + MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.InternalError, + "Response from BPEL engine is empty"); + msoLogger + .debug("End of the transaction, the final response is: " + + (String) resp.getEntity()); + return resp; + } + } + } + + private RecipeLookupResult getServiceInstanceOrchestrationURI( + CatalogDatabase db, E2EServiceInstanceRequest sir, Action action) { + RecipeLookupResult recipeLookupResult = null; + + if (sir.getService().getName().equals("E2EService")) { + recipeLookupResult = getServiceURI(db, sir, action); + } + if (recipeLookupResult != null) { + msoLogger.debug("Orchestration URI is: " + + recipeLookupResult.getOrchestrationURI() + + ", recipe Timeout is: " + + Integer.toString(recipeLookupResult.getRecipeTimeout())); + } else { + msoLogger.debug("No matching recipe record found"); + } + return recipeLookupResult; + } + + private RecipeLookupResult getServiceURI(CatalogDatabase db, + E2EServiceInstanceRequest sir, Action action) { + + Service serviceRecord = null; + ServiceRecipe recipe = null; + + if (sir.getService().getName().equalsIgnoreCase("E2EService")) { + serviceRecord = db + .getServiceByModelName(sir.getService().getName()); + recipe = db.getServiceRecipeByModelUUID( + serviceRecord.getModelUUID(), action.name()); + } + if (recipe == null) { + return null; + } + return new RecipeLookupResult(recipe.getOrchestrationUri(), + recipe.getRecipeTimeout()); + + } +} \ No newline at end of file -- cgit 1.2.3-korg