Remove ECOMP in headers
[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  * 
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.EELFManager;
28
29 import java.io.UnsupportedEncodingException;
30 import java.net.URLEncoder;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36
37 import javax.ws.rs.BadRequestException;
38
39 import org.onap.clamp.clds.config.ClampProperties;
40 import org.onap.clamp.clds.model.properties.Global;
41 import org.onap.clamp.clds.model.properties.ModelProperties;
42 import org.onap.clamp.clds.model.properties.PolicyChain;
43 import org.onap.clamp.clds.model.properties.PolicyItem;
44 import org.onap.policy.api.AttributeType;
45 import org.onap.policy.controlloop.policy.Policy;
46 import org.onap.policy.controlloop.policy.PolicyResult;
47 import org.onap.policy.controlloop.policy.Target;
48 import org.onap.policy.controlloop.policy.TargetType;
49 import org.onap.policy.controlloop.policy.builder.BuilderException;
50 import org.onap.policy.controlloop.policy.builder.ControlLoopPolicyBuilder;
51 import org.onap.policy.controlloop.policy.builder.Message;
52 import org.onap.policy.controlloop.policy.builder.Results;
53 import org.onap.policy.sdc.Resource;
54 import org.onap.policy.sdc.ResourceType;
55 import org.onap.policy.sdc.Service;
56
57 /**
58  * Construct an Operational Policy request given CLDS objects.
59  */
60 public class OperationalPolicyReq {
61
62     private static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicyReq.class);
63
64     protected OperationalPolicyReq() {
65     }
66
67     /**
68      * Format Operational Policy attributes.
69      *
70      * @param refProp
71      * @param prop
72      * @param modelElementId
73      * @param policyChain
74      * @return
75      * @throws BuilderException
76      * @throws UnsupportedEncodingException
77      */
78     public static Map<AttributeType, Map<String, String>> formatAttributes(ClampProperties refProp,
79             ModelProperties prop, String modelElementId, PolicyChain policyChain)
80             throws BuilderException, UnsupportedEncodingException {
81         Global global = prop.getGlobal();
82         prop.setCurrentModelElementId(modelElementId);
83         prop.setPolicyUniqueId(policyChain.getPolicyId());
84         String templateName = refProp.getStringValue("op.templateName", global.getService());
85         String operationTopic = refProp.getStringValue("op.operationTopic", global.getService());
86         String notificationTopic = refProp.getStringValue("op.notificationTopic", global.getService());
87         String controller = refProp.getStringValue("op.controller", global.getService());
88         String recipeTopic = refProp.getStringValue("op.recipeTopic", global.getService());
89         // ruleAttributes
90         logger.info("templateName=" + templateName);
91         logger.info("notificationTopic=" + notificationTopic);
92         Map<String, String> ruleAttributes = new HashMap<>();
93         ruleAttributes.put("templateName", templateName);
94         ruleAttributes.put("ClosedLoopControlName", prop.getControlNameAndPolicyUniqueId());
95         ruleAttributes.put("NotificationTopic", notificationTopic);
96         if (operationTopic == null || operationTopic.isEmpty()) {
97             logger.info("recipeTopic=" + recipeTopic);
98             // if no operationTopic, then don't format yaml - use first policy
99             // from list
100             PolicyItem policyItem = policyChain.getPolicyItems().get(0);
101             ruleAttributes.put("RecipeTopic", recipeTopic);
102             String recipe = policyItem.getRecipe();
103             String maxRetries = String.valueOf(policyItem.getMaxRetries());
104             String retryTimeLimit = String.valueOf(policyItem.getRetryTimeLimit());
105             String targetResourceId = String.valueOf(policyItem.getTargetResourceId());
106             logger.info("recipe=" + recipe);
107             logger.info("maxRetries=" + maxRetries);
108             logger.info("retryTimeLimit=" + retryTimeLimit);
109             logger.info("targetResourceId=" + targetResourceId);
110             ruleAttributes.put("Recipe", recipe);
111             ruleAttributes.put("MaxRetries", maxRetries);
112             ruleAttributes.put("RetryTimeLimit", retryTimeLimit);
113             ruleAttributes.put("ResourceId", targetResourceId);
114         } else {
115             logger.info("operationTopic=" + operationTopic);
116             // format yaml
117             String yaml = formatYaml(refProp, prop, modelElementId, policyChain);
118             ruleAttributes.put("OperationTopic", operationTopic);
119             ruleAttributes.put("ControlLoopYaml", yaml);
120         }
121         // matchingAttributes
122         Map<String, String> matchingAttributes = new HashMap<>();
123         matchingAttributes.put("controller", controller);
124         Map<AttributeType, Map<String, String>> attributes = new HashMap<>();
125         attributes.put(AttributeType.RULE, ruleAttributes);
126         attributes.put(AttributeType.MATCHING, matchingAttributes);
127         return attributes;
128     }
129
130     /**
131      * Format Operational OpenLoop Policy yaml.
132      * 
133      * @param refProp
134      * @param prop
135      * @param modelElementId
136      * @param policyChain
137      * @return
138      * @throws BuilderException
139      * @throws UnsupportedEncodingException
140      */
141     protected static String formatOpenLoopYaml(ClampProperties refProp, ModelProperties prop, String modelElementId,
142             PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
143         // get property objects
144         Global global = prop.getGlobal();
145         prop.setCurrentModelElementId(modelElementId);
146         prop.setPolicyUniqueId(policyChain.getPolicyId());
147         // convert values to SDC objects
148         Service service = new Service(global.getService());
149         Resource[] vfResources = convertToResource(global.getResourceVf(), ResourceType.VF);
150         // create builder
151         ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
152                 policyChain.getTimeout(), service, vfResources);
153         // builder.setTriggerPolicy(refProp.getStringValue("op.openloop.policy"));
154         // Build the specification
155         Results results = builder.buildSpecification();
156         validate(results);
157         return URLEncoder.encode(results.getSpecification(), "UTF-8");
158     }
159
160     /**
161      * Format Operational Policy yaml.
162      *
163      * @param refProp
164      * @param prop
165      * @param modelElementId
166      * @param policyChain
167      * @return
168      * @throws BuilderException
169      * @throws UnsupportedEncodingException
170      */
171     protected static String formatYaml(ClampProperties refProp, ModelProperties prop, String modelElementId,
172             PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
173         // get property objects
174         Global global = prop.getGlobal();
175         prop.setCurrentModelElementId(modelElementId);
176         prop.setPolicyUniqueId(policyChain.getPolicyId());
177         // convert values to SDC objects
178         Service service = new Service(global.getService());
179         Resource[] vfResources = convertToResource(global.getResourceVf(), ResourceType.VF);
180         Resource[] vfcResources = convertToResource(global.getResourceVfc(), ResourceType.VFC);
181         // create builder
182         ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
183                 policyChain.getTimeout(), service, vfResources);
184         builder.addResource(vfcResources);
185         // process each policy
186         Map<String, Policy> policyObjMap = new HashMap<>();
187         List<PolicyItem> policyItemList = orderParentFirst(policyChain.getPolicyItems());
188         for (PolicyItem policyItem : policyItemList) {
189             String policyName = policyItem.getRecipe() + " Policy";
190             Target target = new Target();
191             target.setType(TargetType.VM);
192             target.setResourceID(policyItem.getTargetResourceId());
193             Policy policyObj;
194             if (policyItemList.indexOf(policyItem) == 0) {
195                 String policyDescription = policyItem.getRecipe()
196                         + " Policy - the trigger (no parent) policy - created by CLDS";
197                 policyObj = builder.setTriggerPolicy(policyName, policyDescription,
198                         refProp.getStringValue("op.policy.appc"), target, policyItem.getRecipe(), null,
199                         policyItem.getMaxRetries(), policyItem.getRetryTimeLimit());
200             } else {
201                 Policy parentPolicyObj = policyObjMap.get(policyItem.getParentPolicy());
202                 String policyDescription = policyItem.getRecipe() + " Policy - triggered conditionally by "
203                         + parentPolicyObj.getName() + " - created by CLDS";
204                 policyObj = builder.setPolicyForPolicyResult(policyName, policyDescription,
205                         refProp.getStringValue("op.policy.appc"), target, policyItem.getRecipe(), null,
206                         policyItem.getMaxRetries(), policyItem.getRetryTimeLimit(), parentPolicyObj.getId(),
207                         convertToPolicyResult(policyItem.getParentPolicyConditions()));
208                 logger.info("policyObj.id=" + policyObj.getId() + "; parentPolicyObj.id=" + parentPolicyObj.getId());
209             }
210             policyObjMap.put(policyItem.getId(), policyObj);
211         }
212         // Build the specification
213         Results results = builder.buildSpecification();
214         validate(results);
215         return URLEncoder.encode(results.getSpecification(), "UTF-8");
216     }
217
218     private static void validate(Results results) {
219         if (results.isValid()) {
220             logger.info("results.getSpecification()=" + results.getSpecification());
221         } else {
222             // throw exception with error info
223             StringBuilder sb = new StringBuilder();
224             sb.append("Operation Policy validation problem: ControlLoopPolicyBuilder failed with following messages: ");
225             for (Message message : results.getMessages()) {
226                 sb.append(message.getMessage());
227                 sb.append("; ");
228             }
229             throw new BadRequestException(sb.toString());
230         }
231     }
232
233     /**
234      * Order list of PolicyItems so that parents come before any of their
235      * children
236      *
237      * @param inOrigList
238      * @return
239      */
240     private static List<PolicyItem> orderParentFirst(List<PolicyItem> inOrigList) {
241         List<PolicyItem> inList = new ArrayList<>();
242         inList.addAll(inOrigList);
243         List<PolicyItem> outList = new ArrayList<>();
244         int prevSize = 0;
245         while (!inList.isEmpty()) {
246             // check if there's a loop in the policy chain (the inList should
247             // have been reduced by at least one)
248             if (inList.size() == prevSize) {
249                 throw new BadRequestException("Operation Policy validation problem: loop in Operation Policy chain");
250             }
251             prevSize = inList.size();
252             // the following loop should remove at least one PolicyItem from the
253             // inList
254             Iterator<PolicyItem> inListItr = inList.iterator();
255             while (inListItr.hasNext()) {
256                 PolicyItem inItem = inListItr.next();
257                 // check for trigger policy (no parent)
258                 String parent = inItem.getParentPolicy();
259                 if (parent == null || parent.length() == 0) {
260                     if (!outList.isEmpty()) {
261                         throw new BadRequestException(
262                                 "Operation Policy validation problem: more than one trigger policy");
263                     } else {
264                         outList.add(inItem);
265                         inListItr.remove();
266                     }
267                 } else {
268                     // check if this PolicyItem's parent has been processed
269                     for (PolicyItem outItem : outList) {
270                         if (outItem.getId().equals(parent)) {
271                             // if the inItem parent is already in the outList,
272                             // then add inItem to outList and remove from inList
273                             outList.add(inItem);
274                             inListItr.remove();
275                             break;
276                         }
277                     }
278                 }
279             }
280         }
281         return outList;
282     }
283
284     /**
285      * Convert a List of resource strings to an array of Resource objects.
286      *
287      * @param stringList
288      * @param resourceType
289      * @return
290      */
291     private static Resource[] convertToResource(List<String> stringList, ResourceType resourceType) {
292         if (stringList == null || stringList.isEmpty()) {
293             return new Resource[0];
294         }
295         return stringList.stream().map(stringElem -> new Resource(stringElem, resourceType)).toArray(Resource[]::new);
296     }
297
298     /**
299      * Convert a List of policy result strings to an array of PolicyResult
300      * objects.
301      *
302      * @param prList
303      * @return
304      */
305     private static PolicyResult[] convertToPolicyResult(List<String> prList) {
306         if (prList == null || prList.isEmpty()) {
307             return new PolicyResult[0];
308         }
309         return prList.stream().map(stringElem -> PolicyResult.toResult(stringElem)).toArray(PolicyResult[]::new);
310     }
311 }