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