2 * ============LICENSE_START=======================================================
3 * SOActorServiceProvider
4 * ================================================================================
5 * Copyright (C) 2017-2018 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 com.google.common.collect.ImmutableList;
24 import com.google.common.collect.ImmutableMap;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.List;
30 import java.util.UUID;
32 import org.drools.core.WorkingMemory;
33 import org.onap.policy.aai.AAIManager;
34 import org.onap.policy.aai.AAINQExtraProperty;
35 import org.onap.policy.aai.AAINQInstanceFilters;
36 import org.onap.policy.aai.AAINQInventoryResponseItem;
37 import org.onap.policy.aai.AAINQNamedQuery;
38 import org.onap.policy.aai.AAINQQueryParameters;
39 import org.onap.policy.aai.AAINQRequest;
40 import org.onap.policy.aai.AAINQResponse;
41 import org.onap.policy.aai.AAINQResponseWrapper;
42 import org.onap.policy.controlloop.ControlLoopOperation;
43 import org.onap.policy.controlloop.VirtualControlLoopEvent;
44 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
45 import org.onap.policy.controlloop.policy.Policy;
46 import org.onap.policy.drools.system.PolicyEngine;
47 import org.onap.policy.rest.RESTManager;
48 import org.onap.policy.so.SOCloudConfiguration;
49 import org.onap.policy.so.SOManager;
50 import org.onap.policy.so.SOModelInfo;
51 import org.onap.policy.so.SORelatedInstance;
52 import org.onap.policy.so.SORelatedInstanceListElement;
53 import org.onap.policy.so.SORequest;
54 import org.onap.policy.so.SORequestDetails;
55 import org.onap.policy.so.SORequestInfo;
56 import org.onap.policy.so.SORequestParameters;
57 import org.onap.policy.so.util.Serialization;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
61 public class SOActorServiceProvider implements Actor {
62 private static final Logger logger = LoggerFactory.getLogger(SOActorServiceProvider.class);
64 // Strings for SO Actor
65 private static final String SO_ACTOR = "SO";
67 // Strings for targets
68 private static final String TARGET_VFC = "VFC";
70 // Strings for recipes
71 private static final String RECIPE_VF_MODULE_CREATE = "VF Module Create";
73 private static final ImmutableList<String> recipes = ImmutableList.of(RECIPE_VF_MODULE_CREATE);
74 private static final ImmutableMap<String, List<String>> targets = new ImmutableMap.Builder<String, List<String>>()
75 .put(RECIPE_VF_MODULE_CREATE, ImmutableList.of(TARGET_VFC)).build();
77 // Static variables required to hold the IDs of the last service item and VNF item. Note that in
78 // a multithreaded deployment this WILL break
79 private static String lastVNFItemVnfId;
80 private static String lastServiceItemServiceInstanceId;
83 public String actor() {
88 public List<String> recipes() {
89 return ImmutableList.copyOf(recipes);
93 public List<String> recipeTargets(String recipe) {
94 return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList()));
98 public List<String> recipePayloads(String recipe) {
99 return Collections.emptyList();
103 * Constructs a SO request conforming to the lcm API. The actual request is constructed and then
104 * placed in a wrapper object used to send through DMAAP.
106 * @param onset the event that is reporting the alert for policy to perform an action
107 * @param operation the control loop operation specifying the actor, operation, target, etc.
108 * @param policy the policy the was specified from the yaml generated by CLAMP or through the
110 * @return a SO request conforming to the lcm API using the DMAAP wrapper
112 public SORequest constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy) {
113 String modelNamePropertyKey = "model-ver.model-name";
114 String modelVersionPropertyKey = "model-ver.model-version";
115 String modelVersionIdPropertyKey = "model-ver.model-version-id";
118 if (!SO_ACTOR.equals(policy.getActor()) || !RECIPE_VF_MODULE_CREATE.equals(policy.getRecipe())) {
119 // for future extension
123 // Perform named query request and handle response
124 AAINQResponseWrapper aaiResponseWrapper = performAaiNamedQueryRequest(onset);
125 if (aaiResponseWrapper == null) {
126 // Tracing and error handling handied in the "performAaiNamedQueryRequest()" method
130 AAINQInventoryResponseItem vnfItem;
131 AAINQInventoryResponseItem vnfServiceItem;
132 AAINQInventoryResponseItem tenantItem;
134 // Extract the items we're interested in from the response
136 vnfItem = aaiResponseWrapper.getAainqresponse().getInventoryResponseItems().get(0).getItems()
137 .getInventoryResponseItems().get(0);
138 } catch (Exception e) {
139 logger.error("VNF Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiResponseWrapper),
145 vnfServiceItem = vnfItem.getItems().getInventoryResponseItems().get(0);
146 } catch (Exception e) {
147 logger.error("VNF Service Item not found in AAI response {}",
148 Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
153 tenantItem = aaiResponseWrapper.getAainqresponse().getInventoryResponseItems().get(0).getItems()
154 .getInventoryResponseItems().get(1);
155 } catch (Exception e) {
156 logger.error("Tenant Item not found in AAI response {}",
157 Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
161 // Find the index for base vf module and non-base vf module
162 int baseIndex = findIndex(vnfItem.getItems().getInventoryResponseItems(), true);
163 int nonBaseIndex = findIndex(vnfItem.getItems().getInventoryResponseItems(), false);
165 // Report the error if either base vf module or non-base vf module is not found
166 if (baseIndex == -1 || nonBaseIndex == -1) {
167 logger.error("Either base or non-base vf module is not found from AAI response.");
172 // Construct SO Request
173 SORequest request = new SORequest();
174 request.setRequestId(onset.getRequestID());
175 request.setRequestDetails(new SORequestDetails());
176 request.getRequestDetails().setModelInfo(new SOModelInfo());
177 request.getRequestDetails().setCloudConfiguration(new SOCloudConfiguration());
178 request.getRequestDetails().setRequestInfo(new SORequestInfo());
179 request.getRequestDetails().setRequestParameters(new SORequestParameters());
180 request.getRequestDetails().getRequestParameters().setUserParams(null);
183 // cloudConfiguration
185 request.getRequestDetails().getCloudConfiguration().setTenantId(tenantItem.getTenant().getTenantId());
186 request.getRequestDetails().getCloudConfiguration().setLcpCloudRegionId(
187 tenantItem.getItems().getInventoryResponseItems().get(0).getCloudRegion().getCloudRegionId());
192 AAINQInventoryResponseItem vfModuleItem = vnfItem.getItems().getInventoryResponseItems().get(nonBaseIndex);
194 request.getRequestDetails().getModelInfo().setModelType("vfModule");
195 request.getRequestDetails().getModelInfo()
196 .setModelInvariantId(vfModuleItem.getVfModule().getModelInvariantId());
197 request.getRequestDetails().getModelInfo().setModelVersionId(vfModuleItem.getVfModule().getModelVersionId());
199 for (AAINQExtraProperty prop : vfModuleItem.getExtraProperties().getExtraProperty()) {
200 if (prop.getPropertyName().equals(modelNamePropertyKey)) {
201 request.getRequestDetails().getModelInfo().setModelName(prop.getPropertyValue());
202 } else if (prop.getPropertyName().equals(modelVersionPropertyKey)) {
203 request.getRequestDetails().getModelInfo().setModelVersion(prop.getPropertyValue());
210 String instanceName = vnfItem.getItems().getInventoryResponseItems().get(baseIndex).getVfModule()
211 .getVfModuleName().replace("Vfmodule", "vDNS");
212 int numberOfNonBaseModules = findNonBaseModules(vnfItem.getItems().getInventoryResponseItems());
213 // Code to create unique VF Module names across the invocations.
214 if (numberOfNonBaseModules == 1) {
215 int instanceNumber = 1;
216 instanceName = instanceName.concat("-").concat(String.valueOf(instanceNumber));
217 request.getRequestDetails().getRequestInfo().setInstanceName(instanceName);
218 } else if (numberOfNonBaseModules > 1) {
219 int instanceNumber = numberOfNonBaseModules + 1;
220 instanceName = instanceName.concat("-").concat(String.valueOf(instanceNumber));
221 request.getRequestDetails().getRequestInfo().setInstanceName(instanceName);
223 request.getRequestDetails().getRequestInfo().setInstanceName(vnfItem.getItems().getInventoryResponseItems()
224 .get(baseIndex).getVfModule().getVfModuleName().replace("Vfmodule", "vDNS"));
226 request.getRequestDetails().getRequestInfo().setSource("POLICY");
227 request.getRequestDetails().getRequestInfo().setSuppressRollback(false);
228 request.getRequestDetails().getRequestInfo().setRequestorId("policy");
231 // relatedInstanceList
233 SORelatedInstanceListElement relatedInstanceListElement1 = new SORelatedInstanceListElement();
234 SORelatedInstanceListElement relatedInstanceListElement2 = new SORelatedInstanceListElement();
235 relatedInstanceListElement1.setRelatedInstance(new SORelatedInstance());
236 relatedInstanceListElement2.setRelatedInstance(new SORelatedInstance());
239 relatedInstanceListElement1.getRelatedInstance()
240 .setInstanceId(vnfServiceItem.getServiceInstance().getServiceInstanceID());
241 relatedInstanceListElement1.getRelatedInstance().setModelInfo(new SOModelInfo());
242 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelType("service");
243 relatedInstanceListElement1.getRelatedInstance().getModelInfo()
244 .setModelInvariantId(vnfServiceItem.getServiceInstance().getModelInvariantId());
245 for (AAINQExtraProperty prop : vnfServiceItem.getExtraProperties().getExtraProperty()) {
246 if (prop.getPropertyName().equals(modelNamePropertyKey)) {
247 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
248 } else if (prop.getPropertyName().equals(modelVersionPropertyKey)) {
249 relatedInstanceListElement1.getRelatedInstance().getModelInfo()
250 .setModelVersion(prop.getPropertyValue());
255 relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getGenericVNF().getVnfID());
256 relatedInstanceListElement2.getRelatedInstance().setModelInfo(new SOModelInfo());
257 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelType("vnf");
258 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
259 .setModelInvariantId(vnfItem.getGenericVNF().getModelInvariantId());
260 for (AAINQExtraProperty prop : vnfItem.getExtraProperties().getExtraProperty()) {
261 if (prop.getPropertyName().equals(modelNamePropertyKey)) {
262 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
263 } else if (prop.getPropertyName().equals(modelVersionPropertyKey)) {
264 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
265 .setModelVersion(prop.getPropertyValue());
266 } else if (prop.getPropertyName().equals(modelVersionIdPropertyKey)) {
267 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
268 .setModelVersionId(prop.getPropertyValue());
271 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelCustomizationName(vnfItem
272 .getGenericVNF().getVnfType().substring(vnfItem.getGenericVNF().getVnfType().lastIndexOf('/') + 1));
274 // Insert the Service Item and VNF Item
275 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement1);
276 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement2);
278 // Save the instance IDs for the VNF and service to static fields
279 preserveInstanceIds(vnfItem.getGenericVNF().getVnfID(),
280 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 in the
293 * @param requestId the request Id
294 * @param wm the working memory
295 * @param request the request
297 public static void sendRequest(String requestId, WorkingMemory wm, Object request) {
298 SOManager soManager = new SOManager();
299 soManager.asyncSORestCall(requestId, wm, lastServiceItemServiceInstanceId, lastVNFItemVnfId,
300 (SORequest) request);
304 * Constructs and sends an AAI vserver Named Query.
306 * @param onset the virtial control loop event
307 * @returns the response to the AAI Named Query
309 private AAINQResponseWrapper performAaiNamedQueryRequest(VirtualControlLoopEvent onset) {
311 // create AAI named-query request with UUID started with ""
312 AAINQRequest aaiNqRequest = new AAINQRequest();
313 AAINQQueryParameters aaiNqQueryParam = new AAINQQueryParameters();
314 AAINQNamedQuery aaiNqNamedQuery = new AAINQNamedQuery();
315 final AAINQInstanceFilters aaiNqInstanceFilter = new AAINQInstanceFilters();
318 // UUID.fromString($params.getAaiNamedQueryUUID()) TO DO: AaiNamedQueryUUID
319 aaiNqNamedQuery.setNamedQueryUUID(UUID.fromString("4ff56a54-9e3f-46b7-a337-07a1d3c6b469"));
320 aaiNqQueryParam.setNamedQuery(aaiNqNamedQuery);
321 aaiNqRequest.setQueryParameters(aaiNqQueryParam);
325 Map<String, Map<String, String>> aaiNqInstanceFilterMap = new HashMap<>();
326 Map<String, String> aaiNqInstanceFilterMapItem = new HashMap<>();
327 // TO DO: get vserver.vname from dcae onset.AAI.get("vserver.vserver-name")
328 aaiNqInstanceFilterMapItem.put("vserver-name", onset.getAAI().get("vserver.vserver-name"));
329 aaiNqInstanceFilterMap.put("vserver", aaiNqInstanceFilterMapItem);
330 aaiNqInstanceFilter.getInstanceFilter().add(aaiNqInstanceFilterMap);
331 aaiNqRequest.setInstanceFilters(aaiNqInstanceFilter);
333 if (logger.isDebugEnabled()) {
334 logger.debug("AAI Request sent: {}", Serialization.gsonPretty.toJson(aaiNqRequest));
337 AAINQResponse aaiNqResponse = new AAIManager(new RESTManager()).postQuery(getPeManagerEnvProperty("aai.url"),
338 getPeManagerEnvProperty("aai.username"), getPeManagerEnvProperty("aai.password"), aaiNqRequest,
339 onset.getRequestID());
341 // Check AAI response
342 if (aaiNqResponse == null) {
343 logger.warn("No response received from AAI for request {}", aaiNqRequest);
347 // Create AAINQResponseWrapper
348 AAINQResponseWrapper aaiNqResponseWrapper = new AAINQResponseWrapper(onset.getRequestID(), aaiNqResponse);
350 if (logger.isDebugEnabled()) {
351 logger.debug("AAI Named Query Response: ");
352 logger.debug(Serialization.gsonPretty.toJson(aaiNqResponseWrapper.getAainqresponse()));
355 return aaiNqResponseWrapper;
359 * Find the base index or non base index in a list of inventory response items.
361 * @param inventoryResponseItems the list of inventory response items
362 * @param baseIndexFlag true if we are searching for the base index, false if we are searching
363 * for the non base index
364 * @return the base or non base index or -1 if the index was not found
366 private int findIndex(List<AAINQInventoryResponseItem> inventoryResponseItems, boolean baseIndexFlag) {
367 for (AAINQInventoryResponseItem invenoryResponseItem : inventoryResponseItems) {
368 if (invenoryResponseItem.getVfModule() != null
369 && baseIndexFlag == invenoryResponseItem.getVfModule().getIsBaseVfModule()) {
370 return inventoryResponseItems.indexOf(invenoryResponseItem);
378 * Find the number of non base modules present in API response object.
380 * @param inventoryResponseItems the list of inventory response items
381 * @return number of non base index modules
384 private int findNonBaseModules(List<AAINQInventoryResponseItem> inventoryResponseItems) {
385 int nonBaseModuleCount = 0;
386 for (AAINQInventoryResponseItem invenoryResponseItem : inventoryResponseItems) {
387 if (invenoryResponseItem.getVfModule() != null
388 && (!invenoryResponseItem.getVfModule().getIsBaseVfModule())) {
389 nonBaseModuleCount++;
392 return nonBaseModuleCount;
396 * This method is called to remember the last service instance ID and VNF Item VNF ID. Note
397 * these fields are static, beware for multithreaded deployments
399 * @param vnfInstanceId update the last VNF instance ID to this value
400 * @param serviceInstanceId update the last service instance ID to this value
402 private static void preserveInstanceIds(final String vnfInstanceId, final String serviceInstanceId) {
403 lastVNFItemVnfId = vnfInstanceId;
404 lastServiceItemServiceInstanceId = serviceInstanceId;
408 * This method reads and validates environmental properties coming from the policy engine. Null
409 * properties cause an {@link IllegalArgumentException} runtime exception to be thrown
411 * @param string the name of the parameter to retrieve
412 * @return the property value
414 private static String getPeManagerEnvProperty(String enginePropertyName) {
415 String enginePropertyValue = PolicyEngine.manager.getEnvironmentProperty(enginePropertyName);
416 if (enginePropertyValue == null) {
417 throw new IllegalArgumentException("The value of policy engine manager environment property \""
418 + enginePropertyName + "\" may not be null");
420 return enginePropertyValue;