Adding pdpGroup to PdpRegistrationHandler
[policy/pap.git] / main / src / main / java / org / onap / policy / pap / main / comm / PdpStatusMessageHandler.java
1 /*-
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.pap.main.comm;
23
24 import java.util.List;
25 import java.util.Optional;
26
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;
43
44
45 /**
46  * Handler for PDP Status messages which either represent registration or heart beat.
47  *
48  * @author Ram Krishna Verma (ram.krishna.verma@est.tech)
49  */
50 public class PdpStatusMessageHandler extends PdpMessageGenerator {
51     private static final Logger LOGGER = LoggerFactory.getLogger(PdpStatusMessageHandler.class);
52
53     /**
54      * Constructs the object.
55      */
56     public PdpStatusMessageHandler() {
57         super(true);
58     }
59
60     /**
61      * Handles the PdpStatus message coming from various PDP's.
62      *
63      * @param message the PdpStatus message
64      */
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);
70                 } else {
71                     handlePdpHeartbeat(message, databaseProvider);
72                 }
73
74                 /*
75                  * Indicate that a heart beat was received from the PDP. This is invoked only if handleXxx() does not
76                  * throw an exception.
77                  */
78                 if (message.getName() != null) {
79                     final PdpTracker pdpTracker = Registry.get(PapConstants.REG_PDP_TRACKER);
80                     pdpTracker.add(message.getName());
81                 }
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);
86             }
87         }
88     }
89
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);
96         }
97     }
98
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();
104
105         final List<PdpGroup> pdpGroups = databaseProvider.getFilteredPdpGroups(filter);
106         if (!pdpGroups.isEmpty()) {
107             pdpGroupFound = registerPdp(message, databaseProvider, pdpGroups.get(0));
108         }
109         return pdpGroupFound;
110     }
111
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);
121             }
122             sendPdpMessage(finalizedPdpGroup.getName(), subGroup.get(), message.getName(), null, databaseProvider);
123             pdpGroupFound = true;
124         }
125         return pdpGroupFound;
126     }
127
128     private void updatePdpSubGroup(final PdpGroup pdpGroup, final PdpSubGroup pdpSubGroup, final PdpStatus message,
129             final PolicyModelsProvider databaseProvider) throws PfModelException {
130
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);
137
138         pdpSubGroup.setCurrentInstanceCount(pdpSubGroup.getCurrentInstanceCount() + 1);
139
140         databaseProvider.updatePdpSubGroup(pdpGroup.getName(), pdpSubGroup);
141
142         LOGGER.debug("Updated PdpSubGroup in DB - {} belonging to PdpGroup - {}", pdpSubGroup, pdpGroup);
143     }
144
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;
150
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;
162                 }
163             }
164         }
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);
169         }
170     }
171
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;
177                 break;
178             }
179         }
180         return Optional.ofNullable(pdpSubgroup);
181     }
182
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;
188                 break;
189             }
190         }
191         return Optional.ofNullable(pdpInstance);
192     }
193
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);
201         } else {
202             LOGGER.debug("PdpInstance details are not correct. Sending PdpUpdate message - {}", pdpInstance);
203             sendPdpMessage(pdpGroup.getName(), pdpSubGroup, pdpInstance.getInstanceId(), pdpInstance.getPdpState(),
204                     databaseProvider);
205         }
206     }
207
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);
213
214         LOGGER.debug("Deleted PdpInstance - {} belonging to PdpSubGroup - {} and PdpGroup - {}", pdpInstance,
215                 pdpSubGroup, pdpGroup);
216     }
217
218     private boolean validatePdpDetails(final PdpStatus message, final PdpGroup pdpGroup, final PdpSubGroup subGroup,
219             final Pdp pdpInstanceDetails) {
220
221         /*
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.
224          */
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();
231     }
232
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);
237
238         LOGGER.debug("Updated Pdp in DB - {}", pdpInstance);
239     }
240
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);
250     }
251 }