summaryrefslogtreecommitdiffstats
path: root/models-interactions/model-actors/actor.so
diff options
context:
space:
mode:
authorning.xi <ning.xi@est.tech>2019-04-01 03:07:40 +0000
committerning.xi <ning.xi@est.tech>2019-04-01 03:07:40 +0000
commit2d99454e725df9f0f74572ac10de2b97f7e84c55 (patch)
tree9752cb83dbe3b59fa027acc01f900e1182a99d12 /models-interactions/model-actors/actor.so
parentfbed360c0acdc127fdf56a99401c1aea691ce57e (diff)
move actors code in drools-applications to policy/models
remove white-space in policy/models Issue-ID: POLICY-1264 Change-Id: I8856fc7cd2c2a57af0031637870ca33c684bacf5 Signed-off-by: ning.xi <ning.xi@est.tech>
Diffstat (limited to 'models-interactions/model-actors/actor.so')
-rw-r--r--models-interactions/model-actors/actor.so/pom.xml92
-rw-r--r--models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java458
-rw-r--r--models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor1
-rw-r--r--models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java231
-rw-r--r--models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-Full.json267
-rw-r--r--models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-NoBase.json230
-rw-r--r--models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-NoNonBase.json197
7 files changed, 1476 insertions, 0 deletions
diff --git a/models-interactions/model-actors/actor.so/pom.xml b/models-interactions/model-actors/actor.so/pom.xml
new file mode 100644
index 000000000..a634fb9f0
--- /dev/null
+++ b/models-interactions/model-actors/actor.so/pom.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0"?>
+<!--
+ ============LICENSE_START=======================================================
+ Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ Modifications Copyright (C) 2019 Nordix Foundation.
+ ================================================================================
+ 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=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-actors</groupId>
+ <artifactId>model-actors</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>actor.so</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-actors</groupId>
+ <artifactId>actorServiceProvider</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+ <artifactId>aai</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+ <artifactId>events</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+ <artifactId>so</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-core</artifactId>
+ <version>6.5.0.Final</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>policy-endpoints</artifactId>
+ <version>${policy.common.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.drools-pdp</groupId>
+ <artifactId>policy-management</artifactId>
+ <version>${policy.drools-pdp.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.drools-applications.controlloop.common</groupId>
+ <artifactId>simulators</artifactId>
+ <version>${policy.drools-applications.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java
new file mode 100644
index 000000000..eef6e7c12
--- /dev/null
+++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java
@@ -0,0 +1,458 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SOActorServiceProvider
+ * ================================================================================
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.policy.controlloop.actor.so;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.gson.reflect.TypeToken;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.drools.core.WorkingMemory;
+import org.onap.policy.aai.AaiNqExtraProperty;
+import org.onap.policy.aai.AaiNqInventoryResponseItem;
+import org.onap.policy.aai.AaiNqResponseWrapper;
+import org.onap.policy.controlloop.ControlLoopOperation;
+import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
+import org.onap.policy.controlloop.policy.Policy;
+import org.onap.policy.so.SoCloudConfiguration;
+import org.onap.policy.so.SoManager;
+import org.onap.policy.so.SoModelInfo;
+import org.onap.policy.so.SoOperationType;
+import org.onap.policy.so.SoRelatedInstance;
+import org.onap.policy.so.SoRelatedInstanceListElement;
+import org.onap.policy.so.SoRequest;
+import org.onap.policy.so.SoRequestDetails;
+import org.onap.policy.so.SoRequestInfo;
+import org.onap.policy.so.SoRequestParameters;
+import org.onap.policy.so.util.Serialization;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SoActorServiceProvider implements Actor {
+ private static final Logger logger = LoggerFactory.getLogger(SoActorServiceProvider.class);
+
+ // Strings for SO Actor
+ private static final String SO_ACTOR = "SO";
+
+ // Strings for targets
+ private static final String TARGET_VFC = "VFC";
+
+ // Strings for recipes
+ private static final String RECIPE_VF_MODULE_CREATE = "VF Module Create";
+ private static final String RECIPE_VF_MODULE_DELETE = "VF Module Delete";
+
+ private static final ImmutableList<String> recipes = ImmutableList.of(RECIPE_VF_MODULE_CREATE,
+ RECIPE_VF_MODULE_DELETE);
+ private static final ImmutableMap<String, List<String>> targets = new ImmutableMap.Builder<String, List<String>>()
+ .put(RECIPE_VF_MODULE_CREATE, ImmutableList.of(TARGET_VFC))
+ .put(RECIPE_VF_MODULE_DELETE, ImmutableList.of(TARGET_VFC)).build();
+
+ // name of request parameters within policy payload
+ public static final String REQ_PARAM_NM = "requestParameters";
+
+ // name of configuration parameters within policy payload
+ public static final String CONFIG_PARAM_NM = "configurationParameters";
+
+ private static final String MODEL_NAME_PROPERTY_KEY = "model-ver.model-name";
+ private static final String MODEL_VERSION_PROPERTY_KEY = "model-ver.model-version";
+ private static final String MODEL_VERSION_ID_PROPERTY_KEY = "model-ver.model-version-id";
+
+ // used to decode configuration parameters via gson
+ private static final Type CONFIG_TYPE = new TypeToken<List<Map<String, String>>>() {}.getType();
+
+ // Static variables required to hold the IDs of the last service item, VNF item and VF Module.
+ // Note that in
+ // a multithreaded deployment this WILL break
+ private static String lastVNFItemVnfId;
+ private static String lastServiceItemServiceInstanceId;
+ private static String lastVfModuleItemVfModuleInstanceId;
+
+ @Override
+ public String actor() {
+ return SO_ACTOR;
+ }
+
+ @Override
+ public List<String> recipes() {
+ return ImmutableList.copyOf(recipes);
+ }
+
+ @Override
+ public List<String> recipeTargets(String recipe) {
+ return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList()));
+ }
+
+ @Override
+ public List<String> recipePayloads(String recipe) {
+ return Collections.emptyList();
+ }
+
+ /**
+ * Constructs a SO request conforming to the lcm API. The actual request is
+ * constructed and then placed in a wrapper object used to send through DMAAP.
+ *
+ * @param onset the event that is reporting the alert for policy to perform an action
+ * @param operation the control loop operation specifying the actor, operation,
+ * target, etc.
+ * @param policy the policy the was specified from the yaml generated by CLAMP or
+ * through the Policy GUI/API
+ * @param aaiResponseWrapper wrapper for AAI vserver named-query response
+ * @return a SO request conforming to the lcm API using the DMAAP wrapper
+ */
+ public SoRequest constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy,
+ AaiNqResponseWrapper aaiResponseWrapper) {
+ if (!SO_ACTOR.equals(policy.getActor()) || !recipes().contains(policy.getRecipe())) {
+ return null;
+ }
+
+ // A&AI named query should have been performed by now. If not, return null
+ if (aaiResponseWrapper == null) {
+ return null;
+ }
+
+ AaiNqInventoryResponseItem vnfItem;
+ AaiNqInventoryResponseItem vnfServiceItem;
+ AaiNqInventoryResponseItem tenantItem;
+
+ // Extract the items we're interested in from the response
+ try {
+ vnfItem = aaiResponseWrapper.getAaiNqResponse().getInventoryResponseItems().get(0).getItems()
+ .getInventoryResponseItems().get(0);
+ } catch (Exception e) {
+ logger.error("VNF Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiResponseWrapper),
+ e);
+ return null;
+ }
+
+ try {
+ vnfServiceItem = vnfItem.getItems().getInventoryResponseItems().get(0);
+ } catch (Exception e) {
+ logger.error("VNF Service Item not found in AAI response {}",
+ Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
+ return null;
+ }
+
+ try {
+ tenantItem = aaiResponseWrapper.getAaiNqResponse().getInventoryResponseItems().get(0).getItems()
+ .getInventoryResponseItems().get(1);
+ } catch (Exception e) {
+ logger.error("Tenant Item not found in AAI response {}",
+ Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
+ return null;
+ }
+
+ // Find the index for base vf module and non-base vf module
+ AaiNqInventoryResponseItem baseItem = findVfModule(aaiResponseWrapper, true);
+ AaiNqInventoryResponseItem vfModuleItem = findVfModule(aaiResponseWrapper, false);
+
+ // Report the error if either base vf module or non-base vf module is not found
+ if (baseItem == null || vfModuleItem == null) {
+ logger.error("Either base or non-base vf module is not found from AAI response.");
+ return null;
+ }
+
+ // Construct SO Request for a policy's recipe
+ if (RECIPE_VF_MODULE_CREATE.equals(policy.getRecipe())) {
+ return constructCreateRequest(aaiResponseWrapper, policy, tenantItem, vnfItem, vnfServiceItem,
+ vfModuleItem);
+ } else if (RECIPE_VF_MODULE_DELETE.equals(policy.getRecipe())) {
+ return constructDeleteRequest(tenantItem, vnfItem, vnfServiceItem, vfModuleItem);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Construct SO request to create vf-module.
+ *
+ * @param aaiResponseWrapper the AAI response containing the VF modules
+ * @param policy the policy
+ * @param tenantItem tenant item from A&AI named-query response
+ * @param vnfItem vnf item from A&AI named-query response
+ * @param vnfServiceItem vnf service item from A&AI named-query response
+ * @param vfModuleItem vf module item from A&AI named-query response
+ * @return SO create vf-module request
+ */
+ private SoRequest constructCreateRequest(AaiNqResponseWrapper aaiResponseWrapper, Policy policy,
+ AaiNqInventoryResponseItem tenantItem, AaiNqInventoryResponseItem vnfItem,
+ AaiNqInventoryResponseItem vnfServiceItem,
+ AaiNqInventoryResponseItem vfModuleItem) {
+ SoRequest request = new SoRequest();
+ request.setOperationType(SoOperationType.SCALE_OUT);
+ //
+ //
+ // Do NOT send So the requestId, they do not support this field
+ //
+ request.setRequestDetails(new SoRequestDetails());
+ request.getRequestDetails().setRequestParameters(new SoRequestParameters());
+ request.getRequestDetails().getRequestParameters().setUserParams(null);
+
+ // cloudConfiguration
+ request.getRequestDetails().setCloudConfiguration(constructCloudConfiguration(tenantItem));
+ // modelInfo
+ request.getRequestDetails().setModelInfo(constructVfModuleModelInfo(vfModuleItem));
+ request.getRequestDetails().getModelInfo().setModelVersionId(vfModuleItem.getVfModule().getModelVersionId());
+
+ // requestInfo
+ request.getRequestDetails().setRequestInfo(constructRequestInfo());
+ String vfModuleName = aaiResponseWrapper.genVfModuleName();
+ request.getRequestDetails().getRequestInfo().setInstanceName(vfModuleName);
+
+ // relatedInstanceList
+ SoRelatedInstanceListElement relatedInstanceListElement1 = new SoRelatedInstanceListElement();
+ SoRelatedInstanceListElement relatedInstanceListElement2 = new SoRelatedInstanceListElement();
+ relatedInstanceListElement1.setRelatedInstance(new SoRelatedInstance());
+ relatedInstanceListElement2.setRelatedInstance(new SoRelatedInstance());
+
+ // Service Item
+ relatedInstanceListElement1.getRelatedInstance()
+ .setInstanceId(vnfServiceItem.getServiceInstance().getServiceInstanceId());
+ relatedInstanceListElement1.getRelatedInstance().setModelInfo(new SoModelInfo());
+ relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelType("service");
+ relatedInstanceListElement1.getRelatedInstance().getModelInfo()
+ .setModelInvariantId(vnfServiceItem.getServiceInstance().getModelInvariantId());
+ for (AaiNqExtraProperty prop : vnfServiceItem.getExtraProperties().getExtraProperty()) {
+ if (prop.getPropertyName().equals(MODEL_NAME_PROPERTY_KEY)) {
+ relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
+ } else if (prop.getPropertyName().equals(MODEL_VERSION_PROPERTY_KEY)) {
+ relatedInstanceListElement1.getRelatedInstance().getModelInfo()
+ .setModelVersion(prop.getPropertyValue());
+ } else if (prop.getPropertyName().equals(MODEL_VERSION_ID_PROPERTY_KEY)) {
+ relatedInstanceListElement1.getRelatedInstance().getModelInfo()
+ .setModelVersionId(prop.getPropertyValue());
+ }
+ }
+
+ // VNF Item
+ relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getGenericVnf().getVnfId());
+ relatedInstanceListElement2.getRelatedInstance().setModelInfo(new SoModelInfo());
+ relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelType("vnf");
+ relatedInstanceListElement2.getRelatedInstance().getModelInfo()
+ .setModelInvariantId(vnfItem.getGenericVnf().getModelInvariantId());
+ for (AaiNqExtraProperty prop : vnfItem.getExtraProperties().getExtraProperty()) {
+ if (prop.getPropertyName().equals(MODEL_NAME_PROPERTY_KEY)) {
+ relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
+ } else if (prop.getPropertyName().equals(MODEL_VERSION_PROPERTY_KEY)) {
+ relatedInstanceListElement2.getRelatedInstance().getModelInfo()
+ .setModelVersion(prop.getPropertyValue());
+ } else if (prop.getPropertyName().equals(MODEL_VERSION_ID_PROPERTY_KEY)) {
+ relatedInstanceListElement2.getRelatedInstance().getModelInfo()
+ .setModelVersionId(prop.getPropertyValue());
+ }
+ }
+ relatedInstanceListElement2.getRelatedInstance().getModelInfo()
+ .setModelCustomizationName(vnfItem.getGenericVnf().getVnfType()
+ .substring(vnfItem.getGenericVnf().getVnfType().lastIndexOf('/') + 1));
+ relatedInstanceListElement2.getRelatedInstance().getModelInfo()
+ .setModelCustomizationId(vnfItem.getGenericVnf().getModelCustomizationId());
+
+ // Insert the Service Item and VNF Item
+ request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement1);
+ request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement2);
+
+ // Request Parameters
+ buildRequestParameters(policy, request.getRequestDetails());
+
+ // Configuration Parameters
+ buildConfigurationParameters(policy, request.getRequestDetails());
+ // Save the instance IDs for the VNF and service to static fields
+ // vfModuleId is not required for the create vf-module
+ preserveInstanceIds(vnfItem.getGenericVnf().getVnfId(), vnfServiceItem.getServiceInstance()
+ .getServiceInstanceId(), null);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Constructed SO request: {}", Serialization.gsonPretty.toJson(request));
+ }
+ return request;
+ }
+
+ /**
+ * Construct SO request to delete vf-module.
+ *
+ * @param tenantItem tenant item from A&AI named-query response
+ * @param vnfItem vnf item from A&AI named-query response
+ * @param vnfServiceItem vnf service item from A&AI named-query response
+ * @param vfModuleItem vf module item from A&AI named-query response
+ * @return SO delete vf-module request
+ */
+ private SoRequest constructDeleteRequest(AaiNqInventoryResponseItem tenantItem, AaiNqInventoryResponseItem
+ vnfItem, AaiNqInventoryResponseItem vnfServiceItem, AaiNqInventoryResponseItem vfModuleItem) {
+ SoRequest request = new SoRequest();
+ request.setOperationType(SoOperationType.DELETE_VF_MODULE);
+ request.setRequestDetails(new SoRequestDetails());
+ request.getRequestDetails().setRelatedInstanceList(null);
+ request.getRequestDetails().setConfigurationParameters(null);
+
+ // cloudConfiguration
+ request.getRequestDetails().setCloudConfiguration(constructCloudConfiguration(tenantItem));
+ // modelInfo
+ request.getRequestDetails().setModelInfo(constructVfModuleModelInfo(vfModuleItem));
+ // requestInfo
+ request.getRequestDetails().setRequestInfo(constructRequestInfo());
+ // Save the instance IDs for the VNF, service and vfModule to static fields
+ preserveInstanceIds(vnfItem.getGenericVnf().getVnfId(), vnfServiceItem.getServiceInstance()
+ .getServiceInstanceId(), vfModuleItem.getVfModule().getVfModuleId());
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Constructed SO request: {}", Serialization.gsonPretty.toJson(request));
+ }
+ return request;
+ }
+
+ /**
+ * Construct requestInfo for the SO requestDetails.
+ *
+ * @return SO request information
+ */
+ private SoRequestInfo constructRequestInfo() {
+ SoRequestInfo soRequestInfo = new SoRequestInfo();
+ soRequestInfo.setSource("POLICY");
+ soRequestInfo.setSuppressRollback(false);
+ soRequestInfo.setRequestorId("policy");
+ return soRequestInfo;
+ }
+
+ /**
+ * Construct modelInfo of the vfModule for the SO requestDetails.
+ *
+ * @param vfModuleItem vf module item from A&AI named-query response
+ * @return SO Model info for the vfModule
+ */
+ private SoModelInfo constructVfModuleModelInfo(AaiNqInventoryResponseItem vfModuleItem) {
+ SoModelInfo soModelInfo = new SoModelInfo();
+ soModelInfo.setModelType("vfModule");
+ soModelInfo.setModelInvariantId(vfModuleItem.getVfModule().getModelInvariantId());
+ soModelInfo.setModelCustomizationId(vfModuleItem.getVfModule().getModelCustomizationId());
+
+ for (AaiNqExtraProperty prop : vfModuleItem.getExtraProperties().getExtraProperty()) {
+ if (prop.getPropertyName().equals(MODEL_NAME_PROPERTY_KEY)) {
+ soModelInfo.setModelName(prop.getPropertyValue());
+ } else if (prop.getPropertyName().equals(MODEL_VERSION_PROPERTY_KEY)) {
+ soModelInfo.setModelVersion(prop.getPropertyValue());
+ }
+ }
+ return soModelInfo;
+ }
+
+ /**
+ * Construct cloudConfiguration for the SO requestDetails.
+ *
+ * @param tenantItem tenant item from A&AI named-query response
+ * @return SO cloud configuration
+ */
+ private SoCloudConfiguration constructCloudConfiguration(AaiNqInventoryResponseItem tenantItem) {
+ SoCloudConfiguration cloudConfiguration = new SoCloudConfiguration();
+ cloudConfiguration.setTenantId(tenantItem.getTenant().getTenantId());
+ cloudConfiguration.setLcpCloudRegionId(tenantItem.getItems().getInventoryResponseItems().get(0)
+ .getCloudRegion().getCloudRegionId());
+ return cloudConfiguration;
+ }
+
+ /**
+ * This method is needed to get the serviceInstanceId and vnfInstanceId which is used
+ * in the asyncSORestCall.
+ *
+ * @param requestId the request Id
+ * @param wm the working memory
+ * @param request the request
+ */
+ public static void sendRequest(String requestId, WorkingMemory wm, Object request) {
+ SoManager soManager = new SoManager();
+ soManager.asyncSoRestCall(requestId, wm, lastServiceItemServiceInstanceId, lastVNFItemVnfId,
+ lastVfModuleItemVfModuleInstanceId, (SoRequest) request);
+ }
+
+ /**
+ * Find the base or non base VF module item in an AAI response.
+ * If there is more than one item, then the <i>last</i> item is returned
+ *
+ * @param aaiResponseWrapper the AAI response containing the VF modules
+ * @param baseFlag true if we are searching for the base, false if we are searching
+ * for the non base
+ * @return the base or non base VF module item or null if the module was not found
+ */
+ private AaiNqInventoryResponseItem findVfModule(AaiNqResponseWrapper aaiResponseWrapper, boolean baseFlag) {
+ List<AaiNqInventoryResponseItem> lst = aaiResponseWrapper.getVfModuleItems(baseFlag);
+ return (lst.isEmpty() ? null : lst.get(lst.size() - 1));
+ }
+
+ /**
+ * Builds the request parameters from the policy payload.
+ *
+ * @param policy the policy
+ * @param request request into which to stick the request parameters
+ */
+ private void buildRequestParameters(Policy policy, SoRequestDetails request) {
+ // assume null until proven otherwise
+ request.setRequestParameters(null);
+
+ if (policy.getPayload() == null) {
+ return;
+ }
+
+ String json = policy.getPayload().get(REQ_PARAM_NM);
+ if (json == null) {
+ return;
+ }
+
+ request.setRequestParameters(Serialization.gsonPretty.fromJson(json, SoRequestParameters.class));
+ }
+
+ /**
+ * Builds the configuration parameters from the policy payload.
+ *
+ * @param policy the policy
+ * @param request request into which to stick the configuration parameters
+ */
+ private void buildConfigurationParameters(Policy policy, SoRequestDetails request) {
+ // assume null until proven otherwise
+ request.setConfigurationParameters(null);
+
+ if (policy.getPayload() == null) {
+ return;
+ }
+
+ String json = policy.getPayload().get(CONFIG_PARAM_NM);
+ if (json == null) {
+ return;
+ }
+
+ request.setConfigurationParameters(Serialization.gsonPretty.fromJson(json, CONFIG_TYPE));
+ }
+
+ /**
+ * This method is called to remember the last service instance ID, VNF Item VNF ID and vf module ID.
+ * Note these fields are static, beware for multithreaded deployments
+ *
+ * @param vnfInstanceId update the last VNF instance ID to this value
+ * @param serviceInstanceId update the last service instance ID to this value
+ * @param vfModuleId update the vfModule instance ID to this value
+ */
+ private static void preserveInstanceIds(final String vnfInstanceId, final String serviceInstanceId,
+ final String vfModuleId) {
+ lastVNFItemVnfId = vnfInstanceId;
+ lastServiceItemServiceInstanceId = serviceInstanceId;
+ lastVfModuleItemVfModuleInstanceId = vfModuleId;
+ }
+}
diff --git a/models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor
new file mode 100644
index 000000000..a955eb71c
--- /dev/null
+++ b/models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor
@@ -0,0 +1 @@
+org.onap.policy.controlloop.actor.so.SoActorServiceProvider \ No newline at end of file
diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java
new file mode 100644
index 000000000..d0eab120c
--- /dev/null
+++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java
@@ -0,0 +1,231 @@
+/*
+ * ============LICENSE_START=======================================================
+ * TestSOActorServiceProvider
+ * ================================================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018-2019 AT&T. All rights reserved.
+ * Modifications Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.policy.controlloop.actor.so;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.UUID;
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+import org.onap.policy.aai.AaiNqResponse;
+import org.onap.policy.aai.AaiNqResponseWrapper;
+import org.onap.policy.controlloop.ControlLoopOperation;
+import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.policy.Policy;
+import org.onap.policy.so.SoOperationType;
+import org.onap.policy.so.SoRequest;
+import org.onap.policy.so.SoRequestParameters;
+import org.onap.policy.so.util.Serialization;
+
+public class SoActorServiceProviderTest {
+
+ private static final String VF_MODULE_CREATE = "VF Module Create";
+ private static final String VF_MODULE_DELETE = "VF Module Delete";
+
+ @Test
+ public void testConstructRequest() throws Exception {
+ VirtualControlLoopEvent onset = new VirtualControlLoopEvent();
+ final ControlLoopOperation operation = new ControlLoopOperation();
+ final AaiNqResponseWrapper aaiNqResp = loadAaiResponse(onset, "aai/AaiNqResponse-Full.json");
+
+ final UUID requestId = UUID.randomUUID();
+ onset.setRequestId(requestId);
+
+ Policy policy = new Policy();
+ policy.setActor("Dorothy");
+ policy.setRecipe("GoToOz");
+
+ assertNull(new SoActorServiceProvider().constructRequest(onset, operation, policy, aaiNqResp));
+
+ policy.setActor("SO");
+ assertNull(new SoActorServiceProvider().constructRequest(onset, operation, policy, aaiNqResp));
+
+ policy.setRecipe(VF_MODULE_CREATE);
+
+ // empty policy payload
+ SoRequest request = new SoActorServiceProvider().constructRequest(onset, operation, policy, aaiNqResp);
+ assertNotNull(request);
+
+ assertEquals("my_module_3", request.getRequestDetails().getRequestInfo().getInstanceName());
+ assertEquals("policy", request.getRequestDetails().getRequestInfo().getRequestorId());
+ assertEquals("RegionOne", request.getRequestDetails().getCloudConfiguration().getLcpCloudRegionId());
+
+ // non-empty policy payload
+ policy.setPayload(makePayload());
+ request = new SoActorServiceProvider().constructRequest(onset, operation, policy, aaiNqResp);
+ assertNotNull(request);
+ assertEquals(true, request.getRequestDetails().getRequestParameters().isUsePreload());
+ assertEquals("avalue", request.getRequestDetails().getRequestParameters().getUserParams().get(0).get("akey"));
+ assertEquals(1, request.getRequestDetails().getConfigurationParameters().size());
+ assertEquals("cvalue", request.getRequestDetails().getConfigurationParameters().get(0).get("ckey"));
+
+ // payload with config, but no request params
+ policy.setPayload(makePayload());
+ policy.getPayload().remove(SoActorServiceProvider.REQ_PARAM_NM);
+ request = new SoActorServiceProvider().constructRequest(onset, operation, policy, aaiNqResp);
+ assertNotNull(request);
+ assertNull(request.getRequestDetails().getRequestParameters());
+ assertNotNull(request.getRequestDetails().getConfigurationParameters());
+
+ // payload with request, but no config params
+ policy.setPayload(makePayload());
+ policy.getPayload().remove(SoActorServiceProvider.CONFIG_PARAM_NM);
+ request = new SoActorServiceProvider().constructRequest(onset, operation, policy, aaiNqResp);
+ assertNotNull(request);
+ assertNotNull(request.getRequestDetails().getRequestParameters());
+ assertNull(request.getRequestDetails().getConfigurationParameters());
+
+ // null response
+ assertNull(new SoActorServiceProvider().constructRequest(onset, operation, policy, null));
+
+ // response has no base VF module
+ assertNull(new SoActorServiceProvider().constructRequest(onset, operation, policy,
+ loadAaiResponse(onset, "aai/AaiNqResponse-NoBase.json")));
+
+ // response has no non-base VF modules (other than the "dummy")
+ assertNull(new SoActorServiceProvider().constructRequest(onset, operation, policy,
+ loadAaiResponse(onset, "aai/AaiNqResponse-NoNonBase.json")));
+
+ policy.setRecipe(VF_MODULE_DELETE);
+ SoRequest deleteRequest = new SoActorServiceProvider().constructRequest(onset, operation, policy, aaiNqResp);
+ assertNotNull(deleteRequest);
+ assertEquals(SoOperationType.DELETE_VF_MODULE, deleteRequest.getOperationType());
+
+ /*
+ * NOTE: The remaining tests must be done in order
+ */
+
+ policy.setRecipe(VF_MODULE_CREATE);
+
+ // null tenant
+ aaiNqResp.getAaiNqResponse().getInventoryResponseItems().get(0).getItems().getInventoryResponseItems()
+ .remove(1);
+ assertNull(new SoActorServiceProvider().constructRequest(onset, operation, policy, aaiNqResp));
+
+ // null service item
+ aaiNqResp.getAaiNqResponse().getInventoryResponseItems().get(0).getItems().getInventoryResponseItems().get(0)
+ .setItems(null);
+ assertNull(new SoActorServiceProvider().constructRequest(onset, operation, policy, aaiNqResp));
+
+ // null response
+ aaiNqResp.setAaiNqResponse(null);
+ assertNull(new SoActorServiceProvider().constructRequest(onset, operation, policy, aaiNqResp));
+ }
+
+ @Test
+ public void testSendRequest() {
+ try {
+ SoActorServiceProvider.sendRequest(UUID.randomUUID().toString(), null, null);
+ } catch (Exception e) {
+ fail("Test should not throw an exception");
+ }
+ }
+
+ @Test
+ public void testMethods() {
+ SoActorServiceProvider sp = new SoActorServiceProvider();
+
+ assertEquals("SO", sp.actor());
+ assertEquals(2, sp.recipes().size());
+ assertEquals(VF_MODULE_CREATE, sp.recipes().get(0));
+ assertEquals(VF_MODULE_DELETE, sp.recipes().get(1));
+ assertEquals(0, sp.recipePayloads(VF_MODULE_CREATE).size());
+ assertEquals(0, sp.recipeTargets("unknown recipe").size());
+ assertEquals(1, sp.recipeTargets(VF_MODULE_CREATE).size());
+ }
+
+ /**
+ * Creates a policy payload containing request & configuration parameters.
+ *
+ * @return the payload
+ */
+ private Map<String, String> makePayload() {
+ Map<String, String> payload = new TreeMap<>();
+
+ payload.put(SoActorServiceProvider.REQ_PARAM_NM, makeReqParams());
+ payload.put(SoActorServiceProvider.CONFIG_PARAM_NM, makeConfigParams());
+
+ return payload;
+ }
+
+ /**
+ * Creates request parameters.
+ *
+ * @return request parameters, encoded as JSON
+ */
+ private String makeReqParams() {
+ SoRequestParameters params = new SoRequestParameters();
+
+ params.setUsePreload(true);
+
+ Map<String, String> map = new TreeMap<>();
+ map.put("akey", "avalue");
+
+ List<Map<String, String>> lst = new LinkedList<>();
+ lst.add(map);
+
+ params.setUserParams(lst);
+
+ return Serialization.gsonPretty.toJson(params);
+ }
+
+ /**
+ * Creates configuration parameters.
+ *
+ * @return configuration parameters, encoded as JSON
+ */
+ private String makeConfigParams() {
+ Map<String, String> map = new TreeMap<>();
+ map.put("ckey", "cvalue");
+
+ List<Map<String, String>> lst = new LinkedList<>();
+ lst.add(map);
+
+ return Serialization.gsonPretty.toJson(lst);
+ }
+
+ /**
+ * Reads an AAI vserver named-query response from a file.
+ *
+ * @param onset the ONSET event
+ * @param fileName name of the file containing the JSON response
+ * @return output from the AAI vserver named-query
+ * @throws IOException if the file cannot be read
+ */
+ private AaiNqResponseWrapper loadAaiResponse(VirtualControlLoopEvent onset, String fileName) throws IOException {
+ String resp = IOUtils.toString(getClass().getResource(fileName), StandardCharsets.UTF_8);
+ AaiNqResponse aaiNqResponse = Serialization.gsonPretty.fromJson(resp, AaiNqResponse.class);
+
+ return new AaiNqResponseWrapper(onset.getRequestId(), aaiNqResponse);
+ }
+}
diff --git a/models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-Full.json b/models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-Full.json
new file mode 100644
index 000000000..af40be948
--- /dev/null
+++ b/models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-Full.json
@@ -0,0 +1,267 @@
+{
+ "inventory-response-item": [
+ {
+ "vserver": {
+ "vserver-id": "6ed3642c-f7a1-4a7c-9290-3d51fe1531eb",
+ "vserver-name": "zdfw1lb01lb02",
+ "vserver-name2": "zdfw1lb01lb02",
+ "prov-status": "ACTIVE",
+ "vserver-selflink": "http://10.12.25.2:8774/v2.1/41d6d38489bd40b09ea8a6b6b852dcbd/servers/6ed3642c-f7a1-4a7c-9290-3d51fe1531eb",
+ "in-maint": false,
+ "is-closed-loop-disabled": false,
+ "resource-version": "1510606403522"
+ },
+ "extra-properties": {
+ "extra-property": []
+ },
+ "inventory-response-items": {
+ "inventory-response-item": [
+ {
+ "model-name": "vLoadBalancer",
+ "generic-vnf": {
+ "vnf-id": "db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "vnf-name": "Vfmodule_vLB1113",
+ "vnf-type": "vLoadBalancer-1106/vLoadBalancer 0",
+ "service-id": "66f157fc-4148-4880-95f5-e120677e98d1",
+ "prov-status": "PREPROV",
+ "in-maint": false,
+ "is-closed-loop-disabled": false,
+ "resource-version": "1510604011851",
+ "model-invariant-id": "cee050ed-92a5-494f-ab04-234307a846dc",
+ "model-version-id": "fd65becc-6b2c-4fe8-ace9-cc29db9a3da2"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "fd65becc-6b2c-4fe8-ace9-cc29db9a3da2"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "vLoadBalancer"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "cee050ed-92a5-494f-ab04-234307a846dc"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1.0"
+ }
+ ]
+ },
+ "inventory-response-items": {
+ "inventory-response-item": [
+ {
+ "model-name": "vLoadBalancer-1106",
+ "service-instance": {
+ "service-instance-id": "3b12f31f-8f2d-4f5c-b875-61ff1194b941",
+ "service-instance-name": "vLoadBalancer-1113",
+ "resource-version": "1510603936425",
+ "model-invariant-id": "1321d60d-f7ff-4300-96c2-6bf0b3268b7a",
+ "model-version-id": "732d4692-4b97-46f9-a996-0b3339e88c50"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "732d4692-4b97-46f9-a996-0b3339e88c50"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "vLoadBalancer-1106"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "service"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "1321d60d-f7ff-4300-96c2-6bf0b3268b7a"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1.0"
+ }
+ ]
+ }
+ },
+ {
+ "model-name": "Vloadbalancer..base_vlb..module-0",
+ "vf-module": {
+ "vf-module-id": "e6b3e3eb-34e1-4c00-b8c1-2a4fbe479b12",
+ "vf-module-name": "Vfmodule_vLB1113-1",
+ "heat-stack-id": "Vfmodule_vLB1113-1/3dd6d900-772f-4fcc-a0cb-e250ab2bb4db",
+ "orchestration-status": "active",
+ "is-base-vf-module": true,
+ "resource-version": "1510604612557",
+ "model-invariant-id": "6d760188-9a24-451a-b05b-e08b86cb94f2",
+ "model-version-id": "93facad9-55f2-4fe0-9574-814c2bc2d071"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "93facad9-55f2-4fe0-9574-814c2bc2d071"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "Vloadbalancer..base_vlb..module-0"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "6d760188-9a24-451a-b05b-e08b86cb94f2"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1"
+ }
+ ]
+ }
+ },
+ {
+ "model-name": "Vloadbalancer..dnsscaling..module-1",
+ "vf-module": {
+ "vf-module-id": "dummy_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "vf-module-name": "dummy_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "is-base-vf-module": false,
+ "resource-version": "1510610079687",
+ "model-invariant-id": "356a1cff-71f2-4086-9980-a2927ce11c1c",
+ "model-version-id": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "Vloadbalancer..dnsscaling..module-1"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "356a1cff-71f2-4086-9980-a2927ce11c1c"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1"
+ }
+ ]
+ }
+ },
+ {
+ "model-name": "Vloadbalancer..dnsscaling..module-1",
+ "vf-module": {
+ "vf-module-id": "my_module_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "vf-module-name": "my_module_1",
+ "is-base-vf-module": false,
+ "resource-version": "1510610079687",
+ "model-invariant-id": "356a1cff-71f2-4086-9980-a2927ce11c1c",
+ "model-version-id": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "Vloadbalancer..dnsscaling..module-1"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "356a1cff-71f2-4086-9980-a2927ce11c1c"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1"
+ }
+ ]
+ }
+ },
+ {
+ "model-name": "Vloadbalancer..dnsscaling..module-1",
+ "vf-module": {
+ "vf-module-id": "my_module_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "vf-module-name": "my_module_2",
+ "is-base-vf-module": false,
+ "resource-version": "1510610079687",
+ "model-invariant-id": "356a1cff-71f2-4086-9980-a2927ce11c1c",
+ "model-version-id": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "Vloadbalancer..dnsscaling..module-1"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "356a1cff-71f2-4086-9980-a2927ce11c1c"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "tenant": {
+ "tenant-id": "41d6d38489bd40b09ea8a6b6b852dcbd",
+ "tenant-name": "Integration-SB-00",
+ "resource-version": "1509587770200"
+ },
+ "extra-properties": {
+ "extra-property": []
+ },
+ "inventory-response-items": {
+ "inventory-response-item": [
+ {
+ "cloud-region": {
+ "cloud-owner": "CloudOwner",
+ "cloud-region-id": "RegionOne",
+ "cloud-region-version": "v1",
+ "resource-version": "1509587770092"
+ },
+ "extra-properties": {
+ "extra-property": []
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-NoBase.json b/models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-NoBase.json
new file mode 100644
index 000000000..7101f60f2
--- /dev/null
+++ b/models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-NoBase.json
@@ -0,0 +1,230 @@
+{
+ "inventory-response-item": [
+ {
+ "vserver": {
+ "vserver-id": "6ed3642c-f7a1-4a7c-9290-3d51fe1531eb",
+ "vserver-name": "zdfw1lb01lb02",
+ "vserver-name2": "zdfw1lb01lb02",
+ "prov-status": "ACTIVE",
+ "vserver-selflink": "http://10.12.25.2:8774/v2.1/41d6d38489bd40b09ea8a6b6b852dcbd/servers/6ed3642c-f7a1-4a7c-9290-3d51fe1531eb",
+ "in-maint": false,
+ "is-closed-loop-disabled": false,
+ "resource-version": "1510606403522"
+ },
+ "extra-properties": {
+ "extra-property": []
+ },
+ "inventory-response-items": {
+ "inventory-response-item": [
+ {
+ "model-name": "vLoadBalancer",
+ "generic-vnf": {
+ "vnf-id": "db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "vnf-name": "Vfmodule_vLB1113",
+ "vnf-type": "vLoadBalancer-1106/vLoadBalancer 0",
+ "service-id": "66f157fc-4148-4880-95f5-e120677e98d1",
+ "prov-status": "PREPROV",
+ "in-maint": false,
+ "is-closed-loop-disabled": false,
+ "resource-version": "1510604011851",
+ "model-invariant-id": "cee050ed-92a5-494f-ab04-234307a846dc",
+ "model-version-id": "fd65becc-6b2c-4fe8-ace9-cc29db9a3da2"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "fd65becc-6b2c-4fe8-ace9-cc29db9a3da2"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "vLoadBalancer"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "cee050ed-92a5-494f-ab04-234307a846dc"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1.0"
+ }
+ ]
+ },
+ "inventory-response-items": {
+ "inventory-response-item": [
+ {
+ "model-name": "vLoadBalancer-1106",
+ "service-instance": {
+ "service-instance-id": "3b12f31f-8f2d-4f5c-b875-61ff1194b941",
+ "service-instance-name": "vLoadBalancer-1113",
+ "resource-version": "1510603936425",
+ "model-invariant-id": "1321d60d-f7ff-4300-96c2-6bf0b3268b7a",
+ "model-version-id": "732d4692-4b97-46f9-a996-0b3339e88c50"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "732d4692-4b97-46f9-a996-0b3339e88c50"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "vLoadBalancer-1106"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "service"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "1321d60d-f7ff-4300-96c2-6bf0b3268b7a"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1.0"
+ }
+ ]
+ }
+ },
+ {
+ "model-name": "Vloadbalancer..dnsscaling..module-1",
+ "vf-module": {
+ "vf-module-id": "dummy_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "vf-module-name": "dummy_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "is-base-vf-module": false,
+ "resource-version": "1510610079687",
+ "model-invariant-id": "356a1cff-71f2-4086-9980-a2927ce11c1c",
+ "model-version-id": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "Vloadbalancer..dnsscaling..module-1"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "356a1cff-71f2-4086-9980-a2927ce11c1c"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1"
+ }
+ ]
+ }
+ },
+ {
+ "model-name": "Vloadbalancer..dnsscaling..module-1",
+ "vf-module": {
+ "vf-module-id": "my_module_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "vf-module-name": "my_module_1",
+ "is-base-vf-module": false,
+ "resource-version": "1510610079687",
+ "model-invariant-id": "356a1cff-71f2-4086-9980-a2927ce11c1c",
+ "model-version-id": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "Vloadbalancer..dnsscaling..module-1"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "356a1cff-71f2-4086-9980-a2927ce11c1c"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1"
+ }
+ ]
+ }
+ },
+ {
+ "model-name": "Vloadbalancer..dnsscaling..module-1",
+ "vf-module": {
+ "vf-module-id": "my_module_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "vf-module-name": "my_module_2",
+ "is-base-vf-module": false,
+ "resource-version": "1510610079687",
+ "model-invariant-id": "356a1cff-71f2-4086-9980-a2927ce11c1c",
+ "model-version-id": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "Vloadbalancer..dnsscaling..module-1"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "356a1cff-71f2-4086-9980-a2927ce11c1c"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "tenant": {
+ "tenant-id": "41d6d38489bd40b09ea8a6b6b852dcbd",
+ "tenant-name": "Integration-SB-00",
+ "resource-version": "1509587770200"
+ },
+ "extra-properties": {
+ "extra-property": []
+ },
+ "inventory-response-items": {
+ "inventory-response-item": [
+ {
+ "cloud-region": {
+ "cloud-owner": "CloudOwner",
+ "cloud-region-id": "RegionOne",
+ "cloud-region-version": "v1",
+ "resource-version": "1509587770092"
+ },
+ "extra-properties": {
+ "extra-property": []
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-NoNonBase.json b/models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-NoNonBase.json
new file mode 100644
index 000000000..a58100bc5
--- /dev/null
+++ b/models-interactions/model-actors/actor.so/src/test/resources/org/onap/policy/controlloop/actor/so/aai/AaiNqResponse-NoNonBase.json
@@ -0,0 +1,197 @@
+{
+ "inventory-response-item": [
+ {
+ "vserver": {
+ "vserver-id": "6ed3642c-f7a1-4a7c-9290-3d51fe1531eb",
+ "vserver-name": "zdfw1lb01lb02",
+ "vserver-name2": "zdfw1lb01lb02",
+ "prov-status": "ACTIVE",
+ "vserver-selflink": "http://10.12.25.2:8774/v2.1/41d6d38489bd40b09ea8a6b6b852dcbd/servers/6ed3642c-f7a1-4a7c-9290-3d51fe1531eb",
+ "in-maint": false,
+ "is-closed-loop-disabled": false,
+ "resource-version": "1510606403522"
+ },
+ "extra-properties": {
+ "extra-property": []
+ },
+ "inventory-response-items": {
+ "inventory-response-item": [
+ {
+ "model-name": "vLoadBalancer",
+ "generic-vnf": {
+ "vnf-id": "db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "vnf-name": "Vfmodule_vLB1113",
+ "vnf-type": "vLoadBalancer-1106/vLoadBalancer 0",
+ "service-id": "66f157fc-4148-4880-95f5-e120677e98d1",
+ "prov-status": "PREPROV",
+ "in-maint": false,
+ "is-closed-loop-disabled": false,
+ "resource-version": "1510604011851",
+ "model-invariant-id": "cee050ed-92a5-494f-ab04-234307a846dc",
+ "model-version-id": "fd65becc-6b2c-4fe8-ace9-cc29db9a3da2"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "fd65becc-6b2c-4fe8-ace9-cc29db9a3da2"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "vLoadBalancer"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "cee050ed-92a5-494f-ab04-234307a846dc"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1.0"
+ }
+ ]
+ },
+ "inventory-response-items": {
+ "inventory-response-item": [
+ {
+ "model-name": "vLoadBalancer-1106",
+ "service-instance": {
+ "service-instance-id": "3b12f31f-8f2d-4f5c-b875-61ff1194b941",
+ "service-instance-name": "vLoadBalancer-1113",
+ "resource-version": "1510603936425",
+ "model-invariant-id": "1321d60d-f7ff-4300-96c2-6bf0b3268b7a",
+ "model-version-id": "732d4692-4b97-46f9-a996-0b3339e88c50"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "732d4692-4b97-46f9-a996-0b3339e88c50"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "vLoadBalancer-1106"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "service"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "1321d60d-f7ff-4300-96c2-6bf0b3268b7a"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1.0"
+ }
+ ]
+ }
+ },
+ {
+ "model-name": "Vloadbalancer..base_vlb..module-0",
+ "vf-module": {
+ "vf-module-id": "e6b3e3eb-34e1-4c00-b8c1-2a4fbe479b12",
+ "vf-module-name": "Vfmodule_vLB1113-1",
+ "heat-stack-id": "Vfmodule_vLB1113-1/3dd6d900-772f-4fcc-a0cb-e250ab2bb4db",
+ "orchestration-status": "active",
+ "is-base-vf-module": true,
+ "resource-version": "1510604612557",
+ "model-invariant-id": "6d760188-9a24-451a-b05b-e08b86cb94f2",
+ "model-version-id": "93facad9-55f2-4fe0-9574-814c2bc2d071"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "93facad9-55f2-4fe0-9574-814c2bc2d071"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "Vloadbalancer..base_vlb..module-0"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "6d760188-9a24-451a-b05b-e08b86cb94f2"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1"
+ }
+ ]
+ }
+ },
+ {
+ "model-name": "Vloadbalancer..dnsscaling..module-1",
+ "vf-module": {
+ "vf-module-id": "dummy_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "vf-module-name": "dummy_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+ "is-base-vf-module": false,
+ "resource-version": "1510610079687",
+ "model-invariant-id": "356a1cff-71f2-4086-9980-a2927ce11c1c",
+ "model-version-id": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ "extra-properties": {
+ "extra-property": [
+ {
+ "property-name": "model-ver.model-version-id",
+ "property-value": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+ },
+ {
+ "property-name": "model-ver.model-name",
+ "property-value": "Vloadbalancer..dnsscaling..module-1"
+ },
+ {
+ "property-name": "model.model-type",
+ "property-value": "resource"
+ },
+ {
+ "property-name": "model.model-invariant-id",
+ "property-value": "356a1cff-71f2-4086-9980-a2927ce11c1c"
+ },
+ {
+ "property-name": "model-ver.model-version",
+ "property-value": "1"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "tenant": {
+ "tenant-id": "41d6d38489bd40b09ea8a6b6b852dcbd",
+ "tenant-name": "Integration-SB-00",
+ "resource-version": "1509587770200"
+ },
+ "extra-properties": {
+ "extra-property": []
+ },
+ "inventory-response-items": {
+ "inventory-response-item": [
+ {
+ "cloud-region": {
+ "cloud-owner": "CloudOwner",
+ "cloud-region-id": "RegionOne",
+ "cloud-region-version": "v1",
+ "resource-version": "1509587770092"
+ },
+ "extra-properties": {
+ "extra-property": []
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+}