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 java.lang.reflect.Type;
24 import java.util.Collections;
25 import java.util.List;
27 import java.util.UUID;
28 import org.drools.core.WorkingMemory;
29 import org.onap.policy.aai.AaiNqExtraProperty;
30 import org.onap.policy.aai.AaiNqInventoryResponseItem;
31 import org.onap.policy.aai.AaiNqResponseWrapper;
32 import org.onap.policy.controlloop.ControlLoopOperation;
33 import org.onap.policy.controlloop.VirtualControlLoopEvent;
34 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
35 import org.onap.policy.controlloop.policy.Policy;
36 import org.onap.policy.so.SOCloudConfiguration;
37 import org.onap.policy.so.SOManager;
38 import org.onap.policy.so.SOModelInfo;
39 import org.onap.policy.so.SORelatedInstance;
40 import org.onap.policy.so.SORelatedInstanceListElement;
41 import org.onap.policy.so.SORequest;
42 import org.onap.policy.so.SORequestDetails;
43 import org.onap.policy.so.SORequestInfo;
44 import org.onap.policy.so.SORequestParameters;
45 import org.onap.policy.so.util.Serialization;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import com.google.common.collect.ImmutableList;
49 import com.google.common.collect.ImmutableMap;
50 import com.google.gson.reflect.TypeToken;
52 public class SOActorServiceProvider implements Actor {
53 private static final Logger logger = LoggerFactory.getLogger(SOActorServiceProvider.class);
55 // Strings for SO Actor
56 private static final String SO_ACTOR = "SO";
58 // Strings for targets
59 private static final String TARGET_VFC = "VFC";
61 // Strings for recipes
62 private static final String RECIPE_VF_MODULE_CREATE = "VF Module Create";
64 private static final ImmutableList<String> recipes = ImmutableList.of(RECIPE_VF_MODULE_CREATE);
65 private static final ImmutableMap<String, List<String>> targets = new ImmutableMap.Builder<String, List<String>>()
66 .put(RECIPE_VF_MODULE_CREATE, ImmutableList.of(TARGET_VFC)).build();
68 // name of request parameters within policy payload
69 public static final String REQ_PARAM_NM = "requestParameters";
71 // name of configuration parameters within policy payload
72 public static final String CONFIG_PARAM_NM = "configurationParameters";
74 // used to decode configuration parameters via gson
75 public static Type CONFIG_TYPE = new TypeToken<List<Map<String, String>>>() {}.getType();
77 // Static variables required to hold the IDs of the last service item and VNF item.
79 // 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. The actual request is
105 * constructed and then placed in a wrapper object used to send through DMAAP.
107 * @param onset the event that is reporting the alert for policy to perform an action
108 * @param operation the control loop operation specifying the actor, operation,
110 * @param policy the policy the was specified from the yaml generated by CLAMP or
111 * through the Policy GUI/API
112 * @param aaiResponseWrapper wrapper for AAI vserver named-query response
113 * @return a SO request conforming to the lcm API using the DMAAP wrapper
115 public SORequest constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy,
116 AaiNqResponseWrapper aaiResponseWrapper) {
117 String modelNamePropertyKey = "model-ver.model-name";
118 String modelVersionPropertyKey = "model-ver.model-version";
119 String modelVersionIdPropertyKey = "model-ver.model-version-id";
122 if (!SO_ACTOR.equals(policy.getActor()) || !RECIPE_VF_MODULE_CREATE.equals(policy.getRecipe())) {
123 // for future extension
127 // Perform named query request and handle response
128 if (aaiResponseWrapper == null) {
132 AaiNqInventoryResponseItem vnfItem;
133 AaiNqInventoryResponseItem vnfServiceItem;
134 AaiNqInventoryResponseItem tenantItem;
136 // Extract the items we're interested in from the response
138 vnfItem = aaiResponseWrapper.getAaiNqResponse().getInventoryResponseItems().get(0).getItems()
139 .getInventoryResponseItems().get(0);
140 } catch (Exception e) {
141 logger.error("VNF Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiResponseWrapper),
147 vnfServiceItem = vnfItem.getItems().getInventoryResponseItems().get(0);
148 } catch (Exception e) {
149 logger.error("VNF Service Item not found in AAI response {}",
150 Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
155 tenantItem = aaiResponseWrapper.getAaiNqResponse().getInventoryResponseItems().get(0).getItems()
156 .getInventoryResponseItems().get(1);
157 } catch (Exception e) {
158 logger.error("Tenant Item not found in AAI response {}",
159 Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
163 // Find the index for base vf module and non-base vf module
164 AaiNqInventoryResponseItem baseItem = findVfModule(aaiResponseWrapper, true);
165 AaiNqInventoryResponseItem vfModuleItem = findVfModule(aaiResponseWrapper, false);
167 // Report the error if either base vf module or non-base vf module is not found
168 if (baseItem == null || vfModuleItem == null) {
169 logger.error("Either base or non-base vf module is not found from AAI response.");
174 // Construct SO Request
175 SORequest request = new SORequest();
177 // Do NOT send So the requestId, they do not support this field
179 request.setRequestDetails(new SORequestDetails());
180 request.getRequestDetails().setModelInfo(new SOModelInfo());
181 request.getRequestDetails().setCloudConfiguration(new SOCloudConfiguration());
182 request.getRequestDetails().setRequestInfo(new SORequestInfo());
183 request.getRequestDetails().setRequestParameters(new SORequestParameters());
184 request.getRequestDetails().getRequestParameters().setUserParams(null);
187 // cloudConfiguration
189 request.getRequestDetails().getCloudConfiguration().setTenantId(tenantItem.getTenant().getTenantId());
190 request.getRequestDetails().getCloudConfiguration().setLcpCloudRegionId(
191 tenantItem.getItems().getInventoryResponseItems().get(0).getCloudRegion().getCloudRegionId());
196 request.getRequestDetails().getModelInfo().setModelType("vfModule");
197 request.getRequestDetails().getModelInfo()
198 .setModelInvariantId(vfModuleItem.getVfModule().getModelInvariantId());
199 request.getRequestDetails().getModelInfo().setModelVersionId(vfModuleItem.getVfModule().getModelVersionId());
200 request.getRequestDetails().getModelInfo()
201 .setModelCustomizationId(vfModuleItem.getVfModule().getModelCustomizationId());
203 for (AaiNqExtraProperty prop : vfModuleItem.getExtraProperties().getExtraProperty()) {
204 if (prop.getPropertyName().equals(modelNamePropertyKey)) {
205 request.getRequestDetails().getModelInfo().setModelName(prop.getPropertyValue());
206 } else if (prop.getPropertyName().equals(modelVersionPropertyKey)) {
207 request.getRequestDetails().getModelInfo().setModelVersion(prop.getPropertyValue());
214 String vfModuleName = aaiResponseWrapper.genVfModuleName();
215 request.getRequestDetails().getRequestInfo().setInstanceName(vfModuleName);
216 request.getRequestDetails().getRequestInfo().setSource("POLICY");
217 request.getRequestDetails().getRequestInfo().setSuppressRollback(false);
218 request.getRequestDetails().getRequestInfo().setRequestorId("policy");
221 // relatedInstanceList
223 SORelatedInstanceListElement relatedInstanceListElement0 = new SORelatedInstanceListElement();
224 SORelatedInstanceListElement relatedInstanceListElement1 = new SORelatedInstanceListElement();
225 SORelatedInstanceListElement relatedInstanceListElement2 = new SORelatedInstanceListElement();
226 relatedInstanceListElement1.setRelatedInstance(new SORelatedInstance());
227 relatedInstanceListElement2.setRelatedInstance(new SORelatedInstance());
230 relatedInstanceListElement0.setRelatedInstance(new SORelatedInstance());
231 relatedInstanceListElement0.getRelatedInstance().setInstanceId(UUID.randomUUID().toString());
232 relatedInstanceListElement0.getRelatedInstance().setInstanceName(vfModuleName + "_vol");
233 relatedInstanceListElement0.getRelatedInstance().setModelInfo(new SOModelInfo());
234 relatedInstanceListElement0.getRelatedInstance().getModelInfo().setModelType("volumeGroup");
237 relatedInstanceListElement1.getRelatedInstance()
238 .setInstanceId(vnfServiceItem.getServiceInstance().getServiceInstanceId());
239 relatedInstanceListElement1.getRelatedInstance().setModelInfo(new SOModelInfo());
240 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelType("service");
241 relatedInstanceListElement1.getRelatedInstance().getModelInfo()
242 .setModelInvariantId(vnfServiceItem.getServiceInstance().getModelInvariantId());
243 for (AaiNqExtraProperty prop : vnfServiceItem.getExtraProperties().getExtraProperty()) {
244 if (prop.getPropertyName().equals(modelNamePropertyKey)) {
245 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
246 } else if (prop.getPropertyName().equals(modelVersionPropertyKey)) {
247 relatedInstanceListElement1.getRelatedInstance().getModelInfo()
248 .setModelVersion(prop.getPropertyValue());
249 } else if (prop.getPropertyName().equals(modelVersionIdPropertyKey)) {
250 relatedInstanceListElement1.getRelatedInstance().getModelInfo()
251 .setModelVersionId(prop.getPropertyValue());
256 relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getGenericVnf().getVnfId());
257 relatedInstanceListElement2.getRelatedInstance().setModelInfo(new SOModelInfo());
258 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelType("vnf");
259 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
260 .setModelInvariantId(vnfItem.getGenericVnf().getModelInvariantId());
261 for (AaiNqExtraProperty prop : vnfItem.getExtraProperties().getExtraProperty()) {
262 if (prop.getPropertyName().equals(modelNamePropertyKey)) {
263 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
264 } else if (prop.getPropertyName().equals(modelVersionPropertyKey)) {
265 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
266 .setModelVersion(prop.getPropertyValue());
267 } else if (prop.getPropertyName().equals(modelVersionIdPropertyKey)) {
268 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
269 .setModelVersionId(prop.getPropertyValue());
272 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
273 .setModelCustomizationName(vnfItem.getGenericVnf().getVnfType()
274 .substring(vnfItem.getGenericVnf().getVnfType().lastIndexOf('/') + 1));
275 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
276 .setModelCustomizationId(vnfItem.getGenericVnf().getModelCustomizationId());
278 // Insert the Service Item and VNF Item
279 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement0);
280 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement1);
281 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement2);
283 // Request Parameters
284 request.getRequestDetails().setRequestParameters(buildRequestParameters(policy));
286 // Configuration Parameters
287 request.getRequestDetails().setConfigurationParameters(buildConfigurationParameters(policy));
289 // Save the instance IDs for the VNF and service to static fields
290 preserveInstanceIds(vnfItem.getGenericVnf().getVnfId(),
291 vnfServiceItem.getServiceInstance().getServiceInstanceId());
293 if (logger.isDebugEnabled()) {
294 logger.debug("SO request sent: {}", Serialization.gsonPretty.toJson(request));
301 * This method is needed to get the serviceInstanceId and vnfInstanceId which is used
302 * in the asyncSORestCall.
304 * @param requestId the request Id
305 * @param wm the working memory
306 * @param request the request
308 public static void sendRequest(String requestId, WorkingMemory wm, Object request) {
309 SOManager soManager = new SOManager();
310 soManager.asyncSORestCall(requestId, wm, lastServiceItemServiceInstanceId, lastVNFItemVnfId,
311 (SORequest) request);
315 * Find the base or non base VF module item in an AAI response.
317 * @param aaiResponseWrapper the AAI response containing the VF modules
318 * @param baseFlag true if we are searching for the base, false if we are searching
320 * @return the base or non base VF module item or null if the module was not found
322 private AaiNqInventoryResponseItem findVfModule(AaiNqResponseWrapper aaiResponseWrapper, boolean baseFlag) {
323 List<AaiNqInventoryResponseItem> lst = aaiResponseWrapper.getVfModuleItems(baseFlag);
324 return (lst == null || lst.isEmpty() ? null : lst.get(0));
328 * Builds the request parameters from the policy payload.
330 * @param policy the policy
331 * @return the request parameters, or {@code null} if the payload is {@code null}
333 private SORequestParameters buildRequestParameters(Policy policy) {
334 if (policy.getPayload() == null) {
338 String json = policy.getPayload().get(REQ_PARAM_NM);
343 return Serialization.gsonPretty.fromJson(json, SORequestParameters.class);
347 * Builds the configuration parameters from the policy payload.
349 * @param policy the policy
350 * @return the configuration parameters, or {@code null} if the payload is
353 private List<Map<String, String>> buildConfigurationParameters(Policy policy) {
354 if (policy.getPayload() == null) {
358 String json = policy.getPayload().get(CONFIG_PARAM_NM);
363 return Serialization.gsonPretty.fromJson(json, CONFIG_TYPE);
367 * This method is called to remember the last service instance ID and VNF Item VNF ID.
368 * Note these fields are static, beware for multithreaded deployments
370 * @param vnfInstanceId update the last VNF instance ID to this value
371 * @param serviceInstanceId update the last service instance ID to this value
373 private static void preserveInstanceIds(final String vnfInstanceId, final String serviceInstanceId) {
374 lastVNFItemVnfId = vnfInstanceId;
375 lastServiceItemServiceInstanceId = serviceInstanceId;