From 6dfab64262ea5816c761042192c84e498a3177ab Mon Sep 17 00:00:00 2001 From: jhh Date: Wed, 12 Feb 2020 18:20:06 -0600 Subject: tosca compliant op policy support + vcpe test Tosca Compliant and Toscal Legacy Operational policies are both supported for backwards compatibility. vCPE usecase junits to support 2 equivalent policies, one tosca compliant and the other one legacy. Issue-ID: POLICY-2360 Signed-off-by: jhh Change-Id: Iafbfc92bbec42e6a3fe4ceb4a9a17c85e636ea14 Signed-off-by: jhh --- .../controlloop/drl/legacy/ControlLoopParams.java | 3 +- .../eventmanager/ControlLoopEventManager.java | 46 ++++++--- .../processor/ControlLoopProcessor.java | 109 +++++++++++++++++++-- .../policy/controlloop/utils/ControlLoopUtils.java | 32 +----- 4 files changed, 137 insertions(+), 53 deletions(-) (limited to 'controlloop/common/eventmanager/src/main') diff --git a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/drl/legacy/ControlLoopParams.java b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/drl/legacy/ControlLoopParams.java index 6e24e26bf..769a6d971 100644 --- a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/drl/legacy/ControlLoopParams.java +++ b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/drl/legacy/ControlLoopParams.java @@ -23,6 +23,7 @@ package org.onap.policy.controlloop.drl.legacy; import java.io.Serializable; import lombok.Data; import lombok.NoArgsConstructor; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; @Data @NoArgsConstructor @@ -31,8 +32,8 @@ public class ControlLoopParams implements Serializable { private static final long serialVersionUID = 970755684770982776L; private String closedLoopControlName; - private String controlLoopYaml; private String policyName; private String policyScope; private String policyVersion; + private ToscaPolicy toscaPolicy; } diff --git a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopEventManager.java b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopEventManager.java index f297a8f6b..6e88ce982 100644 --- a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopEventManager.java +++ b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopEventManager.java @@ -55,6 +55,7 @@ import org.onap.policy.drools.core.lock.LockImpl; import org.onap.policy.drools.core.lock.LockState; import org.onap.policy.drools.system.PolicyEngineConstants; import org.onap.policy.drools.utils.Pair; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.rest.RestManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -234,19 +235,7 @@ public class ControlLoopEventManager implements Serializable { return notification; } - // - // At this point we are good to go with this event - // - this.onset = event; - this.numOnsets = 1; - // - // - // Set ourselves as active - // - this.isActivated = true; - - notification.setNotification(ControlLoopNotificationType.ACTIVE); - return notification; + return postActivate(event, notification); } /** @@ -287,6 +276,34 @@ public class ControlLoopEventManager implements Serializable { return rejectNotification(event, e.getMessage()); } + return postActivate(event, notification); + } + + /** + * Activate a control loop event. + * + * @param toscaPolicy the tosca policy + * @param event the event + * @return the VirtualControlLoopNotification + */ + public VirtualControlLoopNotification activate(ToscaPolicy toscaPolicy, VirtualControlLoopEvent event) { + VirtualControlLoopNotification notification = preActivationChecks(event); + if (notification.getNotification() == ControlLoopNotificationType.REJECTED) { + return notification; + } + + try { + this.processor = new ControlLoopProcessor(toscaPolicy); + } catch (ControlLoopException e) { + logger.error("{}: activate from Tosca Policy threw: ", this, e); + return rejectNotification(event, e.getMessage()); + } + + return postActivate(event, notification); + } + + private VirtualControlLoopNotification postActivate( + VirtualControlLoopEvent event, VirtualControlLoopNotification notification) { // // At this point we are good to go with this event // @@ -298,9 +315,6 @@ public class ControlLoopEventManager implements Serializable { // this.isActivated = true; - // - // - // notification.setNotification(ControlLoopNotificationType.ACTIVE); return notification; } diff --git a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/processor/ControlLoopProcessor.java b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/processor/ControlLoopProcessor.java index ac684fcda..4cff616a0 100644 --- a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/processor/ControlLoopProcessor.java +++ b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/processor/ControlLoopProcessor.java @@ -1,8 +1,8 @@ /*- * ============LICENSE_START======================================================= - * controlloop processor + * ONAP * ================================================================================ - * Copyright (C) 2017-2018 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. @@ -21,22 +21,41 @@ package org.onap.policy.controlloop.processor; import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.stream.Collectors; +import lombok.Getter; +import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.controlloop.ControlLoopException; +import org.onap.policy.controlloop.drl.legacy.ControlLoopParams; import org.onap.policy.controlloop.policy.ControlLoop; import org.onap.policy.controlloop.policy.ControlLoopPolicy; import org.onap.policy.controlloop.policy.FinalResult; import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.PolicyParam; import org.onap.policy.controlloop.policy.PolicyResult; +import org.onap.policy.controlloop.policy.Target; +import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.drools.domain.models.DroolsPolicy; +import org.onap.policy.drools.models.domain.legacy.LegacyPolicy; +import org.onap.policy.drools.models.domain.operational.OperationalPolicy; +import org.onap.policy.drools.system.PolicyEngineConstants; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor; public class ControlLoopProcessor implements Serializable { private static final long serialVersionUID = 1L; - - private final String yaml; + private final ControlLoopPolicy policy; private String currentNestedPolicyId = null; + @Getter + private ToscaPolicy toscaOpPolicy; + + @Getter + private DroolsPolicy domainOpPolicy; + /** * Construct an instance from yaml. * @@ -44,11 +63,10 @@ public class ControlLoopProcessor implements Serializable { * @throws ControlLoopException if an error occurs */ public ControlLoopProcessor(String yaml) throws ControlLoopException { - this.yaml = yaml; try { final Yaml y = new Yaml(new CustomClassLoaderConstructor(ControlLoopPolicy.class, ControlLoopPolicy.class.getClassLoader())); - final Object obj = y.load(this.yaml); + final Object obj = y.load(yaml); this.policy = (ControlLoopPolicy) obj; this.currentNestedPolicyId = this.policy.getControlLoop().getTrigger_policy(); @@ -60,6 +78,85 @@ public class ControlLoopProcessor implements Serializable { } } + /** + * Create an instance from a Tosca Policy. + */ + public ControlLoopProcessor(ToscaPolicy toscaPolicy) throws ControlLoopException { + try { + // TODO: automate policy type to models mapping + this.policy = + ("onap.policies.controlloop.Operational".equals(toscaPolicy.getType())) + ? buildPolicyFromToscaLegacy(toscaPolicy) + : buildPolicyFromToscaCompliant(toscaPolicy); + + this.currentNestedPolicyId = this.policy.getControlLoop().getTrigger_policy(); + this.toscaOpPolicy = toscaPolicy; + } catch (RuntimeException | CoderException | UnsupportedEncodingException e) { + throw new ControlLoopException(e); + } + } + + protected ControlLoopPolicy buildPolicyFromToscaLegacy(ToscaPolicy policy) + throws UnsupportedEncodingException, CoderException { + LegacyPolicy legacyPolicy = + PolicyEngineConstants.getManager().getDomainMaker().convertTo(policy, LegacyPolicy.class); + this.domainOpPolicy = legacyPolicy; + String decodedPolicy = URLDecoder.decode(legacyPolicy.getProperties().getContent(), "UTF-8"); + return new Yaml( + new CustomClassLoaderConstructor( + ControlLoopPolicy.class, ControlLoopPolicy.class.getClassLoader())).load(decodedPolicy); + } + + protected ControlLoopPolicy buildPolicyFromToscaCompliant(ToscaPolicy policy) throws CoderException { + OperationalPolicy domainPolicy = + PolicyEngineConstants.getManager().getDomainMaker().convertTo(policy, OperationalPolicy.class); + + ControlLoopPolicy backwardsCompatiblePolicy = new ControlLoopPolicy(); + + // @formatter:off + backwardsCompatiblePolicy.setPolicies( + domainPolicy.getProperties().getOperations().stream().map(operation -> new Policy( + PolicyParam.builder() + .id(operation.getId()) + .name(operation.getActorOperation().getOperation()) + .description(operation.getDescription()) + .actor(operation.getActorOperation().getActor()) + .payload(operation.getActorOperation().getPayload()) + .recipe(operation.getActorOperation().getOperation()) + .retries(operation.getRetries()) + .timeout(operation.getTimeout()) + .target(new Target(TargetType.valueOf(operation.getActorOperation().getTarget().getType()), + operation.getActorOperation().getTarget().getResourceId())).build())) + .collect(Collectors.toList())); + // @formatter:on + + ControlLoop controlLoop = new ControlLoop(); + controlLoop.setAbatement(domainPolicy.getProperties().isAbatement()); + controlLoop.setControlLoopName(domainPolicy.getProperties().getId()); + controlLoop.setTimeout(domainPolicy.getProperties().getTimeout()); + controlLoop.setTrigger_policy(domainPolicy.getProperties().getTrigger()); + controlLoop.setVersion(domainPolicy.getVersion()); + + backwardsCompatiblePolicy.setControlLoop(controlLoop); + this.domainOpPolicy = domainPolicy; + return backwardsCompatiblePolicy; + } + + /** + * Get ControlLoopParams. + */ + public ControlLoopParams getControlLoopParams() { + ControlLoopParams controlLoopParams = new ControlLoopParams(); + + controlLoopParams.setClosedLoopControlName(this.getControlLoop().getControlLoopName()); + controlLoopParams.setPolicyScope(domainOpPolicy.getType() + ":" + domainOpPolicy.getTypeVersion()); + controlLoopParams.setPolicyName(domainOpPolicy.getName()); + controlLoopParams.setPolicyVersion(domainOpPolicy.getVersion()); + controlLoopParams.setToscaPolicy(toscaOpPolicy); + + return controlLoopParams; + } + public ControlLoop getControlLoop() { return this.policy.getControlLoop(); } diff --git a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/utils/ControlLoopUtils.java b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/utils/ControlLoopUtils.java index cfa4b3d3b..b5d95fed7 100644 --- a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/utils/ControlLoopUtils.java +++ b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/utils/ControlLoopUtils.java @@ -18,9 +18,6 @@ package org.onap.policy.controlloop.utils; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import org.apache.commons.lang3.StringUtils; import org.onap.policy.controlloop.ControlLoopException; import org.onap.policy.controlloop.drl.legacy.ControlLoopParams; import org.onap.policy.controlloop.processor.ControlLoopProcessor; @@ -34,7 +31,6 @@ import org.slf4j.LoggerFactory; public class ControlLoopUtils { public static final Logger logger = LoggerFactory.getLogger(ControlLoopUtils.class); - public static final String TOSCA_POLICY_PROPERTY_CONTENT = "content"; private ControlLoopUtils() { super(); @@ -45,35 +41,11 @@ public class ControlLoopUtils { */ public static ControlLoopParams toControlLoopParams(ToscaPolicy policy) { - // TODO: ControlLoopParams class should be moved to this repo and take Tosca Policy in a constructor. - /* No exceptions are thrown to keep the DRL simpler */ try { - if (policy == null || policy.getProperties() == null - || policy.getProperties().get(TOSCA_POLICY_PROPERTY_CONTENT) == null) { - logger.error("Invalid Policy: {}", policy); - return null; - } - - String encodedPolicy = policy.getProperties().get(TOSCA_POLICY_PROPERTY_CONTENT).toString(); - String decodedPolicy = URLDecoder.decode(encodedPolicy, "UTF-8"); - - ControlLoopProcessor controlLoopProcessor = new ControlLoopProcessor(decodedPolicy); - if (controlLoopProcessor.getControlLoop() == null - || StringUtils.isEmpty(controlLoopProcessor.getControlLoop().getControlLoopName())) { - return null; - } - - ControlLoopParams controlLoopParams = new ControlLoopParams(); - controlLoopParams.setClosedLoopControlName(controlLoopProcessor.getControlLoop().getControlLoopName()); - controlLoopParams.setControlLoopYaml(encodedPolicy); - controlLoopParams.setPolicyScope(policy.getType() + ":" + policy.getTypeVersion()); - controlLoopParams.setPolicyName(policy.getName()); - controlLoopParams.setPolicyVersion(policy.getVersion()); - - return controlLoopParams; - } catch (ControlLoopException | RuntimeException | UnsupportedEncodingException e) { + return new ControlLoopProcessor(policy).getControlLoopParams(); + } catch (ControlLoopException | RuntimeException e) { logger.error("Invalid Policy because of {}: {}", e.getMessage(), policy, e); return null; } -- cgit 1.2.3-korg