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;
25 import com.google.gson.reflect.TypeToken;
26 import java.lang.reflect.Type;
27 import java.util.Collections;
28 import java.util.List;
30 import java.util.UUID;
31 import org.drools.core.WorkingMemory;
32 import org.onap.policy.aai.AaiNqExtraProperty;
33 import org.onap.policy.aai.AaiNqInventoryResponseItem;
34 import org.onap.policy.aai.AaiNqResponseWrapper;
35 import org.onap.policy.controlloop.ControlLoopOperation;
36 import org.onap.policy.controlloop.VirtualControlLoopEvent;
37 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
38 import org.onap.policy.controlloop.policy.Policy;
39 import org.onap.policy.so.*;
40 import org.onap.policy.so.util.Serialization;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
44 public class SOActorServiceProvider implements Actor {
45 private static final Logger logger = LoggerFactory.getLogger(SOActorServiceProvider.class);
47 // Strings for SO Actor
48 private static final String SO_ACTOR = "SO";
50 // Strings for targets
51 private static final String TARGET_VFC = "VFC";
53 // Strings for recipes
54 private static final String RECIPE_VF_MODULE_CREATE = "VF Module Create";
55 private static final String RECIPE_VF_MODULE_DELETE = "VF Module Delete";
57 private static final ImmutableList<String> recipes = ImmutableList.of(RECIPE_VF_MODULE_CREATE,
58 RECIPE_VF_MODULE_DELETE);
59 private static final ImmutableMap<String, List<String>> targets = new ImmutableMap.Builder<String, List<String>>()
60 .put(RECIPE_VF_MODULE_CREATE, ImmutableList.of(TARGET_VFC))
61 .put(RECIPE_VF_MODULE_DELETE, ImmutableList.of(TARGET_VFC)).build();
63 // name of request parameters within policy payload
64 public static final String REQ_PARAM_NM = "requestParameters";
66 // name of configuration parameters within policy payload
67 public static final String CONFIG_PARAM_NM = "configurationParameters";
69 private static final String MODEL_NAME_PROPERTY_KEY = "model-ver.model-name";
70 private static final String MODEL_VERSION_PROPERTY_KEY = "model-ver.model-version";
71 private static final String MODEL_VERSION_ID_PROPERTY_KEY = "model-ver.model-version-id";
73 // used to decode configuration parameters via gson
74 private static final Type CONFIG_TYPE = new TypeToken<List<Map<String, String>>>() {}.getType();
76 // Static variables required to hold the IDs of the last service item, VNF item and VF Module.
78 // a multithreaded deployment this WILL break
79 private static String lastVNFItemVnfId;
80 private static String lastServiceItemServiceInstanceId;
81 private static String lastVfModuleItemVfModuleInstanceId;
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 if (!SO_ACTOR.equals(policy.getActor()) || !recipes().contains(policy.getRecipe())) {
121 // A&AI named query should have been performed by now. If not, return null
122 if (aaiResponseWrapper == null) {
126 AaiNqInventoryResponseItem vnfItem;
127 AaiNqInventoryResponseItem vnfServiceItem;
128 AaiNqInventoryResponseItem tenantItem;
130 // Extract the items we're interested in from the response
132 vnfItem = aaiResponseWrapper.getAaiNqResponse().getInventoryResponseItems().get(0).getItems()
133 .getInventoryResponseItems().get(0);
134 } catch (Exception e) {
135 logger.error("VNF Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiResponseWrapper),
141 vnfServiceItem = vnfItem.getItems().getInventoryResponseItems().get(0);
142 } catch (Exception e) {
143 logger.error("VNF Service Item not found in AAI response {}",
144 Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
149 tenantItem = aaiResponseWrapper.getAaiNqResponse().getInventoryResponseItems().get(0).getItems()
150 .getInventoryResponseItems().get(1);
151 } catch (Exception e) {
152 logger.error("Tenant Item not found in AAI response {}",
153 Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
157 // Find the index for base vf module and non-base vf module
158 AaiNqInventoryResponseItem baseItem = findVfModule(aaiResponseWrapper, true);
159 AaiNqInventoryResponseItem vfModuleItem = findVfModule(aaiResponseWrapper, false);
161 // Report the error if either base vf module or non-base vf module is not found
162 if (baseItem == null || vfModuleItem == null) {
163 logger.error("Either base or non-base vf module is not found from AAI response.");
167 // Construct SO Request for a policy's recipe
168 if (RECIPE_VF_MODULE_CREATE.equals(policy.getRecipe())) {
169 return constructCreateRequest(aaiResponseWrapper, policy, tenantItem, vnfItem, vnfServiceItem,
171 } else if (RECIPE_VF_MODULE_DELETE.equals(policy.getRecipe())) {
172 return constructDeleteRequest(aaiResponseWrapper, tenantItem, vnfItem, vnfServiceItem, vfModuleItem);
179 * Construct SO request to create vf-module
181 * @param aaiResponseWrapper the AAI response containing the VF modules
182 * @param policy the policy
183 * @param tenantItem tenant item from A&AI named-query response
184 * @param vnfItem vnf item from A&AI named-query response
185 * @param vnfServiceItem vnf service item from A&AI named-query response
186 * @param vfModuleItem vf module item from A&AI named-query response
187 * @return SO create vf-module request
189 private SORequest constructCreateRequest(AaiNqResponseWrapper aaiResponseWrapper, Policy policy,
190 AaiNqInventoryResponseItem tenantItem, AaiNqInventoryResponseItem vnfItem,
191 AaiNqInventoryResponseItem vnfServiceItem,
192 AaiNqInventoryResponseItem vfModuleItem) {
193 SORequest request = new SORequest();
194 request.setOperationType(SoOperationType.SCALE_OUT);
197 // Do NOT send So the requestId, they do not support this field
199 request.setRequestDetails(new SORequestDetails());
200 request.getRequestDetails().setRequestParameters(new SORequestParameters());
201 request.getRequestDetails().getRequestParameters().setUserParams(null);
203 // cloudConfiguration
204 request.getRequestDetails().setCloudConfiguration(constructCloudConfiguration(tenantItem));
206 request.getRequestDetails().setModelInfo(constructVfModuleModelInfo(vfModuleItem));
207 request.getRequestDetails().getModelInfo().setModelVersionId(vfModuleItem.getVfModule().getModelVersionId());
210 request.getRequestDetails().setRequestInfo(constructRequestInfo());
211 String vfModuleName = aaiResponseWrapper.genVfModuleName();
212 request.getRequestDetails().getRequestInfo().setInstanceName(vfModuleName);
214 // relatedInstanceList
215 SORelatedInstanceListElement relatedInstanceListElement0 = new SORelatedInstanceListElement();
216 SORelatedInstanceListElement relatedInstanceListElement1 = new SORelatedInstanceListElement();
217 SORelatedInstanceListElement relatedInstanceListElement2 = new SORelatedInstanceListElement();
218 relatedInstanceListElement1.setRelatedInstance(new SORelatedInstance());
219 relatedInstanceListElement2.setRelatedInstance(new SORelatedInstance());
222 relatedInstanceListElement0.setRelatedInstance(new SORelatedInstance());
223 relatedInstanceListElement0.getRelatedInstance().setInstanceId(UUID.randomUUID().toString());
224 relatedInstanceListElement0.getRelatedInstance().setInstanceName(vfModuleName + "_vol");
225 relatedInstanceListElement0.getRelatedInstance().setModelInfo(new SOModelInfo());
226 relatedInstanceListElement0.getRelatedInstance().getModelInfo().setModelType("volumeGroup");
229 relatedInstanceListElement1.getRelatedInstance()
230 .setInstanceId(vnfServiceItem.getServiceInstance().getServiceInstanceId());
231 relatedInstanceListElement1.getRelatedInstance().setModelInfo(new SOModelInfo());
232 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelType("service");
233 relatedInstanceListElement1.getRelatedInstance().getModelInfo()
234 .setModelInvariantId(vnfServiceItem.getServiceInstance().getModelInvariantId());
235 for (AaiNqExtraProperty prop : vnfServiceItem.getExtraProperties().getExtraProperty()) {
236 if (prop.getPropertyName().equals(MODEL_NAME_PROPERTY_KEY)) {
237 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
238 } else if (prop.getPropertyName().equals(MODEL_VERSION_PROPERTY_KEY)) {
239 relatedInstanceListElement1.getRelatedInstance().getModelInfo()
240 .setModelVersion(prop.getPropertyValue());
241 } else if (prop.getPropertyName().equals(MODEL_VERSION_ID_PROPERTY_KEY)) {
242 relatedInstanceListElement1.getRelatedInstance().getModelInfo()
243 .setModelVersionId(prop.getPropertyValue());
248 relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getGenericVnf().getVnfId());
249 relatedInstanceListElement2.getRelatedInstance().setModelInfo(new SOModelInfo());
250 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelType("vnf");
251 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
252 .setModelInvariantId(vnfItem.getGenericVnf().getModelInvariantId());
253 for (AaiNqExtraProperty prop : vnfItem.getExtraProperties().getExtraProperty()) {
254 if (prop.getPropertyName().equals(MODEL_NAME_PROPERTY_KEY)) {
255 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
256 } else if (prop.getPropertyName().equals(MODEL_VERSION_PROPERTY_KEY)) {
257 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
258 .setModelVersion(prop.getPropertyValue());
259 } else if (prop.getPropertyName().equals(MODEL_VERSION_ID_PROPERTY_KEY)) {
260 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
261 .setModelVersionId(prop.getPropertyValue());
264 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
265 .setModelCustomizationName(vnfItem.getGenericVnf().getVnfType()
266 .substring(vnfItem.getGenericVnf().getVnfType().lastIndexOf('/') + 1));
267 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
268 .setModelCustomizationId(vnfItem.getGenericVnf().getModelCustomizationId());
270 // Insert the Service Item and VNF Item
271 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement0);
272 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement1);
273 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement2);
275 // Request Parameters
276 request.getRequestDetails().setRequestParameters(buildRequestParameters(policy));
278 // Configuration Parameters
279 request.getRequestDetails().setConfigurationParameters(buildConfigurationParameters(policy));
280 // Save the instance IDs for the VNF and service to static fields
281 // vfModuleId is not required for the create vf-module
282 preserveInstanceIds(vnfItem.getGenericVnf().getVnfId(), vnfServiceItem.getServiceInstance()
283 .getServiceInstanceId(), null);
284 if (logger.isDebugEnabled()) {
285 logger.debug("Constructed SO request: {}", Serialization.gsonPretty.toJson(request));
291 * Construct SO request to delete vf-module
293 * @param aaiResponseWrapper the AAI response containing the VF modules
294 * @param tenantItem tenant item from A&AI named-query response
295 * @param vnfItem vnf item from A&AI named-query response
296 * @param vnfServiceItem vnf service item from A&AI named-query response
297 * @param vfModuleItem vf module item from A&AI named-query response
298 * @return SO delete vf-module request
300 private SORequest constructDeleteRequest(AaiNqResponseWrapper aaiResponseWrapper, AaiNqInventoryResponseItem
301 tenantItem, AaiNqInventoryResponseItem vnfItem, AaiNqInventoryResponseItem vnfServiceItem,
302 AaiNqInventoryResponseItem vfModuleItem) {
303 SORequest request = new SORequest();
304 request.setOperationType(SoOperationType.DELETE_VF_MODULE);
305 request.setRequestDetails(new SORequestDetails());
306 request.getRequestDetails().setRelatedInstanceList(null);
307 request.getRequestDetails().setConfigurationParameters(null);
309 // cloudConfiguration
310 request.getRequestDetails().setCloudConfiguration(constructCloudConfiguration(tenantItem));
312 request.getRequestDetails().setModelInfo(constructVfModuleModelInfo(vfModuleItem));
314 request.getRequestDetails().setRequestInfo(constructRequestInfo());
315 // Save the instance IDs for the VNF, service and vfModule to static fields
316 preserveInstanceIds(vnfItem.getGenericVnf().getVnfId(), vnfServiceItem.getServiceInstance()
317 .getServiceInstanceId(), vfModuleItem.getVfModule().getVfModuleId());
319 if (logger.isDebugEnabled()) {
320 logger.debug("Constructed SO request: {}", Serialization.gsonPretty.toJson(request));
326 * construct requestInfo for the SO requestDetails
328 * @return SO request information
330 private SORequestInfo constructRequestInfo() {
331 SORequestInfo soRequestInfo = new SORequestInfo();
332 soRequestInfo.setSource("POLICY");
333 soRequestInfo.setSuppressRollback(false);
334 soRequestInfo.setRequestorId("policy");
335 return soRequestInfo;
339 * construct modelInfo of the vfModule for the SO requestDetails
341 * @param vfModuleItem vf module item from A&AI named-query response
342 * @return SO Model info for the vfModule
344 private SOModelInfo constructVfModuleModelInfo(AaiNqInventoryResponseItem vfModuleItem) {
345 SOModelInfo soModelInfo = new SOModelInfo();
346 soModelInfo.setModelType("vfModule");
347 soModelInfo.setModelInvariantId(vfModuleItem.getVfModule().getModelInvariantId());
348 soModelInfo.setModelCustomizationId(vfModuleItem.getVfModule().getModelCustomizationId());
350 for (AaiNqExtraProperty prop : vfModuleItem.getExtraProperties().getExtraProperty()) {
351 if (prop.getPropertyName().equals(MODEL_NAME_PROPERTY_KEY)) {
352 soModelInfo.setModelName(prop.getPropertyValue());
353 } else if (prop.getPropertyName().equals(MODEL_VERSION_PROPERTY_KEY)) {
354 soModelInfo.setModelVersion(prop.getPropertyValue());
361 * construct cloudConfiguration for the SO requestDetails
363 * @param tenantItem tenant item from A&AI named-query response
364 * @return SO cloud configuration
366 private SOCloudConfiguration constructCloudConfiguration(AaiNqInventoryResponseItem tenantItem) {
367 SOCloudConfiguration cloudConfiguration = new SOCloudConfiguration();
368 cloudConfiguration.setTenantId(tenantItem.getTenant().getTenantId());
369 cloudConfiguration.setLcpCloudRegionId(tenantItem.getItems().getInventoryResponseItems().get(0)
370 .getCloudRegion().getCloudRegionId());
371 return cloudConfiguration;
375 * This method is needed to get the serviceInstanceId and vnfInstanceId which is used
376 * in the asyncSORestCall.
378 * @param requestId the request Id
379 * @param wm the working memory
380 * @param request the request
382 public static void sendRequest(String requestId, WorkingMemory wm, Object request) {
383 SOManager soManager = new SOManager();
384 soManager.asyncSORestCall(requestId, wm, lastServiceItemServiceInstanceId, lastVNFItemVnfId,
385 lastVfModuleItemVfModuleInstanceId, (SORequest) request);
389 * Find the base or non base VF module item in an AAI response.
390 * If there is more than one item, then the <i>last</i> item is returned
392 * @param aaiResponseWrapper the AAI response containing the VF modules
393 * @param baseFlag true if we are searching for the base, false if we are searching
395 * @return the base or non base VF module item or null if the module was not found
397 private AaiNqInventoryResponseItem findVfModule(AaiNqResponseWrapper aaiResponseWrapper, boolean baseFlag) {
398 List<AaiNqInventoryResponseItem> lst = aaiResponseWrapper.getVfModuleItems(baseFlag);
399 return (lst == null || lst.isEmpty() ? null : lst.get(lst.size() - 1));
403 * Builds the request parameters from the policy payload.
405 * @param policy the policy
406 * @return the request parameters, or {@code null} if the payload is {@code null}
408 private SORequestParameters buildRequestParameters(Policy policy) {
409 if (policy.getPayload() == null) {
413 String json = policy.getPayload().get(REQ_PARAM_NM);
418 return Serialization.gsonPretty.fromJson(json, SORequestParameters.class);
422 * Builds the configuration parameters from the policy payload.
424 * @param policy the policy
425 * @return the configuration parameters, or {@code null} if the payload is
428 private List<Map<String, String>> buildConfigurationParameters(Policy policy) {
429 if (policy.getPayload() == null) {
433 String json = policy.getPayload().get(CONFIG_PARAM_NM);
438 return Serialization.gsonPretty.fromJson(json, CONFIG_TYPE);
442 * This method is called to remember the last service instance ID, VNF Item VNF ID and vf module ID.
443 * Note these fields are static, beware for multithreaded deployments
445 * @param vnfInstanceId update the last VNF instance ID to this value
446 * @param serviceInstanceId update the last service instance ID to this value
447 * @param vfModuleId update the vfModule instance ID to this value
449 private static void preserveInstanceIds(final String vnfInstanceId, final String serviceInstanceId,
450 final String vfModuleId) {
451 lastVNFItemVnfId = vnfInstanceId;
452 lastServiceItemServiceInstanceId = serviceInstanceId;
453 lastVfModuleItemVfModuleInstanceId = vfModuleId;