ccc13a557c72c797480b3b07b8a8aa00c2f25552
[policy/drools-applications.git] /
1 /*
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.policy.controlloop.actor.so;
22
23 import java.lang.reflect.Type;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Map;
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;
51
52 public class SOActorServiceProvider implements Actor {
53     private static final Logger logger = LoggerFactory.getLogger(SOActorServiceProvider.class);
54
55     // Strings for SO Actor
56     private static final String SO_ACTOR = "SO";
57
58     // Strings for targets
59     private static final String TARGET_VFC = "VFC";
60
61     // Strings for recipes
62     private static final String RECIPE_VF_MODULE_CREATE = "VF Module Create";
63
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();
67
68     // name of request parameters within policy payload
69     public static final String REQ_PARAM_NM = "requestParameters";
70
71     // name of configuration parameters within policy payload
72     public static final String CONFIG_PARAM_NM = "configurationParameters";
73
74     // used to decode configuration parameters via gson
75     public static Type CONFIG_TYPE = new TypeToken<List<Map<String, String>>>() {}.getType();
76
77     // Static variables required to hold the IDs of the last service item and VNF item.
78     // Note that in
79     // a multithreaded deployment this WILL break
80     private static String lastVNFItemVnfId;
81     private static String lastServiceItemServiceInstanceId;
82
83     @Override
84     public String actor() {
85         return SO_ACTOR;
86     }
87
88     @Override
89     public List<String> recipes() {
90         return ImmutableList.copyOf(recipes);
91     }
92
93     @Override
94     public List<String> recipeTargets(String recipe) {
95         return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList()));
96     }
97
98     @Override
99     public List<String> recipePayloads(String recipe) {
100         return Collections.emptyList();
101     }
102
103     /**
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.
106      *
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,
109      *        target, etc.
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
114      */
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";
120
121
122         if (!SO_ACTOR.equals(policy.getActor()) || !RECIPE_VF_MODULE_CREATE.equals(policy.getRecipe())) {
123             // for future extension
124             return null;
125         }
126
127         // Perform named query request and handle response
128         if (aaiResponseWrapper == null) {
129             return null;
130         }
131
132         AaiNqInventoryResponseItem vnfItem;
133         AaiNqInventoryResponseItem vnfServiceItem;
134         AaiNqInventoryResponseItem tenantItem;
135
136         // Extract the items we're interested in from the response
137         try {
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),
142                             e);
143             return null;
144         }
145
146         try {
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);
151             return null;
152         }
153
154         try {
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);
160             return null;
161         }
162
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);
166
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.");
170             return null;
171         }
172
173
174         // Construct SO Request
175         SORequest request = new SORequest();
176         //
177         // Do NOT send So the requestId, they do not support this field
178         //
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);
185
186         //
187         // cloudConfiguration
188         //
189         request.getRequestDetails().getCloudConfiguration().setTenantId(tenantItem.getTenant().getTenantId());
190         request.getRequestDetails().getCloudConfiguration().setLcpCloudRegionId(
191                         tenantItem.getItems().getInventoryResponseItems().get(0).getCloudRegion().getCloudRegionId());
192
193         //
194         // modelInfo
195         //
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());
202
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());
208             }
209         }
210
211         //
212         // requestInfo
213         //
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");
219
220         //
221         // relatedInstanceList
222         //
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());
228
229         // Volume Group Item
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");
235
236         // Service Item
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());
252             }
253         }
254
255         // VNF Item
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());
270             }
271         }
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());
277
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);
282
283         // Request Parameters
284         request.getRequestDetails().setRequestParameters(buildRequestParameters(policy));
285
286         // Configuration Parameters
287         request.getRequestDetails().setConfigurationParameters(buildConfigurationParameters(policy));
288
289         // Save the instance IDs for the VNF and service to static fields
290         preserveInstanceIds(vnfItem.getGenericVnf().getVnfId(),
291                         vnfServiceItem.getServiceInstance().getServiceInstanceId());
292
293         if (logger.isDebugEnabled()) {
294             logger.debug("SO request sent: {}", Serialization.gsonPretty.toJson(request));
295         }
296
297         return request;
298     }
299
300     /**
301      * This method is needed to get the serviceInstanceId and vnfInstanceId which is used
302      * in the asyncSORestCall.
303      *
304      * @param requestId the request Id
305      * @param wm the working memory
306      * @param request the request
307      */
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);
312     }
313
314     /**
315      * Find the base or non base VF module item in an AAI response.
316      *
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
319      *        for the non base
320      * @return the base or non base VF module item or null if the module was not found
321      */
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));
325     }
326
327     /**
328      * Builds the request parameters from the policy payload.
329      *
330      * @param policy the policy
331      * @return the request parameters, or {@code null} if the payload is {@code null}
332      */
333     private SORequestParameters buildRequestParameters(Policy policy) {
334         if (policy.getPayload() == null) {
335             return null;
336         }
337
338         String json = policy.getPayload().get(REQ_PARAM_NM);
339         if (json == null) {
340             return null;
341         }
342
343         return Serialization.gsonPretty.fromJson(json, SORequestParameters.class);
344     }
345
346     /**
347      * Builds the configuration parameters from the policy payload.
348      *
349      * @param policy the policy
350      * @return the configuration parameters, or {@code null} if the payload is
351      *         {@code null}
352      */
353     private List<Map<String, String>> buildConfigurationParameters(Policy policy) {
354         if (policy.getPayload() == null) {
355             return null;
356         }
357
358         String json = policy.getPayload().get(CONFIG_PARAM_NM);
359         if (json == null) {
360             return null;
361         }
362
363         return Serialization.gsonPretty.fromJson(json, CONFIG_TYPE);
364     }
365
366     /**
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
369      *
370      * @param vnfInstanceId update the last VNF instance ID to this value
371      * @param serviceInstanceId update the last service instance ID to this value
372      */
373     private static void preserveInstanceIds(final String vnfInstanceId, final String serviceInstanceId) {
374         lastVNFItemVnfId = vnfInstanceId;
375         lastServiceItemServiceInstanceId = serviceInstanceId;
376     }
377 }