2 * ============LICENSE_START=======================================================
3 * SOActorServiceProvider
4 * ================================================================================
5 * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2019 Nordix Foundation.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.controlloop.actor.so;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.ImmutableMap;
26 import com.google.gson.reflect.TypeToken;
27 import java.lang.reflect.Type;
28 import java.util.Collections;
29 import java.util.List;
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.SoCloudConfiguration;
40 import org.onap.policy.so.SoManager;
41 import org.onap.policy.so.SoModelInfo;
42 import org.onap.policy.so.SoOperationType;
43 import org.onap.policy.so.SoRelatedInstance;
44 import org.onap.policy.so.SoRelatedInstanceListElement;
45 import org.onap.policy.so.SoRequest;
46 import org.onap.policy.so.SoRequestDetails;
47 import org.onap.policy.so.SoRequestInfo;
48 import org.onap.policy.so.SoRequestParameters;
49 import org.onap.policy.so.util.Serialization;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
53 public class SoActorServiceProvider implements Actor {
54 private static final Logger logger = LoggerFactory.getLogger(SoActorServiceProvider.class);
56 // Strings for SO Actor
57 private static final String SO_ACTOR = "SO";
59 // Strings for targets
60 private static final String TARGET_VFC = "VFC";
62 // Strings for recipes
63 private static final String RECIPE_VF_MODULE_CREATE = "VF Module Create";
64 private static final String RECIPE_VF_MODULE_DELETE = "VF Module Delete";
66 private static final ImmutableList<String> recipes = ImmutableList.of(RECIPE_VF_MODULE_CREATE,
67 RECIPE_VF_MODULE_DELETE);
68 private static final ImmutableMap<String, List<String>> targets = new ImmutableMap.Builder<String, List<String>>()
69 .put(RECIPE_VF_MODULE_CREATE, ImmutableList.of(TARGET_VFC))
70 .put(RECIPE_VF_MODULE_DELETE, ImmutableList.of(TARGET_VFC)).build();
72 // name of request parameters within policy payload
73 public static final String REQ_PARAM_NM = "requestParameters";
75 // name of configuration parameters within policy payload
76 public static final String CONFIG_PARAM_NM = "configurationParameters";
78 private static final String MODEL_NAME_PROPERTY_KEY = "model-ver.model-name";
79 private static final String MODEL_VERSION_PROPERTY_KEY = "model-ver.model-version";
80 private static final String MODEL_VERSION_ID_PROPERTY_KEY = "model-ver.model-version-id";
82 // used to decode configuration parameters via gson
83 private static final Type CONFIG_TYPE = new TypeToken<List<Map<String, String>>>() {}.getType();
85 // Static variables required to hold the IDs of the last service item, VNF item and VF Module.
87 // a multithreaded deployment this WILL break
88 private static String lastVNFItemVnfId;
89 private static String lastServiceItemServiceInstanceId;
90 private static String lastVfModuleItemVfModuleInstanceId;
93 public String actor() {
98 public List<String> recipes() {
99 return ImmutableList.copyOf(recipes);
103 public List<String> recipeTargets(String recipe) {
104 return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList()));
108 public List<String> recipePayloads(String recipe) {
109 return Collections.emptyList();
113 * Constructs a SO request conforming to the lcm API. The actual request is
114 * constructed and then placed in a wrapper object used to send through DMAAP.
116 * @param onset the event that is reporting the alert for policy to perform an action
117 * @param operation the control loop operation specifying the actor, operation,
119 * @param policy the policy the was specified from the yaml generated by CLAMP or
120 * through the Policy GUI/API
121 * @param aaiResponseWrapper wrapper for AAI vserver named-query response
122 * @return a SO request conforming to the lcm API using the DMAAP wrapper
124 public SoRequest constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy,
125 AaiNqResponseWrapper aaiResponseWrapper) {
126 if (!SO_ACTOR.equals(policy.getActor()) || !recipes().contains(policy.getRecipe())) {
130 // A&AI named query should have been performed by now. If not, return null
131 if (aaiResponseWrapper == null) {
135 AaiNqInventoryResponseItem vnfItem;
136 AaiNqInventoryResponseItem vnfServiceItem;
137 AaiNqInventoryResponseItem tenantItem;
139 // Extract the items we're interested in from the response
141 vnfItem = aaiResponseWrapper.getAaiNqResponse().getInventoryResponseItems().get(0).getItems()
142 .getInventoryResponseItems().get(0);
143 } catch (Exception e) {
144 logger.error("VNF Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiResponseWrapper),
150 vnfServiceItem = vnfItem.getItems().getInventoryResponseItems().get(0);
151 } catch (Exception e) {
152 logger.error("VNF Service Item not found in AAI response {}",
153 Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
158 tenantItem = aaiResponseWrapper.getAaiNqResponse().getInventoryResponseItems().get(0).getItems()
159 .getInventoryResponseItems().get(1);
160 } catch (Exception e) {
161 logger.error("Tenant Item not found in AAI response {}",
162 Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
166 // Find the index for base vf module and non-base vf module
167 AaiNqInventoryResponseItem baseItem = findVfModule(aaiResponseWrapper, true);
168 AaiNqInventoryResponseItem vfModuleItem = findVfModule(aaiResponseWrapper, false);
170 // Report the error if either base vf module or non-base vf module is not found
171 if (baseItem == null || vfModuleItem == null) {
172 logger.error("Either base or non-base vf module is not found from AAI response.");
176 // Construct SO Request for a policy's recipe
177 if (RECIPE_VF_MODULE_CREATE.equals(policy.getRecipe())) {
178 return constructCreateRequest(aaiResponseWrapper, policy, tenantItem, vnfItem, vnfServiceItem,
180 } else if (RECIPE_VF_MODULE_DELETE.equals(policy.getRecipe())) {
181 return constructDeleteRequest(tenantItem, vnfItem, vnfServiceItem, vfModuleItem);
188 * Construct SO request to create vf-module.
190 * @param aaiResponseWrapper the AAI response containing the VF modules
191 * @param policy the policy
192 * @param tenantItem tenant item from A&AI named-query response
193 * @param vnfItem vnf item from A&AI named-query response
194 * @param vnfServiceItem vnf service item from A&AI named-query response
195 * @param vfModuleItem vf module item from A&AI named-query response
196 * @return SO create vf-module request
198 private SoRequest constructCreateRequest(AaiNqResponseWrapper aaiResponseWrapper, Policy policy,
199 AaiNqInventoryResponseItem tenantItem, AaiNqInventoryResponseItem vnfItem,
200 AaiNqInventoryResponseItem vnfServiceItem,
201 AaiNqInventoryResponseItem vfModuleItem) {
202 SoRequest request = new SoRequest();
203 request.setOperationType(SoOperationType.SCALE_OUT);
206 // Do NOT send So the requestId, they do not support this field
208 request.setRequestDetails(new SoRequestDetails());
209 request.getRequestDetails().setRequestParameters(new SoRequestParameters());
210 request.getRequestDetails().getRequestParameters().setUserParams(null);
212 // cloudConfiguration
213 request.getRequestDetails().setCloudConfiguration(constructCloudConfiguration(tenantItem));
215 request.getRequestDetails().setModelInfo(constructVfModuleModelInfo(vfModuleItem));
216 request.getRequestDetails().getModelInfo().setModelVersionId(vfModuleItem.getVfModule().getModelVersionId());
219 request.getRequestDetails().setRequestInfo(constructRequestInfo());
220 String vfModuleName = aaiResponseWrapper.genVfModuleName();
221 request.getRequestDetails().getRequestInfo().setInstanceName(vfModuleName);
223 // relatedInstanceList
224 SoRelatedInstanceListElement relatedInstanceListElement1 = new SoRelatedInstanceListElement();
225 SoRelatedInstanceListElement relatedInstanceListElement2 = new SoRelatedInstanceListElement();
226 relatedInstanceListElement1.setRelatedInstance(new SoRelatedInstance());
227 relatedInstanceListElement2.setRelatedInstance(new SoRelatedInstance());
230 relatedInstanceListElement1.getRelatedInstance()
231 .setInstanceId(vnfServiceItem.getServiceInstance().getServiceInstanceId());
232 relatedInstanceListElement1.getRelatedInstance().setModelInfo(new SoModelInfo());
233 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelType("service");
234 relatedInstanceListElement1.getRelatedInstance().getModelInfo()
235 .setModelInvariantId(vnfServiceItem.getServiceInstance().getModelInvariantId());
236 for (AaiNqExtraProperty prop : vnfServiceItem.getExtraProperties().getExtraProperty()) {
237 if (prop.getPropertyName().equals(MODEL_NAME_PROPERTY_KEY)) {
238 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
239 } else if (prop.getPropertyName().equals(MODEL_VERSION_PROPERTY_KEY)) {
240 relatedInstanceListElement1.getRelatedInstance().getModelInfo()
241 .setModelVersion(prop.getPropertyValue());
242 } else if (prop.getPropertyName().equals(MODEL_VERSION_ID_PROPERTY_KEY)) {
243 relatedInstanceListElement1.getRelatedInstance().getModelInfo()
244 .setModelVersionId(prop.getPropertyValue());
249 relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getGenericVnf().getVnfId());
250 relatedInstanceListElement2.getRelatedInstance().setModelInfo(new SoModelInfo());
251 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelType("vnf");
252 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
253 .setModelInvariantId(vnfItem.getGenericVnf().getModelInvariantId());
254 for (AaiNqExtraProperty prop : vnfItem.getExtraProperties().getExtraProperty()) {
255 if (prop.getPropertyName().equals(MODEL_NAME_PROPERTY_KEY)) {
256 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelName(prop.getPropertyValue());
257 } else if (prop.getPropertyName().equals(MODEL_VERSION_PROPERTY_KEY)) {
258 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
259 .setModelVersion(prop.getPropertyValue());
260 } else if (prop.getPropertyName().equals(MODEL_VERSION_ID_PROPERTY_KEY)) {
261 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
262 .setModelVersionId(prop.getPropertyValue());
265 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
266 .setModelCustomizationName(vnfItem.getGenericVnf().getVnfType()
267 .substring(vnfItem.getGenericVnf().getVnfType().lastIndexOf('/') + 1));
268 relatedInstanceListElement2.getRelatedInstance().getModelInfo()
269 .setModelCustomizationId(vnfItem.getGenericVnf().getModelCustomizationId());
271 // Insert the Service Item and VNF Item
272 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement1);
273 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement2);
275 // Request Parameters
276 buildRequestParameters(policy, request.getRequestDetails());
278 // Configuration Parameters
279 buildConfigurationParameters(policy, request.getRequestDetails());
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 tenantItem tenant item from A&AI named-query response
294 * @param vnfItem vnf item from A&AI named-query response
295 * @param vnfServiceItem vnf service item from A&AI named-query response
296 * @param vfModuleItem vf module item from A&AI named-query response
297 * @return SO delete vf-module request
299 private SoRequest constructDeleteRequest(AaiNqInventoryResponseItem tenantItem, AaiNqInventoryResponseItem
300 vnfItem, AaiNqInventoryResponseItem vnfServiceItem, AaiNqInventoryResponseItem vfModuleItem) {
301 SoRequest request = new SoRequest();
302 request.setOperationType(SoOperationType.DELETE_VF_MODULE);
303 request.setRequestDetails(new SoRequestDetails());
304 request.getRequestDetails().setRelatedInstanceList(null);
305 request.getRequestDetails().setConfigurationParameters(null);
307 // cloudConfiguration
308 request.getRequestDetails().setCloudConfiguration(constructCloudConfiguration(tenantItem));
310 request.getRequestDetails().setModelInfo(constructVfModuleModelInfo(vfModuleItem));
312 request.getRequestDetails().setRequestInfo(constructRequestInfo());
313 // Save the instance IDs for the VNF, service and vfModule to static fields
314 preserveInstanceIds(vnfItem.getGenericVnf().getVnfId(), vnfServiceItem.getServiceInstance()
315 .getServiceInstanceId(), vfModuleItem.getVfModule().getVfModuleId());
317 if (logger.isDebugEnabled()) {
318 logger.debug("Constructed SO request: {}", Serialization.gsonPretty.toJson(request));
324 * Construct requestInfo for the SO requestDetails.
326 * @return SO request information
328 private SoRequestInfo constructRequestInfo() {
329 SoRequestInfo soRequestInfo = new SoRequestInfo();
330 soRequestInfo.setSource("POLICY");
331 soRequestInfo.setSuppressRollback(false);
332 soRequestInfo.setRequestorId("policy");
333 return soRequestInfo;
337 * Construct modelInfo of the vfModule for the SO requestDetails.
339 * @param vfModuleItem vf module item from A&AI named-query response
340 * @return SO Model info for the vfModule
342 private SoModelInfo constructVfModuleModelInfo(AaiNqInventoryResponseItem vfModuleItem) {
343 SoModelInfo soModelInfo = new SoModelInfo();
344 soModelInfo.setModelType("vfModule");
345 soModelInfo.setModelInvariantId(vfModuleItem.getVfModule().getModelInvariantId());
346 soModelInfo.setModelCustomizationId(vfModuleItem.getVfModule().getModelCustomizationId());
348 for (AaiNqExtraProperty prop : vfModuleItem.getExtraProperties().getExtraProperty()) {
349 if (prop.getPropertyName().equals(MODEL_NAME_PROPERTY_KEY)) {
350 soModelInfo.setModelName(prop.getPropertyValue());
351 } else if (prop.getPropertyName().equals(MODEL_VERSION_PROPERTY_KEY)) {
352 soModelInfo.setModelVersion(prop.getPropertyValue());
359 * Construct cloudConfiguration for the SO requestDetails.
361 * @param tenantItem tenant item from A&AI named-query response
362 * @return SO cloud configuration
364 private SoCloudConfiguration constructCloudConfiguration(AaiNqInventoryResponseItem tenantItem) {
365 SoCloudConfiguration cloudConfiguration = new SoCloudConfiguration();
366 cloudConfiguration.setTenantId(tenantItem.getTenant().getTenantId());
367 cloudConfiguration.setLcpCloudRegionId(tenantItem.getItems().getInventoryResponseItems().get(0)
368 .getCloudRegion().getCloudRegionId());
369 return cloudConfiguration;
373 * This method is needed to get the serviceInstanceId and vnfInstanceId which is used
374 * in the asyncSORestCall.
376 * @param requestId the request Id
377 * @param wm the working memory
378 * @param request the request
380 public static void sendRequest(String requestId, WorkingMemory wm, Object request) {
381 SoManager soManager = new SoManager();
382 soManager.asyncSoRestCall(requestId, wm, lastServiceItemServiceInstanceId, lastVNFItemVnfId,
383 lastVfModuleItemVfModuleInstanceId, (SoRequest) request);
387 * Find the base or non base VF module item in an AAI response.
388 * If there is more than one item, then the <i>last</i> item is returned
390 * @param aaiResponseWrapper the AAI response containing the VF modules
391 * @param baseFlag true if we are searching for the base, false if we are searching
393 * @return the base or non base VF module item or null if the module was not found
395 private AaiNqInventoryResponseItem findVfModule(AaiNqResponseWrapper aaiResponseWrapper, boolean baseFlag) {
396 List<AaiNqInventoryResponseItem> lst = aaiResponseWrapper.getVfModuleItems(baseFlag);
397 return (lst.isEmpty() ? null : lst.get(lst.size() - 1));
401 * Builds the request parameters from the policy payload.
403 * @param policy the policy
404 * @param request request into which to stick the request parameters
406 private void buildRequestParameters(Policy policy, SoRequestDetails request) {
407 // assume null until proven otherwise
408 request.setRequestParameters(null);
410 if (policy.getPayload() == null) {
414 String json = policy.getPayload().get(REQ_PARAM_NM);
419 request.setRequestParameters(Serialization.gsonPretty.fromJson(json, SoRequestParameters.class));
423 * Builds the configuration parameters from the policy payload.
425 * @param policy the policy
426 * @param request request into which to stick the configuration parameters
428 private void buildConfigurationParameters(Policy policy, SoRequestDetails request) {
429 // assume null until proven otherwise
430 request.setConfigurationParameters(null);
432 if (policy.getPayload() == null) {
436 String json = policy.getPayload().get(CONFIG_PARAM_NM);
441 request.setConfigurationParameters(Serialization.gsonPretty.fromJson(json, CONFIG_TYPE));
445 * This method is called to remember the last service instance ID, VNF Item VNF ID and vf module ID.
446 * Note these fields are static, beware for multithreaded deployments
448 * @param vnfInstanceId update the last VNF instance ID to this value
449 * @param serviceInstanceId update the last service instance ID to this value
450 * @param vfModuleId update the vfModule instance ID to this value
452 private static void preserveInstanceIds(final String vnfInstanceId, final String serviceInstanceId,
453 final String vfModuleId) {
454 lastVNFItemVnfId = vnfInstanceId;
455 lastServiceItemServiceInstanceId = serviceInstanceId;
456 lastVfModuleItemVfModuleInstanceId = vfModuleId;