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));