Service for VoLTE usecase
[so.git] / mso-api-handlers / mso-api-handler-infra / src / main / java / org / openecomp / mso / apihandlerinfra / E2EServiceInstances.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20  
21 package org.openecomp.mso.apihandlerinfra;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26
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;
35
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;
54
55 @Path("/")
56 public class E2EServiceInstances {
57
58         private HashMap<String, String> instanceIdMap = new HashMap<String, String>();
59
60         private static MsoLogger msoLogger = MsoLogger
61                         .getMsoLogger(MsoLogger.Catalog.APIH);
62
63         private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger();
64
65         public final static String MSO_PROP_APIHANDLER_INFRA = "MSO_PROP_APIHANDLER_INFRA";
66
67         private static MsoJavaProperties props = MsoPropertiesUtils
68                         .loadMsoProperties();
69
70         public E2EServiceInstances() {
71         }
72
73         @POST
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) {
79
80                 Response response = E2EserviceInstances(request, Action.createInstance,
81                                 null, version);
82
83                 return response;
84         }
85
86         @DELETE
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) {
92
93                 Response response = E2EserviceInstances(request, Action.deleteInstance,
94                                 null, version);
95
96                 return response;
97         }
98
99         private Response E2EserviceInstances(String requestJSON, Action action,
100                         HashMap<String, String> instanceIdMap, String version) {
101
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();
108                 try {
109                         sir = mapper.readValue(requestJSON, E2EServiceInstanceRequest.class);
110                 } catch (Exception e) {
111
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,
118                                         null);
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());
127                         return response;
128                 }
129
130                 InfraActiveRequests dup = null;
131                 String instanceName = sir.getService().getName();
132                 String requestScope = sir.getService().getName();
133
134                 try {
135                         if (!(instanceName == null && requestScope.equals("E2EService") && action == Action.createInstance)) {
136                                 dup = (RequestsDatabase.getInstance())
137                                                 .checkInstanceNameDuplicate(instanceIdMap,
138                                                                 instanceName, requestScope);
139                         }
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);
145
146                         Response response = msoRequest.buildServiceErrorResponse(
147                                         HttpStatus.SC_INTERNAL_SERVER_ERROR,
148                                         MsoException.ServiceException, e.getMessage(),
149                                         ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, null);
150
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());
156                         return response;
157                 }
158
159                 if (dup != null) {
160                         // Found the duplicate record. Return the appropriate error.
161                         String instance = null;
162                         if (instanceName != null) {
163                                 instance = instanceName;
164                         } else {
165                                 instance = instanceIdMap.get(requestScope + "InstanceId");
166                         }
167                         String dupMessage = "Error: Locked instance - This "
168                                         + requestScope
169                                         + " ("
170                                         + instance
171                                         + ") "
172                                         + "already has a request being worked with a status of "
173                                         + dup.getRequestStatus()
174                                         + " (RequestId - "
175                                         + dup.getRequestId()
176                                         + "). The existing request must finish or be cleaned up before proceeding.";
177
178                         Response response = msoRequest.buildServiceErrorResponse(
179                                         HttpStatus.SC_CONFLICT, MsoException.ServiceException,
180                                         dupMessage, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, null);
181
182                         msoLogger
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());
190                         return response;
191                 }
192
193                 CatalogDatabase db = null;
194                 try {
195                         db = CatalogDatabase.getInstance();
196                         ;
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);
202                         msoRequest
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());
216                         return response;
217                 }
218
219                 RecipeLookupResult recipeLookupResult = null;
220
221                 try {
222                         recipeLookupResult = getServiceInstanceOrchestrationURI(db, sir, action);
223                 
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);
229                         msoRequest
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 "
235                                                         + e.getMessage(),
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());
245                         db.close();
246                         return response;
247                 }
248
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");
253                         msoRequest
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());
264                         db.close();
265                         return response;
266                 }
267
268                 RequestClient requestClient = null;
269                 HttpResponse response = null;
270                 long subStartTime = System.currentTimeMillis();
271                 try {
272                         requestClient = RequestClientFactory.getRequestClient(
273                                         recipeLookupResult.getOrchestrationURI(), props);
274                         // Capture audit event
275                         msoLogger
276                                         .debug("MSO API Handler Posting call to BPEL engine for url: "
277                                                         + requestClient.getUrl());
278
279                         // System.out.println("URL : " + requestClient.getUrl());
280
281                         response = requestClient
282                                         .post(requestId, false,
283                                                         recipeLookupResult.getRecipeTimeout(),
284                                                         action.name(), null, null, null, null, null, null,
285                                                         null, null, null, requestJSON);
286
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());
313                         return resp;
314                 }
315
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());
330                         return resp;
331                 }
332
333                 ResponseHandler respHandler = new ResponseHandler(response,
334                                 requestClient.getType());
335                 int bpelStatus = respHandler.getStatus();
336
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);
345
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();
353                 } else {
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="
368                                                                 + bpelStatus);
369                                 msoLogger.recordAuditEvent(startTime,
370                                                 MsoLogger.StatusCode.ERROR,
371                                                 MsoLogger.ResponseCode.InternalError,
372                                                 "Response from BPMN engine is failed");
373                                 msoLogger
374                                                 .debug("End of the transaction, the final response is: "
375                                                                 + (String) resp.getEntity());
376                                 return resp;
377                         } else {
378                                 Response resp = msoRequest
379                                                 .buildServiceErrorResponse(
380                                                                 bpelStatus,
381                                                                 MsoException.ServiceException,
382                                                                 "Request Failed due to BPEL error with HTTP Status= %1",
383                                                                 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR,
384                                                                 variables);
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");
393                                 msoLogger
394                                                 .debug("End of the transaction, the final response is: "
395                                                                 + (String) resp.getEntity());
396                                 return resp;
397                         }
398                 }
399         }
400
401         private RecipeLookupResult getServiceInstanceOrchestrationURI(
402                         CatalogDatabase db, E2EServiceInstanceRequest sir, Action action) {
403                 RecipeLookupResult recipeLookupResult = null;
404
405                 if (sir.getService().getName().equals("E2EService")) {
406                         recipeLookupResult = getServiceURI(db, sir, action);
407                 }
408                 if (recipeLookupResult != null) {
409                         msoLogger.debug("Orchestration URI is: "
410                                         + recipeLookupResult.getOrchestrationURI()
411                                         + ", recipe Timeout is: "
412                                         + Integer.toString(recipeLookupResult.getRecipeTimeout()));
413                 } else {
414                         msoLogger.debug("No matching recipe record found");
415                 }
416                 return recipeLookupResult;
417         }
418
419         private RecipeLookupResult getServiceURI(CatalogDatabase db,
420                         E2EServiceInstanceRequest sir, Action action) {
421
422                 Service serviceRecord = null;
423                 ServiceRecipe recipe = null;
424
425                 if (sir.getService().getName().equalsIgnoreCase("E2EService")) {
426                         serviceRecord = db
427                                         .getServiceByModelName(sir.getService().getName());
428                         recipe = db.getServiceRecipeByModelUUID(
429                                         serviceRecord.getModelUUID(), action.name());
430                 }
431                 if (recipe == null) {
432                         return null;
433                 }
434                 return new RecipeLookupResult(recipe.getOrchestrationUri(),
435                                 recipe.getRecipeTimeout());
436
437         }
438 }