Add Rest for VoLTE service
[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.io.IOException;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29 import javax.ws.rs.Consumes;
30 import javax.ws.rs.DELETE;
31 import javax.ws.rs.POST;
32 import javax.ws.rs.Path;
33 import javax.ws.rs.PathParam;
34 import javax.ws.rs.Produces;
35 import javax.ws.rs.core.MediaType;
36 import javax.ws.rs.core.Response;
37
38 import org.apache.http.HttpResponse;
39 import org.apache.http.HttpStatus;
40 import org.codehaus.jackson.map.ObjectMapper;
41 import org.openecomp.mso.apihandler.common.ErrorNumbers;
42 import org.openecomp.mso.apihandler.common.RequestClient;
43 import org.openecomp.mso.apihandler.common.RequestClientFactory;
44 import org.openecomp.mso.apihandler.common.ResponseHandler;
45 import org.openecomp.mso.apihandlerinfra.e2eserviceinstancebeans.E2EServiceInstanceRequest;
46 import org.openecomp.mso.apihandlerinfra.e2eserviceinstancebeans.E2EUserParam;
47 import org.openecomp.mso.apihandlerinfra.serviceinstancebeans.ServiceInstancesRequest;
48 import org.openecomp.mso.db.catalog.CatalogDatabase;
49 import org.openecomp.mso.db.catalog.beans.Service;
50 import org.openecomp.mso.db.catalog.beans.ServiceRecipe;
51 import org.openecomp.mso.logger.MessageEnum;
52 import org.openecomp.mso.logger.MsoAlarmLogger;
53 import org.openecomp.mso.logger.MsoLogger;
54 import org.openecomp.mso.requestsdb.InfraActiveRequests;
55 import org.openecomp.mso.requestsdb.RequestsDatabase;
56 import org.openecomp.mso.utils.UUIDChecker;
57
58 @Path("/")
59 public class E2EServiceInstances {
60
61         private HashMap<String, String> instanceIdMap = new HashMap<String,String>();
62         private static MsoLogger msoLogger = MsoLogger.getMsoLogger (MsoLogger.Catalog.APIH);
63         private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
64         public final static String MSO_PROP_APIHANDLER_INFRA = "MSO_PROP_APIHANDLER_INFRA";
65
66         public E2EServiceInstances() {
67         }
68
69         @POST
70         @Path("e2eServiceInstances/{version:[vV][2-3]}")
71         @Consumes(MediaType.APPLICATION_JSON)
72         @Produces(MediaType.APPLICATION_JSON)
73         public Response createE2EServiceInstance(String request, @PathParam("version") String version) {
74
75                 Response response = E2EserviceInstances(request, Action.createInstance, null, version);
76
77                 return response;
78         }
79
80         @DELETE
81         @Path("e2eServiceInstances/{version:[vV][2-3]}/{serviceId}")
82         @Consumes(MediaType.APPLICATION_JSON)
83         @Produces(MediaType.APPLICATION_JSON)
84         public Response deleteE2EServiceInstance(String request, @PathParam("version") String version) {
85
86                 Response response = E2EserviceInstances(request, Action.deleteInstance, null, version);
87
88                 return response;
89         }
90
91         private Response E2EserviceInstances(String requestJSON, Action action,
92                         HashMap<String, String> instanceIdMap, String version) {
93
94                 String requestId = UUIDChecker.generateUUID(msoLogger);
95                 long startTime = System.currentTimeMillis();
96                 msoLogger.debug("requestId is: " + requestId);
97                 E2EServiceInstanceRequest sir = null;
98
99                 MsoRequest msoRequest = new MsoRequest(requestId);
100                 ObjectMapper mapper = new ObjectMapper();
101                 try {
102                         sir = mapper
103                                         .readValue(requestJSON, E2EServiceInstanceRequest.class);
104
105                 } catch (Exception e) {
106
107                         msoLogger.debug("Mapping of request to JSON object failed : ", e);
108                         Response response = msoRequest.buildServiceErrorResponse(
109                                         HttpStatus.SC_BAD_REQUEST,
110                                         MsoException.ServiceException,
111                                         "Mapping of request to JSON object failed.  "
112                                                         + e.getMessage(), ErrorNumbers.SVC_BAD_PARAMETER,
113                                                         null);
114                         msoLogger.error(MessageEnum.APIH_REQUEST_VALIDATION_ERROR,
115                                         MSO_PROP_APIHANDLER_INFRA, "", "",
116                                         MsoLogger.ErrorCode.SchemaError, requestJSON, e);
117                         msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
118                                         MsoLogger.ResponseCode.SchemaError,
119                                         "Mapping of request to JSON object failed");
120                         msoLogger.debug("End of the transaction, the final response is: "
121                                         + (String) response.getEntity());
122                         return response;
123                 }
124
125                 InfraActiveRequests dup = null;
126                 String instanceName = sir.getService().getName();
127                 String requestScope = sir.getService().getParameters().getNodeType();
128
129                 try {
130                         if(!(instanceName==null && requestScope.equals("service") && (action == Action.createInstance || action == Action.activateInstance))){
131                                 dup = (RequestsDatabase.getInstance()).checkInstanceNameDuplicate (instanceIdMap, instanceName, requestScope);
132                         }
133                 } catch (Exception e) {
134                         msoLogger.error (MessageEnum.APIH_DUPLICATE_CHECK_EXC, MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.DataError, "Error during duplicate check ", e);
135
136                         Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, MsoException.ServiceException,
137                                         e.getMessage(),
138                                         ErrorNumbers.SVC_DETAILED_SERVICE_ERROR,
139                                         null) ;
140
141
142                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DBAccessError, "Error during duplicate check");
143                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
144                         return response;
145                 }
146
147                 if (dup != null) {
148                         // Found the duplicate record. Return the appropriate error.
149                         String instance = null;
150                         if(instanceName != null){
151                                 instance = instanceName;
152                         }else{
153                                 instance = instanceIdMap.get(requestScope + "InstanceId");
154                         }
155                         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.";
156
157                         Response response = msoRequest.buildServiceErrorResponse(HttpStatus.SC_CONFLICT, MsoException.ServiceException,
158                                         dupMessage,
159                                         ErrorNumbers.SVC_DETAILED_SERVICE_ERROR,
160                                         null) ;
161
162
163                         msoLogger.warn (MessageEnum.APIH_DUPLICATE_FOUND, dupMessage, "", "", MsoLogger.ErrorCode.SchemaError, "Duplicate request - Subscriber already has a request for this service");
164                         msoRequest.createRequestRecord (Status.FAILED, action);
165                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, dupMessage);
166                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
167                         return response;
168                 }
169
170                 CatalogDatabase db = null;
171                 try {
172                         db = CatalogDatabase.getInstance();
173                 } catch (Exception e) {
174                         msoLogger.error (MessageEnum.APIH_DB_ACCESS_EXC, MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.AvailabilityError, "Exception while communciate with Catalog DB", e);
175                         msoRequest.setStatus (org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED);
176                         Response response = msoRequest.buildServiceErrorResponse (HttpStatus.SC_NOT_FOUND,
177                                         MsoException.ServiceException,
178                                         "No communication to catalog DB " + e.getMessage (),
179                                         ErrorNumbers.SVC_NO_SERVER_RESOURCES,
180                                         null);
181                         alarmLogger.sendAlarm ("MsoDatabaseAccessError",
182                                         MsoAlarmLogger.CRITICAL,
183                                         Messages.errors.get (ErrorNumbers.NO_COMMUNICATION_TO_CATALOG_DB));
184                         msoRequest.createRequestRecord (Status.FAILED,action);
185                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DBAccessError, "Exception while communciate with DB");
186                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
187                         return response;
188                 }
189
190
191                 RecipeLookupResult recipeLookupResult = null;
192
193                 try {
194                         recipeLookupResult = getServiceInstanceOrchestrationURI(db, sir, action);
195                 } catch (Exception e) {
196                         msoLogger.error (MessageEnum.APIH_DB_ACCESS_EXC, MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.DataError, "Exception while querying Catalog DB", e);
197                         msoRequest.setStatus (org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED);
198                         Response response = msoRequest.buildServiceErrorResponse (HttpStatus.SC_NOT_FOUND,
199                                         MsoException.ServiceException,
200                                         "Recipe could not be retrieved from catalog DB " + e.getMessage (),
201                                         ErrorNumbers.SVC_GENERAL_SERVICE_ERROR,
202                                         null);
203                         alarmLogger.sendAlarm ("MsoDatabaseAccessError",
204                                         MsoAlarmLogger.CRITICAL,
205                                         Messages.errors.get (ErrorNumbers.ERROR_FROM_CATALOG_DB));
206                         msoRequest.createRequestRecord (Status.FAILED,action);
207                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DBAccessError, "Exception while querying Catalog DB");
208                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
209                         db.close();
210                         return response;
211                 }
212                 finally{
213                         if(null != db)
214                         {
215                                 db.close();
216                         }
217
218                 }
219
220                 if (recipeLookupResult == null) {
221                         msoLogger.error (MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND, MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.DataError, "No recipe found in DB");
222                         msoRequest.setStatus (org.openecomp.mso.apihandlerinfra.vnfbeans.RequestStatusType.FAILED);
223                         Response response = msoRequest.buildServiceErrorResponse (HttpStatus.SC_NOT_FOUND,
224                                         MsoException.ServiceException,
225                                         "Recipe does not exist in catalog DB",
226                                         ErrorNumbers.SVC_GENERAL_SERVICE_ERROR,
227                                         null);
228                         msoRequest.createRequestRecord (Status.FAILED, action);
229                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, "No recipe found in DB");
230                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
231
232                         return response;
233                 }
234
235
236                 String modelInfo = sir.getService().getParameters().getNodeTemplateName();
237                 String[] arrayOfInfo = modelInfo.split(":");
238                 String serviceInstanceType = arrayOfInfo[0];
239
240
241
242                 String serviceInstanceId = "";
243
244                 RequestClient requestClient = null;
245                 HttpResponse response = null;
246
247                 long subStartTime = System.currentTimeMillis();
248                 String sirRequestJson = mappingObtainedRequestJSONToServiceInstanceRequest(sir);
249
250                 try {
251                         requestClient = RequestClientFactory.getRequestClient (recipeLookupResult.getOrchestrationURI (), MsoPropertiesUtils.loadMsoProperties ());
252
253                         // Capture audit event
254                         msoLogger.debug ("MSO API Handler Posting call to BPEL engine for url: " + requestClient.getUrl ());
255
256                         response = requestClient.post(requestId, false,
257                                         recipeLookupResult.getRecipeTimeout(),
258                                         action.name(), serviceInstanceId, null, null, null, null, serviceInstanceType,
259                                         null, null, null, sirRequestJson);
260
261                         msoLogger.recordMetricEvent(subStartTime,
262                                         MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
263                                         "Successfully received response from BPMN engine", "BPMN",
264                                         recipeLookupResult.getOrchestrationURI(), null);
265                 } catch (Exception e) {
266                         msoLogger.recordMetricEvent(subStartTime,
267                                         MsoLogger.StatusCode.ERROR,
268                                         MsoLogger.ResponseCode.CommunicationError,
269                                         "Exception while communicate with BPMN engine", "BPMN",
270                                         recipeLookupResult.getOrchestrationURI(), null);
271                         Response resp = msoRequest.buildServiceErrorResponse(
272                                         HttpStatus.SC_BAD_GATEWAY, MsoException.ServiceException,
273                                         "Failed calling bpmn " + e.getMessage(),
274                                         ErrorNumbers.SVC_NO_SERVER_RESOURCES, null);
275                         alarmLogger.sendAlarm("MsoConfigurationError",
276                                         MsoAlarmLogger.CRITICAL,
277                                         Messages.errors.get(ErrorNumbers.NO_COMMUNICATION_TO_BPEL));
278                         msoLogger.error(MessageEnum.APIH_BPEL_COMMUNICATE_ERROR,
279                                         MSO_PROP_APIHANDLER_INFRA, "", "",
280                                         MsoLogger.ErrorCode.AvailabilityError,
281                                         "Exception while communicate with BPMN engine");
282                         msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
283                                         MsoLogger.ResponseCode.CommunicationError,
284                                         "Exception while communicate with BPMN engine");
285                         msoLogger.debug("End of the transaction, the final response is: "
286                                         + (String) resp.getEntity());
287                         return resp;
288                 }
289
290                 if (response == null) {
291                         Response resp = msoRequest.buildServiceErrorResponse(
292                                         HttpStatus.SC_BAD_GATEWAY, MsoException.ServiceException,
293                                         "bpelResponse is null",
294                                         ErrorNumbers.SVC_NO_SERVER_RESOURCES, null);
295                         msoLogger.error(MessageEnum.APIH_BPEL_COMMUNICATE_ERROR,
296                                         MSO_PROP_APIHANDLER_INFRA, "", "",
297                                         MsoLogger.ErrorCode.BusinessProcesssError,
298                                         "Null response from BPEL");
299                         msoLogger.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
300                                         MsoLogger.ResponseCode.InternalError,
301                                         "Null response from BPMN");
302                         msoLogger.debug("End of the transaction, the final response is: "
303                                         + (String) resp.getEntity());
304                         return resp;
305                 }
306
307                 ResponseHandler respHandler = new ResponseHandler(response,
308                                 requestClient.getType());
309                 int bpelStatus = respHandler.getStatus();
310
311                 // BPEL accepted the request, the request is in progress
312                 if (bpelStatus == HttpStatus.SC_ACCEPTED) {
313                         String camundaJSONResponseBody = respHandler.getResponseBody();
314                         msoLogger
315                         .debug("Received from Camunda: " + camundaJSONResponseBody);
316                         (RequestsDatabase.getInstance()).updateInfraStatus(requestId,
317                                         Status.IN_PROGRESS.toString(),
318                                         Constants.PROGRESS_REQUEST_IN_PROGRESS,
319                                         Constants.MODIFIED_BY_APIHANDLER);
320
321                         msoLogger.recordAuditEvent(startTime,
322                                         MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
323                                         "BPMN accepted the request, the request is in progress");
324                         msoLogger.debug("End of the transaction, the final response is: "
325                                         + (String) camundaJSONResponseBody);
326                         return Response.status(HttpStatus.SC_ACCEPTED)
327                                         .entity(camundaJSONResponseBody).build();
328                 } else {
329                         List<String> variables = new ArrayList<String>();
330                         variables.add(bpelStatus + "");
331                         String camundaJSONResponseBody = respHandler.getResponseBody();
332                         if (camundaJSONResponseBody != null
333                                         && !camundaJSONResponseBody.isEmpty()) {
334                                 Response resp = msoRequest.buildServiceErrorResponse(
335                                                 bpelStatus, MsoException.ServiceException,
336                                                 "Request Failed due to BPEL error with HTTP Status= %1 "
337                                                                 + '\n' + camundaJSONResponseBody,
338                                                                 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR, variables);
339                                 msoLogger.error(MessageEnum.APIH_BPEL_RESPONSE_ERROR,
340                                                 requestClient.getUrl(), "", "",
341                                                 MsoLogger.ErrorCode.BusinessProcesssError,
342                                                 "Response from BPEL engine is failed with HTTP Status="
343                                                                 + bpelStatus);
344                                 msoLogger.recordAuditEvent(startTime,
345                                                 MsoLogger.StatusCode.ERROR,
346                                                 MsoLogger.ResponseCode.InternalError,
347                                                 "Response from BPMN engine is failed");
348                                 msoLogger
349                                 .debug("End of the transaction, the final response is: "
350                                                 + (String) resp.getEntity());
351                                 return resp;
352                         } else {
353                                 Response resp = msoRequest
354                                                 .buildServiceErrorResponse(
355                                                                 bpelStatus,
356                                                                 MsoException.ServiceException,
357                                                                 "Request Failed due to BPEL error with HTTP Status= %1",
358                                                                 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR,
359                                                                 variables);
360                                 msoLogger.error(MessageEnum.APIH_BPEL_RESPONSE_ERROR,
361                                                 requestClient.getUrl(), "", "",
362                                                 MsoLogger.ErrorCode.BusinessProcesssError,
363                                                 "Response from BPEL engine is empty");
364                                 msoLogger.recordAuditEvent(startTime,
365                                                 MsoLogger.StatusCode.ERROR,
366                                                 MsoLogger.ResponseCode.InternalError,
367                                                 "Response from BPEL engine is empty");
368                                 msoLogger
369                                 .debug("End of the transaction, the final response is: "
370                                                 + (String) resp.getEntity());
371                                 return resp;
372                         }
373                 }
374         }
375
376         private RecipeLookupResult getServiceInstanceOrchestrationURI(
377                         CatalogDatabase db, E2EServiceInstanceRequest sir, Action action) {
378
379                 RecipeLookupResult recipeLookupResult = null;
380
381                 recipeLookupResult = getServiceURI(db, sir, action);
382
383                 if (recipeLookupResult != null) {
384                         msoLogger.debug ("Orchestration URI is: " + recipeLookupResult.getOrchestrationURI() + ", recipe Timeout is: " + Integer.toString(recipeLookupResult.getRecipeTimeout ()));
385                 }
386                 else {
387                         msoLogger.debug("No matching recipe record found");
388                 }
389                 return recipeLookupResult;
390         }
391
392         private RecipeLookupResult getServiceURI(CatalogDatabase db,
393                         E2EServiceInstanceRequest sir, Action action) {
394
395                 String defaultServiceModelName = "UUI_DEFAULT";
396
397                 Service serviceRecord = null;
398                 ServiceRecipe recipe = null;
399
400                 serviceRecord = db.getServiceByModelName(defaultServiceModelName);
401                 recipe = db.getServiceRecipeByModelUUID(serviceRecord.getModelUUID(), action.name());
402
403                 if (recipe == null) {
404                         return null;
405                 }
406                 return new RecipeLookupResult(recipe.getOrchestrationUri(),
407                                 recipe.getRecipeTimeout());
408
409         }
410
411         private String mappingObtainedRequestJSONToServiceInstanceRequest(E2EServiceInstanceRequest e2eSir){
412
413                 ServiceInstancesRequest sir = new ServiceInstancesRequest();
414
415                 String returnString = null;
416
417                 //ModelInvariantId
418                 sir.getRequestDetails().getModelInfo().setModelInvariantId(e2eSir.getService().getServiceDefId());
419
420                 //modelNameVersionId
421                 sir.getRequestDetails().getModelInfo().setModelNameVersionId(e2eSir.getService().getTemplateId());
422
423                 String modelInfo = e2eSir.getService().getParameters().getNodeTemplateName();
424                 String[] arrayOfInfo = modelInfo.split(":");
425                 String modelName = arrayOfInfo[0];
426                 String modelVersion = arrayOfInfo[0];
427
428                 //modelName
429                 sir.getRequestDetails().getModelInfo().setModelName(modelName);
430
431                 //modelVersion
432                 sir.getRequestDetails().getModelInfo().setModelVersion(modelVersion);
433
434                 //modelType
435                 if(ModelType.service.equals(e2eSir.getService().getParameters().getNodeType())){
436                         sir.getRequestDetails().getModelInfo().setModelType(ModelType.service);
437                 }
438
439                 sir.getRequestDetails().getModelInfo().getModelType();
440
441                 //globalsubscriberId
442                 sir.getRequestDetails().getSubscriberInfo().setGlobalSubscriberId(e2eSir.getService().getParameters().getGlobalSubscriberId());
443
444                 //subscriberName
445                 sir.getRequestDetails().getSubscriberInfo().setSubscriberName(e2eSir.getService().getParameters().getSubscriberName());
446
447                 //instanceName
448                 sir.getRequestDetails().getRequestInfo().setInstanceName(e2eSir.getService().getName());
449
450                 //source
451                 sir.getRequestDetails().getRequestInfo().setSource("UUI");
452
453                 //suppressRollback
454                 sir.getRequestDetails().getRequestInfo().setSuppressRollback(true);
455
456                 //subscriptionServiceType
457                 sir.getRequestDetails().getRequestParameters().setSubscriptionServiceType("MOG");
458
459                 //Userparams
460                 List<E2EUserParam> userParams = new ArrayList<>(); 
461                 userParams = e2eSir.getService().getParameters().getRequestParameters().getUserParams();
462                 List<Map<String, String>> userParamList = new ArrayList<Map<String,String>>();
463                 Map<String,String> userParamMap= new HashMap<String, String>();
464                 for(E2EUserParam userp: userParams){
465                         userParamMap.put(userp.getName(), userp.getValue());
466                         userParamList.add(userParamMap);
467                 }
468
469                 sir.getRequestDetails().getRequestParameters().setUserParams(userParamList);
470
471                 //converting to string
472                 ObjectMapper mapper = new ObjectMapper();
473                 try {
474                         returnString = mapper.writeValueAsString(sir);
475                 } catch (IOException e) {
476                         msoLogger.debug("Exception while converting ServiceInstancesRequest object to string", e);
477                 }
478
479                 return returnString;
480         }
481 }