2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 package org.onap.clamp.clds.client.req;
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;
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;
40 import javax.ws.rs.BadRequestException;
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.asdc.Resource;
50 import org.onap.policy.asdc.ResourceType;
51 import org.onap.policy.asdc.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;
63 * Construct an Operational Policy request given CLDS objects.
65 public class OperationalPolicyReq {
66 protected static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicyReq.class);
67 protected static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
70 * Format Operational Policy attributes.
75 * @throws BuilderException
76 * @throws UnsupportedEncodingException
78 public static Map<AttributeType, Map<String, String>> formatAttributes(RefProp refProp, ModelProperties prop,
79 String modelElementId, PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
80 Global global = prop.getGlobal();
81 prop.setCurrentModelElementId(modelElementId);
82 prop.setPolicyUniqueId(policyChain.getPolicyId());
84 String templateName = "";
85 String operationTopic = "";
86 String notificationTopic = "";
87 String controller = "";
88 Tca tca = prop.getTca();
90 if (!global.getActionSet().equalsIgnoreCase("enbRecipe")) {
91 throw new BadRequestException(
92 "Operation Policy validation problem: action set is not selected properly.");
94 templateName = refProp.getStringValue("op.eNodeB.templateName", global.getService());
95 operationTopic = refProp.getStringValue("op.eNodeB.operationTopic", global.getService());
96 notificationTopic = refProp.getStringValue("op.eNodeB.notificationTopic", global.getService());
97 controller = refProp.getStringValue("op.eNodeB.controller", global.getService());
99 if (!global.getActionSet().equalsIgnoreCase("vnfRecipe")) {
100 throw new BadRequestException(
101 "Operation Policy validation problem: Action set is not selected properly.");
103 templateName = refProp.getStringValue("op.templateName", global.getService());
104 operationTopic = refProp.getStringValue("op.operationTopic", global.getService());
105 notificationTopic = refProp.getStringValue("op.notificationTopic", global.getService());
106 controller = refProp.getStringValue("op.controller", global.getService());
108 String recipeTopic = refProp.getStringValue("op.recipeTopic", global.getService());
111 Map<String, String> ruleAttributes = new HashMap<String, String>();
113 if (operationTopic == null || operationTopic.length() == 0) {
114 logger.info("templateName=" + templateName);
115 logger.info("recipeTopic=" + recipeTopic);
116 logger.info("notificationTopic=" + notificationTopic);
118 // if no operationTopic, then don't format yaml - use first policy
120 PolicyItem policyItem = policyChain.getPolicyItems().get(0);
122 ruleAttributes.put("templateName", templateName);
123 ruleAttributes.put("ClosedLoopControlName", prop.getControlNameAndPolicyUniqueId());
124 ruleAttributes.put("RecipeTopic", recipeTopic);
125 ruleAttributes.put("NotificationTopic", notificationTopic);
127 String recipe = policyItem.getRecipe();
128 String maxRetries = String.valueOf(policyItem.getMaxRetries());
129 String retryTimeLimit = String.valueOf(policyItem.getRetryTimeLimit());
130 logger.info("recipe=" + recipe);
131 logger.info("maxRetries=" + maxRetries);
132 logger.info("retryTimeLimit=" + retryTimeLimit);
133 ruleAttributes.put("Recipe", recipe);
134 ruleAttributes.put("MaxRetries", maxRetries);
135 ruleAttributes.put("RetryTimeLimit", retryTimeLimit);
137 logger.info("templateName=" + templateName);
138 logger.info("operationTopic=" + operationTopic);
139 logger.info("notificationTopic=" + notificationTopic);
142 String yaml = tca.isFound() ? formateNodeBYaml(refProp, prop, modelElementId, policyChain)
143 : formatYaml(refProp, prop, modelElementId, policyChain);
145 ruleAttributes.put("templateName", templateName);
146 ruleAttributes.put("ClosedLoopControlName", prop.getControlNameAndPolicyUniqueId());
147 ruleAttributes.put("OperationTopic", operationTopic);
148 ruleAttributes.put("NotificationTopic", notificationTopic);
150 ruleAttributes.put("ControlLoopYaml", yaml);
153 // matchingAttributes
154 Map<String, String> matchingAttributes = new HashMap<String, String>();
155 matchingAttributes.put("controller", controller);
157 Map<AttributeType, Map<String, String>> attributes = new HashMap<AttributeType, Map<String, String>>();
158 attributes.put(AttributeType.RULE, ruleAttributes);
159 attributes.put(AttributeType.MATCHING, matchingAttributes);
165 * Format Operational Policy yaml.
170 * @throws BuilderException
171 * @throws UnsupportedEncodingException
173 private static String formatYaml(RefProp refProp, ModelProperties prop, String modelElementId,
174 PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
176 // get property objects
177 Global global = prop.getGlobal();
178 prop.setCurrentModelElementId(modelElementId);
179 prop.setPolicyUniqueId(policyChain.getPolicyId());
181 // convert values to SDC objects
182 Service service = new Service(global.getService());
183 Resource[] vfResources = convertToResource(global.getResourceVf(), ResourceType.VF);
184 Resource[] vfcResources = convertToResource(global.getResourceVfc(), ResourceType.VFC);
187 ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
188 policyChain.getTimeout(), service, vfResources);
189 builder.addResource(vfcResources);
191 // process each policy
192 HashMap<String, org.onap.policy.controlloop.policy.Policy> policyObjMap = new HashMap<String, org.onap.policy.controlloop.policy.Policy>();
193 List<PolicyItem> policyItemList = orderParentFirst(policyChain.getPolicyItems());
194 Target target = new Target();
195 target.setType(TargetType.VM);
196 for (int i = 0; i < policyItemList.size(); i++) {
198 org.onap.policy.controlloop.policy.Policy policyObj;
199 PolicyItem policyItem = policyItemList.get(i);
200 String policyName = policyItem.getRecipe() + " Policy";
202 String policyDescription = policyItem.getRecipe()
203 + " Policy - the trigger (no parent) policy - created by CLDS";
204 policyObj = builder.setTriggerPolicy(policyName, policyDescription,
205 refProp.getStringValue("op.policy.appc"), target, policyItem.getRecipe(), null,
206 policyItem.getMaxRetries(), policyItem.getRetryTimeLimit());
208 org.onap.policy.controlloop.policy.Policy parentPolicyObj = policyObjMap
209 .get(policyItem.getParentPolicy());
210 String policyDescription = policyItem.getRecipe() + " Policy - triggered conditionally by "
211 + parentPolicyObj.getName() + " - created by CLDS";
212 policyObj = builder.setPolicyForPolicyResult(policyName, policyDescription,
213 refProp.getStringValue("op.policy.appc"), target, policyItem.getRecipe(), null,
214 policyItem.getMaxRetries(), policyItem.getRetryTimeLimit(), parentPolicyObj.getId(),
215 convertToPolicyResult(policyItem.getParentPolicyConditions()));
217 logger.info("policyObj.id=" + policyObj.getId() + "; parentPolicyObj.id=" + parentPolicyObj.getId());
219 policyObjMap.put(policyItem.getId(), policyObj);
223 // Build the specification
225 Results results = builder.buildSpecification();
226 if (results.isValid()) {
227 logger.info("results.getSpecification()=" + results.getSpecification());
229 // throw exception with error info
230 StringBuffer sb = new StringBuffer();
231 sb.append("Operation Policy validation problem: ControlLoopPolicyBuilder failed with following messages: ");
232 for (Message message : results.getMessages()) {
233 sb.append(message.getMessage());
236 throw new BadRequestException(sb.toString());
239 String encodedYaml = URLEncoder.encode(results.getSpecification(), "UTF-8");
245 * Format Operational Policy yaml.
250 * @throws BuilderException
251 * @throws UnsupportedEncodingException
253 private static String formateNodeBYaml(RefProp refProp, ModelProperties prop, String modelElementId,
254 PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
256 // get property objects
257 Global global = prop.getGlobal();
258 prop.setCurrentModelElementId(modelElementId);
259 prop.setPolicyUniqueId(policyChain.getPolicyId());
261 // convert values to SDC objects
262 Service service = new Service(global.getService());
263 Resource[] vfResources = convertToResource(global.getResourceVf(), ResourceType.VF);
264 Resource[] vfcResources = convertToResource(global.getResourceVfc(), ResourceType.VFC);
267 ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
268 policyChain.getTimeout(), service, vfResources);
269 builder.addResource(vfcResources);
271 // process each policy
272 HashMap<String, Policy> policyObjMap = new HashMap<String, Policy>();
273 List<PolicyItem> policyItemList = addAOTSActorRecipe(refProp, global.getService(),
274 policyChain.getPolicyItems());
275 Target target = new Target();
276 target.setType(TargetType.VM);
277 Policy lastPolicyObj = new Policy();
278 for (int i = 0; i < policyItemList.size(); i++) {
279 org.onap.policy.controlloop.policy.Policy policyObj;
280 PolicyItem policyItem = policyItemList.get(i);
281 String policyName = policyItem.getRecipe() + " Policy";
283 // To set up time window payload for trigger policy
284 Map<String, String> payloadMap = new HashMap<String, String>();
285 payloadMap.put("timeWindow", refProp.getStringValue("op.eNodeB.timeWindow"));
286 String policyDescription = policyItem.getRecipe()
287 + " Policy - the trigger (no parent) policy - created by CLDS";
288 policyObj = builder.setTriggerPolicy(policyName, policyDescription, policyItem.getActor(), target,
289 policyItem.getRecipe(), payloadMap, policyItem.getMaxRetries(), policyItem.getRetryTimeLimit());
291 Policy parentPolicyObj = policyObjMap.get(policyItem.getParentPolicy());
292 String policyDescription = policyItem.getRecipe() + " Policy - triggered conditionally by "
293 + parentPolicyObj.getName() + " - created by CLDS";
294 policyObj = builder.setPolicyForPolicyResult(policyName, policyDescription, policyItem.getActor(),
295 target, policyItem.getRecipe(), null, policyItem.getMaxRetries(),
296 policyItem.getRetryTimeLimit(), parentPolicyObj.getId(),
297 convertToPolicyResult(policyItem.getParentPolicyConditions()));
298 lastPolicyObj = policyObj;
299 logger.info("policyObj.id=" + policyObj.getId() + "; parentPolicyObj.id=" + parentPolicyObj.getId());
301 policyObjMap.put(policyItem.getId(), policyObj);
303 // To set up operations accumulate params
304 OperationsAccumulateParams operationsAccumulateParams = new OperationsAccumulateParams();
305 operationsAccumulateParams.setLimit(Integer.valueOf(refProp.getStringValue("op.eNodeB.limit")));
306 operationsAccumulateParams.setPeriod(refProp.getStringValue("op.eNodeB.period"));
307 builder.addOperationsAccumulateParams(lastPolicyObj.getId(), operationsAccumulateParams);
310 // Build the specification
312 Results results = builder.buildSpecification();
313 if (results.isValid()) {
314 logger.info("results.getSpecification()=" + results.getSpecification());
316 // throw exception with error info
317 StringBuffer sb = new StringBuffer();
318 sb.append("Operation Policy validation problem: ControlLoopPolicyBuilder failed with following messages: ");
319 for (Message message : results.getMessages()) {
320 sb.append(message.getMessage());
323 throw new BadRequestException(sb.toString());
326 String encodedYaml = URLEncoder.encode(results.getSpecification(), "UTF-8");
332 * Adding AOTS actor and other recipe for yaml
337 private static List<PolicyItem> addAOTSActorRecipe(RefProp refProp, String service, List<PolicyItem> inOrigList) {
338 List<PolicyItem> outList = new ArrayList<PolicyItem>();
340 PolicyItem policyItem = inOrigList.get(0);
341 ObjectNode rootNode = (ObjectNode) refProp.getJsonTemplate("op.eNodeB.recipe", service);
342 Iterator<JsonNode> itr = rootNode.get("eNodeBRecipes").elements();
343 while (itr.hasNext()) {
344 PolicyItem policyItemObj = (PolicyItem) policyItem.clone();
345 JsonNode recipeNode = itr.next();
346 policyItemObj.setId(recipeNode.path("Recipe").asText());
347 policyItemObj.setActor(recipeNode.path("Actor").asText());
348 policyItemObj.setRecipe(recipeNode.path("Recipe").asText());
349 policyItemObj.setParentPolicy(recipeNode.path("ParentPolicy").asText());
350 if (!recipeNode.path("Retry").asText().isEmpty()) {
351 policyItemObj.setMaxRetries(Integer.parseInt(recipeNode.path("Retry").asText()));
353 if (!recipeNode.path("TimeLimit").asText().isEmpty()) {
354 policyItemObj.setRetryTimeLimit(Integer.parseInt(recipeNode.path("TimeLimit").asText()));
356 if (!recipeNode.path("PPConditions").asText().isEmpty()) {
357 List<String> parentPolicyConditions = new ArrayList<String>();
358 for (String ppCondition : recipeNode.path("PPConditions").asText().split(",")) {
359 parentPolicyConditions.add(ppCondition);
361 policyItemObj.setParentPolicyConditions(parentPolicyConditions);
363 outList.add(policyItemObj);
365 } catch (Exception e) {
366 logger.log(Level.ERROR, "Error", e);
372 * Order list of PolicyItems so that parents come before any of their
378 private static List<PolicyItem> orderParentFirst(List<PolicyItem> inOrigList) {
379 List<PolicyItem> inList = new ArrayList<>();
380 inList.addAll(inOrigList);
381 List<PolicyItem> outList = new ArrayList<>();
383 while (!inList.isEmpty()) {
384 // check if there's a loop in the policy chain (the inList should
385 // have been reduced by at least one)
386 if (inList.size() == prevSize) {
387 throw new BadRequestException("Operation Policy validation problem: loop in Operation Policy chain");
389 prevSize = inList.size();
390 // the following loop should remove at least one PolicyItem from the
392 Iterator<PolicyItem> inListItr = inList.iterator();
393 while (inListItr.hasNext()) {
394 PolicyItem inItem = inListItr.next();
395 // check for trigger policy (no parent)
396 String parent = inItem.getParentPolicy();
397 if (parent == null || parent.length() == 0) {
398 if (outList.size() > 0) {
399 throw new BadRequestException(
400 "Operation Policy validation problem: more than one trigger policy");
406 // check if this PolicyItem's parent has been processed
407 for (PolicyItem outItem : outList) {
408 if (outItem.getId().equals(parent)) {
409 // if the inItem parent is already in the outList,
410 // then add inItem to outList and remove from inList
423 * Convert a List of resource strings to an array of Resource objects.
426 * @param resourceType
429 private static Resource[] convertToResource(List<String> stringList, ResourceType resourceType) {
430 if (stringList == null || stringList.isEmpty()) {
431 return new Resource[0];
433 return stringList.stream().map(stringElem -> new Resource(stringElem, resourceType)).toArray(Resource[]::new);
437 * Convert a List of policy result strings to an array of PolicyResult
443 private static PolicyResult[] convertToPolicyResult(List<String> prList) {
444 if (prList == null || prList.isEmpty()) {
445 return new PolicyResult[0];
447 return prList.stream().map(stringElem -> PolicyResult.toResult(stringElem)).toArray(PolicyResult[]::new);