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