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.aai.domain.yang.Vserver;
40 import org.onap.policy.aai.AaiCqResponse;
41 import org.onap.policy.common.utils.coder.StandardCoderObject;
42 import org.onap.policy.controlloop.VirtualControlLoopEvent;
43 import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation;
44 import org.onap.policy.controlloop.actor.aai.AaiGetTenantOperation;
45 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
46 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
47 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
48 import org.onap.policy.controlloop.eventmanager.Step;
49 import org.onap.policy.controlloop.eventmanager.StepContext;
50 import org.onap.policy.drools.apps.controller.usecases.UsecasesConstants;
53 * Steps specific to the usecases controller. The {@link #setProperties()} method is used
54 * to load the various properties into the operation, extracting enrichment data where
55 * appropriate, and extracting other data from the step's context. For each property,
56 * there is a getXxx() method for extracting the value and a loadXxx() method for loading
57 * the extracted value into the operation. In addition, the
58 * {@link #success(OperationOutcome)} method is responsible for extracting responses from
59 * an operation outcome and recording the data in the step's context for use by subsequent
62 public class Step2 extends Step {
63 public static final String TARGET_MODEL_VERSION_ID = "modelVersionId";
64 public static final String TARGET_MODEL_CUSTOMIZATION_ID = "modelCustomizationId";
65 public static final String TARGET_MODEL_INVARIANT_ID = "modelInvariantId";
66 public static final String TARGET_RESOURCE_ID = "resourceID";
67 public static final String TARGET_INFO_MSG = "Target Entity IDs";
68 public static final String ENRICHMENT_PREFIX = "enrichment/";
69 public static final String VSERVER_VSERVER_NAME = "vserver.vserver-name";
70 public static final String RESOURCE_LINK = "resource-link";
71 public static final String RESULT_DATA = "result-data";
73 private static final Map<String, BiConsumer<Step2, String>> PROPERTY_LOADER;
74 private static final Map<String, Consumer<Step2>> PROPERTY_SAVER;
78 * Populate map for PROPERTY_LOADER.
80 Map<String, BiConsumer<Step2, String>> map = new HashMap<>();
82 map.put(OperationProperties.AAI_DEFAULT_CLOUD_REGION, Step2::loadCloudRegion);
83 map.put(OperationProperties.AAI_DEFAULT_TENANT, Step2::loadTenant);
84 map.put(OperationProperties.AAI_PNF, Step2::loadPnf);
85 map.put(OperationProperties.AAI_RESOURCE_VNF, Step2::loadResourceVnf);
86 map.put(OperationProperties.AAI_SERVICE, Step2::loadService);
87 map.put(OperationProperties.AAI_SERVICE_MODEL, Step2::loadServiceModel);
88 map.put(OperationProperties.AAI_TARGET_ENTITY, Step2::loadTargetEntity);
89 map.put(OperationProperties.AAI_VNF, Step2::loadVnf);
90 map.put(OperationProperties.AAI_VNF_MODEL, Step2::loadVnfModel);
91 map.put(OperationProperties.AAI_VSERVER_LINK, Step2::loadVserverLink);
92 map.put(OperationProperties.DATA_VF_COUNT, Step2::loadVfCount);
93 map.put(OperationProperties.EVENT_ADDITIONAL_PARAMS, Step2::loadAdditionalEventParams);
94 map.put(OperationProperties.EVENT_PAYLOAD, Step2::loadEventPayload);
95 map.put(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES, Step2::loadOptCdsGrpcAaiProperties);
97 map.put(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, Step2::loadDefaultGenericVnf);
99 PROPERTY_LOADER = Collections.unmodifiableMap(map);
103 * Populate map for PROPERTY_SAVER.
105 Map<String, Consumer<Step2>> map2 = new HashMap<>();
107 map2.put(OperationProperties.DATA_VF_COUNT, Step2::storeVfCount);
109 PROPERTY_SAVER = Collections.unmodifiableMap(map2);
113 protected final StepContext stepContext;
114 protected final VirtualControlLoopEvent event;
117 * {@code True} if the associated preprocessing steps have been loaded, {@code false}
122 private boolean preprocessed;
125 * Actions to take to store the Operation's properties back into the context.
127 private List<Consumer<Step2>> postProcessors = new LinkedList<>();
131 * Constructs the object. This is used when constructing the step for the policy's
134 * @param stepContext the step's context
135 * @param params operation parameters
136 * @param event the event being processed
138 public Step2(StepContext stepContext, ControlLoopOperationParams params, VirtualControlLoopEvent event) {
139 super(params, new AtomicReference<>());
140 this.stepContext = stepContext;
145 * Constructs the object using information from another step. This is used when
146 * constructing a preprocessing step.
148 * @param otherStep step whose information should be used
149 * @param actor actor name
150 * @param operation operation name
152 public Step2(Step2 otherStep, String actor, String operation) {
153 super(otherStep, actor, operation);
154 this.stepContext = otherStep.stepContext;
155 this.event = otherStep.event;
159 * Determines if starting this step indicates acceptance of the event. The default
160 * method simply invokes {@link #isPolicyStep()}.
162 * @return {@code true} if this step accepts the event, {@code false} if it is still
165 public boolean acceptsEvent() {
166 return isPolicyStep();
170 * Indicates that the step succeeded with the given outcome. Invoked by the rules. The
171 * default method invokes the post processors.
173 * @param outcome operation's outcome
175 public void success(OperationOutcome outcome) {
176 for (Consumer<Step2> proc : postProcessors) {
182 * Gets the names of the properties required by the operation. The default method just
183 * delegates to the operation to identify the properties.
185 * @return the names of the properties required by the operation
187 public List<String> getPropertyNames() {
188 return getOperation().getPropertyNames();
192 * Sets the operation's properties. This is invoked <i>after</i> any preprocessor
193 * steps have been performed. It also adds items to {@link #postProcessors}.
195 public void setProperties() {
196 postProcessors.clear();
198 for (String propName : getPropertyNames()) {
199 // identify the saver, if any
200 Consumer<Step2> saver = PROPERTY_SAVER.get(propName);
202 postProcessors.add(saver);
207 if (propName.startsWith(ENRICHMENT_PREFIX)) {
208 loadEnrichment(propName);
212 BiConsumer<Step2, String> loader = PROPERTY_LOADER.get(propName);
213 if (loader == null) {
214 throw new IllegalArgumentException("unknown property " + propName + " needed by " + getActorName() + "."
215 + getOperationName());
218 loader.accept(this, propName);
222 protected void loadCloudRegion(String propName) {
223 getOperation().setProperty(propName, getCloudRegion());
226 protected void loadTenant(String propName) {
227 getOperation().setProperty(propName, getTenant());
230 protected void loadPnf(String propName) {
231 getOperation().setProperty(propName, getPnf());
234 protected void loadResourceVnf(String propName) {
235 getOperation().setProperty(propName, getResourceVnf());
238 protected void loadService(String propName) {
239 getOperation().setProperty(propName, getService());
242 protected void loadServiceModel(String propName) {
243 getOperation().setProperty(propName, getServiceModel());
246 protected void loadTargetEntity(String propName) {
247 getOperation().setProperty(propName, getTargetEntity());
250 protected void loadVnf(String propName) {
251 getOperation().setProperty(propName, getVnf());
254 protected void loadVnfModel(String propName) {
255 getOperation().setProperty(propName, getVnfModel());
258 protected void loadVserverLink(String propName) {
259 getOperation().setProperty(propName, getVserverLink());
262 protected void loadVfCount(String propName) {
263 getOperation().setProperty(propName, getVfCount());
266 protected void loadEnrichment(String propName) {
267 getOperation().setProperty(propName, getEnrichment(propName));
270 protected void loadAdditionalEventParams(String propName) {
271 getOperation().setProperty(propName, getAdditionalEventParams());
274 protected void loadEventPayload(String propName) {
275 getOperation().setProperty(propName, getEventPayload());
278 protected void loadOptCdsGrpcAaiProperties(String propName) {
282 protected void loadDefaultGenericVnf(String propName) {
283 getOperation().setProperty(propName, getDefaultGenericVnf());
286 protected CloudRegion getCloudRegion() {
287 AaiCqResponse aaicq = getCustomQueryData();
288 return aaicq.getDefaultCloudRegion();
291 protected Tenant getTenant() {
292 AaiCqResponse aaicq = getCustomQueryData();
293 return aaicq.getDefaultTenant();
296 protected StandardCoderObject getPnf() {
297 return stepContext.getProperty(AaiGetPnfOperation.getKey(getTargetEntity()));
300 protected GenericVnf getResourceVnf() {
301 verifyNotNull(TARGET_INFO_MSG, params.getTargetEntityIds());
303 String resourceId = params.getTargetEntityIds().get(TARGET_RESOURCE_ID);
305 verifyNotNull("Target resource ID", resourceId);
307 AaiCqResponse aaicq = getCustomQueryData();
308 return aaicq.getGenericVnfByModelInvariantId(resourceId);
311 protected ServiceInstance getService() {
312 AaiCqResponse aaicq = getCustomQueryData();
313 return aaicq.getServiceInstance();
316 protected ModelVer getServiceModel() {
317 AaiCqResponse aaicq = getCustomQueryData();
318 ServiceInstance service = aaicq.getServiceInstance();
319 return aaicq.getModelVerByVersionId(service.getModelVersionId());
322 protected Vserver getVServer() {
323 AaiCqResponse aaicq = getCustomQueryData();
324 return aaicq.getVserver();
328 * The default method assumes there is only one target entity and that it's stored
329 * within the step's context.
331 protected String getTargetEntity() {
332 return stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY);
335 protected GenericVnf getVnf() {
336 verifyNotNull(TARGET_INFO_MSG, params.getTargetEntityIds());
338 String modelInvariantId = params.getTargetEntityIds().get(TARGET_MODEL_INVARIANT_ID);
340 verifyNotNull(TARGET_MODEL_INVARIANT_ID, modelInvariantId);
342 AaiCqResponse aaicq = getCustomQueryData();
343 return aaicq.getGenericVnfByVfModuleModelInvariantId(modelInvariantId);
346 protected ModelVer getVnfModel() {
347 GenericVnf vnf = getVnf();
348 AaiCqResponse aaicq = getCustomQueryData();
349 return aaicq.getModelVerByVersionId(vnf.getModelVersionId());
352 protected String getVserverLink() {
353 String vserver = event.getAai().get(VSERVER_VSERVER_NAME);
354 if (StringUtils.isBlank(vserver)) {
355 throw new IllegalArgumentException("missing " + VSERVER_VSERVER_NAME + " in enrichment data");
358 StandardCoderObject tenant = stepContext.getProperty(AaiGetTenantOperation.getKey(vserver));
359 verifyNotNull("tenant data", tenant);
361 String resourceLink = tenant.getString(RESULT_DATA, 0, RESOURCE_LINK);
362 verifyNotNull("tenant data resource-link", resourceLink);
364 return stripPrefix(resourceLink, 3);
367 protected Integer getVfCount() {
368 if (stepContext.contains(OperationProperties.DATA_VF_COUNT)) {
369 return stepContext.getProperty(OperationProperties.DATA_VF_COUNT);
372 verifyNotNull(TARGET_INFO_MSG, params.getTargetEntityIds());
374 String modelCustomizationId = params.getTargetEntityIds().get(TARGET_MODEL_CUSTOMIZATION_ID);
375 String modelInvariantId = params.getTargetEntityIds().get(TARGET_MODEL_INVARIANT_ID);
376 String modelVersionId = params.getTargetEntityIds().get(TARGET_MODEL_VERSION_ID);
378 verifyNotNull("target modelCustomizationId", modelCustomizationId);
379 verifyNotNull("target modelInvariantId", modelInvariantId);
380 verifyNotNull("target modelVersionId", modelVersionId);
382 AaiCqResponse aaicq = getCustomQueryData();
383 return aaicq.getVfModuleCount(modelCustomizationId, modelInvariantId, modelVersionId);
386 protected String getEnrichment(String propName) {
387 String enrichmentKey = propName.substring(ENRICHMENT_PREFIX.length());
388 String value = event.getAai().get(enrichmentKey);
389 verifyNotNull(propName, value);
394 protected Map<String, String> getAdditionalEventParams() {
395 return event.getAdditionalEventParams();
398 protected String getEventPayload() {
399 return event.getPayload();
402 protected GenericVnf getDefaultGenericVnf() {
403 AaiCqResponse aaicq = getCustomQueryData();
404 return aaicq.getDefaultGenericVnf();
407 protected AaiCqResponse getCustomQueryData() {
408 AaiCqResponse aaicq = stepContext.getProperty(AaiCqResponse.CONTEXT_KEY);
409 verifyNotNull("custom query data", aaicq);
414 protected void storeVfCount() {
415 if (!getOperation().containsProperty(OperationProperties.DATA_VF_COUNT)) {
419 int vfcount = getOperation().getProperty(OperationProperties.DATA_VF_COUNT);
420 stepContext.setProperty(OperationProperties.DATA_VF_COUNT, vfcount);
423 protected void verifyNotNull(String propName, Object value) {
425 throw new IllegalArgumentException(
426 "missing " + propName + " for " + getActorName() + "." + getOperationName());
430 protected static String stripPrefix(String resourceLink, int ncomponents) {
432 for (int nslashes = 0; nslashes < ncomponents; ++nslashes) {
433 int idx = resourceLink.indexOf('/', previdx + 1);
441 return resourceLink.substring(Math.max(0, previdx));