2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2018 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.policy;
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.config.ClampProperties;
43 import org.onap.clamp.clds.model.properties.Global;
44 import org.onap.clamp.clds.model.properties.ModelProperties;
45 import org.onap.clamp.clds.model.properties.PolicyChain;
46 import org.onap.clamp.clds.model.properties.PolicyItem;
47 import org.onap.clamp.clds.model.properties.Tca;
48 import org.onap.policy.api.AttributeType;
49 import org.onap.policy.controlloop.policy.OperationsAccumulateParams;
50 import org.onap.policy.controlloop.policy.Policy;
51 import org.onap.policy.controlloop.policy.PolicyResult;
52 import org.onap.policy.controlloop.policy.Target;
53 import org.onap.policy.controlloop.policy.TargetType;
54 import org.onap.policy.controlloop.policy.builder.BuilderException;
55 import org.onap.policy.controlloop.policy.builder.ControlLoopPolicyBuilder;
56 import org.onap.policy.controlloop.policy.builder.Message;
57 import org.onap.policy.controlloop.policy.builder.Results;
58 import org.onap.policy.sdc.Resource;
59 import org.onap.policy.sdc.ResourceType;
60 import org.onap.policy.sdc.Service;
63 * Construct an Operational Policy request given CLDS objects.
65 public class OperationalPolicyReq {
67 private static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicyReq.class);
69 protected OperationalPolicyReq() {
73 * Format Operational Policy attributes.
77 * @param modelElementId
80 * @throws BuilderException
81 * @throws UnsupportedEncodingException
83 public static Map<AttributeType, Map<String, String>> formatAttributes(ClampProperties refProp,
84 ModelProperties prop, String modelElementId, PolicyChain policyChain)
85 throws BuilderException, UnsupportedEncodingException {
86 Global global = prop.getGlobal();
87 prop.setCurrentModelElementId(modelElementId);
88 prop.setPolicyUniqueId(policyChain.getPolicyId());
89 String templateName = "";
90 String operationTopic = "";
91 String notificationTopic = "";
92 String controller = "";
93 Tca tca = prop.getType(Tca.class);
94 if (tca != null && tca.isFound()) {
95 if (global.getActionSet().equalsIgnoreCase("enbRecipe")) {
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());
101 templateName = refProp.getStringValue("op.templateName", global.getService());
102 operationTopic = refProp.getStringValue("op.operationTopic", global.getService());
103 notificationTopic = refProp.getStringValue("op.notificationTopic", global.getService());
104 controller = refProp.getStringValue("op.controller", global.getService());
107 String recipeTopic = refProp.getStringValue("op.recipeTopic", global.getService());
109 logger.info("templateName=" + templateName);
110 logger.info("notificationTopic=" + notificationTopic);
111 Map<String, String> ruleAttributes = new HashMap<>();
112 ruleAttributes.put("templateName", templateName);
113 ruleAttributes.put("ClosedLoopControlName", prop.getControlNameAndPolicyUniqueId());
114 ruleAttributes.put("NotificationTopic", notificationTopic);
115 if (operationTopic == null || operationTopic.isEmpty()) {
116 logger.info("recipeTopic=" + recipeTopic);
117 // if no operationTopic, then don't format yaml - use first policy
119 PolicyItem policyItem = policyChain.getPolicyItems().get(0);
120 ruleAttributes.put("RecipeTopic", recipeTopic);
121 String recipe = policyItem.getRecipe();
122 String maxRetries = String.valueOf(policyItem.getMaxRetries());
123 String retryTimeLimit = String.valueOf(policyItem.getRetryTimeLimit());
124 String targetResourceId = String.valueOf(policyItem.getTargetResourceId());
125 logger.info("recipe=" + recipe);
126 logger.info("maxRetries=" + maxRetries);
127 logger.info("retryTimeLimit=" + retryTimeLimit);
128 logger.info("targetResourceId=" + targetResourceId);
129 ruleAttributes.put("Recipe", recipe);
130 ruleAttributes.put("MaxRetries", maxRetries);
131 ruleAttributes.put("RetryTimeLimit", retryTimeLimit);
132 ruleAttributes.put("ResourceId", targetResourceId);
134 logger.info("operationTopic=" + operationTopic);
136 String yaml = (tca != null && tca.isFound()) ? formateNodeBYaml(refProp, prop, modelElementId, policyChain)
137 : formatYaml(refProp, prop, modelElementId, policyChain);
138 ruleAttributes.put("OperationTopic", operationTopic);
139 ruleAttributes.put("ControlLoopYaml", yaml);
141 // matchingAttributes
142 Map<String, String> matchingAttributes = new HashMap<>();
143 matchingAttributes.put("controller", controller);
144 Map<AttributeType, Map<String, String>> attributes = new HashMap<>();
145 attributes.put(AttributeType.RULE, ruleAttributes);
146 attributes.put(AttributeType.MATCHING, matchingAttributes);
151 * Format Operational OpenLoop Policy yaml.
155 * @param modelElementId
158 * @throws BuilderException
159 * @throws UnsupportedEncodingException
161 protected static String formatOpenLoopYaml(ClampProperties refProp, ModelProperties prop, String modelElementId,
162 PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
163 // get property objects
164 Global global = prop.getGlobal();
165 prop.setCurrentModelElementId(modelElementId);
166 prop.setPolicyUniqueId(policyChain.getPolicyId());
167 // convert values to SDC objects
168 Service service = new Service(global.getService());
169 Resource[] vfResources = convertToResource(global.getResourceVf(), ResourceType.VF);
171 ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
172 policyChain.getTimeout(), service, vfResources);
173 // builder.setTriggerPolicy(refProp.getStringValue("op.openloop.policy"));
174 // Build the specification
175 Results results = builder.buildSpecification();
177 return URLEncoder.encode(results.getSpecification(), "UTF-8");
181 * Format Operational Policy yaml.
185 * @param modelElementId
188 * @throws BuilderException
189 * @throws UnsupportedEncodingException
191 protected static String formatYaml(ClampProperties refProp, ModelProperties prop, String modelElementId,
192 PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
193 // get property objects
194 Global global = prop.getGlobal();
195 prop.setCurrentModelElementId(modelElementId);
196 prop.setPolicyUniqueId(policyChain.getPolicyId());
197 // convert values to SDC objects
198 Service service = new Service(global.getService());
199 Resource[] vfResources = convertToResource(global.getResourceVf(), ResourceType.VF);
200 Resource[] vfcResources = convertToResource(global.getResourceVfc(), ResourceType.VFC);
202 ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
203 policyChain.getTimeout(), service, vfResources);
204 builder.addResource(vfcResources);
205 // process each policy
206 Map<String, Policy> policyObjMap = new HashMap<>();
207 List<PolicyItem> policyItemList = orderParentFirst(policyChain.getPolicyItems());
208 for (PolicyItem policyItem : policyItemList) {
209 String policyName = policyItem.getRecipe() + " Policy";
210 Target target = new Target();
211 target.setType(TargetType.VM);
212 target.setResourceID(policyItem.getTargetResourceId());
214 if (policyItemList.indexOf(policyItem) == 0) {
215 String policyDescription = policyItem.getRecipe()
216 + " Policy - the trigger (no parent) policy - created by CLDS";
217 policyObj = builder.setTriggerPolicy(policyName, policyDescription,
218 refProp.getStringValue("op.policy.appc"), target, policyItem.getRecipe(), null,
219 policyItem.getMaxRetries(), policyItem.getRetryTimeLimit());
221 Policy parentPolicyObj = policyObjMap.get(policyItem.getParentPolicy());
222 String policyDescription = policyItem.getRecipe() + " Policy - triggered conditionally by "
223 + parentPolicyObj.getName() + " - created by CLDS";
224 policyObj = builder.setPolicyForPolicyResult(policyName, policyDescription,
225 refProp.getStringValue("op.policy.appc"), target, policyItem.getRecipe(), null,
226 policyItem.getMaxRetries(), policyItem.getRetryTimeLimit(), parentPolicyObj.getId(),
227 convertToPolicyResult(policyItem.getParentPolicyConditions()));
228 logger.info("policyObj.id=" + policyObj.getId() + "; parentPolicyObj.id=" + parentPolicyObj.getId());
230 policyObjMap.put(policyItem.getId(), policyObj);
232 // Build the specification
233 Results results = builder.buildSpecification();
235 return URLEncoder.encode(results.getSpecification(), "UTF-8");
239 * Format Operational Policy yaml.
243 * @param modelElementId
246 * @throws BuilderException
247 * @throws UnsupportedEncodingException
249 protected static String formateNodeBYaml(ClampProperties refProp, ModelProperties prop, String modelElementId,
250 PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
251 // get property objects
252 Global global = prop.getGlobal();
253 prop.setCurrentModelElementId(modelElementId);
254 prop.setPolicyUniqueId(policyChain.getPolicyId());
255 // convert values to SDC objects
256 Service service = new Service(global.getService());
257 Resource[] vfResources = convertToResource(global.getResourceVf(), ResourceType.VF);
258 Resource[] vfcResources = convertToResource(global.getResourceVfc(), ResourceType.VFC);
260 ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
261 policyChain.getTimeout(), service, vfResources);
262 builder.addResource(vfcResources);
263 // process each policy
264 Map<String, Policy> policyObjMap = new HashMap<>();
265 List<PolicyItem> policyItemList = addAOTSActorRecipe(refProp, global.getService(),
266 policyChain.getPolicyItems());
267 Policy lastPolicyObj = new Policy();
268 for (PolicyItem policyItem : policyItemList) {
269 Target target = new Target();
270 target.setType(TargetType.VM);
271 target.setResourceID(policyItem.getTargetResourceId());
272 String policyName = policyItem.getRecipe() + " Policy";
274 if (policyItemList.indexOf(policyItem) == 0) {
275 // To set up time window payload for trigger policy
276 Map<String, String> payloadMap = new HashMap<>();
277 payloadMap.put("timeWindow", refProp.getStringValue("op.eNodeB.timeWindow"));
278 String policyDescription = policyItem.getRecipe()
279 + " Policy - the trigger (no parent) policy - created by CLDS";
280 policyObj = builder.setTriggerPolicy(policyName, policyDescription, policyItem.getActor(), target,
281 policyItem.getRecipe(), payloadMap, policyItem.getMaxRetries(), policyItem.getRetryTimeLimit());
283 Policy parentPolicyObj = policyObjMap.get(policyItem.getParentPolicy());
284 String policyDescription = policyItem.getRecipe() + " Policy - triggered conditionally by "
285 + parentPolicyObj.getName() + " - created by CLDS";
286 policyObj = builder.setPolicyForPolicyResult(policyName, policyDescription, policyItem.getActor(),
287 target, policyItem.getRecipe(), null, policyItem.getMaxRetries(),
288 policyItem.getRetryTimeLimit(), parentPolicyObj.getId(),
289 convertToPolicyResult(policyItem.getParentPolicyConditions()));
290 lastPolicyObj = policyObj;
291 logger.info("policyObj.id=" + policyObj.getId() + "; parentPolicyObj.id=" + parentPolicyObj.getId());
293 policyObjMap.put(policyItem.getId(), policyObj);
295 // To set up operations accumulate params
296 OperationsAccumulateParams operationsAccumulateParams = new OperationsAccumulateParams();
297 operationsAccumulateParams.setLimit(Integer.valueOf(refProp.getStringValue("op.eNodeB.limit")));
298 operationsAccumulateParams.setPeriod(refProp.getStringValue("op.eNodeB.period"));
299 builder.addOperationsAccumulateParams(lastPolicyObj.getId(), operationsAccumulateParams);
300 // Build the specification
301 Results results = builder.buildSpecification();
303 return URLEncoder.encode(results.getSpecification(), "UTF-8");
306 private static void validate(Results results) {
307 if (results.isValid()) {
308 logger.info("results.getSpecification()=" + results.getSpecification());
310 // throw exception with error info
311 StringBuilder sb = new StringBuilder();
312 sb.append("Operation Policy validation problem: ControlLoopPolicyBuilder failed with following messages: ");
313 for (Message message : results.getMessages()) {
314 sb.append(message.getMessage());
317 throw new BadRequestException(sb.toString());
322 * Adding AOTS actor and other recipe for yaml
327 private static List<PolicyItem> addAOTSActorRecipe(ClampProperties refProp, String service,
328 List<PolicyItem> inOrigList) {
329 List<PolicyItem> outList = new ArrayList<>();
331 PolicyItem policyItem = inOrigList.get(0);
332 ObjectNode rootNode = (ObjectNode) refProp.getJsonTemplate("op.eNodeB.recipe", service);
333 Iterator<JsonNode> itr = rootNode.get("eNodeBRecipes").elements();
334 while (itr.hasNext()) {
335 PolicyItem policyItemObj = (PolicyItem) policyItem.clone();
336 JsonNode recipeNode = itr.next();
337 policyItemObj.setId(recipeNode.path("Recipe").asText());
338 policyItemObj.setActor(recipeNode.path("Actor").asText());
339 policyItemObj.setRecipe(recipeNode.path("Recipe").asText());
340 policyItemObj.setParentPolicy(recipeNode.path("ParentPolicy").asText());
341 if (!recipeNode.path("Retry").asText().isEmpty()) {
342 policyItemObj.setMaxRetries(Integer.parseInt(recipeNode.path("Retry").asText()));
344 if (!recipeNode.path("TimeLimit").asText().isEmpty()) {
345 policyItemObj.setRetryTimeLimit(Integer.parseInt(recipeNode.path("TimeLimit").asText()));
347 if (!recipeNode.path("PPConditions").asText().isEmpty()) {
348 List<String> parentPolicyConditions = new ArrayList<>();
349 for (String ppCondition : recipeNode.path("PPConditions").asText().split(",")) {
350 parentPolicyConditions.add(ppCondition);
352 policyItemObj.setParentPolicyConditions(parentPolicyConditions);
354 outList.add(policyItemObj);
356 } catch (Exception e) {
357 logger.log(Level.ERROR, "Error", e);
363 * Order list of PolicyItems so that parents come before any of their
369 private static List<PolicyItem> orderParentFirst(List<PolicyItem> inOrigList) {
370 List<PolicyItem> inList = new ArrayList<>();
371 inList.addAll(inOrigList);
372 List<PolicyItem> outList = new ArrayList<>();
374 while (!inList.isEmpty()) {
375 // check if there's a loop in the policy chain (the inList should
376 // have been reduced by at least one)
377 if (inList.size() == prevSize) {
378 throw new BadRequestException("Operation Policy validation problem: loop in Operation Policy chain");
380 prevSize = inList.size();
381 // the following loop should remove at least one PolicyItem from the
383 Iterator<PolicyItem> inListItr = inList.iterator();
384 while (inListItr.hasNext()) {
385 PolicyItem inItem = inListItr.next();
386 // check for trigger policy (no parent)
387 String parent = inItem.getParentPolicy();
388 if (parent == null || parent.length() == 0) {
389 if (!outList.isEmpty()) {
390 throw new BadRequestException(
391 "Operation Policy validation problem: more than one trigger policy");
397 // check if this PolicyItem's parent has been processed
398 for (PolicyItem outItem : outList) {
399 if (outItem.getId().equals(parent)) {
400 // if the inItem parent is already in the outList,
401 // then add inItem to outList and remove from inList
414 * Convert a List of resource strings to an array of Resource objects.
417 * @param resourceType
420 private static Resource[] convertToResource(List<String> stringList, ResourceType resourceType) {
421 if (stringList == null || stringList.isEmpty()) {
422 return new Resource[0];
424 return stringList.stream().map(stringElem -> new Resource(stringElem, resourceType)).toArray(Resource[]::new);
428 * Convert a List of policy result strings to an array of PolicyResult
434 private static PolicyResult[] convertToPolicyResult(List<String> prList) {
435 if (prList == null || prList.isEmpty()) {
436 return new PolicyResult[0];
438 return prList.stream().map(stringElem -> PolicyResult.toResult(stringElem)).toArray(PolicyResult[]::new);