e0b00c71b4a6d0fc9ba678d061b5b1d4bbf6d272
[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  * ================================================================================
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.pap.main.comm;
22
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Optional;
26 import org.apache.commons.lang3.tuple.Pair;
27 import org.onap.policy.common.utils.services.Registry;
28 import org.onap.policy.models.base.PfModelException;
29 import org.onap.policy.models.pdp.concepts.Pdp;
30 import org.onap.policy.models.pdp.concepts.PdpGroup;
31 import org.onap.policy.models.pdp.concepts.PdpGroupFilter;
32 import org.onap.policy.models.pdp.concepts.PdpStateChange;
33 import org.onap.policy.models.pdp.concepts.PdpStatistics;
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.models.tosca.authorative.concepts.ToscaPolicy;
40 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
41 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
42 import org.onap.policy.pap.main.PapConstants;
43 import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper;
44 import org.onap.policy.pap.main.PolicyPapException;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48
49 /**
50  * Handler for PDP Status messages which either represent registration or heart beat.
51  *
52  * @author Ram Krishna Verma (ram.krishna.verma@est.tech)
53  */
54 public class PdpStatusMessageHandler {
55
56     private static final Logger LOGGER = LoggerFactory.getLogger(PdpStatusMessageHandler.class);
57
58     /**
59      * Handles the PdpStatus message coming from various PDP's.
60      *
61      * @param message the PdpStatus message
62      */
63     public void handlePdpStatus(final PdpStatus message) {
64         final PolicyModelsProviderFactoryWrapper modelProviderWrapper =
65                 Registry.get(PapConstants.REG_PAP_DAO_FACTORY, PolicyModelsProviderFactoryWrapper.class);
66         try (PolicyModelsProvider databaseProvider = modelProviderWrapper.create()) {
67             if (message.getPdpGroup().isEmpty() && message.getPdpSubgroup().isEmpty()) {
68                 handlePdpRegistration(message, databaseProvider);
69             } else {
70                 handlePdpHeartbeat(message, databaseProvider);
71             }
72         } catch (final PolicyPapException exp) {
73             LOGGER.error("Operation Failed", exp);
74         } catch (final Exception exp) {
75             LOGGER.error("Failed connecting to database provider", exp);
76         }
77     }
78
79     private void handlePdpRegistration(final PdpStatus message, final PolicyModelsProvider databaseProvider)
80             throws PfModelException, PolicyPapException {
81         if (!findAndUpdatePdpGroup(message, databaseProvider)) {
82             final String errorMessage = "Failed to register PDP. No matching PdpGroup/SubGroup Found - ";
83             LOGGER.debug("{}{}", errorMessage, message);
84             throw new PolicyPapException(errorMessage + message);
85         }
86     }
87
88     private boolean findAndUpdatePdpGroup(final PdpStatus message, final PolicyModelsProvider databaseProvider)
89             throws PfModelException {
90         boolean pdpGroupFound = false;
91         Optional<PdpSubGroup> subGroup = null;
92         final List<Pair<String, String>> supportedPolicyTypesPair = createSupportedPolictTypesPair(message);
93         final PdpGroupFilter filter = PdpGroupFilter.builder().pdpType(message.getPdpType()).build();
94         // TODO setSupportedTypes(supportedPolicyTypesPair)
95         final List<PdpGroup> pdpGroups =
96                 databaseProvider.getFilteredPdpGroups(filter);
97         for (final PdpGroup pdpGroup : pdpGroups) {
98             subGroup = findPdpSubGroup(message, pdpGroup);
99             if (subGroup.isPresent()) {
100                 LOGGER.debug("Found pdpGroup - {}, going for registration of PDP - {}", pdpGroup, message);
101                 if (!findPdpInstance(message, subGroup.get()).isPresent()) {
102                     updatePdpSubGroup(pdpGroup, subGroup.get(), message, databaseProvider);
103                 }
104                 sendPdpMessage(pdpGroup.getName(), subGroup.get(), message.getName(), null, databaseProvider);
105                 pdpGroupFound = true;
106                 break;
107             }
108         }
109         return pdpGroupFound;
110     }
111
112     private List<Pair<String, String>> createSupportedPolictTypesPair(final PdpStatus message) {
113         final List<Pair<String, String>> supportedPolicyTypesPair = new ArrayList<>();
114         for (final ToscaPolicyTypeIdentifier policyTypeIdent : message.getSupportedPolicyTypes()) {
115             supportedPolicyTypesPair.add(Pair.of(policyTypeIdent.getName(), policyTypeIdent.getVersion()));
116         }
117         return supportedPolicyTypesPair;
118     }
119
120     private void updatePdpSubGroup(final PdpGroup pdpGroup, final PdpSubGroup pdpSubGroup, final PdpStatus message,
121             final PolicyModelsProvider databaseProvider) throws PfModelException {
122
123         final Pdp pdpInstance = new Pdp();
124         pdpInstance.setInstanceId(message.getName());
125         pdpInstance.setPdpState(message.getState());
126         pdpInstance.setHealthy(message.getHealthy());
127         pdpInstance.setMessage(message.getDescription());
128         pdpSubGroup.getPdpInstances().add(pdpInstance);
129
130         pdpSubGroup.setCurrentInstanceCount(pdpSubGroup.getCurrentInstanceCount() + 1);
131
132         databaseProvider.updatePdpSubGroup(pdpGroup.getName(), pdpGroup.getVersion(), pdpSubGroup);
133
134         LOGGER.debug("Updated PdpSubGroup in DB - {} belonging to PdpGroup - {}", pdpSubGroup, pdpGroup);
135     }
136
137     private void handlePdpHeartbeat(final PdpStatus message, final PolicyModelsProvider databaseProvider)
138             throws PfModelException, PolicyPapException {
139         boolean pdpInstanceFound = false;
140         Optional<PdpSubGroup> pdpSubgroup = null;
141         Optional<Pdp> pdpInstance = null;
142
143         final PdpGroupFilter filter = PdpGroupFilter.builder().name(message.getPdpGroup())
144                         .version(PdpGroupFilter.LATEST_VERSION).build();
145         final List<PdpGroup> pdpGroups = databaseProvider.getFilteredPdpGroups(filter);
146         if (!pdpGroups.isEmpty()) {
147             final PdpGroup pdpGroup = pdpGroups.get(0);
148             pdpSubgroup = findPdpSubGroup(message, pdpGroup);
149             if (pdpSubgroup.isPresent()) {
150                 pdpInstance = findPdpInstance(message, pdpSubgroup.get());
151                 if (pdpInstance.isPresent()) {
152                     processPdpDetails(message, pdpSubgroup.get(), pdpInstance.get(), pdpGroup, databaseProvider);
153                     pdpInstanceFound = true;
154                 }
155             }
156         }
157         if (!pdpInstanceFound) {
158             final String errorMessage = "Failed to process heartbeat. No matching PdpGroup/SubGroup Found - ";
159             LOGGER.debug("{}{}", errorMessage, message);
160             throw new PolicyPapException(errorMessage + message);
161         }
162     }
163
164     private Optional<PdpSubGroup> findPdpSubGroup(final PdpStatus message, final PdpGroup pdpGroup) {
165         PdpSubGroup pdpSubgroup = null;
166         for (final PdpSubGroup subGroup : pdpGroup.getPdpSubgroups()) {
167             if (message.getPdpSubgroup().equals(subGroup.getPdpType())) {
168                 pdpSubgroup = subGroup;
169                 break;
170             }
171         }
172         return Optional.ofNullable(pdpSubgroup);
173     }
174
175     private Optional<Pdp> findPdpInstance(final PdpStatus message, final PdpSubGroup subGroup) {
176         Pdp pdpInstance = null;
177         for (final Pdp pdpInstanceDetails : subGroup.getPdpInstances()) {
178             if (pdpInstanceDetails.getInstanceId().equals(message.getName())) {
179                 pdpInstance = pdpInstanceDetails;
180                 break;
181             }
182         }
183         return Optional.ofNullable(pdpInstance);
184     }
185
186     private void processPdpDetails(final PdpStatus message, final PdpSubGroup pdpSubgroup, final Pdp pdpInstance,
187             final PdpGroup pdpGroup, final PolicyModelsProvider databaseProvider) throws PfModelException {
188         if (validatePdpDetails(message, pdpGroup, pdpSubgroup, pdpInstance)) {
189             LOGGER.debug("PdpInstance details are correct. Saving current state in DB - {}", pdpInstance);
190             updatePdpHealthStatus(message, pdpSubgroup, pdpInstance, pdpGroup, databaseProvider);
191             updatePdpStatistics(message, pdpSubgroup, pdpInstance, pdpGroup, databaseProvider);
192         } else {
193             LOGGER.debug("PdpInstance details are not correct. Sending PdpUpdate message - {}", pdpInstance);
194             sendPdpMessage(pdpGroup.getName(), pdpSubgroup, pdpInstance.getInstanceId(), pdpInstance.getPdpState(),
195                     databaseProvider);
196         }
197     }
198
199     private boolean validatePdpDetails(final PdpStatus message, final PdpGroup pdpGroup, final PdpSubGroup subGroup,
200             final Pdp pdpInstanceDetails) {
201
202         return message.getPdpGroup().equals(pdpGroup.getName())
203                 && message.getPdpSubgroup().equals(subGroup.getPdpType())
204                 && message.getState().equals(pdpInstanceDetails.getPdpState())
205                 && message.getSupportedPolicyTypes().containsAll(subGroup.getSupportedPolicyTypes())
206                 && message.getPdpType().equals(subGroup.getPdpType());
207     }
208
209     private void updatePdpHealthStatus(final PdpStatus message, final PdpSubGroup pdpSubgroup, final Pdp pdpInstance,
210             final PdpGroup pdpGroup, final PolicyModelsProvider databaseProvider) throws PfModelException {
211         pdpInstance.setHealthy(message.getHealthy());
212         databaseProvider.updatePdp(pdpGroup.getName(), pdpGroup.getVersion(), pdpSubgroup.getPdpType(), pdpInstance);
213
214         LOGGER.debug("Updated Pdp in DB - {}", pdpInstance);
215     }
216
217     private void updatePdpStatistics(final PdpStatus message, final PdpSubGroup pdpSubgroup, final Pdp pdpInstance,
218             final PdpGroup pdpGroup, final PolicyModelsProvider databaseProvider) throws PfModelException {
219         final PdpStatistics pdpStatistics = new PdpStatistics();
220         pdpStatistics.setPdpInstanceId(message.getName());
221         pdpStatistics.setPolicyDeployCount(message.getStatistics().getPolicyDeployCount());
222         pdpStatistics.setPolicyDeploySuccessCount(message.getStatistics().getPolicyDeploySuccessCount());
223         pdpStatistics.setPolicyDeployFailCount(message.getStatistics().getPolicyDeployFailCount());
224         pdpStatistics.setPolicyExecutedCount(message.getStatistics().getPolicyExecutedCount());
225         pdpStatistics.setPolicyExecutedSuccessCount(message.getStatistics().getPolicyExecutedSuccessCount());
226         pdpStatistics.setPolicyExecutedFailCount(message.getStatistics().getPolicyExecutedFailCount());
227
228         databaseProvider.updatePdpStatistics(pdpGroup.getName(), pdpGroup.getVersion(), pdpSubgroup.getPdpType(),
229                 pdpInstance.getInstanceId(), pdpStatistics);
230
231         LOGGER.debug("Updated PdpStatistics in DB - {}", pdpStatistics);
232     }
233
234     private void sendPdpMessage(final String pdpGroupName, final PdpSubGroup subGroup, final String pdpInstanceId,
235             final PdpState pdpState, final PolicyModelsProvider databaseProvider) throws PfModelException {
236         final PdpUpdate pdpUpdatemessage =
237                 createPdpUpdateMessage(pdpGroupName, subGroup, pdpInstanceId, databaseProvider);
238         final PdpStateChange pdpStateChangeMessage =
239                 createPdpStateChangeMessage(pdpGroupName, subGroup, pdpInstanceId, pdpState);
240         final PdpModifyRequestMap requestMap = Registry.get(PapConstants.REG_PDP_MODIFY_MAP, PdpModifyRequestMap.class);
241         requestMap.addRequest(pdpUpdatemessage, pdpStateChangeMessage);
242         LOGGER.debug("Sent PdpUpdate message - {}", pdpUpdatemessage);
243         LOGGER.debug("Sent PdpStateChange message - {}", pdpStateChangeMessage);
244     }
245
246     private PdpUpdate createPdpUpdateMessage(final String pdpGroupName, final PdpSubGroup subGroup,
247             final String pdpInstanceId, final PolicyModelsProvider databaseProvider) throws PfModelException {
248
249         final PdpUpdate update = new PdpUpdate();
250         update.setName(pdpInstanceId);
251         update.setPdpGroup(pdpGroupName);
252         update.setPdpSubgroup(subGroup.getPdpType());
253         update.setPolicies(getToscaPolicies(subGroup, databaseProvider));
254
255         LOGGER.debug("Created PdpUpdate message - {}", update);
256         return update;
257     }
258
259     private List<ToscaPolicy> getToscaPolicies(final PdpSubGroup subGroup, final PolicyModelsProvider databaseProvider)
260             throws PfModelException {
261         final List<ToscaPolicy> policies = new ArrayList<>();
262         for (final ToscaPolicyIdentifier policyIdentifier : subGroup.getPolicies()) {
263             policies.addAll(databaseProvider.getPolicyList(policyIdentifier.getName(), policyIdentifier.getVersion()));
264         }
265         LOGGER.debug("Created ToscaPolicy list - {}", policies);
266         return policies;
267     }
268
269     private PdpStateChange createPdpStateChangeMessage(final String pdpGroupName, final PdpSubGroup subGroup,
270             final String pdpInstanceId, final PdpState pdpState) {
271
272         final PdpStateChange stateChange = new PdpStateChange();
273         stateChange.setName(pdpInstanceId);
274         stateChange.setPdpGroup(pdpGroupName);
275         stateChange.setPdpSubgroup(subGroup.getPdpType());
276         stateChange.setState(pdpState == null ? PdpState.ACTIVE : pdpState);
277         LOGGER.debug("Created PdpStateChange message - {}", stateChange);
278         return stateChange;
279     }
280 }