From 4e5bcfe2a7aeccebcea55c0146a38a931567ea75 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Mon, 11 Jan 2021 10:53:54 -0500 Subject: Make PAP stateless Removed old code that tracked the status using a cache. Modified the code to use the status found in the DB instead. Issue-ID: POLICY-2648 Change-Id: I4f1f5201eff7b3352631f50d67c40349ac7f2014 Signed-off-by: Jim Hahn --- .../policy/pap/main/comm/PdpModifyRequestMap.java | 16 +- .../policy/pap/main/comm/msgdata/UpdateReq.java | 12 +- .../pap/main/notification/DeploymentStatus.java | 10 +- .../pap/main/notification/DeploymentTracker.java | 8 + .../pap/main/notification/PolicyCommonTracker.java | 245 --------------- .../pap/main/notification/PolicyDeployTracker.java | 54 ---- .../pap/main/notification/PolicyNotifier.java | 201 ++---------- .../notification/PolicyPdpNotificationData.java | 86 ----- .../pap/main/notification/PolicyTrackerData.java | 193 ------------ .../main/notification/PolicyUndeployTracker.java | 52 --- .../main/rest/PdpGroupCreateOrUpdateProvider.java | 9 +- .../pap/main/rest/PdpGroupDeleteProvider.java | 4 +- .../pap/main/rest/PdpGroupDeployProvider.java | 24 +- .../pap/main/rest/PolicyStatusControllerV1.java | 72 +++-- .../policy/pap/main/rest/PolicyStatusProvider.java | 95 ++++++ .../policy/pap/main/rest/PolicyUndeployerImpl.java | 4 +- .../onap/policy/pap/main/rest/ProviderBase.java | 13 +- .../org/onap/policy/pap/main/rest/SessionData.java | 104 +++--- .../org/onap/policy/pap/main/startstop/Main.java | 10 +- main/src/main/resources/META-INF/persistence.xml | 2 + .../pap/main/comm/PdpModifyRequestMapTest.java | 41 ++- .../pap/main/comm/msgdata/UpdateReqTest.java | 12 +- .../pap/main/notification/PolicyCommonSupport.java | 94 ------ .../main/notification/PolicyCommonTrackerTest.java | 347 -------------------- .../main/notification/PolicyDeployTrackerTest.java | 250 --------------- .../pap/main/notification/PolicyNotifierTest.java | 245 +++------------ .../PolicyPdpNotificationDataTest.java | 121 ------- .../main/notification/PolicyTrackerDataTest.java | 350 --------------------- .../notification/PolicyUndeployTrackerTest.java | 264 ---------------- .../onap/policy/pap/main/rest/ProviderSuper.java | 13 +- .../rest/TestPdpGroupCreateOrUpdateProvider.java | 6 +- .../pap/main/rest/TestPdpGroupDeleteProvider.java | 4 +- .../pap/main/rest/TestPdpGroupDeployProvider.java | 50 +-- .../pap/main/rest/TestPolicyStatusProvider.java | 152 +++++++++ .../policy/pap/main/rest/TestProviderBase.java | 36 +-- .../onap/policy/pap/main/rest/TestSessionData.java | 89 +++--- .../onap/policy/pap/main/rest/e2e/End2EndBase.java | 30 +- .../policy/pap/main/rest/e2e/PolicyStatusTest.java | 12 +- main/src/test/resources/META-INF/persistence.xml | 2 + main/src/test/resources/e2e/policyStatus.json | 65 +--- 40 files changed, 623 insertions(+), 2774 deletions(-) delete mode 100644 main/src/main/java/org/onap/policy/pap/main/notification/PolicyCommonTracker.java delete mode 100644 main/src/main/java/org/onap/policy/pap/main/notification/PolicyDeployTracker.java delete mode 100644 main/src/main/java/org/onap/policy/pap/main/notification/PolicyPdpNotificationData.java delete mode 100644 main/src/main/java/org/onap/policy/pap/main/notification/PolicyTrackerData.java delete mode 100644 main/src/main/java/org/onap/policy/pap/main/notification/PolicyUndeployTracker.java create mode 100644 main/src/main/java/org/onap/policy/pap/main/rest/PolicyStatusProvider.java delete mode 100644 main/src/test/java/org/onap/policy/pap/main/notification/PolicyCommonSupport.java delete mode 100644 main/src/test/java/org/onap/policy/pap/main/notification/PolicyCommonTrackerTest.java delete mode 100644 main/src/test/java/org/onap/policy/pap/main/notification/PolicyDeployTrackerTest.java delete mode 100644 main/src/test/java/org/onap/policy/pap/main/notification/PolicyPdpNotificationDataTest.java delete mode 100644 main/src/test/java/org/onap/policy/pap/main/notification/PolicyTrackerDataTest.java delete mode 100644 main/src/test/java/org/onap/policy/pap/main/notification/PolicyUndeployTrackerTest.java create mode 100644 main/src/test/java/org/onap/policy/pap/main/rest/TestPolicyStatusProvider.java (limited to 'main/src') diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/PdpModifyRequestMap.java b/main/src/main/java/org/onap/policy/pap/main/comm/PdpModifyRequestMap.java index 85038dee..fb19b01a 100644 --- a/main/src/main/java/org/onap/policy/pap/main/comm/PdpModifyRequestMap.java +++ b/main/src/main/java/org/onap/policy/pap/main/comm/PdpModifyRequestMap.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP PAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2021 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import lombok.Setter; import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.pap.concepts.PolicyNotification; import org.onap.policy.models.pdp.concepts.Pdp; import org.onap.policy.models.pdp.concepts.PdpGroup; import org.onap.policy.models.pdp.concepts.PdpGroupFilter; @@ -45,6 +46,7 @@ import org.onap.policy.pap.main.comm.msgdata.Request; import org.onap.policy.pap.main.comm.msgdata.RequestListener; import org.onap.policy.pap.main.comm.msgdata.StateChangeReq; import org.onap.policy.pap.main.comm.msgdata.UpdateReq; +import org.onap.policy.pap.main.notification.DeploymentStatus; import org.onap.policy.pap.main.notification.PolicyNotifier; import org.onap.policy.pap.main.parameters.PdpModifyRequestMapParams; import org.onap.policy.pap.main.parameters.RequestParams; @@ -264,9 +266,13 @@ public class PdpModifyRequestMap { List groups = dao.getFilteredPdpGroups(filter); List updates = new ArrayList<>(1); + DeploymentStatus status = new DeploymentStatus(dao); + for (PdpGroup group : groups) { if (removeFromGroup(pdpName, group)) { updates.add(group); + status.loadByGroup(group.getName()); + status.deleteDeployment(pdpName); } } @@ -275,6 +281,12 @@ public class PdpModifyRequestMap { } else { dao.updatePdpGroups(updates); + + PolicyNotification notification = new PolicyNotification(); + status.flush(notification); + + policyNotifier.publish(notification); + return true; } } @@ -448,8 +460,6 @@ public class PdpModifyRequestMap { logger.warn("removing {}", pdpName); - policyNotifier.removePdp(pdpName); - // remove the PDP from all groups try { removeFromGroups(pdpName); diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java index ada9d193..4b5b7f04 100644 --- a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java +++ b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP PAP * ================================================================================ - * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2021 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -77,9 +77,6 @@ public class UpdateReq extends RequestImpl { return reason; } - Set actualSet = new HashSet<>(alwaysList(response.getPolicies())); - getNotifier().processResponse(response.getName(), actualSet); - PdpUpdate message = getMessage(); if (!StringUtils.equals(message.getPdpGroup(), response.getPdpGroup())) { @@ -94,11 +91,14 @@ public class UpdateReq extends RequestImpl { return null; } - // see if the policies match - + Set actualSet = new HashSet<>(alwaysList(response.getPolicies())); Set expectedSet = new HashSet<>(alwaysList(message.getPolicies()).stream() .map(ToscaPolicy::getIdentifier).collect(Collectors.toSet())); + getNotifier().processResponse(response.getName(), message.getPdpGroup(), expectedSet, actualSet); + + // see if the policies match + if (!actualSet.equals(expectedSet)) { // need to undeploy the policies that are expected, but missing from the // response diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/DeploymentStatus.java b/main/src/main/java/org/onap/policy/pap/main/notification/DeploymentStatus.java index ef97fae9..7b627803 100644 --- a/main/src/main/java/org/onap/policy/pap/main/notification/DeploymentStatus.java +++ b/main/src/main/java/org/onap/policy/pap/main/notification/DeploymentStatus.java @@ -41,7 +41,14 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.pap.main.notification.StatusAction.Action; /** - * Collection of Policy Deployment Status records. + * Collection of Policy Deployment Status records. The sequence of method invocations + * should be as follows: + *
    + *
  1. {@link #loadByGroup(String)}
  2. + *
  3. various other methods
  4. + *
  5. repeat the previous steps as appropriate
  6. + *
  7. {@link #flush(PolicyNotification)}
  8. + *
*/ public class DeploymentStatus { /** @@ -115,6 +122,7 @@ public class DeploymentStatus { * @param notif notification to which to add policy status */ public void flush(PolicyNotification notif) { + // must add notifications BEFORE deleting undeployments addNotifications(notif); deleteUndeployments(); flush(); diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/DeploymentTracker.java b/main/src/main/java/org/onap/policy/pap/main/notification/DeploymentTracker.java index cef70a39..4522debb 100644 --- a/main/src/main/java/org/onap/policy/pap/main/notification/DeploymentTracker.java +++ b/main/src/main/java/org/onap/policy/pap/main/notification/DeploymentTracker.java @@ -146,6 +146,14 @@ public class DeploymentTracker { newStatus.setPolicyTypeId(status.getPolicyTypeId()); newStatus.setPolicyTypeVersion(status.getPolicyTypeVersion()); + /* + * Adding the status to the "added" set may be a bit unexpected, but when all + * status records are deleted from the group, we don't actually undeploy the + * policy from the subgroup. Instead, we leave it in the subgroup so that as + * soon as a PDP registers, we immediately deploy the policy to the PDP and + * continue on; the client can always undeploy the policy when it receives the + * notification, if so desired. + */ notif.getAdded().add(newStatus); } } diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyCommonTracker.java b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyCommonTracker.java deleted file mode 100644 index 3529ccb7..00000000 --- a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyCommonTracker.java +++ /dev/null @@ -1,245 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP PAP - * ================================================================================ - * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2020 Bell Canada. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.pap.main.notification; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; -import java.util.function.BiPredicate; -import java.util.stream.Collectors; -import org.onap.policy.models.pap.concepts.PolicyStatus; -import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; - -/** - * Common super class for deploy and undeploy trackers. - */ -public abstract class PolicyCommonTracker { - - /** - * Maps a policy id to its deployment data. The subclass determines when an entry is - * removed. - * - *

- * Use a LinkedHashMap, because we'll be doing lots of iteration over the map, and - * iteration over a LinkedHashMap is faster than over a plain HashMap. - */ - private final Map policy2data = new LinkedHashMap<>(); - - - /** - * Constructs the object. - */ - protected PolicyCommonTracker() { - super(); - } - - /** - * Gets the status of all policies being tracked. - * - * @return the status of all policies - */ - public List getStatus() { - return policy2data.entrySet().stream().map(this::makeStatus).collect(Collectors.toList()); - } - - /** - * Gets the status of all versions of a policy. - * - * @param policyId ID of the policy of interest, without the version - * @return the status of all versions of the policy having the given ID - */ - public List getStatus(String policyId) { - // version is not specified - have to scan the whole list - return policy2data.entrySet().stream().filter(ent -> ent.getKey().getName().equals(policyId)) - .map(this::makeStatus).collect(Collectors.toList()); - } - - /** - * Gets the status of a particular policy. - * - * @param ident identifier of the policy of interest - * @return the status of the given policy, or empty if the policy is not found - */ - public Optional getStatus(ToscaConceptIdentifier ident) { - ToscaConceptIdentifier ident2 = new ToscaConceptIdentifier(ident.getName(), ident.getVersion()); - PolicyTrackerData data = policy2data.get(ident2); - return Optional.ofNullable(data == null ? null : makeStatus(ident2, data)); - } - - /** - * Adds data to the tracker. - * - * @param data data to be added to the tracker - */ - public void addData(PolicyPdpNotificationData data) { - policy2data.computeIfAbsent(data.getPolicyId(), policyId -> new PolicyTrackerData(data.getPolicyType())) - .addPdps(data.getPdps()); - } - - /** - * Removes a set of PDPs from all policies within the tracker. - * - * @param notifyData data identifying the policy and the PDPs to be removed from it - */ - public void removeData(PolicyPdpNotificationData notifyData) { - - policy2data.computeIfPresent(notifyData.getPolicyId(), (policyId, data) -> { - - if (!data.removePdps(notifyData.getPdps())) { - // not complete yet - return data; - } - - // this policy is complete - return (shouldRemove(data) ? null : data); - }); - } - - /** - * Removes a PDP from all policies within the tracker. - * - * @param pdp PDP to be removed - * @param statusList status messages are added here if policies become complete as a - * result of this operation - */ - public void removePdp(String pdp, List statusList) { - updateMap(statusList, (policyId, data) -> data.removePdp(pdp)); - } - - /** - * Processes a response from a PDP. - * - * @param pdp PDP of interest - * @param activePolicies policies that are still active on the PDP, as specified in - * the response - * @param statusList status messages are added here if policies become complete as a - * result of this operation - */ - public void processResponse(String pdp, Collection activePolicies, - List statusList) { - processResponse(pdp, new HashSet<>(activePolicies), statusList); - } - - /** - * Processes a response from a PDP. - * - * @param pdp PDP of interest - * @param activePolicies policies that are still active on the PDP, as specified in - * the response - * @param statusList status messages are added here if policies become complete as a - * result of this operation - */ - public void processResponse(String pdp, Set activePolicies, List statusList) { - updateMap(statusList, (policyId, data) -> updateData(pdp, data, activePolicies.contains(policyId))); - } - - /** - * Updates the map. - * - *

- * Note: this iterates through the whole map. While it may be more efficient to - * iterate through just the policies relevant to the PDP, that would complicate the - * code and complicate the testing. In addition, this should still perform well - * enough, but if not, it can always be enhanced. - * - * @param statusList status messages are added here if policies become complete as a - * result of this operation - * @param updater function to update a policy's data. Returns {@code true} if the - * policy is complete (i.e., no longer awaiting any responses) - */ - private void updateMap(List statusList, - BiPredicate updater) { - - Iterator> iter = policy2data.entrySet().iterator(); - while (iter.hasNext()) { - Entry ent = iter.next(); - - ToscaConceptIdentifier policyId = ent.getKey(); - PolicyTrackerData data = ent.getValue(); - - if (!updater.test(policyId, data)) { - // not complete yet - continue; - } - - // this policy is complete - notify - statusList.add(makeStatus(ent)); - - if (shouldRemove(data)) { - iter.remove(); - } - } - } - - /** - * Updates the policy data, based on a response from a PDP. - * - * @param pdp PDP whose response was just received - * @param data data associated with the policy of interest - * @param stillActive {@code true} if the policy is still active for the PDP, - * {@code false} otherwise - * @return {@code true} if the policy is complete (i.e., no longer awaiting any - * responses), {@code false} otherwise - */ - protected abstract boolean updateData(String pdp, PolicyTrackerData data, boolean stillActive); - - /** - * Determines if a policy should be removed from the tracker, based on the state of - * its data. - * - * @param data data associated with the policy of interest - * @return {@code true} if the policy should be removed from the tracker, - * {@code false} otherwise - */ - protected abstract boolean shouldRemove(PolicyTrackerData data); - - /** - * Makes a status notification for the given policy entry. - * - * @param entry policy entry - * @return a new status notification - */ - private PolicyStatus makeStatus(Map.Entry entry) { - return makeStatus(entry.getKey(), entry.getValue()); - } - - /** - * Makes a status notification for the given policy. - * - * @param policyId policy ID - * @param data data to be used to set the status fields - * @return a new status notification - */ - private PolicyStatus makeStatus(ToscaConceptIdentifier policyId, PolicyTrackerData data) { - - PolicyStatus status = new PolicyStatus(data.getPolicyType(), policyId); - data.putValuesInto(status); - return status; - } -} diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyDeployTracker.java b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyDeployTracker.java deleted file mode 100644 index 17a5e211..00000000 --- a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyDeployTracker.java +++ /dev/null @@ -1,54 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP PAP - * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.pap.main.notification; - -/** - * Tracker for policy deployments to PDPs. - * - *

- * Policies are not removed from the internal map until all of the sets contained within - * the data are empty. This may be the result of a PDP being removed from the system - * because it is no longer responsive, or because the PDP Subgroup that contained it is - * deleted. - */ -public class PolicyDeployTracker extends PolicyCommonTracker { - - /** - * Constructs the object. - */ - public PolicyDeployTracker() { - super(); - } - - @Override - protected boolean updateData(String pdp, PolicyTrackerData data, boolean stillActive) { - return (stillActive ? data.success(pdp) : data.fail(pdp)); - } - - /** - * Returns {@code true} only when the data is completely empty (i.e., it has no - * more PDPs) - */ - @Override - protected boolean shouldRemove(PolicyTrackerData data) { - return data.isEmpty(); - } -} diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyNotifier.java b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyNotifier.java index c13e9b78..66b83ccc 100644 --- a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyNotifier.java +++ b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyNotifier.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP PAP * ================================================================================ - * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020-2021 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,24 +21,11 @@ package org.onap.policy.pap.main.notification; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.pap.concepts.PolicyNotification; -import org.onap.policy.models.pap.concepts.PolicyStatus; -import org.onap.policy.models.pdp.concepts.Pdp; -import org.onap.policy.models.pdp.concepts.PdpGroup; -import org.onap.policy.models.pdp.concepts.PdpSubGroup; import org.onap.policy.models.provider.PolicyModelsProvider; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; -import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; -import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyFilter; import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper; import org.onap.policy.pap.main.comm.Publisher; import org.onap.policy.pap.main.comm.QueueToken; @@ -56,15 +43,7 @@ public class PolicyNotifier { */ private final Publisher publisher; - /** - * Deployment tracker. - */ - private final PolicyDeployTracker deployTracker = makeDeploymentTracker(); - - /** - * Undeployment tracker. - */ - private final PolicyUndeployTracker undeployTracker = makeUndeploymentTracker(); + private final PolicyModelsProviderFactoryWrapper daoFactory; /** @@ -72,170 +51,38 @@ public class PolicyNotifier { * * @param publisher notification publisher * @param daoFactory factory used to load policy deployment data from the DB - * @throws PfModelException if a DB error occurs */ - public PolicyNotifier(Publisher publisher, PolicyModelsProviderFactoryWrapper daoFactory) - throws PfModelException { + public PolicyNotifier(Publisher publisher, PolicyModelsProviderFactoryWrapper daoFactory) { this.publisher = publisher; - - try (PolicyModelsProvider dao = daoFactory.create()) { - Map id2type = loadPolicyTypes(dao); - loadPolicies(dao, id2type); - } - } - - /** - * Loads policy types from the DB. - * - * @param dao provider used to retrieve policies from the DB - * @return a mapping from policy id to policy type - * @throws PfModelException if a DB error occurs - */ - private Map loadPolicyTypes(PolicyModelsProvider dao) - throws PfModelException { - - Map id2type = new HashMap<>(); - - for (ToscaPolicy policy : dao.getFilteredPolicyList(ToscaPolicyFilter.builder().build())) { - id2type.put(policy.getIdentifier(), policy.getTypeIdentifier()); - } - - return id2type; - } - - /** - * Loads deployed policies. - * - * @param id2type mapping from policy id to policy type - * @param dao provider used to retrieve policies from the DB - * @throws PfModelException if a DB error occurs - */ - private void loadPolicies(PolicyModelsProvider dao, Map id2type) - throws PfModelException { - for (PdpGroup group : dao.getPdpGroups(null)) { - for (PdpSubGroup subgrp : group.getPdpSubgroups()) { - loadPolicies(id2type, group, subgrp); - } - } - } - - /** - * Loads a subgroup's deployed policies. - * - * @param id2type maps a policy id to its type - * @param group group containing the subgroup - * @param subgrp subgroup whose policies are to be loaded - */ - private void loadPolicies(Map id2type, PdpGroup group, - PdpSubGroup subgrp) { - - for (ToscaConceptIdentifier policyId : subgrp.getPolicies()) { - - ToscaConceptIdentifier type = id2type.get(policyId); - if (type == null) { - logger.error("group {}:{} refers to non-existent policy {}", group.getName(), subgrp.getPdpType(), - policyId); - continue; - } - - PolicyPdpNotificationData data = new PolicyPdpNotificationData(policyId, type); - data.addAll(subgrp.getPdpInstances().stream().map(Pdp::getInstanceId).collect(Collectors.toList())); - deployTracker.addData(data); - } - } - - /** - * Gets the status of all deployed policies. - * - * @return the status of all deployed policies - */ - public synchronized List getStatus() { - return deployTracker.getStatus(); - } - - /** - * Gets the status of a particular deployed policy. - * - * @param policyId ID of the policy of interest, without the version - * @return the status of all deployed policies matching the given identifier - */ - public synchronized List getStatus(String policyId) { - return deployTracker.getStatus(policyId); - } - - /** - * Gets the status of a particular deployed policy. - * - * @param ident identifier of the policy of interest - * @return the status of the given policy, or empty if the policy is not found - */ - public synchronized Optional getStatus(ToscaConceptIdentifier ident) { - return deployTracker.getStatus(ident); - } - - /** - * Adds data to the deployment tracker. If a PDP appears within the undeployment - * tracker, then it's removed from there. - * - * @param data data to be added - */ - public synchronized void addDeploymentData(PolicyPdpNotificationData data) { - undeployTracker.removeData(data); - deployTracker.addData(data); - } - - /** - * Adds data to the undeployment tracker. If a PDP appears within the deployment - * tracker, then it's removed from there. - * - * @param data data to be added - */ - public synchronized void addUndeploymentData(PolicyPdpNotificationData data) { - deployTracker.removeData(data); - undeployTracker.addData(data); - } - - /** - * Processes a response from a PDP. - * - * @param pdp PDP of interest - * @param activePolicies policies that are still active on the PDP, as specified in - * the response - */ - public synchronized void processResponse(String pdp, Collection activePolicies) { - processResponse(pdp, new HashSet<>(activePolicies)); + this.daoFactory = daoFactory; } /** * Processes a response from a PDP. * * @param pdp PDP of interest - * @param activePolicies policies that are still active on the PDP, as specified in + * @param pdpGroup name of the PdpGroup containing the PDP + * @param expectedPolicies policies that expected to be deployed on the PDP + * @param actualPolicies policies that are still active on the PDP, as specified in * the response */ - public synchronized void processResponse(String pdp, Set activePolicies) { - PolicyNotification notification = new PolicyNotification(); + public synchronized void processResponse(String pdp, String pdpGroup, Set expectedPolicies, + Set actualPolicies) { - undeployTracker.processResponse(pdp, activePolicies, notification.getDeleted()); - deployTracker.processResponse(pdp, activePolicies, notification.getAdded()); + try (PolicyModelsProvider dao = daoFactory.create()) { + DeploymentStatus status = makeDeploymentTracker(dao); + status.loadByGroup(pdpGroup); + status.completeDeploy(pdp, expectedPolicies, actualPolicies); - publish(notification); - } + PolicyNotification notification = new PolicyNotification(); + status.flush(notification); - /** - * Removes a PDP from any policies still awaiting responses from it, generating - * notifications for any of those policies that become complete as a result. - * - * @param pdp PDP to be removed - */ - public synchronized void removePdp(String pdp) { - PolicyNotification notification = new PolicyNotification(); + publish(notification); - undeployTracker.removePdp(pdp, notification.getDeleted()); - deployTracker.removePdp(pdp, notification.getAdded()); - - publish(notification); + } catch (PfModelException e) { + logger.warn("cannot update deployment status", e); + } } /** @@ -243,7 +90,7 @@ public class PolicyNotifier { * * @param notification notification to be published */ - private void publish(PolicyNotification notification) { + public synchronized void publish(PolicyNotification notification) { if (!notification.isEmpty()) { publisher.enqueue(new QueueToken<>(notification)); } @@ -252,11 +99,7 @@ public class PolicyNotifier { // the following methods may be overridden by junit tests - protected PolicyDeployTracker makeDeploymentTracker() { - return new PolicyDeployTracker(); - } - - protected PolicyUndeployTracker makeUndeploymentTracker() { - return new PolicyUndeployTracker(); + protected DeploymentStatus makeDeploymentTracker(PolicyModelsProvider dao) { + return new DeploymentStatus(dao); } } diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyPdpNotificationData.java b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyPdpNotificationData.java deleted file mode 100644 index b93f8930..00000000 --- a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyPdpNotificationData.java +++ /dev/null @@ -1,86 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP PAP - * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.pap.main.notification; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import lombok.Getter; -import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; - -/** - * Data used to track deploy/undeploy of a policy to PDPs. - */ -@Getter -public class PolicyPdpNotificationData { - private final ToscaConceptIdentifier policyId; - private final ToscaConceptIdentifier policyType; - private final Set pdps = new HashSet<>(); - - - /** - * Constructs the object. - * - * @param policyId ID of the policy being deployed/undeployed - * @param policyType type of the associated policy - */ - public PolicyPdpNotificationData(ToscaConceptIdentifier policyId, ToscaConceptIdentifier policyType) { - this.policyId = policyId; - this.policyType = policyType; - } - - /** - * Determines if there are any PDPs in the data. - * - * @return {@code true} if the data contains at least one PDP, {@code false} otherwise - */ - public boolean isEmpty() { - return pdps.isEmpty(); - } - - /** - * Adds a PDP to the set of PDPs. - * - * @param pdp PDP to be added - */ - public void add(String pdp) { - pdps.add(pdp); - } - - /** - * Adds PDPs to the set of PDPs. - * - * @param pdps PDPs to be added - */ - public void addAll(Collection pdps) { - this.pdps.addAll(pdps); - } - - /** - * Removes PDPs from the set of PDPs. - * - * @param pdps PDPs to be removed - */ - public void removeAll(Collection pdps) { - this.pdps.removeAll(pdps); - } -} diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyTrackerData.java b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyTrackerData.java deleted file mode 100644 index 7dfb378f..00000000 --- a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyTrackerData.java +++ /dev/null @@ -1,193 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP PAP - * ================================================================================ - * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.pap.main.notification; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import lombok.Getter; -import org.onap.policy.models.pap.concepts.PolicyStatus; -import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; - -/** - * Data associated with a policy, used by PolicyTracker. PDPs start in - * {@link #incompletePdps} and are moved to either {@link #successPdps} or - * {@link #failPdps}, depending on their response. Objects of this type are not - * multi-thread safe. - */ -public class PolicyTrackerData { - /** - * The policy type associated with the policy. - */ - @Getter - private final ToscaConceptIdentifier policyType; - - /** - * PDPs that have successfully completed an update of the policy. - */ - private final Set successPdps = new HashSet<>(); - - /** - * PDPs that have failed to complete an update of the policy. - */ - private final Set failPdps = new HashSet<>(); - - /** - * PDPs for which we're still awaiting a response. - */ - private final Set incompletePdps = new HashSet<>(); - - - /** - * Constructs the object. - * - * @param policyType policy type - */ - public PolicyTrackerData(ToscaConceptIdentifier policyType) { - this.policyType = policyType; - } - - /** - * Determines if this is complete (i.e., it is not waiting for responses from any - * other PDPs). - * - * @return {@code true} if this is complete, {@code false} otherwise - */ - public boolean isComplete() { - return incompletePdps.isEmpty(); - } - - /** - * Determines if everything has succeeded. - * - * @return {@code true} if this is complete and nothing has failed, - * {@code false} otherwise - */ - public boolean allSucceeded() { - return (failPdps.isEmpty() && incompletePdps.isEmpty()); - } - - /** - * Determines if all of the sets within the data are empty (i.e., contain no PDPs). - * - * @return {@code true} if the data is completely empty, {@code false} otherwise - */ - public boolean isEmpty() { - return (successPdps.isEmpty() && failPdps.isEmpty() && incompletePdps.isEmpty()); - } - - /** - * Puts the values from this data into the given status object. - * - * @param status object whose values are to be set - */ - public void putValuesInto(PolicyStatus status) { - status.setFailureCount(failPdps.size()); - status.setIncompleteCount(incompletePdps.size()); - status.setSuccessCount(successPdps.size()); - } - - /** - * Adds PDPs to {@link #incompletePdps}, removing them from any other sets in which - * they appear. - * - * @param pdps PDPs to be added - */ - public void addPdps(Collection pdps) { - successPdps.removeAll(pdps); - failPdps.removeAll(pdps); - - incompletePdps.addAll(pdps); - } - - /** - * Removes PDPs from the sets. - * - * @param pdps PDPs to be removed - * @return {@code true} if anything changed and the policy is now complete, {@code false} otherwise - */ - public boolean removePdps(Collection pdps) { - boolean changed = successPdps.removeAll(pdps); - changed = failPdps.removeAll(pdps) || changed; - changed = incompletePdps.removeAll(pdps) || changed; - - return (changed && incompletePdps.isEmpty()); - } - - /** - * Removes a PDP from all sets. - * - * @param pdp PDP to be removed - * @return {@code true} if anything changed and the policy is now complete, {@code false} otherwise - */ - public boolean removePdp(String pdp) { - boolean changed = successPdps.remove(pdp); - changed = failPdps.remove(pdp) || changed; - changed = incompletePdps.remove(pdp) || changed; - - return (changed && incompletePdps.isEmpty()); - } - - /** - * Indicates that a PDP has successfully processed this policy. - * - * @param pdp the PDP of interest - * @return {@code true} if the policy is now complete, {@code false} otherwise - */ - public boolean success(String pdp) { - return complete(pdp, successPdps, failPdps); - } - - /** - * Indicates that a PDP has processed this policy, but was unsuccessful. - * - * @param pdp the PDP of interest - * @return {@code true} if the policy is now complete, {@code false} otherwise - */ - public boolean fail(String pdp) { - return complete(pdp, failPdps, successPdps); - } - - /** - * Indicates that a PDP has processed this policy, either successfully or - * unsuccessfully. - * - * @param pdp the PDP of interest - * @param addSet set to which the PDP should be added - * @param removeSet set from which the PDP should be removed - * @return {@code true} if the policy is now complete, {@code false} otherwise - */ - private boolean complete(String pdp, Set addSet, Set removeSet) { - if (incompletePdps.remove(pdp) || removeSet.remove(pdp)) { - // successfully removed from one of the sets - addSet.add(pdp); - return incompletePdps.isEmpty(); - } - - /* - * Else: wasn't in either set, thus it's already in the "addSet" or it isn't - * relevant to this policy. Either way, just discard it without triggering any new - * notification. - */ - return false; - } -} diff --git a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyUndeployTracker.java b/main/src/main/java/org/onap/policy/pap/main/notification/PolicyUndeployTracker.java deleted file mode 100644 index af2f0b6a..00000000 --- a/main/src/main/java/org/onap/policy/pap/main/notification/PolicyUndeployTracker.java +++ /dev/null @@ -1,52 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP PAP - * ================================================================================ - * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.pap.main.notification; - -/** - * Tracker for policy undeployments from PDPs. - * - *

- * Policies are removed from the internal map when they are no longer waiting for - * responses from any PDPs. - */ -public class PolicyUndeployTracker extends PolicyCommonTracker { - - /** - * Constructs the object. - */ - public PolicyUndeployTracker() { - super(); - } - - @Override - protected boolean updateData(String pdp, PolicyTrackerData data, boolean stillActive) { - // note: still active means the policy wasn't undeployed, thus it's a failure - return (stillActive ? data.fail(pdp) : data.success(pdp)); - } - - /** - * Returns {@code true} only when the data is all successful. - */ - @Override - protected boolean shouldRemove(PolicyTrackerData data) { - return data.allSucceeded(); - } -} diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupCreateOrUpdateProvider.java b/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupCreateOrUpdateProvider.java index 00db7cc0..39608cdd 100644 --- a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupCreateOrUpdateProvider.java +++ b/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupCreateOrUpdateProvider.java @@ -3,7 +3,7 @@ * ONAP PAP * ================================================================================ * Copyright (C) 2019-2021 Nordix Foundation. - * Modifications Copyright (C) 2019 AT&T Intellectual Property. + * Modifications Copyright (C) 2019, 2021 AT&T Intellectual Property. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -303,7 +303,7 @@ public class PdpGroupCreateOrUpdateProvider extends ProviderBase { // this subgroup no longer appears - notify its PDPs updated = true; notifyPdpsDelSubGroup(data, subgrp); - trackPdpsDelSubGroup(data, subgrp); + trackPdpsDelSubGroup(data, dbgroup.getName(), subgrp); } } @@ -337,14 +337,15 @@ public class PdpGroupCreateOrUpdateProvider extends ProviderBase { * Tracks PDP responses when their subgroup is removed. * * @param data session data + * @param pdpGroup PdpGroup name * @param subgrp subgroup that is being removed * @throws PfModelException if an error occurred */ - private void trackPdpsDelSubGroup(SessionData data, PdpSubGroup subgrp) throws PfModelException { + private void trackPdpsDelSubGroup(SessionData data, String pdpGroup, PdpSubGroup subgrp) throws PfModelException { Set pdps = subgrp.getPdpInstances().stream().map(Pdp::getInstanceId).collect(Collectors.toSet()); for (ToscaConceptIdentifier policyId : subgrp.getPolicies()) { - data.trackUndeploy(policyId, pdps); + data.trackUndeploy(policyId, pdps, pdpGroup, subgrp.getPdpType()); } } diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeleteProvider.java b/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeleteProvider.java index 38851cd3..0170197c 100644 --- a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeleteProvider.java +++ b/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeleteProvider.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP PAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020-2021 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -158,7 +158,7 @@ public class PdpGroupDeleteProvider extends ProviderBase { logger.info("remove policy {} from subgroup {} {} count={}", ident, group.getName(), subgroup.getPdpType(), subgroup.getPolicies().size()); - data.trackUndeploy(ident, pdps); + data.trackUndeploy(ident, pdps, group.getName(), subgroup.getPdpType()); } } diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java b/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java index c30ee8f9..3c8ce4c8 100644 --- a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java +++ b/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP PAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020-2021 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -202,14 +202,14 @@ public class PdpGroupDeployProvider extends ProviderBase { switch (subgrp.getAction()) { case POST: - updated = addPolicies(data, dbsub, subgrp); + updated = addPolicies(data, dbgroup.getName(), dbsub, subgrp); break; case DELETE: - updated = deletePolicies(data, dbsub, subgrp); + updated = deletePolicies(data, dbgroup.getName(), dbsub, subgrp); break; case PATCH: default: - updated = updatePolicies(data, dbsub, subgrp); + updated = updatePolicies(data, dbgroup.getName(), dbsub, subgrp); break; } @@ -222,7 +222,7 @@ public class PdpGroupDeployProvider extends ProviderBase { return false; } - private boolean addPolicies(SessionData data, PdpSubGroup dbsub, DeploymentSubGroup subgrp) + private boolean addPolicies(SessionData data, String pdpGroup, PdpSubGroup dbsub, DeploymentSubGroup subgrp) throws PfModelException { Set policies = new LinkedHashSet<>(dbsub.getPolicies()); @@ -232,10 +232,10 @@ public class PdpGroupDeployProvider extends ProviderBase { subgrp2.getPolicies().clear(); subgrp2.getPolicies().addAll(policies); - return updatePolicies(data, dbsub, subgrp2); + return updatePolicies(data, pdpGroup, dbsub, subgrp2); } - private boolean deletePolicies(SessionData data, PdpSubGroup dbsub, DeploymentSubGroup subgrp) + private boolean deletePolicies(SessionData data, String pdpGroup, PdpSubGroup dbsub, DeploymentSubGroup subgrp) throws PfModelException { Set policies = new LinkedHashSet<>(dbsub.getPolicies()); @@ -245,10 +245,10 @@ public class PdpGroupDeployProvider extends ProviderBase { subgrp2.getPolicies().clear(); subgrp2.getPolicies().addAll(policies); - return updatePolicies(data, dbsub, subgrp2); + return updatePolicies(data, pdpGroup, dbsub, subgrp2); } - private boolean updatePolicies(SessionData data, PdpSubGroup dbsub, DeploymentSubGroup subgrp) + private boolean updatePolicies(SessionData data, String pdpGroup, PdpSubGroup dbsub, DeploymentSubGroup subgrp) throws PfModelException { Set undeployed = new HashSet<>(dbsub.getPolicies()); @@ -266,11 +266,11 @@ public class PdpGroupDeployProvider extends ProviderBase { Set pdps = dbsub.getPdpInstances().stream().map(Pdp::getInstanceId).collect(Collectors.toSet()); for (ToscaConceptIdentifier policyId : deployed) { - data.trackDeploy(policyId, pdps); + data.trackDeploy(policyId, pdps, pdpGroup, dbsub.getPdpType()); } for (ToscaConceptIdentifier policyId : undeployed) { - data.trackUndeploy(policyId, pdps); + data.trackUndeploy(policyId, pdps, pdpGroup, dbsub.getPdpType()); } dbsub.setPolicies(new ArrayList<>(subgrp.getPolicies())); @@ -443,7 +443,7 @@ public class PdpGroupDeployProvider extends ProviderBase { subgroup.getPdpType(), subgroup.getPolicies().size()); Set pdps = subgroup.getPdpInstances().stream().map(Pdp::getInstanceId).collect(Collectors.toSet()); - data.trackDeploy(desiredIdent, pdps); + data.trackDeploy(desiredIdent, pdps, group.getName(), subgroup.getPdpType()); return true; }; diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/PolicyStatusControllerV1.java b/main/src/main/java/org/onap/policy/pap/main/rest/PolicyStatusControllerV1.java index bc838621..ec7c00a9 100644 --- a/main/src/main/java/org/onap/policy/pap/main/rest/PolicyStatusControllerV1.java +++ b/main/src/main/java/org/onap/policy/pap/main/rest/PolicyStatusControllerV1.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP PAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2021 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,30 +29,30 @@ import io.swagger.annotations.Authorization; import io.swagger.annotations.Extension; import io.swagger.annotations.ExtensionProperty; import io.swagger.annotations.ResponseHeader; -import java.util.List; -import java.util.Optional; +import java.util.Collection; import java.util.UUID; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; -import org.onap.policy.common.utils.services.Registry; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.pap.concepts.PolicyStatus; -import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; -import org.onap.policy.pap.main.PapConstants; -import org.onap.policy.pap.main.notification.PolicyNotifier; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifierOptVersion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Class to provide REST end points for PAP component to retrieve the status of deployed * policies. */ public class PolicyStatusControllerV1 extends PapRestControllerV1 { - private final PolicyNotifier notifier; + private static final String GET_DEPLOYMENTS_FAILED = "get deployments failed"; - public PolicyStatusControllerV1() { - this.notifier = Registry.get(PapConstants.REG_POLICY_NOTIFIER, PolicyNotifier.class); - } + private static final Logger logger = LoggerFactory.getLogger(PolicyStatusControllerV1.class); + + private final PolicyStatusProvider provider = new PolicyStatusProvider(); /** * Queries status of all deployed policies. @@ -88,8 +88,15 @@ public class PolicyStatusControllerV1 extends PapRestControllerV1 { public Response queryAllDeployedPolicies( @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) final UUID requestId) { - return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) - .entity(notifier.getStatus()).build(); + try { + return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) + .entity(provider.getStatus()).build(); + + } catch (PfModelException | PfModelRuntimeException e) { + logger.warn(GET_DEPLOYMENTS_FAILED, e); + return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), + requestId).entity(e.getErrorResponse().getErrorMessage()).build(); + } } @@ -128,13 +135,20 @@ public class PolicyStatusControllerV1 extends PapRestControllerV1 { @ApiParam(value = "Policy Id", required = true) @PathParam("name") String name, @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) final UUID requestId) { - List result = notifier.getStatus(name); - if (result.isEmpty()) { - return makeNotFoundResponse(requestId); + try { + Collection result = provider.getStatus(new ToscaConceptIdentifierOptVersion(name, null)); + if (result.isEmpty()) { + return makeNotFoundResponse(requestId); - } else { - return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) - .entity(result).build(); + } else { + return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) + .entity(result).build(); + } + + } catch (PfModelException | PfModelRuntimeException e) { + logger.warn(GET_DEPLOYMENTS_FAILED, e); + return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), + requestId).entity(e.getErrorResponse().getErrorMessage()).build(); } } @@ -174,14 +188,20 @@ public class PolicyStatusControllerV1 extends PapRestControllerV1 { @ApiParam(value = "Policy Version", required = true) @PathParam("version") String version, @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) final UUID requestId) { - ToscaConceptIdentifier ident = new ToscaConceptIdentifier(name, version); - Optional result = notifier.getStatus(ident); - if (result.isPresent()) { - return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) - .entity(result.get()).build(); + try { + Collection result = provider.getStatus(new ToscaConceptIdentifierOptVersion(name, version)); + if (result.isEmpty()) { + return makeNotFoundResponse(requestId); + + } else { + return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) + .entity(result.iterator().next()).build(); + } - } else { - return makeNotFoundResponse(requestId); + } catch (PfModelException | PfModelRuntimeException e) { + logger.warn(GET_DEPLOYMENTS_FAILED, e); + return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), + requestId).entity(e.getErrorResponse().getErrorMessage()).build(); } } diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/PolicyStatusProvider.java b/main/src/main/java/org/onap/policy/pap/main/rest/PolicyStatusProvider.java new file mode 100644 index 00000000..98cf47b9 --- /dev/null +++ b/main/src/main/java/org/onap/policy/pap/main/rest/PolicyStatusProvider.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pap.main.rest; + +import java.util.Collection; +import org.onap.policy.common.utils.services.Registry; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.pap.concepts.PolicyStatus; +import org.onap.policy.models.pdp.concepts.PdpPolicyStatus; +import org.onap.policy.models.provider.PolicyModelsProvider; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifierOptVersion; +import org.onap.policy.pap.main.PapConstants; +import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper; +import org.onap.policy.pap.main.notification.DeploymentTracker; + +/** + * Provider for PAP component to query policy deployment status. + */ +public class PolicyStatusProvider { + + /** + * Factory for PAP DAO. + */ + private final PolicyModelsProviderFactoryWrapper daoFactory; + + + /** + * Constructs the object. Loads all deployed policies into the internal cache. + */ + public PolicyStatusProvider() { + this.daoFactory = Registry.get(PapConstants.REG_PAP_DAO_FACTORY, PolicyModelsProviderFactoryWrapper.class); + } + + /** + * Gets the deployment status of all policies. + * + * @return the deployment status of all policies + * @throws PfModelException if a DB error occurs + */ + public Collection getStatus() throws PfModelException { + try (PolicyModelsProvider dao = daoFactory.create()) { + return accumulate(dao.getAllPolicyStatus()); + } + } + + /** + * Gets the deployment status of a policy. + * + * @param policy policy of interest + * @return the deployment status of all policies + * @throws PfModelException if a DB error occurs + */ + public Collection getStatus(ToscaConceptIdentifierOptVersion policy) throws PfModelException { + try (PolicyModelsProvider dao = daoFactory.create()) { + return accumulate(dao.getAllPolicyStatus(policy)); + } + } + + /** + * Accumulates the deployment status of individual PDP/policy pairs into a status for + * a policy. + * + * @param source PDP/policy pairs + * @return the deployment status of the policies + */ + private Collection accumulate(Collection source) { + DeploymentTracker tracker = new DeploymentTracker(); + + for (PdpPolicyStatus status : source) { + if (status.isDeploy()) { + tracker.add(status); + } + } + + return tracker.getDeploymentStatus(); + } +} diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/PolicyUndeployerImpl.java b/main/src/main/java/org/onap/policy/pap/main/rest/PolicyUndeployerImpl.java index 1e7c788b..c3dd505c 100644 --- a/main/src/main/java/org/onap/policy/pap/main/rest/PolicyUndeployerImpl.java +++ b/main/src/main/java/org/onap/policy/pap/main/rest/PolicyUndeployerImpl.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP PAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020-2021 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -93,7 +93,7 @@ public class PolicyUndeployerImpl extends ProviderBase implements PolicyUndeploy subgroup.getPdpType(), subgroup.getPolicies().size()); updated = true; - data.trackUndeploy(ident, pdps); + data.trackUndeploy(ident, pdps, policyInfo.group, policyInfo.subgroup); } // push the updates diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/ProviderBase.java b/main/src/main/java/org/onap/policy/pap/main/rest/ProviderBase.java index 0de7a6c4..7f013ac7 100644 --- a/main/src/main/java/org/onap/policy/pap/main/rest/ProviderBase.java +++ b/main/src/main/java/org/onap/policy/pap/main/rest/ProviderBase.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP PAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2020-2021 Nordix Foundation. * Modifications Copyright (C) 2020 Bell Canada. All rights reserved. * ================================================================================ @@ -28,6 +28,7 @@ import javax.ws.rs.core.Response.Status; import org.onap.policy.common.utils.services.Registry; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; +import org.onap.policy.models.pap.concepts.PolicyNotification; import org.onap.policy.models.pdp.concepts.Pdp; import org.onap.policy.models.pdp.concepts.PdpGroup; import org.onap.policy.models.pdp.concepts.PdpSubGroup; @@ -95,6 +96,7 @@ public abstract class ProviderBase { synchronized (updateLock) { SessionData data; + PolicyNotification notif = new PolicyNotification(); try (PolicyModelsProvider dao = daoFactory.create()) { @@ -102,7 +104,7 @@ public abstract class ProviderBase { processor.accept(data, request); // make all of the DB updates - data.updateDb(); + data.updateDb(notif); } catch (PfModelException | PfModelRuntimeException e) { throw e; @@ -111,12 +113,11 @@ public abstract class ProviderBase { throw new PfModelException(Status.INTERNAL_SERVER_ERROR, "request failed", e); } - // track responses for notification purposes - data.getDeployData().forEach(notifier::addDeploymentData); - data.getUndeployData().forEach(notifier::addUndeploymentData); - // publish the requests data.getPdpRequests().forEach(pair -> requestMap.addRequest(pair.getLeft(), pair.getRight())); + + // publish the notifications + notifier.publish(notif); } } diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/SessionData.java b/main/src/main/java/org/onap/policy/pap/main/rest/SessionData.java index cdcc51c6..930302a2 100644 --- a/main/src/main/java/org/onap/policy/pap/main/rest/SessionData.java +++ b/main/src/main/java/org/onap/policy/pap/main/rest/SessionData.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP PAP * ================================================================================ - * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2021 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,13 +25,12 @@ import com.google.re2j.Pattern; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.pap.concepts.PolicyNotification; import org.onap.policy.models.pdp.concepts.PdpGroup; import org.onap.policy.models.pdp.concepts.PdpGroupFilter; import org.onap.policy.models.pdp.concepts.PdpStateChange; @@ -44,7 +43,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyFilter; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyFilter.ToscaPolicyFilterBuilder; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; -import org.onap.policy.pap.main.notification.PolicyPdpNotificationData; +import org.onap.policy.pap.main.notification.DeploymentStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -93,16 +92,9 @@ public class SessionData { private final Map typeCache = new HashMap<>(); /** - * Policies to be deployed. This is just used to build up the data, which is then - * passed to the notifier once the update is "committed". + * Tracks policy deployment status so notifications can be generated. */ - private final Map deploy = new HashMap<>(); - - /** - * Policies to be undeployed. This is just used to build up the data, which is then - * passed to the notifier once the update is "committed". - */ - private final Map undeploy = new HashMap<>(); + private final DeploymentStatus deployStatus; /** @@ -112,6 +104,7 @@ public class SessionData { */ public SessionData(PolicyModelsProvider dao) { this.dao = dao; + this.deployStatus = makeDeploymentStatus(dao); } /** @@ -332,6 +325,8 @@ public class SessionData { data = new GroupData(lst.get(0)); groupCache.put(name, data); + deployStatus.loadByGroup(name); + } else { logger.info("use cached group {}", name); } @@ -352,7 +347,7 @@ public class SessionData { * exception and handling that would obfuscate the code too much, thus disabling * the sonar. */ - List data = type2groups.get(type); // NOSONAR + List data = type2groups.get(type); // NOSONAR if (data == null) { PdpGroupFilter filter = PdpGroupFilter.builder().policyTypeList(Collections.singletonList(type)) .groupState(PdpState.ACTIVE).build(); @@ -388,10 +383,11 @@ public class SessionData { /** * Update the DB with the changes. + * @param notification notification to which to add policy status * * @throws PfModelException if an error occurred */ - public void updateDb() throws PfModelException { + public void updateDb(PolicyNotification notification) throws PfModelException { // create new groups List created = groupCache.values().stream().filter(GroupData::isNew).collect(Collectors.toList()); if (!created.isEmpty()) { @@ -410,6 +406,9 @@ public class SessionData { } dao.updatePdpGroups(updated.stream().map(GroupData::getGroup).collect(Collectors.toList())); } + + // flush deployment status records to the DB + deployStatus.flush(notification); } /** @@ -429,32 +428,13 @@ public class SessionData { * * @param policyId ID of the policy being deployed * @param pdps PDPs to which the policy is being deployed + * @param pdpGroup PdpGroup containing the PDP of interest + * @param pdpType PDP type (i.e., PdpSubGroup) containing the PDP of interest * @throws PfModelException if an error occurred */ - protected void trackDeploy(ToscaConceptIdentifier policyId, Collection pdps) throws PfModelException { - trackDeploy(policyId, new HashSet<>(pdps)); - } - - /** - * Adds policy deployment data. - * - * @param policyId ID of the policy being deployed - * @param pdps PDPs to which the policy is being deployed - * @throws PfModelException if an error occurred - */ - protected void trackDeploy(ToscaConceptIdentifier policyId, Set pdps) throws PfModelException { - addData(policyId, pdps, deploy, undeploy); - } - - /** - * Adds policy undeployment data. - * - * @param policyId ID of the policy being undeployed - * @param pdps PDPs to which the policy is being undeployed - * @throws PfModelException if an error occurred - */ - protected void trackUndeploy(ToscaConceptIdentifier policyId, Collection pdps) throws PfModelException { - trackUndeploy(policyId, new HashSet<>(pdps)); + protected void trackDeploy(ToscaConceptIdentifier policyId, Collection pdps, String pdpGroup, + String pdpType) throws PfModelException { + addData(policyId, pdps, pdpGroup, pdpType, true); } /** @@ -462,10 +442,13 @@ public class SessionData { * * @param policyId ID of the policy being undeployed * @param pdps PDPs to which the policy is being undeployed + * @param pdpGroup PdpGroup containing the PDP of interest + * @param pdpType PDP type (i.e., PdpSubGroup) containing the PDP of interest * @throws PfModelException if an error occurred */ - protected void trackUndeploy(ToscaConceptIdentifier policyId, Set pdps) throws PfModelException { - addData(policyId, pdps, undeploy, deploy); + protected void trackUndeploy(ToscaConceptIdentifier policyId, Collection pdps, String pdpGroup, + String pdpType) throws PfModelException { + addData(policyId, pdps, pdpGroup, pdpType, false); } /** @@ -473,40 +456,29 @@ public class SessionData { * * @param policyId ID of the policy being deployed/undeployed * @param pdps PDPs to which the policy is being deployed/undeployed - * @param addMap map to which it should be added - * @param removeMap map from which it should be removed + * @param deploy {@code true} if the policy is being deployed, {@code false} if + * undeployed + * @param pdpGroup PdpGroup containing the PDP of interest + * @param pdpType PDP type (i.e., PdpSubGroup) containing the PDP of interest * @throws PfModelException if an error occurred */ - private void addData(ToscaConceptIdentifier policyId, Set pdps, - Map addMap, - Map removeMap) throws PfModelException { + private void addData(ToscaConceptIdentifier policyId, Collection pdps, String pdpGroup, String pdpType, + boolean deploy) throws PfModelException { - PolicyPdpNotificationData removeData = removeMap.get(policyId); - if (removeData != null) { - removeData.removeAll(pdps); - } + // delete all records whose "deploy" flag is the opposite of what we want + deployStatus.deleteDeployment(policyId, !deploy); ToscaConceptIdentifierOptVersion optid = new ToscaConceptIdentifierOptVersion(policyId); ToscaConceptIdentifier policyType = getPolicy(optid).getTypeIdentifier(); - addMap.computeIfAbsent(policyId, key -> new PolicyPdpNotificationData(policyId, policyType)).addAll(pdps); + for (String pdp : pdps) { + deployStatus.deploy(pdp, policyId, policyType, pdpGroup, pdpType, deploy); + } } - /** - * Gets the policies to be deployed. - * - * @return the policies to be deployed - */ - public Collection getDeployData() { - return deploy.values(); - } + // these may be overridden by junit tests - /** - * Gets the policies to be undeployed. - * - * @return the policies to be undeployed - */ - public Collection getUndeployData() { - return undeploy.values(); + protected DeploymentStatus makeDeploymentStatus(PolicyModelsProvider dao) { + return new DeploymentStatus(dao); } } diff --git a/main/src/main/java/org/onap/policy/pap/main/startstop/Main.java b/main/src/main/java/org/onap/policy/pap/main/startstop/Main.java index 4ccfb116..a351e6f7 100644 --- a/main/src/main/java/org/onap/policy/pap/main/startstop/Main.java +++ b/main/src/main/java/org/onap/policy/pap/main/startstop/Main.java @@ -1,7 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2019 Nordix Foundation. - * Modifications Copyright (C) 2019 AT&T Intellectual Property. + * Modifications Copyright (C) 2019, 2021 AT&T Intellectual Property. * Modifications Copyright (C) 2020 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -78,7 +78,13 @@ public class Main { // Start the activator activator.start(); - } catch (Exception exp) { + } catch (Exception exp) { // NOSONAR + /* + * Disabled sonar on the above line, because we want to capture the stack + * trace via the logger while still reporting the exception message on stdout + * when the JVM exits. + */ + LOGGER.error("failed to start Main", exp); if (null != activator) { Registry.unregister(PapConstants.REG_PAP_ACTIVATOR); } diff --git a/main/src/main/resources/META-INF/persistence.xml b/main/src/main/resources/META-INF/persistence.xml index 8c385f8a..a9624f35 100644 --- a/main/src/main/resources/META-INF/persistence.xml +++ b/main/src/main/resources/META-INF/persistence.xml @@ -2,6 +2,7 @@