From 5c71b5a62f4208030b3c3cd18b3f42398a0a86e5 Mon Sep 17 00:00:00 2001 From: jhh Date: Mon, 24 Aug 2020 20:04:52 -0500 Subject: block status operations until controllers ready Status messages to the PAP won't be send until all mandatory resources specified in the lifecycle.pdp.policytypes property are functional. Issue-ID: POLICY-2669 Signed-off-by: jhh Change-Id: Ia9d4c678fcfbdb232059d0827235845ee11f1201 Signed-off-by: jhh --- .../feature/config/feature-lifecycle.properties | 5 +- .../onap/policy/drools/lifecycle/LifecycleFsm.java | 56 +++++++++++++++------- .../drools/lifecycle/LifecycleStateRunning.java | 10 ++-- .../LifecycleStateActivePoliciesTest.java | 18 +++++++ .../drools/lifecycle/LifecycleStateActiveTest.java | 8 ++-- .../test/resources/feature-lifecycle.properties | 1 + packages/install/src/files/base.conf | 3 +- 7 files changed, 74 insertions(+), 27 deletions(-) diff --git a/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties b/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties index 076da1f9..b495664d 100644 --- a/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties +++ b/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties @@ -1,7 +1,7 @@ # ============LICENSE_START======================================================= # ONAP # ================================================================================ -# Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. +# 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. @@ -18,6 +18,9 @@ lifecycle.pdp.group=${envd:POLICY_PDP_PAP_GROUP:defaultGroup} +# Mandatory policy types that this PDP-D must support at a minimum +lifecycle.pdp.policytypes=${envd:POLICY_PDP_PAP_POLICYTYPES} + dmaap.source.topics=POLICY-PDP-PAP dmaap.sink.topics=POLICY-PDP-PAP diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java index 319770bd..a45f2b4e 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java @@ -22,10 +22,12 @@ package org.onap.policy.drools.lifecycle; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Properties; +import java.util.Set; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; @@ -77,6 +79,7 @@ public class LifecycleFsm implements Startable { protected static final String CONFIGURATION_PROPERTIES_NAME = "feature-lifecycle"; protected static final String GROUP_NAME = "lifecycle.pdp.group"; + protected static final String MANDATORY_POLICY_TYPES = "lifecycle.pdp.policytypes"; protected static final String DEFAULT_PDP_GROUP = "defaultGroup"; protected static final long MIN_STATUS_INTERVAL_SECONDS = 5L; protected static final String PDP_MESSAGE_NAME = "messageName"; @@ -128,6 +131,9 @@ public class LifecycleFsm implements Startable { @Setter protected String subgroup; + @Getter + protected Set mandatoryPolicyTypes = new HashSet<>(); + @Getter protected final Map policyTypesMap = new HashMap<>(); @@ -146,6 +152,16 @@ public class LifecycleFsm implements Startable { this.policyTypesMap.put( POLICY_TYPE_DROOLS_NATIVE_RULES, new PolicyTypeNativeArtifactController(this, POLICY_TYPE_DROOLS_NATIVE_RULES)); + + String commaSeparatedPolicyTypes = this.properties.getProperty(MANDATORY_POLICY_TYPES); + if (!StringUtils.isBlank(commaSeparatedPolicyTypes)) { + for (String mpt: commaSeparatedPolicyTypes.split("\\s*,\\s*")) { + this.mandatoryPolicyTypes.add(mpt); + } + } + + logger.info("The mandatory Policy Types are {}. Compliance is {}", + this.mandatoryPolicyTypes, this.isMandatoryPolicyTypesCompliant()); } @GsonJsonIgnore @@ -165,6 +181,7 @@ public class LifecycleFsm implements Startable { return state.state(); } + /* ** FSM events - entry points of events into the FSM ** */ @Override @@ -184,14 +201,12 @@ public class LifecycleFsm implements Startable { } for (ToscaPolicyTypeIdentifier id : controller.getPolicyTypes()) { - if (isToscaPolicyType(id.getName())) { - PolicyTypeDroolsController ptDroolsController = (PolicyTypeDroolsController) policyTypesMap.get(id); - if (ptDroolsController == null) { - policyTypesMap.put(id, new PolicyTypeDroolsController(this, id, controller)); - logger.info("policy-type {} added", id); - } else { - ptDroolsController.add(controller); - } + PolicyTypeDroolsController ptDc = (PolicyTypeDroolsController) policyTypesMap.get(id); //NOSONAR + if (ptDc == null) { + policyTypesMap.put(id, new PolicyTypeDroolsController(this, id, controller)); + logger.info("policy-type {} added", id); + } else { + ptDc.add(controller); } } } @@ -329,10 +344,6 @@ public class LifecycleFsm implements Startable { return stopTimers() && startTimers(); } - protected PolicyTypeController getController(ToscaPolicyTypeIdentifier policyType) { - return policyTypesMap.get(policyType); - } - protected List getDeployablePoliciesAction(@NonNull List policies) { List deployPolicies = new ArrayList<>(policies); deployPolicies.removeAll(policiesMap.values()); @@ -363,6 +374,22 @@ public class LifecycleFsm implements Startable { return (this.scheduler.submit(() -> state.updatePolicies(toscaPolicies)) != null); } + protected PolicyTypeController getController(ToscaPolicyTypeIdentifier policyType) { + return policyTypesMap.get(policyType); + } + + /** + * Do I support the mandatory policy types?. + */ + protected boolean isMandatoryPolicyTypesCompliant() { + return getCurrentPolicyTypes().containsAll(getMandatoryPolicyTypes()); + } + + protected Set getCurrentPolicyTypes() { + return getPolicyTypesMap().keySet().stream() + .map(ToscaPolicyTypeIdentifier::getName).collect(Collectors.toSet()); + } + /* ** Action Helpers ** */ private boolean startIo() { @@ -444,11 +471,6 @@ public class LifecycleFsm implements Startable { return this.client.getSink().start(); } - protected boolean isToscaPolicyType(String domain) { - // HACK: until legacy controllers support is removed - return StringUtils.countMatches(domain, ".") > 1; - } - protected boolean isItMe(String name, String group, String subgroup) { if (Objects.equals(name, getName())) { return true; diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java index 503c0c11..cf13c46d 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java @@ -79,11 +79,13 @@ public abstract class LifecycleStateRunning extends LifecycleStateDefault { @Override public boolean status() { synchronized (fsm) { - if (fsm.getPolicyTypesMap().isEmpty()) { - return true; - } else { - return fsm.statusAction(); + if (!fsm.isMandatoryPolicyTypesCompliant()) { + logger.info("Not all expected policy types are registered yet, current={}, expected={}", + fsm.getCurrentPolicyTypes(), fsm.getMandatoryPolicyTypes()); + return false; } + + return fsm.statusAction(); } } diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActivePoliciesTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActivePoliciesTest.java index 49e439d9..2b0e65bf 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActivePoliciesTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActivePoliciesTest.java @@ -23,6 +23,7 @@ package org.onap.policy.drools.lifecycle; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -32,6 +33,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import org.junit.Before; import org.junit.Test; import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; @@ -82,6 +84,22 @@ public class LifecycleStateActivePoliciesTest extends LifecycleStateRunningTest controllerSupport.getController().start(); } + @Test + public void testMandatoryPolicyTypes() { + assertEquals(Set.of("onap.policies.native.drools.Artifact", "onap.policies.native.drools.Controller"), + fsm.getMandatoryPolicyTypes()); + assertEquals(fsm.getMandatoryPolicyTypes(), fsm.getCurrentPolicyTypes()); + assertTrue(fsm.isMandatoryPolicyTypesCompliant()); + assertTrue(fsm.status()); + + fsm.mandatoryPolicyTypes.add("blah"); + assertEquals(Set.of("onap.policies.native.drools.Artifact", "onap.policies.native.drools.Controller", "blah"), + fsm.getMandatoryPolicyTypes()); + assertNotEquals(fsm.getMandatoryPolicyTypes(), fsm.getCurrentPolicyTypes()); + assertFalse(fsm.isMandatoryPolicyTypesCompliant()); + assertFalse(fsm.status()); + } + @Test public void testUpdatePolicies() throws IOException, CoderException { assertEquals(2, fsm.policyTypesMap.size()); diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java index e8a9c825..39a3a939 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java @@ -205,7 +205,7 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest { ToscaPolicy toscaPolicyRestartV1 = getExamplesPolicy("policies/vCPE.policy.operational.input.tosca.json", "operational.restart"); toscaPolicyRestartV1.getProperties().put("controllerName", "lifecycle"); - update.setPolicies(Arrays.asList(toscaPolicyRestartV1)); + update.setPolicies(Collections.singletonList(toscaPolicyRestartV1)); int qlength = fsm.client.getSink().getRecentEvents().length; @@ -260,7 +260,7 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest { // redeploy operational.restart policy - update.setPolicies(Arrays.asList(toscaPolicyRestartV1)); + update.setPolicies(Collections.singletonList(toscaPolicyRestartV1)); assertTrue(fsm.update(update)); assertEquals(qlength + 4, fsm.client.getSink().getRecentEvents().length); assertEquals(3, fsm.policyTypesMap.size()); @@ -279,7 +279,7 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest { getExamplesPolicy("policies/vCPE.policy.operational.input.tosca.json", "operational.restart"); toscaPolicyRestartV2.setVersion("2.0.0"); toscaPolicyRestartV2.getProperties().put("controllerName", "lifecycle"); - update.setPolicies(Arrays.asList(toscaPolicyRestartV2)); + update.setPolicies(Collections.singletonList(toscaPolicyRestartV2)); assertTrue(fsm.update(update)); assertEquals(qlength + 5, fsm.client.getSink().getRecentEvents().length); assertEquals(3, fsm.policyTypesMap.size()); @@ -327,7 +327,7 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest { String badIntegerPolicy = Files.readString(Paths.get(POLICY_COMPLIANT_VCPE_BAD_INTEGER_JSON), StandardCharsets.UTF_8); ToscaPolicy toscaPolicyRestartBad = new StandardCoder().decode(badIntegerPolicy, ToscaPolicy.class); - update.setPolicies(Arrays.asList(toscaPolicyRestartBad)); + update.setPolicies(Collections.singletonList(toscaPolicyRestartBad)); assertFalse(fsm.update(update)); assertTrue(controllerSupport.getController().getDrools().delete(ToscaPolicy.class)); diff --git a/feature-lifecycle/src/test/resources/feature-lifecycle.properties b/feature-lifecycle/src/test/resources/feature-lifecycle.properties index 0c80ed45..052b0165 100644 --- a/feature-lifecycle/src/test/resources/feature-lifecycle.properties +++ b/feature-lifecycle/src/test/resources/feature-lifecycle.properties @@ -17,6 +17,7 @@ # ============LICENSE_END========================================================= lifecycle.pdp.group=${envd:POLICY_PDP_PAP_GROUP:defaultGroup} +lifecycle.pdp.policytypes=${envd:POLICY_PDP_PAP_POLICYTYPES:onap.policies.native.drools.Controller,onap.policies.native.drools.Artifact} noop.source.topics=POLICY-PDP-PAP noop.sink.topics=POLICY-PDP-PAP diff --git a/packages/install/src/files/base.conf b/packages/install/src/files/base.conf index 865a9d18..19a5e44b 100644 --- a/packages/install/src/files/base.conf +++ b/packages/install/src/files/base.conf @@ -2,7 +2,7 @@ # ============LICENSE_START======================================================= # ONAP POLICY # ================================================================================ -# Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. +# Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. # Modifications Copyright (C) 2020 Bell Canada. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); @@ -101,6 +101,7 @@ PAP_HOST= PAP_USERNAME= PAP_PASSWORD= POLICY_PDP_PAP_GROUP=defaultGroup +POLICY_PDP_PAP_POLICYTYPES= # PDP-X -- cgit 1.2.3-korg