797fe50a323a797aa82fe1af42a2011becb1669c
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
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.runtime.supervision.scanner;
22
23 import java.util.UUID;
24 import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
25 import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher;
26 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
27 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
28 import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils;
29 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
30 import org.onap.policy.clamp.models.acm.document.concepts.DocMessage;
31 import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
32 import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35 import org.springframework.stereotype.Component;
36
37 @Component
38 public class AcDefinitionScanner {
39     private static final Logger LOGGER = LoggerFactory.getLogger(AcDefinitionScanner.class);
40
41     private final long maxOperationWaitMs;
42
43     private final AcDefinitionProvider acDefinitionProvider;
44     private final ParticipantSyncPublisher participantSyncPublisher;
45
46     /**
47      * Constructor for instantiating AcDefinitionScanner.
48      *
49      * @param acDefinitionProvider the Policy Models Provider
50      * @param participantSyncPublisher the Participant Sync Publisher
51      * @param acRuntimeParameterGroup the parameters for the automation composition runtime
52      */
53     public AcDefinitionScanner(final AcDefinitionProvider acDefinitionProvider,
54             final ParticipantSyncPublisher participantSyncPublisher,
55             final AcRuntimeParameterGroup acRuntimeParameterGroup) {
56         this.acDefinitionProvider = acDefinitionProvider;
57         this.participantSyncPublisher = participantSyncPublisher;
58         this.maxOperationWaitMs = acRuntimeParameterGroup.getParticipantParameters().getMaxOperationWaitMs();
59     }
60
61     private UpdateSync handlePrimeAckElement(DocMessage message, AutomationCompositionDefinition acDefinition) {
62         var result = new UpdateSync();
63         if (StateChangeResult.FAILED.equals(message.getStateChangeResult())) {
64             acDefinition.setStateChangeResult(StateChangeResult.FAILED);
65             result.setUpdated(true);
66             result.setToBeSync(true);
67         }
68         for (var element : acDefinition.getElementStateMap().values()) {
69             if (message.getParticipantId().equals(element.getParticipantId())) {
70                 element.setMessage(message.getMessage());
71                 element.setState(message.getCompositionState());
72                 result.setUpdated(true);
73             }
74         }
75         return result;
76     }
77
78     private UpdateSync handleOutProperties(DocMessage message, AutomationCompositionDefinition acDefinition) {
79         var elementOpt = acDefinition.getElementStateMap().values().stream()
80                 .filter(element -> element.getNodeTemplateId().equals(message.getAcElementDefinitionId())).findFirst();
81
82         var result = new UpdateSync();
83         if (elementOpt.isPresent()) {
84             elementOpt.get().setOutProperties(message.getOutProperties());
85             result.setUpdated(true);
86             result.setToBeSync(true);
87         }
88         return result;
89     }
90
91     /**
92      * Scan Message.
93      *
94      * @param acDefinition the AutomationComposition Definition
95      * @param message the message
96      */
97     public UpdateSync scanMessage(AutomationCompositionDefinition acDefinition, DocMessage message) {
98         return switch (message.getMessageType()) {
99             case PARTICIPANT_STATUS -> handleOutProperties(message, acDefinition);
100             case PARTICIPANT_PRIME_ACK -> handlePrimeAckElement(message, acDefinition);
101             default -> {
102                 LOGGER.debug("Not valid MessageType {}", message.getMessageType());
103                 yield new UpdateSync();
104             }
105         };
106     }
107
108     /**
109      * Scan an AutomationComposition Definition.
110      *
111      * @param acDefinition the AutomationComposition Definition
112      * @param updateSync defines if true if the composition has to be saved or sync
113      */
114     public void scanAutomationCompositionDefinition(AutomationCompositionDefinition acDefinition,
115             UpdateSync updateSync) {
116         if (StateChangeResult.FAILED.equals(acDefinition.getStateChangeResult())) {
117             LOGGER.debug("automation definition {} scanned, OK", acDefinition.getCompositionId());
118             updateAcDefinitionState(acDefinition, updateSync);
119             return;
120         }
121
122         boolean completed = true;
123         var finalState = AcTypeState.PRIMING.equals(acDefinition.getState())
124                 || AcTypeState.PRIMED.equals(acDefinition.getState()) ? AcTypeState.PRIMED : AcTypeState.COMMISSIONED;
125         for (var element : acDefinition.getElementStateMap().values()) {
126             if (!finalState.equals(element.getState())) {
127                 completed = false;
128                 break;
129             }
130         }
131         if (completed) {
132             acDefinition.setState(finalState);
133             acDefinition.setStateChangeResult(StateChangeResult.NO_ERROR);
134             updateSync.setUpdated(true);
135             updateSync.setToBeSync(true);
136         } else {
137             updateSync.or(handleTimeout(acDefinition));
138         }
139         updateAcDefinitionState(acDefinition, updateSync);
140     }
141
142     private UpdateSync handleTimeout(AutomationCompositionDefinition acDefinition) {
143         var result = new UpdateSync();
144         if (StateChangeResult.TIMEOUT.equals(acDefinition.getStateChangeResult())) {
145             LOGGER.debug("The ac definition is in timeout {}", acDefinition.getCompositionId());
146             return result;
147         }
148         var name = ParticipantUtils.getOpName(acDefinition.getState());
149         var maxWaitMs = ParticipantUtils
150                 .getTimeout(acDefinition.getServiceTemplate().getMetadata(), name, maxOperationWaitMs);
151         var lastMsg = TimestampHelper.toEpochMilli(acDefinition.getLastMsg());
152         var now = TimestampHelper.nowEpochMilli();
153         if ((now - lastMsg) > maxWaitMs) {
154             LOGGER.debug("Report timeout for the ac definition {}", acDefinition.getCompositionId());
155             acDefinition.setStateChangeResult(StateChangeResult.TIMEOUT);
156             result.setUpdated(true);
157             result.setToBeSync(true);
158         }
159         return result;
160     }
161
162     private void updateAcDefinitionState(AutomationCompositionDefinition acDefinition,
163             UpdateSync updateSync) {
164         if (updateSync.isUpdated()) {
165             acDefinition.setRevisionId(UUID.randomUUID());
166             acDefinitionProvider.updateAcDefinitionState(acDefinition);
167         }
168         if (updateSync.isToBeSync()) {
169             participantSyncPublisher.sendSync(acDefinition, null);
170         }
171     }
172 }