1011f620c4215379b7c3339493a834cc08a9e4c4
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2021 Nordix Foundation.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.clamp.controlloop.runtime.instantiation;
22
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.function.UnaryOperator;
28 import java.util.stream.Collectors;
29 import javax.ws.rs.core.Response;
30 import javax.ws.rs.core.Response.Status;
31 import lombok.AllArgsConstructor;
32 import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException;
33 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
34 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
35 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
36 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops;
37 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
38 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand;
39 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationResponse;
40 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
41 import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler;
42 import org.onap.policy.common.parameters.BeanValidationResult;
43 import org.onap.policy.common.parameters.ObjectValidationResult;
44 import org.onap.policy.common.parameters.ValidationResult;
45 import org.onap.policy.common.parameters.ValidationStatus;
46 import org.onap.policy.models.base.PfModelException;
47 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
48 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
49 import org.springframework.stereotype.Component;
50
51 /**
52  * This class is dedicated to the Instantiation of Commissioned control loop.
53  */
54 @Component
55 @AllArgsConstructor
56 public class ControlLoopInstantiationProvider {
57     private final ControlLoopProvider controlLoopProvider;
58     private final CommissioningProvider commissioningProvider;
59     private final SupervisionHandler supervisionHandler;
60
61     private static final Object lockit = new Object();
62
63     /**
64      * Create control loops.
65      *
66      * @param controlLoops the control loop
67      * @return the result of the instantiation operation
68      * @throws PfModelException on creation errors
69      */
70     public InstantiationResponse createControlLoops(ControlLoops controlLoops) throws PfModelException {
71
72         synchronized (lockit) {
73             for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
74                 var checkControlLoop = controlLoopProvider.getControlLoop(controlLoop.getKey().asIdentifier());
75                 if (checkControlLoop != null) {
76                     throw new PfModelException(Response.Status.BAD_REQUEST,
77                             controlLoop.getKey().asIdentifier() + " already defined");
78                 }
79             }
80             BeanValidationResult validationResult = validateControlLoops(controlLoops);
81             if (!validationResult.isValid()) {
82                 throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
83             }
84             controlLoopProvider.createControlLoops(controlLoops.getControlLoopList());
85         }
86
87         var response = new InstantiationResponse();
88         response.setAffectedControlLoops(controlLoops.getControlLoopList().stream()
89                 .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList()));
90
91         return response;
92     }
93
94     /**
95      * Update control loops.
96      *
97      * @param controlLoops the control loop
98      * @return the result of the instantiation operation
99      * @throws PfModelException on update errors
100      */
101     public InstantiationResponse updateControlLoops(ControlLoops controlLoops) throws PfModelException {
102         synchronized (lockit) {
103             BeanValidationResult validationResult = validateControlLoops(controlLoops);
104             if (!validationResult.isValid()) {
105                 throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
106             }
107             controlLoopProvider.updateControlLoops(controlLoops.getControlLoopList());
108         }
109
110         var response = new InstantiationResponse();
111         response.setAffectedControlLoops(controlLoops.getControlLoopList().stream()
112                 .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList()));
113
114         return response;
115     }
116
117     /**
118      * Validate ControlLoops.
119      *
120      * @param controlLoops ControlLoops to validate
121      * @return the result of validation
122      * @throws PfModelException if controlLoops is not valid
123      */
124     private BeanValidationResult validateControlLoops(ControlLoops controlLoops) throws PfModelException {
125
126         var result = new BeanValidationResult("ControlLoops", controlLoops);
127
128         for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
129             var subResult = new BeanValidationResult("entry " + controlLoop.getDefinition().getName(), controlLoop);
130
131             List<ToscaNodeTemplate> toscaNodeTemplates = commissioningProvider.getControlLoopDefinitions(
132                     controlLoop.getDefinition().getName(), controlLoop.getDefinition().getVersion());
133
134             if (toscaNodeTemplates.isEmpty()) {
135                 subResult.addResult(new ObjectValidationResult("ControlLoop", controlLoop.getDefinition().getName(),
136                         ValidationStatus.INVALID, "Commissioned control loop definition not FOUND"));
137             } else if (toscaNodeTemplates.size() > 1) {
138                 subResult.addResult(new ObjectValidationResult("ControlLoop", controlLoop.getDefinition().getName(),
139                         ValidationStatus.INVALID, "Commissioned control loop definition not VALID"));
140             } else {
141
142                 List<ToscaNodeTemplate> clElementDefinitions =
143                         commissioningProvider.getControlLoopElementDefinitions(toscaNodeTemplates.get(0));
144
145                 // @formatter:off
146                 Map<String, ToscaConceptIdentifier> definitions = clElementDefinitions
147                         .stream()
148                         .map(nodeTemplate -> nodeTemplate.getKey().asIdentifier())
149                         .collect(Collectors.toMap(ToscaConceptIdentifier::getName, UnaryOperator.identity()));
150                 // @formatter:on
151
152                 for (ControlLoopElement element : controlLoop.getElements().values()) {
153                     subResult.addResult(validateDefinition(definitions, element.getDefinition()));
154                 }
155             }
156             result.addResult(subResult);
157         }
158         return result;
159     }
160
161     /**
162      * Validate ToscaConceptIdentifier, checking if exist in ToscaConceptIdentifiers map.
163      *
164      * @param definitions map of all ToscaConceptIdentifiers
165      * @param definition ToscaConceptIdentifier to validate
166      * @return the validation result
167      */
168     private ValidationResult validateDefinition(Map<String, ToscaConceptIdentifier> definitions,
169             ToscaConceptIdentifier definition) {
170         var result = new BeanValidationResult("entry " + definition.getName(), definition);
171         ToscaConceptIdentifier identifier = definitions.get(definition.getName());
172         if (identifier == null) {
173             result.setResult(ValidationStatus.INVALID, "Not FOUND");
174         } else if (!identifier.equals(definition)) {
175             result.setResult(ValidationStatus.INVALID, "Version not matching");
176         }
177         return (result.isClean() ? null : result);
178     }
179
180     /**
181      * Delete the control loop with the given name and version.
182      *
183      * @param name the name of the control loop to delete
184      * @param version the version of the control loop to delete
185      * @return the result of the deletion
186      * @throws PfModelException on deletion errors
187      */
188     public InstantiationResponse deleteControlLoop(String name, String version) throws PfModelException {
189         var response = new InstantiationResponse();
190         synchronized (lockit) {
191             List<ControlLoop> controlLoops = controlLoopProvider.getControlLoops(name, version);
192             if (controlLoops.isEmpty()) {
193                 throw new PfModelException(Response.Status.NOT_FOUND, "Control Loop not found");
194             }
195             for (ControlLoop controlLoop : controlLoops) {
196                 if (!ControlLoopState.UNINITIALISED.equals(controlLoop.getState())) {
197                     throw new PfModelException(Response.Status.BAD_REQUEST,
198                             "Control Loop State is still " + controlLoop.getState());
199                 }
200             }
201
202             response.setAffectedControlLoops(Collections
203                     .singletonList(controlLoopProvider.deleteControlLoop(name, version).getKey().asIdentifier()));
204         }
205         return response;
206     }
207
208     /**
209      * Get the requested control loops.
210      *
211      * @param name the name of the control loop to get, null for all control loops
212      * @param version the version of the control loop to get, null for all control loops
213      * @return the control loops
214      * @throws PfModelException on errors getting control loops
215      */
216     public ControlLoops getControlLoops(String name, String version) throws PfModelException {
217         var controlLoops = new ControlLoops();
218         controlLoops.setControlLoopList(controlLoopProvider.getControlLoops(name, version));
219
220         return controlLoops;
221     }
222
223     /**
224      * Issue a command to control loops, setting their ordered state.
225      *
226      * @param command the command to issue to control loops
227      * @return the result of the initiation command
228      * @throws PfModelException on errors setting the ordered state on the control loops
229      * @throws ControlLoopException on ordered state invalid
230      */
231     public InstantiationResponse issueControlLoopCommand(InstantiationCommand command)
232             throws ControlLoopException, PfModelException {
233
234         if (command.getOrderedState() == null) {
235             throw new ControlLoopException(Status.BAD_REQUEST, "ordered state invalid or not specified on command");
236         }
237
238         synchronized (lockit) {
239             List<ControlLoop> controlLoops = new ArrayList<>(command.getControlLoopIdentifierList().size());
240             for (ToscaConceptIdentifier id : command.getControlLoopIdentifierList()) {
241                 var controlLoop = controlLoopProvider.getControlLoop(id);
242                 controlLoop.setCascadedOrderedState(command.getOrderedState());
243                 controlLoops.add(controlLoop);
244             }
245             controlLoopProvider.updateControlLoops(controlLoops);
246         }
247
248         supervisionHandler.triggerControlLoopSupervision(command.getControlLoopIdentifierList());
249         var response = new InstantiationResponse();
250         response.setAffectedControlLoops(command.getControlLoopIdentifierList());
251
252         return response;
253     }
254 }