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.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
27 import javax.ws.rs.Consumes;
28 import javax.ws.rs.DELETE;
29 import javax.ws.rs.POST;
30 import javax.ws.rs.Path;
31 import javax.ws.rs.PathParam;
32 import javax.ws.rs.Produces;
33 import javax.ws.rs.core.MediaType;
34 import javax.ws.rs.core.Response;
36 import org.apache.http.HttpResponse;
37 import org.apache.http.HttpStatus;
38 import org.codehaus.jackson.map.ObjectMapper;
39 import org.openecomp.mso.apihandler.common.ErrorNumbers;
40 import org.openecomp.mso.apihandler.common.RequestClient;
41 import org.openecomp.mso.apihandler.common.RequestClientFactory;
42 import org.openecomp.mso.apihandler.common.ResponseHandler;
43 import org.openecomp.mso.apihandlerinfra.serviceinstancebeans.E2EServiceInstanceRequest;
44 import org.openecomp.mso.db.catalog.CatalogDatabase;
45 import org.openecomp.mso.db.catalog.beans.Service;
46 import org.openecomp.mso.db.catalog.beans.ServiceRecipe;
47 import org.openecomp.mso.logger.MessageEnum;
48 import org.openecomp.mso.logger.MsoAlarmLogger;
49 import org.openecomp.mso.logger.MsoLogger;
50 import org.openecomp.mso.properties.MsoJavaProperties;
51 import org.openecomp.mso.requestsdb.InfraActiveRequests;
52 import org.openecomp.mso.requestsdb.RequestsDatabase;
53 import org.openecomp.mso.utils.UUIDChecker;
56 public class E2EServiceInstances {
58 private HashMap<String, String> instanceIdMap = new HashMap<String, String>();
60 private static MsoLogger msoLogger = MsoLogger
61 .getMsoLogger(MsoLogger.Catalog.APIH);
63 private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger();
65 public final static String MSO_PROP_APIHANDLER_INFRA = "MSO_PROP_APIHANDLER_INFRA";
67 private static MsoJavaProperties props = MsoPropertiesUtils
70 public E2EServiceInstances() {
74 @Path("e2eServiceInstances/{version:[vV][2-3]}")
75 @Consumes(MediaType.APPLICATION_JSON)
76 @Produces(MediaType.APPLICATION_JSON)
77 public Response createE2EServiceInstance(String request,
78 @PathParam("version") String version) {
80 Response response = E2EserviceInstances(request, Action.createInstance,
87 @Path("e2eServiceInstances/{version:[vV][2-3]}/{serviceId}")
88 @Consumes(MediaType.APPLICATION_JSON)
89 @Produces(MediaType.APPLICATION_JSON)
90 public Response deleteE2EServiceInstance(String request,
91 @PathParam("version") String version) {
93 Response response = E2EserviceInstances(request, Action.deleteInstance,
99 private Response E2EserviceInstances(String requestJSON, Action action,
100 HashMap<String, String> instanceIdMap, String version) {
102 String requestId = UUIDChecker.generateUUID(msoLogger);
103 long startTime = System.currentTimeMillis();
104 msoLogger.debug("requestId is: " + requestId);
105 E2EServiceInstanceRequest sir = null;
106 MsoRequest msoRequest = new MsoRequest(requestId);
107 ObjectMapper mapper = new ObjectMapper();
109 sir = mapper.readValue(requestJSON, E2EServiceInstanceRequest.class);
110 } catch (Exception e) {
112 msoLogger.debug("Mapping of request to JSON object failed : ", e);
113 Response response = msoRequest.buildServiceErrorResponse(
114 HttpStatus.SC_BAD_REQUEST,
115 MsoException.ServiceException,
116 "Mapping of request to JSON object failed. "
117 + e.getMessage(), ErrorNumbers.SVC_BAD_PARAMETER,
119 msoLogger.error(MessageEnum.APIH_REQUEST_VALIDATION_ERROR,
120 MSO_PROP_APIHANDLER_INFRA, "", "",
121 MsoLogger.ErrorCode.SchemaError, requestJSON, e);
122 msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
123 MsoLogger.ResponseCode.SchemaError,
124 "Mapping of request to JSON object failed");
125 msoLogger.debug("End of the transaction, the final response is: "
126 + (String) response.getEntity());
130 InfraActiveRequests dup = null;
131 String instanceName = sir.getService().getName();
132 String requestScope = sir.getService().getName();
135 if (!(instanceName == null && requestScope.equals("E2EService") && action == Action.createInstance)) {
136 dup = (RequestsDatabase.getInstance())
137 .checkInstanceNameDuplicate(instanceIdMap,
138 instanceName, requestScope);
140 } catch (Exception e) {
141 msoLogger.error(MessageEnum.APIH_DUPLICATE_CHECK_EXC,
142 MSO_PROP_APIHANDLER_INFRA, "", "",
143 MsoLogger.ErrorCode.DataError,
144 "Error during duplicate check ", e);
146 Response response = msoRequest.buildServiceErrorResponse(
147 HttpStatus.SC_INTERNAL_SERVER_ERROR,
148 MsoException.ServiceException, e.getMessage(),
149 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, null);
151 msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
152 MsoLogger.ResponseCode.DBAccessError,
153 "Error during duplicate check");
154 msoLogger.debug("End of the transaction, the final response is: "
155 + (String) response.getEntity());
160 // Found the duplicate record. Return the appropriate error.
161 String instance = null;
162 if (instanceName != null) {
163 instance = instanceName;
165 instance = instanceIdMap.get(requestScope + "InstanceId");
167 String dupMessage = "Error: Locked instance - This "
172 + "already has a request being worked with a status of "
173 + dup.getRequestStatus()
176 + "). The existing request must finish or be cleaned up before proceeding.";
178 Response response = msoRequest.buildServiceErrorResponse(
179 HttpStatus.SC_CONFLICT, MsoException.ServiceException,
180 dupMessage, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, null);
183 .warn(MessageEnum.APIH_DUPLICATE_FOUND, dupMessage, "", "",
184 MsoLogger.ErrorCode.SchemaError,
185 "Duplicate request - Subscriber already has a request for this service");
186 msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
187 MsoLogger.ResponseCode.Conflict, dupMessage);
188 msoLogger.debug("End of the transaction, the final response is: "
189 + (String) response.getEntity());
193 CatalogDatabase db = null;
195 db = CatalogDatabase.getInstance();
197 } catch (Exception e) {
198 msoLogger.error(MessageEnum.APIH_DB_ACCESS_EXC,
199 MSO_PROP_APIHANDLER_INFRA, "", "",
200 MsoLogger.ErrorCode.AvailabilityError,
201 "Exception while communciate with Catalog DB", e);
203 .setStatus(org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED);
204 Response response = msoRequest.buildServiceErrorResponse(
205 HttpStatus.SC_NOT_FOUND, MsoException.ServiceException,
206 "No communication to catalog DB " + e.getMessage(),
207 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null);
208 alarmLogger.sendAlarm("MsoDatabaseAccessError",
209 MsoAlarmLogger.CRITICAL, Messages.errors
210 .get(ErrorNumbers.NO_COMMUNICATION_TO_CATALOG_DB));
211 msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
212 MsoLogger.ResponseCode.DBAccessError,
213 "Exception while communciate with DB");
214 msoLogger.debug("End of the transaction, the final response is: "
215 + (String) response.getEntity());
219 RecipeLookupResult recipeLookupResult = null;
222 recipeLookupResult = getServiceInstanceOrchestrationURI(db, sir, action);
224 } catch (Exception e) {
225 msoLogger.error(MessageEnum.APIH_DB_ACCESS_EXC,
226 MSO_PROP_APIHANDLER_INFRA, "", "",
227 MsoLogger.ErrorCode.DataError,
228 "Exception while querying Catalog DB", e);
230 .setStatus(org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED);
231 Response response = msoRequest.buildServiceErrorResponse(
232 HttpStatus.SC_NOT_FOUND,
233 MsoException.ServiceException,
234 "Recipe could not be retrieved from catalog DB "
236 ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null);
237 alarmLogger.sendAlarm("MsoDatabaseAccessError",
238 MsoAlarmLogger.CRITICAL,
239 Messages.errors.get(ErrorNumbers.ERROR_FROM_CATALOG_DB));
240 msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
241 MsoLogger.ResponseCode.DBAccessError,
242 "Exception while querying Catalog DB");
243 msoLogger.debug("End of the transaction, the final response is: "
244 + (String) response.getEntity());
249 if (recipeLookupResult == null) {
250 msoLogger.error(MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND,
251 MSO_PROP_APIHANDLER_INFRA, "", "",
252 MsoLogger.ErrorCode.DataError, "No recipe found in DB");
254 .setStatus(org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED);
255 Response response = msoRequest.buildServiceErrorResponse(
256 HttpStatus.SC_NOT_FOUND, MsoException.ServiceException,
257 "Recipe does not exist in catalog DB",
258 ErrorNumbers.SVC_GENERAL_SERVICE_ERROR, null);
259 msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
260 MsoLogger.ResponseCode.DataNotFound,
261 "No recipe found in DB");
262 msoLogger.debug("End of the transaction, the final response is: "
263 + (String) response.getEntity());
268 RequestClient requestClient = null;
269 HttpResponse response = null;
270 long subStartTime = System.currentTimeMillis();
272 requestClient = RequestClientFactory.getRequestClient(
273 recipeLookupResult.getOrchestrationURI(), props);
274 // Capture audit event
276 .debug("MSO API Handler Posting call to BPEL engine for url: "
277 + requestClient.getUrl());
279 // System.out.println("URL : " + requestClient.getUrl());
281 response = requestClient
282 .post(requestId, false,
283 recipeLookupResult.getRecipeTimeout(),
284 action.name(), null, null, null, null, null, null,
285 null, null, null, requestJSON);
287 msoLogger.recordMetricEvent(subStartTime,
288 MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
289 "Successfully received response from BPMN engine", "BPMN",
290 recipeLookupResult.getOrchestrationURI(), null);
291 } catch (Exception e) {
292 msoLogger.recordMetricEvent(subStartTime,
293 MsoLogger.StatusCode.ERROR,
294 MsoLogger.ResponseCode.CommunicationError,
295 "Exception while communicate with BPMN engine", "BPMN",
296 recipeLookupResult.getOrchestrationURI(), null);
297 Response resp = msoRequest.buildServiceErrorResponse(
298 HttpStatus.SC_BAD_GATEWAY, MsoException.ServiceException,
299 "Failed calling bpmn " + e.getMessage(),
300 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null);
301 alarmLogger.sendAlarm("MsoConfigurationError",
302 MsoAlarmLogger.CRITICAL,
303 Messages.errors.get(ErrorNumbers.NO_COMMUNICATION_TO_BPEL));
304 msoLogger.error(MessageEnum.APIH_BPEL_COMMUNICATE_ERROR,
305 MSO_PROP_APIHANDLER_INFRA, "", "",
306 MsoLogger.ErrorCode.AvailabilityError,
307 "Exception while communicate with BPMN engine");
308 msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
309 MsoLogger.ResponseCode.CommunicationError,
310 "Exception while communicate with BPMN engine");
311 msoLogger.debug("End of the transaction, the final response is: "
312 + (String) resp.getEntity());
316 if (response == null) {
317 Response resp = msoRequest.buildServiceErrorResponse(
318 HttpStatus.SC_BAD_GATEWAY, MsoException.ServiceException,
319 "bpelResponse is null",
320 ErrorNumbers.SVC_NO_SERVER_RESOURCES, null);
321 msoLogger.error(MessageEnum.APIH_BPEL_COMMUNICATE_ERROR,
322 MSO_PROP_APIHANDLER_INFRA, "", "",
323 MsoLogger.ErrorCode.BusinessProcesssError,
324 "Null response from BPEL");
325 msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
326 MsoLogger.ResponseCode.InternalError,
327 "Null response from BPMN");
328 msoLogger.debug("End of the transaction, the final response is: "
329 + (String) resp.getEntity());
333 ResponseHandler respHandler = new ResponseHandler(response,
334 requestClient.getType());
335 int bpelStatus = respHandler.getStatus();
337 // BPEL accepted the request, the request is in progress
338 if (bpelStatus == HttpStatus.SC_ACCEPTED) {
339 String camundaJSONResponseBody = respHandler.getResponseBody();
340 msoLogger.debug("Received from Camunda: " + camundaJSONResponseBody);
341 (RequestsDatabase.getInstance()).updateInfraStatus(requestId,
342 Status.IN_PROGRESS.toString(),
343 Constants.PROGRESS_REQUEST_IN_PROGRESS,
344 Constants.MODIFIED_BY_APIHANDLER);
346 msoLogger.recordAuditEvent(startTime,
347 MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
348 "BPMN accepted the request, the request is in progress");
349 msoLogger.debug("End of the transaction, the final response is: "
350 + (String) camundaJSONResponseBody);
351 return Response.status(HttpStatus.SC_ACCEPTED)
352 .entity(camundaJSONResponseBody).build();
354 List<String> variables = new ArrayList<String>();
355 variables.add(bpelStatus + "");
356 String camundaJSONResponseBody = respHandler.getResponseBody();
357 if (camundaJSONResponseBody != null
358 && !camundaJSONResponseBody.isEmpty()) {
359 Response resp = msoRequest.buildServiceErrorResponse(
360 bpelStatus, MsoException.ServiceException,
361 "Request Failed due to BPEL error with HTTP Status= %1 "
362 + '\n' + camundaJSONResponseBody,
363 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, variables);
364 msoLogger.error(MessageEnum.APIH_BPEL_RESPONSE_ERROR,
365 requestClient.getUrl(), "", "",
366 MsoLogger.ErrorCode.BusinessProcesssError,
367 "Response from BPEL engine is failed with HTTP Status="
369 msoLogger.recordAuditEvent(startTime,
370 MsoLogger.StatusCode.ERROR,
371 MsoLogger.ResponseCode.InternalError,
372 "Response from BPMN engine is failed");
374 .debug("End of the transaction, the final response is: "
375 + (String) resp.getEntity());
378 Response resp = msoRequest
379 .buildServiceErrorResponse(
381 MsoException.ServiceException,
382 "Request Failed due to BPEL error with HTTP Status= %1",
383 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR,
385 msoLogger.error(MessageEnum.APIH_BPEL_RESPONSE_ERROR,
386 requestClient.getUrl(), "", "",
387 MsoLogger.ErrorCode.BusinessProcesssError,
388 "Response from BPEL engine is empty");
389 msoLogger.recordAuditEvent(startTime,
390 MsoLogger.StatusCode.ERROR,
391 MsoLogger.ResponseCode.InternalError,
392 "Response from BPEL engine is empty");
394 .debug("End of the transaction, the final response is: "
395 + (String) resp.getEntity());
401 private RecipeLookupResult getServiceInstanceOrchestrationURI(
402 CatalogDatabase db, E2EServiceInstanceRequest sir, Action action) {
403 RecipeLookupResult recipeLookupResult = null;
405 if (sir.getService().getName().equals("E2EService")) {
406 recipeLookupResult = getServiceURI(db, sir, action);
408 if (recipeLookupResult != null) {
409 msoLogger.debug("Orchestration URI is: "
410 + recipeLookupResult.getOrchestrationURI()
411 + ", recipe Timeout is: "
412 + Integer.toString(recipeLookupResult.getRecipeTimeout()));
414 msoLogger.debug("No matching recipe record found");
416 return recipeLookupResult;
419 private RecipeLookupResult getServiceURI(CatalogDatabase db,
420 E2EServiceInstanceRequest sir, Action action) {
422 Service serviceRecord = null;
423 ServiceRecipe recipe = null;
425 if (sir.getService().getName().equalsIgnoreCase("E2EService")) {
427 .getServiceByModelName(sir.getService().getName());
428 recipe = db.getServiceRecipeByModelUUID(
429 serviceRecord.getModelUUID(), action.name());
431 if (recipe == null) {
434 return new RecipeLookupResult(recipe.getOrchestrationUri(),
435 recipe.getRecipeTimeout());