2 * ============LICENSE_START=======================================================
3 * SOActorServiceProvider
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.controlloop.actor.so;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
27 import java.util.UUID;
29 import org.drools.core.WorkingMemory;
30 import org.onap.policy.aai.AAIManager;
31 import org.onap.policy.aai.AAINQExtraProperties;
32 import org.onap.policy.aai.AAINQExtraProperty;
33 import org.onap.policy.aai.AAINQInstanceFilters;
34 import org.onap.policy.aai.AAINQInventoryResponseItem;
35 import org.onap.policy.aai.AAINQNamedQuery;
36 import org.onap.policy.aai.AAINQQueryParameters;
37 import org.onap.policy.aai.AAINQRequest;
38 import org.onap.policy.aai.AAINQResponse;
39 import org.onap.policy.aai.AAINQResponseWrapper;
40 import org.onap.policy.controlloop.ControlLoopOperation;
41 import org.onap.policy.controlloop.VirtualControlLoopEvent;
42 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
43 import org.onap.policy.controlloop.policy.Policy;
44 import org.onap.policy.drools.system.PolicyEngine;
45 import org.onap.policy.rest.RESTManager;
46 import org.onap.policy.so.SOCloudConfiguration;
47 import org.onap.policy.so.SOManager;
48 import org.onap.policy.so.SOModelInfo;
49 import org.onap.policy.so.SORelatedInstance;
50 import org.onap.policy.so.SORelatedInstanceListElement;
51 import org.onap.policy.so.SORequest;
52 import org.onap.policy.so.SORequestDetails;
53 import org.onap.policy.so.SORequestInfo;
54 import org.onap.policy.so.SORequestParameters;
55 import org.onap.policy.so.util.Serialization;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
59 import com.google.common.collect.ImmutableList;
60 import com.google.common.collect.ImmutableMap;
62 public class SOActorServiceProvider implements Actor {
63 private static final Logger logger = LoggerFactory.getLogger(SOActorServiceProvider.class);
65 // Strings for SO Actor
66 private static final String SO_ACTOR = "SO";
68 // Strings for targets
69 private static final String TARGET_VFC = "VFC";
71 // Strings for recipes
72 private static final String RECIPE_VF_MODULE_CREATE = "VF Module Create";
74 private static final ImmutableList<String> recipes = ImmutableList.of(RECIPE_VF_MODULE_CREATE);
75 private static final ImmutableMap<String, List<String>> targets = new ImmutableMap.Builder<String, List<String>>()
76 .put(RECIPE_VF_MODULE_CREATE, ImmutableList.of(TARGET_VFC))
79 // Static variables required to hold the IDs of the last service item and VNF item. Note that in a multithreaded deployment this WILL break
80 private static String lastVNFItemVnfId;
81 private static String lastServiceItemServiceInstanceId;
84 public String actor() {
89 public List<String> recipes() {
90 return ImmutableList.copyOf(recipes);
94 public List<String> recipeTargets(String recipe) {
95 return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList()));
99 public List<String> recipePayloads(String recipe) {
100 return Collections.emptyList();
104 * Constructs a SO request conforming to the lcm API.
105 * The actual request is constructed and then placed in a
106 * wrapper object used to send through DMAAP.
109 * the event that is reporting the alert for policy
110 * to perform an action
112 * the control loop operation specifying the actor,
113 * operation, target, etc.
115 * the policy the was specified from the yaml generated
116 * by CLAMP or through the Policy GUI/API
117 * @return a SO request conforming to the lcm API using the DMAAP wrapper
119 public SORequest constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy) {
120 String modelNamePropertyKey = "model-ver.model-name";
121 String modelVersionPropertyKey = "model-ver.model-version";
122 String modelVersionIdPropertyKey = "model-ver.model-version-id";
125 if (!SO_ACTOR.equals(policy.getActor()) || !RECIPE_VF_MODULE_CREATE.equals(policy.getRecipe())) {
126 // for future extension
130 // Perform named query request and handle response
131 AAINQResponseWrapper aaiResponseWrapper = performAaiNamedQueryRequest(onset);
132 if (aaiResponseWrapper == null) {
133 // Tracing and error handling handied in the "performAaiNamedQueryRequest()" method
137 AAINQInventoryResponseItem vnfItem;
138 AAINQInventoryResponseItem vnfServiceItem;
139 AAINQInventoryResponseItem tenantItem;
141 // Extract the items we're interested in from the response
143 vnfItem = aaiResponseWrapper.getAainqresponse().getInventoryResponseItems().get(0).getItems().getInventoryResponseItems().get(0);
145 catch (Exception e) {
146 logger.error("VNF Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
151 vnfServiceItem = vnfItem.getItems().getInventoryResponseItems().get(0);
153 catch (Exception e) {
154 logger.error("VNF Service Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
159 tenantItem = aaiResponseWrapper.getAainqresponse().getInventoryResponseItems().get(0).getItems().getInventoryResponseItems().get(1);
161 catch (Exception e) {
162 logger.error("Tenant Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
166 // Find the index for base vf module and non-base vf module
167 int baseIndex = findIndex(vnfItem.getItems().getInventoryResponseItems(), true);
168 int nonBaseIndex = findIndex(vnfItem.getItems().getInventoryResponseItems(), false);
170 // Report the error if either base vf module or non-base vf module is not found
171 if (baseIndex == -1 || nonBaseIndex == -1) {
172 logger.error("Either base or non-base vf module is not found from AAI response.");
177 // Construct SO Request
178 SORequest request = new SORequest();
179 request.setRequestId(onset.getRequestID());
180 request.setRequestDetails(new SORequestDetails());
181 request.getRequestDetails().setModelInfo(new SOModelInfo());
182 request.getRequestDetails().setCloudConfiguration(new SOCloudConfiguration());
183 request.getRequestDetails().setRequestInfo(new SORequestInfo());
184 request.getRequestDetails().setRequestParameters(new SORequestParameters());
185 request.getRequestDetails().getRequestParameters().setUserParams(null);
188 // cloudConfiguration
190 request.getRequestDetails().getCloudConfiguration().setTenantId(tenantItem.getTenant().getTenantId());
191 request.getRequestDetails().getCloudConfiguration().setLcpCloudRegionId(tenantItem.getItems().getInventoryResponseItems().get(0).getCloudRegion().getCloudRegionId());
196 AAINQInventoryResponseItem vfModuleItem = vnfItem.getItems().getInventoryResponseItems().get(nonBaseIndex);
198 request.getRequestDetails().getModelInfo().setModelType("vfModule");
199 request.getRequestDetails().getModelInfo().setModelInvariantId(vfModuleItem.getVfModule().getModelInvariantId());
200 request.getRequestDetails().getModelInfo().setModelVersionId(vfModuleItem.getVfModule().getModelVersionId());
202 for (AAINQExtraProperty prop : vfModuleItem.getExtraProperties().getExtraProperty()) {
203 if (prop.getPropertyName().equals(modelNamePropertyKey)) {
204 request.getRequestDetails().getModelInfo().setModelName(prop.getPropertyValue());
206 else if (prop.getPropertyName().equals(modelVersionPropertyKey)) {
207 request.getRequestDetails().getModelInfo().setModelVersion(prop.getPropertyValue());
214 String instanceName = vnfItem.getItems().getInventoryResponseItems().get(baseIndex).getVfModule()
215 .getVfModuleName().replace("Vfmodule", "vDNS");
216 int numberOfNonBaseModules = findNonBaseModules(vnfItem.getItems().getInventoryResponseItems());
217 // Code to create unique VF Module names across the invocations.
218 if (numberOfNonBaseModules == 1) {
219 int instanceNumber = 1;
220 instanceName = instanceName.concat("-").concat(String.valueOf(instanceNumber));
221 request.getRequestDetails().getRequestInfo().setInstanceName(instanceName);
222 } else if (numberOfNonBaseModules > 1) {
223 int instanceNumber = numberOfNonBaseModules + 1;
224 instanceName = instanceName.concat("-").concat(String.valueOf(instanceNumber));
225 request.getRequestDetails().getRequestInfo().setInstanceName(instanceName);
227 request.getRequestDetails().getRequestInfo().setInstanceName(vnfItem.getItems().getInventoryResponseItems()
228 .get(baseIndex).getVfModule().getVfModuleName().replace("Vfmodule", "vDNS"));
230 request.getRequestDetails().getRequestInfo().setSource("POLICY");
231 request.getRequestDetails().getRequestInfo().setSuppressRollback(false);
232 request.getRequestDetails().getRequestInfo().setRequestorId("policy");
235 // relatedInstanceList
237 SORelatedInstanceListElement relatedInstanceListElement1 = new SORelatedInstanceListElement();
238 SORelatedInstanceListElement relatedInstanceListElement2 = new SORelatedInstanceListElement();
239 relatedInstanceListElement1.setRelatedInstance(new SORelatedInstance());
240 relatedInstanceListElement2.setRelatedInstance(new SORelatedInstance());
243 relatedInstanceListElement1.getRelatedInstance().setInstanceId(vnfServiceItem.getServiceInstance().getServiceInstanceID());
244 relatedInstanceListElement1.getRelatedInstance().setModelInfo(new SOModelInfo());
245 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelType("service");
246 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelInvariantId(vnfServiceItem.getServiceInstance().getModelInvariantId());
247 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelVersionId(vnfServiceItem.getServiceInstance().getModelVersionId());
248 for (AAINQExtraProperty prop : vnfServiceItem.getExtraProperties().getExtraProperty()) {
249 if (prop.getPropertyName().equals(modelNamePropertyKey)) {
250 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
252 else if (prop.getPropertyName().equals(modelVersionPropertyKey)) {
253 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelVersion(prop.getPropertyValue());
258 relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getGenericVNF().getVnfID());
259 relatedInstanceListElement2.getRelatedInstance().setModelInfo(new SOModelInfo());
260 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelType("vnf");
261 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelInvariantId(vnfItem.getGenericVNF().getModelInvariantId());
262 for (AAINQExtraProperty prop : vnfItem.getExtraProperties().getExtraProperty()) {
263 if (prop.getPropertyName().equals(modelNamePropertyKey)) {
264 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
266 else if (prop.getPropertyName().equals(modelVersionPropertyKey)) {
267 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersion(prop.getPropertyValue());
269 else if (prop.getPropertyName().equals(modelVersionIdPropertyKey)) {
270 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersionId(prop.getPropertyValue());
273 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelCustomizationName(vnfItem.getGenericVNF().getVnfType().substring(vnfItem.getGenericVNF().getVnfType().lastIndexOf('/') + 1));
275 // Insert the Service Item and VNF Item
276 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement1);
277 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement2);
279 // Save the instance IDs for the VNF and service to static fields
280 preserveInstanceIDs(vnfItem.getGenericVNF().getVnfID(), vnfServiceItem.getServiceInstance().getServiceInstanceID());
282 if (logger.isDebugEnabled()) {
283 logger.debug("SO request sent: {}", Serialization.gsonPretty.toJson(request));
290 * This method is needed to get the serviceInstanceId and vnfInstanceId which is used
291 * in the asyncSORestCall
296 public static void sendRequest(String requestID, WorkingMemory wm, Object request) {
297 SOManager soManager = new SOManager();
298 soManager.asyncSORestCall(requestID, wm, lastServiceItemServiceInstanceId, lastVNFItemVnfId, (SORequest)request);
302 * Constructs and sends an AAI vserver Named Query
305 * @returns the response to the AAI Named Query
307 private AAINQResponseWrapper performAaiNamedQueryRequest(VirtualControlLoopEvent onset) {
309 // create AAI named-query request with UUID started with ""
310 AAINQRequest aainqrequest = new AAINQRequest();
311 AAINQQueryParameters aainqqueryparam = new AAINQQueryParameters();
312 AAINQNamedQuery aainqnamedquery = new AAINQNamedQuery();
313 AAINQInstanceFilters aainqinstancefilter = new AAINQInstanceFilters();
316 aainqnamedquery.setNamedQueryUUID(UUID.fromString("4ff56a54-9e3f-46b7-a337-07a1d3c6b469")); // UUID.fromString($params.getAaiNamedQueryUUID()) TO DO: AaiNamedQueryUUID
317 aainqqueryparam.setNamedQuery(aainqnamedquery);
318 aainqrequest.setQueryParameters(aainqqueryparam);
322 Map<String, Map<String, String>> aainqinstancefiltermap = new HashMap<>();
323 Map<String, String> aainqinstancefiltermapitem = new HashMap<>();
324 aainqinstancefiltermapitem.put("vserver-name", onset.getAAI().get("vserver.vserver-name")); // TO DO: get vserver.vname from dcae onset.AAI.get("vserver.vserver-name")
325 aainqinstancefiltermap.put("vserver", aainqinstancefiltermapitem);
326 aainqinstancefilter.getInstanceFilter().add(aainqinstancefiltermap);
327 aainqrequest.setInstanceFilters(aainqinstancefilter);
329 if (logger.isDebugEnabled()) {
330 logger.debug("AAI Request sent: {}", Serialization.gsonPretty.toJson(aainqrequest));
333 AAINQResponse aainqresponse = new AAIManager(new RESTManager()).postQuery(
334 getPEManagerEnvProperty("aai.url"),
335 getPEManagerEnvProperty("aai.username"),
336 getPEManagerEnvProperty("aai.password"),
337 aainqrequest, onset.getRequestID());
339 // Check AAI response
340 if (aainqresponse == null) {
341 logger.warn("No response received from AAI for request {}", aainqrequest);
345 // Create AAINQResponseWrapper
346 AAINQResponseWrapper aainqResponseWrapper = new AAINQResponseWrapper(onset.getRequestID(), aainqresponse);
348 if (logger.isDebugEnabled()) {
349 logger.debug("AAI Named Query Response: ");
350 logger.debug(Serialization.gsonPretty.toJson(aainqResponseWrapper.getAainqresponse()));
353 return aainqResponseWrapper;
357 * Find the base index or non base index in a list of inventory response items
358 * @param inventoryResponseItems
359 * @param baseIndexFlag true if we are searching for the base index, false if we are searching for hte non base index
360 * @return the base or non base index or -1 if the index was not found
362 private int findIndex(List<AAINQInventoryResponseItem> inventoryResponseItems, boolean baseIndexFlag) {
363 for (AAINQInventoryResponseItem invenoryResponseItem : inventoryResponseItems) {
364 if (invenoryResponseItem.getVfModule() != null && baseIndexFlag == invenoryResponseItem.getVfModule().getIsBaseVfModule()) {
365 return inventoryResponseItems.indexOf(invenoryResponseItem);
373 * Find the number of non base modules present in API response object.
375 * @param inventoryResponseItems
376 * @return number of non base index modules
379 private int findNonBaseModules(List<AAINQInventoryResponseItem> inventoryResponseItems) {
380 int nonBaseModuleCount = 0;
381 for (AAINQInventoryResponseItem invenoryResponseItem : inventoryResponseItems) {
382 if (invenoryResponseItem.getVfModule() != null
383 && (!invenoryResponseItem.getVfModule().getIsBaseVfModule())) {
384 nonBaseModuleCount++;
387 return nonBaseModuleCount;
391 * This method is called to remember the last service instance ID and VNF Item VNF ID. Note these fields are static, beware for multithreaded deployments
392 * @param vnfInstanceID update the last VNF instance ID to this value
393 * @param serviceInstanceID update the last service instance ID to this value
395 private static void preserveInstanceIDs(final String vnfInstanceID, final String serviceInstanceID) {
396 lastVNFItemVnfId = vnfInstanceID;
397 lastServiceItemServiceInstanceId = serviceInstanceID;
401 * This method reads and validates environmental properties coming from the policy engine. Null properties cause
402 * an {@link IllegalArgumentException} runtime exception to be thrown
403 * @param string the name of the parameter to retrieve
404 * @return the property value
406 private static String getPEManagerEnvProperty(String enginePropertyName) {
407 String enginePropertyValue = PolicyEngine.manager.getEnvironmentProperty(enginePropertyName);
408 if (enginePropertyValue == null) {
409 throw new IllegalArgumentException("The value of policy engine manager environment property \"" + enginePropertyName + "\" may not be null");
411 return enginePropertyValue;