4385ce272df1104a0628efdc576563f7af251103
[policy/drools-applications.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * SOActorServiceProvider
4  * ================================================================================
5  * Copyright (C) 2017 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.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.UUID;
28
29 import org.drools.core.WorkingMemory;
30 import org.onap.policy.aai.AAIManager;
31 import org.onap.policy.aai.AAINQInstanceFilters;
32 import org.onap.policy.aai.AAINQInventoryResponseItem;
33 import org.onap.policy.aai.AAINQNamedQuery;
34 import org.onap.policy.aai.AAINQQueryParameters;
35 import org.onap.policy.aai.AAINQRequest;
36 import org.onap.policy.aai.AAINQResponse;
37 import org.onap.policy.aai.AAINQResponseWrapper;
38 import org.onap.policy.controlloop.ControlLoopOperation;
39 import org.onap.policy.controlloop.VirtualControlLoopEvent;
40 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
41 import org.onap.policy.controlloop.policy.Policy;
42 import org.onap.policy.drools.system.PolicyEngine;
43 import org.onap.policy.rest.RESTManager;
44 import org.onap.policy.so.SOCloudConfiguration;
45 import org.onap.policy.so.SOManager;
46 import org.onap.policy.so.SOModelInfo;
47 import org.onap.policy.so.SORelatedInstance;
48 import org.onap.policy.so.SORelatedInstanceListElement;
49 import org.onap.policy.so.SORequest;
50 import org.onap.policy.so.SORequestDetails;
51 import org.onap.policy.so.SORequestInfo;
52 import org.onap.policy.so.SORequestParameters;
53 import org.onap.policy.so.util.Serialization;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 import com.google.common.collect.ImmutableList;
58 import com.google.common.collect.ImmutableMap;
59
60 public class SOActorServiceProvider implements Actor {
61         private static final Logger logger = LoggerFactory.getLogger(SOActorServiceProvider.class);
62
63         // Strings for SO Actor
64         private static final String SO_ACTOR  = "SO";
65
66         // Strings for targets
67         private static final String TARGET_VFC = "VFC";
68
69         // Strings for recipes
70         private static final String RECIPE_VF_MODULE_CREATE = "VF Module Create";
71
72         private static final ImmutableList<String> recipes = ImmutableList.of(RECIPE_VF_MODULE_CREATE);
73         private static final ImmutableMap<String, List<String>> targets = new ImmutableMap.Builder<String, List<String>>()
74                         .put(RECIPE_VF_MODULE_CREATE, ImmutableList.of(TARGET_VFC))
75                         .build();
76
77         // Static variables required to hold the IDs of the last service item and VNF item. Note that in a multithreaded deployment this WILL break
78         private static String lastVNFItemVnfId;
79         private static String lastServiceItemServiceInstanceId;
80
81         @Override
82         public String actor() {
83                 return SO_ACTOR;
84         }
85
86         @Override
87         public List<String> recipes() {
88                 return ImmutableList.copyOf(recipes);
89         }
90
91         @Override
92         public List<String> recipeTargets(String recipe) {
93                 return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList()));
94         }
95
96         @Override
97         public List<String> recipePayloads(String recipe) {
98                 return Collections.emptyList();
99         }
100
101         /**
102          * Constructs a SO request conforming to the lcm API.
103          * The actual request is constructed and then placed in a 
104          * wrapper object used to send through DMAAP.
105          * 
106          * @param onset
107          *            the event that is reporting the alert for policy
108          *            to perform an action        
109          * @param operation
110          *            the control loop operation specifying the actor,
111          *            operation, target, etc.  
112          * @param policy
113          *            the policy the was specified from the yaml generated
114          *            by CLAMP or through the Policy GUI/API                        
115          * @return a SO request conforming to the lcm API using the DMAAP wrapper
116          */
117         public SORequest constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy) {
118                 if (!SO_ACTOR.equals(policy.getActor()) || !RECIPE_VF_MODULE_CREATE.equals(policy.getRecipe())) {
119                         // for future extension
120                         return null;
121                 }
122
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
127                         return null;
128                 }
129
130                 AAINQInventoryResponseItem vnfItem;
131                 AAINQInventoryResponseItem vnfServiceItem;
132                 AAINQInventoryResponseItem tenantItem;
133
134                 // Extract the items we're interested in from the response
135                 try     {
136                         vnfItem = aaiResponseWrapper.getAainqresponse().getInventoryResponseItems().get(0).getItems().getInventoryResponseItems().get(0);
137                 }
138                 catch (Exception e) {
139                         logger.error("VNF Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
140                         return null;
141                 }
142
143                 try     {
144                         vnfServiceItem = vnfItem.getItems().getInventoryResponseItems().get(0);
145                 }
146                 catch (Exception e) {
147                         logger.error("VNF Service Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
148                         return null;
149                 }
150
151                 try     {
152                         tenantItem = aaiResponseWrapper.getAainqresponse().getInventoryResponseItems().get(0).getItems().getInventoryResponseItems().get(1);
153                 }
154                 catch (Exception e) {
155                         logger.error("Tenant Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiResponseWrapper), e);
156                         return null;
157                 }
158
159                 // Find the index for base vf module and non-base vf module
160                 int baseIndex = findIndex(vnfItem.getItems().getInventoryResponseItems(), true);
161                 int nonBaseIndex = findIndex(vnfItem.getItems().getInventoryResponseItems(), false);
162
163                 // Report the error if either base vf module or non-base vf module is not found
164                 if (baseIndex == -1 || nonBaseIndex == -1) {
165                         logger.error("Either base or non-base vf module is not found from AAI response.");
166                         return null;
167                 }
168
169                 // Construct SO Request
170                 SORequest request = new SORequest();
171                 request.setRequestId(onset.getRequestID());
172                 request.setRequestDetails(new SORequestDetails());
173                 request.getRequestDetails().setModelInfo(new SOModelInfo());
174                 request.getRequestDetails().setCloudConfiguration(new SOCloudConfiguration());
175                 request.getRequestDetails().setRequestInfo(new SORequestInfo());
176                 request.getRequestDetails().setRequestParameters(new SORequestParameters());
177                 request.getRequestDetails().getRequestParameters().setUserParams(null);
178
179                 //
180                 // cloudConfiguration
181                 //
182                 request.getRequestDetails().getCloudConfiguration().setTenantId(tenantItem.getTenant().getTenantId());
183                 request.getRequestDetails().getCloudConfiguration().setLcpCloudRegionId(tenantItem.getItems().getInventoryResponseItems().get(0).getCloudRegion().getCloudRegionId());
184
185                 //
186                 // modelInfo
187                 //
188                 AAINQInventoryResponseItem vfModuleItem = vnfItem.getItems().getInventoryResponseItems().get(nonBaseIndex);
189
190                 request.getRequestDetails().getModelInfo().setModelType("vfModule");
191                 request.getRequestDetails().getModelInfo().setModelInvariantId(vfModuleItem.getVfModule().getModelInvariantId());
192                 request.getRequestDetails().getModelInfo().setModelVersionId(vfModuleItem.getVfModule().getModelVersionId());
193                 request.getRequestDetails().getModelInfo().setModelName(vfModuleItem.getExtraProperties().getExtraProperty().get(1).getPropertyValue());
194                 request.getRequestDetails().getModelInfo().setModelVersion(vfModuleItem.getExtraProperties().getExtraProperty().get(4).getPropertyValue());
195
196                 //
197                 // requestInfo
198                 //
199                 String instanceName = vnfItem.getItems().getInventoryResponseItems().get(baseIndex).getVfModule()
200                                 .getVfModuleName().replace("Vfmodule", "vDNS");
201                 int numberOfNonBaseModules = findNonBaseModules(vnfItem.getItems().getInventoryResponseItems());
202                 // Code to create unique VF Module names across the invocations.
203                 if (numberOfNonBaseModules == 1) {
204                         int instanceNumber = 1;
205                         instanceName = instanceName.concat("-").concat(String.valueOf(instanceNumber));
206                         request.getRequestDetails().getRequestInfo().setInstanceName(instanceName);
207                 } else if (numberOfNonBaseModules > 1) {
208                         int instanceNumber = numberOfNonBaseModules + 1;
209                         instanceName = instanceName.concat("-").concat(String.valueOf(instanceNumber));
210                         request.getRequestDetails().getRequestInfo().setInstanceName(instanceName);
211                 } else {
212                         request.getRequestDetails().getRequestInfo().setInstanceName(vnfItem.getItems().getInventoryResponseItems()
213                                         .get(baseIndex).getVfModule().getVfModuleName().replace("Vfmodule", "vDNS"));
214                 }
215                 request.getRequestDetails().getRequestInfo().setSource("POLICY");
216                 request.getRequestDetails().getRequestInfo().setSuppressRollback(false);
217                 request.getRequestDetails().getRequestInfo().setRequestorId("policy");
218
219                 //
220                 // relatedInstanceList
221                 //
222                 SORelatedInstanceListElement relatedInstanceListElement1 = new SORelatedInstanceListElement();
223                 SORelatedInstanceListElement relatedInstanceListElement2 = new SORelatedInstanceListElement();
224                 relatedInstanceListElement1.setRelatedInstance(new SORelatedInstance());
225                 relatedInstanceListElement2.setRelatedInstance(new SORelatedInstance());
226
227                 // Service Item
228                 relatedInstanceListElement1.getRelatedInstance().setInstanceId(vnfServiceItem.getServiceInstance().getServiceInstanceID());
229                 relatedInstanceListElement1.getRelatedInstance().setModelInfo(new SOModelInfo());
230                 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelType("service");
231                 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelInvariantId(vnfServiceItem.getServiceInstance().getModelInvariantId());
232                 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelVersionId(vnfServiceItem.getServiceInstance().getModelVersionId());
233                 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelName(vnfServiceItem.getExtraProperties().getExtraProperty().get(1).getPropertyValue());
234                 relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelVersion(vnfServiceItem.getExtraProperties().getExtraProperty().get(4).getPropertyValue());
235
236                 // VNF Item
237                 relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getGenericVNF().getVnfID());
238                 relatedInstanceListElement2.getRelatedInstance().setModelInfo(new SOModelInfo());
239                 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelType("vnf");
240                 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelInvariantId(vnfItem.getGenericVNF().getModelInvariantId());
241                 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersionId(vnfItem.getExtraProperties().getExtraProperty().get(0).getPropertyValue());
242                 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelName(vnfItem.getExtraProperties().getExtraProperty().get(1).getPropertyValue());
243                 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersion(vnfItem.getExtraProperties().getExtraProperty().get(4).getPropertyValue());
244                 relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelCustomizationName(vnfItem.getGenericVNF().getVnfType().substring(vnfItem.getGenericVNF().getVnfType().lastIndexOf('/') + 1));
245
246                 // Insert the Service Item and VNF Item 
247                 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement1);
248                 request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement2);
249
250                 // Save the instance IDs for the VNF and service to static fields
251                 preserveInstanceIDs(vnfItem.getGenericVNF().getVnfID(), vnfServiceItem.getServiceInstance().getServiceInstanceID());
252
253                 if (logger.isDebugEnabled()) {
254                         logger.debug("SO request sent: {}", Serialization.gsonPretty.toJson(request));
255                 }
256
257                 return request;
258         }
259
260         /**
261          * This method is needed to get the serviceInstanceId and vnfInstanceId which is used
262          * in the asyncSORestCall 
263          * 
264          * @param wm
265          * @param request
266          */
267         public static void sendRequest(String requestID, WorkingMemory wm, Object request) {
268                 SOManager soManager = new SOManager();
269                 soManager.asyncSORestCall(requestID, wm, lastServiceItemServiceInstanceId, lastVNFItemVnfId, (SORequest)request);
270         }
271
272         /**
273          * Constructs and sends an AAI vserver Named Query
274          * 
275          * @param onset
276          * @returns the response to the AAI Named Query
277          */
278         private AAINQResponseWrapper performAaiNamedQueryRequest(VirtualControlLoopEvent onset) {
279
280                 // create AAI named-query request with UUID started with ""
281                 AAINQRequest aainqrequest = new AAINQRequest();
282                 AAINQQueryParameters aainqqueryparam = new AAINQQueryParameters();
283                 AAINQNamedQuery aainqnamedquery = new AAINQNamedQuery();
284                 AAINQInstanceFilters aainqinstancefilter = new AAINQInstanceFilters();
285
286                 // queryParameters
287                 aainqnamedquery.setNamedQueryUUID(UUID.fromString("4ff56a54-9e3f-46b7-a337-07a1d3c6b469")); // UUID.fromString($params.getAaiNamedQueryUUID()) TO DO: AaiNamedQueryUUID 
288                 aainqqueryparam.setNamedQuery(aainqnamedquery);
289                 aainqrequest.setQueryParameters(aainqqueryparam);
290                 //
291                 // instanceFilters
292                 //
293                 Map<String, Map<String, String>> aainqinstancefiltermap = new HashMap<>();
294                 Map<String, String> aainqinstancefiltermapitem = new HashMap<>();
295                 aainqinstancefiltermapitem.put("vserver-name", onset.getAAI().get("vserver.vserver-name")); // TO DO: get vserver.vname from dcae onset.AAI.get("vserver.vserver-name")
296                 aainqinstancefiltermap.put("vserver", aainqinstancefiltermapitem);
297                 aainqinstancefilter.getInstanceFilter().add(aainqinstancefiltermap);
298                 aainqrequest.setInstanceFilters(aainqinstancefilter);
299
300                 if (logger.isDebugEnabled()) {
301                         logger.debug("AAI Request sent: {}", Serialization.gsonPretty.toJson(aainqrequest));
302                 }
303
304                 AAINQResponse aainqresponse = new AAIManager(new RESTManager()).postQuery(
305                                 getPEManagerEnvProperty("aai.url"),
306                                 getPEManagerEnvProperty("aai.username"),
307                                 getPEManagerEnvProperty("aai.password"),
308                                 aainqrequest, onset.getRequestID());
309
310                 // Check AAI response
311                 if (aainqresponse == null) {
312                         logger.warn("No response received from AAI for request {}", aainqrequest);
313                         return null;
314                 }
315
316                 // Create AAINQResponseWrapper
317                 AAINQResponseWrapper aainqResponseWrapper = new AAINQResponseWrapper(onset.getRequestID(), aainqresponse);
318
319                 if (logger.isDebugEnabled()) {
320                         logger.debug("AAI Named Query Response: ");
321                         logger.debug(Serialization.gsonPretty.toJson(aainqResponseWrapper.getAainqresponse()));
322                 }
323
324                 return aainqResponseWrapper;
325         }
326
327         /**
328          * Find the base index or non base index in a list of inventory response items
329          * @param inventoryResponseItems
330          * @param baseIndexFlag true if we are searching for the base index, false if we are searching for hte non base index
331          * @return the base or non base index or -1 if the index was not found
332          */
333         private int findIndex(List<AAINQInventoryResponseItem> inventoryResponseItems, boolean baseIndexFlag) {
334                 for (AAINQInventoryResponseItem invenoryResponseItem : inventoryResponseItems) {
335                         if (invenoryResponseItem.getVfModule() != null && baseIndexFlag == invenoryResponseItem.getVfModule().getIsBaseVfModule()) {
336                                 return inventoryResponseItems.indexOf(invenoryResponseItem);
337                         }
338                 }
339
340                 return -1;
341         }
342         
343         /**
344          * Find the number of non base modules present in API response object.
345          * 
346          * @param inventoryResponseItems
347          * @return number of non base index modules
348          */
349
350         private int findNonBaseModules(List<AAINQInventoryResponseItem> inventoryResponseItems) {
351                 int nonBaseModuleCount = 0;
352                 for (AAINQInventoryResponseItem invenoryResponseItem : inventoryResponseItems) {
353                         if (invenoryResponseItem.getVfModule() != null
354                                         && (!invenoryResponseItem.getVfModule().getIsBaseVfModule())) {
355                                 nonBaseModuleCount++;
356                         }
357                 }
358                 return nonBaseModuleCount;
359         }
360
361         /**
362          * This method is called to remember the last service instance ID and VNF Item VNF ID. Note these fields are static, beware for multithreaded deployments
363          * @param vnfInstanceID update the last VNF instance ID to this value
364          * @param serviceInstanceID update the last service instance ID to this value
365          */
366         private static void preserveInstanceIDs(final String vnfInstanceID, final String serviceInstanceID) {
367                 lastVNFItemVnfId = vnfInstanceID;
368                 lastServiceItemServiceInstanceId = serviceInstanceID;
369         }
370
371         /**
372          * This method reads and validates environmental properties coming from the policy engine. Null properties cause
373          * an {@link IllegalArgumentException} runtime exception to be thrown 
374          * @param string the name of the parameter to retrieve
375          * @return the property value
376          */
377         private static String getPEManagerEnvProperty(String enginePropertyName) {
378                 String enginePropertyValue = PolicyEngine.manager.getEnvironmentProperty(enginePropertyName);
379                 if (enginePropertyValue == null) {
380                         throw new IllegalArgumentException("The value of policy engine manager environment property \"" + enginePropertyName + "\" may not be null");
381                 }
382                 return enginePropertyValue;
383         }
384 }