1c54658fa832e8c7c2709024ae42e1b26f3fed39
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 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.controlloop.participant.intermediary.handler;
22
23 import java.io.Closeable;
24 import java.util.Objects;
25 import lombok.Getter;
26 import lombok.Setter;
27 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant;
28 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantHealthStatus;
29 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantState;
30 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatistics;
31 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantControlLoopStateChange;
32 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantControlLoopUpdate;
33 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantHealthCheck;
34 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessage;
35 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseDetails;
36 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseStatus;
37 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStateChange;
38 import org.onap.policy.clamp.controlloop.participant.intermediary.comm.MessageSender;
39 import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ParticipantStatusPublisher;
40 import org.onap.policy.clamp.controlloop.participant.intermediary.parameters.ParticipantParameters;
41 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.stereotype.Component;
45
46 /**
47  * This class is responsible for managing the state of a participant.
48  */
49 @Getter
50 @Component
51 public class ParticipantHandler implements Closeable {
52     private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantHandler.class);
53
54     private final ToscaConceptIdentifier participantType;
55     private final ToscaConceptIdentifier participantId;
56     private final MessageSender sender;
57     private final ControlLoopHandler controlLoopHandler;
58     private final ParticipantStatistics participantStatistics;
59
60     @Setter
61     private ParticipantState state = ParticipantState.UNKNOWN;
62
63     @Setter
64     private ParticipantHealthStatus healthStatus = ParticipantHealthStatus.UNKNOWN;
65
66     /**
67      * Constructor, set the participant ID and sender.
68      *
69      * @param parameters the parameters of the participant
70      * @param publisher the publisher for sending responses to messages
71      */
72     public ParticipantHandler(ParticipantParameters parameters, ParticipantStatusPublisher publisher) {
73         this.participantType = parameters.getIntermediaryParameters().getParticipantType();
74         this.participantId = parameters.getIntermediaryParameters().getParticipantId();
75         this.sender =
76                 new MessageSender(this, publisher, parameters.getIntermediaryParameters().getReportingTimeInterval());
77         this.controlLoopHandler = new ControlLoopHandler(parameters.getIntermediaryParameters(), sender);
78         this.participantStatistics = new ParticipantStatistics();
79     }
80
81     @Override
82     public void close() {
83         sender.close();
84     }
85
86     /**
87      * Method which handles a participant state change event from clamp.
88      *
89      * @param stateChangeMsg participant state change message
90      */
91     public void handleParticipantStateChange(final ParticipantStateChange stateChangeMsg) {
92
93         if (!stateChangeMsg.appliesTo(participantType, participantId)) {
94             return;
95         }
96
97         var response = new ParticipantResponseDetails(stateChangeMsg);
98
99         switch (stateChangeMsg.getState()) {
100             case PASSIVE:
101                 handlePassiveState(response);
102                 break;
103             case ACTIVE:
104                 handleActiveState(response);
105                 break;
106             case SAFE:
107                 handleSafeState(response);
108                 break;
109             case TEST:
110                 handleTestState(response);
111                 break;
112             case TERMINATED:
113                 handleTerminatedState(response);
114                 break;
115             default:
116                 LOGGER.debug("StateChange message has no state, state is null {}", stateChangeMsg.getParticipantId());
117                 response.setResponseStatus(ParticipantResponseStatus.FAIL);
118                 response.setResponseMessage(
119                         "StateChange message has invalid state for participantId " + stateChangeMsg.getParticipantId());
120                 break;
121         }
122
123         sender.sendResponse(response);
124     }
125
126     /**
127      * Method which handles a participant health check event from clamp.
128      *
129      * @param healthCheckMsg participant health check message
130      */
131     public void handleParticipantHealthCheck(final ParticipantHealthCheck healthCheckMsg) {
132         var response = new ParticipantResponseDetails(healthCheckMsg);
133         response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
134         response.setResponseMessage(healthStatus.toString());
135
136         sender.sendResponse(response);
137     }
138
139     /**
140      * Handle a control loop update message.
141      *
142      * @param updateMsg the update message
143      */
144     public void handleControlLoopUpdate(ParticipantControlLoopUpdate updateMsg) {
145         controlLoopHandler.handleControlLoopUpdate(updateMsg);
146     }
147
148     /**
149      * Handle a control loop state change message.
150      *
151      * @param stateChangeMsg the state change message
152      */
153     public void handleControlLoopStateChange(ParticipantControlLoopStateChange stateChangeMsg) {
154         controlLoopHandler.handleControlLoopStateChange(stateChangeMsg);
155     }
156
157     /**
158      * Method to handle when the new state from participant is active.
159      *
160      * @param response participant response
161      */
162     private void handleActiveState(final ParticipantResponseDetails response) {
163         handleStateChange(ParticipantState.ACTIVE, response);
164     }
165
166     /**
167      * Method to handle when the new state from participant is passive.
168      *
169      * @param response participant response
170      */
171     private void handlePassiveState(final ParticipantResponseDetails response) {
172         handleStateChange(ParticipantState.PASSIVE, response);
173     }
174
175     /**
176      * Method to handle when the new state from participant is safe.
177      *
178      * @param response participant response
179      */
180     private void handleSafeState(final ParticipantResponseDetails response) {
181         handleStateChange(ParticipantState.SAFE, response);
182     }
183
184     /**
185      * Method to handle when the new state from participant is TEST.
186      *
187      * @param response participant response
188      */
189     private void handleTestState(final ParticipantResponseDetails response) {
190         handleStateChange(ParticipantState.TEST, response);
191     }
192
193     /**
194      * Method to handle when the new state from participant is Terminated.
195      *
196      * @param response participant response
197      */
198     private void handleTerminatedState(final ParticipantResponseDetails response) {
199         handleStateChange(ParticipantState.TERMINATED, response);
200     }
201
202     private void handleStateChange(ParticipantState newParticipantState, ParticipantResponseDetails response) {
203         if (state.equals(newParticipantState)) {
204             response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
205             response.setResponseMessage("Participant already in state " + newParticipantState);
206         } else {
207             response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
208             response.setResponseMessage("Participant state changed from " + state + " to " + newParticipantState);
209             state = newParticipantState;
210         }
211     }
212
213     /**
214      * Method to update participant state.
215      *
216      * @param definition participant definition
217      * @param participantState participant state
218      * @return the participant
219      */
220     public Participant updateParticipantState(ToscaConceptIdentifier definition, ParticipantState participantState) {
221         if (!Objects.equals(definition, participantId)) {
222             LOGGER.debug("No participant with this ID {}", definition.getName());
223             return null;
224         }
225         var response = new ParticipantResponseDetails();
226         handleStateChange(participantState, response);
227         sender.sendResponse(response);
228         return getParticipant(definition.getName(), definition.getVersion());
229     }
230
231     /**
232      * Get participants as a {@link Participant} class.
233      *
234      * @param name the participant name to get
235      * @param version the version of the participant to get
236      * @return the participant
237      */
238     public Participant getParticipant(String name, String version) {
239         if (participantId.getName().equals(name)) {
240             var participant = new Participant();
241             participant.setDefinition(participantId);
242             participant.setParticipantState(state);
243             participant.setHealthStatus(healthStatus);
244             return participant;
245         }
246         return null;
247     }
248
249     /**
250      * Check if a participant message applies to this participant handler.
251      *
252      * @param partipantMsg the message to check
253      * @return true if it applies, false otherwise
254      */
255     public boolean canHandle(ParticipantMessage partipantMsg) {
256         return partipantMsg.appliesTo(participantType, participantId);
257     }
258
259     /**
260      * Check if a participant message applies to this participant handler.
261      *
262      * @param partipantMsg the message to check
263      * @return true if it applies, false otherwise
264      */
265     public boolean appliesTo(ParticipantMessage partipantMsg) {
266         return partipantMsg.appliesTo(participantType, participantId);
267     }
268 }