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