f2536b1f0ab4c1aa4026098de5f84847b0bcb02e
[clamp.git] / src / main / java / org / onap / clamp / clds / client / req / policy / OperationalPolicyYamlFormatter.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  * Modifications copyright (c) 2018 Nokia
21  * ===================================================================
22  *
23  */
24
25 package org.onap.clamp.clds.client.req.policy;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29
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;
36 import java.util.Map;
37
38 import javax.ws.rs.BadRequestException;
39
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.controlloop.policy.Policy;
45 import org.onap.policy.controlloop.policy.PolicyResult;
46 import org.onap.policy.controlloop.policy.Target;
47 import org.onap.policy.controlloop.policy.TargetType;
48 import org.onap.policy.controlloop.policy.builder.BuilderException;
49 import org.onap.policy.controlloop.policy.builder.ControlLoopPolicyBuilder;
50 import org.onap.policy.controlloop.policy.builder.Message;
51 import org.onap.policy.controlloop.policy.builder.Results;
52 import org.onap.policy.sdc.Resource;
53 import org.onap.policy.sdc.ResourceType;
54 import org.onap.policy.sdc.Service;
55
56 public class OperationalPolicyYamlFormatter {
57     private static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicyYamlFormatter.class);
58
59     protected OperationalPolicyYamlFormatter() {
60     }
61
62     /**
63      * Format Operational OpenLoop Policy yaml.
64      *
65      * @param prop The model properties
66      * @param modelElementId The model element ID
67      * @param policyChain The policy chain
68      * @return The operational openloop policy in yaml format
69      * @throws BuilderException The builder exception
70      * @throws UnsupportedEncodingException The unsupported encoding exception
71      */
72     public static String formatOpenLoopYaml(ModelProperties prop, String modelElementId, PolicyChain policyChain)
73         throws BuilderException, UnsupportedEncodingException {
74         // get property objects
75         Global global = prop.getGlobal();
76         prop.setCurrentModelElementId(modelElementId);
77         prop.setPolicyUniqueId(policyChain.getPolicyId());
78         // convert values to SDC objects
79         Service service = new Service(global.getService());
80         Resource[] vfResources = convertToResources(global.getResourceVf(), ResourceType.VF);
81         // create builder
82         ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
83             policyChain.getTimeout(), service, vfResources);
84         // builder.setTriggerPolicy(refProp.getStringValue("op.openloop.policy"));
85         // Build the specification
86         Results results = builder.buildSpecification();
87         validate(results);
88         return URLEncoder.encode(results.getSpecification(), "UTF-8");
89     }
90
91     /**
92      * Format Operational Policy yaml.
93      * @param prop The model properties
94      * @param modelElementId The model element ID
95      * @param policyChain The policy chain
96      * @return The operational policy properties in yaml format
97      * @throws BuilderException The builder exception
98      * @throws UnsupportedEncodingException The unsupported encoding exception
99      */
100     public static String formatYaml(ModelProperties prop, String modelElementId, PolicyChain policyChain)
101         throws BuilderException, UnsupportedEncodingException {
102         // get property objects
103         prop.setCurrentModelElementId(modelElementId);
104         prop.setPolicyUniqueId(policyChain.getPolicyId());
105
106         // create builder
107         ControlLoopPolicyBuilder builder = ControlLoopPolicyBuilder.Factory.buildControlLoop(prop.getControlName(),
108             policyChain.getTimeout());
109         // process each policy
110         Map<String, Policy> policyObjMap = new HashMap<>();
111         List<PolicyItem> policyItemList = orderParentFirst(policyChain.getPolicyItems());
112         for (PolicyItem policyItem : policyItemList) {
113             String policyName = policyItem.getRecipe() + " Policy";
114             Target target = new Target();
115             target.setType(TargetType.VM);
116             // We can send target type as VM/VNF for most of recipes
117             if (policyItem.getRecipeLevel() != null && !policyItem.getRecipeLevel().isEmpty()) {
118                 target.setType(TargetType.valueOf(policyItem.getRecipeLevel()));
119             }
120             target.setResourceID(policyItem.getTargetResourceId());
121             String actor = policyItem.getActor();
122             Map<String, String> payloadMap = policyItem.getRecipePayload();
123             Policy policyObj;
124             if (policyItemList.indexOf(policyItem) == 0) {
125                 String policyDescription = policyItem.getRecipe()
126                     + " Policy - the trigger (no parent) policy - created by CLDS";
127                 policyObj = builder.setTriggerPolicy(policyName, policyDescription, actor, target,
128                     policyItem.getRecipe(), payloadMap, policyItem.getMaxRetries(), policyItem.getRetryTimeLimit());
129             } else {
130                 Policy parentPolicyObj = policyObjMap.get(policyItem.getParentPolicy());
131                 String policyDescription = policyItem.getRecipe() + " Policy - triggered conditionally by "
132                     + parentPolicyObj.getName() + " - created by CLDS";
133                 policyObj = builder.setPolicyForPolicyResult(policyName, policyDescription, actor, target,
134                     policyItem.getRecipe(), payloadMap, policyItem.getMaxRetries(), policyItem.getRetryTimeLimit(),
135                     parentPolicyObj.getId(), convertToPolicyResults(policyItem.getParentPolicyConditions()));
136                 logger.info("policyObj.id=" + policyObj.getId() + "; parentPolicyObj.id=" + parentPolicyObj.getId());
137             }
138             policyObjMap.put(policyItem.getId(), policyObj);
139         }
140         // Build the specification
141         Results results = builder.buildSpecification();
142         validate(results);
143         return URLEncoder.encode(results.getSpecification(), "UTF-8");
144     }
145
146     protected static List<PolicyItem> orderParentFirst(List<PolicyItem> inOrigList) {
147         List<PolicyItem> inList = new ArrayList<>();
148         inList.addAll(inOrigList);
149         List<PolicyItem> outList = new ArrayList<>();
150         int prevSize = 0;
151         while (!inList.isEmpty()) {
152             // check if there's a loop in the policy chain (the inList should
153             // have been reduced by at least one)
154             if (inList.size() == prevSize) {
155                 throw new BadRequestException("Operation Policy validation problem: loop in Operation Policy chain");
156             }
157             prevSize = inList.size();
158             // the following loop should remove at least one PolicyItem from the
159             // inList
160             Iterator<PolicyItem> inListItr = inList.iterator();
161             while (inListItr.hasNext()) {
162                 PolicyItem inItem = inListItr.next();
163                 // check for trigger policy (no parent)
164                 String parent = inItem.getParentPolicy();
165                 if (parent == null || parent.length() == 0) {
166                     if (!outList.isEmpty()) {
167                         throw new BadRequestException(
168                             "Operation Policy validation problem: more than one trigger policy");
169                     } else {
170                         outList.add(inItem);
171                         inListItr.remove();
172                     }
173                 } else {
174                     // check if this PolicyItem's parent has been processed
175                     for (PolicyItem outItem : outList) {
176                         if (outItem.getId().equals(parent)) {
177                             // if the inItem parent is already in the outList,
178                             // then add inItem to outList and remove from inList
179                             outList.add(inItem);
180                             inListItr.remove();
181                             break;
182                         }
183                     }
184                 }
185             }
186         }
187         return outList;
188     }
189
190     protected static void validate(Results results) {
191         if (results.isValid()) {
192             logger.info("results.getSpecification()=" + results.getSpecification());
193         } else {
194             // throw exception with error info
195             StringBuilder sb = new StringBuilder();
196             sb.append("Operation Policy validation problem: ControlLoopPolicyBuilder failed with following messages: ");
197             for (Message message : results.getMessages()) {
198                 sb.append(message.getMessage());
199                 sb.append("; ");
200             }
201             throw new BadRequestException(sb.toString());
202         }
203     }
204
205     protected static Resource[] convertToResources(List<String> stringList, ResourceType resourceType) {
206         if (stringList == null || stringList.isEmpty()) {
207             return new Resource[0];
208         }
209         return stringList.stream().map(stringElem -> new Resource(stringElem, resourceType)).toArray(Resource[]::new);
210     }
211
212     protected static PolicyResult[] convertToPolicyResults(List<String> prList) {
213         if (prList == null || prList.isEmpty()) {
214             return new PolicyResult[0];
215         }
216         return prList.stream().map(PolicyResult::toResult).toArray(PolicyResult[]::new);
217     }
218
219 }