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