2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2020 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.step;
 
  23 import java.util.Collections;
 
  24 import java.util.HashMap;
 
  25 import java.util.LinkedList;
 
  26 import java.util.List;
 
  28 import java.util.concurrent.atomic.AtomicReference;
 
  29 import java.util.function.BiConsumer;
 
  30 import java.util.function.Consumer;
 
  33 import org.apache.commons.lang3.StringUtils;
 
  34 import org.onap.aai.domain.yang.CloudRegion;
 
  35 import org.onap.aai.domain.yang.GenericVnf;
 
  36 import org.onap.aai.domain.yang.ModelVer;
 
  37 import org.onap.aai.domain.yang.ServiceInstance;
 
  38 import org.onap.aai.domain.yang.Tenant;
 
  39 import org.onap.policy.aai.AaiCqResponse;
 
  40 import org.onap.policy.common.utils.coder.StandardCoderObject;
 
  41 import org.onap.policy.controlloop.VirtualControlLoopEvent;
 
  42 import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation;
 
  43 import org.onap.policy.controlloop.actor.aai.AaiGetTenantOperation;
 
  44 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 
  45 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
 
  46 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 
  47 import org.onap.policy.controlloop.eventmanager.Step;
 
  48 import org.onap.policy.controlloop.eventmanager.StepContext;
 
  49 import org.onap.policy.drools.apps.controller.usecases.UsecasesConstants;
 
  52  * Steps specific to the usecases controller. The {@link #setProperties()} method is used
 
  53  * to load the various properties into the operation, extracting enrichment data where
 
  54  * appropriate, and extracting other data from the step's context. For each property,
 
  55  * there is a getXxx() method for extracting the value and a loadXxx() method for loading
 
  56  * the extracted value into the operation. In addition, the
 
  57  * {@link #success(OperationOutcome)} method is responsible for extracting responses from
 
  58  * an operation outcome and recording the data in the step's context for use by subsequent
 
  61 public class Step2 extends Step {
 
  62     public static final String TARGET_MODEL_VERSION_ID = "modelVersionId";
 
  63     public static final String TARGET_MODEL_CUSTOMIZATION_ID = "modelCustomizationId";
 
  64     public static final String TARGET_MODEL_INVARIANT_ID = "modelInvariantId";
 
  65     public static final String TARGET_RESOURCE_ID = "resourceID";
 
  66     public static final String TARGET_INFO_MSG = "Target Entity IDs";
 
  67     public static final String ENRICHMENT_PREFIX = "enrichment/";
 
  68     public static final String VSERVER_VSERVER_NAME = "vserver.vserver-name";
 
  69     public static final String RESOURCE_LINK = "resource-link";
 
  70     public static final String RESULT_DATA = "result-data";
 
  72     private static final Map<String, BiConsumer<Step2, String>> PROPERTY_LOADER;
 
  73     private static final Map<String, Consumer<Step2>> PROPERTY_SAVER;
 
  77          * Populate map for PROPERTY_LOADER.
 
  79         Map<String, BiConsumer<Step2, String>> map = new HashMap<>();
 
  81         map.put(OperationProperties.AAI_DEFAULT_CLOUD_REGION, Step2::loadCloudRegion);
 
  82         map.put(OperationProperties.AAI_DEFAULT_TENANT, Step2::loadTenant);
 
  83         map.put(OperationProperties.AAI_PNF, Step2::loadPnf);
 
  84         map.put(OperationProperties.AAI_RESOURCE_VNF, Step2::loadResourceVnf);
 
  85         map.put(OperationProperties.AAI_SERVICE, Step2::loadService);
 
  86         map.put(OperationProperties.AAI_SERVICE_MODEL, Step2::loadServiceModel);
 
  87         map.put(OperationProperties.AAI_TARGET_ENTITY, Step2::loadTargetEntity);
 
  88         map.put(OperationProperties.AAI_VNF, Step2::loadVnf);
 
  89         map.put(OperationProperties.AAI_VNF_MODEL, Step2::loadVnfModel);
 
  90         map.put(OperationProperties.AAI_VSERVER_LINK, Step2::loadVserverLink);
 
  91         map.put(OperationProperties.DATA_VF_COUNT, Step2::loadVfCount);
 
  92         map.put(OperationProperties.EVENT_ADDITIONAL_PARAMS, Step2::loadAdditionalEventParams);
 
  93         map.put(OperationProperties.EVENT_PAYLOAD, Step2::loadEventPayload);
 
  94         map.put(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES, Step2::loadOptCdsGrpcAaiProperties);
 
  96         map.put(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, Step2::loadDefaultGenericVnf);
 
  98         PROPERTY_LOADER = Collections.unmodifiableMap(map);
 
 102          * Populate map for PROPERTY_SAVER.
 
 104         Map<String, Consumer<Step2>> map2 = new HashMap<>();
 
 106         map2.put(OperationProperties.DATA_VF_COUNT, Step2::storeVfCount);
 
 108         PROPERTY_SAVER = Collections.unmodifiableMap(map2);
 
 112     protected final StepContext stepContext;
 
 113     protected final VirtualControlLoopEvent event;
 
 116      * {@code True} if the associated preprocessing steps have been loaded, {@code false}
 
 121     private boolean preprocessed;
 
 124      * Actions to take to store the Operation's properties back into the context.
 
 126     private List<Consumer<Step2>> postProcessors = new LinkedList<>();
 
 130      * Constructs the object. This is used when constructing the step for the policy's
 
 133      * @param stepContext the step's context
 
 134      * @param params operation parameters
 
 135      * @param event the event being processed
 
 137     public Step2(StepContext stepContext, ControlLoopOperationParams params, VirtualControlLoopEvent event) {
 
 138         super(params, new AtomicReference<>());
 
 139         this.stepContext = stepContext;
 
 144      * Constructs the object using information from another step. This is used when
 
 145      * constructing a preprocessing step.
 
 147      * @param otherStep step whose information should be used
 
 148      * @param actor actor name
 
 149      * @param operation operation name
 
 151     public Step2(Step2 otherStep, String actor, String operation) {
 
 152         super(otherStep, actor, operation);
 
 153         this.stepContext = otherStep.stepContext;
 
 154         this.event = otherStep.event;
 
 158      * Determines if starting this step indicates acceptance of the event. The default
 
 159      * method simply invokes {@link #isPolicyStep()}.
 
 161      * @return {@code true} if this step accepts the event, {@code false} if it is still
 
 164     public boolean acceptsEvent() {
 
 165         return isPolicyStep();
 
 169      * Indicates that the step succeeded with the given outcome. Invoked by the rules. The
 
 170      * default method invokes the post processors.
 
 172      * @param outcome operation's outcome
 
 174     public void success(OperationOutcome outcome) {
 
 175         for (Consumer<Step2> proc : postProcessors) {
 
 181      * Gets the names of the properties required by the operation. The default method just
 
 182      * delegates to the operation to identify the properties.
 
 184      * @return the names of the properties required by the operation
 
 186     public List<String> getPropertyNames() {
 
 187         return getOperation().getPropertyNames();
 
 191      * Sets the operation's properties. This is invoked <i>after</i> any preprocessor
 
 192      * steps have been performed. It also adds items to {@link #postProcessors}.
 
 194     public void setProperties() {
 
 195         postProcessors.clear();
 
 197         for (String propName : getPropertyNames()) {
 
 198             // identify the saver, if any
 
 199             Consumer<Step2> saver = PROPERTY_SAVER.get(propName);
 
 201                 postProcessors.add(saver);
 
 206             if (propName.startsWith(ENRICHMENT_PREFIX)) {
 
 207                 loadEnrichment(propName);
 
 211             BiConsumer<Step2, String> loader = PROPERTY_LOADER.get(propName);
 
 212             if (loader == null) {
 
 213                 throw new IllegalArgumentException("unknown property " + propName + " needed by " + getActorName() + "."
 
 214                                 + getOperationName());
 
 217             loader.accept(this, propName);
 
 221     protected void loadCloudRegion(String propName) {
 
 222         getOperation().setProperty(propName, getCloudRegion());
 
 225     protected void loadTenant(String propName) {
 
 226         getOperation().setProperty(propName, getTenant());
 
 229     protected void loadPnf(String propName) {
 
 230         getOperation().setProperty(propName, getPnf());
 
 233     protected void loadResourceVnf(String propName) {
 
 234         getOperation().setProperty(propName, getResourceVnf());
 
 237     protected void loadService(String propName) {
 
 238         getOperation().setProperty(propName, getService());
 
 241     protected void loadServiceModel(String propName) {
 
 242         getOperation().setProperty(propName, getServiceModel());
 
 245     protected void loadTargetEntity(String propName) {
 
 246         getOperation().setProperty(propName, getTargetEntity());
 
 249     protected void loadVnf(String propName) {
 
 250         getOperation().setProperty(propName, getVnf());
 
 253     protected void loadVnfModel(String propName) {
 
 254         getOperation().setProperty(propName, getVnfModel());
 
 257     protected void loadVserverLink(String propName) {
 
 258         getOperation().setProperty(propName, getVserverLink());
 
 261     protected void loadVfCount(String propName) {
 
 262         getOperation().setProperty(propName, getVfCount());
 
 265     protected void loadEnrichment(String propName) {
 
 266         getOperation().setProperty(propName, getEnrichment(propName));
 
 269     protected void loadAdditionalEventParams(String propName) {
 
 270         getOperation().setProperty(propName, getAdditionalEventParams());
 
 273     protected void loadEventPayload(String propName) {
 
 274         getOperation().setProperty(propName, getEventPayload());
 
 277     protected void loadOptCdsGrpcAaiProperties(String propName) {
 
 281     protected void loadDefaultGenericVnf(String propName) {
 
 282         getOperation().setProperty(propName, getDefaultGenericVnf());
 
 285     protected CloudRegion getCloudRegion() {
 
 286         AaiCqResponse aaicq = getCustomQueryData();
 
 287         return aaicq.getDefaultCloudRegion();
 
 290     protected Tenant getTenant() {
 
 291         AaiCqResponse aaicq = getCustomQueryData();
 
 292         return aaicq.getDefaultTenant();
 
 295     protected StandardCoderObject getPnf() {
 
 296         return stepContext.getProperty(AaiGetPnfOperation.getKey(getTargetEntity()));
 
 299     protected GenericVnf getResourceVnf() {
 
 300         verifyNotNull(TARGET_INFO_MSG, params.getTargetEntityIds());
 
 302         String resourceId = params.getTargetEntityIds().get(TARGET_RESOURCE_ID);
 
 304         verifyNotNull("Target resource ID", resourceId);
 
 306         AaiCqResponse aaicq = getCustomQueryData();
 
 307         return aaicq.getGenericVnfByModelInvariantId(resourceId);
 
 310     protected ServiceInstance getService() {
 
 311         AaiCqResponse aaicq = getCustomQueryData();
 
 312         return aaicq.getServiceInstance();
 
 315     protected ModelVer getServiceModel() {
 
 316         AaiCqResponse aaicq = getCustomQueryData();
 
 317         ServiceInstance service = aaicq.getServiceInstance();
 
 318         return aaicq.getModelVerByVersionId(service.getModelVersionId());
 
 322      * The default method assumes there is only one target entity and that it's stored
 
 323      * within the step's context.
 
 325     protected String getTargetEntity() {
 
 326         return stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY);
 
 329     protected GenericVnf getVnf() {
 
 330         verifyNotNull(TARGET_INFO_MSG, params.getTargetEntityIds());
 
 332         String modelInvariantId = params.getTargetEntityIds().get(TARGET_MODEL_INVARIANT_ID);
 
 334         verifyNotNull(TARGET_MODEL_INVARIANT_ID, modelInvariantId);
 
 336         AaiCqResponse aaicq = getCustomQueryData();
 
 337         return aaicq.getGenericVnfByVfModuleModelInvariantId(modelInvariantId);
 
 340     protected ModelVer getVnfModel() {
 
 341         GenericVnf vnf = getVnf();
 
 342         AaiCqResponse aaicq = getCustomQueryData();
 
 343         return aaicq.getModelVerByVersionId(vnf.getModelVersionId());
 
 346     protected String getVserverLink() {
 
 347         String vserver = event.getAai().get(VSERVER_VSERVER_NAME);
 
 348         if (StringUtils.isBlank(vserver)) {
 
 349             throw new IllegalArgumentException("missing " + VSERVER_VSERVER_NAME + " in enrichment data");
 
 352         StandardCoderObject tenant = stepContext.getProperty(AaiGetTenantOperation.getKey(vserver));
 
 353         verifyNotNull("tenant data", tenant);
 
 355         String resourceLink = tenant.getString(RESULT_DATA, 0, RESOURCE_LINK);
 
 356         verifyNotNull("tenant data resource-link", resourceLink);
 
 358         return stripPrefix(resourceLink, 3);
 
 361     protected Integer getVfCount() {
 
 362         if (stepContext.contains(OperationProperties.DATA_VF_COUNT)) {
 
 363             return stepContext.getProperty(OperationProperties.DATA_VF_COUNT);
 
 366         verifyNotNull(TARGET_INFO_MSG, params.getTargetEntityIds());
 
 368         String modelCustomizationId = params.getTargetEntityIds().get(TARGET_MODEL_CUSTOMIZATION_ID);
 
 369         String modelInvariantId = params.getTargetEntityIds().get(TARGET_MODEL_INVARIANT_ID);
 
 370         String modelVersionId = params.getTargetEntityIds().get(TARGET_MODEL_VERSION_ID);
 
 372         verifyNotNull("target modelCustomizationId", modelCustomizationId);
 
 373         verifyNotNull("target modelInvariantId", modelInvariantId);
 
 374         verifyNotNull("target modelVersionId", modelVersionId);
 
 376         AaiCqResponse aaicq = getCustomQueryData();
 
 377         return aaicq.getVfModuleCount(modelCustomizationId, modelInvariantId, modelVersionId);
 
 380     protected String getEnrichment(String propName) {
 
 381         String enrichmentKey = propName.substring(ENRICHMENT_PREFIX.length());
 
 382         String value = event.getAai().get(enrichmentKey);
 
 383         verifyNotNull(propName, value);
 
 388     protected Map<String, String> getAdditionalEventParams() {
 
 389         return event.getAdditionalEventParams();
 
 392     protected String getEventPayload() {
 
 393         return event.getPayload();
 
 396     protected GenericVnf getDefaultGenericVnf() {
 
 397         AaiCqResponse aaicq = getCustomQueryData();
 
 398         return aaicq.getDefaultGenericVnf();
 
 401     protected AaiCqResponse getCustomQueryData() {
 
 402         AaiCqResponse aaicq = stepContext.getProperty(AaiCqResponse.CONTEXT_KEY);
 
 403         verifyNotNull("custom query data", aaicq);
 
 408     protected void storeVfCount() {
 
 409         if (!getOperation().containsProperty(OperationProperties.DATA_VF_COUNT)) {
 
 413         int vfcount = getOperation().getProperty(OperationProperties.DATA_VF_COUNT);
 
 414         stepContext.setProperty(OperationProperties.DATA_VF_COUNT, vfcount);
 
 417     protected void verifyNotNull(String propName, Object value) {
 
 419             throw new IllegalArgumentException(
 
 420                             "missing " + propName + " for " + getActorName() + "." + getOperationName());
 
 424     protected static String stripPrefix(String resourceLink, int ncomponents) {
 
 426         for (int nslashes = 0; nslashes < ncomponents; ++nslashes) {
 
 427             int idx = resourceLink.indexOf('/', previdx + 1);
 
 435         return resourceLink.substring(Math.max(0, previdx));