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