c4b2cd4caf9dd35c2db43dfdc391c047e7b6f1f5
[policy/models.git] / models-interactions / model-yaml / src / main / java / org / onap / policy / controlloop / policy / builder / impl / ControlLoopPolicyBuilderImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * policy-yaml
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019-2020 Nordix Foundation.
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  */
21
22 package org.onap.policy.controlloop.policy.builder.impl;
23
24 import com.google.common.base.Strings;
25 import java.util.LinkedList;
26 import java.util.UUID;
27 import org.onap.aai.domain.yang.Pnf;
28 import org.onap.policy.controlloop.compiler.CompilerException;
29 import org.onap.policy.controlloop.compiler.ControlLoopCompiler;
30 import org.onap.policy.controlloop.compiler.ControlLoopCompilerCallback;
31 import org.onap.policy.controlloop.policy.ControlLoop;
32 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
33 import org.onap.policy.controlloop.policy.FinalResult;
34 import org.onap.policy.controlloop.policy.OperationsAccumulateParams;
35 import org.onap.policy.controlloop.policy.Policy;
36 import org.onap.policy.controlloop.policy.PolicyParam;
37 import org.onap.policy.controlloop.policy.PolicyResult;
38 import org.onap.policy.controlloop.policy.builder.BuilderException;
39 import org.onap.policy.controlloop.policy.builder.ControlLoopPolicyBuilder;
40 import org.onap.policy.controlloop.policy.builder.MessageLevel;
41 import org.onap.policy.controlloop.policy.builder.Results;
42 import org.onap.policy.sdc.Resource;
43 import org.onap.policy.sdc.Service;
44 import org.yaml.snakeyaml.DumperOptions;
45 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
46 import org.yaml.snakeyaml.Yaml;
47
48 public class ControlLoopPolicyBuilderImpl implements ControlLoopPolicyBuilder {
49     private static final String UNKNOWN_POLICY = "Unknown policy ";
50     private ControlLoopPolicy controlLoopPolicy;
51
52     /**
53      * Constructor.
54      *
55      * @param controlLoopName control loop id
56      * @param timeout timeout value
57      */
58     public ControlLoopPolicyBuilderImpl(String controlLoopName, Integer timeout) {
59         controlLoopPolicy = new ControlLoopPolicy();
60         ControlLoop controlLoop = new ControlLoop();
61         controlLoop.setControlLoopName(controlLoopName);
62         controlLoop.setTimeout(timeout);
63         controlLoopPolicy.setControlLoop(controlLoop);
64     }
65
66     /**
67      * Constructor.
68      *
69      * @param controlLoopName control loop id
70      * @param timeout timeout value
71      * @param resource resource
72      * @param services services
73      * @throws BuilderException builder exception
74      */
75     public ControlLoopPolicyBuilderImpl(String controlLoopName, Integer timeout, Resource resource,
76         Service... services) throws BuilderException {
77         this(controlLoopName, timeout);
78         this.addResource(resource);
79         this.addService(services);
80     }
81
82     public ControlLoopPolicyBuilderImpl(String controlLoopName, Integer timeout, Pnf pnf) throws BuilderException {
83         this(controlLoopName, timeout);
84         this.setPnf(pnf);
85     }
86
87     /**
88      * Constructor.
89      *
90      * @param controlLoopName control loop id
91      * @param timeout timeout
92      * @param service service
93      * @param resources resources
94      * @throws BuilderException builder exception
95      */
96     public ControlLoopPolicyBuilderImpl(String controlLoopName, Integer timeout, Service service,
97         Resource[] resources) throws BuilderException {
98         this(controlLoopName, timeout);
99         this.addService(service);
100         this.addResource(resources);
101     }
102
103     @Override
104     public ControlLoopPolicyBuilder removePnf() throws BuilderException {
105         controlLoopPolicy.getControlLoop().setPnf(null);
106         return this;
107     }
108
109     @Override
110     public ControlLoopPolicyBuilder addService(Service... services) throws BuilderException {
111         for (Service service : services) {
112             if (service == null) {
113                 throw new BuilderException("Service must not be null");
114             }
115             if (service.getServiceUUID() == null && Strings.isNullOrEmpty(service.getServiceName())) {
116                 throw new BuilderException("Invalid service - need either a serviceUUID or serviceName");
117             }
118             if (controlLoopPolicy.getControlLoop().getServices() == null) {
119                 controlLoopPolicy.getControlLoop().setServices(new LinkedList<>());
120             }
121             controlLoopPolicy.getControlLoop().getServices().add(service);
122         }
123         return this;
124     }
125
126     @Override
127     public ControlLoopPolicyBuilder removeService(Service... services) throws BuilderException {
128         if (controlLoopPolicy.getControlLoop().getServices() == null) {
129             throw new BuilderException("No existing services to remove");
130         }
131         for (Service service : services) {
132             if (service == null) {
133                 throw new BuilderException("Service must not be null");
134             }
135             if (service.getServiceUUID() == null && Strings.isNullOrEmpty(service.getServiceName())) {
136                 throw new BuilderException("Invalid service - need either a serviceUUID or serviceName");
137             }
138             boolean removed = controlLoopPolicy.getControlLoop().getServices().remove(service);
139             if (!removed) {
140                 throw new BuilderException("Unknown service " + service.getServiceName());
141             }
142         }
143         return this;
144     }
145
146     @Override
147     public ControlLoopPolicyBuilder removeAllServices() throws BuilderException {
148         controlLoopPolicy.getControlLoop().getServices().clear();
149         return this;
150     }
151
152     @Override
153     public ControlLoopPolicyBuilder addResource(Resource... resources) throws BuilderException {
154         for (Resource resource : resources) {
155             if (resource == null) {
156                 throw new BuilderException("Resource must not be null");
157             }
158             if (resource.getResourceUuid() == null && Strings.isNullOrEmpty(resource.getResourceName())) {
159                 throw new BuilderException("Invalid resource - need either resourceUUID or resourceName");
160             }
161             if (controlLoopPolicy.getControlLoop().getResources() == null) {
162                 controlLoopPolicy.getControlLoop().setResources(new LinkedList<>());
163             }
164             controlLoopPolicy.getControlLoop().getResources().add(resource);
165         }
166         return this;
167     }
168
169     @Override
170     public ControlLoopPolicyBuilder setPnf(Pnf pnf) throws BuilderException {
171         if (pnf == null) {
172             throw new BuilderException("PNF must not be null");
173         }
174         if (pnf.getPnfName() == null && pnf.getEquipType() == null) {
175             throw new BuilderException("Invalid PNF - need either pnfName or pnfType");
176         }
177         controlLoopPolicy.getControlLoop().setPnf(pnf);
178         return this;
179     }
180
181     @Override
182     public ControlLoopPolicyBuilder setAbatement(Boolean abatement) throws BuilderException {
183         if (abatement == null) {
184             throw new BuilderException("abatement must not be null");
185         }
186         controlLoopPolicy.getControlLoop().setAbatement(abatement);
187         return this;
188     }
189
190     @Override
191     public ControlLoopPolicyBuilder setTimeout(Integer timeout) {
192         controlLoopPolicy.getControlLoop().setTimeout(timeout);
193         return this;
194     }
195
196     @Override
197     public Policy setTriggerPolicy(PolicyParam policyParam) throws BuilderException {
198
199         Policy trigger = new Policy(policyParam);
200
201         controlLoopPolicy.getControlLoop().setTrigger_policy(trigger.getId());
202
203         this.addNewPolicy(trigger);
204         //
205         // Return a copy of the policy
206         //
207         return new Policy(trigger);
208     }
209
210     @Override
211     public ControlLoop setExistingTriggerPolicy(String id) throws BuilderException {
212         if (id == null) {
213             throw new BuilderException("Id must not be null");
214         }
215         Policy trigger = this.findPolicy(id);
216         if (trigger == null) {
217             throw new BuilderException(UNKNOWN_POLICY + id);
218         } else {
219             this.controlLoopPolicy.getControlLoop().setTrigger_policy(id);
220         }
221         return new ControlLoop(this.controlLoopPolicy.getControlLoop());
222     }
223
224     @Override
225     public Policy setPolicyForPolicyResult(PolicyParam policyParam, PolicyResult... results) throws BuilderException {
226         //
227         // Find the existing policy
228         //
229         Policy existingPolicy = this.findPolicy(policyParam.getId());
230         if (existingPolicy == null) {
231             throw new BuilderException(UNKNOWN_POLICY + policyParam.getId());
232         }
233         //
234         // Create the new Policy
235         //
236         // @formatter:off
237         Policy newPolicy = new Policy(PolicyParam.builder()
238             .id(UUID.randomUUID().toString())
239             .name(policyParam.getName())
240             .description(policyParam.getDescription())
241             .actor(policyParam.getActor())
242             .payload(policyParam.getPayload())
243             .target(policyParam.getTarget())
244             .recipe(policyParam.getRecipe())
245             .retries(policyParam.getRetries())
246             .timeout(policyParam.getTimeout())
247             .build());
248         // @formatter:on
249         //
250         // Connect the results
251         //
252         for (PolicyResult result : results) {
253             switch (result) {
254                 case FAILURE:
255                     existingPolicy.setFailure(newPolicy.getId());
256                     break;
257                 case FAILURE_EXCEPTION:
258                     existingPolicy.setFailure_exception(newPolicy.getId());
259                     break;
260                 case FAILURE_RETRIES:
261                     existingPolicy.setFailure_retries(newPolicy.getId());
262                     break;
263                 case FAILURE_TIMEOUT:
264                     existingPolicy.setFailure_timeout(newPolicy.getId());
265                     break;
266                 case FAILURE_GUARD:
267                     existingPolicy.setFailure_guard(newPolicy.getId());
268                     break;
269                 case SUCCESS:
270                     existingPolicy.setSuccess(newPolicy.getId());
271                     break;
272                 default:
273                     throw new BuilderException("Invalid PolicyResult " + result);
274             }
275         }
276         //
277         // Add it to our list
278         //
279         this.controlLoopPolicy.getPolicies().add(newPolicy);
280         //
281         // Return a policy to them
282         //
283         return new Policy(newPolicy);
284     }
285
286     @Override
287     public Policy setPolicyForPolicyResult(String policyResultId, String policyId, PolicyResult... results)
288         throws BuilderException {
289         //
290         // Find the existing policy
291         //
292         Policy existingPolicy = this.findPolicy(policyId);
293         if (existingPolicy == null) {
294             throw new BuilderException(policyId + " does not exist");
295         }
296         if (this.findPolicy(policyResultId) == null) {
297             throw new BuilderException("Operational policy " + policyResultId + " does not exist");
298         }
299         //
300         // Connect the results
301         //
302         for (PolicyResult result : results) {
303             switch (result) {
304                 case FAILURE:
305                     existingPolicy.setFailure(policyResultId);
306                     break;
307                 case FAILURE_EXCEPTION:
308                     existingPolicy.setFailure_exception(policyResultId);
309                     break;
310                 case FAILURE_RETRIES:
311                     existingPolicy.setFailure_retries(policyResultId);
312                     break;
313                 case FAILURE_TIMEOUT:
314                     existingPolicy.setFailure_timeout(policyResultId);
315                     break;
316                 case FAILURE_GUARD:
317                     existingPolicy.setFailure_guard(policyResultId);
318                     break;
319                 case SUCCESS:
320                     existingPolicy.setSuccess(policyResultId);
321                     break;
322                 default:
323                     throw new BuilderException("Invalid PolicyResult " + result);
324             }
325         }
326         return new Policy(this.findPolicy(policyResultId));
327     }
328
329     private class BuilderCompilerCallback implements ControlLoopCompilerCallback {
330
331         private ResultsImpl results = new ResultsImpl();
332
333         @Override
334         public boolean onWarning(String message) {
335             results.addMessage(new MessageImpl(message, MessageLevel.WARNING));
336             return false;
337         }
338
339         @Override
340         public boolean onError(String message) {
341             results.addMessage(new MessageImpl(message, MessageLevel.ERROR));
342             return false;
343         }
344     }
345
346     @Override
347     public Results buildSpecification() {
348         //
349         // Dump the specification
350         //
351         DumperOptions options = new DumperOptions();
352         options.setDefaultFlowStyle(FlowStyle.BLOCK);
353         options.setPrettyFlow(true);
354         Yaml yaml = new Yaml(options);
355         String dumpedYaml = yaml.dump(controlLoopPolicy);
356         //
357         // This is our callback class for our compiler
358         //
359         BuilderCompilerCallback callback = new BuilderCompilerCallback();
360         //
361         // Compile it
362         //
363         try {
364             ControlLoopCompiler.compile(controlLoopPolicy, callback);
365         } catch (CompilerException e) {
366             callback.results.addMessage(new MessageImpl(e.getMessage(), MessageLevel.EXCEPTION));
367         }
368         //
369         // Save the spec
370         //
371         callback.results.setSpecification(dumpedYaml);
372         return callback.results;
373     }
374
375     private void addNewPolicy(Policy policy) {
376         if (this.controlLoopPolicy.getPolicies() == null) {
377             this.controlLoopPolicy.setPolicies(new LinkedList<>());
378         }
379         this.controlLoopPolicy.getPolicies().add(policy);
380     }
381
382     private Policy findPolicy(String id) {
383         if (this.controlLoopPolicy.getPolicies() != null) {
384             for (Policy policy : this.controlLoopPolicy.getPolicies()) {
385                 if (policy.getId().equals(id)) {
386                     return policy;
387                 }
388             }
389         }
390         return null;
391     }
392
393     @Override
394     public ControlLoopPolicyBuilder removeResource(Resource... resources) throws BuilderException {
395         if (controlLoopPolicy.getControlLoop().getResources() == null) {
396             throw new BuilderException("No existing resources to remove");
397         }
398         for (Resource resource : resources) {
399             if (resource == null) {
400                 throw new BuilderException("Resource must not be null");
401             }
402             if (resource.getResourceUuid() == null && Strings.isNullOrEmpty(resource.getResourceName())) {
403                 throw new BuilderException("Invalid resource - need either a resourceUUID or resourceName");
404             }
405             boolean removed = controlLoopPolicy.getControlLoop().getResources().remove(resource);
406             if (!removed) {
407                 throw new BuilderException("Unknown resource " + resource.getResourceName());
408             }
409         }
410         return this;
411     }
412
413     @Override
414     public ControlLoopPolicyBuilder removeAllResources() throws BuilderException {
415         controlLoopPolicy.getControlLoop().getResources().clear();
416         return this;
417     }
418
419     @Override
420     public Integer calculateTimeout() {
421         int sum = 0;
422         for (Policy policy : this.controlLoopPolicy.getPolicies()) {
423             sum += policy.getTimeout().intValue();
424         }
425         return Integer.valueOf(sum);
426     }
427
428     @Override
429     public boolean isOpenLoop() {
430         return this.controlLoopPolicy.getControlLoop().getTrigger_policy()
431             .equals(FinalResult.FINAL_OPENLOOP.toString());
432     }
433
434     @Override
435     public Policy getTriggerPolicy() throws BuilderException {
436         if (this.controlLoopPolicy.getControlLoop().getTrigger_policy().equals(FinalResult.FINAL_OPENLOOP.toString())) {
437             return null;
438         } else {
439             return new Policy(this.findPolicy(this.controlLoopPolicy.getControlLoop().getTrigger_policy()));
440         }
441     }
442
443     @Override
444     public ControlLoop getControlLoop() {
445         return new ControlLoop(this.controlLoopPolicy.getControlLoop());
446     }
447
448     @Override
449     public boolean removePolicy(String policyId) throws BuilderException {
450         Policy existingPolicy = this.findPolicy(policyId);
451         if (existingPolicy == null) {
452             throw new BuilderException(UNKNOWN_POLICY + policyId);
453         }
454         //
455         // Check if the policy to remove is trigger_policy
456         //
457         if (this.controlLoopPolicy.getControlLoop().getTrigger_policy().equals(policyId)) {
458             this.controlLoopPolicy.getControlLoop().setTrigger_policy(FinalResult.FINAL_OPENLOOP.toString());
459         } else {
460             updateChainedPoliciesForPolicyRemoval(policyId);
461         }
462         //
463         // remove the policy
464         //
465         return this.controlLoopPolicy.getPolicies().remove(existingPolicy);
466     }
467
468     private void updateChainedPoliciesForPolicyRemoval(String idOfPolicyBeingRemoved) {
469         for (Policy policy : this.controlLoopPolicy.getPolicies()) {
470             final int index = this.controlLoopPolicy.getPolicies().indexOf(policy);
471             if (policy.getSuccess().equals(idOfPolicyBeingRemoved)) {
472                 policy.setSuccess(FinalResult.FINAL_SUCCESS.toString());
473             }
474             if (policy.getFailure().equals(idOfPolicyBeingRemoved)) {
475                 policy.setFailure(FinalResult.FINAL_FAILURE.toString());
476             }
477             if (policy.getFailure_retries().equals(idOfPolicyBeingRemoved)) {
478                 policy.setFailure_retries(FinalResult.FINAL_FAILURE_RETRIES.toString());
479             }
480             if (policy.getFailure_timeout().equals(idOfPolicyBeingRemoved)) {
481                 policy.setFailure_timeout(FinalResult.FINAL_FAILURE_TIMEOUT.toString());
482             }
483             if (policy.getFailure_exception().equals(idOfPolicyBeingRemoved)) {
484                 policy.setFailure_exception(FinalResult.FINAL_FAILURE_EXCEPTION.toString());
485             }
486             if (policy.getFailure_guard().equals(idOfPolicyBeingRemoved)) {
487                 policy.setFailure_guard(FinalResult.FINAL_FAILURE_GUARD.toString());
488             }
489             this.controlLoopPolicy.getPolicies().set(index, policy);
490         }
491     }
492
493     @Override
494     public Policy resetPolicyResults(String policyId) throws BuilderException {
495         Policy existingPolicy = this.findPolicy(policyId);
496         if (existingPolicy == null) {
497             throw new BuilderException(UNKNOWN_POLICY + policyId);
498         }
499         //
500         // reset policy results
501         //
502         existingPolicy.setSuccess(FinalResult.FINAL_SUCCESS.toString());
503         existingPolicy.setFailure(FinalResult.FINAL_FAILURE.toString());
504         existingPolicy.setFailure_retries(FinalResult.FINAL_FAILURE_RETRIES.toString());
505         existingPolicy.setFailure_timeout(FinalResult.FINAL_FAILURE_TIMEOUT.toString());
506         existingPolicy.setFailure_exception(FinalResult.FINAL_FAILURE_EXCEPTION.toString());
507         existingPolicy.setFailure_guard(FinalResult.FINAL_FAILURE_GUARD.toString());
508         return new Policy(existingPolicy);
509     }
510
511     @Override
512     public ControlLoopPolicyBuilder removeAllPolicies() {
513         //
514         // Remove all existing operational policies
515         //
516         this.controlLoopPolicy.getPolicies().clear();
517         //
518         // Revert controlLoop back to an open loop
519         //
520         this.controlLoopPolicy.getControlLoop().setTrigger_policy(FinalResult.FINAL_OPENLOOP.toString());
521         return this;
522     }
523
524     @Override
525     public Policy addOperationsAccumulateParams(String policyId, OperationsAccumulateParams operationsAccumulateParams)
526         throws BuilderException {
527         Policy existingPolicy = this.findPolicy(policyId);
528         if (existingPolicy == null) {
529             throw new BuilderException(UNKNOWN_POLICY + policyId);
530         }
531         //
532         // Add operationsAccumulateParams to existingPolicy
533         //
534         existingPolicy.setOperationsAccumulateParams(operationsAccumulateParams);
535         return new Policy(existingPolicy);
536     }
537
538 }