77bcb19efad41617dc1f868da41619659abecd7e
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2023-2024 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.acm.participant.intermediary.handler;
22
23 import java.util.List;
24 import java.util.Map;
25 import java.util.UUID;
26 import lombok.RequiredArgsConstructor;
27 import org.onap.policy.clamp.acm.participant.intermediary.comm.ParticipantMessagePublisher;
28 import org.onap.policy.clamp.models.acm.concepts.AcElementDeployAck;
29 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
30 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
31 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
32 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
33 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementInfo;
34 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionInfo;
35 import org.onap.policy.clamp.models.acm.concepts.DeployState;
36 import org.onap.policy.clamp.models.acm.concepts.LockState;
37 import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition;
38 import org.onap.policy.clamp.models.acm.concepts.ParticipantState;
39 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
40 import org.onap.policy.clamp.models.acm.concepts.SubState;
41 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck;
42 import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantMessageType;
43 import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrimeAck;
44 import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantStatus;
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.stereotype.Component;
49
50 @Component
51 @RequiredArgsConstructor
52 public class AutomationCompositionOutHandler {
53     private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionOutHandler.class);
54
55     private final ParticipantMessagePublisher publisher;
56     private final CacheProvider cacheProvider;
57
58     /**
59      * Handle a automation composition element stage change message.
60      *
61      * @param instance the automationComposition Id
62      * @param elementId the automationComposition Element Id
63      * @param stage the next stage
64      * @param message the message
65      * @param stateChangeResult the indicator if error occurs
66      */
67     public void updateAutomationCompositionElementStage(UUID instance, UUID elementId,
68         StateChangeResult stateChangeResult, int stage, String message) {
69
70         if (instance == null || elementId == null) {
71             LOGGER.error("Cannot update Automation composition element stage, id is null");
72             return;
73         }
74
75         var automationComposition = cacheProvider.getAutomationComposition(instance);
76         if (automationComposition == null) {
77             LOGGER.error("Cannot update Automation composition element stage, Automation composition id {} not present",
78                 instance);
79             return;
80         }
81
82         var element = automationComposition.getElements().get(elementId);
83         if (element == null) {
84             var msg = "Cannot update Automation composition element stage, AC Element id {} not present";
85             LOGGER.error(msg, elementId);
86             return;
87         }
88
89         element.setRestarting(null);
90
91         var automationCompositionStateChangeAck =
92             new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK);
93         automationCompositionStateChangeAck.setParticipantId(cacheProvider.getParticipantId());
94         automationCompositionStateChangeAck.setMessage(message);
95         automationCompositionStateChangeAck.setResponseTo(cacheProvider.getMsgIdentification().get(element.getId()));
96         automationCompositionStateChangeAck.setStateChangeResult(stateChangeResult);
97         automationCompositionStateChangeAck.setStage(stage);
98         automationCompositionStateChangeAck.setAutomationCompositionId(instance);
99         automationCompositionStateChangeAck.getAutomationCompositionResultMap().put(element.getId(),
100             new AcElementDeployAck(element.getDeployState(), element.getLockState(), element.getOperationalState(),
101                 element.getUseState(), element.getOutProperties(), true, message));
102         LOGGER.debug("Automation composition element {} stage changed to {}", elementId, stage);
103         automationCompositionStateChangeAck.setResult(true);
104         publisher.sendAutomationCompositionAck(automationCompositionStateChangeAck);
105         cacheProvider.getMsgIdentification().remove(element.getId());
106     }
107
108     /**
109      * Handle a automation composition element state change message.
110      *
111      * @param instance the automationComposition Id
112      * @param elementId the automationComposition Element Id
113      * @param deployState the DeployState state
114      * @param lockState the LockState state
115      * @param message the message
116      * @param stateChangeResult the indicator if error occurs
117      */
118     public void updateAutomationCompositionElementState(UUID instance, UUID elementId,
119             DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message) {
120
121         if (instance == null || elementId == null) {
122             LOGGER.error("Cannot update Automation composition element state, id is null");
123             return;
124         }
125
126         var automationComposition = cacheProvider.getAutomationComposition(instance);
127         if (automationComposition == null) {
128             LOGGER.error("Cannot update Automation composition element state, Automation composition id {} not present",
129                 instance);
130             return;
131         }
132
133         var element = automationComposition.getElements().get(elementId);
134         if (element == null) {
135             var msg = "Cannot update Automation composition element state, AC Element id {} not present";
136             LOGGER.error(msg, elementId);
137             return;
138         }
139
140         if ((element.getRestarting() == null)
141                 && ((deployState != null && lockState != null) || (deployState == null && lockState == null))) {
142             LOGGER.error("state error {} and {} cannot be handled", deployState, lockState);
143             return;
144         }
145         element.setRestarting(null);
146
147         if (deployState != null && !SubState.NONE.equals(element.getSubState())) {
148             handleSubState(automationComposition, element);
149             if (!StateChangeResult.NO_ERROR.equals(stateChangeResult)) {
150                 stateChangeResult = StateChangeResult.NO_ERROR;
151                 LOGGER.warn("SubState has always NO_ERROR result!");
152             }
153         } else if (deployState != null) {
154             handleDeployState(automationComposition, element, deployState);
155         }
156         if (lockState != null) {
157             handleLockState(automationComposition, element, lockState);
158         }
159
160         var automationCompositionStateChangeAck =
161                 new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK);
162         automationCompositionStateChangeAck.setParticipantId(cacheProvider.getParticipantId());
163         automationCompositionStateChangeAck.setReplicaId(cacheProvider.getReplicaId());
164         automationCompositionStateChangeAck.setMessage(message);
165         automationCompositionStateChangeAck.setResponseTo(cacheProvider.getMsgIdentification().get(element.getId()));
166         automationCompositionStateChangeAck.setStateChangeResult(stateChangeResult);
167         automationCompositionStateChangeAck.setAutomationCompositionId(instance);
168         automationCompositionStateChangeAck.getAutomationCompositionResultMap().put(element.getId(),
169                 new AcElementDeployAck(element.getDeployState(), element.getLockState(), element.getOperationalState(),
170                         element.getUseState(), element.getOutProperties(), true, message));
171         LOGGER.debug("Automation composition element {} state changed to {}", elementId, deployState);
172         automationCompositionStateChangeAck.setResult(true);
173         publisher.sendAutomationCompositionAck(automationCompositionStateChangeAck);
174         cacheProvider.getMsgIdentification().remove(element.getId());
175     }
176
177     private void handleDeployState(AutomationComposition automationComposition, AutomationCompositionElement element,
178             DeployState deployState) {
179         element.setDeployState(deployState);
180         element.setLockState(DeployState.DEPLOYED.equals(element.getDeployState()) ? LockState.LOCKED : LockState.NONE);
181         var checkOpt = automationComposition.getElements().values().stream()
182                 .filter(acElement -> !deployState.equals(acElement.getDeployState())).findAny();
183         if (checkOpt.isEmpty()) {
184             if (DeployState.DEPLOYED.equals(automationComposition.getDeployState())
185                     && automationComposition.getCompositionTargetId() != null) {
186                 // migration scenario
187                 automationComposition.setCompositionId(automationComposition.getCompositionTargetId());
188                 automationComposition.setCompositionTargetId(null);
189             }
190             automationComposition.setDeployState(deployState);
191             automationComposition.setLockState(element.getLockState());
192             automationComposition.setSubState(SubState.NONE);
193
194             if (DeployState.DELETED.equals(deployState)) {
195                 cacheProvider.removeAutomationComposition(automationComposition.getInstanceId());
196             }
197         }
198     }
199
200     private void handleLockState(AutomationComposition automationComposition, AutomationCompositionElement element,
201             LockState lockState) {
202         element.setLockState(lockState);
203         var checkOpt = automationComposition.getElements().values().stream()
204                 .filter(acElement -> !lockState.equals(acElement.getLockState())).findAny();
205         if (checkOpt.isEmpty()) {
206             automationComposition.setLockState(lockState);
207             automationComposition.setSubState(SubState.NONE);
208         }
209     }
210
211     private void handleSubState(AutomationComposition automationComposition, AutomationCompositionElement element) {
212         element.setSubState(SubState.NONE);
213         var checkOpt = automationComposition.getElements().values().stream()
214                 .filter(acElement -> !SubState.NONE.equals(acElement.getSubState())).findAny();
215         if (checkOpt.isEmpty()) {
216             automationComposition.setSubState(SubState.NONE);
217         }
218     }
219
220     /**
221      * Send Ac Element Info.
222      *
223      * @param automationCompositionId the automationComposition Id
224      * @param elementId the automationComposition Element id
225      * @param useState the use State
226      * @param operationalState the operational State
227      * @param outProperties the output Properties Map
228      */
229     public void sendAcElementInfo(UUID automationCompositionId, UUID elementId, String useState,
230             String operationalState, Map<String, Object> outProperties) {
231
232         if (automationCompositionId == null || elementId == null) {
233             LOGGER.error("Cannot update Automation composition element state, id is null");
234             return;
235         }
236
237         var automationComposition = cacheProvider.getAutomationComposition(automationCompositionId);
238         if (automationComposition == null) {
239             LOGGER.error("Cannot update Automation composition element state, Automation composition id {} not present",
240                     automationCompositionId);
241             return;
242         }
243
244         var element = automationComposition.getElements().get(elementId);
245         if (element == null) {
246             var msg = "Cannot update Automation composition element state, AC Element id {} not present";
247             LOGGER.error(msg, elementId);
248             return;
249         }
250         element.setOperationalState(operationalState);
251         element.setUseState(useState);
252         element.setOutProperties(outProperties);
253
254         var acInfo = new AutomationCompositionInfo();
255         acInfo.setAutomationCompositionId(automationCompositionId);
256         acInfo.setDeployState(automationComposition.getDeployState());
257         acInfo.setLockState(automationComposition.getLockState());
258         acInfo.setElements(List.of(getAutomationCompositionElementInfo(element)));
259         var statusMsg = createParticipantStatus();
260         statusMsg.setCompositionId(automationComposition.getCompositionId());
261         statusMsg.setAutomationCompositionInfoList(List.of(acInfo));
262         publisher.sendParticipantStatus(statusMsg);
263     }
264
265     /**
266      * Get AutomationCompositionElementInfo from AutomationCompositionElement.
267      *
268      * @param element the AutomationCompositionElement
269      * @return the AutomationCompositionElementInfo
270      */
271     public AutomationCompositionElementInfo getAutomationCompositionElementInfo(AutomationCompositionElement element) {
272         var elementInfo = new AutomationCompositionElementInfo();
273         elementInfo.setAutomationCompositionElementId(element.getId());
274         elementInfo.setDeployState(element.getDeployState());
275         elementInfo.setLockState(element.getLockState());
276         elementInfo.setOperationalState(element.getOperationalState());
277         elementInfo.setUseState(element.getUseState());
278         elementInfo.setOutProperties(element.getOutProperties());
279         return elementInfo;
280     }
281
282     /**
283      * Update Composition State for prime and deprime.
284      *
285      * @param compositionId the composition id
286      * @param state the Composition State
287      * @param stateChangeResult the indicator if error occurs
288      * @param message the message
289      */
290     public void updateCompositionState(UUID compositionId, AcTypeState state, StateChangeResult stateChangeResult,
291             String message) {
292         var participantPrimeAck = new ParticipantPrimeAck();
293         participantPrimeAck.setCompositionId(compositionId);
294         participantPrimeAck.setMessage(message);
295         participantPrimeAck.setResult(true);
296         participantPrimeAck.setResponseTo(cacheProvider.getMsgIdentification().get(compositionId));
297         participantPrimeAck.setCompositionState(state);
298         participantPrimeAck.setStateChangeResult(stateChangeResult);
299         participantPrimeAck.setParticipantId(cacheProvider.getParticipantId());
300         participantPrimeAck.setReplicaId(cacheProvider.getReplicaId());
301         participantPrimeAck.setState(ParticipantState.ON_LINE);
302         publisher.sendParticipantPrimeAck(participantPrimeAck);
303         cacheProvider.getMsgIdentification().remove(compositionId);
304         if (AcTypeState.COMMISSIONED.equals(state) && StateChangeResult.NO_ERROR.equals(stateChangeResult)) {
305             cacheProvider.removeElementDefinition(compositionId);
306         }
307     }
308
309     /**
310      * Send Composition Definition Info.
311      *
312      * @param compositionId the composition id
313      * @param elementId the Composition Definition Element id
314      * @param outProperties the output Properties Map
315      */
316     public void sendAcDefinitionInfo(UUID compositionId, ToscaConceptIdentifier elementId,
317             Map<String, Object> outProperties) {
318         if (compositionId == null) {
319             LOGGER.error("Cannot send Composition outProperties, id is null");
320             return;
321         }
322         var statusMsg = createParticipantStatus();
323         statusMsg.setCompositionId(compositionId);
324         var acElementDefsMap = cacheProvider.getAcElementsDefinitions();
325         var acElementsDefinitions = acElementDefsMap.get(compositionId);
326         if (acElementsDefinitions == null) {
327             LOGGER.error("Cannot send Composition outProperties, id {} is null", compositionId);
328             return;
329         }
330         var acElementDefinition = getAutomationCompositionElementDefinition(acElementsDefinitions, elementId);
331         if (acElementDefinition == null) {
332             LOGGER.error("Cannot send Composition outProperties, elementId {} not present", elementId);
333             return;
334         }
335         acElementDefinition.setOutProperties(outProperties);
336         var participantDefinition = new ParticipantDefinition();
337         participantDefinition.setParticipantId(cacheProvider.getParticipantId());
338         participantDefinition.setAutomationCompositionElementDefinitionList(List.of(acElementDefinition));
339         statusMsg.setParticipantDefinitionUpdates(List.of(participantDefinition));
340         publisher.sendParticipantStatus(statusMsg);
341     }
342
343     private AutomationCompositionElementDefinition getAutomationCompositionElementDefinition(
344             Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> acElementsDefinition,
345             ToscaConceptIdentifier elementId) {
346
347         if (elementId == null) {
348             if (acElementsDefinition.size() == 1) {
349                 return acElementsDefinition.values().iterator().next();
350             }
351             return null;
352         }
353         return acElementsDefinition.get(elementId);
354     }
355
356     private ParticipantStatus createParticipantStatus() {
357         var statusMsg = new ParticipantStatus();
358         statusMsg.setParticipantId(cacheProvider.getParticipantId());
359         statusMsg.setReplicaId(cacheProvider.getReplicaId());
360         statusMsg.setState(ParticipantState.ON_LINE);
361         statusMsg.setParticipantSupportedElementType(cacheProvider.getSupportedAcElementTypes());
362         return statusMsg;
363     }
364 }