06b11bbca3201338546f699b452aed7c5cf919e6
[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 state change message.
60      *
61      * @param automationCompositionId the automationComposition Id
62      * @param elementId the automationComposition Element Id
63      * @param deployState the DeployState state
64      * @param lockState the LockState state
65      * @param message the message
66      * @param stateChangeResult the indicator if error occurs
67      */
68     public void updateAutomationCompositionElementState(UUID automationCompositionId, UUID elementId,
69             DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message) {
70
71         if (automationCompositionId == null || elementId == null) {
72             LOGGER.error("Cannot update Automation composition element state, id is null");
73             return;
74         }
75
76         var automationComposition = cacheProvider.getAutomationComposition(automationCompositionId);
77         if (automationComposition == null) {
78             LOGGER.error("Cannot update Automation composition element state, Automation composition id {} not present",
79                     automationCompositionId);
80             return;
81         }
82
83         var element = automationComposition.getElements().get(elementId);
84         if (element == null) {
85             var msg = "Cannot update Automation composition element state, AC Element id {} not present";
86             LOGGER.error(msg, elementId);
87             return;
88         }
89
90         if ((element.getRestarting() == null)
91                 && ((deployState != null && lockState != null) || (deployState == null && lockState == null))) {
92             LOGGER.error("state error {} and {} cannot be handled", deployState, lockState);
93             return;
94         }
95         element.setRestarting(null);
96
97         if (deployState != null && !SubState.NONE.equals(element.getSubState())) {
98             handleSubState(automationComposition, element);
99             if (!StateChangeResult.NO_ERROR.equals(stateChangeResult)) {
100                 stateChangeResult = StateChangeResult.NO_ERROR;
101                 LOGGER.warn("SubState has always NO_ERROR result!");
102             }
103         } else if (deployState != null) {
104             handleDeployState(automationComposition, element, deployState);
105         }
106         if (lockState != null) {
107             handleLockState(automationComposition, element, lockState);
108         }
109
110         var automationCompositionStateChangeAck =
111                 new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK);
112         automationCompositionStateChangeAck.setParticipantId(cacheProvider.getParticipantId());
113         automationCompositionStateChangeAck.setReplicaId(cacheProvider.getReplicaId());
114         automationCompositionStateChangeAck.setMessage(message);
115         automationCompositionStateChangeAck.setResponseTo(cacheProvider.getMsgIdentification().get(element.getId()));
116         automationCompositionStateChangeAck.setStateChangeResult(stateChangeResult);
117         automationCompositionStateChangeAck.setAutomationCompositionId(automationCompositionId);
118         automationCompositionStateChangeAck.getAutomationCompositionResultMap().put(element.getId(),
119                 new AcElementDeployAck(element.getDeployState(), element.getLockState(), element.getOperationalState(),
120                         element.getUseState(), element.getOutProperties(), true, message));
121         LOGGER.debug("Automation composition element {} state changed to {}", elementId, deployState);
122         automationCompositionStateChangeAck.setResult(true);
123         publisher.sendAutomationCompositionAck(automationCompositionStateChangeAck);
124         cacheProvider.getMsgIdentification().remove(element.getId());
125     }
126
127     private void handleDeployState(AutomationComposition automationComposition, AutomationCompositionElement element,
128             DeployState deployState) {
129         element.setDeployState(deployState);
130         element.setLockState(DeployState.DEPLOYED.equals(element.getDeployState()) ? LockState.LOCKED : LockState.NONE);
131         var checkOpt = automationComposition.getElements().values().stream()
132                 .filter(acElement -> !deployState.equals(acElement.getDeployState())).findAny();
133         if (checkOpt.isEmpty()) {
134             if (DeployState.DEPLOYED.equals(automationComposition.getDeployState())
135                     && automationComposition.getCompositionTargetId() != null) {
136                 // migration scenario
137                 automationComposition.setCompositionId(automationComposition.getCompositionTargetId());
138                 automationComposition.setCompositionTargetId(null);
139             }
140             automationComposition.setDeployState(deployState);
141             automationComposition.setLockState(element.getLockState());
142             automationComposition.setSubState(SubState.NONE);
143
144             if (DeployState.DELETED.equals(deployState)) {
145                 cacheProvider.removeAutomationComposition(automationComposition.getInstanceId());
146             }
147         }
148     }
149
150     private void handleLockState(AutomationComposition automationComposition, AutomationCompositionElement element,
151             LockState lockState) {
152         element.setLockState(lockState);
153         var checkOpt = automationComposition.getElements().values().stream()
154                 .filter(acElement -> !lockState.equals(acElement.getLockState())).findAny();
155         if (checkOpt.isEmpty()) {
156             automationComposition.setLockState(lockState);
157             automationComposition.setSubState(SubState.NONE);
158         }
159     }
160
161     private void handleSubState(AutomationComposition automationComposition, AutomationCompositionElement element) {
162         element.setSubState(SubState.NONE);
163         var checkOpt = automationComposition.getElements().values().stream()
164                 .filter(acElement -> !SubState.NONE.equals(acElement.getSubState())).findAny();
165         if (checkOpt.isEmpty()) {
166             automationComposition.setSubState(SubState.NONE);
167         }
168     }
169
170     /**
171      * Send Ac Element Info.
172      *
173      * @param automationCompositionId the automationComposition Id
174      * @param elementId the automationComposition Element id
175      * @param useState the use State
176      * @param operationalState the operational State
177      * @param outProperties the output Properties Map
178      */
179     public void sendAcElementInfo(UUID automationCompositionId, UUID elementId, String useState,
180             String operationalState, Map<String, Object> outProperties) {
181
182         if (automationCompositionId == null || elementId == null) {
183             LOGGER.error("Cannot update Automation composition element state, id is null");
184             return;
185         }
186
187         var automationComposition = cacheProvider.getAutomationComposition(automationCompositionId);
188         if (automationComposition == null) {
189             LOGGER.error("Cannot update Automation composition element state, Automation composition id {} not present",
190                     automationCompositionId);
191             return;
192         }
193
194         var element = automationComposition.getElements().get(elementId);
195         if (element == null) {
196             var msg = "Cannot update Automation composition element state, AC Element id {} not present";
197             LOGGER.error(msg, elementId);
198             return;
199         }
200         element.setOperationalState(operationalState);
201         element.setUseState(useState);
202         element.setOutProperties(outProperties);
203
204         var acInfo = new AutomationCompositionInfo();
205         acInfo.setAutomationCompositionId(automationCompositionId);
206         acInfo.setDeployState(automationComposition.getDeployState());
207         acInfo.setLockState(automationComposition.getLockState());
208         acInfo.setElements(List.of(getAutomationCompositionElementInfo(element)));
209         var statusMsg = createParticipantStatus();
210         statusMsg.setCompositionId(automationComposition.getCompositionId());
211         statusMsg.setAutomationCompositionInfoList(List.of(acInfo));
212         publisher.sendParticipantStatus(statusMsg);
213     }
214
215     /**
216      * Get AutomationCompositionElementInfo from AutomationCompositionElement.
217      *
218      * @param element the AutomationCompositionElement
219      * @return the AutomationCompositionElementInfo
220      */
221     public AutomationCompositionElementInfo getAutomationCompositionElementInfo(AutomationCompositionElement element) {
222         var elementInfo = new AutomationCompositionElementInfo();
223         elementInfo.setAutomationCompositionElementId(element.getId());
224         elementInfo.setDeployState(element.getDeployState());
225         elementInfo.setLockState(element.getLockState());
226         elementInfo.setOperationalState(element.getOperationalState());
227         elementInfo.setUseState(element.getUseState());
228         elementInfo.setOutProperties(element.getOutProperties());
229         return elementInfo;
230     }
231
232     /**
233      * Update Composition State for prime and deprime.
234      *
235      * @param compositionId the composition id
236      * @param state the Composition State
237      * @param stateChangeResult the indicator if error occurs
238      * @param message the message
239      */
240     public void updateCompositionState(UUID compositionId, AcTypeState state, StateChangeResult stateChangeResult,
241             String message) {
242         var participantPrimeAck = new ParticipantPrimeAck();
243         participantPrimeAck.setCompositionId(compositionId);
244         participantPrimeAck.setMessage(message);
245         participantPrimeAck.setResult(true);
246         participantPrimeAck.setResponseTo(cacheProvider.getMsgIdentification().get(compositionId));
247         participantPrimeAck.setCompositionState(state);
248         participantPrimeAck.setStateChangeResult(stateChangeResult);
249         participantPrimeAck.setParticipantId(cacheProvider.getParticipantId());
250         participantPrimeAck.setReplicaId(cacheProvider.getReplicaId());
251         participantPrimeAck.setState(ParticipantState.ON_LINE);
252         publisher.sendParticipantPrimeAck(participantPrimeAck);
253         cacheProvider.getMsgIdentification().remove(compositionId);
254         if (AcTypeState.COMMISSIONED.equals(state) && StateChangeResult.NO_ERROR.equals(stateChangeResult)) {
255             cacheProvider.removeElementDefinition(compositionId);
256         }
257     }
258
259     /**
260      * Send Composition Definition Info.
261      *
262      * @param compositionId the composition id
263      * @param elementId the Composition Definition Element id
264      * @param outProperties the output Properties Map
265      */
266     public void sendAcDefinitionInfo(UUID compositionId, ToscaConceptIdentifier elementId,
267             Map<String, Object> outProperties) {
268         if (compositionId == null) {
269             LOGGER.error("Cannot send Composition outProperties, id is null");
270             return;
271         }
272         var statusMsg = createParticipantStatus();
273         statusMsg.setCompositionId(compositionId);
274         var acElementDefsMap = cacheProvider.getAcElementsDefinitions();
275         var acElementsDefinitions = acElementDefsMap.get(compositionId);
276         if (acElementsDefinitions == null) {
277             LOGGER.error("Cannot send Composition outProperties, id {} is null", compositionId);
278             return;
279         }
280         var acElementDefinition = getAutomationCompositionElementDefinition(acElementsDefinitions, elementId);
281         if (acElementDefinition == null) {
282             LOGGER.error("Cannot send Composition outProperties, elementId {} not present", elementId);
283             return;
284         }
285         acElementDefinition.setOutProperties(outProperties);
286         var participantDefinition = new ParticipantDefinition();
287         participantDefinition.setParticipantId(cacheProvider.getParticipantId());
288         participantDefinition.setAutomationCompositionElementDefinitionList(List.of(acElementDefinition));
289         statusMsg.setParticipantDefinitionUpdates(List.of(participantDefinition));
290         publisher.sendParticipantStatus(statusMsg);
291     }
292
293     private AutomationCompositionElementDefinition getAutomationCompositionElementDefinition(
294             Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> acElementsDefinition,
295             ToscaConceptIdentifier elementId) {
296
297         if (elementId == null) {
298             if (acElementsDefinition.size() == 1) {
299                 return acElementsDefinition.values().iterator().next();
300             }
301             return null;
302         }
303         return acElementsDefinition.get(elementId);
304     }
305
306     private ParticipantStatus createParticipantStatus() {
307         var statusMsg = new ParticipantStatus();
308         statusMsg.setParticipantId(cacheProvider.getParticipantId());
309         statusMsg.setReplicaId(cacheProvider.getReplicaId());
310         statusMsg.setState(ParticipantState.ON_LINE);
311         statusMsg.setParticipantSupportedElementType(cacheProvider.getSupportedAcElementTypes());
312         return statusMsg;
313     }
314 }