2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
 
   6  * ================================================================================
 
   7  * Licensed under the Apache License, Version 2.0 (the "License");
 
   8  * you may not use this file except in compliance with the License.
 
   9  * You may obtain a copy of the License at
 
  11  *      http://www.apache.org/licenses/LICENSE-2.0
 
  13  * Unless required by applicable law or agreed to in writing, software
 
  14  * distributed under the License is distributed on an "AS IS" BASIS,
 
  15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  16  * See the License for the specific language governing permissions and
 
  17  * limitations under the License.
 
  18  * ============LICENSE_END=========================================================
 
  21 package org.onap.policy.drools.apps.controller.usecases;
 
  23 import static org.onap.policy.controlloop.ControlLoopTargetType.PNF;
 
  24 import static org.onap.policy.controlloop.ControlLoopTargetType.VM;
 
  25 import static org.onap.policy.controlloop.ControlLoopTargetType.VNF;
 
  26 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.GENERIC_VNF_IS_CLOSED_LOOP_DISABLED;
 
  27 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.GENERIC_VNF_PROV_STATUS;
 
  28 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.GENERIC_VNF_VNF_ID;
 
  29 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.GENERIC_VNF_VNF_NAME;
 
  30 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.PNF_IS_IN_MAINT;
 
  31 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.PNF_NAME;
 
  32 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.PROV_STATUS_ACTIVE;
 
  33 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VM_NAME;
 
  34 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VNF_NAME;
 
  35 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VSERVER_IS_CLOSED_LOOP_DISABLED;
 
  36 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VSERVER_PROV_STATUS;
 
  37 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VSERVER_VSERVER_NAME;
 
  39 import java.util.Deque;
 
  42 import java.util.stream.Collectors;
 
  43 import java.util.stream.Stream;
 
  44 import org.drools.core.WorkingMemory;
 
  45 import org.onap.policy.controlloop.ControlLoopException;
 
  46 import org.onap.policy.controlloop.ControlLoopResponse;
 
  47 import org.onap.policy.controlloop.VirtualControlLoopEvent;
 
  48 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 
  49 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
 
  50 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 
  51 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
 
  52 import org.onap.policy.controlloop.eventmanager.ActorConstants;
 
  53 import org.onap.policy.controlloop.eventmanager.ClEventManagerWithEvent;
 
  54 import org.onap.policy.controlloop.eventmanager.EventManagerServices;
 
  55 import org.onap.policy.controlloop.eventmanager.StepContext;
 
  56 import org.onap.policy.drools.apps.controller.usecases.step.AaiCqStep2;
 
  57 import org.onap.policy.drools.apps.controller.usecases.step.AaiGetPnfStep2;
 
  58 import org.onap.policy.drools.apps.controller.usecases.step.AaiGetTenantStep2;
 
  59 import org.onap.policy.drools.apps.controller.usecases.step.GetTargetEntityStep2;
 
  60 import org.onap.policy.drools.apps.controller.usecases.step.GuardStep2;
 
  61 import org.onap.policy.drools.apps.controller.usecases.step.LockStep2;
 
  62 import org.onap.policy.drools.apps.controller.usecases.step.Step2;
 
  63 import org.onap.policy.sdnr.PciMessage;
 
  66  * Manager for a single control loop event. Once this has been created, the event can be
 
  67  * retracted from working memory. Processing progresses through each policy, which
 
  68  * involves at least one step. As a step is processed, additional preprocessor steps may
 
  69  * be pushed onto the queue (e.g., locks, A&AI queries, guards).
 
  71 public class UsecasesEventManager extends ClEventManagerWithEvent<Step2> implements StepContext {
 
  73     private static final long serialVersionUID = -1216568161322872641L;
 
  76      * If there's a failure from one of these actors, then the TOSCA processing should be
 
  79     private static final Set<String> ABORT_ACTORS = Set.of(ActorConstants.CL_TIMEOUT_ACTOR, ActorConstants.LOCK_ACTOR);
 
  81     private static final Set<String> VALID_TARGETS = Stream
 
  82                     .of(VM_NAME, VNF_NAME, VSERVER_VSERVER_NAME, GENERIC_VNF_VNF_ID, GENERIC_VNF_VNF_NAME, PNF_NAME)
 
  83                     .map(String::toLowerCase).collect(Collectors.toSet());
 
  85     private static final Set<String> TRUE_VALUES = Set.of("true", "t", "yes", "y");
 
  88      * Names of Operation properties for which A&AI PNF query is needed.
 
  90     private static final Set<String> PNF_PROPERTIES = Set.of(OperationProperties.AAI_PNF);
 
  93      * Names of Operation properties for which A&AI Tenant query is needed.
 
  95     private static final Set<String> TENANT_PROPERTIES = Set.of(OperationProperties.AAI_VSERVER_LINK);
 
  98      * Names of Operation properties for which A&AI custom query is needed.
 
 100     private static final Set<String> CQ_PROPERTIES = Set.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION,
 
 101                     OperationProperties.AAI_VNF, OperationProperties.AAI_SERVICE_MODEL,
 
 102                     OperationProperties.AAI_VNF_MODEL, OperationProperties.AAI_SERVICE,
 
 103                     OperationProperties.AAI_RESOURCE_VNF, UsecasesConstants.AAI_DEFAULT_GENERIC_VNF);
 
 107      * Constructs the object.
 
 109      * @param services services the manager should use when processing the event
 
 110      * @param params control loop parameters
 
 111      * @param event event to be managed by this object
 
 112      * @param workMem working memory to update if this changes
 
 113      * @throws ControlLoopException if the event is invalid or if a YAML processor cannot
 
 116     public UsecasesEventManager(EventManagerServices services, ControlLoopParams params, VirtualControlLoopEvent event,
 
 117                     WorkingMemory workMem) throws ControlLoopException {
 
 119         super(services, params, event, workMem);
 
 121         if (isClosedLoopDisabled(event)) {
 
 122             throw new IllegalStateException("is-closed-loop-disabled is set to true on VServer or VNF");
 
 125         if (isProvStatusInactive(event)) {
 
 126             throw new IllegalStateException("prov-status is not ACTIVE on VServer or VNF");
 
 131      * This is needed to satisfy drools, thus disabling sonar.
 
 134     public Deque<Step2> getSteps() {    // NOSONAR
 
 135         return super.getSteps();
 
 139     public void loadPreprocessorSteps() {
 
 140         super.loadPreprocessorSteps();
 
 142         final Deque<Step2> steps = getSteps();
 
 143         final Step2 step = getSteps().peek();
 
 145         // determine if any A&AI queries are needed
 
 148         var needTenant = false;
 
 149         var needTargetEntity = false;
 
 151         for (String propName : step.getPropertyNames()) {
 
 152             needCq = needCq || CQ_PROPERTIES.contains(propName);
 
 153             needPnf = needPnf || PNF_PROPERTIES.contains(propName);
 
 154             needTenant = needTenant || TENANT_PROPERTIES.contains(propName);
 
 155             needTargetEntity = needTargetEntity || OperationProperties.AAI_TARGET_ENTITY.equals(propName);
 
 159          * The Policy's actual operation requires additional, implicit steps, such as
 
 160          * locking and guards.
 
 162         final boolean needPolicySteps = step.isPolicyStep();
 
 166          * NOTE: need to push steps onto the queue in the OPPOSITE order in which they
 
 171         // GUARD must be pushed first
 
 172         if (needPolicySteps) {
 
 173             steps.push(new GuardStep2(step, getClosedLoopControlName()));
 
 178             steps.push(new AaiCqStep2(step));
 
 182             steps.push(new AaiGetPnfStep2(step));
 
 186             steps.push(new AaiGetTenantStep2(step));
 
 189         // LOCK must be pushed after the queries
 
 190         if (needPolicySteps) {
 
 191             steps.push(new LockStep2(step));
 
 194         // GET-TARGET-ENTITY should be pushed last
 
 195         if (needTargetEntity) {
 
 196             steps.push(new GetTargetEntityStep2(step));
 
 201     public boolean isAbort(OperationOutcome outcome) {
 
 202         return (super.isAbort(outcome) && ABORT_ACTORS.contains(outcome.getActor()));
 
 206      * Stores an operation outcome in the DB.
 
 208      * @param outcome operation outcome to store
 
 210     public void storeInDataBase(OperationOutcome2 outcome) {
 
 211         storeInDataBase(outcome, getProperty(OperationProperties.AAI_TARGET_ENTITY));
 
 215     public ControlLoopResponse makeControlLoopResponse(OperationOutcome outcome) {
 
 216         var clRsp = super.makeControlLoopResponse(outcome);
 
 218         Object obj = outcome.getResponse();
 
 219         if (!(obj instanceof PciMessage)) {
 
 223         PciMessage msg = (PciMessage) obj;
 
 224         if (msg.getBody() != null && msg.getBody().getOutput() != null) {
 
 225             clRsp.setPayload(msg.getBody().getOutput().getPayload());
 
 232     protected void checkEventSyntax(VirtualControlLoopEvent event) throws ControlLoopException {
 
 233         super.checkEventSyntax(event);
 
 234         validateAaiData(event);
 
 238     protected void validateTarget(VirtualControlLoopEvent event) throws ControlLoopException {
 
 239         super.validateTarget(event);
 
 241         if (!VALID_TARGETS.contains(event.getTarget().toLowerCase())) {
 
 242             throw new ControlLoopException("target field invalid");
 
 246     private void validateAaiData(VirtualControlLoopEvent event) throws ControlLoopException {
 
 247         Map<String, String> eventAai = event.getAai();
 
 248         if (eventAai == null) {
 
 249             throw new ControlLoopException("AAI is null");
 
 251         if (event.getTargetType() == null) {
 
 252             throw new ControlLoopException("The Target type is null");
 
 254         switch (event.getTargetType()) {
 
 257                 validateAaiVmVnfData(eventAai);
 
 260                 validateAaiPnfData(eventAai);
 
 263                 throw new ControlLoopException("The target type is not supported");
 
 267     private void validateAaiVmVnfData(Map<String, String> eventAai) throws ControlLoopException {
 
 268         if (eventAai.get(GENERIC_VNF_VNF_ID) == null && eventAai.get(VSERVER_VSERVER_NAME) == null
 
 269                         && eventAai.get(GENERIC_VNF_VNF_NAME) == null) {
 
 270             throw new ControlLoopException(
 
 271                             "generic-vnf.vnf-id or generic-vnf.vnf-name or vserver.vserver-name information missing");
 
 275     private void validateAaiPnfData(Map<String, String> eventAai) throws ControlLoopException {
 
 276         if (eventAai.get(PNF_NAME) == null) {
 
 277             throw new ControlLoopException("AAI PNF object key pnf-name is missing");
 
 282      * Is closed loop disabled for an event.
 
 284      * @param event the event
 
 285      * @return <code>true</code> if the control loop is disabled, <code>false</code>
 
 288     private static boolean isClosedLoopDisabled(VirtualControlLoopEvent event) {
 
 289         Map<String, String> aai = event.getAai();
 
 290         return (isAaiTrue(aai.get(VSERVER_IS_CLOSED_LOOP_DISABLED))
 
 291                         || isAaiTrue(aai.get(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED))
 
 292                         || isAaiTrue(aai.get(PNF_IS_IN_MAINT)));
 
 296      * Does provisioning status, for an event, have a value other than ACTIVE.
 
 298      * @param event the event
 
 299      * @return {@code true} if the provisioning status is neither ACTIVE nor {@code null},
 
 300      *         {@code false} otherwise
 
 302     private static boolean isProvStatusInactive(VirtualControlLoopEvent event) {
 
 303         Map<String, String> aai = event.getAai();
 
 304         return !(PROV_STATUS_ACTIVE.equalsIgnoreCase(aai.getOrDefault(VSERVER_PROV_STATUS, PROV_STATUS_ACTIVE))
 
 305                         && PROV_STATUS_ACTIVE.equalsIgnoreCase(
 
 306                                         aai.getOrDefault(GENERIC_VNF_PROV_STATUS, PROV_STATUS_ACTIVE)));
 
 310      * Determines the boolean value represented by the given AAI field value.
 
 312      * @param aaiValue value to be examined
 
 313      * @return the boolean value represented by the field value, or {@code false} if the
 
 314      *         value is {@code null}
 
 316     private static boolean isAaiTrue(String aaiValue) {
 
 317         return (aaiValue != null && TRUE_VALUES.contains(aaiValue.toLowerCase()));
 
 321     protected void loadPolicyStep(ControlLoopOperationParams params) {
 
 322         getSteps().add(new Step2(this, params, getEvent()));