2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021-2023 Nordix Foundation.
4 * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.clamp.acm.participant.intermediary.handler;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.UUID;
27 import org.onap.policy.clamp.acm.participant.intermediary.comm.ParticipantMessagePublisher;
28 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
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.AutomationCompositionElementDefinition;
32 import org.onap.policy.clamp.models.acm.concepts.DeployState;
33 import org.onap.policy.clamp.models.acm.concepts.LockState;
34 import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy;
35 import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc;
36 import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils;
37 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
38 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionDeploy;
39 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionDeployAck;
40 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionStateChange;
41 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessageType;
42 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.PropertiesUpdate;
43 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
44 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
45 import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.stereotype.Component;
51 * This class is responsible for managing the state of all automation compositions in the participant.
54 public class AutomationCompositionHandler {
55 private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionHandler.class);
57 private final CacheProvider cacheProvider;
58 private final ParticipantMessagePublisher publisher;
59 private final ThreadHandler listener;
60 private final AcInstanceStateResolver acInstanceStateResolver;
63 * Constructor, set the participant ID and messageSender.
65 * @param cacheProvider the Cache Provider
66 * @param publisher the ParticipantMessage Publisher
67 * @param listener the ThreadHandler Listener
69 public AutomationCompositionHandler(CacheProvider cacheProvider, ParticipantMessagePublisher publisher,
70 ThreadHandler listener) {
71 this.cacheProvider = cacheProvider;
72 this.publisher = publisher;
73 this.listener = listener;
74 this.acInstanceStateResolver = new AcInstanceStateResolver();
78 * Handle a automation composition state change message.
80 * @param stateChangeMsg the state change message
82 public void handleAutomationCompositionStateChange(AutomationCompositionStateChange stateChangeMsg) {
83 if (stateChangeMsg.getAutomationCompositionId() == null) {
87 var automationComposition = cacheProvider.getAutomationComposition(stateChangeMsg.getAutomationCompositionId());
89 if (automationComposition == null) {
90 if (DeployOrder.DELETE.equals(stateChangeMsg.getDeployOrderedState())) {
91 var automationCompositionAck = new AutomationCompositionDeployAck(
92 ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK);
93 automationCompositionAck.setParticipantId(cacheProvider.getParticipantId());
94 automationCompositionAck.setMessage("Already deleted or never used");
95 automationCompositionAck.setResult(true);
96 automationCompositionAck.setStateChangeResult(StateChangeResult.NO_ERROR);
97 automationCompositionAck.setResponseTo(stateChangeMsg.getMessageId());
98 automationCompositionAck.setAutomationCompositionId(stateChangeMsg.getAutomationCompositionId());
99 publisher.sendAutomationCompositionAck(automationCompositionAck);
101 LOGGER.debug("Automation composition {} does not use this participant",
102 stateChangeMsg.getAutomationCompositionId());
107 if (!checkConsistantOrderState(automationComposition, stateChangeMsg.getDeployOrderedState(),
108 stateChangeMsg.getLockOrderedState())) {
109 LOGGER.warn("Not Consistant OrderState Automation composition {}",
110 stateChangeMsg.getAutomationCompositionId());
114 if (DeployOrder.NONE.equals(stateChangeMsg.getDeployOrderedState())) {
115 handleLockOrderState(stateChangeMsg.getMessageId(), automationComposition,
116 stateChangeMsg.getLockOrderedState(), stateChangeMsg.getStartPhase());
118 handleDeployOrderState(stateChangeMsg.getMessageId(), automationComposition,
119 stateChangeMsg.getDeployOrderedState(), stateChangeMsg.getStartPhase());
123 private boolean checkConsistantOrderState(AutomationComposition automationComposition, DeployOrder deployOrder,
124 LockOrder lockOrder) {
125 if (DeployOrder.UPDATE.equals(deployOrder)) {
128 return acInstanceStateResolver.resolve(deployOrder, lockOrder, automationComposition.getDeployState(),
129 automationComposition.getLockState(), automationComposition.getStateChangeResult()) != null;
133 * Method to handle state changes.
135 * @param messageId the messageId
136 * @param automationComposition participant response
137 * @param orderedState automation composition ordered state
138 * @param startPhaseMsg startPhase from message
140 private void handleDeployOrderState(UUID messageId, final AutomationComposition automationComposition,
141 DeployOrder orderedState, Integer startPhaseMsg) {
143 switch (orderedState) {
145 handleUndeployState(messageId, automationComposition, startPhaseMsg);
148 handleDeleteState(messageId, automationComposition, startPhaseMsg);
152 LOGGER.error("StateChange message has no state, state is null {}", automationComposition.getKey());
158 * Method to handle state changes.
160 * @param messageId the messageId
161 * @param automationComposition participant response
162 * @param orderedState automation composition ordered state
163 * @param startPhaseMsg startPhase from message
165 private void handleLockOrderState(UUID messageId, final AutomationComposition automationComposition,
166 LockOrder orderedState, Integer startPhaseMsg) {
168 switch (orderedState) {
170 handleLockState(messageId, automationComposition, startPhaseMsg);
173 handleUnlockState(messageId, automationComposition, startPhaseMsg);
176 LOGGER.error("StateChange message has no state, state is null {}", automationComposition.getKey());
182 * Handle a automation composition properties update message.
184 * @param updateMsg the properties update message
186 public void handleAcPropertyUpdate(PropertiesUpdate updateMsg) {
188 if (updateMsg.getParticipantUpdatesList().isEmpty()) {
189 LOGGER.warn("No AutomationCompositionElement updates in message {}",
190 updateMsg.getAutomationCompositionId());
194 for (var participantDeploy : updateMsg.getParticipantUpdatesList()) {
195 if (cacheProvider.getParticipantId().equals(participantDeploy.getParticipantId())) {
197 updateExistingElementsOnThisParticipant(updateMsg.getAutomationCompositionId(), participantDeploy);
199 callParticipantUpdateProperty(updateMsg.getMessageId(), participantDeploy.getAcElementList(),
200 updateMsg.getAutomationCompositionId());
206 * Handle a automation composition Deploy message.
208 * @param deployMsg the Deploy message
210 public void handleAutomationCompositionDeploy(AutomationCompositionDeploy deployMsg) {
212 if (deployMsg.getParticipantUpdatesList().isEmpty()) {
213 LOGGER.warn("No AutomationCompositionElement deploy in message {}", deployMsg.getAutomationCompositionId());
217 for (var participantDeploy : deployMsg.getParticipantUpdatesList()) {
218 if (cacheProvider.getParticipantId().equals(participantDeploy.getParticipantId())) {
219 if (deployMsg.isFirstStartPhase()) {
220 cacheProvider.initializeAutomationComposition(deployMsg.getCompositionId(),
221 deployMsg.getAutomationCompositionId(), participantDeploy);
223 callParticipanDeploy(deployMsg.getMessageId(), participantDeploy.getAcElementList(),
224 deployMsg.getStartPhase(), deployMsg.getAutomationCompositionId());
229 private void callParticipanDeploy(UUID messageId, List<AcElementDeploy> acElements, Integer startPhaseMsg,
231 for (var element : acElements) {
232 var commonProperties = cacheProvider.getCommonProperties(instanceId, element.getId());
233 int startPhase = ParticipantUtils.findStartPhase(commonProperties);
234 if (startPhaseMsg.equals(startPhase)) {
235 var map = new HashMap<>(commonProperties);
236 map.putAll(element.getProperties());
237 listener.deploy(messageId, instanceId, element, map);
242 private void callParticipantUpdateProperty(UUID messageId, List<AcElementDeploy> acElements, UUID instanceId) {
243 for (var element : acElements) {
244 listener.update(messageId, instanceId, element, element.getProperties());
248 private void updateExistingElementsOnThisParticipant(UUID instanceId, ParticipantDeploy participantDeploy) {
249 var acElementList = cacheProvider.getAutomationComposition(instanceId).getElements();
250 for (var element : participantDeploy.getAcElementList()) {
251 var acElement = acElementList.get(element.getId());
252 acElement.getProperties().putAll(element.getProperties());
257 * Method to handle when the new state from participant is UNINITIALISED state.
259 * @param messageId the messageId
260 * @param automationComposition participant response
261 * @param startPhaseMsg startPhase from message
263 private void handleUndeployState(UUID messageId, final AutomationComposition automationComposition,
264 Integer startPhaseMsg) {
265 for (var acElement : automationComposition.getElements().values()) {
266 int startPhase = ParticipantUtils.findStartPhase(
267 cacheProvider.getCommonProperties(automationComposition.getInstanceId(), acElement.getId()));
268 if (startPhaseMsg.equals(startPhase)) {
269 acElement.setDeployState(DeployState.UNDEPLOYING);
270 listener.undeploy(messageId, automationComposition.getInstanceId(), acElement.getId());
275 private void handleDeleteState(UUID messageId, final AutomationComposition automationComposition,
276 Integer startPhaseMsg) {
277 for (var acElement : automationComposition.getElements().values()) {
278 int startPhase = ParticipantUtils.findStartPhase(
279 cacheProvider.getCommonProperties(automationComposition.getInstanceId(), acElement.getId()));
280 if (startPhaseMsg.equals(startPhase)) {
281 acElement.setDeployState(DeployState.DELETING);
282 listener.delete(messageId, automationComposition.getInstanceId(), acElement.getId());
288 * Method to handle when the new state from participant is PASSIVE state.
290 * @param messageId the messageId
291 * @param automationComposition participant response
292 * @param startPhaseMsg startPhase from message
294 private void handleLockState(UUID messageId, final AutomationComposition automationComposition,
295 Integer startPhaseMsg) {
296 for (var acElement : automationComposition.getElements().values()) {
297 int startPhase = ParticipantUtils.findStartPhase(
298 cacheProvider.getCommonProperties(automationComposition.getInstanceId(), acElement.getId()));
299 if (startPhaseMsg.equals(startPhase)) {
300 acElement.setLockState(LockState.LOCKING);
301 listener.lock(messageId, automationComposition.getInstanceId(), acElement.getId());
307 * Method to handle when the new state from participant is RUNNING state.
309 * @param messageId the messageId
310 * @param automationComposition participant response
311 * @param startPhaseMsg startPhase from message
313 private void handleUnlockState(UUID messageId, final AutomationComposition automationComposition,
314 Integer startPhaseMsg) {
315 for (var acElement : automationComposition.getElements().values()) {
316 int startPhase = ParticipantUtils.findStartPhase(
317 cacheProvider.getCommonProperties(automationComposition.getInstanceId(), acElement.getId()));
318 if (startPhaseMsg.equals(startPhase)) {
319 acElement.setLockState(LockState.UNLOCKING);
320 listener.unlock(messageId, automationComposition.getInstanceId(), acElement.getId());
326 * Handles prime a Composition Definition.
328 * @param messageId the messageId
329 * @param compositionId the compositionId
330 * @param list the list of AutomationCompositionElementDefinition
332 public void prime(UUID messageId, UUID compositionId, List<AutomationCompositionElementDefinition> list) {
333 listener.prime(messageId, compositionId, list);
337 * Handles deprime a Composition Definition.
339 * @param messageId the messageId
340 * @param compositionId the compositionId
342 public void deprime(UUID messageId, UUID compositionId) {
343 listener.deprime(messageId, compositionId);
347 * Handles restarted scenario.
349 * @param messageId the messageId
350 * @param compositionId the compositionId
351 * @param list the list of AutomationCompositionElementDefinition
352 * @param state the state of the composition
353 * @param automationCompositionList list of ParticipantRestartAc
355 public void restarted(UUID messageId, UUID compositionId, List<AutomationCompositionElementDefinition> list,
356 AcTypeState state, List<ParticipantRestartAc> automationCompositionList) {
358 for (var automationcomposition : automationCompositionList) {
359 cacheProvider.initializeAutomationComposition(compositionId, automationcomposition);
361 listener.restarted(messageId, compositionId, list, state, automationCompositionList);