Refactor OofHomingV2 02/84602/6
authorMarcus G K Williams <marcus.williams@intel.com>
Tue, 9 Apr 2019 04:59:29 +0000 (21:59 -0700)
committerMarcus G K Williams <marcus.williams@intel.com>
Tue, 9 Apr 2019 17:52:34 +0000 (10:52 -0700)
Refactor OofHomingV2 Java
to working state and fix IT tests.

Issue-ID: SO-1469
Change-Id: I8647058adf5ed41c5bebebee79f9dbc4d80c2974
Signed-off-by: Marcus G K Williams <marcus.williams@intel.com>
14 files changed:
bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/bbobjects/Customer.java
bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/buildingblock/OofHomingV2.java
bpmn/so-bpmn-tasks/src/main/java/org/onap/so/client/oof/beans/LicenseDemand.java [new file with mode: 0644]
bpmn/so-bpmn-tasks/src/main/java/org/onap/so/client/oof/beans/LicenseInfo.java [new file with mode: 0644]
bpmn/so-bpmn-tasks/src/main/java/org/onap/so/client/oof/beans/OofRequest.java
bpmn/so-bpmn-tasks/src/main/java/org/onap/so/client/oof/beans/PlacementDemand.java
bpmn/so-bpmn-tasks/src/main/java/org/onap/so/client/oof/beans/PlacementInfo.java
bpmn/so-bpmn-tasks/src/test/java/org/onap/so/BaseIntegrationTest.java
bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/flowspecific/tasks/OofHomingV2IT.java [new file with mode: 0644]
bpmn/so-bpmn-tasks/src/test/java/org/onap/so/client/oof/OofClientTestIT.java
bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest1Vpn.json [new file with mode: 0644]
bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest1VpnOpt.json [new file with mode: 0644]
bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest3Ar.json [new file with mode: 0644]
bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest3Vpn.json [new file with mode: 0644]

index 30492dd..d7b58ba 100644 (file)
@@ -46,6 +46,10 @@ public class Customer implements Serializable, ShallowCopy<Customer> {
     private String subscriberCommonSiteId;
     @JsonProperty("service-subscription")
     private ServiceSubscription serviceSubscription;
+    @JsonProperty("customer-latitude")
+    private String customerLatitude;
+    @JsonProperty("customer-longitude")
+    private String customerLongitude;
     @JsonProperty("vpn-bindings")
     private List<VpnBinding> vpnBindings = new ArrayList<>();
 
@@ -89,6 +93,22 @@ public class Customer implements Serializable, ShallowCopy<Customer> {
         this.serviceSubscription = serviceSubscription;
     }
 
+    public String getCustomerLatitude() {
+        return customerLatitude;
+    }
+
+    public void setCustomerLatitude(String customerLatitude) {
+        this.customerLatitude = customerLatitude;
+    }
+
+    public String getCustomerLongitude() {
+        return customerLongitude;
+    }
+
+    public void setCustomerLongitude(String customerLongitude) {
+        this.customerLongitude = customerLongitude;
+    }
+
     public List<VpnBinding> getVpnBindings() {
         return vpnBindings;
     }
index 2524fc7..2696313 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP - SO
  * ================================================================================
- * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019 Intel Corp. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
 package org.onap.so.bpmn.buildingblock;
 
 import org.apache.commons.lang.SerializationUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
 import org.camunda.bpm.engine.delegate.BpmnError;
 import java.util.ArrayList;
 import org.json.JSONArray;
@@ -38,7 +39,6 @@ import org.onap.so.bpmn.servicedecomposition.bbobjects.VpnBondingLink;
 import org.onap.so.bpmn.servicedecomposition.entities.GeneralBuildingBlock;
 import org.onap.so.bpmn.servicedecomposition.generalobjects.License;
 import org.onap.so.bpmn.servicedecomposition.generalobjects.RequestContext;
-import org.onap.so.bpmn.servicedecomposition.generalobjects.RequestParameters;
 import org.onap.so.bpmn.servicedecomposition.homingobjects.Candidate;
 import org.onap.so.bpmn.servicedecomposition.homingobjects.CandidateType;
 import org.onap.so.bpmn.servicedecomposition.homingobjects.SolutionCandidates;
@@ -49,13 +49,14 @@ import org.onap.so.client.exception.BadResponseException;
 import org.onap.so.client.exception.ExceptionBuilder;
 import org.onap.so.client.oof.OofClient;
 import org.onap.so.client.oof.OofValidator;
+import org.onap.so.client.oof.beans.LicenseDemand;
+import org.onap.so.client.oof.beans.LicenseInfo;
 import org.onap.so.client.oof.beans.ModelInfo;
 import org.onap.so.client.oof.beans.OofRequest;
 import org.onap.so.client.oof.beans.OofRequestParameters;
 import org.onap.so.client.oof.beans.PlacementDemand;
 import org.onap.so.client.oof.beans.PlacementInfo;
 import org.onap.so.client.oof.beans.RequestInfo;
-import org.onap.so.client.oof.beans.ResourceModelInfo;
 import org.onap.so.client.oof.beans.ServiceInfo;
 import org.onap.so.client.oof.beans.SubscriberInfo;
 import org.onap.so.db.catalog.beans.OrchestrationStatus;
@@ -85,7 +86,7 @@ public class OofHomingV2 {
     @Autowired
     private Environment env;
     @Autowired
-    private OofClient client;
+    private OofClient oofClient;
     @Autowired
     private OofValidator oofValidator;
     @Autowired
@@ -98,7 +99,6 @@ public class OofHomingV2 {
     private static final String RESOURCE_MODULE_NAME = "resourceModuleName";
     private static final String RESOURCE_MODEL_INFO = "resourceModelInfo";
     private static final String IDENTIFIER_TYPE = "identifierType";
-    private static final String INVENTORY_TYPE = "inventoryType";
     private static final String SOLUTIONS = "solutions";
     private static final String RESOURCE_MISSING_DATA = "Resource does not contain: ";
     private static final String SERVICE_MISSING_DATA = "Service Instance does not contain: ";
@@ -111,12 +111,11 @@ public class OofHomingV2 {
      * @param execution
      */
     public void callOof(BuildingBlockExecution execution) {
-        logger.trace("Started Sniro Homing Call Sniro");
+        logger.trace("Started Oof Homing Call Oof");
         try {
             GeneralBuildingBlock bb = execution.getGeneralBuildingBlock();
 
             RequestContext requestContext = bb.getRequestContext();
-            RequestParameters requestParams = requestContext.getRequestParameters();
             String requestId = requestContext.getMsoRequestId();
 
             ServiceInstance serviceInstance = bb.getCustomer().getServiceSubscription().getServiceInstances().get(0);
@@ -127,28 +126,24 @@ public class OofHomingV2 {
                 timeout = env.getProperty("oof.timeout", "PT30M");
             }
 
-            OofRequest request = new OofRequest();
+            OofRequest oofRequest = new OofRequest();
 
             RequestInfo requestInfo = (RequestInfo) buildRequestInfo(requestId, timeout);
-            request.setRequestInformation(requestInfo);
+            oofRequest.setRequestInformation(requestInfo);
 
             ServiceInfo serviceInfo = buildServiceInfo(serviceInstance);
-            request.setServiceInformation(serviceInfo);
+            oofRequest.setServiceInformation(serviceInfo);
 
-            PlacementInfo placementInfo = buildPlacementInfo(customer, requestParams);
+            PlacementInfo placementInfo = buildPlacementInfo(customer);
 
-            ArrayList<PlacementDemand> placementDemands = buildPlacementDemands(serviceInstance);
-            placementInfo.setPlacementDemands(placementDemands);
-            request.setPlacementInformation(placementInfo);
+            placementInfo = buildPlacementDemands(serviceInstance, placementInfo);
+            oofRequest.setPlacementInformation(placementInfo);
 
-            JSONObject licenseInfo = new JSONObject();
+            LicenseInfo licenseInfo = buildLicenseInfo(serviceInstance);
+            oofRequest.setLicenseInformation(licenseInfo);
 
-            JSONArray licenseDemands = buildLicenseDemands(serviceInstance);
-            licenseInfo.put("licenseDemands", licenseDemands);
-            request.setLicenseInformation(licenseInfo.toString());
-
-            if (placementDemands.size() > 0 || licenseDemands.length() > 0) {
-                client.postDemands(request);
+            if (!placementInfo.getPlacementDemands().isEmpty() || !licenseInfo.getLicenseDemands().isEmpty()) {
+                oofClient.postDemands(oofRequest);
             } else {
                 logger.debug(SERVICE_MISSING_DATA + " resources eligible for homing or licensing");
                 throw new BpmnError(UNPROCESSABLE,
@@ -162,12 +157,15 @@ public class OofHomingV2 {
 
             logger.trace("Completed Oof Homing Call Oof");
         } catch (BpmnError e) {
+            logger.debug(" Error - while preparing oof request: " + e.getStackTrace());
             exceptionUtil.buildAndThrowWorkflowException(execution, Integer.parseInt(e.getErrorCode()), e.getMessage());
         } catch (BadResponseException e) {
+            logger.debug(" Error - while preparing oof request: " + e.getStackTrace());
             exceptionUtil.buildAndThrowWorkflowException(execution, 400, e.getMessage());
         } catch (Exception e) {
-            exceptionUtil.buildAndThrowWorkflowException(execution, INTERNAL,
-                    "Internal Error - occurred while preparing oof request: " + e.getMessage());
+            logger.debug(" Error - while preparing oof request: " + e.getStackTrace());
+            exceptionUtil.buildAndThrowWorkflowException(execution, INTERNAL, "Internal Error - occurred while "
+                    + "preparing oof request: " + e + "   Stack:" + ExceptionUtils.getFullStackTrace(e));
         }
     }
 
@@ -240,6 +238,10 @@ public class OofHomingV2 {
             requestInfo.setSourceId("mso");
             requestInfo.setRequestType("create");
             requestInfo.setTimeout(timeoutSeconds);
+            requestInfo.setNumSolutions(1);
+            ArrayList optimizers = new ArrayList();
+            optimizers.add("placement");
+            requestInfo.setOptimizers(optimizers);
         } else {
             throw new BpmnError(UNPROCESSABLE, "Request Context does not contain: requestId");
         }
@@ -270,7 +272,7 @@ public class OofHomingV2 {
      * Builds initial section of placement info for the homing/licensing request
      *
      */
-    private PlacementInfo buildPlacementInfo(Customer customer, RequestParameters requestParams) {
+    private PlacementInfo buildPlacementInfo(Customer customer) {
         PlacementInfo placementInfo = new PlacementInfo();
         if (customer != null) {
             logger.debug("Adding subscriber to placement information");
@@ -279,22 +281,11 @@ public class OofHomingV2 {
             subscriberInfo.setSubscriberName(customer.getSubscriberName());
             subscriberInfo.setSubscriberCommonSiteId(customer.getSubscriberCommonSiteId());
             placementInfo.setSubscriberInfo(subscriberInfo);
-            if (requestParams != null) {
-                logger.debug("Adding request parameters to placement information");
-                OofRequestParameters oofRequestParams = new OofRequestParameters();
-                for (Map requestParam : requestParams.getUserParams()) {
-                    if (requestParam.containsKey("customerLatitude")) {
-                        oofRequestParams.setCustomerLatitude(requestParam.get("customerLatitude").toString());
-                    }
-                    if (requestParam.containsKey("customerLongitude")) {
-                        oofRequestParams.setCustomerLongitude(requestParam.get("customerLongitude").toString());
-                    }
-                    if (requestParam.containsKey("customerName")) {
-                        oofRequestParams.setCustomerName(requestParam.get("customerName").toString());
-                    }
-                }
-                placementInfo.setRequestParameters(oofRequestParams);
-            }
+            OofRequestParameters oofRequestParams = new OofRequestParameters();
+            oofRequestParams.setCustomerLatitude(customer.getCustomerLatitude());
+            oofRequestParams.setCustomerLongitude(customer.getCustomerLongitude());
+            oofRequestParams.setCustomerName(customer.getSubscriberName());
+            placementInfo.setRequestParameters(oofRequestParams);
         } else {
             throw new BpmnError(UNPROCESSABLE, SERVICE_MISSING_DATA + "customer");
         }
@@ -306,9 +297,8 @@ public class OofHomingV2 {
      * Builds the placement demand list for the homing/licensing request
      *
      */
-    private ArrayList<PlacementDemand> buildPlacementDemands(ServiceInstance serviceInstance) {
+    private PlacementInfo buildPlacementDemands(ServiceInstance serviceInstance, PlacementInfo placementInfo) {
         logger.trace("Building placement information demands");
-        ArrayList<PlacementDemand> placementDemands = new ArrayList();
 
         List<AllottedResource> allottedResourceList = serviceInstance.getAllottedResources();
         if (!allottedResourceList.isEmpty()) {
@@ -319,7 +309,7 @@ public class OofHomingV2 {
                 }
                 PlacementDemand demand = buildDemand(ar.getId(), ar.getModelInfoAllottedResource());
                 // addCandidates(ar, demand);
-                placementDemands.add(demand);
+                placementInfo.getPlacementDemands().add(demand);
             }
         }
         List<VpnBondingLink> vpnBondingLinkList = serviceInstance.getVpnBondingLinks();
@@ -333,42 +323,43 @@ public class OofHomingV2 {
                     }
                     PlacementDemand demand = buildDemand(sp.getId(), sp.getModelInfoServiceProxy());
                     // addCandidates(sp, demand);
-                    placementDemands.add(demand);
+                    placementInfo.getPlacementDemands().add(demand);
                 }
             }
         }
-        return placementDemands;
+        return placementInfo;
     }
 
     /**
      * Builds the license demand list for the homing/licensing request
      *
      */
-    private JSONArray buildLicenseDemands(ServiceInstance serviceInstance) {
+    private LicenseInfo buildLicenseInfo(ServiceInstance serviceInstance) {
         logger.trace("Building license information");
-        JSONArray licenseDemands = new JSONArray();
+        LicenseInfo licenseInfo = new LicenseInfo();
         List<GenericVnf> vnfList = serviceInstance.getVnfs();
         if (!vnfList.isEmpty()) {
             logger.debug("Adding vnfs to license demands list");
             for (GenericVnf vnf : vnfList) {
-                JSONObject demand = buildLicenseDemand(vnf.getVnfId(), vnf.getModelInfoGenericVnf());
-                licenseDemands.put(demand);
+                LicenseDemand demand = buildLicenseDemand(vnf.getVnfId(), vnf.getModelInfoGenericVnf());
+                licenseInfo.getLicenseDemands().add(demand);
             }
         }
-        return licenseDemands;
+        return licenseInfo;
     }
 
     /**
      * Builds a single license demand object
      *
      */
-    private JSONObject buildLicenseDemand(String id, ModelInfoMetadata metadata) {
+    private LicenseDemand buildLicenseDemand(String id, ModelInfoMetadata metadata) {
         logger.debug("Building demand for service or resource: " + id);
-        JSONObject demand = new JSONObject();
+        LicenseDemand demand = new LicenseDemand();
         if (isNotBlank(id) && isNotBlank(metadata.getModelInstanceName())) {
-            demand.put(SERVICE_RESOURCE_ID, id);
-            demand.put(RESOURCE_MODULE_NAME, metadata.getModelInstanceName());
-            demand.put(RESOURCE_MODEL_INFO, buildModelInfo(metadata));
+
+            demand.setServiceResourceId(id);
+            demand.setResourceModuleName(metadata.getModelInstanceName());
+            demand.setResourceModelInfo(buildModelInfo(metadata));
         } else {
             throw new BpmnError(UNPROCESSABLE, RESOURCE_MISSING_DATA + "modelInstanceName");
         }
@@ -385,7 +376,7 @@ public class OofHomingV2 {
         if (isNotBlank(id) && isNotBlank(metadata.getModelInstanceName())) {
             placementDemand.setServiceResourceId(id);
             placementDemand.setResourceModuleName(metadata.getModelInstanceName());
-            placementDemand.setResourceModelInfo((ResourceModelInfo) buildModelInfo(metadata));
+            placementDemand.setResourceModelInfo(buildModelInfo(metadata));
         } else {
             throw new BpmnError(UNPROCESSABLE, RESOURCE_MISSING_DATA + "modelInstanceName");
         }
@@ -525,11 +516,11 @@ public class OofHomingV2 {
         JSONArray assignments = placement.getJSONArray("assignmentInfo");
         Map<String, String> assignmentsMap = jsonUtils.entryArrayToMap(assignments.toString(), "key", "value");
         solutionInfo.setRehome(Boolean.parseBoolean(assignmentsMap.get("isRehome")));
-        String type = placement.getString(INVENTORY_TYPE);
+        String type = identifierType;
 
         ServiceInstance si = new ServiceInstance();
         CloudRegion cloud = setCloud(assignmentsMap);
-        if (type.equals("service")) {
+        if (type.equals("serviceInstanceId")) {
             if (identifierType.equals(CandidateType.SERVICE_INSTANCE_ID.toString())) {
                 solutionInfo.setHomed(true);
                 si.setServiceInstanceId(identifierValue);
@@ -556,7 +547,7 @@ public class OofHomingV2 {
                 logger.debug(invalidMessage + IDENTIFIER_TYPE);
                 throw new BpmnError(UNPROCESSABLE, invalidMessage + IDENTIFIER_TYPE);
             }
-        } else if (type.equals("cloud")) {
+        } else if (type.equals("cloudRegionId")) {
             if (identifierType.equals(CandidateType.CLOUD_REGION_ID.toString())) {
                 logger.debug("Resources has been homed to a cloud region");
                 cloud.setLcpCloudRegionId(identifierValue);
@@ -567,9 +558,6 @@ public class OofHomingV2 {
                 logger.debug(invalidMessage + IDENTIFIER_TYPE);
                 throw new BpmnError(UNPROCESSABLE, invalidMessage + IDENTIFIER_TYPE);
             }
-        } else {
-            logger.debug(invalidMessage + INVENTORY_TYPE);
-            throw new BpmnError(UNPROCESSABLE, invalidMessage + INVENTORY_TYPE);
         }
         si.setSolutionInfo(solutionInfo);
         return si;
diff --git a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/client/oof/beans/LicenseDemand.java b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/client/oof/beans/LicenseDemand.java
new file mode 100644 (file)
index 0000000..e64a545
--- /dev/null
@@ -0,0 +1,97 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 Intel Corp.  All rights reserved.
+ * ================================================================================
+ * 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
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.client.oof.beans;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonRootName;
+import java.io.Serializable;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({"resourceModuleName", "serviceResourceId", "tenantId", "resourceModelInfo"})
+@JsonRootName("licenseDemand")
+public class LicenseDemand implements Serializable {
+
+    private static final long serialVersionUID = -759180997599143791L;
+
+    @JsonProperty("resourceModuleName")
+    private String resourceModuleName;
+    @JsonProperty("serviceResourceId")
+    private String serviceResourceId;
+    @JsonProperty("tenantId")
+    private String tenantId;
+    @JsonProperty("resourceModelInfo")
+    private ResourceModelInfo resourceModelInfo;
+
+    @JsonProperty("resourceModuleName")
+    public String getResourceModuleName() {
+        return resourceModuleName;
+    }
+
+    @JsonProperty("resourceModuleName")
+    public void setResourceModuleName(String resourceModuleName) {
+        this.resourceModuleName = resourceModuleName;
+    }
+
+    @JsonProperty("serviceResourceId")
+    public String getServiceResourceId() {
+        return serviceResourceId;
+    }
+
+    @JsonProperty("serviceResourceId")
+    public void setServiceResourceId(String serviceResourceId) {
+        this.serviceResourceId = serviceResourceId;
+    }
+
+    @JsonProperty("tenantId")
+    public String getTenantId() {
+        return tenantId;
+    }
+
+    @JsonProperty("tenantId")
+    public void setTenantId(String tenantId) {
+        this.tenantId = tenantId;
+    }
+
+    @JsonProperty("resourceModelInfo")
+    public ResourceModelInfo getResourceModelInfo() {
+        return resourceModelInfo;
+    }
+
+    @JsonProperty("resourceModelInfo")
+    public void setResourceModelInfo(ResourceModelInfo resourceModelInfo) {
+        this.resourceModelInfo = resourceModelInfo;
+    }
+
+    public void setResourceModelInfo(ModelInfo modelInfo) {
+        ResourceModelInfo localResourceModelInfo = new ResourceModelInfo();
+        localResourceModelInfo.setModelVersionId(modelInfo.getModelVersionId());
+        localResourceModelInfo.setModelVersionId(modelInfo.getModelVersionId());
+        localResourceModelInfo.setModelVersion(modelInfo.getModelVersion());
+        localResourceModelInfo.setModelName(modelInfo.getModelName());
+        localResourceModelInfo.setModelType(modelInfo.getModelType());
+        localResourceModelInfo.setModelInvariantId(modelInfo.getModelInvariantId());
+        localResourceModelInfo.setModelCustomizationName(modelInfo.getModelCustomizationName());
+        this.resourceModelInfo = localResourceModelInfo;
+    }
+
+}
diff --git a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/client/oof/beans/LicenseInfo.java b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/client/oof/beans/LicenseInfo.java
new file mode 100644 (file)
index 0000000..74ff933
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 Intel Corp.  All rights reserved.
+ * ================================================================================
+ * 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
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.client.oof.beans;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonRootName;
+import java.io.Serializable;
+import java.util.ArrayList;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonRootName("licenseInfo")
+public class LicenseInfo implements Serializable {
+
+    private static final long serialVersionUID = -759180997599143791L;
+
+    @JsonProperty("licenseDemands")
+    private ArrayList<LicenseDemand> licenseDemands = new ArrayList<>();
+
+
+    @JsonProperty("licenseDemands")
+    public ArrayList<LicenseDemand> getLicenseDemands() {
+        return licenseDemands;
+    }
+
+    @JsonProperty("licenseDemands")
+    public void setLicenseDemands(ArrayList<LicenseDemand> licenseDemands) {
+        this.licenseDemands = licenseDemands;
+    }
+
+}
index e3c29fe..f889624 100644 (file)
@@ -46,7 +46,7 @@ public class OofRequest implements Serializable {
     private PlacementInfo placementInformation;
 
     @JsonProperty("licenseInfo")
-    private String licenseInformation;
+    private LicenseInfo licenseInformation;
 
 
     public RequestInfo getRequestInformation() {
@@ -73,11 +73,11 @@ public class OofRequest implements Serializable {
         this.placementInformation = placementInformation;
     }
 
-    public String getLicenseInformation() {
+    public LicenseInfo getLicenseInformation() {
         return licenseInformation;
     }
 
-    public void setLicenseInformation(String licenseInformation) {
+    public void setLicenseInformation(LicenseInfo licenseInformation) {
         this.licenseInformation = licenseInformation;
     }
 
index 73c100d..631b370 100644 (file)
@@ -82,4 +82,16 @@ public class PlacementDemand implements Serializable {
         this.resourceModelInfo = resourceModelInfo;
     }
 
+    public void setResourceModelInfo(ModelInfo modelInfo) {
+        ResourceModelInfo localResourceModelInfo = new ResourceModelInfo();
+        localResourceModelInfo.setModelVersionId(modelInfo.getModelVersionId());
+        localResourceModelInfo.setModelVersionId(modelInfo.getModelVersionId());
+        localResourceModelInfo.setModelVersion(modelInfo.getModelVersion());
+        localResourceModelInfo.setModelName(modelInfo.getModelName());
+        localResourceModelInfo.setModelType(modelInfo.getModelType());
+        localResourceModelInfo.setModelInvariantId(modelInfo.getModelInvariantId());
+        localResourceModelInfo.setModelCustomizationName(modelInfo.getModelCustomizationName());
+        this.resourceModelInfo = localResourceModelInfo;
+    }
+
 }
index 0eb14d9..7519e8c 100644 (file)
@@ -39,7 +39,7 @@ public class PlacementInfo implements Serializable {
     @JsonProperty("subscriberInfo")
     private SubscriberInfo subscriberInfo;
     @JsonProperty("placementDemands")
-    private ArrayList<PlacementDemand> placementDemands = null;
+    private ArrayList<PlacementDemand> placementDemands = new ArrayList<>();
 
     @JsonProperty("requestParameters")
     public OofRequestParameters getRequestParameters() {
index 3bb8fb7..43e4ce3 100644 (file)
@@ -23,9 +23,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import org.junit.Before;
 import org.junit.runner.RunWith;
+import org.onap.so.bpmn.buildingblock.OofHomingV2;
 import org.onap.so.bpmn.buildingblock.SniroHomingV2;
 import org.onap.so.bpmn.common.data.TestDataSetup;
 import org.onap.so.client.appc.ApplicationControllerAction;
+import org.onap.so.client.oof.OofClient;
 import org.onap.so.client.orchestration.SDNOHealthCheckResources;
 import org.onap.so.client.sdnc.SDNCClient;
 import org.onap.so.client.sniro.SniroClient;
@@ -63,6 +65,12 @@ public abstract class BaseIntegrationTest extends TestDataSetup {
     @SpyBean
     protected SniroClient sniroClient;
 
+    @SpyBean
+    protected OofHomingV2 oofHoming;
+
+    @SpyBean
+    protected OofClient oofClient;
+
     @MockBean
     protected ApplicationControllerAction appCClient;
 
diff --git a/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/flowspecific/tasks/OofHomingV2IT.java b/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/flowspecific/tasks/OofHomingV2IT.java
new file mode 100644 (file)
index 0000000..e066058
--- /dev/null
@@ -0,0 +1,594 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. & Intel Corp. All rights reserved.
+ * ================================================================================
+ * 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
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.bpmn.infrastructure.flowspecific.tasks;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.camunda.bpm.engine.delegate.BpmnError;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.onap.so.BaseIntegrationTest;
+import org.onap.so.bpmn.servicedecomposition.bbobjects.AllottedResource;
+import org.onap.so.bpmn.servicedecomposition.bbobjects.Customer;
+import org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf;
+import org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance;
+import org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceProxy;
+import org.onap.so.bpmn.servicedecomposition.bbobjects.VpnBondingLink;
+import org.onap.so.bpmn.servicedecomposition.generalobjects.RequestContext;
+import org.onap.so.bpmn.servicedecomposition.generalobjects.RequestParameters;
+import org.onap.so.bpmn.servicedecomposition.homingobjects.Candidate;
+import org.onap.so.bpmn.servicedecomposition.homingobjects.CandidateType;
+import org.onap.so.client.exception.BadResponseException;
+import org.onap.so.client.oof.beans.OofRequest;
+import org.skyscreamer.jsonassert.JSONAssert;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class OofHomingV2IT extends BaseIntegrationTest {
+
+    private ServiceInstance serviceInstance;
+
+    private RequestContext requestContext;
+
+    private Customer customer;
+
+    private static final String RESOURCE_PATH = "__files/BuildingBlocks/OofHoming/";
+
+
+    String mockResponse =
+            "{\"transactionId\": \"123456789\", \"requestId\": \"1234\", \"statusMessage\": \"homing request accepted\", \"requestStatus\": \"accepted\"}";
+
+    @Before
+    public void before() {
+        serviceInstance = setServiceInstance();
+        customer = setCustomer();
+        customer.setGlobalCustomerId("testCustomerId");
+        customer.setSubscriberName("testCustomerName");
+        customer.getServiceSubscription().getServiceInstances().add(serviceInstance);
+        customer.setCustomerLatitude("customerLatitude");
+        customer.setCustomerLongitude("customerLongitude");
+
+        requestContext = setRequestContext();
+        requestContext.setMsoRequestId("requestId");
+
+        RequestParameters params = new RequestParameters();
+        params.setaLaCarte(false);
+        params.setSubscriptionServiceType("testSubscriptionServiceType");
+        requestContext.setRequestParameters(params);
+    }
+
+    public void beforeVpnBondingLink(String id) {
+        VpnBondingLink bondingLink = new VpnBondingLink();
+        bondingLink.setVpnBondingLinkId("testVpnBondingId" + id);
+        bondingLink.getServiceProxies().add(setServiceProxy("1", "transport"));
+        ServiceProxy sp2 = setServiceProxy("2", "infrastructure");
+        Candidate requiredCandidate = new Candidate();
+        requiredCandidate.setIdentifierType(CandidateType.VNF_ID);
+        List<String> c = new ArrayList<String>();
+        c.add("testVnfId");
+        requiredCandidate.setIdentifiers(c);
+        sp2.addRequiredCandidates(requiredCandidate);
+        bondingLink.getServiceProxies().add(sp2);
+        serviceInstance.getVpnBondingLinks().add(bondingLink);
+
+    }
+
+    public void beforeAllottedResource() {
+        serviceInstance.getAllottedResources().add(setAllottedResource("1"));
+        serviceInstance.getAllottedResources().add(setAllottedResource("2"));
+        serviceInstance.getAllottedResources().add(setAllottedResource("3"));
+    }
+
+    public void beforeVnf() {
+        setGenericVnf();
+    }
+
+    @Test
+    public void testCallOof_success_1VpnLink() throws BadResponseException, IOException {
+        beforeVpnBondingLink("1");
+
+        wireMockServer.stubFor(post(urlEqualTo("/api/oof/v1/placement")).willReturn(
+                aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBody(mockResponse)));
+
+        oofHoming.callOof(execution);
+
+        String request = readResourceFile(RESOURCE_PATH + "oofRequest1Vpn.json");
+        request = request.replace("28080", wireMockPort);
+
+        ArgumentCaptor<OofRequest> argument = ArgumentCaptor.forClass(OofRequest.class);
+        verify(oofClient, times(1)).postDemands(argument.capture());
+        JSONAssert.assertEquals(request, argument.getValue().toJsonString(), false);
+    }
+
+    @Test
+    public void testCallOof_success_3VpnLink() throws JsonProcessingException, BadResponseException {
+        beforeVpnBondingLink("1");
+        beforeVpnBondingLink("2");
+        beforeVpnBondingLink("3");
+
+        wireMockServer.stubFor(post(urlEqualTo("/api/oof/v1/placement")).willReturn(
+                aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBody(mockResponse)));
+
+        oofHoming.callOof(execution);
+
+        String request = readResourceFile(RESOURCE_PATH + "oofRequest3Vpn.json");
+        request = request.replace("28080", wireMockPort);
+
+        ArgumentCaptor<OofRequest> argument = ArgumentCaptor.forClass(OofRequest.class);
+        verify(oofClient, times(1)).postDemands(argument.capture());
+        JSONAssert.assertEquals(request, argument.getValue().toJsonString(), false);
+    }
+
+    @Test
+    public void testCallOof_success_3Allotteds() throws BadResponseException, JsonProcessingException {
+        beforeAllottedResource();
+
+        wireMockServer.stubFor(post(urlEqualTo("/api/oof/v1/placement")).willReturn(
+                aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBody(mockResponse)));
+
+        oofHoming.callOof(execution);
+
+        String request = readResourceFile(RESOURCE_PATH + "oofRequest3Ar.json");
+        request = request.replace("28080", wireMockPort);
+
+        ArgumentCaptor<OofRequest> argument = ArgumentCaptor.forClass(OofRequest.class);
+        verify(oofClient, times(1)).postDemands(argument.capture());
+        JSONAssert.assertEquals(request, argument.getValue().toJsonString(), false);
+    }
+
+    @Test
+    public void testCallOof_success_1Vnf() throws JsonProcessingException, BadResponseException {
+        beforeVnf();
+
+        wireMockServer.stubFor(post(urlEqualTo("/api/oof/v1/placement")).willReturn(
+                aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBody(mockResponse)));
+
+        oofHoming.callOof(execution);
+
+        ArgumentCaptor<OofRequest> argument = ArgumentCaptor.forClass(OofRequest.class);
+        verify(oofClient, times(1)).postDemands(argument.capture());
+        // TODO assertEquals(request, argument.getValue().toJsonString());
+    }
+
+    @Test
+    public void testCallOof_success_3Allotteds1Vnf() throws JsonProcessingException, BadResponseException {
+        beforeAllottedResource();
+        beforeVnf();
+
+        wireMockServer.stubFor(post(urlEqualTo("/api/oof/v1/placement")).willReturn(
+                aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBody(mockResponse)));
+
+        oofHoming.callOof(execution);
+
+        verify(oofClient, times(1)).postDemands(isA(OofRequest.class));
+    }
+
+    @Test
+    public void testProcessSolution_success_1VpnLink_1Solution() {
+        beforeVpnBondingLink("1");
+
+        JSONObject asyncResponse = new JSONObject();
+        asyncResponse.put("transactionId", "transactionId").put("requestId", "testRequestId").put("requestState",
+                "completed");
+        JSONArray solution1 = new JSONArray();
+        solution1.put(new JSONObject().put("serviceResourceId", "testProxyId1")
+                .put("solution",
+                        new JSONObject().put("identifierType", "serviceInstanceId").put("identifiers",
+                                new JSONArray().put("testServiceInstanceId1")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "False"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "vnfHostName").put("value", "testVnfHostName1"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli1"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))
+                                .put(new JSONObject().put("key", "vnfId").put("value", "testVnfId1"))
+                                .put(new JSONObject().put("key", "cloudRegionId").put("value", "testSloudRegionId1"))));
+        solution1.put(new JSONObject().put("serviceResourceId", "testProxyId2")
+                .put("solution",
+                        new JSONObject().put("identifierType", "serviceInstanceId").put("identifiers",
+                                new JSONArray().put("testServiceInstanceId2")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "False"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "primaryPnfName").put("value", "testPrimaryPnfName2"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli2"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))
+                                .put(new JSONObject().put("key", "secondaryPnfName").put("value",
+                                        "testSecondaryPnfName2"))
+                                .put(new JSONObject().put("key", "cloudRegionId").put("value", "testSloudRegionId2"))));
+
+        asyncResponse.put("solutions", new JSONObject().put("placementSolutions", new JSONArray().put(solution1))
+                .put("licenseSolutions", new JSONArray()));
+
+        oofHoming.processSolution(execution, asyncResponse.toString());
+
+        ServiceInstance si =
+                execution.getGeneralBuildingBlock().getCustomer().getServiceSubscription().getServiceInstances().get(0);
+
+        assertFalse(si.getVpnBondingLinks().isEmpty());
+        VpnBondingLink link = si.getVpnBondingLinks().get(0);
+        assertNotNull(link);
+        assertFalse(link.getServiceProxies().isEmpty());
+
+        assertEquals("testServiceInstanceId1",
+                link.getServiceProxy("testProxyId1").getServiceInstance().getServiceInstanceId());
+        assertNotNull(link.getServiceProxy("testProxyId1").getServiceInstance().getSolutionInfo());
+        assertEquals("testVnfHostName1",
+                link.getServiceProxy("testProxyId1").getServiceInstance().getVnfs().get(0).getVnfName());
+
+        assertEquals("testServiceInstanceId2",
+                link.getServiceProxy("testProxyId2").getServiceInstance().getServiceInstanceId());
+        assertNotNull(link.getServiceProxy("testProxyId2").getServiceInstance().getSolutionInfo());
+        assertFalse(link.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().isEmpty());
+        assertEquals("testPrimaryPnfName2",
+                link.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(0).getPnfName());
+        assertEquals("primary", link.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(0).getRole());
+        assertEquals("testSecondaryPnfName2",
+                link.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(1).getPnfName());
+        assertEquals("secondary", link.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(1).getRole());
+    }
+
+    @Test
+    public void testProcessSolution_success_1VpnLink_2Solutions() {
+        beforeVpnBondingLink("1");
+
+        JSONObject asyncResponse = new JSONObject();
+        asyncResponse.put("transactionId", "transactionId").put("requestId", "testRequestId").put("requestState",
+                "completed");
+        JSONArray solution1 = new JSONArray();
+        solution1.put(new JSONObject().put("serviceResourceId", "testProxyId1")
+                .put("solution",
+                        new JSONObject().put("identifierType", "serviceInstanceId").put("identifiers",
+                                new JSONArray().put("testServiceInstanceId1")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "False"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "vnfHostName").put("value", "testVnfHostName1"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli1"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))
+                                .put(new JSONObject().put("key", "vnfId").put("value", "testVnfId1"))
+                                .put(new JSONObject().put("key", "cloudRegionId").put("value", "testSloudRegionId1"))));
+        solution1.put(new JSONObject().put("serviceResourceId", "testProxyId2")
+                .put("solution",
+                        new JSONObject().put("identifierType", "serviceInstanceId").put("identifiers",
+                                new JSONArray().put("testServiceInstanceId2")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "False"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "primaryPnfName").put("value", "testPrimaryPnfName2"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli2"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))
+                                .put(new JSONObject().put("key", "secondaryPnfName").put("value",
+                                        "testSecondaryPnfName2"))
+                                .put(new JSONObject().put("key", "cloudRegionId").put("value", "testSloudRegionId2"))));
+
+        JSONArray solution2 = new JSONArray();
+        solution2.put(new JSONObject().put("serviceResourceId", "testProxyId1")
+                .put("solution",
+                        new JSONObject().put("identifierType", "serviceInstanceId").put("identifiers",
+                                new JSONArray().put("testServiceInstanceId3")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "False"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "vnfHostName").put("value", "testVnfHostName3"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli3"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))
+                                .put(new JSONObject().put("key", "vnfId").put("value", "testVnfId3"))
+                                .put(new JSONObject().put("key", "cloudRegionId").put("value", "testSloudRegionId3"))));
+        solution2.put(new JSONObject().put("serviceResourceId", "testProxyId2")
+                .put("solution",
+                        new JSONObject().put("identifierType", "serviceInstanceId").put("identifiers",
+                                new JSONArray().put("testServiceInstanceId4")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "False"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "primaryPnfName").put("value", "testPrimaryPnfName4"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli4"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))
+                                .put(new JSONObject().put("key", "secondaryPnfName").put("value",
+                                        "testSecondaryPnfName4"))
+                                .put(new JSONObject().put("key", "cloudRegionId").put("value", "testSloudRegionId4"))));
+
+        asyncResponse.put("solutions",
+                new JSONObject().put("placementSolutions", new JSONArray().put(solution1).put(solution2))
+                        .put("licenseSolutions", new JSONArray()));
+
+        oofHoming.processSolution(execution, asyncResponse.toString());
+
+        ServiceInstance si =
+                execution.getGeneralBuildingBlock().getCustomer().getServiceSubscription().getServiceInstances().get(0);
+
+        assertFalse(si.getVpnBondingLinks().isEmpty());
+        VpnBondingLink link = si.getVpnBondingLinks().get(0);
+        VpnBondingLink link2 = si.getVpnBondingLinks().get(1);
+        assertNotNull(link);
+        assertFalse(link.getServiceProxies().isEmpty());
+
+        assertEquals("testServiceInstanceId1",
+                link.getServiceProxy("testProxyId1").getServiceInstance().getServiceInstanceId());
+        assertNotNull(link.getServiceProxy("testProxyId1").getServiceInstance().getSolutionInfo());
+        assertEquals("testVnfHostName1",
+                link.getServiceProxy("testProxyId1").getServiceInstance().getVnfs().get(0).getVnfName());
+
+        assertEquals("testServiceInstanceId2",
+                link.getServiceProxy("testProxyId2").getServiceInstance().getServiceInstanceId());
+        assertNotNull(link.getServiceProxy("testProxyId2").getServiceInstance().getSolutionInfo());
+        assertFalse(link.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().isEmpty());
+        assertEquals("testPrimaryPnfName2",
+                link.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(0).getPnfName());
+        assertEquals("primary", link.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(0).getRole());
+        assertEquals("testSecondaryPnfName2",
+                link.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(1).getPnfName());
+        assertEquals("secondary", link.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(1).getRole());
+
+        assertNotNull(link2);
+        assertFalse(link2.getServiceProxies().isEmpty());
+
+        assertEquals("testServiceInstanceId3",
+                link2.getServiceProxy("testProxyId1").getServiceInstance().getServiceInstanceId());
+        assertNotNull(link2.getServiceProxy("testProxyId1").getServiceInstance().getSolutionInfo());
+        assertEquals("testVnfHostName3",
+                link2.getServiceProxy("testProxyId1").getServiceInstance().getVnfs().get(0).getVnfName());
+
+        assertEquals("testServiceInstanceId4",
+                link2.getServiceProxy("testProxyId2").getServiceInstance().getServiceInstanceId());
+        assertNotNull(link2.getServiceProxy("testProxyId2").getServiceInstance().getSolutionInfo());
+        assertFalse(link2.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().isEmpty());
+        assertEquals("testPrimaryPnfName4",
+                link2.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(0).getPnfName());
+        assertEquals("primary", link2.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(0).getRole());
+        assertEquals("testSecondaryPnfName4",
+                link2.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(1).getPnfName());
+        assertEquals("secondary",
+                link2.getServiceProxy("testProxyId2").getServiceInstance().getPnfs().get(1).getRole());
+
+    }
+
+    @Test
+    public void testProcessSolution_success_3VpnLink_2Solutions() {
+        // TODO
+    }
+
+    @Test
+    public void testProcessSolution_success_3Allotteds_1Solution() {
+        beforeAllottedResource();
+
+        JSONObject asyncResponse = new JSONObject();
+        asyncResponse.put("transactionId", "transactionId").put("requestId", "testRequestId").put("requestState",
+                "completed");
+        JSONArray solution1 = new JSONArray();
+        solution1.put(new JSONObject().put("serviceResourceId", "testAllottedResourceId1")
+                .put("solution",
+                        new JSONObject().put("identifierType", "serviceInstanceId").put("identifiers",
+                                new JSONArray().put("testServiceInstanceId1")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "True"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "vnfHostName").put("value", "testVnfHostName1"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli1"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))
+                                .put(new JSONObject().put("key", "vnfId").put("value", "testVnfId1"))
+                                .put(new JSONObject().put("key", "cloudRegionId").put("value", "testCloudRegionId1"))));
+        solution1.put(new JSONObject().put("serviceResourceId", "testAllottedResourceId2")
+                .put("solution",
+                        new JSONObject().put("identifierType", "serviceInstanceId").put("identifiers",
+                                new JSONArray().put("testServiceInstanceId2")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "True"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "vnfHostName").put("value", "testVnfHostName2"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli2"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))
+                                .put(new JSONObject().put("key", "vnfId").put("value", "testVnfId1"))
+                                .put(new JSONObject().put("key", "cloudRegionId").put("value", "testCloudRegionId2"))));
+        solution1.put(new JSONObject().put("serviceResourceId", "testAllottedResourceId3")
+                .put("solution",
+                        new JSONObject().put("identifierType", "cloudRegionId").put("identifiers",
+                                new JSONArray().put("testCloudRegionId3")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "True"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli2"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))));
+
+        asyncResponse.put("solutions", new JSONObject().put("placementSolutions", new JSONArray().put(solution1))
+                .put("licenseSolutions", new JSONArray()));
+
+        oofHoming.processSolution(execution, asyncResponse.toString());
+
+        ServiceInstance si =
+                execution.getGeneralBuildingBlock().getCustomer().getServiceSubscription().getServiceInstances().get(0);
+
+        assertFalse(si.getAllottedResources().isEmpty());
+        AllottedResource ar = si.getAllottedResources().get(0);
+        assertNotNull(ar);
+        assertEquals("testServiceInstanceId1", ar.getParentServiceInstance().getServiceInstanceId());
+        assertNotNull(ar.getParentServiceInstance().getSolutionInfo());
+        assertEquals("testVnfHostName1", ar.getParentServiceInstance().getVnfs().get(0).getVnfName());
+
+        AllottedResource ar2 = si.getAllottedResources().get(1);
+        assertNotNull(ar2);
+        assertEquals("testServiceInstanceId2", ar2.getParentServiceInstance().getServiceInstanceId());
+        assertNotNull(ar2.getParentServiceInstance().getSolutionInfo());
+        assertEquals("testVnfHostName2", ar2.getParentServiceInstance().getVnfs().get(0).getVnfName());
+
+        AllottedResource ar3 = si.getAllottedResources().get(2);
+        assertNotNull(ar3);
+        assertNotNull(ar3.getParentServiceInstance().getSolutionInfo());
+        assertEquals("testCloudRegionId3",
+                ar3.getParentServiceInstance().getSolutionInfo().getTargetedCloudRegion().getLcpCloudRegionId());
+    }
+
+    @Test
+    public void testProcessSolution_success_3Allotteds1Vnf_1Solution() {
+        beforeVnf();
+        beforeAllottedResource();
+
+        JSONObject asyncResponse = new JSONObject();
+        asyncResponse.put("transactionId", "transactionId").put("requestId", "testRequestId").put("requestState",
+                "completed");
+        JSONArray solution1 = new JSONArray();
+        JSONArray licenseSolution = new JSONArray();
+        solution1.put(new JSONObject().put("serviceResourceId", "testAllottedResourceId1")
+                .put("solution",
+                        new JSONObject().put("identifierType", "serviceInstanceId").put("identifiers",
+                                new JSONArray().put("testServiceInstanceId1")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "True"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "vnfHostName").put("value", "testVnfHostName1"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli1"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))
+                                .put(new JSONObject().put("key", "vnfId").put("value", "testVnfId1"))
+                                .put(new JSONObject().put("key", "cloudRegionId").put("value", "testCloudRegionId1"))));
+        solution1.put(new JSONObject().put("serviceResourceId", "testAllottedResourceId2")
+                .put("solution",
+                        new JSONObject().put("identifierType", "serviceInstanceId").put("identifiers",
+                                new JSONArray().put("testServiceInstanceId2")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "True"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "vnfHostName").put("value", "testVnfHostName2"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli2"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))
+                                .put(new JSONObject().put("key", "vnfId").put("value", "testVnfId1"))
+                                .put(new JSONObject().put("key", "cloudRegionId").put("value", "testCloudRegionId2"))));
+        solution1.put(new JSONObject().put("serviceResourceId", "testAllottedResourceId3")
+                .put("solution",
+                        new JSONObject().put("identifierType", "cloudRegionId").put("identifiers",
+                                new JSONArray().put("testCloudRegionId3")))
+                .put("assignmentInfo",
+                        new JSONArray().put(new JSONObject().put("key", "isRehome").put("value", "True"))
+                                .put(new JSONObject().put("key", "cloudOwner").put("value", "aic"))
+                                .put(new JSONObject().put("key", "aicClli").put("value", "testAicClli2"))
+                                .put(new JSONObject().put("key", "aicVersion").put("value", "3"))));
+
+        licenseSolution.put(new JSONObject().put("serviceResourceId", "testVnfId1")
+                .put("entitlementPoolUUID",
+                        new JSONArray().put("f1d563e8-e714-4393-8f99-cc480144a05e")
+                                .put("j1d563e8-e714-4393-8f99-cc480144a05e"))
+                .put("licenseKeyGroupUUID", new JSONArray().put("s1d563e8-e714-4393-8f99-cc480144a05e")
+                        .put("b1d563e8-e714-4393-8f99-cc480144a05e")));
+
+        asyncResponse.put("solutions", new JSONObject().put("placementSolutions", new JSONArray().put(solution1))
+                .put("licenseSolutions", licenseSolution));
+
+        oofHoming.processSolution(execution, asyncResponse.toString());
+
+        ServiceInstance si =
+                execution.getGeneralBuildingBlock().getCustomer().getServiceSubscription().getServiceInstances().get(0);
+
+        assertFalse(si.getAllottedResources().isEmpty());
+        AllottedResource ar = si.getAllottedResources().get(0);
+        assertNotNull(ar);
+        assertEquals("testServiceInstanceId1", ar.getParentServiceInstance().getServiceInstanceId());
+        assertNotNull(ar.getParentServiceInstance().getSolutionInfo());
+        assertEquals("testVnfHostName1", ar.getParentServiceInstance().getVnfs().get(0).getVnfName());
+
+        AllottedResource ar2 = si.getAllottedResources().get(1);
+        assertNotNull(ar2);
+        assertEquals("testServiceInstanceId2", ar2.getParentServiceInstance().getServiceInstanceId());
+        assertNotNull(ar2.getParentServiceInstance().getSolutionInfo());
+        assertEquals("testVnfHostName2", ar2.getParentServiceInstance().getVnfs().get(0).getVnfName());
+
+        AllottedResource ar3 = si.getAllottedResources().get(2);
+        assertNotNull(ar3);
+        assertNotNull(ar3.getParentServiceInstance().getSolutionInfo());
+        assertEquals("testCloudRegionId3",
+                ar3.getParentServiceInstance().getSolutionInfo().getTargetedCloudRegion().getLcpCloudRegionId());
+
+        GenericVnf vnf = si.getVnfs().get(0);
+        assertNotNull(vnf);
+        assertNotNull(vnf.getLicense());
+        assertEquals(2, vnf.getLicense().getEntitlementPoolUuids().size());
+        assertEquals("s1d563e8-e714-4393-8f99-cc480144a05e", vnf.getLicense().getLicenseKeyGroupUuids().get(0));
+
+    }
+
+    @Test
+    public void testProcessSolution_success_1Vnf_1Solution() {
+        beforeVnf();
+
+        JSONObject asyncResponse = new JSONObject();
+        asyncResponse.put("transactionId", "transactionId").put("requestId", "testRequestId").put("requestState",
+                "completed");
+        JSONArray licenseSolution = new JSONArray();
+
+        licenseSolution.put(new JSONObject().put("serviceResourceId", "testVnfId1")
+                .put("entitlementPoolUUID",
+                        new JSONArray().put("f1d563e8-e714-4393-8f99-cc480144a05e")
+                                .put("j1d563e8-e714-4393-8f99-cc480144a05e"))
+                .put("licenseKeyGroupUUID", new JSONArray().put("s1d563e8-e714-4393-8f99-cc480144a05e")
+                        .put("b1d563e8-e714-4393-8f99-cc480144a05e")));
+
+        asyncResponse.put("solutions", new JSONObject().put("licenseSolutions", licenseSolution));
+
+        oofHoming.processSolution(execution, asyncResponse.toString());
+
+        ServiceInstance si =
+                execution.getGeneralBuildingBlock().getCustomer().getServiceSubscription().getServiceInstances().get(0);
+
+        GenericVnf vnf = si.getVnfs().get(0);
+        assertNotNull(vnf);
+        assertNotNull(vnf.getLicense());
+        assertEquals(2, vnf.getLicense().getEntitlementPoolUuids().size());
+        assertEquals(2, vnf.getLicense().getLicenseKeyGroupUuids().size());
+        assertEquals("f1d563e8-e714-4393-8f99-cc480144a05e", vnf.getLicense().getEntitlementPoolUuids().get(0));
+        assertEquals("s1d563e8-e714-4393-8f99-cc480144a05e", vnf.getLicense().getLicenseKeyGroupUuids().get(0));
+
+
+    }
+
+    @Test(expected = BpmnError.class)
+    public void testCallOof_error_0Resources() throws BadResponseException, JsonProcessingException {
+
+        oofHoming.callOof(execution);
+
+        verify(oofClient, times(0)).postDemands(isA(OofRequest.class));
+    }
+
+    @Test(expected = BpmnError.class)
+    public void testCallOof_error_badResponse() throws BadResponseException, JsonProcessingException {
+        beforeAllottedResource();
+
+        mockResponse =
+                "{\"transactionId\": \"123456789\", \"requestId\": \"1234\", \"statusMessage\": \"\", \"requestStatus\": \"failed\"}";
+        wireMockServer.stubFor(post(urlEqualTo("/api/oof/v1/placement")).willReturn(
+                aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBody(mockResponse)));
+
+        oofHoming.callOof(execution);
+
+        verify(oofClient, times(1)).postDemands(isA(OofRequest.class));
+    }
+
+}
index ce7d557..3ae0db6 100644 (file)
@@ -27,6 +27,7 @@ import static org.junit.Assert.assertEquals;
 import org.junit.Test;
 import org.onap.so.BaseIntegrationTest;
 import org.onap.so.client.exception.BadResponseException;
+import org.onap.so.client.oof.beans.LicenseInfo;
 import org.onap.so.client.oof.beans.ModelInfo;
 import org.onap.so.client.oof.beans.OofRequest;
 import org.onap.so.client.oof.beans.OofRequestParameters;
@@ -36,6 +37,7 @@ import org.onap.so.client.oof.beans.RequestInfo;
 import org.onap.so.client.oof.beans.ResourceModelInfo;
 import org.onap.so.client.oof.beans.ServiceInfo;
 import org.onap.so.client.oof.beans.SubscriberInfo;
+import org.skyscreamer.jsonassert.JSONAssert;
 import org.springframework.beans.factory.annotation.Autowired;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import java.util.ArrayList;
@@ -114,7 +116,7 @@ public class OofClientTestIT extends BaseIntegrationTest {
         oofRequest.setRequestInformation(requestInfo);
         oofRequest.setPlacementInformation(placementInfo);
         oofRequest.setServiceInformation(serviceInfo);
-        oofRequest.setLicenseInformation("");
+        oofRequest.setLicenseInformation(new LicenseInfo());
 
         wireMockServer.stubFor(post(urlEqualTo("/api/oof/v1/placement")).willReturn(
                 aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBody(mockResponse)));
@@ -122,7 +124,7 @@ public class OofClientTestIT extends BaseIntegrationTest {
         client.postDemands(oofRequest);
 
         String oofRequestOutput = oofRequest.toJsonString();
-        assertEquals("{\n" + "  \"requestInfo\" : {\n" + "    \"transactionId\" : \"transactionId\",\n"
+        JSONAssert.assertEquals("{\n" + "  \"requestInfo\" : {\n" + "    \"transactionId\" : \"transactionId\",\n"
                 + "    \"requestId\" : \"requestId\",\n" + "    \"callbackUrl\" : \"callBackUrl\",\n"
                 + "    \"sourceId\" : \"sourceId\",\n" + "    \"requestType\" : \"requestType\",\n"
                 + "    \"numSolutions\" : 1,\n" + "    \"optimizers\" : [ \"optimizer1\", \"optimizer2\" ],\n"
@@ -147,7 +149,8 @@ public class OofClientTestIT extends BaseIntegrationTest {
                 + "        \"modelInvariantId\" : \"invarianteId\",\n" + "        \"modelVersionId\" : \"versionId\",\n"
                 + "        \"modelName\" : \"modelName\",\n" + "        \"modelVersion\" : \"version\",\n"
                 + "        \"modelCustomizationName\" : \"modelCustomizationName\"\n" + "      }\n" + "    } ]\n"
-                + "  },\n" + "  \"licenseInfo\" : \"\"\n" + "}", oofRequestOutput);
+                + "  },\n" + "  \"licenseInfo\" : { \n" + "    \"licenseDemands\" : [ ]\n" + "}\n" + "}",
+                oofRequestOutput, false);
     }
 
     @Test
diff --git a/bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest1Vpn.json b/bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest1Vpn.json
new file mode 100644 (file)
index 0000000..99ce7fb
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "requestInfo":{
+    "transactionId":"requestId",
+    "requestId":"requestId",
+    "callbackUrl":"http://localhost:28080/mso/WorkflowMesssage/OofResponse/requestId",
+    "sourceId":"mso",
+    "requestType":"create",
+    "numSolutions":1,
+    "optimizers":[ "placement" ],
+    "timeout":1800
+  },
+  "serviceInfo":{
+    "serviceInstanceId":"testServiceInstanceId1",
+    "serviceName":"testServiceType1",
+    "modelInfo":{
+      "modelInvariantId":"testModelInvariantUUID1",
+      "modelVersionId":"testModelUUID1",
+      "modelName":"testModelName1",
+      "modelVersion":"testModelVersion1"
+    }
+  },
+  "placementInfo":{
+    "requestParameters":{
+      "customerLatitude":"customerLatitude",
+      "customerLongitude":"customerLongitude",
+      "customerName":"testCustomerName"
+    },
+    "subscriberInfo":{
+      "globalSubscriberId":"testCustomerId",
+      "subscriberName":"testCustomerName"
+    },
+    "placementDemands":[
+      {
+        "resourceModuleName":"testProxyInstanceName1",
+        "serviceResourceId":"testProxyId1",
+        "resourceModelInfo":{
+          "modelInvariantId":"testProxyModelInvariantUuid1",
+          "modelVersionId":"testProxyModelUuid1",
+          "modelName":"testProxyModelName1",
+          "modelVersion":"testProxyModelVersion1"
+        }
+      },
+      {
+        "resourceModuleName":"testProxyInstanceName2",
+        "serviceResourceId":"testProxyId2",
+        "resourceModelInfo":{
+          "modelInvariantId":"testProxyModelInvariantUuid2",
+          "modelVersionId":"testProxyModelUuid2",
+          "modelName":"testProxyModelName2",
+          "modelVersion":"testProxyModelVersion2"
+        }
+      }
+    ]
+  },
+  "licenseInfo":{
+    "licenseDemands" : [ ]
+  }
+}
diff --git a/bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest1VpnOpt.json b/bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest1VpnOpt.json
new file mode 100644 (file)
index 0000000..d149b32
--- /dev/null
@@ -0,0 +1,61 @@
+{
+  "requestInfo" : {
+    "transactionId" : "requestId",
+    "requestId" : "requestId",
+    "callbackUrl" : "http://localhost:28080/mso/WorkflowMesssage/OofResponse/requestId",
+    "sourceId" : "mso",
+    "requestType" : "create",
+    "numSolutions" : 1,
+    "optimizers" : [ "placement" ],
+    "timeout" : 1800
+  },
+  "serviceInfo" : {
+    "serviceInstanceId" : "serviceInstanceId",
+    "serviceName" : "serviceName",
+    "modelInfo" : {
+      "modelType" : "modelType-Service",
+      "modelInvariantId" : "modelInvariantId-Service",
+      "modelVersionId" : "modelVersionId-Service",
+      "modelName" : "modelName-Service",
+      "modelVersion" : "modelVersion-Service",
+      "modelCustomizationName" : "modelCustomizationName-Service"
+    }
+  },
+  "placementInfo" : {
+    "requestParameters" : {
+      "customerLatitude" : "customerLatitude",
+      "customerLongitude" : "customerLongitude",
+      "customerName" : "customerName"
+    },
+    "subscriberInfo" : {
+      "globalSubscriberId" : "globalSubscriberId",
+      "subscriberName" : "subscriberName"
+    },
+    "placementDemands" : [ {
+      "serviceResourceId" : "testProxyId1",
+      "resourceModuleName" : "testProxyInstanceName1",
+      "resourceModelInfo" : {
+        "modelName" : "testProxyModelName1",
+        "modelVersionId" : "testProxyModelUuid1",
+        "modelVersion" : "testProxyModelVersion1",
+        "modelInvariantId" : "testProxyModelInvariantUuid1"
+      }
+    }, {
+      "serviceResourceId" : "testProxyId2",
+      "resourceModuleName" : "testProxyInstanceName2",
+      "resourceModelInfo" : {
+        "modelName" : "testProxyModelName2",
+        "modelVersionId" : "testProxyModelUuid2",
+        "modelVersion" : "testProxyModelVersion2",
+        "modelInvariantId" : "testProxyModelInvariantUuid2"
+      },
+      "requiredCandidates" : [ {
+        "identifierType" : "vnfId",
+        "identifiers" : [ "testVnfId" ]
+      } ]
+    } ]
+  },
+  "licenseInfo" : {
+    "licenseDemands" : [ ]
+  }
+}
diff --git a/bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest3Ar.json b/bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest3Ar.json
new file mode 100644 (file)
index 0000000..9b251aa
--- /dev/null
@@ -0,0 +1,67 @@
+{
+  "requestInfo" : {
+    "transactionId" : "requestId",
+    "requestId" : "requestId",
+    "callbackUrl" : "http://localhost:28080/mso/WorkflowMesssage/OofResponse/requestId",
+    "sourceId" : "mso",
+    "requestType" : "create",
+    "numSolutions" : 1,
+    "optimizers" : [ "placement" ],
+    "timeout" : 1800
+  },
+  "serviceInfo" : {
+    "serviceInstanceId" : "testServiceInstanceId1",
+    "serviceName" : "testServiceType1",
+    "modelInfo" : {
+      "modelInvariantId" : "testModelInvariantUUID1",
+      "modelVersionId" : "testModelUUID1",
+      "modelName" : "testModelName1",
+      "modelVersion" : "testModelVersion1"
+    }
+  },
+  "placementInfo" : {
+    "requestParameters": {
+      "customerLatitude": "customerLatitude",
+      "customerLongitude": "customerLongitude",
+      "customerName": "testCustomerName"
+    },
+    "subscriberInfo": {
+      "globalSubscriberId" : "testCustomerId",
+      "subscriberName" : "testCustomerName"
+    },
+    "placementDemands": [
+      {
+        "serviceResourceId": "testAllottedResourceId1",
+        "resourceModuleName": "testAllottedModelInstanceName1",
+        "resourceModelInfo": {
+          "modelName": "testAllottedModelName1",
+          "modelVersionId": "testAllottedModelUuid1",
+          "modelVersion": "testAllottedModelVersion1",
+          "modelInvariantId": "testAllottedModelInvariantUuid1"
+        }
+      },
+      {
+        "serviceResourceId": "testAllottedResourceId2",
+        "resourceModuleName": "testAllottedModelInstanceName2",
+        "resourceModelInfo": {
+          "modelName": "testAllottedModelName2",
+          "modelVersionId": "testAllottedModelUuid2",
+          "modelVersion": "testAllottedModelVersion2",
+          "modelInvariantId": "testAllottedModelInvariantUuid2"
+        }
+      },
+      {
+        "serviceResourceId": "testAllottedResourceId3",
+        "resourceModuleName": "testAllottedModelInstanceName3",
+        "resourceModelInfo": {
+          "modelName": "testAllottedModelName3",
+          "modelVersionId": "testAllottedModelUuid3",
+          "modelVersion": "testAllottedModelVersion3",
+          "modelInvariantId": "testAllottedModelInvariantUuid3"
+        }
+      } ]
+  },
+  "licenseInfo" : {
+    "licenseDemands" : [ ]
+  }
+}
diff --git a/bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest3Vpn.json b/bpmn/so-bpmn-tasks/src/test/resources/__files/BuildingBlocks/OofHoming/oofRequest3Vpn.json
new file mode 100644 (file)
index 0000000..e3a735d
--- /dev/null
@@ -0,0 +1,91 @@
+{
+  "requestInfo" : {
+    "transactionId" : "requestId",
+    "requestId" : "requestId",
+    "callbackUrl" : "http://localhost:28080/mso/WorkflowMesssage/OofResponse/requestId",
+    "sourceId" : "mso",
+    "requestType" : "create",
+    "numSolutions" : 1,
+    "optimizers" : [ "placement" ],
+    "timeout" : 1800
+  },
+  "serviceInfo" : {
+    "serviceInstanceId" : "testServiceInstanceId1",
+    "serviceName" : "testServiceType1",
+    "modelInfo":{
+      "modelInvariantId":"testModelInvariantUUID1",
+      "modelVersionId":"testModelUUID1",
+      "modelName":"testModelName1",
+      "modelVersion":"testModelVersion1"
+    }
+  },
+  "placementInfo" : {
+    "requestParameters" : {
+      "customerLatitude" : "customerLatitude",
+      "customerLongitude" : "customerLongitude",
+      "customerName" : "testCustomerName"
+    },
+    "subscriberInfo" : {
+      "globalSubscriberId" : "testCustomerId",
+      "subscriberName" : "testCustomerName"
+    },
+    "placementDemands" : [ {
+      "resourceModuleName" : "testProxyInstanceName1",
+      "serviceResourceId" : "testProxyId1",
+      "resourceModelInfo" : {
+        "modelInvariantId" : "testProxyModelInvariantUuid1",
+        "modelVersionId" : "testProxyModelUuid1",
+        "modelName" : "testProxyModelName1",
+        "modelVersion" : "testProxyModelVersion1"
+      }
+    }, {
+      "resourceModuleName" : "testProxyInstanceName2",
+      "serviceResourceId" : "testProxyId2",
+      "resourceModelInfo" : {
+        "modelInvariantId" : "testProxyModelInvariantUuid2",
+        "modelVersionId" : "testProxyModelUuid2",
+        "modelName" : "testProxyModelName2",
+        "modelVersion" : "testProxyModelVersion2"
+      }
+    }, {
+      "resourceModuleName" : "testProxyInstanceName1",
+      "serviceResourceId" : "testProxyId1",
+      "resourceModelInfo" : {
+        "modelInvariantId" : "testProxyModelInvariantUuid1",
+        "modelVersionId" : "testProxyModelUuid1",
+        "modelName" : "testProxyModelName1",
+        "modelVersion" : "testProxyModelVersion1"
+      }
+    }, {
+      "resourceModuleName" : "testProxyInstanceName2",
+      "serviceResourceId" : "testProxyId2",
+      "resourceModelInfo" : {
+        "modelInvariantId" : "testProxyModelInvariantUuid2",
+        "modelVersionId" : "testProxyModelUuid2",
+        "modelName" : "testProxyModelName2",
+        "modelVersion" : "testProxyModelVersion2"
+      }
+    }, {
+      "resourceModuleName" : "testProxyInstanceName1",
+      "serviceResourceId" : "testProxyId1",
+      "resourceModelInfo" : {
+        "modelInvariantId" : "testProxyModelInvariantUuid1",
+        "modelVersionId" : "testProxyModelUuid1",
+        "modelName" : "testProxyModelName1",
+        "modelVersion" : "testProxyModelVersion1"
+      }
+    }, {
+      "resourceModuleName" : "testProxyInstanceName2",
+      "serviceResourceId" : "testProxyId2",
+      "resourceModelInfo" : {
+        "modelInvariantId" : "testProxyModelInvariantUuid2",
+        "modelVersionId" : "testProxyModelUuid2",
+        "modelName" : "testProxyModelName2",
+        "modelVersion" : "testProxyModelVersion2"
+      }
+    } ]
+  },
+  "licenseInfo" : {
+    "licenseDemands" : [ ]
+  }
+}