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