2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2019 Nordix Foundation.
4 * Modifications Copyright (C) 2019 AT&T Intellectual Property.
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.pap.main.comm;
24 import java.util.List;
25 import java.util.Optional;
27 import org.apache.commons.lang3.builder.EqualsBuilder;
28 import org.onap.policy.common.utils.services.Registry;
29 import org.onap.policy.models.base.PfModelException;
30 import org.onap.policy.models.pdp.concepts.Pdp;
31 import org.onap.policy.models.pdp.concepts.PdpGroup;
32 import org.onap.policy.models.pdp.concepts.PdpGroupFilter;
33 import org.onap.policy.models.pdp.concepts.PdpStateChange;
34 import org.onap.policy.models.pdp.concepts.PdpStatus;
35 import org.onap.policy.models.pdp.concepts.PdpSubGroup;
36 import org.onap.policy.models.pdp.concepts.PdpUpdate;
37 import org.onap.policy.models.pdp.enums.PdpState;
38 import org.onap.policy.models.provider.PolicyModelsProvider;
39 import org.onap.policy.pap.main.PapConstants;
40 import org.onap.policy.pap.main.PolicyPapException;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
46 * Handler for PDP Status messages which either represent registration or heart beat.
48 * @author Ram Krishna Verma (ram.krishna.verma@est.tech)
50 public class PdpStatusMessageHandler extends PdpMessageGenerator {
51 private static final Logger LOGGER = LoggerFactory.getLogger(PdpStatusMessageHandler.class);
54 * Constructs the object.
56 public PdpStatusMessageHandler() {
61 * Handles the PdpStatus message coming from various PDP's.
63 * @param message the PdpStatus message
65 public void handlePdpStatus(final PdpStatus message) {
66 synchronized (updateLock) {
67 try (PolicyModelsProvider databaseProvider = modelProviderWrapper.create()) {
68 if (message.getPdpSubgroup() == null) {
69 handlePdpRegistration(message, databaseProvider);
71 handlePdpHeartbeat(message, databaseProvider);
75 * Indicate that a heart beat was received from the PDP. This is invoked only if handleXxx() does not
78 if (message.getName() != null) {
79 final PdpTracker pdpTracker = Registry.get(PapConstants.REG_PDP_TRACKER);
80 pdpTracker.add(message.getName());
82 } catch (final PolicyPapException exp) {
83 LOGGER.error("Operation Failed", exp);
84 } catch (final Exception exp) {
85 LOGGER.error("Failed connecting to database provider", exp);
90 private void handlePdpRegistration(final PdpStatus message, final PolicyModelsProvider databaseProvider)
91 throws PfModelException, PolicyPapException {
92 if (!findAndUpdatePdpGroup(message, databaseProvider)) {
93 final String errorMessage = "Failed to register PDP. No matching PdpGroup/SubGroup Found - ";
94 LOGGER.debug("{}{}", errorMessage, message);
95 throw new PolicyPapException(errorMessage + message);
99 private boolean findAndUpdatePdpGroup(final PdpStatus message, final PolicyModelsProvider databaseProvider)
100 throws PfModelException {
101 boolean pdpGroupFound = false;
102 final PdpGroupFilter filter =
103 PdpGroupFilter.builder().name(message.getPdpGroup()).groupState(PdpState.ACTIVE).build();
105 final List<PdpGroup> pdpGroups = databaseProvider.getFilteredPdpGroups(filter);
106 if (!pdpGroups.isEmpty()) {
107 pdpGroupFound = registerPdp(message, databaseProvider, pdpGroups.get(0));
109 return pdpGroupFound;
112 private boolean registerPdp(final PdpStatus message, final PolicyModelsProvider databaseProvider,
113 final PdpGroup finalizedPdpGroup) throws PfModelException {
114 Optional<PdpSubGroup> subGroup;
115 boolean pdpGroupFound = false;
116 subGroup = findPdpSubGroup(message, finalizedPdpGroup);
117 if (subGroup.isPresent()) {
118 LOGGER.debug("Found pdpGroup - {}, going for registration of PDP - {}", finalizedPdpGroup, message);
119 if (!findPdpInstance(message, subGroup.get()).isPresent()) {
120 updatePdpSubGroup(finalizedPdpGroup, subGroup.get(), message, databaseProvider);
122 sendPdpMessage(finalizedPdpGroup.getName(), subGroup.get(), message.getName(), null, databaseProvider);
123 pdpGroupFound = true;
125 return pdpGroupFound;
128 private void updatePdpSubGroup(final PdpGroup pdpGroup, final PdpSubGroup pdpSubGroup, final PdpStatus message,
129 final PolicyModelsProvider databaseProvider) throws PfModelException {
131 final Pdp pdpInstance = new Pdp();
132 pdpInstance.setInstanceId(message.getName());
133 pdpInstance.setPdpState(PdpState.ACTIVE);
134 pdpInstance.setHealthy(message.getHealthy());
135 pdpInstance.setMessage(message.getDescription());
136 pdpSubGroup.getPdpInstances().add(pdpInstance);
138 pdpSubGroup.setCurrentInstanceCount(pdpSubGroup.getCurrentInstanceCount() + 1);
140 databaseProvider.updatePdpSubGroup(pdpGroup.getName(), pdpSubGroup);
142 LOGGER.debug("Updated PdpSubGroup in DB - {} belonging to PdpGroup - {}", pdpSubGroup, pdpGroup);
145 private void handlePdpHeartbeat(final PdpStatus message, final PolicyModelsProvider databaseProvider)
146 throws PfModelException, PolicyPapException {
147 boolean pdpInstanceFound = false;
148 Optional<PdpSubGroup> pdpSubgroup = null;
149 Optional<Pdp> pdpInstance = null;
151 final PdpGroupFilter filter =
152 PdpGroupFilter.builder().name(message.getPdpGroup()).groupState(PdpState.ACTIVE).build();
153 final List<PdpGroup> pdpGroups = databaseProvider.getFilteredPdpGroups(filter);
154 if (!pdpGroups.isEmpty()) {
155 final PdpGroup pdpGroup = pdpGroups.get(0);
156 pdpSubgroup = findPdpSubGroup(message, pdpGroup);
157 if (pdpSubgroup.isPresent()) {
158 pdpInstance = findPdpInstance(message, pdpSubgroup.get());
159 if (pdpInstance.isPresent()) {
160 processPdpDetails(message, pdpSubgroup.get(), pdpInstance.get(), pdpGroup, databaseProvider);
161 pdpInstanceFound = true;
165 if (!pdpInstanceFound) {
166 final String errorMessage = "Failed to process heartbeat. No matching PdpGroup/SubGroup Found - ";
167 LOGGER.debug("{}{}", errorMessage, message);
168 throw new PolicyPapException(errorMessage + message);
172 private Optional<PdpSubGroup> findPdpSubGroup(final PdpStatus message, final PdpGroup pdpGroup) {
173 PdpSubGroup pdpSubgroup = null;
174 for (final PdpSubGroup subGroup : pdpGroup.getPdpSubgroups()) {
175 if (message.getPdpType().equals(subGroup.getPdpType())) {
176 pdpSubgroup = subGroup;
180 return Optional.ofNullable(pdpSubgroup);
183 private Optional<Pdp> findPdpInstance(final PdpStatus message, final PdpSubGroup subGroup) {
184 Pdp pdpInstance = null;
185 for (final Pdp pdpInstanceDetails : subGroup.getPdpInstances()) {
186 if (pdpInstanceDetails.getInstanceId().equals(message.getName())) {
187 pdpInstance = pdpInstanceDetails;
191 return Optional.ofNullable(pdpInstance);
194 private void processPdpDetails(final PdpStatus message, final PdpSubGroup pdpSubGroup, final Pdp pdpInstance,
195 final PdpGroup pdpGroup, final PolicyModelsProvider databaseProvider) throws PfModelException {
196 if (PdpState.TERMINATED.equals(message.getState())) {
197 processPdpTermination(pdpSubGroup, pdpInstance, pdpGroup, databaseProvider);
198 } else if (validatePdpDetails(message, pdpGroup, pdpSubGroup, pdpInstance)) {
199 LOGGER.debug("PdpInstance details are correct. Saving current state in DB - {}", pdpInstance);
200 updatePdpHealthStatus(message, pdpSubGroup, pdpInstance, pdpGroup, databaseProvider);
202 LOGGER.debug("PdpInstance details are not correct. Sending PdpUpdate message - {}", pdpInstance);
203 sendPdpMessage(pdpGroup.getName(), pdpSubGroup, pdpInstance.getInstanceId(), pdpInstance.getPdpState(),
208 private void processPdpTermination(final PdpSubGroup pdpSubGroup, final Pdp pdpInstance, final PdpGroup pdpGroup,
209 final PolicyModelsProvider databaseProvider) throws PfModelException {
210 pdpSubGroup.getPdpInstances().remove(pdpInstance);
211 pdpSubGroup.setCurrentInstanceCount(pdpSubGroup.getCurrentInstanceCount() - 1);
212 databaseProvider.updatePdpSubGroup(pdpGroup.getName(), pdpSubGroup);
214 LOGGER.debug("Deleted PdpInstance - {} belonging to PdpSubGroup - {} and PdpGroup - {}", pdpInstance,
215 pdpSubGroup, pdpGroup);
218 private boolean validatePdpDetails(final PdpStatus message, final PdpGroup pdpGroup, final PdpSubGroup subGroup,
219 final Pdp pdpInstanceDetails) {
222 * "EqualsBuilder" is a bit of a misnomer, as it uses containsAll() to check policies. Nevertheless, it does the
223 * job and provides a convenient way to build a bunch of comparisons.
225 return new EqualsBuilder().append(message.getPdpGroup(), pdpGroup.getName())
226 .append(message.getPdpSubgroup(), subGroup.getPdpType())
227 .append(message.getPdpType(), subGroup.getPdpType())
228 .append(message.getState(), pdpInstanceDetails.getPdpState())
229 .append(message.getPolicies().containsAll(subGroup.getPolicies()), true)
230 .append(subGroup.getPolicies().containsAll(message.getPolicies()), true).build();
233 private void updatePdpHealthStatus(final PdpStatus message, final PdpSubGroup pdpSubgroup, final Pdp pdpInstance,
234 final PdpGroup pdpGroup, final PolicyModelsProvider databaseProvider) throws PfModelException {
235 pdpInstance.setHealthy(message.getHealthy());
236 databaseProvider.updatePdp(pdpGroup.getName(), pdpSubgroup.getPdpType(), pdpInstance);
238 LOGGER.debug("Updated Pdp in DB - {}", pdpInstance);
241 private void sendPdpMessage(final String pdpGroupName, final PdpSubGroup subGroup, final String pdpInstanceId,
242 final PdpState pdpState, final PolicyModelsProvider databaseProvider) throws PfModelException {
243 final PdpUpdate pdpUpdatemessage =
244 createPdpUpdateMessage(pdpGroupName, subGroup, pdpInstanceId, databaseProvider);
245 final PdpStateChange pdpStateChangeMessage =
246 createPdpStateChangeMessage(pdpGroupName, subGroup, pdpInstanceId, pdpState);
247 requestMap.addRequest(pdpUpdatemessage, pdpStateChangeMessage);
248 LOGGER.debug("Sent PdpUpdate message - {}", pdpUpdatemessage);
249 LOGGER.debug("Sent PdpStateChange message - {}", pdpStateChangeMessage);