Merge "improvements to audit inventory feature"
[so.git] / mso-api-handlers / mso-api-handler-infra / src / main / java / org / onap / so / apihandlerinfra / ServiceInstances.java
index bb7df4b..0b2b1e7 100644 (file)
@@ -5,6 +5,8 @@
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
  * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
  * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -32,6 +34,7 @@ import io.swagger.annotations.ApiOperation;
 import org.apache.commons.lang.StringUtils;
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
 import org.onap.so.apihandler.camundabeans.CamundaResponse;
 import org.onap.so.apihandler.common.CommonConstants;
 import org.onap.so.apihandler.common.ErrorNumbers;
@@ -43,12 +46,15 @@ import org.onap.so.apihandler.common.ResponseHandler;
 import org.onap.so.apihandlerinfra.exceptions.ApiException;
 import org.onap.so.apihandlerinfra.exceptions.BPMNFailureException;
 import org.onap.so.apihandlerinfra.exceptions.ClientConnectionException;
+import org.onap.so.apihandlerinfra.exceptions.ContactCamundaException;
 import org.onap.so.apihandlerinfra.exceptions.DuplicateRequestException;
 import org.onap.so.apihandlerinfra.exceptions.RecipeNotFoundException;
+import org.onap.so.apihandlerinfra.exceptions.RequestDbFailureException;
 import org.onap.so.apihandlerinfra.exceptions.ValidateException;
 import org.onap.so.apihandlerinfra.exceptions.VfModuleNotFoundException;
 import org.onap.so.apihandlerinfra.logging.ErrorLoggerInfo;
 import org.onap.so.db.catalog.beans.NetworkResource;
+import org.onap.so.db.catalog.beans.NetworkResourceCustomization;
 import org.onap.so.db.catalog.beans.Recipe;
 import org.onap.so.db.catalog.beans.ServiceRecipe;
 import org.onap.so.db.catalog.beans.VfModule;
@@ -60,6 +66,7 @@ import org.onap.so.db.catalog.client.CatalogDbClient;
 import org.onap.so.db.request.beans.InfraActiveRequests;
 import org.onap.so.db.request.client.RequestsDbClient;
 import org.onap.so.exceptions.ValidationException;
+import org.onap.so.logger.LogConstants;
 import org.onap.so.logger.MessageEnum;
 import org.onap.so.logger.MsoLogger;
 import org.onap.so.serviceinstancebeans.CloudConfiguration;
@@ -76,10 +83,23 @@ import org.onap.so.serviceinstancebeans.ServiceInstancesRequest;
 import org.onap.so.serviceinstancebeans.ServiceInstancesResponse;
 import org.onap.so.serviceinstancebeans.VfModules;
 import org.onap.so.serviceinstancebeans.Vnfs;
+import org.onap.so.utils.CryptoUtils;
 import org.onap.so.utils.UUIDChecker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.core.env.Environment;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
+import org.springframework.web.client.HttpStatusCodeException;
+import org.springframework.web.client.RestTemplate;
+import org.camunda.bpm.engine.history.HistoricProcessInstance;
+import org.camunda.bpm.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
 
 import javax.transaction.Transactional;
 import javax.ws.rs.Consumes;
@@ -92,8 +112,12 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.container.ContainerRequestContext;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
+import javax.xml.bind.DatatypeConverter;
 import java.io.IOException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -106,10 +130,11 @@ import java.util.Optional;
 @Api(value="/onap/so/infra/serviceInstantiation",description="Infrastructure API Requests for Service Instances")
 public class ServiceInstances {
 
-       private static MsoLogger msoLogger = MsoLogger.getMsoLogger (MsoLogger.Catalog.APIH,MsoRequest.class);
+       private static Logger logger = LoggerFactory.getLogger(MsoRequest.class);
        private static String NAME = "name";
        private static String VALUE = "value";
-       
+       private static final String SAVE_TO_DB = "save instance to db";
+
        @Autowired
        private Environment env;
        
@@ -128,6 +153,9 @@ public class ServiceInstances {
        @Autowired
        private MsoRequest msoRequest;
        
+       @Autowired
+       private RestTemplate restTemplate;
+       
        @POST
     @Path("/{version:[vV][5-7]}/serviceInstances")
        @Consumes(MediaType.APPLICATION_JSON)
@@ -608,12 +636,77 @@ public class ServiceInstances {
                instanceIdMap.put("networkInstanceId", networkInstanceId);
                return serviceInstances(request, Action.deleteInstance, instanceIdMap, version, requestId, getRequestUri(requestContext));
        }
+       
+       @POST
+    @Path("/{version:[vV][7]}/instanceGroups")
+       @Consumes(MediaType.APPLICATION_JSON)
+       @Produces(MediaType.APPLICATION_JSON)
+       @ApiOperation(value="Create instanceGroups",response=Response.class)
+       @Transactional
+    public Response createInstanceGroups(String request, @PathParam("version") String version, @Context ContainerRequestContext requestContext) throws ApiException {
+               String requestId = getRequestId(requestContext);
+               return serviceInstances(request, Action.createInstance, null, version, requestId, getRequestUri(requestContext));
+       }
+       
+       @DELETE
+       @Path("/{version:[vV][7]}/instanceGroups/{instanceGroupId}")
+       @Consumes(MediaType.APPLICATION_JSON)
+       @Produces(MediaType.APPLICATION_JSON)
+       @ApiOperation(value="Delete instanceGroup",response=Response.class)
+       @Transactional
+       public Response deleteInstanceGroups(@PathParam("version") String version, @PathParam("instanceGroupId") String instanceGroupId, @Context ContainerRequestContext requestContext) throws ApiException {
+               String requestId = getRequestId(requestContext);
+               HashMap<String, String> instanceIdMap = new HashMap<>();
+               instanceIdMap.put(CommonConstants.INSTANCE_GROUP_ID, instanceGroupId);
+               return deleteInstanceGroups(Action.deleteInstance, instanceIdMap, version, requestId, getRequestUri(requestContext), requestContext);
+       }
+       
+       @POST
+    @Path("/{version:[vV][7]}/instanceGroups/{instanceGroupId}/addMembers")
+       @Consumes(MediaType.APPLICATION_JSON)
+       @Produces(MediaType.APPLICATION_JSON)
+       @ApiOperation(value="Add instanceGroup members",response=Response.class)
+       @Transactional
+    public Response addInstanceGroupMembers(String request, @PathParam("version") String version, @PathParam("instanceGroupId") String instanceGroupId, @Context ContainerRequestContext requestContext) throws ApiException {
+               String requestId = getRequestId(requestContext);
+               HashMap<String, String> instanceIdMap = new HashMap<>();
+               instanceIdMap.put(CommonConstants.INSTANCE_GROUP_ID, instanceGroupId);
+               return serviceInstances(request, Action.addMembers, instanceIdMap, version, requestId, getRequestUri(requestContext));
+       }
+       
+       @POST
+    @Path("/{version:[vV][7]}/instanceGroups/{instanceGroupId}/removeMembers")
+       @Consumes(MediaType.APPLICATION_JSON)
+       @Produces(MediaType.APPLICATION_JSON)
+       @ApiOperation(value="Remove instanceGroup members",response=Response.class)
+       @Transactional
+    public Response removeInstanceGroupMembers(String request, @PathParam("version") String version, @PathParam("instanceGroupId") String instanceGroupId, @Context ContainerRequestContext requestContext) throws ApiException {
+               String requestId = getRequestId(requestContext);
+               HashMap<String, String> instanceIdMap = new HashMap<>();
+               instanceIdMap.put(CommonConstants.INSTANCE_GROUP_ID, instanceGroupId);
+               return serviceInstances(request, Action.removeMembers, instanceIdMap, version, requestId, getRequestUri(requestContext));
+       }
 
        public String getRequestUri(ContainerRequestContext context){
                String requestUri = context.getUriInfo().getPath();
+               String httpUrl = MDC.get(LogConstants.URI_BASE).concat(requestUri);
+               MDC.put(LogConstants.HTTP_URL, httpUrl);
                requestUri = requestUri.substring(requestUri.indexOf("/serviceInstantiation/") + 22);
                return requestUri;
        }
+       
+       public void validateHeaders(ContainerRequestContext context) throws ValidationException{
+               MultivaluedMap<String, String> headers = context.getHeaders();
+               if(!headers.containsKey(ONAPLogConstants.Headers.REQUEST_ID)){
+                        throw new ValidationException(ONAPLogConstants.Headers.REQUEST_ID + " header", true);
+               }
+               if(!headers.containsKey(ONAPLogConstants.Headers.PARTNER_NAME)){
+                       throw new ValidationException(ONAPLogConstants.Headers.PARTNER_NAME + " header", true);
+               }
+               if(!headers.containsKey(MsoLogger.REQUESTOR_ID)){
+                       throw new ValidationException(MsoLogger.REQUESTOR_ID + " header", true);
+               }
+       }
     
        public Response serviceInstances(String requestJSON, Actions action, HashMap<String, String> instanceIdMap, String version, String requestId, String requestUri) throws ApiException {
                String serviceInstanceId = (instanceIdMap ==null)? null:instanceIdMap.get("serviceInstanceId");
@@ -621,10 +714,10 @@ public class ServiceInstances {
                long startTime = System.currentTimeMillis ();
                ServiceInstancesRequest sir = null;
                String apiVersion = version.substring(1);
-
+               
                sir = convertJsonToServiceInstanceRequest(requestJSON, action, startTime, sir, msoRequest, requestId, requestUri);
                String requestScope = deriveRequestScope(action, sir, requestUri);
-               InfraActiveRequests currentActiveReq =  msoRequest.createRequestObject (sir,  action, requestId, Status.PENDING, requestJSON, requestScope);
+               InfraActiveRequests currentActiveReq =  msoRequest.createRequestObject (sir,  action, requestId, Status.IN_PROGRESS, requestJSON, requestScope);
                if(sir.getRequestDetails().getRequestParameters() != null){
                        aLaCarte = sir.getRequestDetails().getRequestParameters().getALaCarte();
                }
@@ -637,7 +730,6 @@ public class ServiceInstances {
                String vnfType = msoRequest.getVnfType(sir,requestScope,action,requestVersion);
                String networkType = msoRequest.getNetworkType(sir,requestScope);
                String sdcServiceModelVersion = msoRequest.getSDCServiceModelVersion(sir);
-               String serviceInstanceType = msoRequest.getServiceInstanceType(sir,requestScope);
                String vfModuleType = msoRequest.getVfModuleType(sir,requestScope,action,requestVersion);
                
                if(requestScope.equalsIgnoreCase(ModelType.vnf.name()) && vnfType != null){
@@ -647,11 +739,15 @@ public class ServiceInstances {
                }
                
                InfraActiveRequests dup = null;
-                               
+               boolean inProgress = false;             
 
                dup = duplicateCheck(action, instanceIdMap, startTime, msoRequest, instanceName,requestScope, currentActiveReq);
 
-               if (dup != null) {
+               if(dup != null){
+                       inProgress = camundaHistoryCheck(dup, currentActiveReq);
+               }
+               
+               if (dup != null && inProgress) {
             buildErrorOnDuplicateRecord(currentActiveReq, action, instanceIdMap, startTime, msoRequest, instanceName, requestScope, dup);
                }
                ServiceInstancesResponse serviceResponse = new ServiceInstancesResponse();
@@ -664,11 +760,13 @@ public class ServiceInstances {
                Boolean isBaseVfModule = false;
 
         RecipeLookupResult recipeLookupResult = getServiceInstanceOrchestrationURI(sir, action, alaCarteFlag, currentActiveReq);
-                                                               
+        String serviceInstanceType = getServiceType(requestScope, sir, alaCarteFlag);                                          
                        ModelType modelType;
                        ModelInfo modelInfo =  sir.getRequestDetails().getModelInfo();
                        if (action == Action.applyUpdatedConfig || action == Action.inPlaceSoftwareUpdate) {
                                modelType = ModelType.vnf;
+                       }else if(action == Action.addMembers || action == Action.removeMembers){
+                               modelType = ModelType.instanceGroup;
                        }else {
                                modelType =modelInfo.getModelType();
                        }
@@ -715,8 +813,8 @@ public class ServiceInstances {
                String vfModuleId = "";
                String volumeGroupId = "";
                String networkId = "";
-               String correlationId = "";
-
+               String pnfCorrelationId = "";
+               String instanceGroupId = null;
                if(sir.getServiceInstanceId () != null){
                        serviceInstanceId = sir.getServiceInstanceId ();
                }
@@ -736,26 +834,133 @@ public class ServiceInstances {
                if(sir.getNetworkInstanceId () != null){
                        networkId = sir.getNetworkInstanceId ();
                }
-               
-               if (sir.getCorrelationId() != null) {
-                       correlationId = sir.getCorrelationId();
+               if(sir.getInstanceGroupId() != null){
+                       instanceGroupId = sir.getInstanceGroupId();
                }
-               infraActiveRequestsClient.save(currentActiveReq);
+
+        pnfCorrelationId = getPnfCorrelationId(sir);
+
+        try{
+            infraActiveRequestsClient.save(currentActiveReq);
+        }catch(Exception e){
+            ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, MsoLogger.ErrorCode.DataError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
+            throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(), HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
+                    .errorInfo(errorLoggerInfo).build();
+        }
                
-               if(!requestScope.equalsIgnoreCase(ModelType.service.name())){
+               if(!requestScope.equalsIgnoreCase(ModelType.service.name()) && action != Action.recreateInstance){
                        aLaCarte = true;
                }else if(aLaCarte == null){
                        aLaCarte = false;
                }
                
-               return postBPELRequest(currentActiveReq,action, requestId, startTime, requestJSON, recipeLookupResult.getOrchestrationURI(), recipeLookupResult.getRecipeTimeout(), 
-                                                               isBaseVfModule, serviceInstanceId, correlationId, vnfId, vfModuleId, volumeGroupId, networkId, null,
-                                                               serviceInstanceType,vnfType, vfModuleType,networkType, apiVersion, aLaCarte, requestUri, null, requestScope, sir);
+               RequestClientParameter requestClientParameter = null;
+               try {
+                       requestClientParameter = new RequestClientParameter.Builder()
+                                               .setRequestId(requestId)
+                                               .setBaseVfModule(isBaseVfModule)
+                                               .setRecipeTimeout(recipeLookupResult.getRecipeTimeout())
+                                               .setRequestAction(action.toString())
+                                               .setServiceInstanceId(serviceInstanceId)
+                                               .setPnfCorrelationId(pnfCorrelationId)
+                                               .setVnfId(vnfId)
+                                               .setVfModuleId(vfModuleId)
+                                               .setVolumeGroupId(volumeGroupId)
+                                               .setNetworkId(networkId)
+                                               .setServiceType(serviceInstanceType)
+                                               .setVnfType(vnfType)
+                                               .setVfModuleType(vfModuleType)
+                                               .setNetworkType(networkType)
+                                               .setRequestDetails(mapJSONtoMSOStyle(requestJSON, sir, aLaCarte, action))
+                                               .setApiVersion(apiVersion)
+                                               .setALaCarte(aLaCarte)
+                                               .setRequestUri(requestUri)
+                                               .setInstanceGroupId(instanceGroupId).build();
+               } catch (IOException e) {
+                       ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, MsoLogger.ErrorCode.SchemaError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
+                       throw new ValidateException.Builder("Unable to generate RequestClientParamter object" + e.getMessage(), HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER)
+                         .errorInfo(errorLoggerInfo).build();
+               }
+               return postBPELRequest(currentActiveReq, requestClientParameter, recipeLookupResult.getOrchestrationURI(), requestScope);
+       }
+       public Response deleteInstanceGroups(Actions action, HashMap<String, String> instanceIdMap, String version, String requestId, String requestUri, ContainerRequestContext requestContext) throws ApiException {
+               String instanceGroupId = instanceIdMap.get(CommonConstants.INSTANCE_GROUP_ID);
+               Boolean aLaCarte = true;
+               long startTime = System.currentTimeMillis ();
+               String apiVersion = version.substring(1);
+               ServiceInstancesRequest sir = new ServiceInstancesRequest();
+               sir.setInstanceGroupId(instanceGroupId);
+       
+               String requestScope = ModelType.instanceGroup.toString();
+               InfraActiveRequests currentActiveReq =  msoRequest.createRequestObject (sir,  action, requestId, Status.IN_PROGRESS, null, requestScope);
+               setInstanceId(currentActiveReq, requestScope, null, instanceIdMap);
+               try {
+                       validateHeaders(requestContext);
+               } catch (ValidationException e) {
+                       logger.error("Exception occurred", e);
+            ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_VALIDATION_ERROR, MsoLogger.ErrorCode.SchemaError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
+            ValidateException validateException = new ValidateException.Builder(e.getMessage(), HttpStatus.SC_BAD_REQUEST, ErrorNumbers.SVC_BAD_PARAMETER).cause(e)
+                        .errorInfo(errorLoggerInfo).build();
+            updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
+            throw validateException;
+               }
+               
+               InfraActiveRequests dup = duplicateCheck(action, instanceIdMap, startTime, msoRequest, null, requestScope, currentActiveReq);
+               boolean inProgress = false;
+               
+               if(dup != null){
+                       inProgress = camundaHistoryCheck(dup, currentActiveReq);
+               }
+               
+               if (dup != null && inProgress) {
+            buildErrorOnDuplicateRecord(currentActiveReq, action, instanceIdMap, startTime, msoRequest, null, requestScope, dup);
+               }
+               
+               ServiceInstancesResponse serviceResponse = new ServiceInstancesResponse();
+
+               RequestReferences referencesResponse = new RequestReferences();
+
+               referencesResponse.setRequestId(requestId);
+
+               serviceResponse.setRequestReferences(referencesResponse);
+               Boolean isBaseVfModule = false;
+
+        RecipeLookupResult recipeLookupResult = new RecipeLookupResult("/mso/async/services/WorkflowActionBB", 180);
+                                                               
+        try{
+            infraActiveRequestsClient.save(currentActiveReq);
+        }catch(Exception e){
+            ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, MsoLogger.ErrorCode.DataError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
+            throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(), HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
+                    .errorInfo(errorLoggerInfo).build();
+        }
+        
+               RequestClientParameter requestClientParameter = new RequestClientParameter.Builder()
+                                       .setRequestId(requestId)
+                                       .setBaseVfModule(isBaseVfModule)
+                                       .setRecipeTimeout(recipeLookupResult.getRecipeTimeout())
+                                       .setRequestAction(action.toString())
+                                       .setApiVersion(apiVersion)
+                                       .setALaCarte(aLaCarte)
+                                       .setRequestUri(requestUri)
+                                       .setInstanceGroupId(instanceGroupId).build();
+               
+               return postBPELRequest(currentActiveReq, requestClientParameter, recipeLookupResult.getOrchestrationURI(), requestScope);
+       }
+
+       private String getPnfCorrelationId(ServiceInstancesRequest sir) {
+               return Optional.of(sir)
+                               .map(ServiceInstancesRequest::getRequestDetails)
+                               .map(RequestDetails::getRequestParameters)
+                               .map(parameters -> parameters.getUserParamValue("pnfId"))
+                               .orElse("");
        }
 
        private String deriveRequestScope(Actions action, ServiceInstancesRequest sir, String requestUri) {
                if(action == Action.inPlaceSoftwareUpdate || action == Action.applyUpdatedConfig){
                        return (ModelType.vnf.name());
+               }else if(action == Action.addMembers || action == Action.removeMembers){
+                       return(ModelType.instanceGroup.toString());
                }else{
                        String requestScope;
                        if(sir.getRequestDetails().getModelInfo().getModelType() == null){
@@ -783,38 +988,12 @@ public class ServiceInstances {
                }
                return requestScope;
        }
-       private Response postBPELRequest(InfraActiveRequests currentActiveReq, Actions action, String requestId, long startTime, String msoRawRequest,
-                                                                       String orchestrationUri, int timeOut, Boolean isBaseVfModule,
-                                                                       String serviceInstanceId, String correlationId, String vnfId, String vfModuleId, String volumeGroupId, String networkId,
-                                     String configurationId, String serviceInstanceType, String vnfType, String vfModuleType, String networkType, 
-                                     String apiVersion, boolean aLaCarte, String requestUri, String paramXsd, String requestScope, ServiceInstancesRequest sir) throws ApiException {
+       private Response postBPELRequest(InfraActiveRequests currentActiveReq, RequestClientParameter requestClientParameter, String orchestrationUri, String requestScope)throws ApiException {
                RequestClient requestClient = null;
                HttpResponse response = null;
                try {
                        requestClient = reqClientFactory.getRequestClient (orchestrationUri);
-                       response = requestClient.post(new RequestClientParameter.Builder()
-                                       .setRequestId(requestId)
-                                       .setBaseVfModule(isBaseVfModule)
-                                       .setRecipeTimeout(timeOut)
-                                       .setRequestAction(action.toString())
-                                       .setServiceInstanceId(serviceInstanceId)
-                                       .setCorrelationId(correlationId)
-                                       .setVnfId(vnfId)
-                                       .setVfModuleId(vfModuleId)
-                                       .setVolumeGroupId(volumeGroupId)
-                                       .setNetworkId(networkId)
-                                       .setConfigurationId(configurationId)
-                                       .setServiceType(serviceInstanceType)
-                                       .setVnfType(vnfType)
-                                       .setVfModuleType(vfModuleType)
-                                       .setNetworkType(networkType)
-                                       .setRequestDetails(mapJSONtoMSOStyle(msoRawRequest, sir, aLaCarte, action))
-                                       .setApiVersion(apiVersion)
-                                       .setALaCarte(aLaCarte)
-                                       .setRecipeParamXsd(paramXsd)
-                                       .setRequestUri(requestUri).build());
-                       
-                       
+                       response = requestClient.post(requestClientParameter);
                } catch (Exception e) {
                        
             ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_COMMUNICATE_ERROR, MsoLogger.ErrorCode.AvailabilityError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
@@ -841,7 +1020,7 @@ public class ServiceInstances {
             respHandler = new ResponseHandler (response, requestClient.getType ());
             bpelStatus = respHandler.getStatus ();
         } catch (ApiException e) {
-            msoLogger.error(e);
+            logger.error("Exception occurred", e);
             ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, MsoLogger.ErrorCode.SchemaError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
             ValidateException validateException = new ValidateException.Builder("Exception caught mapping Camunda JSON response to object", HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER).cause(e)
                         .errorInfo(errorLoggerInfo).build();
@@ -858,20 +1037,22 @@ public class ServiceInstances {
                                try {
                                        ObjectMapper mapper = new ObjectMapper();
                                        jsonResponse = mapper.readValue(camundaResp.getResponse(), ServiceInstancesResponse.class);
+                                       jsonResponse.getRequestReferences().setRequestId(requestClientParameter.getRequestId());
+                                       Optional<URL> selfLinkUrl = msoRequest.buildSelfLinkUrl(currentActiveReq.getRequestUrl(), requestClientParameter.getRequestId());
+                                       if(selfLinkUrl.isPresent()){
+                                               jsonResponse.getRequestReferences().setRequestSelfLink(selfLinkUrl.get());
+                                       } else {
+                                           jsonResponse.getRequestReferences().setRequestSelfLink(null);
+                                       }    
                                } catch (IOException e) {
-                                       msoLogger.error(e);
+                                       logger.error("Exception occurred", e);
                                        ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, MsoLogger.ErrorCode.SchemaError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
                                        ValidateException validateException = new ValidateException.Builder("Exception caught mapping Camunda JSON response to object", HttpStatus.SC_NOT_ACCEPTABLE, ErrorNumbers.SVC_BAD_PARAMETER).cause(e)
                                            .errorInfo(errorLoggerInfo).build();
                                        updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
                                        throw validateException;
-                               }
-                       
-                               currentActiveReq.setRequestStatus(Status.IN_PROGRESS.name());
-                               setInstanceId(currentActiveReq, requestScope, jsonResponse.getRequestReferences().getInstanceId(), new HashMap<>());
-                               
-                               infraActiveRequestsClient.save(currentActiveReq);
-                               return builder.buildResponse(HttpStatus.SC_ACCEPTED, requestId, jsonResponse, apiVersion);
+                               }       
+                               return builder.buildResponse(HttpStatus.SC_ACCEPTED, requestClientParameter.getRequestId(), jsonResponse, requestClientParameter.getApiVersion());
                        } 
                }
                        
@@ -914,6 +1095,8 @@ public class ServiceInstances {
                                currentActiveReq.setNetworkId(instanceId);
                        } else if(ModelType.configuration.name().equalsIgnoreCase(requestScope)) {
                                currentActiveReq.setConfigurationId(instanceId);
+                       }else if(ModelType.instanceGroup.toString().equalsIgnoreCase(requestScope)){
+                               currentActiveReq.setInstanceGroupId(instanceId);
                        }
                } else if(instanceIdMap != null && !instanceIdMap.isEmpty()) {
                        if(instanceIdMap.get("serviceInstanceId") != null){
@@ -934,21 +1117,27 @@ public class ServiceInstances {
                if(instanceIdMap.get("configurationInstanceId") != null){
                        currentActiveReq.setConfigurationId(instanceIdMap.get("configurationInstanceId"));
                }
+               if(instanceIdMap.get("InstanceGroupInstanceId") != null){
+                       currentActiveReq.setInstanceGroupId(instanceIdMap.get("InstanceGroupInstanceId"));
+               }
                }
        }
 
     protected String mapJSONtoMSOStyle(String msoRawRequest, ServiceInstancesRequest serviceInstRequest, boolean isAlaCarte, Actions action) throws IOException {
        ObjectMapper mapper = new ObjectMapper();       
        mapper.setSerializationInclusion(Include.NON_NULL);     
-       ServiceInstancesRequest sir = mapper.readValue(msoRawRequest, ServiceInstancesRequest.class);           
-       if(     !isAlaCarte && Action.createInstance.equals(action) && serviceInstRequest != null && 
-               serviceInstRequest.getRequestDetails() != null && 
-               serviceInstRequest.getRequestDetails().getRequestParameters() != null) {
-               sir.getRequestDetails().setCloudConfiguration(serviceInstRequest.getRequestDetails().getCloudConfiguration());
-               sir.getRequestDetails().getRequestParameters().setUserParams(serviceInstRequest.getRequestDetails().getRequestParameters().getUserParams());
+       if(msoRawRequest != null){
+               ServiceInstancesRequest sir = mapper.readValue(msoRawRequest, ServiceInstancesRequest.class);           
+               if(     !isAlaCarte && Action.createInstance.equals(action) && serviceInstRequest != null && 
+                       serviceInstRequest.getRequestDetails() != null && 
+                       serviceInstRequest.getRequestDetails().getRequestParameters() != null) {
+                       sir.getRequestDetails().setCloudConfiguration(serviceInstRequest.getRequestDetails().getCloudConfiguration());
+                       sir.getRequestDetails().getRequestParameters().setUserParams(serviceInstRequest.getRequestDetails().getRequestParameters().getUserParams());
+               }
+               logger.debug("Value as string: {}", mapper.writeValueAsString(sir));
+               return mapper.writeValueAsString(sir);
        }
-       msoLogger.debug("Value as string: " + mapper.writeValueAsString(sir));
-       return mapper.writeValueAsString(sir);
+       return null;
        }
 
     private void buildErrorOnDuplicateRecord(InfraActiveRequests currentActiveReq, Actions action, HashMap<String, String> instanceIdMap, long startTime, MsoRequest msoRequest,
@@ -983,17 +1172,56 @@ public class ServiceInstances {
                        }
                } catch (Exception e) {
             ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_DUPLICATE_CHECK_EXC, MsoLogger.ErrorCode.DataError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
-
-
-            ValidateException validateException = new ValidateException.Builder("Duplicate Check Request", HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
+            RequestDbFailureException requestDbFailureException = new RequestDbFailureException.Builder("check for duplicate instance", e.toString(), HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
                     .errorInfo(errorLoggerInfo).build();
-
-            updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
-
-            throw validateException;
+            updateStatus(currentActiveReq, Status.FAILED, requestDbFailureException.getMessage());
+            throw requestDbFailureException;
                }
                return dup;
        }
+    protected boolean camundaHistoryCheck(InfraActiveRequests duplicateRecord, InfraActiveRequests currentActiveReq) throws RequestDbFailureException, ContactCamundaException{
+       String requestId = duplicateRecord.getRequestId();
+       String path = env.getProperty("mso.camunda.rest.history.uri") + requestId;
+       String targetUrl = env.getProperty("mso.camundaURL") + path;
+       HttpHeaders headers = setCamundaHeaders(env.getRequiredProperty("mso.camundaAuth"), env.getRequiredProperty("mso.msoKey")); 
+       HttpEntity<?> requestEntity = new HttpEntity<>(headers);
+       ResponseEntity<List<HistoricProcessInstanceEntity>> response = null;
+       try{
+               response = restTemplate.exchange(targetUrl, HttpMethod.GET, requestEntity, new ParameterizedTypeReference<List<HistoricProcessInstanceEntity>>(){});
+       }catch(HttpStatusCodeException e){
+               ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_DUPLICATE_CHECK_EXC, MsoLogger.ErrorCode.DataError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
+            ContactCamundaException contactCamundaException= new ContactCamundaException.Builder(requestId, e.toString(), HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
+                    .errorInfo(errorLoggerInfo).build();
+            updateStatus(currentActiveReq, Status.FAILED, contactCamundaException.getMessage());
+            throw contactCamundaException;
+               }
+       if(response.getBody().isEmpty()){
+               updateStatus(duplicateRecord, Status.COMPLETE, "Request Completed");
+       }
+               for(HistoricProcessInstance instance : response.getBody()){
+                       if(instance.getState().equals("ACTIVE")){
+                               return true;
+                       }else{
+                               updateStatus(duplicateRecord, Status.COMPLETE, "Request Completed");
+                       }
+       }       
+               return false;
+       }
+    protected HttpHeaders setCamundaHeaders(String auth, String msoKey) {
+               HttpHeaders headers = new HttpHeaders();
+               List<org.springframework.http.MediaType> acceptableMediaTypes = new ArrayList<>();
+               acceptableMediaTypes.add(org.springframework.http.MediaType.APPLICATION_JSON);
+               headers.setAccept(acceptableMediaTypes);
+               try {
+                       String userCredentials = CryptoUtils.decrypt(auth, msoKey);
+                       if(userCredentials != null) {
+                               headers.add(HttpHeaders.AUTHORIZATION, "Basic " + DatatypeConverter.printBase64Binary(userCredentials.getBytes()));
+                       }
+        } catch(GeneralSecurityException e) {
+                logger.error("Security exception", e);
+        }
+               return headers;
+       }
 
        private ServiceInstancesRequest convertJsonToServiceInstanceRequest(String requestJSON, Actions action, long startTime,
                                                                         ServiceInstancesRequest sir, MsoRequest msoRequest, String requestId, String requestUri) throws ApiException {
@@ -1016,11 +1244,12 @@ public class ServiceInstances {
        }
        
        private void parseRequest(ServiceInstancesRequest sir, HashMap<String, String> instanceIdMap, Actions action, String version, 
-                                                               String requestJSON, Boolean aLaCarte, String requestId, InfraActiveRequests currentActiveReq) throws ValidateException {
+                                                               String requestJSON, Boolean aLaCarte, String requestId, InfraActiveRequests currentActiveReq) throws ValidateException, RequestDbFailureException {
                int reqVersion = Integer.parseInt(version.substring(1));
                try {
                        msoRequest.parse(sir, instanceIdMap, action, version, requestJSON, reqVersion, aLaCarte);
                } catch (Exception e) {
+                       logger.error("failed to parse request", e);
                        ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, MsoLogger.ErrorCode.SchemaError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
                ValidateException validateException = new ValidateException.Builder("Error parsing request: " + e.getMessage(), HttpStatus.SC_BAD_REQUEST, ErrorNumbers.SVC_BAD_PARAMETER).cause(e)
                  .errorInfo(errorLoggerInfo).build();
@@ -1040,7 +1269,9 @@ public class ServiceInstances {
                
                if (action == Action.applyUpdatedConfig || action == Action.inPlaceSoftwareUpdate) {
                        recipeLookupResult = getDefaultVnfUri(sir, action);
-        } else if (modelInfo.getModelType().equals(ModelType.service)) {
+        }else if(action == Action.addMembers || action == Action.removeMembers){
+               recipeLookupResult = new RecipeLookupResult("/mso/async/services/WorkflowActionBB", 180);
+        }else if (modelInfo.getModelType().equals(ModelType.service)) {
                        try {
                        recipeLookupResult = getServiceURI(sir, action,alaCarteFlag);
                        } catch (IOException e) {
@@ -1082,7 +1313,9 @@ public class ServiceInstances {
                 updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
 
                 throw validateException;
-               }
+            }
+        }else if(modelInfo.getModelType().equals(ModelType.instanceGroup)){
+               recipeLookupResult = new RecipeLookupResult("/mso/async/services/WorkflowActionBB", 180);
         }
 
         if (recipeLookupResult == null) {
@@ -1218,13 +1451,14 @@ public class ServiceInstances {
                        targetConfiguration.setAicNodeClli(sourceCloudConfiguration.getAicNodeClli());
                        targetConfiguration.setTenantId(sourceCloudConfiguration.getTenantId());
                        targetConfiguration.setLcpCloudRegionId(sourceCloudConfiguration.getLcpCloudRegionId());
+                       targetConfiguration.setCloudOwner(sourceCloudConfiguration.getCloudOwner());
                        return Optional.of(targetConfiguration);
                }
                return Optional.empty();
        }
 
        protected List<Map<String, Object>> configureUserParams(RequestParameters reqParams) throws IOException {
-       msoLogger.debug("Configuring UserParams for Macro Request");
+       logger.debug("Configuring UserParams for Macro Request");
        Map<String, Object> userParams = new HashMap<>();
        
        for(Map<String, Object> params : reqParams.getUserParams()){
@@ -1512,7 +1746,9 @@ public class ServiceInstances {
                Recipe recipe = null;
 
                if(modelInfo.getModelCustomizationId()!=null){
-            NetworkResource networkResource = catalogDbClient.getNetworkResourceCustomizationByModelCustomizationUUID(modelInfo.getModelCustomizationId()).getNetworkResource();
+            NetworkResourceCustomization networkResourceCustomization = catalogDbClient.getNetworkResourceCustomizationByModelCustomizationUUID(modelInfo.getModelCustomizationId());
+                       if(networkResourceCustomization != null){
+                               NetworkResource networkResource = networkResourceCustomization.getNetworkResource();
                        if(networkResource!=null){
                                if(modelInfo.getModelVersionId() == null) {
                                        modelInfo.setModelVersionId(networkResource.getModelUUID());
@@ -1521,6 +1757,9 @@ public class ServiceInstances {
                        }else{
                                throw new ValidationException("no catalog entry found");
                        }
+                       }else if(action != Action.deleteInstance){
+                               throw new ValidationException("modelCustomizationId for networkResourceCustomization lookup", true);
+                       }
                }else{
                        //ok for version < 3 and action delete
                        if(modelName != null){
@@ -1555,7 +1794,7 @@ public class ServiceInstances {
                        testApi = TestApi.valueOf(requestTestApi);
                        return Optional.of(testApi.getModelName());
                } catch (Exception e) {
-                       msoLogger.warnSimple("Catching the exception on the valueOf enum call and continuing", e);
+                       logger.warn("Catching the exception on the valueOf enum call and continuing", e);
                        throw new IllegalArgumentException("Invalid TestApi is provided", e);
                }
     }
@@ -1573,6 +1812,7 @@ public class ServiceInstances {
                String serviceInstanceId = (instanceIdMap ==null)? null:instanceIdMap.get("serviceInstanceId");
                Boolean aLaCarte = null;
                String apiVersion = version.substring(1);
+               boolean inProgress = false;
                
                long startTime = System.currentTimeMillis ();
                ServiceInstancesRequest sir = null;             
@@ -1590,8 +1830,12 @@ public class ServiceInstances {
                InfraActiveRequests dup = null;
                
                dup = duplicateCheck(action, instanceIdMap, startTime, msoRequest, instanceName,requestScope, currentActiveReq);
+               
+               if(dup != null){
+                       inProgress = camundaHistoryCheck(dup, currentActiveReq);
+               }
 
-               if (instanceIdMap != null && dup != null) {
+               if (instanceIdMap != null && dup != null && inProgress) {
             buildErrorOnDuplicateRecord(currentActiveReq, action, instanceIdMap, startTime, msoRequest, instanceName, requestScope, dup);
                }
                
@@ -1621,7 +1865,7 @@ public class ServiceInstances {
                
                serviceInstanceId = "";
                String configurationId = "";
-               String correlationId = "";
+               String pnfCorrelationId = "";
 
                if(sir.getServiceInstanceId () != null){
                        serviceInstanceId = sir.getServiceInstanceId ();
@@ -1630,22 +1874,46 @@ public class ServiceInstances {
                if(sir.getConfigurationId() != null){
             configurationId = sir.getConfigurationId();
         }
-               if (sir.getCorrelationId() != null) {
-                       correlationId = sir.getCorrelationId();
+
+        pnfCorrelationId = getPnfCorrelationId(sir);
+
+               try{
+                       infraActiveRequestsClient.save(currentActiveReq);
+               }catch(Exception e){
+                       ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, MsoLogger.ErrorCode.DataError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
+            throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(), HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
+                    .errorInfo(errorLoggerInfo).build();
                }
-               infraActiveRequestsClient.save(currentActiveReq);
                
                if(!requestScope.equalsIgnoreCase(ModelType.service.name())){
                        aLaCarte = true;
                }else if(aLaCarte == null){
                        aLaCarte = false;
                }
-       
-               return postBPELRequest(currentActiveReq,action, requestId, startTime, requestJSON, orchestrationUri, Integer.parseInt(timeOut), false, 
-                                                               serviceInstanceId, correlationId, null, null, null, null, configurationId, null, null, null, null, apiVersion, aLaCarte, requestUri, null, requestScope, null);
+               RequestClientParameter requestClientParameter = null;
+               try {
+                       requestClientParameter = new RequestClientParameter.Builder()
+                               .setRequestId(requestId)
+                               .setBaseVfModule(false)
+                               .setRecipeTimeout(Integer.parseInt(timeOut))
+                               .setRequestAction(action.toString())
+                               .setServiceInstanceId(serviceInstanceId)
+                               .setPnfCorrelationId(pnfCorrelationId)
+                               .setConfigurationId(configurationId)
+                               .setRequestDetails(mapJSONtoMSOStyle(requestJSON, sir, aLaCarte, action))
+                               .setApiVersion(apiVersion)
+                               .setALaCarte(aLaCarte)
+                               .setRequestUri(requestUri).build();
+               } catch (IOException e) {
+                       ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, MsoLogger.ErrorCode.SchemaError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
+                       throw new ValidateException.Builder("Unable to generate RequestClientParamter object" + e.getMessage(), HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER)
+                           .errorInfo(errorLoggerInfo).build();
+               }
+                               
+                       return postBPELRequest(currentActiveReq, requestClientParameter, orchestrationUri, requestScope);
        }
 
-    public String getRequestId(ContainerRequestContext requestContext) throws ValidateException {
+       public String getRequestId(ContainerRequestContext requestContext) throws ValidateException {
        String requestId = null;
        if (requestContext.getProperty("requestId") != null) {
                requestId = requestContext.getProperty("requestId").toString();
@@ -1660,14 +1928,46 @@ public class ServiceInstances {
                        throw validateException;
        }
     }
-       public void updateStatus(InfraActiveRequests aq, Status status, String errorMessage){
+       public void updateStatus(InfraActiveRequests aq, Status status, String errorMessage) throws RequestDbFailureException{
                if ((status == Status.FAILED) || (status == Status.COMPLETE)) {
                        aq.setStatusMessage (errorMessage);
                        aq.setProgress(new Long(100));
                        aq.setRequestStatus(status.toString());
                        Timestamp endTimeStamp = new Timestamp (System.currentTimeMillis());
                        aq.setEndTime (endTimeStamp);
-                       infraActiveRequestsClient.save(aq);
+                       try{
+                               infraActiveRequestsClient.save(aq);
+                       }catch(Exception e){
+                               ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, MsoLogger.ErrorCode.DataError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
+                   throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(), HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
+                           .errorInfo(errorLoggerInfo).build();
+                       }
+               }
+       }
+       protected String getServiceType(String requestScope, ServiceInstancesRequest sir, Boolean aLaCarteFlag){
+               String serviceType = null;
+               if(requestScope.equalsIgnoreCase(ModelType.service.toString())){
+                       String defaultServiceModelName = getDefaultModel(sir);
+                       org.onap.so.db.catalog.beans.Service serviceRecord;
+                       if(aLaCarteFlag){
+                                serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
+                                if(serviceRecord != null){
+                                        serviceType = serviceRecord.getServiceType();
+                                }
+                       }else{
+                               serviceRecord = catalogDbClient.getServiceByID(sir.getRequestDetails().getModelInfo().getModelVersionId());
+                               if(serviceRecord != null){
+                                        serviceType = serviceRecord.getServiceType();
+                                }else{
+                                        serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
+                                        if(serviceRecord != null){
+                                                serviceType = serviceRecord.getServiceType();
+                                        }
+                                }
+                       }
+               }else{
+                       serviceType = msoRequest.getServiceInstanceType(sir, requestScope);
                }
+               return serviceType;
        }
 }