Fix multiple instantations via serviceOrder
[externalapi/nbi.git] / src / main / java / org / onap / nbi / apis / serviceorder / workflow / PostSoProcessor.java
index e590afc..83e3785 100644 (file)
@@ -20,6 +20,9 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+import java.util.Random;
 
 import org.onap.nbi.apis.servicecatalog.ServiceSpecificationService;
 import org.onap.nbi.apis.serviceorder.SoClient;
@@ -27,6 +30,7 @@ import org.onap.nbi.apis.serviceorder.model.ServiceCharacteristic;
 import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
 import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
 import org.onap.nbi.apis.serviceorder.model.StateType;
+import org.onap.nbi.apis.serviceorder.model.ServiceStateType;
 import org.onap.nbi.apis.serviceorder.model.consumer.CloudConfiguration;
 import org.onap.nbi.apis.serviceorder.model.consumer.CreateE2EServiceInstanceResponse;
 import org.onap.nbi.apis.serviceorder.model.consumer.CreateMacroServiceInstanceResponse;
@@ -180,20 +184,34 @@ public class PostSoProcessor {
                         service.getServiceType(), serviceOrderItem.getService().getId());
                 break;
             case MODIFY:
-                if (StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState()) {
+            //EXT-API supports E2E service activation/deactivation with action=modify and seviceState=active/inactive
+               boolean isActivateReq = ServiceStateType.ACTIVE == serviceOrderItem.getService().getServiceState() ||
+                               ServiceStateType.INACTIVE == serviceOrderItem.getService().getServiceState();
+
+                if (ServiceStateType.ACTIVE == serviceOrderItem.getService().getServiceState()) {
+                       response = soClient.callServiceActivationE2EService(service.getGlobalSubscriberId(),
+                            service.getServiceType(), serviceOrderItem.getService().getId(),"activate");
+               }
+               if (ServiceStateType.INACTIVE == serviceOrderItem.getService().getServiceState()) {
+                       response = soClient.callServiceActivationE2EService(service.getGlobalSubscriberId(),
+                            service.getServiceType(), serviceOrderItem.getService().getId(),"deactivate");
+               }
+               //Other E2E service modification follows Deletion followed by activation.
+               //For service modification, do not send serviceState=active/inactive
+               if (!isActivateReq && StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState()) {
                     response = soClient.callE2ECreateServiceInstance(msoE2EPayload);
                 }
-                if (StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
+                if (!isActivateReq && StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
                     response = soClient.callE2EDeleteServiceInstance(service.getGlobalSubscriberId(),
                             service.getServiceType(), serviceOrderItem.getService().getId());
                 }
                 break;
-            default:
+           default:
                 break;
         }
         return response;
     }
-    
     private ResponseEntity<CreateMacroServiceInstanceResponse> postSOMacroRequest(ServiceOrderItem serviceOrderItem,
                             ServiceOrderInfo serviceOrderInfo) {
       
@@ -209,8 +227,8 @@ public class PostSoProcessor {
           response = soClient.callMacroCreateServiceInstance(msoMacroPayload);
           break;
         case DELETE:
-          // response = soClient.callDeleteServiceInstance(msoPayload,
-          // serviceOrderItem.getService().getId());
+           response = soClient.callMacroDeleteServiceInstance(msoMacroPayload,
+           serviceOrderItem.getService().getId());
           break;
         case MODIFY:
           if (StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState()) {
@@ -248,21 +266,33 @@ public class PostSoProcessor {
 
                Map<String, Object> resourseSpecificationMap = resourseSpecificationArray.get(0);
 
+               Map serviceInstanceParam = (Map) resourseSpecificationMap.get("serviceInstanceParams");
                Map instanceSpecification = (Map) resourseSpecificationMap.get("InstanceSpecification");
                ArrayList<VFModelInfo> childResourceSpecification = (ArrayList<VFModelInfo>) resourseSpecificationMap
                                .get("childResourceSpecification");
+               
+               HashMap<String, Object> instanceParamsFromServiceCharacteristics = retrieveInstanceParamsFromServiceCharacteristics(
+                               orderItem.getService().getServiceCharacteristic());
+               
+               HashMap<String, Object> instanceParams = (HashMap<String, Object>) buildAndDistinguishServiceAndVnfLevelParams(
+                               instanceParamsFromServiceCharacteristics, instanceSpecification, serviceInstanceParam);
 
+               HashMap<String, Object> vnfInstanceParams = (HashMap<String, Object>) instanceParams.get("vnf");
                List<Object> serviceObject = new ArrayList<>();
 
                ArrayList<Object> vnfInstanceParam = new ArrayList<>();
 
                //Differentiating vnf with cnf(Can be discussed and improved)
                if (instanceSpecification.get("public_net_id") != null) {
+                       Map<String, Object> instanceParam = new HashMap<>();
+                       //Merge instanceSpecification with vnfInstanceParams
+                       instanceSpecification.putAll(vnfInstanceParams);
                        vnfInstanceParam.add(instanceSpecification);
                } else {
-                       Map<String, Object> instanceParam = new HashMap<>();
-                       instanceParam.put("k8s-rb-profile-name", k8sRbProfileName);
-                       vnfInstanceParam.add(instanceParam);
+                       //if skip_post_instantiation_configuration is true then add k8s-rb-profile-name
+                       if(instanceSpecification.get("skip_post_instantiation_configuration").equals(true))
+                               vnfInstanceParams.put("k8s-rb-profile-name", k8sRbProfileName);
+                       vnfInstanceParam.add(vnfInstanceParams);
                }
 
                List resSpec = (ArrayList) sdcInfos.get("resourceSpecification");
@@ -292,13 +322,22 @@ public class PostSoProcessor {
                Map<String, String> lob = new HashMap<>();
                lob.put("lineOfBusinessName", "LOB-Demonstration");
 
+               //Create a random variable that will be concatanate to the instanceName
+               Random rand = new Random();
+               int upperbound = 100000;
+               //generate random values from 0-upperbound
+               int int_random = rand.nextInt(upperbound); 
+               
+               String vnfInstanceNameTmp = (String) resSpecMap.get("resourceInstanceName");
+               String vnfInstanceName = vnfInstanceNameTmp + int_random;
+               
                Map<String, Object> vnfModel = new HashMap<>();
                vnfModel.put("modelInfo", vnfInfoObject);
                vnfModel.put("cloudConfiguration", cloudConfiguration);
                vnfModel.put("platform", platformName);
                vnfModel.put("lineOfBusiness", lob);
                vnfModel.put("productFamilyId", "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb");
-               vnfModel.put("instanceName", (String) resSpecMap.get("resourceInstanceName"));
+               vnfModel.put("instanceName", vnfInstanceName);
                vnfModel.put("instanceParams", vnfInstanceParam);
 
                List<Object> vfModulesObjects = new ArrayList<>();
@@ -310,7 +349,8 @@ public class PostSoProcessor {
                        
                } else {
                        Map<String, Object> instanceParam = new HashMap<>();
-                       instanceParam.put("k8s-rb-profile-name", k8sRbProfileName);
+                       if(instanceSpecification.get("skip_post_instantiation_configuration").equals(true))
+                               instanceParam.put("k8s-rb-profile-name", k8sRbProfileName);
                        vfInstanceParam.add(instanceParam);
                }
                
@@ -318,13 +358,19 @@ public class PostSoProcessor {
                        Map<String, Object> vfModuleObject = new HashMap<>();
                        Map<String, String> vfModuleInfo = new HashMap<>();
 
+                       //generate random values from 0-upperbound
+                       int_random = rand.nextInt(upperbound); 
+               
+                       String vfmoduleInstanceNameTmp = (String) crsObject.getModelName();
+                       String vfmoduleInstanceName = vfmoduleInstanceNameTmp + int_random;     
+               
                        vfModuleInfo.put("modelName", crsObject.getModelName());
                        vfModuleInfo.put("modelVersionId", crsObject.getModelUuid());
                        vfModuleInfo.put("modelInvariantUuid", crsObject.getModelInvariantUuid());
                        vfModuleInfo.put("modelVersion", crsObject.getModelVersion());
                        vfModuleInfo.put("modelCustomizationId", crsObject.getModelCustomizationUuid());
                        vfModuleObject.put("modelInfo", vfModuleInfo);
-                       vfModuleObject.put("instanceName", crsObject.getModelName());
+                       vfModuleObject.put("instanceName", vfmoduleInstanceName);
                        vfModuleObject.put("instanceParams", vfInstanceParam);
 
                        vfModulesObjects.add(vfModuleObject);
@@ -349,7 +395,7 @@ public class PostSoProcessor {
                // For now it is empty to comply with so request
 
                List<Map<String, String>> listOfServiceLevelInstanceParams = new ArrayList<>();
-               Map<String, String> serviceInstanceParams= new HashMap<>();
+               Map<String, String> serviceInstanceParams = (HashMap<String, String>) instanceParams.get("service");
                listOfServiceLevelInstanceParams.add(serviceInstanceParams);
                
                Map<String, Object> serviceData = new HashMap<>();
@@ -563,5 +609,89 @@ public class PostSoProcessor {
 
         return userParams;
     }
+    
+    /**
+        * Build a list of InstanceParams for the SO Macro request by browsing a list of
+        * ServiceCharacteristics
+        */
+       private HashMap<String, Object> retrieveInstanceParamsFromServiceCharacteristics(
+                       List<ServiceCharacteristic> characteristics) {
+
+               HashMap<String, Object> instanceParams = new HashMap<>();
+
+               if (!CollectionUtils.isEmpty(characteristics)) {
+                       for (ServiceCharacteristic characteristic : characteristics) {
+                               // Check is the characteristic is of type object, if proceed as before to allow
+                               // for
+                               // backwards compatibility.
+                               if (characteristic.getValueType() != null && !characteristic.getValueType().isEmpty()
+                                               && characteristic.getValueType().equals("object")) {
+                                       ObjectMapper mapper = new ObjectMapper();
+                                       JsonNode jsonNode = null;
+                                       try {
+                                               jsonNode = mapper.readTree(characteristic.getValue().getServiceCharacteristicValue());
+                                       } catch (IOException e) {
+                                               LOGGER.error("Failed to read object json {} , exception is ",
+                                                               characteristic.getValue().getServiceCharacteristicValue(), e.getMessage());
+                                       }
+                                       ObjectNode objectNode = (ObjectNode) jsonNode;
+                                       Iterator<Map.Entry<String, JsonNode>> iter = objectNode.fields();
+                                       while (iter.hasNext()) {
+                                               Map.Entry<String, JsonNode> entry = iter.next();
+                                               if (!entry.getValue().isArray()) {
+                                                       instanceParams.put(entry.getKey(), entry.getValue().asText());
+                                               } else {
+                                                       ArrayNode arrayNode = (ArrayNode) entry.getValue();
+                                                       String arrayNodeValueString = arrayNode.toString();
+                                                       instanceParams.put(entry.getKey(), arrayNodeValueString);
+                                               }
+                                       }
+                               } else {
+                                       instanceParams.put(characteristic.getName(),
+                                                       characteristic.getValue().getServiceCharacteristicValue());
+                               }
+                       }
+               }
+
+               return instanceParams;
+       }
+       
+       /**
+        * Build and distinguish InstanceParams at VNF Level and Service level and overwrite values from ServiceOrder JSON Request.
+        * Can be used as buildAndDistinguishServiceAndVnfLevelParams.get("vnf"); or buildAndDistinguishServiceAndVnfLevelParams.get("cnf");
+        */
+       private Map<String, Object> buildAndDistinguishServiceAndVnfLevelParams(
+                       Map<String, Object> instanceParamsFromServiceCharacteristic, Map<String, Object> existingVNFParams,
+                       Map<String, Object> existingServiceParams) {
+
+               //To be used by passing key as "vnf" or "service" for respective instanceParams
+               Map<String, Object> serviceAndVNFLevelInstanceParams = new HashMap<>();
+
+               Map<String, Object> resultVNFParams = new HashMap<>();
+               Map<String, Object> resultServiceParams = new HashMap<>();
+
+               // First Filter VNF level Params From Service Characteristics and overwrite
+               // values
+               resultVNFParams = instanceParamsFromServiceCharacteristic.entrySet().stream()
+                               .filter(entry -> existingVNFParams.containsKey(entry.getKey()))
+                               .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
+
+               //Add it as VNF level Params
+               serviceAndVNFLevelInstanceParams.put("vnf", resultVNFParams);
+
+               // Filter VNF level Params From Service Level
+               existingServiceParams.entrySet().removeIf(e -> existingVNFParams.containsKey(e.getKey()));
+
+               // Filter Service level Params From Service Characteristics and overwrite values
+               resultServiceParams = instanceParamsFromServiceCharacteristic.entrySet().stream()
+                               .filter(entry -> existingServiceParams.containsKey(entry.getKey()))
+                               .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
+
+               //Add it as Service level params
+               serviceAndVNFLevelInstanceParams.put("service", resultServiceParams);
+
+               return serviceAndVNFLevelInstanceParams;
+
+       }
 
-}
\ No newline at end of file
+}