From 319e008dae673c08706cb41f3da81bf338476035 Mon Sep 17 00:00:00 2001 From: jhh Date: Wed, 25 Mar 2020 19:37:20 -0500 Subject: native policy use engine for top-down processing This will ensure proper invocation of all feature hooks. Issue-ID: POLICY-2388 Signed-off-by: jhh Change-Id: I8d1666bb5e9526faa588e4f613674e080181d4ba Signed-off-by: jhh --- .../policy/drools/lifecycle/LifecycleFeature.java | 20 +++++++-- .../onap/policy/drools/lifecycle/LifecycleFsm.java | 17 ++++++++ .../PolicyTypeNativeArtifactController.java | 47 +++++++++++++--------- .../PolicyTypeNativeDroolsController.java | 10 ++--- .../features/PolicyControllerFeatureApi.java | 29 +++++++++++-- .../internal/AggregatedPolicyController.java | 42 ++++++++++--------- 6 files changed, 116 insertions(+), 49 deletions(-) diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java index d27172b2..d9205977 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java @@ -38,7 +38,7 @@ public class LifecycleFeature @Override public int getSequenceNumber() { - return 10; + return 1; } @Override @@ -51,6 +51,11 @@ public class LifecycleFeature return fsmStart(controller); } + @Override + public boolean afterPatch(PolicyController controller, boolean success) { + return fsmPatch(controller); + } + @Override public boolean beforeStop(PolicyEngine engine) { return fsmStop(); @@ -63,8 +68,7 @@ public class LifecycleFeature @Override public boolean beforeShutdown(PolicyEngine engine) { - fsm.shutdown(); - return false; + return fsmShutdown(engine); } @Override @@ -101,4 +105,14 @@ public class LifecycleFeature fsm.stop(controller); return false; } + + private boolean fsmPatch(PolicyController controller) { + fsm.patch(controller); + return false; + } + + private boolean fsmShutdown(PolicyEngine engine) { + fsm.shutdown(); + return false; + } } 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 6953d831..3ecb4b3a 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 @@ -179,6 +179,11 @@ public class LifecycleFsm implements Startable { */ public synchronized void start(@NonNull PolicyController controller) { logger.info("lifecycle event: start controller: {}", controller.getName()); + if (!controller.getDrools().isBrained()) { + logger.warn("ignoring lifecycle event: start controller: {}", controller); + return; + } + for (ToscaPolicyTypeIdentifier id : controller.getPolicyTypes()) { if (isToscaPolicyType(id.getName())) { PolicyTypeDroolsController ptDroolsController = (PolicyTypeDroolsController) policyTypesMap.get(id); @@ -191,6 +196,18 @@ public class LifecycleFsm implements Startable { } } + /** + * Patch a controller event. + */ + public synchronized void patch(@NonNull PolicyController controller) { + logger.info("lifecycle event: patch controller: {}", controller.getName()); + if (controller.getDrools().isBrained()) { + this.start(controller); + } else { + this.stop(controller); + } + } + @Override public synchronized boolean stop() { logger.info("lifecycle event: stop engine"); diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeArtifactController.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeArtifactController.java index d91ecccf..113bb885 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeArtifactController.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeArtifactController.java @@ -26,9 +26,11 @@ import org.onap.policy.common.gson.annotation.GsonJsonIgnore; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.drools.controller.DroolsControllerConstants; import org.onap.policy.drools.domain.models.artifact.NativeArtifactPolicy; +import org.onap.policy.drools.protocol.configuration.ControllerConfiguration; import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; import org.onap.policy.drools.system.PolicyController; import org.onap.policy.drools.system.PolicyControllerConstants; +import org.onap.policy.drools.system.PolicyEngineConstants; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; import org.slf4j.Logger; @@ -55,42 +57,47 @@ public class PolicyTypeNativeArtifactController implements PolicyTypeController PolicyController controller; try { nativePolicy = fsm.getDomainMaker().convertTo(policy, NativeArtifactPolicy.class); + DroolsConfiguration droolsConfig = + new DroolsConfiguration( + nativePolicy.getProperties().getRulesArtifact().getArtifactId(), + nativePolicy.getProperties().getRulesArtifact().getGroupId(), + nativePolicy.getProperties().getRulesArtifact().getVersion()); + controller = PolicyControllerConstants.getFactory().get(nativePolicy.getProperties().getController().getName()); + if (controller.getDrools().isBrained()) { + logger.warn("upgrade of a live controller is strongly discouraged (undeploy first): {} -> {}", + controller, droolsConfig); + } + + return update(nativePolicy, droolsConfig); } catch (CoderException | RuntimeException e) { logger.warn("Invalid Policy: {}", policy); return false; } - - DroolsConfiguration newConfig = - new DroolsConfiguration( - nativePolicy.getProperties().getRulesArtifact().getArtifactId(), - nativePolicy.getProperties().getRulesArtifact().getGroupId(), - nativePolicy.getProperties().getRulesArtifact().getVersion()); - - PolicyControllerConstants.getFactory().patch(controller, newConfig); - return true; } @Override public boolean undeploy(ToscaPolicy policy) { - PolicyController controller; try { NativeArtifactPolicy nativePolicy = fsm.getDomainMaker().convertTo(policy, NativeArtifactPolicy.class); - controller = - PolicyControllerConstants.getFactory().get(nativePolicy.getProperties().getController().getName()); + DroolsConfiguration noConfig = + new DroolsConfiguration( + DroolsControllerConstants.NO_ARTIFACT_ID, + DroolsControllerConstants.NO_GROUP_ID, + DroolsControllerConstants.NO_VERSION); + + return update(nativePolicy, noConfig); } catch (RuntimeException | CoderException e) { logger.warn("Invalid Policy: {}", policy); return false; } + } - DroolsConfiguration noConfig = - new DroolsConfiguration( - DroolsControllerConstants.NO_ARTIFACT_ID, - DroolsControllerConstants.NO_GROUP_ID, - DroolsControllerConstants.NO_VERSION); - - PolicyControllerConstants.getFactory().patch(controller, noConfig); - return true; + private boolean update(NativeArtifactPolicy nativePolicy, DroolsConfiguration droolsConfig) { + ControllerConfiguration controllerConfig = + new ControllerConfiguration(nativePolicy.getProperties().getController().getName(), + ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UPDATE, droolsConfig); + return PolicyEngineConstants.getManager().updatePolicyController(controllerConfig) != null; } } diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java index 2a417dcb..8255c027 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java @@ -41,6 +41,7 @@ import org.onap.policy.drools.domain.models.controller.ControllerSourceTopic; import org.onap.policy.drools.properties.DroolsPropertyConstants; import org.onap.policy.drools.system.PolicyController; import org.onap.policy.drools.system.PolicyControllerConstants; +import org.onap.policy.drools.system.PolicyEngineConstants; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; import org.slf4j.Logger; @@ -83,9 +84,8 @@ public class PolicyTypeNativeDroolsController implements PolicyTypeController { PolicyController controller; try { - controller = - PolicyControllerConstants.getFactory().build( - controllerConfig.getControllerName(), controllerProps); + controller = PolicyEngineConstants.getManager() + .createPolicyController(controllerConfig.getControllerName(), controllerProps); } catch (RuntimeException e) { logger.warn("failed deploy (cannot create controller) for policy: {}", policy); return false; @@ -98,8 +98,8 @@ public class PolicyTypeNativeDroolsController implements PolicyTypeController { public boolean undeploy(ToscaPolicy policy) { try { ControllerPolicy nativePolicy = fsm.getDomainMaker().convertTo(policy, ControllerPolicy.class); - PolicyControllerConstants.getFactory() - .destroy(nativePolicy.getProperties().getControllerName()); + PolicyEngineConstants.getManager() + .removePolicyController(nativePolicy.getProperties().getControllerName()); return true; } catch (RuntimeException | CoderException e) { logger.warn("failed undeploy of policy: {}", policy); diff --git a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java index 9c6ac223..49287786 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java +++ b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java @@ -1,8 +1,8 @@ /* * ============LICENSE_START======================================================= - * policy-management + * ONAP * ================================================================================ - * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-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. @@ -23,6 +23,7 @@ package org.onap.policy.drools.features; import java.util.Properties; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.utils.services.OrderedService; +import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; import org.onap.policy.drools.system.PolicyController; public interface PolicyControllerFeatureApi extends OrderedService { @@ -83,7 +84,7 @@ public interface PolicyControllerFeatureApi extends OrderedService { * * @return true if this feature intercepts and takes ownership * of the operation preventing the invocation of - * lower priority features. False, otherwise.. + * lower priority features. False, otherwise. */ default boolean beforeStop(PolicyController controller) { return false; @@ -100,6 +101,28 @@ public interface PolicyControllerFeatureApi extends OrderedService { return false; } + /** + * intercept before the Policy Controller is patched. + * + * @return true if this feature intercepts and takes ownership + * of the operation preventing the invocation of + * lower priority features. False, otherwise. + */ + default boolean beforePatch(PolicyController controller, DroolsConfiguration configuration) { + return false; + } + + /** + * intercept after the Policy Controller is patched. + * + * @return true if this feature intercepts and takes ownership + * of the operation preventing the invocation of + * lower priority features. False, otherwise. + */ + default boolean afterPatch(PolicyController controller, boolean success) { + return false; + } + /** * intercept before the Policy Controller is locked. * diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java b/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java index 5685ff6e..b80f4c86 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java +++ b/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java @@ -215,7 +215,6 @@ public class AggregatedPolicyController implements PolicyController, TopicListen */ @Override public boolean updateDrools(DroolsConfiguration newDroolsConfiguration) { - DroolsConfiguration oldDroolsConfiguration = new DroolsConfiguration(this.droolsController.getArtifactId(), this.droolsController.getGroupId(), this.droolsController.getVersion()); @@ -227,46 +226,53 @@ public class AggregatedPolicyController implements PolicyController, TopicListen return true; } + if (FeatureApiUtils.apply(getProviders(), + feature -> feature.beforePatch(this, newDroolsConfiguration), + (feature, ex) -> logger.error("{}: feature {} before-patch failure because of {}", this, + feature.getClass().getName(), ex.getMessage(), ex))) { + return true; + } + if (droolsController.isBrained() && (newDroolsConfiguration.getArtifactId() == null || DroolsControllerConstants.NO_ARTIFACT_ID.equals(newDroolsConfiguration.getArtifactId()))) { + // detach maven artifact DroolsControllerConstants.getFactory().destroy(this.droolsController); } + boolean success = true; try { - /* Drools Controller created, update initialization properties for restarts */ - this.properties.setProperty(DroolsPropertyConstants.RULES_GROUPID, newDroolsConfiguration.getGroupId()); this.properties.setProperty(DroolsPropertyConstants.RULES_ARTIFACTID, newDroolsConfiguration.getArtifactId()); this.properties.setProperty(DroolsPropertyConstants.RULES_VERSION, newDroolsConfiguration.getVersion()); - getPersistenceManager().storeController(name, this.properties); this.initDrools(this.properties); - /* set drools controller to current locked status */ - - if (this.isLocked()) { - this.droolsController.lock(); + if (isLocked()) { + droolsController.lock(); } else { - this.droolsController.unlock(); + droolsController.unlock(); } - /* set drools controller to current alive status */ - - if (this.isAlive()) { - this.droolsController.start(); + if (isAlive()) { + droolsController.start(); } else { - this.droolsController.stop(); + droolsController.stop(); } - - } catch (IllegalArgumentException e) { + } catch (RuntimeException e) { logger.error("{}: cannot update-drools because of {}", this, e.getMessage(), e); - return false; + success = false; } - return true; + boolean finalSuccess = success; + FeatureApiUtils.apply(getProviders(), + feature -> feature.afterPatch(this, finalSuccess), + (feature, ex) -> logger.error("{}: feature {} after-patch failure because of {}", this, + feature.getClass().getName(), ex.getMessage(), ex)); + + return finalSuccess; } /** -- cgit 1.2.3-korg