2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.mso.apihandlerinfra;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
29 import javax.ws.rs.Consumes;
30 import javax.ws.rs.DELETE;
31 import javax.ws.rs.GET;
32 import javax.ws.rs.POST;
33 import javax.ws.rs.Path;
34 import javax.ws.rs.PathParam;
35 import javax.ws.rs.Produces;
36 import javax.ws.rs.core.MediaType;
37 import javax.ws.rs.core.Response;
39 import org.apache.http.HttpResponse;
40 import org.apache.http.HttpStatus;
41 import org.codehaus.jackson.map.ObjectMapper;
42 import org.openecomp.mso.apihandler.common.ErrorNumbers;
43 import org.openecomp.mso.apihandler.common.RequestClient;
44 import org.openecomp.mso.apihandler.common.RequestClientFactory;
45 import org.openecomp.mso.apihandler.common.ResponseHandler;
46 import org.openecomp.mso.apihandlerinfra.e2eserviceinstancebeans.E2EServiceInstanceRequest;
47 import org.openecomp.mso.apihandlerinfra.e2eserviceinstancebeans.E2EUserParam;
48 import org.openecomp.mso.apihandlerinfra.serviceinstancebeans.ModelInfo;
49 import org.openecomp.mso.apihandlerinfra.serviceinstancebeans.RequestDetails;
50 import org.openecomp.mso.apihandlerinfra.serviceinstancebeans.RequestInfo;
51 import org.openecomp.mso.apihandlerinfra.serviceinstancebeans.RequestParameters;
52 import org.openecomp.mso.apihandlerinfra.serviceinstancebeans.ServiceInstancesRequest;
53 import org.openecomp.mso.apihandlerinfra.serviceinstancebeans.SubscriberInfo;
54 import org.openecomp.mso.db.catalog.CatalogDatabase;
55 import org.openecomp.mso.db.catalog.beans.Service;
56 import org.openecomp.mso.db.catalog.beans.ServiceRecipe;
57 import org.openecomp.mso.logger.MessageEnum;
58 import org.openecomp.mso.logger.MsoAlarmLogger;
59 import org.openecomp.mso.logger.MsoLogger;
60 import org.openecomp.mso.requestsdb.InfraActiveRequests;
61 import org.openecomp.mso.requestsdb.RequestsDatabase;
62 import org.openecomp.mso.utils.UUIDChecker;
64 import com.wordnik.swagger.annotations.Api;
65 import com.wordnik.swagger.annotations.ApiOperation;
67 @Path("/e2eServiceInstances")
68 @Api(value="/e2eServiceInstances",description="API Requests for E2E Service Instances")
69 public class E2EServiceInstances {
71 private HashMap<String, String> instanceIdMap = new HashMap<String,String>();
72 private static MsoLogger msoLogger = MsoLogger.getMsoLogger (MsoLogger.Catalog.APIH);
73 private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
74 public final static String MSO_PROP_APIHANDLER_INFRA = "MSO_PROP_APIHANDLER_INFRA";
76 public E2EServiceInstances() {
80 *POST Requests for E2E Service create Instance on a version provided
84 @Path("/{version:[vV][3-5]}")
85 @Consumes(MediaType.APPLICATION_JSON)
86 @Produces(MediaType.APPLICATION_JSON)
87 @ApiOperation(value="Create a E2E Service Instance on a version provided",response=Response.class)
88 public Response createE2EServiceInstance(String request, @PathParam("version") String version) {
90 Response response = E2EserviceInstances(request, Action.createInstance, null, version);
96 *DELETE Requests for E2E Service delete Instance on a specified version and serviceId
100 @Path("/{version:[vV][3-5]}/{serviceId}")
101 @Consumes(MediaType.APPLICATION_JSON)
102 @Produces(MediaType.APPLICATION_JSON)
103 @ApiOperation(value="Delete E2E Service Instance on a specified version and serviceId",response=Response.class)
104 public Response deleteE2EServiceInstance(String request, @PathParam("version") String version, @PathParam("serviceId") String serviceId) {
106 instanceIdMap.put("serviceId", serviceId);
107 Response response = E2EserviceInstances(request, Action.deleteInstance, null, version);
112 private Response E2EserviceInstances(String requestJSON, Action action,
113 HashMap<String, String> instanceIdMap, String version) {
115 String requestId = UUIDChecker.generateUUID(msoLogger);
116 long startTime = System.currentTimeMillis();
117 msoLogger.debug("requestId is: " + requestId);
118 E2EServiceInstanceRequest sir = null;
120 MsoRequest msoRequest = new MsoRequest(requestId);
121 ObjectMapper mapper = new ObjectMapper();
124 .readValue(requestJSON, E2EServiceInstanceRequest.class);
126 } catch (Exception e) {
128 msoLogger.debug("Mapping of request to JSON object failed : ", e);
129 Response response = msoRequest.buildServiceErrorResponse(
130 HttpStatus.SC_BAD_REQUEST,
131 MsoException.ServiceException,
132 "Mapping of request to JSON object failed. "
133 + e.getMessage(), ErrorNumbers.SVC_BAD_PARAMETER,
135 msoLogger.error(MessageEnum.APIH_REQUEST_VALIDATION_ERROR,
136 MSO_PROP_APIHANDLER_INFRA, "", "",
137 MsoLogger.ErrorCode.SchemaError, requestJSON, e);
138 msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
139 MsoLogger.ResponseCode.SchemaError,
140 "Mapping of request to JSON object failed");
141 msoLogger.debug("End of the transaction, the final response is: "
142 + (String) response.getEntity());
146 InfraActiveRequests dup = null;
147 String instanceName = sir.getService().getName();
148 String requestScope = sir.getService().getParameters().getNodeType();
151 if(!(instanceName==null && requestScope.equals("service") && (action == Action.createInstance || action == Action.activateInstance))){
152 dup = (RequestsDatabase.getInstance()).checkInstanceNameDuplicate (instanceIdMap, instanceName, requestScope);
154 } catch (Exception e) {
155 msoLogger.error (MessageEnum.APIH_DUPLICATE_CHECK_EXC, MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.DataError, "Error during duplicate check ", e);
157 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, MsoException.ServiceException,
159 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR,
163 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DBAccessError, "Error during duplicate check");
164 msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
169 // Found the duplicate record. Return the appropriate error.
170 String instance = null;
171 if(instanceName != null){
172 instance = instanceName;
174 instance = instanceIdMap.get(requestScope + "InstanceId");
176 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.";
178 Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_CONFLICT, MsoException.ServiceException,
180 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR,
184 msoLogger.warn (MessageEnum.APIH_DUPLICATE_FOUND, dupMessage, "", "", MsoLogger.ErrorCode.SchemaError, "Duplicate request - Subscriber already has a request for this service");
185 msoRequest.createRequestRecord (Status.FAILED, action);
186 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, dupMessage);
187 msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
191 CatalogDatabase db = null;
193 db = CatalogDatabase.getInstance();
194 } catch (Exception e) {
195 msoLogger.error (MessageEnum.APIH_DB_ACCESS_EXC, MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.AvailabilityError, "Exception while communciate with Catalog DB", e);
196 msoRequest.setStatus (org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED);
197 Response response = msoRequest.buildServiceErrorResponse (HttpStatus.SC_NOT_FOUND,
198 MsoException.ServiceException,
199 "No communication to catalog DB " + e.getMessage (),
200 ErrorNumbers.SVC_NO_SERVER_RESOURCES,
202 alarmLogger.sendAlarm ("MsoDatabaseAccessError",
203 MsoAlarmLogger.CRITICAL,
204 Messages.errors.get (ErrorNumbers.NO_COMMUNICATION_TO_CATALOG_DB));
205 msoRequest.createRequestRecord (Status.FAILED,action);
206 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DBAccessError, "Exception while communciate with DB");
207 msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
212 RecipeLookupResult recipeLookupResult = null;
215 recipeLookupResult = getServiceInstanceOrchestrationURI(db, sir, action);
216 } catch (Exception e) {
217 msoLogger.error (MessageEnum.APIH_DB_ACCESS_EXC, MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.DataError, "Exception while querying Catalog DB", e);
218 msoRequest.setStatus (org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED);
219 Response response = msoRequest.buildServiceErrorResponse (HttpStatus.SC_NOT_FOUND,
220 MsoException.ServiceException,
221 "Recipe could not be retrieved from catalog DB " + e.getMessage (),
222 ErrorNumbers.SVC_GENERAL_SERVICE_ERROR,
224 alarmLogger.sendAlarm ("MsoDatabaseAccessError",
225 MsoAlarmLogger.CRITICAL,
226 Messages.errors.get (ErrorNumbers.ERROR_FROM_CATALOG_DB));
227 msoRequest.createRequestRecord (Status.FAILED,action);
228 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DBAccessError, "Exception while querying Catalog DB");
229 msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
241 if (recipeLookupResult == null) {
242 msoLogger.error (MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND, MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.DataError, "No recipe found in DB");
243 msoRequest.setStatus (org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED);
244 Response response = msoRequest.buildServiceErrorResponse (HttpStatus.SC_NOT_FOUND,
245 MsoException.ServiceException,
246 "Recipe does not exist in catalog DB",
247 ErrorNumbers.SVC_GENERAL_SERVICE_ERROR,
249 msoRequest.createRequestRecord (Status.FAILED, action);
250 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, "No recipe found in DB");
251 msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
257 String modelInfo = sir.getService().getParameters().getNodeTemplateName();
258 String[] arrayOfInfo = modelInfo.split(":");
259 String serviceInstanceType = arrayOfInfo[0];
263 String serviceId = "";
265 RequestClient requestClient = null;
266 HttpResponse response = null;
268 long subStartTime = System.currentTimeMillis();
269 String sirRequestJson = mappingObtainedRequestJSONToServiceInstanceRequest(sir);
272 requestClient = RequestClientFactory.getRequestClient (recipeLookupResult.getOrchestrationURI (), MsoPropertiesUtils.loadMsoProperties ());
274 // Capture audit event
275 msoLogger.debug ("MSO API Handler Posting call to BPEL engine for url: " + requestClient.getUrl ());
277 response = requestClient.post(requestId, false,
278 recipeLookupResult.getRecipeTimeout(),
279 action.name(), serviceId, null, null, null, null, serviceInstanceType,
280 null, null, null, sirRequestJson);
282 msoLogger.recordMetricEvent(subStartTime,
283 MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
284 "Successfully received response from BPMN engine", "BPMN",
285 recipeLookupResult.getOrchestrationURI(), null);
286 } catch (Exception e) {
287 msoLogger.recordMetricEvent(subStartTime,
288 MsoLogger.StatusCode.ERROR,
289 MsoLogger.ResponseCode.CommunicationError,
290 "Exception while communicate with BPMN engine", "BPMN",
291 recipeLookupResult.getOrchestrationURI(), null);
292 Response resp = msoRequest.buildServiceErrorResponse(
293 HttpStatus.SC_BAD_GATEWAY, MsoException.ServiceException,
294 "Failed calling bpmn " + e.getMessage(),
295 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null);
296 alarmLogger.sendAlarm("MsoConfigurationError",
297 MsoAlarmLogger.CRITICAL,
298 Messages.errors.get(ErrorNumbers.NO_COMMUNICATION_TO_BPEL));
299 msoLogger.error(MessageEnum.APIH_BPEL_COMMUNICATE_ERROR,
300 MSO_PROP_APIHANDLER_INFRA, "", "",
301 MsoLogger.ErrorCode.AvailabilityError,
302 "Exception while communicate with BPMN engine");
303 msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
304 MsoLogger.ResponseCode.CommunicationError,
305 "Exception while communicate with BPMN engine");
306 msoLogger.debug("End of the transaction, the final response is: "
307 + (String) resp.getEntity());
311 if (response == null) {
312 Response resp = msoRequest.buildServiceErrorResponse(
313 HttpStatus.SC_BAD_GATEWAY, MsoException.ServiceException,
314 "bpelResponse is null",
315 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null);
316 msoLogger.error(MessageEnum.APIH_BPEL_COMMUNICATE_ERROR,
317 MSO_PROP_APIHANDLER_INFRA, "", "",
318 MsoLogger.ErrorCode.BusinessProcesssError,
319 "Null response from BPEL");
320 msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
321 MsoLogger.ResponseCode.InternalError,
322 "Null response from BPMN");
323 msoLogger.debug("End of the transaction, the final response is: "
324 + (String) resp.getEntity());
328 ResponseHandler respHandler = new ResponseHandler(response,
329 requestClient.getType());
330 int bpelStatus = respHandler.getStatus();
332 // BPEL accepted the request, the request is in progress
333 if (bpelStatus == HttpStatus.SC_ACCEPTED) {
334 String camundaJSONResponseBody = respHandler.getResponseBody();
336 .debug("Received from Camunda: " + camundaJSONResponseBody);
337 (RequestsDatabase.getInstance()).updateInfraStatus(requestId,
338 Status.IN_PROGRESS.toString(),
339 Constants.PROGRESS_REQUEST_IN_PROGRESS,
340 Constants.MODIFIED_BY_APIHANDLER);
342 msoLogger.recordAuditEvent(startTime,
343 MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
344 "BPMN accepted the request, the request is in progress");
345 msoLogger.debug("End of the transaction, the final response is: "
346 + (String) camundaJSONResponseBody);
347 return Response.status(HttpStatus.SC_ACCEPTED)
348 .entity(camundaJSONResponseBody).build();
350 List<String> variables = new ArrayList<String>();
351 variables.add(bpelStatus + "");
352 String camundaJSONResponseBody = respHandler.getResponseBody();
353 if (camundaJSONResponseBody != null
354 && !camundaJSONResponseBody.isEmpty()) {
355 Response resp = msoRequest.buildServiceErrorResponse(
356 bpelStatus, MsoException.ServiceException,
357 "Request Failed due to BPEL error with HTTP Status= %1 "
358 + '\n' + camundaJSONResponseBody,
359 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, variables);
360 msoLogger.error(MessageEnum.APIH_BPEL_RESPONSE_ERROR,
361 requestClient.getUrl(), "", "",
362 MsoLogger.ErrorCode.BusinessProcesssError,
363 "Response from BPEL engine is failed with HTTP Status="
365 msoLogger.recordAuditEvent(startTime,
366 MsoLogger.StatusCode.ERROR,
367 MsoLogger.ResponseCode.InternalError,
368 "Response from BPMN engine is failed");
370 .debug("End of the transaction, the final response is: "
371 + (String) resp.getEntity());
374 Response resp = msoRequest
375 .buildServiceErrorResponse(
377 MsoException.ServiceException,
378 "Request Failed due to BPEL error with HTTP Status= %1",
379 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR,
381 msoLogger.error(MessageEnum.APIH_BPEL_RESPONSE_ERROR,
382 requestClient.getUrl(), "", "",
383 MsoLogger.ErrorCode.BusinessProcesssError,
384 "Response from BPEL engine is empty");
385 msoLogger.recordAuditEvent(startTime,
386 MsoLogger.StatusCode.ERROR,
387 MsoLogger.ResponseCode.InternalError,
388 "Response from BPEL engine is empty");
390 .debug("End of the transaction, the final response is: "
391 + (String) resp.getEntity());
397 private RecipeLookupResult getServiceInstanceOrchestrationURI(
398 CatalogDatabase db, E2EServiceInstanceRequest sir, Action action) {
400 RecipeLookupResult recipeLookupResult = null;
402 recipeLookupResult = getServiceURI(db, sir, action);
404 if (recipeLookupResult != null) {
405 msoLogger.debug ("Orchestration URI is: " + recipeLookupResult.getOrchestrationURI() + ", recipe Timeout is: " + Integer.toString(recipeLookupResult.getRecipeTimeout ()));
408 msoLogger.debug("No matching recipe record found");
410 return recipeLookupResult;
413 private RecipeLookupResult getServiceURI(CatalogDatabase db,
414 E2EServiceInstanceRequest sir, Action action) {
416 String defaultServiceModelName = "UUI_DEFAULT";
418 Service serviceRecord = null;
419 ServiceRecipe recipe = null;
421 serviceRecord = db.getServiceByModelName(defaultServiceModelName);
422 recipe = db.getServiceRecipeByModelUUID(serviceRecord.getModelUUID(), action.name());
424 if (recipe == null) {
427 return new RecipeLookupResult(recipe.getOrchestrationUri(),
428 recipe.getRecipeTimeout());
432 private String mappingObtainedRequestJSONToServiceInstanceRequest(E2EServiceInstanceRequest e2eSir){
434 ServiceInstancesRequest sir = new ServiceInstancesRequest();
436 String returnString = null;
437 RequestDetails requestDetails = new RequestDetails();
438 ModelInfo modelInfo = new ModelInfo();
441 modelInfo.setModelInvariantId(e2eSir.getService().getServiceDefId());
444 modelInfo.setModelNameVersionId(e2eSir.getService().getTemplateId());
446 String modelInfoValue = e2eSir.getService().getParameters().getNodeTemplateName();
447 String[] arrayOfInfo = modelInfoValue.split(":");
448 String modelName = arrayOfInfo[0];
449 String modelVersion = arrayOfInfo[1];
452 modelInfo.setModelName(modelName);
455 modelInfo.setModelVersion(modelVersion);
458 //if(ModelType.service.equals(e2eSir.getService().getParameters().getNodeType())){
459 modelInfo.setModelType(ModelType.service);
462 //setting modelInfo to requestDetails
463 requestDetails.setModelInfo(modelInfo);
465 SubscriberInfo subscriberInfo = new SubscriberInfo();
468 subscriberInfo.setGlobalSubscriberId(e2eSir.getService().getParameters().getGlobalSubscriberId());
471 subscriberInfo.setSubscriberName(e2eSir.getService().getParameters().getSubscriberName());
473 //setting subscriberInfo to requestDetails
474 requestDetails.setSubscriberInfo(subscriberInfo);
476 RequestInfo requestInfo = new RequestInfo();
479 requestInfo.setInstanceName(e2eSir.getService().getName());
482 requestInfo.setSource("UUI");
485 requestInfo.setSuppressRollback(true);
487 //setting requestInfo to requestDetails
488 requestDetails.setRequestInfo(requestInfo);
490 RequestParameters requestParameters = new RequestParameters();
492 //subscriptionServiceType
493 requestParameters.setSubscriptionServiceType("MOG");
496 List<E2EUserParam> userParams = new ArrayList<>();
497 userParams = e2eSir.getService().getParameters().getRequestParameters().getUserParams();
498 List<Map<String, String>> userParamList = new ArrayList<Map<String,String>>();
499 Map<String,String> userParamMap= new HashMap<String, String>();
500 for(E2EUserParam userp: userParams){
501 userParamMap.put(userp.getName(), userp.getValue());
502 userParamList.add(userParamMap);
505 requestParameters.setUserParams(userParamList);
507 //setting requestParameters to requestDetails
508 requestDetails.setRequestParameters(requestParameters);
510 sir.setRequestDetails(requestDetails);
512 //converting to string
513 ObjectMapper mapper = new ObjectMapper();
515 returnString = mapper.writeValueAsString(sir);
516 } catch (IOException e) {
517 msoLogger.debug("Exception while converting ServiceInstancesRequest object to string", e);