2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2019-2021 Nordix Foundation.
4 * Modifications Copyright (C) 2021 Bell Canada. 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.apex.services.onappf.handler;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.List;
27 import org.onap.policy.apex.service.engine.main.ApexPolicyStatisticsManager;
28 import org.onap.policy.apex.services.onappf.ApexStarterConstants;
29 import org.onap.policy.apex.services.onappf.comm.PdpStatusPublisher;
30 import org.onap.policy.apex.services.onappf.exception.ApexStarterException;
31 import org.onap.policy.common.endpoints.event.comm.TopicSink;
32 import org.onap.policy.common.utils.services.Registry;
33 import org.onap.policy.models.pdp.concepts.PdpResponseDetails;
34 import org.onap.policy.models.pdp.concepts.PdpStatus;
35 import org.onap.policy.models.pdp.concepts.PdpUpdate;
36 import org.onap.policy.models.pdp.enums.PdpResponseStatus;
37 import org.onap.policy.models.pdp.enums.PdpState;
38 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 * This class supports the handling of pdp update messages.
45 * @author Ajith Sreekumar (ajith.sreekumar@est.tech)
47 public class PdpUpdateMessageHandler {
49 private static final Logger LOGGER = LoggerFactory.getLogger(PdpUpdateMessageHandler.class);
52 * Method which handles a pdp update event from PAP.
54 * @param pdpUpdateMsg pdp update message
56 public void handlePdpUpdateEvent(final PdpUpdate pdpUpdateMsg) {
57 final PdpMessageHandler pdpMessageHandler = new PdpMessageHandler();
58 final PdpStatus pdpStatusContext = Registry.get(ApexStarterConstants.REG_PDP_STATUS_OBJECT, PdpStatus.class);
59 PdpResponseDetails pdpResponseDetails = null;
60 if (pdpUpdateMsg.appliesTo(pdpStatusContext.getName(), pdpStatusContext.getPdpGroup(),
61 pdpStatusContext.getPdpSubgroup())) {
62 if (checkIfAlreadyHandled(pdpUpdateMsg, pdpStatusContext)) {
63 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
64 PdpResponseStatus.SUCCESS, "Pdp already updated");
66 pdpResponseDetails = handlePdpUpdate(pdpUpdateMsg, pdpMessageHandler, pdpStatusContext);
68 final PdpStatusPublisher pdpStatusPublisherTemp =
69 Registry.get(ApexStarterConstants.REG_PDP_STATUS_PUBLISHER);
70 final PdpStatus pdpStatus = pdpMessageHandler.createPdpStatusFromContext();
71 pdpStatus.setResponse(pdpResponseDetails);
72 pdpStatus.setDescription("Pdp status response message for PdpUpdate");
73 pdpStatusPublisherTemp.send(pdpStatus);
78 * Method to do pdp update.
80 * @param pdpUpdateMsg the pdp update message
81 * @param pdpMessageHandler the message handler
82 * @param pdpStatusContext the pdp status in memory
83 * @return pdpResponseDetails the pdp response
85 private PdpResponseDetails handlePdpUpdate(final PdpUpdate pdpUpdateMsg, final PdpMessageHandler pdpMessageHandler,
86 final PdpStatus pdpStatusContext) {
87 PdpResponseDetails pdpResponseDetails = null;
88 final PdpStatusPublisher pdpStatusPublisher = Registry.get(ApexStarterConstants.REG_PDP_STATUS_PUBLISHER);
89 if (null != pdpUpdateMsg.getPdpHeartbeatIntervalMs() && pdpUpdateMsg.getPdpHeartbeatIntervalMs() > 0
90 && pdpStatusPublisher.getInterval() != pdpUpdateMsg.getPdpHeartbeatIntervalMs()) {
91 updateInterval(pdpUpdateMsg.getPdpHeartbeatIntervalMs());
93 pdpStatusContext.setPdpGroup(pdpUpdateMsg.getPdpGroup());
94 pdpStatusContext.setPdpSubgroup(pdpUpdateMsg.getPdpSubgroup());
96 .setPolicies(new PdpMessageHandler().getToscaPolicyIdentifiers(pdpUpdateMsg.getPolicies()));
97 Registry.registerOrReplace(ApexStarterConstants.REG_APEX_TOSCA_POLICY_LIST, pdpUpdateMsg.getPolicies());
98 if (pdpStatusContext.getState().equals(PdpState.ACTIVE)) {
99 pdpResponseDetails = startOrStopApexEngineBasedOnPolicies(pdpUpdateMsg, pdpMessageHandler);
101 ApexEngineHandler apexEngineHandler =
102 Registry.getOrDefault(ApexStarterConstants.REG_APEX_ENGINE_HANDLER, ApexEngineHandler.class, null);
103 // in hearbeat while in active state, only the policies which are running should be there.
104 // if some policy fails, that shouldn't go in the heartbeat.
105 // If no policies are running, then the policy list in the heartbeat can be empty
106 if (null != apexEngineHandler && apexEngineHandler.isApexEngineRunning()) {
107 pdpStatusContext.setPolicies(apexEngineHandler.getRunningPolicies());
109 pdpStatusContext.setPolicies(Collections.emptyList());
112 if (null == pdpResponseDetails) {
113 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
114 PdpResponseStatus.SUCCESS, "Pdp update successful.");
116 return pdpResponseDetails;
120 * Method to start or stop apex engine based on the list of policies received from pap. When current state is
121 * active, if PAP sends PdpUpdate with empty policies list, stop apex engine, or, if there is a change in policies,
122 * stop the current running policies and the deploy the new ones.
124 * @param pdpUpdateMsg the pdp update message from pap
125 * @param pdpMessageHandler pdp message handler
126 * @param pdpStatusContext the pdp status object in memory
127 * @return pdpResponseDetails the pdp response
129 private PdpResponseDetails startOrStopApexEngineBasedOnPolicies(final PdpUpdate pdpUpdateMsg,
130 final PdpMessageHandler pdpMessageHandler) {
131 PdpResponseDetails pdpResponseDetails = null;
132 ApexEngineHandler apexEngineHandler = null;
134 apexEngineHandler = Registry.get(ApexStarterConstants.REG_APEX_ENGINE_HANDLER);
135 } catch (final IllegalArgumentException e) {
136 LOGGER.debug("ApenEngineHandler not in registry.", e);
138 if (pdpUpdateMsg.getPolicies().isEmpty()) {
139 pdpResponseDetails = stopApexEngineBasedOnPolicies(pdpUpdateMsg, pdpMessageHandler, apexEngineHandler);
141 pdpResponseDetails = startApexEngineBasedOnPolicies(pdpUpdateMsg, pdpMessageHandler, apexEngineHandler);
143 return pdpResponseDetails;
146 private PdpResponseDetails stopApexEngineBasedOnPolicies(final PdpUpdate pdpUpdateMsg,
147 final PdpMessageHandler pdpMessageHandler, ApexEngineHandler apexEngineHandler) {
148 PdpResponseDetails pdpResponseDetails = null;
149 if (null != apexEngineHandler && apexEngineHandler.isApexEngineRunning()) {
151 apexEngineHandler.shutdown();
152 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
153 PdpResponseStatus.SUCCESS, "Pdp update successful. No policies are running.");
154 } catch (final ApexStarterException e) {
155 LOGGER.error("Pdp update failed as the policies couldn't be undeployed.", e);
156 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
157 PdpResponseStatus.FAIL, "Pdp update failed as the policies couldn't be undeployed.");
160 return pdpResponseDetails;
163 private PdpResponseDetails startApexEngineBasedOnPolicies(final PdpUpdate pdpUpdateMsg,
164 final PdpMessageHandler pdpMessageHandler, ApexEngineHandler apexEngineHandler) {
165 PdpResponseDetails pdpResponseDetails = null;
168 if (null != apexEngineHandler && apexEngineHandler.isApexEngineRunning()) {
169 apexEngineHandler.updateApexEngine(pdpUpdateMsg.getPolicies());
171 apexEngineHandler = new ApexEngineHandler(pdpUpdateMsg.getPolicies());
172 Registry.registerOrReplace(ApexStarterConstants.REG_APEX_ENGINE_HANDLER, apexEngineHandler);
174 if (apexEngineHandler.isApexEngineRunning()) {
175 List<ToscaConceptIdentifier> runningPolicies = apexEngineHandler.getRunningPolicies();
176 if (new HashSet<>(runningPolicies)
177 .equals(new HashSet<>(pdpMessageHandler.getToscaPolicyIdentifiers(pdpUpdateMsg.getPolicies())))) {
178 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
179 PdpResponseStatus.SUCCESS, "Apex engine started and policies are running.");
181 StringBuilder message =
182 new StringBuilder("Apex engine started. But, only the following polices are running - ");
183 for (ToscaConceptIdentifier policy : runningPolicies) {
184 message.append(policy.getName()).append(":").append(policy.getVersion()).append(" ");
186 message.append(". Other policies failed execution. Please see the logs for more details.");
187 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
188 PdpResponseStatus.SUCCESS, message.toString());
191 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
192 PdpResponseStatus.FAIL, "Apex engine failed to start.");
194 } catch (final ApexStarterException e) {
195 LOGGER.error("Apex engine service running failed. ", e);
196 pdpResponseDetails = pdpMessageHandler.createPdpResonseDetails(pdpUpdateMsg.getRequestId(),
197 PdpResponseStatus.FAIL, "Apex engine service running failed. " + e.getMessage());
199 final ApexPolicyStatisticsManager apexPolicyStatisticsManager =
200 ApexPolicyStatisticsManager.getInstanceFromRegistry();
201 if (apexPolicyStatisticsManager != null) {
202 apexPolicyStatisticsManager
203 .updatePolicyDeployCounter(pdpResponseDetails.getResponseStatus() == PdpResponseStatus.SUCCESS);
205 return pdpResponseDetails;
209 * Method checks if the Pdp update message is already handled by checking the values in the context.
211 * @param pdpUpdateMsg pdp update message received from pap
212 * @param pdpStatusContext values saved in context memory
213 * @return boolean flag which tells if the information is same or not
215 private boolean checkIfAlreadyHandled(final PdpUpdate pdpUpdateMsg, final PdpStatus pdpStatusContext) {
216 return null != pdpStatusContext.getPdpGroup()
217 && pdpStatusContext.getPdpGroup().equals(pdpUpdateMsg.getPdpGroup())
218 && null != pdpStatusContext.getPdpSubgroup()
219 && pdpStatusContext.getPdpSubgroup().equals(pdpUpdateMsg.getPdpSubgroup())
220 && null != pdpStatusContext.getPolicies() && new PdpMessageHandler()
221 .getToscaPolicyIdentifiers(pdpUpdateMsg.getPolicies()).equals(pdpStatusContext.getPolicies());
225 * Method to update the time interval used by the timer task.
227 * @param interval time interval received in the pdp update message from pap
229 public void updateInterval(final long interval) {
230 final PdpStatusPublisher pdpStatusPublisher = Registry.get(ApexStarterConstants.REG_PDP_STATUS_PUBLISHER);
231 pdpStatusPublisher.terminate();
232 final List<TopicSink> topicSinks = Registry.get(ApexStarterConstants.REG_APEX_PDP_TOPIC_SINKS);
233 Registry.registerOrReplace(ApexStarterConstants.REG_PDP_STATUS_PUBLISHER,
234 new PdpStatusPublisher(topicSinks, interval));