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