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