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 * Modifications copyright (c) 2018 Nokia
21 * ===================================================================
25 package org.onap.clamp.clds.client.req.policy;
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
30 import java.io.UnsupportedEncodingException;
31 import java.net.URLEncoder;
32 import java.util.ArrayList;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
38 import javax.ws.rs.BadRequestException;
40 import org.onap.clamp.clds.config.ClampProperties;
41 import org.onap.clamp.clds.model.properties.Global;
42 import org.onap.clamp.clds.model.properties.ModelProperties;
43 import org.onap.clamp.clds.model.properties.PolicyChain;
44 import org.onap.clamp.clds.model.properties.PolicyItem;
45 import org.onap.policy.api.AttributeType;
46 import org.onap.policy.controlloop.policy.Policy;
47 import org.onap.policy.controlloop.policy.PolicyResult;
48 import org.onap.policy.controlloop.policy.Target;
49 import org.onap.policy.controlloop.policy.TargetType;
50 import org.onap.policy.controlloop.policy.builder.BuilderException;
51 import org.onap.policy.controlloop.policy.builder.ControlLoopPolicyBuilder;
52 import org.onap.policy.controlloop.policy.builder.Message;
53 import org.onap.policy.controlloop.policy.builder.Results;
54 import org.onap.policy.sdc.Resource;
55 import org.onap.policy.sdc.ResourceType;
56 import org.onap.policy.sdc.Service;
59 * Construct an Operational Policy request given CLDS objects.
61 public class OperationalPolicyReq {
63 private static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicyReq.class);
65 protected OperationalPolicyReq() {
69 * Format Operational Policy attributes.
73 * @param modelElementId
76 * @throws BuilderException
77 * @throws UnsupportedEncodingException
79 public static Map<AttributeType, Map<String, String>> formatAttributes(ClampProperties refProp,
80 ModelProperties prop, String modelElementId, PolicyChain policyChain)
81 throws BuilderException, UnsupportedEncodingException {
82 Global global = prop.getGlobal();
83 prop.setCurrentModelElementId(modelElementId);
84 prop.setPolicyUniqueId(policyChain.getPolicyId());
85 String templateName = refProp.getStringValue("op.templateName", global.getService());
86 String operationTopic = refProp.getStringValue("op.operationTopic", global.getService());
87 String notificationTopic = refProp.getStringValue("op.notificationTopic", global.getService());
88 String controller = refProp.getStringValue("op.controller", global.getService());
89 String recipeTopic = refProp.getStringValue("op.recipeTopic", global.getService());
91 logger.info("templateName=" + templateName);
92 logger.info("notificationTopic=" + notificationTopic);
93 Map<String, String> ruleAttributes = new HashMap<>();
94 ruleAttributes.put("templateName", templateName);
95 ruleAttributes.put("closedLoopControlName", prop.getControlNameAndPolicyUniqueId());
96 ruleAttributes.put("notificationTopic", notificationTopic);
97 if (operationTopic == null || operationTopic.isEmpty()) {
98 logger.info("recipeTopic=" + recipeTopic);
99 // if no operationTopic, then don't format yaml - use first policy
101 PolicyItem policyItem = policyChain.getPolicyItems().get(0);
102 ruleAttributes.put("RecipeTopic", recipeTopic);
103 String recipe = policyItem.getRecipe();
104 String maxRetries = String.valueOf(policyItem.getMaxRetries());
105 String retryTimeLimit = String.valueOf(policyItem.getRetryTimeLimit());
106 String targetResourceId = String.valueOf(policyItem.getTargetResourceId());
107 logger.info("recipe=" + recipe);
108 logger.info("maxRetries=" + maxRetries);
109 logger.info("retryTimeLimit=" + retryTimeLimit);
110 logger.info("targetResourceId=" + targetResourceId);
111 ruleAttributes.put("Recipe", recipe);
112 ruleAttributes.put("MaxRetries", maxRetries);
113 ruleAttributes.put("RetryTimeLimit", retryTimeLimit);
114 ruleAttributes.put("ResourceId", targetResourceId);
116 logger.info("operationTopic=" + operationTopic);
118 String yaml = formatYaml(refProp, prop, modelElementId, policyChain);
119 ruleAttributes.put("operationTopic", operationTopic);
120 ruleAttributes.put("controlLoopYaml", yaml);
122 // matchingAttributes
123 Map<String, String> matchingAttributes = new HashMap<>();
124 matchingAttributes.put("controller", controller);
125 Map<AttributeType, Map<String, String>> attributes = new HashMap<>();
126 attributes.put(AttributeType.RULE, ruleAttributes);
127 attributes.put(AttributeType.MATCHING, matchingAttributes);
132 * Format Operational OpenLoop Policy yaml.
136 * @param modelElementId
139 * @throws BuilderException
140 * @throws UnsupportedEncodingException
142 protected static String formatOpenLoopYaml(ClampProperties refProp, ModelProperties prop, String modelElementId,
143 PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
144 // get property objects
145 Global global = prop.getGlobal();
146 prop.setCurrentModelElementId(modelElementId);
147 prop.setPolicyUniqueId(policyChain.getPolicyId());
148 // convert values to SDC objects
149 Service service = new Service(global.getService());
150 Resource[] vfResources = convertToResource(global.getResourceVf(), ResourceType.VF);
152 ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
153 policyChain.getTimeout(), service, vfResources);
154 // builder.setTriggerPolicy(refProp.getStringValue("op.openloop.policy"));
155 // Build the specification
156 Results results = builder.buildSpecification();
158 return URLEncoder.encode(results.getSpecification(), "UTF-8");
162 * Format Operational Policy yaml.
166 * @param modelElementId
169 * @throws BuilderException
170 * @throws UnsupportedEncodingException
172 protected static String formatYaml(ClampProperties refProp, ModelProperties prop, String modelElementId,
173 PolicyChain policyChain) throws BuilderException, UnsupportedEncodingException {
174 // get property objects
175 Global global = prop.getGlobal();
176 prop.setCurrentModelElementId(modelElementId);
177 prop.setPolicyUniqueId(policyChain.getPolicyId());
178 // convert values to SDC objects
179 Service service = new Service(global.getService());
180 Resource[] vfResources = convertToResource(global.getResourceVf(), ResourceType.VF);
181 Resource[] vfcResources = convertToResource(global.getResourceVfc(), ResourceType.VFC);
183 ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
184 policyChain.getTimeout(), service, vfResources);
185 builder.addResource(vfcResources);
186 // process each policy
187 Map<String, Policy> policyObjMap = new HashMap<>();
188 List<PolicyItem> policyItemList = orderParentFirst(policyChain.getPolicyItems());
189 for (PolicyItem policyItem : policyItemList) {
190 String policyName = policyItem.getRecipe() + " Policy";
191 Target target = new Target();
192 target.setType(TargetType.VM);
193 // We can send target type as VM/VNF for most of recipes
194 if (policyItem.getRecipeLevel() != null && !policyItem.getRecipeLevel().isEmpty()) {
195 target.setType(TargetType.valueOf(policyItem.getRecipeLevel()));
197 target.setResourceID(policyItem.getTargetResourceId());
198 String actor = refProp.getStringValue("op.policy.appc");
199 Map<String, String> payloadMap = null;
200 if ("health-diagnostic".equalsIgnoreCase(policyItem.getRecipe())) {
201 actor = refProp.getStringValue("op.policy.sdno");
202 payloadMap = new HashMap<String, String>();
203 payloadMap.put("ttl", policyItem.getRecipePayload());
205 // For reboot recipe we have to send type as SOFT/HARD in pay load
206 if (policyItem.getRecipeInfo() != null && !policyItem.getRecipeInfo().isEmpty()) {
207 payloadMap = new HashMap<String, String>();
208 payloadMap.put("type", policyItem.getRecipeInfo());
211 if (policyItemList.indexOf(policyItem) == 0) {
212 String policyDescription = policyItem.getRecipe()
213 + " Policy - the trigger (no parent) policy - created by CLDS";
214 policyObj = builder.setTriggerPolicy(policyName, policyDescription, actor, target,
215 policyItem.getRecipe(), payloadMap, policyItem.getMaxRetries(), policyItem.getRetryTimeLimit());
217 Policy parentPolicyObj = policyObjMap.get(policyItem.getParentPolicy());
218 String policyDescription = policyItem.getRecipe() + " Policy - triggered conditionally by "
219 + parentPolicyObj.getName() + " - created by CLDS";
220 policyObj = builder.setPolicyForPolicyResult(policyName, policyDescription, actor, target,
221 policyItem.getRecipe(), payloadMap, policyItem.getMaxRetries(), policyItem.getRetryTimeLimit(),
222 parentPolicyObj.getId(), convertToPolicyResult(policyItem.getParentPolicyConditions()));
223 logger.info("policyObj.id=" + policyObj.getId() + "; parentPolicyObj.id=" + parentPolicyObj.getId());
225 policyObjMap.put(policyItem.getId(), policyObj);
227 // Build the specification
228 Results results = builder.buildSpecification();
230 return URLEncoder.encode(results.getSpecification(), "UTF-8");
233 protected static void validate(Results results) {
234 if (results.isValid()) {
235 logger.info("results.getSpecification()=" + results.getSpecification());
237 // throw exception with error info
238 StringBuilder sb = new StringBuilder();
239 sb.append("Operation Policy validation problem: ControlLoopPolicyBuilder failed with following messages: ");
240 for (Message message : results.getMessages()) {
241 sb.append(message.getMessage());
244 throw new BadRequestException(sb.toString());
249 * Order list of PolicyItems so that parents come before any of their
255 private static List<PolicyItem> orderParentFirst(List<PolicyItem> inOrigList) {
256 List<PolicyItem> inList = new ArrayList<>();
257 inList.addAll(inOrigList);
258 List<PolicyItem> outList = new ArrayList<>();
260 while (!inList.isEmpty()) {
261 // check if there's a loop in the policy chain (the inList should
262 // have been reduced by at least one)
263 if (inList.size() == prevSize) {
264 throw new BadRequestException("Operation Policy validation problem: loop in Operation Policy chain");
266 prevSize = inList.size();
267 // the following loop should remove at least one PolicyItem from the
269 Iterator<PolicyItem> inListItr = inList.iterator();
270 while (inListItr.hasNext()) {
271 PolicyItem inItem = inListItr.next();
272 // check for trigger policy (no parent)
273 String parent = inItem.getParentPolicy();
274 if (parent == null || parent.length() == 0) {
275 if (!outList.isEmpty()) {
276 throw new BadRequestException(
277 "Operation Policy validation problem: more than one trigger policy");
283 // check if this PolicyItem's parent has been processed
284 for (PolicyItem outItem : outList) {
285 if (outItem.getId().equals(parent)) {
286 // if the inItem parent is already in the outList,
287 // then add inItem to outList and remove from inList
300 * Convert a List of resource strings to an array of Resource objects.
303 * @param resourceType
306 protected static Resource[] convertToResource(List<String> stringList, ResourceType resourceType) {
307 if (stringList == null || stringList.isEmpty()) {
308 return new Resource[0];
310 return stringList.stream().map(stringElem -> new Resource(stringElem, resourceType)).toArray(Resource[]::new);
314 * Convert a List of policy result strings to an array of PolicyResult
320 protected static PolicyResult[] convertToPolicyResult(List<String> prList) {
321 if (prList == null || prList.isEmpty()) {
322 return new PolicyResult[0];
324 return prList.stream().map(PolicyResult::toResult).toArray(PolicyResult[]::new);