2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2020 Nordix Foundation.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.pap.main.rest;
24 import java.util.Collection;
25 import java.util.stream.Collectors;
26 import javax.ws.rs.core.Response.Status;
27 import org.onap.policy.common.utils.services.Registry;
28 import org.onap.policy.models.base.PfModelException;
29 import org.onap.policy.models.base.PfModelRuntimeException;
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.PdpSubGroup;
33 import org.onap.policy.models.pdp.concepts.PdpUpdate;
34 import org.onap.policy.models.provider.PolicyModelsProvider;
35 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
36 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifierOptVersion;
37 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
38 import org.onap.policy.pap.main.PapConstants;
39 import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper;
40 import org.onap.policy.pap.main.comm.PdpModifyRequestMap;
41 import org.onap.policy.pap.main.notification.PolicyNotifier;
44 * Super class of providers that deploy and undeploy PDP groups. The following items must
45 * be in the {@link Registry}:
47 * <li>PDP Modification Lock</li>
48 * <li>PDP Modify Request Map</li>
49 * <li>PAP DAO Factory</li>
52 public abstract class ProviderBase {
53 public static final String DB_ERROR_MSG = "DB error";
56 * Lock used when updating PDPs.
58 private final Object updateLock;
61 * Used to send UPDATE and STATE-CHANGE requests to the PDPs.
63 private final PdpModifyRequestMap requestMap;
66 * Generates policy notifications based on responses from PDPs.
68 private final PolicyNotifier notifier;
71 * Factory for PAP DAO.
73 private final PolicyModelsProviderFactoryWrapper daoFactory;
77 * Constructs the object.
79 public ProviderBase() {
80 this.updateLock = Registry.get(PapConstants.REG_PDP_MODIFY_LOCK, Object.class);
81 this.requestMap = Registry.get(PapConstants.REG_PDP_MODIFY_MAP, PdpModifyRequestMap.class);
82 this.daoFactory = Registry.get(PapConstants.REG_PAP_DAO_FACTORY, PolicyModelsProviderFactoryWrapper.class);
83 this.notifier = Registry.get(PapConstants.REG_POLICY_NOTIFIER, PolicyNotifier.class);
87 * Processes a policy request.
89 * @param request PDP policy request
90 * @param processor function that processes the request
91 * @throws PfModelException if an error occurred
93 protected <T> void process(T request, BiConsumerWithEx<SessionData, T> processor) throws PfModelException {
95 synchronized (updateLock) {
98 try (PolicyModelsProvider dao = daoFactory.create()) {
100 data = new SessionData(dao);
101 processor.accept(data, request);
103 // make all of the DB updates
106 } catch (PfModelException | PfModelRuntimeException e) {
109 } catch (RuntimeException e) {
110 throw new PfModelException(Status.INTERNAL_SERVER_ERROR, "request failed", e);
113 // track responses for notification purposes
114 data.getDeployData().forEach(notifier::addDeploymentData);
115 data.getUndeployData().forEach(notifier::addUndeploymentData);
117 // publish the requests
118 data.getPdpRequests().forEach(pair -> requestMap.addRequest(pair.getLeft(), pair.getRight()));
123 * Process a single policy from the request.
125 * @param data session data
126 * @param desiredPolicy request policy
127 * @throws PfModelException if an error occurred
129 protected void processPolicy(SessionData data, ToscaPolicyIdentifierOptVersion desiredPolicy)
130 throws PfModelException {
132 ToscaPolicy policy = getPolicy(data, desiredPolicy);
134 Collection<PdpGroup> groups = getGroups(data, policy.getTypeIdentifier());
135 if (groups.isEmpty()) {
136 throw new PfModelException(Status.BAD_REQUEST, "policy not supported by any PDP group: "
137 + desiredPolicy.getName() + " " + desiredPolicy.getVersion());
140 Updater updater = makeUpdater(data, policy, desiredPolicy);
142 for (PdpGroup group : groups) {
143 upgradeGroup(data, group, updater);
148 * Makes a function to update a subgroup. The function is expected to return
149 * {@code true} if the subgroup was updated, {@code false} if no update was
150 * necessary/appropriate.
152 * @param data session data
153 * @param policy policy to be added to or removed from each subgroup
154 * @param desiredPolicy request policy
155 * @return a function to update a subgroup
157 protected abstract Updater makeUpdater(SessionData data, ToscaPolicy policy,
158 ToscaPolicyIdentifierOptVersion desiredPolicy);
161 * Finds the active PDP group(s) that supports the given policy type.
163 * @param data session data
164 * @param policyType the policy type of interest
165 * @return the matching PDP group, or {@code null} if no active group supports the
167 * @throws PfModelException if an error occurred
169 private Collection<PdpGroup> getGroups(SessionData data, ToscaPolicyTypeIdentifier policyType)
170 throws PfModelException {
172 return data.getActivePdpGroupsByPolicyType(policyType);
176 * Updates a group, assigning a new version number, if it actually changes.
178 * @param data session data
179 * @param group the original group, to be updated
180 * @param updater function to update a group
181 * @throws PfModelException if an error occurred
183 private void upgradeGroup(SessionData data, PdpGroup group, Updater updater) throws PfModelException {
185 boolean updated = false;
187 for (PdpSubGroup subgroup : group.getPdpSubgroups()) {
189 if (!updater.apply(group, subgroup)) {
195 makeUpdates(data, group, subgroup);
206 * Makes UPDATE messages for each PDP in a subgroup.
208 * @param data session data
209 * @param group group containing the subgroup
210 * @param subgroup subgroup whose PDPs should receive messages
212 protected void makeUpdates(SessionData data, PdpGroup group, PdpSubGroup subgroup) {
213 for (Pdp pdp : subgroup.getPdpInstances()) {
214 data.addUpdate(makeUpdate(data, group, subgroup, pdp));
219 * Makes an UPDATE message for a particular PDP.
221 * @param data session data
222 * @param group group to which the PDP should belong
223 * @param subgroup subgroup to which the PDP should belong
224 * @param pdp the PDP of interest
225 * @return a new UPDATE message
227 private PdpUpdate makeUpdate(SessionData data, PdpGroup group, PdpSubGroup subgroup, Pdp pdp) {
229 PdpUpdate update = new PdpUpdate();
231 update.setName(pdp.getInstanceId());
232 update.setDescription(group.getDescription());
233 update.setPdpGroup(group.getName());
234 update.setPdpSubgroup(subgroup.getPdpType());
235 update.setPolicies(subgroup.getPolicies().stream().map(ToscaPolicyIdentifierOptVersion::new)
236 .map(ident -> getPolicy(data, ident)).collect(Collectors.toList()));
242 * Gets the specified policy.
244 * @param data session data
245 * @param ident policy identifier, with an optional version
246 * @return the policy of interest
247 * @throws PfModelRuntimeException if an error occurred or the policy was not found
249 private ToscaPolicy getPolicy(SessionData data, ToscaPolicyIdentifierOptVersion ident) {
251 ToscaPolicy policy = data.getPolicy(ident);
252 if (policy == null) {
253 throw new PfModelRuntimeException(Status.NOT_FOUND,
254 "cannot find policy: " + ident.getName() + " " + ident.getVersion());
259 } catch (PfModelException e) {
260 throw new PfModelRuntimeException(e.getErrorResponse().getResponseCode(),
261 e.getErrorResponse().getErrorMessage(), e);
266 public static interface BiConsumerWithEx<F, S> {
268 * Performs this operation on the given arguments.
270 * @param firstArg the first input argument
271 * @param secondArg the second input argument
272 * @throws PfModelException if an error occurred
274 void accept(F firstArg, S secondArg) throws PfModelException;
278 public static interface Updater {
279 boolean apply(PdpGroup group, PdpSubGroup subgroup) throws PfModelException;