efa037d3934411fe819c3c05e09ea53e3cc092e6
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
7  * Modifications Copyright (C) 2019 IBM.
8  * ================================================================================
9  * Modifications Copyright (c) 2019 Samsung
10  * ================================================================================
11  * Modifications Copyright (c) 2022 Ericsson. All rights reserved.
12  * ================================================================================
13  * Licensed under the Apache License, Version 2.0 (the "License");
14  * you may not use this file except in compliance with the License.
15  * You may obtain a copy of the License at
16  * 
17  *      http://www.apache.org/licenses/LICENSE-2.0
18  * 
19  * Unless required by applicable law or agreed to in writing, software
20  * distributed under the License is distributed on an "AS IS" BASIS,
21  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  * See the License for the specific language governing permissions and
23  * limitations under the License.
24  * ============LICENSE_END=========================================================
25  */
26
27 package org.onap.so.apihandlerinfra;
28
29
30 import static org.onap.so.logger.HttpHeadersConstants.REQUESTOR_ID;
31 import java.io.IOException;
32 import java.net.URL;
33 import java.sql.Timestamp;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Map.Entry;
39 import java.util.Optional;
40 import java.util.Set;
41 import java.util.stream.Collectors;
42 import javax.ws.rs.container.ContainerRequestContext;
43 import javax.ws.rs.core.MultivaluedMap;
44 import javax.ws.rs.core.Response;
45 import org.apache.commons.lang.StringUtils;
46 import org.apache.http.HttpStatus;
47 import org.camunda.bpm.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
48 import org.onap.logging.filter.base.ErrorCode;
49 import org.onap.logging.ref.slf4j.ONAPLogConstants;
50 import org.onap.so.apihandler.camundabeans.CamundaResponse;
51 import org.onap.so.apihandler.common.CamundaClient;
52 import org.onap.so.apihandler.common.CommonConstants;
53 import org.onap.so.apihandler.common.ErrorNumbers;
54 import org.onap.so.apihandler.common.RequestClientParameter;
55 import org.onap.so.apihandler.common.ResponseBuilder;
56 import org.onap.so.apihandler.common.ResponseHandler;
57 import org.onap.so.apihandlerinfra.exceptions.ApiException;
58 import org.onap.so.apihandlerinfra.exceptions.BPMNFailureException;
59 import org.onap.so.apihandlerinfra.exceptions.ContactCamundaException;
60 import org.onap.so.apihandlerinfra.exceptions.DuplicateRequestException;
61 import org.onap.so.apihandlerinfra.exceptions.RecipeNotFoundException;
62 import org.onap.so.apihandlerinfra.exceptions.RequestDbFailureException;
63 import org.onap.so.apihandlerinfra.exceptions.ValidateException;
64 import org.onap.so.apihandlerinfra.exceptions.VfModuleNotFoundException;
65 import org.onap.so.apihandlerinfra.infra.rest.handler.AbstractRestHandler;
66 import org.onap.so.apihandlerinfra.logging.ErrorLoggerInfo;
67 import org.onap.so.constants.Status;
68 import org.onap.so.db.catalog.beans.NetworkResource;
69 import org.onap.so.db.catalog.beans.NetworkResourceCustomization;
70 import org.onap.so.db.catalog.beans.Recipe;
71 import org.onap.so.db.catalog.beans.ServiceRecipe;
72 import org.onap.so.db.catalog.beans.VfModule;
73 import org.onap.so.db.catalog.beans.VfModuleCustomization;
74 import org.onap.so.db.catalog.beans.VnfRecipe;
75 import org.onap.so.db.catalog.beans.VnfResource;
76 import org.onap.so.db.catalog.beans.VnfResourceCustomization;
77 import org.onap.so.db.catalog.client.CatalogDbClient;
78 import org.onap.so.db.request.beans.InfraActiveRequests;
79 import org.onap.so.exceptions.ValidationException;
80 import org.onap.so.logger.LogConstants;
81 import org.onap.so.logger.MessageEnum;
82 import org.onap.so.serviceinstancebeans.CloudConfiguration;
83 import org.onap.so.serviceinstancebeans.ModelInfo;
84 import org.onap.so.serviceinstancebeans.ModelType;
85 import org.onap.so.serviceinstancebeans.Networks;
86 import org.onap.so.serviceinstancebeans.RelatedInstance;
87 import org.onap.so.serviceinstancebeans.RelatedInstanceList;
88 import org.onap.so.serviceinstancebeans.RequestDetails;
89 import org.onap.so.serviceinstancebeans.RequestParameters;
90 import org.onap.so.serviceinstancebeans.Service;
91 import org.onap.so.serviceinstancebeans.ServiceInstancesRequest;
92 import org.onap.so.serviceinstancebeans.ServiceInstancesResponse;
93 import org.onap.so.serviceinstancebeans.VfModules;
94 import org.onap.so.serviceinstancebeans.Vnfs;
95 import org.onap.so.utils.UUIDChecker;
96 import org.slf4j.Logger;
97 import org.slf4j.LoggerFactory;
98 import org.slf4j.MDC;
99 import org.springframework.beans.factory.annotation.Autowired;
100 import org.springframework.core.env.Environment;
101 import org.springframework.http.ResponseEntity;
102 import org.springframework.stereotype.Component;
103 import org.springframework.web.client.RestClientException;
104 import com.fasterxml.jackson.annotation.JsonInclude.Include;
105 import com.fasterxml.jackson.databind.ObjectMapper;
106
107 @Component
108 public class RequestHandlerUtils extends AbstractRestHandler {
109
110     private static Logger logger = LoggerFactory.getLogger(RequestHandlerUtils.class);
111
112     protected static final String SAVE_TO_DB = "save instance to db";
113     private static final String NAME = "name";
114     private static final String VALUE = "value";
115
116     @Autowired
117     private Environment env;
118
119     @Autowired
120     private ResponseBuilder builder;
121
122     @Autowired
123     private MsoRequest msoRequest;
124
125     @Autowired
126     private CamundaRequestHandler camundaRequestHandler;
127
128     @Autowired
129     private CatalogDbClient catalogDbClient;
130
131     @Autowired
132     private CamundaClient camundaClient;
133
134     @Autowired
135     private ResponseHandler responseHandler;
136
137     protected ResponseEntity<String> postRequest(InfraActiveRequests currentActiveReq,
138             RequestClientParameter requestClientParameter, String orchestrationUri) throws ApiException {
139         try {
140             return camundaClient.post(requestClientParameter, orchestrationUri);
141         } catch (ApiException e) {
142             updateStatus(currentActiveReq, Status.FAILED, e.getMessage());
143             throw e;
144         }
145     }
146
147     public Response postBPELRequest(InfraActiveRequests currentActiveReq, RequestClientParameter requestClientParameter,
148             String orchestrationUri, String requestScope) throws ApiException {
149         ObjectMapper mapper = new ObjectMapper();
150         ResponseEntity<String> response = postRequest(currentActiveReq, requestClientParameter, orchestrationUri);
151         ServiceInstancesResponse jsonResponse = null;
152         int bpelStatus = responseHandler.setStatus(response.getStatusCodeValue());
153         try {
154             responseHandler.acceptedResponse(response);
155             CamundaResponse camundaResponse = responseHandler.getCamundaResponse(response);
156             String responseBody = camundaResponse.getResponse();
157             if ("Success".equalsIgnoreCase(camundaResponse.getMessage())) {
158                 jsonResponse = mapper.readValue(responseBody, ServiceInstancesResponse.class);
159                 jsonResponse.getRequestReferences().setRequestId(requestClientParameter.getRequestId());
160                 Optional<URL> selfLinkUrl =
161                         buildSelfLinkUrl(currentActiveReq.getRequestUrl(), requestClientParameter.getRequestId());
162                 if (selfLinkUrl.isPresent()) {
163                     jsonResponse.getRequestReferences().setRequestSelfLink(selfLinkUrl.get());
164                 } else {
165                     jsonResponse.getRequestReferences().setRequestSelfLink(null);
166                 }
167             } else {
168                 BPMNFailureException bpmnException =
169                         new BPMNFailureException.Builder(String.valueOf(bpelStatus) + responseBody, bpelStatus,
170                                 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).build();
171                 updateStatus(currentActiveReq, Status.FAILED, bpmnException.getMessage());
172                 throw bpmnException;
173             }
174         } catch (ApiException e) {
175             updateStatus(currentActiveReq, Status.FAILED, e.getMessage());
176             throw e;
177         } catch (IOException e) {
178             logger.error("Exception caught mapping Camunda JSON response to object: ", e);
179             updateStatus(currentActiveReq, Status.FAILED, e.getMessage());
180             throw new ValidateException.Builder("Exception caught mapping Camunda JSON response to object",
181                     HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER).cause(e).build();
182         }
183         return builder.buildResponse(HttpStatus.SC_ACCEPTED, requestClientParameter.getRequestId(), jsonResponse,
184                 requestClientParameter.getApiVersion());
185     }
186
187     @Override
188     public void updateStatus(InfraActiveRequests aq, Status status, String errorMessage)
189             throws RequestDbFailureException {
190         if ((status == Status.FAILED) || (status == Status.COMPLETE)) {
191             aq.setStatusMessage(errorMessage);
192             aq.setProgress(new Long(100));
193             aq.setRequestStatus(status.toString());
194             Timestamp endTimeStamp = new Timestamp(System.currentTimeMillis());
195             aq.setEndTime(endTimeStamp);
196             try {
197                 infraActiveRequestsClient.save(aq);
198             } catch (Exception e) {
199                 ErrorLoggerInfo errorLoggerInfo =
200                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
201                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
202                 throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(),
203                         HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
204                                 .errorInfo(errorLoggerInfo).build();
205             }
206         }
207     }
208
209     public String deriveRequestScope(Actions action, ServiceInstancesRequest sir, String requestUri) {
210         if (action == Action.inPlaceSoftwareUpdate || action == Action.applyUpdatedConfig) {
211             return (ModelType.vnf.name());
212         } else if (action == Action.addMembers || action == Action.removeMembers) {
213             return (ModelType.instanceGroup.toString());
214         } else {
215             String requestScope = requestScopeFromUri(requestUri);;
216
217             if (sir.getRequestDetails() == null) {
218                 return requestScope;
219             }
220             if (sir.getRequestDetails().getModelInfo() == null) {
221                 return requestScope;
222             }
223             if (sir.getRequestDetails().getModelInfo().getModelType() == null) {
224                 return requestScope;
225             }
226             requestScope = sir.getRequestDetails().getModelInfo().getModelType().name();
227             return requestScope;
228         }
229     }
230
231
232     public void validateHeaders(ContainerRequestContext context) throws ValidationException {
233         MultivaluedMap<String, String> headers = context.getHeaders();
234         if (!headers.containsKey(ONAPLogConstants.Headers.REQUEST_ID)) {
235             throw new ValidationException(ONAPLogConstants.Headers.REQUEST_ID + " header", true);
236         }
237         if (!headers.containsKey(ONAPLogConstants.Headers.PARTNER_NAME)) {
238             throw new ValidationException(ONAPLogConstants.Headers.PARTNER_NAME + " header", true);
239         }
240         if (!headers.containsKey(REQUESTOR_ID)) {
241             throw new ValidationException(REQUESTOR_ID + " header", true);
242         }
243     }
244
245     public String getRequestUri(ContainerRequestContext context, String uriPrefix) {
246         String requestUri = context.getUriInfo().getPath();
247         String httpUrl = MDC.get(LogConstants.URI_BASE).concat(requestUri);
248         MDC.put(LogConstants.HTTP_URL, httpUrl);
249         requestUri = requestUri.substring(requestUri.indexOf(uriPrefix) + uriPrefix.length());
250         return requestUri;
251     }
252
253     public void checkForDuplicateRequests(Actions action, HashMap<String, String> instanceIdMap, String requestScope,
254             InfraActiveRequests currentActiveReq, String instanceName) throws ApiException {
255         InfraActiveRequests dup = null;
256         boolean inProgress = false;
257
258         dup = duplicateCheck(action, instanceIdMap, instanceName, requestScope, currentActiveReq);
259
260         if (dup != null) {
261             inProgress = camundaHistoryCheck(dup, currentActiveReq);
262         }
263
264         if (dup != null && inProgress) {
265             buildErrorOnDuplicateRecord(currentActiveReq, action, instanceIdMap, instanceName, requestScope, dup);
266         }
267     }
268
269     public InfraActiveRequests duplicateCheck(Actions action, Map<String, String> instanceIdMap, String instanceName,
270             String requestScope, InfraActiveRequests currentActiveReq) throws ApiException {
271         InfraActiveRequests dup = null;
272         try {
273             if (!(instanceName == null && "service".equals(requestScope) && (action == Action.createInstance
274                     || action == Action.activateInstance || action == Action.assignInstance))) {
275                 dup = infraActiveRequestsClient.checkInstanceNameDuplicate(instanceIdMap, instanceName, requestScope);
276             }
277         } catch (Exception e) {
278             ErrorLoggerInfo errorLoggerInfo =
279                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_DUPLICATE_CHECK_EXC, ErrorCode.DataError)
280                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
281             RequestDbFailureException requestDbFailureException =
282                     new RequestDbFailureException.Builder("check for duplicate instance", e.toString(),
283                             HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
284                                     .errorInfo(errorLoggerInfo).build();
285             updateStatus(currentActiveReq, Status.FAILED, requestDbFailureException.getMessage());
286             throw requestDbFailureException;
287         }
288         return dup;
289     }
290
291     public boolean camundaHistoryCheck(InfraActiveRequests duplicateRecord, InfraActiveRequests currentActiveReq)
292             throws RequestDbFailureException, ContactCamundaException {
293         String requestId = duplicateRecord.getRequestId();
294         ResponseEntity<List<HistoricProcessInstanceEntity>> response = null;
295         try {
296             response = camundaRequestHandler.getCamundaProcessInstanceHistory(requestId, true, true, false);
297         } catch (RestClientException e) {
298             logger.error("Error querying Camunda for process-instance history for requestId: {}, exception: {}",
299                     requestId, e.getMessage());
300             ContactCamundaException contactCamundaException =
301                     new ContactCamundaException.Builder("process-instance", requestId, e.toString(),
302                             HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
303                                     .build();
304             updateStatus(currentActiveReq, Status.FAILED, contactCamundaException.getMessage());
305             throw contactCamundaException;
306         }
307
308         if (response.getBody().isEmpty()) {
309             updateStatus(duplicateRecord, Status.COMPLETE, "Request Completed");
310         } else {
311             return true;
312         }
313         return false;
314     }
315
316     public ServiceInstancesRequest convertJsonToServiceInstanceRequest(String requestJSON, Actions action,
317             String requestId, String requestUri) throws ApiException {
318         try {
319             ObjectMapper mapper = new ObjectMapper();
320             return mapper.readValue(requestJSON, ServiceInstancesRequest.class);
321
322         } catch (IOException e) {
323
324             ErrorLoggerInfo errorLoggerInfo =
325                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
326                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
327
328             ValidateException validateException =
329                     new ValidateException.Builder("Error mapping request: " + e.getMessage(), HttpStatus.SC_BAD_REQUEST,
330                             ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
331             String requestScope = requestScopeFromUri(requestUri);
332
333             msoRequest.createErrorRequestRecord(Status.FAILED, requestId, validateException.getMessage(), action,
334                     requestScope, requestJSON, null, null);
335
336             throw validateException;
337         }
338     }
339
340     public void parseRequest(ServiceInstancesRequest sir, Map<String, String> instanceIdMap, Actions action,
341             String version, String requestJSON, Boolean aLaCarte, String requestId,
342             InfraActiveRequests currentActiveReq) throws ValidateException, RequestDbFailureException {
343         int reqVersion = Integer.parseInt(version.substring(1));
344         try {
345             msoRequest.parse(sir, instanceIdMap, action, version, requestJSON, reqVersion, aLaCarte);
346         } catch (Exception e) {
347             logger.error("failed to parse request", e);
348             ErrorLoggerInfo errorLoggerInfo =
349                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
350                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
351             ValidateException validateException =
352                     new ValidateException.Builder("Error parsing request: " + e.getMessage(), HttpStatus.SC_BAD_REQUEST,
353                             ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
354
355             updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
356
357             throw validateException;
358         }
359     }
360
361     public void buildErrorOnDuplicateRecord(InfraActiveRequests currentActiveReq, Actions action,
362             Map<String, String> instanceIdMap, String instanceName, String requestScope, InfraActiveRequests dup)
363             throws ApiException {
364
365         String instance = null;
366         if (instanceName != null) {
367             instance = instanceName;
368         } else {
369             instance = instanceIdMap.get(requestScope + "InstanceId");
370         }
371         ErrorLoggerInfo errorLoggerInfo =
372                 new ErrorLoggerInfo.Builder(MessageEnum.APIH_DUPLICATE_FOUND, ErrorCode.SchemaError)
373                         .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
374
375         DuplicateRequestException dupException =
376                 new DuplicateRequestException.Builder(requestScope, instance, dup.getRequestStatus(),
377                         dup.getRequestId(), HttpStatus.SC_CONFLICT, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR)
378                                 .errorInfo(errorLoggerInfo).build();
379
380         updateStatus(currentActiveReq, Status.FAILED, dupException.getMessage());
381
382         throw dupException;
383     }
384
385     @Override
386     public String getRequestId(ContainerRequestContext requestContext) throws ValidateException {
387         String requestId = null;
388         if (requestContext.getProperty("requestId") != null) {
389             requestId = requestContext.getProperty("requestId").toString();
390         }
391         if (UUIDChecker.isValidUUID(requestId)) {
392             return requestId;
393         } else {
394             ErrorLoggerInfo errorLoggerInfo =
395                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.SchemaError)
396                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
397             ValidateException validateException =
398                     new ValidateException.Builder("Request Id " + requestId + " is not a valid UUID",
399                             HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER)
400                                     .errorInfo(errorLoggerInfo).build();
401
402             throw validateException;
403         }
404     }
405
406     public void setInstanceId(InfraActiveRequests currentActiveReq, String requestScope, String instanceId,
407             Map<String, String> instanceIdMap) {
408         if (StringUtils.isNotBlank(instanceId)) {
409             if (ModelType.service.name().equalsIgnoreCase(requestScope)) {
410                 currentActiveReq.setServiceInstanceId(instanceId);
411             } else if (ModelType.vnf.name().equalsIgnoreCase(requestScope)) {
412                 currentActiveReq.setVnfId(instanceId);
413             } else if (ModelType.vfModule.name().equalsIgnoreCase(requestScope)) {
414                 currentActiveReq.setVfModuleId(instanceId);
415             } else if (ModelType.volumeGroup.name().equalsIgnoreCase(requestScope)) {
416                 currentActiveReq.setVolumeGroupId(instanceId);
417             } else if (ModelType.network.name().equalsIgnoreCase(requestScope)) {
418                 currentActiveReq.setNetworkId(instanceId);
419             } else if (ModelType.configuration.name().equalsIgnoreCase(requestScope)) {
420                 currentActiveReq.setConfigurationId(instanceId);
421             } else if (ModelType.instanceGroup.toString().equalsIgnoreCase(requestScope)) {
422                 currentActiveReq.setInstanceGroupId(instanceId);
423             }
424         } else if (instanceIdMap != null && !instanceIdMap.isEmpty()) {
425             if (instanceIdMap.get("serviceInstanceId") != null) {
426                 currentActiveReq.setServiceInstanceId(instanceIdMap.get("serviceInstanceId"));
427             }
428             if (instanceIdMap.get("vnfInstanceId") != null) {
429                 currentActiveReq.setVnfId(instanceIdMap.get("vnfInstanceId"));
430             }
431             if (instanceIdMap.get("vfModuleInstanceId") != null) {
432                 currentActiveReq.setVfModuleId(instanceIdMap.get("vfModuleInstanceId"));
433             }
434             if (instanceIdMap.get("volumeGroupInstanceId") != null) {
435                 currentActiveReq.setVolumeGroupId(instanceIdMap.get("volumeGroupInstanceId"));
436             }
437             if (instanceIdMap.get("networkInstanceId") != null) {
438                 currentActiveReq.setNetworkId(instanceIdMap.get("networkInstanceId"));
439             }
440             if (instanceIdMap.get("configurationInstanceId") != null) {
441                 currentActiveReq.setConfigurationId(instanceIdMap.get("configurationInstanceId"));
442             }
443             if (instanceIdMap.get(CommonConstants.INSTANCE_GROUP_INSTANCE_ID) != null) {
444                 currentActiveReq.setInstanceGroupId(instanceIdMap.get(CommonConstants.INSTANCE_GROUP_INSTANCE_ID));
445             }
446             if (instanceIdMap.get("pnfName") != null) {
447                 currentActiveReq.setPnfName(instanceIdMap.get("pnfName"));
448             }
449         }
450     }
451
452     public String mapJSONtoMSOStyle(String msoRawRequest, ServiceInstancesRequest serviceInstRequest,
453             boolean isAlaCarte, Actions action) throws IOException {
454         ObjectMapper mapper = new ObjectMapper();
455         mapper.setSerializationInclusion(Include.NON_NULL);
456         if (serviceInstRequest != null) {
457             return mapper.writeValueAsString(serviceInstRequest);
458         } else {
459             return msoRawRequest;
460         }
461     }
462
463     public Optional<String> retrieveModelName(RequestParameters requestParams) {
464         String requestTestApi = null;
465         TestApi testApi = null;
466
467         if (requestParams != null) {
468             requestTestApi = requestParams.getTestApi();
469         }
470
471         if (requestTestApi == null) {
472             if (requestParams != null && requestParams.getALaCarte() != null && !requestParams.getALaCarte()) {
473                 requestTestApi = env.getProperty(CommonConstants.MACRO_TEST_API);
474             } else {
475                 requestTestApi = env.getProperty(CommonConstants.ALACARTE_TEST_API);
476             }
477         }
478
479         try {
480             testApi = TestApi.valueOf(requestTestApi);
481             return Optional.of(testApi.getModelName());
482         } catch (Exception e) {
483             logger.warn("Catching the exception on the valueOf enum call and continuing", e);
484             throw new IllegalArgumentException("Invalid TestApi is provided", e);
485         }
486     }
487
488     public String getDefaultModel(ServiceInstancesRequest sir) {
489         String defaultModel = sir.getRequestDetails().getRequestInfo().getSource() + "_DEFAULT";
490         Optional<String> oModelName = retrieveModelName(sir.getRequestDetails().getRequestParameters());
491         if (oModelName.isPresent()) {
492             defaultModel = oModelName.get();
493         }
494         return defaultModel;
495     }
496
497     public String getServiceType(String requestScope, ServiceInstancesRequest sir, Boolean aLaCarteFlag) {
498         String serviceType = null;
499         if (requestScope.equalsIgnoreCase(ModelType.service.toString())) {
500             String defaultServiceModelName = getDefaultModel(sir);
501             org.onap.so.db.catalog.beans.Service serviceRecord;
502             if (aLaCarteFlag) {
503                 serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
504                 if (serviceRecord != null) {
505                     serviceType = serviceRecord.getServiceType();
506                 }
507             } else {
508                 serviceRecord =
509                         catalogDbClient.getServiceByID(sir.getRequestDetails().getModelInfo().getModelVersionId());
510                 if (serviceRecord != null) {
511                     serviceType = serviceRecord.getServiceType();
512                 } else {
513                     serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
514                     if (serviceRecord != null) {
515                         serviceType = serviceRecord.getServiceType();
516                     }
517                 }
518             }
519         } else {
520             serviceType = msoRequest.getServiceInstanceType(sir, requestScope);
521         }
522         return serviceType;
523     }
524
525     protected String setServiceInstanceId(String requestScope, ServiceInstancesRequest sir) {
526         String serviceInstanceId = null;
527         if (sir.getServiceInstanceId() != null) {
528             serviceInstanceId = sir.getServiceInstanceId();
529         } else {
530             Optional<String> serviceInstanceIdForInstance = getServiceInstanceIdForInstanceGroup(requestScope, sir);
531             if (serviceInstanceIdForInstance.isPresent()) {
532                 serviceInstanceId = serviceInstanceIdForInstance.get();
533             }
534         }
535         return serviceInstanceId;
536     }
537
538     private String requestScopeFromUri(String requestUri) {
539         String requestScope;
540         if (requestUri.contains(ModelType.network.name())) {
541             requestScope = ModelType.network.name();
542         } else if (requestUri.contains(ModelType.vfModule.name())) {
543             requestScope = ModelType.vfModule.name();
544         } else if (requestUri.contains(ModelType.volumeGroup.name())) {
545             requestScope = ModelType.volumeGroup.name();
546         } else if (requestUri.contains(ModelType.configuration.name())) {
547             requestScope = ModelType.configuration.name();
548         } else if (requestUri.contains(ModelType.vnf.name())) {
549             requestScope = ModelType.vnf.name();
550         } else if (requestUri.contains(ModelType.pnf.name())) {
551             requestScope = ModelType.pnf.name();
552
553         } else if (requestUri.contains(ModelType.cnf.name())) {
554             requestScope = ModelType.cnf.name();
555         } else {
556             requestScope = ModelType.service.name();
557         }
558         return requestScope;
559     }
560
561     protected InfraActiveRequests createNewRecordCopyFromInfraActiveRequest(InfraActiveRequests infraActiveRequest,
562             String requestId, Timestamp startTimeStamp, String source, String requestUri, String requestorId,
563             String originalRequestId) throws ApiException {
564         InfraActiveRequests request = new InfraActiveRequests();
565         request.setRequestId(requestId);
566         request.setStartTime(startTimeStamp);
567         request.setSource(source);
568         request.setRequestUrl(requestUri);
569         request.setProgress(new Long(5));
570         request.setRequestorId(requestorId);
571         request.setRequestStatus(Status.IN_PROGRESS.toString());
572         request.setOriginalRequestId(originalRequestId);
573         request.setLastModifiedBy(Constants.MODIFIED_BY_APIHANDLER);
574         if (infraActiveRequest != null) {
575             request.setTenantId(infraActiveRequest.getTenantId());
576             request.setRequestBody(updateRequestorIdInRequestBody(infraActiveRequest, requestorId));
577             request.setCloudRegion(infraActiveRequest.getCloudRegion());
578             request.setRequestScope(infraActiveRequest.getRequestScope());
579             request.setRequestAction(infraActiveRequest.getRequestAction());
580             setInstanceIdAndName(infraActiveRequest, request);
581         }
582         return request;
583     }
584
585     protected void setInstanceIdAndName(InfraActiveRequests infraActiveRequest,
586             InfraActiveRequests currentActiveRequest) throws ApiException {
587         String requestScope = infraActiveRequest.getRequestScope();
588         try {
589             ModelType type = ModelType.valueOf(requestScope);
590             String instanceName = type.getName(infraActiveRequest);
591             if (instanceName == null && type.equals(ModelType.vfModule)) {
592                 logger.error("vfModule for requestId: {} being resumed does not have an instanceName.",
593                         infraActiveRequest.getRequestId());
594                 ValidateException validateException = new ValidateException.Builder(
595                         "vfModule for requestId: " + infraActiveRequest.getRequestId()
596                                 + " being resumed does not have an instanceName.",
597                         HttpStatus.SC_BAD_REQUEST, ErrorNumbers.SVC_BAD_PARAMETER).build();
598                 updateStatus(currentActiveRequest, Status.FAILED, validateException.getMessage());
599                 throw validateException;
600             }
601             if (instanceName != null) {
602                 type.setName(currentActiveRequest, instanceName);
603             }
604             type.setId(currentActiveRequest, type.getId(infraActiveRequest));
605         } catch (IllegalArgumentException e) {
606             logger.error(
607                     "requestScope \"{}\" does not match a ModelType enum. Unable to set instanceId and instanceName from the original request.",
608                     requestScope);
609         }
610     }
611
612     protected Boolean getIsBaseVfModule(ModelInfo modelInfo, Actions action, String vnfType,
613             String sdcServiceModelVersion, InfraActiveRequests currentActiveReq) throws ApiException {
614         // Get VF Module-specific base module indicator
615         VfModule vfm = null;
616         String modelVersionId = modelInfo.getModelVersionId();
617         Boolean isBaseVfModule = false;
618
619         if (modelVersionId != null) {
620             vfm = catalogDbClient.getVfModuleByModelUUID(modelVersionId);
621         } else if (modelInfo.getModelInvariantId() != null && modelInfo.getModelVersion() != null) {
622             vfm = catalogDbClient.getVfModuleByModelInvariantUUIDAndModelVersion(modelInfo.getModelInvariantId(),
623                     modelInfo.getModelVersion());
624         }
625
626         if (vfm != null) {
627             if (vfm.getIsBase()) {
628                 isBaseVfModule = true;
629             }
630         } else if (action == Action.createInstance || action == Action.updateInstance) {
631             String serviceVersionText = "";
632             if (sdcServiceModelVersion != null && !sdcServiceModelVersion.isEmpty()) {
633                 serviceVersionText = " with version " + sdcServiceModelVersion;
634             }
635             String errorMessage = "VnfType " + vnfType + " and VF Module Model Name " + modelInfo.getModelName()
636                     + serviceVersionText + " not found in MSO Catalog DB";
637             ErrorLoggerInfo errorLoggerInfo =
638                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND, ErrorCode.DataError)
639                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
640             VfModuleNotFoundException vfModuleException = new VfModuleNotFoundException.Builder(errorMessage,
641                     HttpStatus.SC_NOT_FOUND, ErrorNumbers.SVC_BAD_PARAMETER).errorInfo(errorLoggerInfo).build();
642             updateStatus(currentActiveReq, Status.FAILED, vfModuleException.getMessage());
643             throw vfModuleException;
644         }
645         return isBaseVfModule;
646     }
647
648     protected ModelType getModelType(Actions action, ModelInfo modelInfo) {
649         if (action == Action.applyUpdatedConfig || action == Action.inPlaceSoftwareUpdate) {
650             return ModelType.vnf;
651         } else if (action == Action.addMembers || action == Action.removeMembers) {
652             return ModelType.instanceGroup;
653         } else {
654             return modelInfo.getModelType();
655         }
656     }
657
658     protected String updateRequestorIdInRequestBody(InfraActiveRequests infraActiveRequest, String newRequestorId) {
659         String requestBody = infraActiveRequest.getRequestBody();
660         return requestBody.replaceAll(
661                 "(?s)(\"requestInfo\"\\s*?:\\s*?\\{.*?\"requestorId\"\\s*?:\\s*?\")(.*?)(\"[ ]*(?:,|\\R|\\}))",
662                 "$1" + newRequestorId + "$3");
663     }
664
665     public RecipeLookupResult getServiceInstanceOrchestrationURI(ServiceInstancesRequest sir, Actions action,
666             boolean alaCarteFlag, InfraActiveRequests currentActiveReq) throws ApiException {
667         RecipeLookupResult recipeLookupResult = null;
668         // if the aLaCarte flag is set to TRUE, the API-H should choose the VID_DEFAULT recipe for the requested action
669         ModelInfo modelInfo = sir.getRequestDetails().getModelInfo();
670         // Query MSO Catalog DB
671
672         if (action == Action.applyUpdatedConfig || action == Action.inPlaceSoftwareUpdate) {
673             recipeLookupResult = getDefaultVnfUri(sir, action);
674         } else if (action == Action.addMembers || action == Action.removeMembers) {
675             recipeLookupResult = new RecipeLookupResult("/mso/async/services/WorkflowActionBB", 180);
676         } else if (modelInfo.getModelType().equals(ModelType.service)) {
677             try {
678                 recipeLookupResult = getServiceURI(sir, action, alaCarteFlag);
679             } catch (IOException e) {
680                 ErrorLoggerInfo errorLoggerInfo =
681                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
682                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
683
684
685                 ValidateException validateException =
686                         new ValidateException.Builder(e.getMessage(), HttpStatus.SC_BAD_REQUEST,
687                                 ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
688
689                 updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
690
691                 throw validateException;
692             }
693         } else if (modelInfo.getModelType().equals(ModelType.vfModule)
694                 || modelInfo.getModelType().equals(ModelType.volumeGroup)
695                 || modelInfo.getModelType().equals(ModelType.vnf)) {
696             try {
697                 recipeLookupResult = getVnfOrVfModuleUri(sir, action);
698             } catch (ValidationException e) {
699                 ErrorLoggerInfo errorLoggerInfo =
700                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
701                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
702
703
704                 ValidateException validateException =
705                         new ValidateException.Builder(e.getMessage(), HttpStatus.SC_BAD_REQUEST,
706                                 ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
707
708                 updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
709
710                 throw validateException;
711             }
712         } else if (modelInfo.getModelType().equals(ModelType.network)) {
713             try {
714                 recipeLookupResult = getNetworkUri(sir, action);
715             } catch (ValidationException e) {
716
717                 ErrorLoggerInfo errorLoggerInfo =
718                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
719                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
720
721
722                 ValidateException validateException =
723                         new ValidateException.Builder(e.getMessage(), HttpStatus.SC_BAD_REQUEST,
724                                 ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
725                 updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
726
727                 throw validateException;
728             }
729         } else if (modelInfo.getModelType().equals(ModelType.instanceGroup)) {
730             recipeLookupResult = new RecipeLookupResult("/mso/async/services/WorkflowActionBB", 180);
731         } else if (modelInfo.getModelType().equals(ModelType.cnf)) {
732             // Capturing CNF workflow URI
733             logger.debug("Capturing cnf workflow URI");
734             recipeLookupResult = new RecipeLookupResult("/mso/async/services/WorkflowActionBB", 360);
735         }
736
737         if (recipeLookupResult == null) {
738             ErrorLoggerInfo errorLoggerInfo =
739                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
740                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
741
742
743             RecipeNotFoundException recipeNotFoundExceptionException =
744                     new RecipeNotFoundException.Builder("Recipe could not be retrieved from catalog DB.",
745                             HttpStatus.SC_NOT_FOUND, ErrorNumbers.SVC_GENERAL_SERVICE_ERROR).errorInfo(errorLoggerInfo)
746                                     .build();
747
748             updateStatus(currentActiveReq, Status.FAILED, recipeNotFoundExceptionException.getMessage());
749             throw recipeNotFoundExceptionException;
750         }
751         return recipeLookupResult;
752     }
753
754     protected RecipeLookupResult getServiceURI(ServiceInstancesRequest servInstReq, Actions action,
755             boolean alaCarteFlag) throws IOException {
756         // SERVICE REQUEST
757         // Construct the default service name
758         // TODO need to make this a configurable property
759         String defaultServiceModelName = getDefaultModel(servInstReq);
760         RequestDetails requestDetails = servInstReq.getRequestDetails();
761         ModelInfo modelInfo = requestDetails.getModelInfo();
762         org.onap.so.db.catalog.beans.Service serviceRecord;
763         List<org.onap.so.db.catalog.beans.Service> serviceRecordList;
764         ServiceRecipe recipe = null;
765
766         if (alaCarteFlag) {
767             serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
768             if (serviceRecord != null) {
769                 recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(serviceRecord.getModelUUID(),
770                         action.toString());
771             }
772         } else {
773             serviceRecord = catalogDbClient.getServiceByID(modelInfo.getModelVersionId());
774             recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(modelInfo.getModelVersionId(),
775                     action.toString());
776             if (recipe == null) {
777                 serviceRecordList = catalogDbClient
778                         .getServiceByModelInvariantUUIDOrderByModelVersionDesc(modelInfo.getModelInvariantId());
779                 if (!serviceRecordList.isEmpty()) {
780                     for (org.onap.so.db.catalog.beans.Service record : serviceRecordList) {
781                         recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(record.getModelUUID(),
782                                 action.toString());
783                         if (recipe != null) {
784                             break;
785                         }
786                     }
787                 }
788             }
789         }
790
791         // if an aLaCarte flag was sent in the request, throw an error if the recipe was not found
792         RequestParameters reqParam = requestDetails.getRequestParameters();
793         if (reqParam != null && alaCarteFlag && recipe == null) {
794             return null;
795         } else if (!alaCarteFlag && recipe != null && Action.createInstance.equals(action)) {
796             mapToLegacyRequest(requestDetails);
797         } else if (recipe == null) { // aLaCarte wasn't sent, so we'll try the default
798             serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
799             recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(serviceRecord.getModelUUID(),
800                     action.toString());
801         }
802         if (modelInfo.getModelVersionId() == null) {
803             modelInfo.setModelVersionId(serviceRecord.getModelUUID());
804         }
805         if (recipe == null) {
806             return null;
807         }
808         return new RecipeLookupResult(recipe.getOrchestrationUri(), recipe.getRecipeTimeout());
809     }
810
811     protected void mapToLegacyRequest(RequestDetails requestDetails) throws IOException {
812         RequestParameters reqParam;
813         if (requestDetails.getRequestParameters() == null) {
814             reqParam = new RequestParameters();
815         } else {
816             reqParam = requestDetails.getRequestParameters();
817         }
818         if (requestDetails.getCloudConfiguration() == null) {
819             CloudConfiguration cloudConfig = configureCloudConfig(reqParam);
820             if (cloudConfig != null) {
821                 requestDetails.setCloudConfiguration(cloudConfig);
822             }
823         }
824
825         List<Map<String, Object>> userParams = configureUserParams(reqParam);
826         if (!userParams.isEmpty()) {
827             if (reqParam == null) {
828                 requestDetails.setRequestParameters(new RequestParameters());
829             }
830             requestDetails.getRequestParameters().setUserParams(userParams);
831         }
832     }
833
834     private Service serviceMapper(Map<String, Object> params) throws IOException {
835         ObjectMapper obj = new ObjectMapper();
836         String input = obj.writeValueAsString(params.get("service"));
837         return obj.readValue(input, Service.class);
838     }
839
840     private void addUserParams(Map<String, Object> targetUserParams, List<Map<String, String>> sourceUserParams) {
841         for (Map<String, String> map : sourceUserParams) {
842             for (Map.Entry<String, String> entry : map.entrySet()) {
843                 targetUserParams.put(entry.getKey(), entry.getValue());
844             }
845         }
846     }
847
848     protected List<Map<String, Object>> configureUserParams(RequestParameters reqParams) throws IOException {
849         logger.debug("Configuring UserParams for Macro Request");
850         Map<String, Object> userParams = new HashMap<>();
851
852         for (Map<String, Object> params : reqParams.getUserParams()) {
853             if (params.containsKey("service")) {
854                 Service service = serviceMapper(params);
855
856                 // Filter out non-string params for backward compatibility
857                 Map<String, String> svcStrParams = service.getInstanceParams().stream().map(Map::entrySet)
858                         .flatMap(Set::stream).filter(e -> e.getValue() instanceof String)
859                         .collect(Collectors.toMap(Entry::getKey, e -> (String) e.getValue()));
860                 userParams.putAll(svcStrParams);
861
862                 for (Networks network : service.getResources().getNetworks()) {
863                     addUserParams(userParams, network.getInstanceParams());
864                 }
865
866                 for (Vnfs vnf : service.getResources().getVnfs()) {
867                     addUserParams(userParams, vnf.getInstanceParams());
868
869                     for (VfModules vfModule : vnf.getVfModules()) {
870                         addUserParams(userParams, vfModule.getInstanceParams());
871                     }
872                 }
873             }
874         }
875
876         return mapFlatMapToNameValue(userParams);
877     }
878
879     protected List<Map<String, Object>> mapFlatMapToNameValue(Map<String, Object> flatMap) {
880         List<Map<String, Object>> targetUserParams = new ArrayList<>();
881
882         for (Map.Entry<String, Object> map : flatMap.entrySet()) {
883             Map<String, Object> targetMap = new HashMap<>();
884             targetMap.put(NAME, map.getKey());
885             targetMap.put(VALUE, map.getValue());
886             targetUserParams.add(targetMap);
887         }
888         return targetUserParams;
889     }
890
891     protected CloudConfiguration configureCloudConfig(RequestParameters reqParams) throws IOException {
892
893         for (Map<String, Object> params : reqParams.getUserParams()) {
894             if (params.containsKey("service")) {
895                 Service service = serviceMapper(params);
896
897                 Optional<CloudConfiguration> targetConfiguration = addCloudConfig(service.getCloudConfiguration());
898
899                 if (targetConfiguration.isPresent()) {
900                     return targetConfiguration.get();
901                 } else {
902                     for (Networks network : service.getResources().getNetworks()) {
903                         targetConfiguration = addCloudConfig(network.getCloudConfiguration());
904                         if (targetConfiguration.isPresent()) {
905                             return targetConfiguration.get();
906                         }
907                     }
908
909                     for (Vnfs vnf : service.getResources().getVnfs()) {
910                         targetConfiguration = addCloudConfig(vnf.getCloudConfiguration());
911
912                         if (targetConfiguration.isPresent()) {
913                             return targetConfiguration.get();
914                         }
915
916                         for (VfModules vfModule : vnf.getVfModules()) {
917                             targetConfiguration = addCloudConfig(vfModule.getCloudConfiguration());
918
919                             if (targetConfiguration.isPresent()) {
920                                 return targetConfiguration.get();
921                             }
922                         }
923                     }
924                 }
925             }
926         }
927
928         return null;
929     }
930
931     protected Optional<String> getServiceInstanceIdForValidationError(ServiceInstancesRequest sir,
932             HashMap<String, String> instanceIdMap, String requestScope) {
933         if (instanceIdMap != null && !instanceIdMap.isEmpty() && instanceIdMap.get("serviceInstanceId") != null) {
934             return Optional.of(instanceIdMap.get("serviceInstanceId"));
935         } else {
936             return getServiceInstanceIdForInstanceGroup(requestScope, sir);
937         }
938     }
939
940     protected Optional<String> getServiceInstanceIdForInstanceGroup(String requestScope, ServiceInstancesRequest sir) {
941         if (requestScope.equalsIgnoreCase(ModelType.instanceGroup.toString())) {
942             RelatedInstanceList[] relatedInstances = sir.getRequestDetails().getRelatedInstanceList();
943             if (relatedInstances != null) {
944                 for (RelatedInstanceList relatedInstanceList : relatedInstances) {
945                     RelatedInstance relatedInstance = relatedInstanceList.getRelatedInstance();
946                     if (relatedInstance.getModelInfo().getModelType() == ModelType.service) {
947                         return Optional.ofNullable(relatedInstance.getInstanceId());
948                     }
949                 }
950             }
951         }
952         return Optional.empty();
953     }
954
955     private RecipeLookupResult getDefaultVnfUri(ServiceInstancesRequest sir, Actions action) {
956         String defaultSource = getDefaultModel(sir);
957         VnfRecipe vnfRecipe = catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(defaultSource, action.toString());
958         if (vnfRecipe == null) {
959             return null;
960         }
961         return new RecipeLookupResult(vnfRecipe.getOrchestrationUri(), vnfRecipe.getRecipeTimeout());
962     }
963
964
965     private RecipeLookupResult getNetworkUri(ServiceInstancesRequest sir, Actions action) throws ValidationException {
966         String defaultNetworkType = getDefaultModel(sir);
967         ModelInfo modelInfo = sir.getRequestDetails().getModelInfo();
968         String modelName = modelInfo.getModelName();
969         Recipe recipe = null;
970
971         if (modelInfo.getModelCustomizationId() != null) {
972             NetworkResourceCustomization networkResourceCustomization = catalogDbClient
973                     .getNetworkResourceCustomizationByModelCustomizationUUID(modelInfo.getModelCustomizationId());
974             if (networkResourceCustomization != null) {
975                 NetworkResource networkResource = networkResourceCustomization.getNetworkResource();
976                 if (networkResource != null) {
977                     if (modelInfo.getModelVersionId() == null) {
978                         modelInfo.setModelVersionId(networkResource.getModelUUID());
979                     }
980                     recipe = catalogDbClient.getFirstNetworkRecipeByModelNameAndAction(networkResource.getModelName(),
981                             action.toString());
982                 } else {
983                     throw new ValidationException("no catalog entry found");
984                 }
985             } else if (action != Action.deleteInstance) {
986                 throw new ValidationException("modelCustomizationId for networkResourceCustomization lookup", true);
987             }
988         } else {
989             // ok for version < 3 and action delete
990             if (modelName != null) {
991                 recipe = catalogDbClient.getFirstNetworkRecipeByModelNameAndAction(modelName, action.toString());
992             }
993         }
994
995         if (recipe == null) {
996             recipe = catalogDbClient.getFirstNetworkRecipeByModelNameAndAction(defaultNetworkType, action.toString());
997         }
998
999         return recipe != null ? new RecipeLookupResult(recipe.getOrchestrationUri(), recipe.getRecipeTimeout()) : null;
1000     }
1001
1002
1003     private Optional<CloudConfiguration> addCloudConfig(CloudConfiguration sourceCloudConfiguration) {
1004         CloudConfiguration targetConfiguration = new CloudConfiguration();
1005         if (sourceCloudConfiguration != null) {
1006             targetConfiguration.setAicNodeClli(sourceCloudConfiguration.getAicNodeClli());
1007             targetConfiguration.setTenantId(sourceCloudConfiguration.getTenantId());
1008             targetConfiguration.setLcpCloudRegionId(sourceCloudConfiguration.getLcpCloudRegionId());
1009             targetConfiguration.setCloudOwner(sourceCloudConfiguration.getCloudOwner());
1010             return Optional.of(targetConfiguration);
1011         }
1012         return Optional.empty();
1013     }
1014
1015     private RecipeLookupResult getVnfOrVfModuleUri(ServiceInstancesRequest servInstReq, Actions action)
1016             throws ValidationException {
1017
1018         ModelInfo modelInfo = servInstReq.getRequestDetails().getModelInfo();
1019         String vnfComponentType = modelInfo.getModelType().name();
1020
1021         RelatedInstanceList[] instanceList = null;
1022         if (servInstReq.getRequestDetails() != null) {
1023             instanceList = servInstReq.getRequestDetails().getRelatedInstanceList();
1024         }
1025
1026         Recipe recipe;
1027         String defaultSource = getDefaultModel(servInstReq);
1028         String modelCustomizationId = modelInfo.getModelCustomizationId();
1029         String modelCustomizationName = modelInfo.getModelCustomizationName();
1030         String relatedInstanceModelVersionId = null;
1031         String relatedInstanceModelInvariantId = null;
1032         String relatedInstanceVersion = null;
1033         String relatedInstanceModelCustomizationName = null;
1034
1035         if (instanceList != null) {
1036
1037             for (RelatedInstanceList relatedInstanceList : instanceList) {
1038
1039                 RelatedInstance relatedInstance = relatedInstanceList.getRelatedInstance();
1040                 ModelInfo relatedInstanceModelInfo = relatedInstance.getModelInfo();
1041                 if (relatedInstanceModelInfo.getModelType().equals(ModelType.service)) {
1042                     relatedInstanceModelVersionId = relatedInstanceModelInfo.getModelVersionId();
1043                     relatedInstanceVersion = relatedInstanceModelInfo.getModelVersion();
1044                 }
1045
1046                 if (relatedInstanceModelInfo.getModelType().equals(ModelType.vnf)) {
1047                     relatedInstanceModelVersionId = relatedInstanceModelInfo.getModelVersionId();
1048                     relatedInstanceModelInvariantId = relatedInstanceModelInfo.getModelInvariantId();
1049                     relatedInstanceVersion = relatedInstanceModelInfo.getModelVersion();
1050                     relatedInstanceModelCustomizationName = relatedInstanceModelInfo.getModelCustomizationName();
1051                 }
1052             }
1053
1054             if (modelInfo.getModelType().equals(ModelType.vnf)) {
1055                 // a. For a vnf request (only create, no update currently):
1056                 // i. (v3-v4) If modelInfo.modelCustomizationId is provided, use it to validate catalog DB has record in
1057                 // vnf_resource_customization.model_customization_uuid.
1058                 // ii. (v2-v4) If modelInfo.modelCustomizationId is NOT provided (because it is a pre-1702 ASDC model or
1059                 // pre-v3), then modelInfo.modelCustomizationName must have
1060                 // been provided (else create request should be rejected). APIH should use the
1061                 // relatedInstance.modelInfo[service].modelVersionId** + modelInfo[vnf].modelCustomizationName
1062                 // to â€œjoinâ€�? service_to_resource_customizations with vnf_resource_customization to confirm a
1063                 // vnf_resource_customization.model_customization_uuid record exists.
1064                 // **If relatedInstance.modelInfo[service].modelVersionId was not provided, use
1065                 // relatedInstance.modelInfo[service].modelInvariantId + modelVersion instead to lookup modelVersionId
1066                 // (MODEL_UUID) in SERVICE table.
1067                 // iii. Regardless of how the value was provided/obtained above, APIH must always populate
1068                 // vnfModelCustomizationId in bpmnRequest. It would be assumed it was MSO generated
1069                 // during 1707 data migration if VID did not provide it originally on request.
1070                 // iv. Note: continue to construct the â€œvnf-typeâ€�? value and pass to BPMN (must still be populated
1071                 // in A&AI).
1072                 // 1. If modelCustomizationName is NOT provided on a vnf/vfModule request, use modelCustomizationId to
1073                 // look it up in our catalog to construct vnf-type value to pass to BPMN.
1074
1075                 VnfResource vnfResource = null;
1076                 VnfResourceCustomization vrc = null;
1077                 // Validation for vnfResource
1078
1079                 if (modelCustomizationId != null) {
1080                     vrc = catalogDbClient.getVnfResourceCustomizationByModelCustomizationUUID(modelCustomizationId);
1081                     if (vrc != null) {
1082                         vnfResource = vrc.getVnfResources();
1083                     }
1084                 } else {
1085                     org.onap.so.db.catalog.beans.Service service =
1086                             catalogDbClient.getServiceByID(relatedInstanceModelVersionId);
1087                     if (service == null) {
1088                         service = catalogDbClient.getServiceByModelVersionAndModelInvariantUUID(relatedInstanceVersion,
1089                                 relatedInstanceModelInvariantId);
1090                     }
1091
1092                     if (service == null) {
1093                         throw new ValidationException("service in relatedInstance");
1094                     }
1095                     for (VnfResourceCustomization vnfResourceCustom : service.getVnfCustomizations()) {
1096                         if (vnfResourceCustom.getModelInstanceName().equals(modelCustomizationName)) {
1097                             vrc = vnfResourceCustom;
1098                         }
1099                     }
1100
1101                     if (vrc != null) {
1102                         vnfResource = vrc.getVnfResources();
1103                         modelInfo.setModelCustomizationId(vrc.getModelCustomizationUUID());
1104                         modelInfo.setModelCustomizationUuid(vrc.getModelCustomizationUUID());
1105                     }
1106                 }
1107
1108                 if (vnfResource == null) {
1109                     throw new ValidationException("vnfResource");
1110                 } else {
1111                     if (modelInfo.getModelVersionId() == null) {
1112                         modelInfo.setModelVersionId(vnfResource.getModelUUID());
1113                     }
1114                 }
1115
1116                 VnfRecipe vnfRecipe = null;
1117
1118                 if (vrc != null) {
1119                     String nfRole = vrc.getNfRole();
1120                     if (nfRole != null) {
1121                         vnfRecipe =
1122                                 catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(vrc.getNfRole(), action.toString());
1123                     }
1124                 }
1125
1126                 if (vnfRecipe == null) {
1127                     vnfRecipe = catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(defaultSource, action.toString());
1128                 }
1129
1130                 if (vnfRecipe == null) {
1131                     return null;
1132                 }
1133
1134                 return new RecipeLookupResult(vnfRecipe.getOrchestrationUri(), vnfRecipe.getRecipeTimeout());
1135             } else {
1136                 /*
1137                  * (v5-v7) If modelInfo.modelCustomizationId is NOT provided (because it is a pre-1702 ASDC model or
1138                  * pre-v3), then modelInfo.modelCustomizationName must have // been provided (else create request should
1139                  * be rejected). APIH should use the relatedInstance.modelInfo[vnf].modelVersionId +
1140                  * modelInfo[vnf].modelCustomizationName // to join vnf_to_resource_customizations with
1141                  * vf_resource_customization to confirm a vf_resource_customization.model_customization_uuid record
1142                  * exists. // Once the vnfs model_customization_uuid has been obtained, use it to find all vfModule
1143                  * customizations for that vnf customization in the vnf_res_custom_to_vf_module_custom join table. //
1144                  * For each vf_module_cust_model_customization_uuid value returned, use that UUID to query
1145                  * vf_module_customization table along with modelInfo[vfModule|volumeGroup].modelVersionId to // confirm
1146                  * record matches request data (and to identify the modelCustomizationId associated with the vfModule in
1147                  * the request). This means taking each record found // in vf_module_customization and looking up in
1148                  * vf_module (using vf_module_customization’s FK into vf_module) to find a match on
1149                  * MODEL_INVARIANT_UUID (modelInvariantId) // and MODEL_VERSION (modelVersion).
1150                  */
1151                 VfModuleCustomization vfmc = null;
1152                 VnfResource vnfr;
1153                 VnfResourceCustomization vnfrc;
1154                 VfModule vfModule = null;
1155
1156                 if (modelInfo.getModelCustomizationId() != null) {
1157                     vfmc = catalogDbClient
1158                             .getVfModuleCustomizationByModelCuztomizationUUID(modelInfo.getModelCustomizationId());
1159                 } else {
1160                     vnfr = catalogDbClient.getVnfResourceByModelUUID(relatedInstanceModelVersionId);
1161                     if (vnfr == null) {
1162                         vnfr = catalogDbClient.getFirstVnfResourceByModelInvariantUUIDAndModelVersion(
1163                                 relatedInstanceModelInvariantId, relatedInstanceVersion);
1164                     }
1165                     vnfrc = catalogDbClient.getFirstVnfResourceCustomizationByModelInstanceNameAndVnfResources(
1166                             relatedInstanceModelCustomizationName, vnfr);
1167
1168                     List<VfModuleCustomization> list = vnfrc.getVfModuleCustomizations();
1169
1170                     String vfModuleModelUUID = modelInfo.getModelVersionId();
1171                     for (VfModuleCustomization vf : list) {
1172                         VfModuleCustomization vfmCustom;
1173                         if (vfModuleModelUUID != null) {
1174                             vfmCustom = catalogDbClient
1175                                     .getVfModuleCustomizationByModelCustomizationUUIDAndVfModuleModelUUID(
1176                                             vf.getModelCustomizationUUID(), vfModuleModelUUID);
1177                             if (vfmCustom != null) {
1178                                 vfModule = vfmCustom.getVfModule();
1179                             }
1180                         } else {
1181                             vfmCustom = catalogDbClient
1182                                     .getVfModuleCustomizationByModelCuztomizationUUID(vf.getModelCustomizationUUID());
1183                             if (vfmCustom != null) {
1184                                 vfModule = vfmCustom.getVfModule();
1185                             } else {
1186                                 vfModule = catalogDbClient.getVfModuleByModelInvariantUUIDAndModelVersion(
1187                                         relatedInstanceModelInvariantId, relatedInstanceVersion);
1188                             }
1189                         }
1190
1191                         if (vfModule != null) {
1192                             modelInfo.setModelCustomizationId(vf.getModelCustomizationUUID());
1193                             modelInfo.setModelCustomizationUuid(vf.getModelCustomizationUUID());
1194                             break;
1195                         }
1196                     }
1197                 }
1198
1199                 if (vfmc == null && vfModule == null) {
1200                     throw new ValidationException("vfModuleCustomization");
1201                 } else if (vfModule == null && vfmc != null) {
1202                     vfModule = vfmc.getVfModule(); // can't be null as vfModuleModelUUID is not-null property in
1203                                                    // VfModuleCustomization table
1204                 }
1205
1206                 if (modelInfo.getModelVersionId() == null) {
1207                     modelInfo.setModelVersionId(vfModule.getModelUUID());
1208                 }
1209
1210
1211                 recipe = catalogDbClient.getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1212                         vfModule.getModelUUID(), vnfComponentType, action.toString());
1213                 if (recipe == null) {
1214                     List<VfModule> vfModuleRecords = catalogDbClient
1215                             .getVfModuleByModelInvariantUUIDOrderByModelVersionDesc(vfModule.getModelInvariantUUID());
1216                     if (!vfModuleRecords.isEmpty()) {
1217                         for (VfModule record : vfModuleRecords) {
1218                             recipe = catalogDbClient
1219                                     .getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1220                                             record.getModelUUID(), vnfComponentType, action.toString());
1221                             if (recipe != null) {
1222                                 break;
1223                             }
1224                         }
1225                     }
1226                 }
1227                 if (recipe == null) {
1228                     recipe = catalogDbClient.getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1229                             defaultSource, vnfComponentType, action.toString());
1230                     if (recipe == null) {
1231                         recipe = catalogDbClient.getFirstVnfComponentsRecipeByVnfComponentTypeAndAction(
1232                                 vnfComponentType, action.toString());
1233                     }
1234
1235                     if (recipe == null) {
1236                         return null;
1237                     }
1238                 }
1239             }
1240         } else {
1241
1242             if (modelInfo.getModelType().equals(ModelType.vnf)) {
1243                 recipe = catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(defaultSource, action.toString());
1244                 if (recipe == null) {
1245                     return null;
1246                 }
1247             } else {
1248                 recipe = catalogDbClient.getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1249                         defaultSource, vnfComponentType, action.toString());
1250
1251                 if (recipe == null) {
1252                     return null;
1253                 }
1254             }
1255         }
1256
1257         return new RecipeLookupResult(recipe.getOrchestrationUri(), recipe.getRecipeTimeout());
1258     }
1259 }