Fix Sonar bugs
[clamp.git] / src / main / java / org / onap / clamp / clds / client / req / OperationalPolicyReq.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP CLAMP
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                             reserved.
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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============================================
20  * ===================================================================
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  */
23
24 package org.onap.clamp.clds.client.req;
25
26 import com.att.eelf.configuration.EELFLogger;
27 import com.att.eelf.configuration.EELFLogger.Level;
28 import com.att.eelf.configuration.EELFManager;
29 import com.fasterxml.jackson.databind.JsonNode;
30 import com.fasterxml.jackson.databind.node.ObjectNode;
31
32 import java.io.UnsupportedEncodingException;
33 import java.net.URLEncoder;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39
40 import javax.ws.rs.BadRequestException;
41
42 import org.onap.clamp.clds.model.prop.Global;
43 import org.onap.clamp.clds.model.prop.ModelProperties;
44 import org.onap.clamp.clds.model.prop.PolicyChain;
45 import org.onap.clamp.clds.model.prop.PolicyItem;
46 import org.onap.clamp.clds.model.prop.Tca;
47 import org.onap.clamp.clds.model.refprop.RefProp;
48 import org.onap.policy.api.AttributeType;
49 import org.onap.policy.asdc.Resource;
50 import org.onap.policy.asdc.ResourceType;
51 import org.onap.policy.asdc.Service;
52 import org.onap.policy.controlloop.policy.OperationsAccumulateParams;
53 import org.onap.policy.controlloop.policy.Policy;
54 import org.onap.policy.controlloop.policy.PolicyResult;
55 import org.onap.policy.controlloop.policy.Target;
56 import org.onap.policy.controlloop.policy.TargetType;
57 import org.onap.policy.controlloop.policy.builder.BuilderException;
58 import org.onap.policy.controlloop.policy.builder.ControlLoopPolicyBuilder;
59 import org.onap.policy.controlloop.policy.builder.Message;
60 import org.onap.policy.controlloop.policy.builder.Results;
61
62 /**
63  * Construct an Operational Policy request given CLDS objects.
64  */
65 public class OperationalPolicyReq {
66     protected static final EELFLogger logger        = EELFManager.getInstance().getLogger(OperationalPolicyReq.class);
67     protected static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
68
69     /**
70      * Format Operational Policy attributes.
71      *
72      * @param refProp
73      * @param prop
74      * @return
75      * @throws BuilderException
76      * @throws UnsupportedEncodingException
77      */
78     public static Map<AttributeType, Map<String, String>> formatAttributes(RefProp refProp, ModelProperties prop,
79             String modelElementId, PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
80         Global global = prop.getGlobal();
81         prop.setCurrentModelElementId(modelElementId);
82         prop.setPolicyUniqueId(policyChain.getPolicyId());
83
84         String templateName = "";
85         String operationTopic = "";
86         String notificationTopic = "";
87         String controller = "";
88         Tca tca = prop.getTca();
89         if (tca.isFound()) {
90             if (!global.getActionSet().equalsIgnoreCase("enbRecipe")) {
91                 throw new BadRequestException(
92                         "Operation Policy validation problem: action set is not selected properly.");
93             }
94             templateName = refProp.getStringValue("op.eNodeB.templateName", global.getService());
95             operationTopic = refProp.getStringValue("op.eNodeB.operationTopic", global.getService());
96             notificationTopic = refProp.getStringValue("op.eNodeB.notificationTopic", global.getService());
97             controller = refProp.getStringValue("op.eNodeB.controller", global.getService());
98         } else {
99             if (!global.getActionSet().equalsIgnoreCase("vnfRecipe")) {
100                 throw new BadRequestException(
101                         "Operation Policy validation problem: Action set is not selected properly.");
102             }
103             templateName = refProp.getStringValue("op.templateName", global.getService());
104             operationTopic = refProp.getStringValue("op.operationTopic", global.getService());
105             notificationTopic = refProp.getStringValue("op.notificationTopic", global.getService());
106             controller = refProp.getStringValue("op.controller", global.getService());
107         }
108         String recipeTopic = refProp.getStringValue("op.recipeTopic", global.getService());
109
110         // ruleAttributes
111         Map<String, String> ruleAttributes = new HashMap<String, String>();
112
113         if (operationTopic == null || operationTopic.length() == 0) {
114             logger.info("templateName=" + templateName);
115             logger.info("recipeTopic=" + recipeTopic);
116             logger.info("notificationTopic=" + notificationTopic);
117
118             // if no operationTopic, then don't format yaml - use first policy
119             // from list
120             PolicyItem policyItem = policyChain.getPolicyItems().get(0);
121
122             ruleAttributes.put("templateName", templateName);
123             ruleAttributes.put("ClosedLoopControlName", prop.getControlNameAndPolicyUniqueId());
124             ruleAttributes.put("RecipeTopic", recipeTopic);
125             ruleAttributes.put("NotificationTopic", notificationTopic);
126
127             String recipe = policyItem.getRecipe();
128             String maxRetries = String.valueOf(policyItem.getMaxRetries());
129             String retryTimeLimit = String.valueOf(policyItem.getRetryTimeLimit());
130             logger.info("recipe=" + recipe);
131             logger.info("maxRetries=" + maxRetries);
132             logger.info("retryTimeLimit=" + retryTimeLimit);
133             ruleAttributes.put("Recipe", recipe);
134             ruleAttributes.put("MaxRetries", maxRetries);
135             ruleAttributes.put("RetryTimeLimit", retryTimeLimit);
136         } else {
137             logger.info("templateName=" + templateName);
138             logger.info("operationTopic=" + operationTopic);
139             logger.info("notificationTopic=" + notificationTopic);
140
141             // format yaml
142             String yaml = tca.isFound() ? formateNodeBYaml(refProp, prop, modelElementId, policyChain)
143                     : formatYaml(refProp, prop, modelElementId, policyChain);
144
145             ruleAttributes.put("templateName", templateName);
146             ruleAttributes.put("ClosedLoopControlName", prop.getControlNameAndPolicyUniqueId());
147             ruleAttributes.put("OperationTopic", operationTopic);
148             ruleAttributes.put("NotificationTopic", notificationTopic);
149
150             ruleAttributes.put("ControlLoopYaml", yaml);
151         }
152
153         // matchingAttributes
154         Map<String, String> matchingAttributes = new HashMap<String, String>();
155         matchingAttributes.put("controller", controller);
156
157         Map<AttributeType, Map<String, String>> attributes = new HashMap<AttributeType, Map<String, String>>();
158         attributes.put(AttributeType.RULE, ruleAttributes);
159         attributes.put(AttributeType.MATCHING, matchingAttributes);
160
161         return attributes;
162     }
163
164     /**
165      * Format Operational Policy yaml.
166      *
167      * @param refProp
168      * @param prop
169      * @return
170      * @throws BuilderException
171      * @throws UnsupportedEncodingException
172      */
173     private static String formatYaml(RefProp refProp, ModelProperties prop, String modelElementId,
174             PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
175
176         // get property objects
177         Global global = prop.getGlobal();
178         prop.setCurrentModelElementId(modelElementId);
179         prop.setPolicyUniqueId(policyChain.getPolicyId());
180
181         // convert values to SDC objects
182         Service service = new Service(global.getService());
183         Resource[] vfResources = convertToResource(global.getResourceVf(), ResourceType.VF);
184         Resource[] vfcResources = convertToResource(global.getResourceVfc(), ResourceType.VFC);
185
186         // create builder
187         ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
188                 policyChain.getTimeout(), service, vfResources);
189         builder.addResource(vfcResources);
190
191         // process each policy
192         HashMap<String, org.onap.policy.controlloop.policy.Policy> policyObjMap = new HashMap<String, org.onap.policy.controlloop.policy.Policy>();
193         List<PolicyItem> policyItemList = orderParentFirst(policyChain.getPolicyItems());
194         Target target = new Target();
195         target.setType(TargetType.VM);
196         for (int i = 0; i < policyItemList.size(); i++) {
197
198             org.onap.policy.controlloop.policy.Policy policyObj;
199             PolicyItem policyItem = policyItemList.get(i);
200             String policyName = policyItem.getRecipe() + " Policy";
201             if (i == 0) {
202                 String policyDescription = policyItem.getRecipe()
203                         + " Policy - the trigger (no parent) policy - created by CLDS";
204                 policyObj = builder.setTriggerPolicy(policyName, policyDescription,
205                         refProp.getStringValue("op.policy.appc"), target, policyItem.getRecipe(), null,
206                         policyItem.getMaxRetries(), policyItem.getRetryTimeLimit());
207             } else {
208                 org.onap.policy.controlloop.policy.Policy parentPolicyObj = policyObjMap
209                         .get(policyItem.getParentPolicy());
210                 String policyDescription = policyItem.getRecipe() + " Policy - triggered conditionally by "
211                         + parentPolicyObj.getName() + " - created by CLDS";
212                 policyObj = builder.setPolicyForPolicyResult(policyName, policyDescription,
213                         refProp.getStringValue("op.policy.appc"), target, policyItem.getRecipe(), null,
214                         policyItem.getMaxRetries(), policyItem.getRetryTimeLimit(), parentPolicyObj.getId(),
215                         convertToPolicyResult(policyItem.getParentPolicyConditions()));
216
217                 logger.info("policyObj.id=" + policyObj.getId() + "; parentPolicyObj.id=" + parentPolicyObj.getId());
218             }
219             policyObjMap.put(policyItem.getId(), policyObj);
220         }
221
222         //
223         // Build the specification
224         //
225         Results results = builder.buildSpecification();
226         if (results.isValid()) {
227             logger.info("results.getSpecification()=" + results.getSpecification());
228         } else {
229             // throw exception with error info
230             StringBuffer sb = new StringBuffer();
231             sb.append("Operation Policy validation problem: ControlLoopPolicyBuilder failed with following messages: ");
232             for (Message message : results.getMessages()) {
233                 sb.append(message.getMessage());
234                 sb.append("; ");
235             }
236             throw new BadRequestException(sb.toString());
237         }
238
239         String encodedYaml = URLEncoder.encode(results.getSpecification(), "UTF-8");
240
241         return encodedYaml;
242     }
243
244     /**
245      * Format Operational Policy yaml.
246      *
247      * @param refProp
248      * @param prop
249      * @return
250      * @throws BuilderException
251      * @throws UnsupportedEncodingException
252      */
253     private static String formateNodeBYaml(RefProp refProp, ModelProperties prop, String modelElementId,
254             PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
255
256         // get property objects
257         Global global = prop.getGlobal();
258         prop.setCurrentModelElementId(modelElementId);
259         prop.setPolicyUniqueId(policyChain.getPolicyId());
260
261         // convert values to SDC objects
262         Service service = new Service(global.getService());
263         Resource[] vfResources = convertToResource(global.getResourceVf(), ResourceType.VF);
264         Resource[] vfcResources = convertToResource(global.getResourceVfc(), ResourceType.VFC);
265
266         // create builder
267         ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
268                 policyChain.getTimeout(), service, vfResources);
269         builder.addResource(vfcResources);
270
271         // process each policy
272         HashMap<String, Policy> policyObjMap = new HashMap<String, Policy>();
273         List<PolicyItem> policyItemList = addAOTSActorRecipe(refProp, global.getService(),
274                 policyChain.getPolicyItems());
275         Target target = new Target();
276         target.setType(TargetType.VM);
277         Policy lastPolicyObj = new Policy();
278         for (int i = 0; i < policyItemList.size(); i++) {
279             org.onap.policy.controlloop.policy.Policy policyObj;
280             PolicyItem policyItem = policyItemList.get(i);
281             String policyName = policyItem.getRecipe() + " Policy";
282             if (i == 0) {
283                 // To set up time window payload for trigger policy
284                 Map<String, String> payloadMap = new HashMap<String, String>();
285                 payloadMap.put("timeWindow", refProp.getStringValue("op.eNodeB.timeWindow"));
286                 String policyDescription = policyItem.getRecipe()
287                         + " Policy - the trigger (no parent) policy - created by CLDS";
288                 policyObj = builder.setTriggerPolicy(policyName, policyDescription, policyItem.getActor(), target,
289                         policyItem.getRecipe(), payloadMap, policyItem.getMaxRetries(), policyItem.getRetryTimeLimit());
290             } else {
291                 Policy parentPolicyObj = policyObjMap.get(policyItem.getParentPolicy());
292                 String policyDescription = policyItem.getRecipe() + " Policy - triggered conditionally by "
293                         + parentPolicyObj.getName() + " - created by CLDS";
294                 policyObj = builder.setPolicyForPolicyResult(policyName, policyDescription, policyItem.getActor(),
295                         target, policyItem.getRecipe(), null, policyItem.getMaxRetries(),
296                         policyItem.getRetryTimeLimit(), parentPolicyObj.getId(),
297                         convertToPolicyResult(policyItem.getParentPolicyConditions()));
298                 lastPolicyObj = policyObj;
299                 logger.info("policyObj.id=" + policyObj.getId() + "; parentPolicyObj.id=" + parentPolicyObj.getId());
300             }
301             policyObjMap.put(policyItem.getId(), policyObj);
302         }
303         // To set up operations accumulate params
304         OperationsAccumulateParams operationsAccumulateParams = new OperationsAccumulateParams();
305         operationsAccumulateParams.setLimit(Integer.valueOf(refProp.getStringValue("op.eNodeB.limit")));
306         operationsAccumulateParams.setPeriod(refProp.getStringValue("op.eNodeB.period"));
307         builder.addOperationsAccumulateParams(lastPolicyObj.getId(), operationsAccumulateParams);
308
309         //
310         // Build the specification
311         //
312         Results results = builder.buildSpecification();
313         if (results.isValid()) {
314             logger.info("results.getSpecification()=" + results.getSpecification());
315         } else {
316             // throw exception with error info
317             StringBuffer sb = new StringBuffer();
318             sb.append("Operation Policy validation problem: ControlLoopPolicyBuilder failed with following messages: ");
319             for (Message message : results.getMessages()) {
320                 sb.append(message.getMessage());
321                 sb.append("; ");
322             }
323             throw new BadRequestException(sb.toString());
324         }
325
326         String encodedYaml = URLEncoder.encode(results.getSpecification(), "UTF-8");
327
328         return encodedYaml;
329     }
330
331     /**
332      * Adding AOTS actor and other recipe for yaml
333      *
334      * @param inOrigList
335      * @return
336      */
337     private static List<PolicyItem> addAOTSActorRecipe(RefProp refProp, String service, List<PolicyItem> inOrigList) {
338         List<PolicyItem> outList = new ArrayList<PolicyItem>();
339         try {
340             PolicyItem policyItem = inOrigList.get(0);
341             ObjectNode rootNode = (ObjectNode) refProp.getJsonTemplate("op.eNodeB.recipe", service);
342             Iterator<JsonNode> itr = rootNode.get("eNodeBRecipes").elements();
343             while (itr.hasNext()) {
344                 PolicyItem policyItemObj = (PolicyItem) policyItem.clone();
345                 JsonNode recipeNode = itr.next();
346                 policyItemObj.setId(recipeNode.path("Recipe").asText());
347                 policyItemObj.setActor(recipeNode.path("Actor").asText());
348                 policyItemObj.setRecipe(recipeNode.path("Recipe").asText());
349                 policyItemObj.setParentPolicy(recipeNode.path("ParentPolicy").asText());
350                 if (!recipeNode.path("Retry").asText().isEmpty()) {
351                     policyItemObj.setMaxRetries(Integer.parseInt(recipeNode.path("Retry").asText()));
352                 }
353                 if (!recipeNode.path("TimeLimit").asText().isEmpty()) {
354                     policyItemObj.setRetryTimeLimit(Integer.parseInt(recipeNode.path("TimeLimit").asText()));
355                 }
356                 if (!recipeNode.path("PPConditions").asText().isEmpty()) {
357                     List<String> parentPolicyConditions = new ArrayList<String>();
358                     for (String ppCondition : recipeNode.path("PPConditions").asText().split(",")) {
359                         parentPolicyConditions.add(ppCondition);
360                     }
361                     policyItemObj.setParentPolicyConditions(parentPolicyConditions);
362                 }
363                 outList.add(policyItemObj);
364             }
365         } catch (Exception e) {
366             logger.log(Level.ERROR, "Error", e);
367         }
368         return outList;
369     }
370
371     /**
372      * Order list of PolicyItems so that parents come before any of their
373      * children
374      *
375      * @param inOrigList
376      * @return
377      */
378     private static List<PolicyItem> orderParentFirst(List<PolicyItem> inOrigList) {
379         List<PolicyItem> inList = new ArrayList<>();
380         inList.addAll(inOrigList);
381         List<PolicyItem> outList = new ArrayList<>();
382         int prevSize = 0;
383         while (!inList.isEmpty()) {
384             // check if there's a loop in the policy chain (the inList should
385             // have been reduced by at least one)
386             if (inList.size() == prevSize) {
387                 throw new BadRequestException("Operation Policy validation problem: loop in Operation Policy chain");
388             }
389             prevSize = inList.size();
390             // the following loop should remove at least one PolicyItem from the
391             // inList
392             Iterator<PolicyItem> inListItr = inList.iterator();
393             while (inListItr.hasNext()) {
394                 PolicyItem inItem = inListItr.next();
395                 // check for trigger policy (no parent)
396                 String parent = inItem.getParentPolicy();
397                 if (parent == null || parent.length() == 0) {
398                     if (outList.size() > 0) {
399                         throw new BadRequestException(
400                                 "Operation Policy validation problem: more than one trigger policy");
401                     } else {
402                         outList.add(inItem);
403                         inListItr.remove();
404                     }
405                 } else {
406                     // check if this PolicyItem's parent has been processed
407                     for (PolicyItem outItem : outList) {
408                         if (outItem.getId().equals(parent)) {
409                             // if the inItem parent is already in the outList,
410                             // then add inItem to outList and remove from inList
411                             outList.add(inItem);
412                             inListItr.remove();
413                             break;
414                         }
415                     }
416                 }
417             }
418         }
419         return outList;
420     }
421
422     /**
423      * Convert a List of resource strings to an array of Resource objects.
424      *
425      * @param stringList
426      * @param resourceType
427      * @return
428      */
429     private static Resource[] convertToResource(List<String> stringList, ResourceType resourceType) {
430         if (stringList == null || stringList.isEmpty()) {
431             return new Resource[0];
432         }
433         return stringList.stream().map(stringElem -> new Resource(stringElem, resourceType)).toArray(Resource[]::new);
434     }
435
436     /**
437      * Convert a List of policy result strings to an array of PolicyResult
438      * objects.
439      *
440      * @param prList
441      * @return
442      */
443     private static PolicyResult[] convertToPolicyResult(List<String> prList) {
444         if (prList == null || prList.isEmpty()) {
445             return new PolicyResult[0];
446         }
447         return prList.stream().map(stringElem -> PolicyResult.toResult(stringElem)).toArray(PolicyResult[]::new);
448     }
449
450 }