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_INFO_MSG = "Target information";
63 public static final String ENRICHMENT_PREFIX = "enrichment/";
64 public static final String VSERVER_VSERVER_NAME = "vserver.vserver-name";
65 public static final String RESOURCE_LINK = "resource-link";
66 public static final String RESULT_DATA = "result-data";
68 private static final Map<String, BiConsumer<Step2, String>> PROPERTY_LOADER;
69 private static final Map<String, Consumer<Step2>> PROPERTY_SAVER;
73 * Populate map for PROPERTY_LOADER.
75 Map<String, BiConsumer<Step2, String>> map = new HashMap<>();
77 map.put(OperationProperties.AAI_DEFAULT_CLOUD_REGION, Step2::loadCloudRegion);
78 map.put(OperationProperties.AAI_DEFAULT_TENANT, Step2::loadTenant);
79 map.put(OperationProperties.AAI_PNF, Step2::loadPnf);
80 map.put(OperationProperties.AAI_RESOURCE_VNF, Step2::loadResourceVnf);
81 map.put(OperationProperties.AAI_SERVICE, Step2::loadService);
82 map.put(OperationProperties.AAI_SERVICE_MODEL, Step2::loadServiceModel);
83 map.put(OperationProperties.AAI_TARGET_ENTITY, Step2::loadTargetEntity);
84 map.put(OperationProperties.AAI_VNF, Step2::loadVnf);
85 map.put(OperationProperties.AAI_VNF_MODEL, Step2::loadVnfModel);
86 map.put(OperationProperties.AAI_VSERVER_LINK, Step2::loadVserverLink);
87 map.put(OperationProperties.DATA_VF_COUNT, Step2::loadVfCount);
88 map.put(OperationProperties.EVENT_ADDITIONAL_PARAMS, Step2::loadAdditionalEventParams);
89 map.put(OperationProperties.EVENT_PAYLOAD, Step2::loadEventPayload);
90 map.put(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES, Step2::loadOptCdsGrpcAaiProperties);
92 map.put(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, Step2::loadDefaultGenericVnf);
94 PROPERTY_LOADER = Collections.unmodifiableMap(map);
98 * Populate map for PROPERTY_SAVER.
100 Map<String, Consumer<Step2>> map2 = new HashMap<>();
102 map2.put(OperationProperties.DATA_VF_COUNT, Step2::storeVfCount);
104 PROPERTY_SAVER = Collections.unmodifiableMap(map2);
108 protected final StepContext stepContext;
109 protected final VirtualControlLoopEvent event;
112 * {@code True} if the associated preprocessing steps have been loaded, {@code false}
117 private boolean preprocessed;
120 * Actions to take to store the Operation's properties back into the context.
122 private List<Consumer<Step2>> postProcessors = new LinkedList<>();
126 * Constructs the object. This is used when constructing the step for the policy's
129 * @param stepContext the step's context
130 * @param params operation parameters
131 * @param event the event being processed
133 public Step2(StepContext stepContext, ControlLoopOperationParams params, VirtualControlLoopEvent event) {
134 super(params, new AtomicReference<>());
135 this.stepContext = stepContext;
140 * Constructs the object using information from another step. This is used when
141 * constructing a preprocessing step.
143 * @param otherStep step whose information should be used
144 * @param actor actor name
145 * @param operation operation name
147 public Step2(Step2 otherStep, String actor, String operation) {
148 super(otherStep, actor, operation);
149 this.stepContext = otherStep.stepContext;
150 this.event = otherStep.event;
154 * Determines if starting this step indicates acceptance of the event. The default
155 * method simply invokes {@link #isPolicyStep()}.
157 * @return {@code true} if this step accepts the event, {@code false} if it is still
160 public boolean acceptsEvent() {
161 return isPolicyStep();
165 * Indicates that the step succeeded with the given outcome. Invoked by the rules. The
166 * default method invokes the post processors.
168 * @param outcome operation's outcome
170 public void success(OperationOutcome outcome) {
171 for (Consumer<Step2> proc : postProcessors) {
177 * Gets the names of the properties required by the operation. The default method just
178 * delegates to the operation to identify the properties.
180 * @return the names of the properties required by the operation
182 public List<String> getPropertyNames() {
183 return getOperation().getPropertyNames();
187 * Sets the operation's properties. This is invoked <i>after</i> any preprocessor
188 * steps have been performed. It also adds items to {@link #postProcessors}.
190 public void setProperties() {
191 postProcessors.clear();
193 for (String propName : getPropertyNames()) {
194 // identify the saver, if any
195 Consumer<Step2> saver = PROPERTY_SAVER.get(propName);
197 postProcessors.add(saver);
202 if (propName.startsWith(ENRICHMENT_PREFIX)) {
203 loadEnrichment(propName);
207 BiConsumer<Step2, String> loader = PROPERTY_LOADER.get(propName);
208 if (loader == null) {
209 throw new IllegalArgumentException("unknown property " + propName + " needed by " + getActorName() + "."
210 + getOperationName());
213 loader.accept(this, propName);
217 protected void loadCloudRegion(String propName) {
218 getOperation().setProperty(propName, getCloudRegion());
221 protected void loadTenant(String propName) {
222 getOperation().setProperty(propName, getTenant());
225 protected void loadPnf(String propName) {
226 getOperation().setProperty(propName, getPnf());
229 protected void loadResourceVnf(String propName) {
230 getOperation().setProperty(propName, getResourceVnf());
233 protected void loadService(String propName) {
234 getOperation().setProperty(propName, getService());
237 protected void loadServiceModel(String propName) {
238 getOperation().setProperty(propName, getServiceModel());
241 protected void loadTargetEntity(String propName) {
242 getOperation().setProperty(propName, getTargetEntity());
245 protected void loadVnf(String propName) {
246 getOperation().setProperty(propName, getVnf());
249 protected void loadVnfModel(String propName) {
250 getOperation().setProperty(propName, getVnfModel());
253 protected void loadVserverLink(String propName) {
254 getOperation().setProperty(propName, getVserverLink());
257 protected void loadVfCount(String propName) {
258 getOperation().setProperty(propName, getVfCount());
261 protected void loadEnrichment(String propName) {
262 getOperation().setProperty(propName, getEnrichment(propName));
265 protected void loadAdditionalEventParams(String propName) {
266 getOperation().setProperty(propName, getAdditionalEventParams());
269 protected void loadEventPayload(String propName) {
270 getOperation().setProperty(propName, getEventPayload());
273 protected void loadOptCdsGrpcAaiProperties(String propName) {
277 protected void loadDefaultGenericVnf(String propName) {
278 getOperation().setProperty(propName, getDefaultGenericVnf());
281 protected CloudRegion getCloudRegion() {
282 AaiCqResponse aaicq = getCustomQueryData();
283 return aaicq.getDefaultCloudRegion();
286 protected Tenant getTenant() {
287 AaiCqResponse aaicq = getCustomQueryData();
288 return aaicq.getDefaultTenant();
291 protected StandardCoderObject getPnf() {
292 return stepContext.getProperty(AaiGetPnfOperation.getKey(getTargetEntity()));
295 protected GenericVnf getResourceVnf() {
296 verifyNotNull(TARGET_INFO_MSG, params.getTarget());
298 String resourceId = params.getTarget().getResourceID();
300 verifyNotNull("Target resource ID", resourceId);
302 AaiCqResponse aaicq = getCustomQueryData();
303 return aaicq.getGenericVnfByModelInvariantId(resourceId);
306 protected ServiceInstance getService() {
307 AaiCqResponse aaicq = getCustomQueryData();
308 return aaicq.getServiceInstance();
311 protected ModelVer getServiceModel() {
312 AaiCqResponse aaicq = getCustomQueryData();
313 ServiceInstance service = aaicq.getServiceInstance();
314 return aaicq.getModelVerByVersionId(service.getModelVersionId());
318 * The default method assumes there is only one target entity and that it's stored
319 * within the step's context.
321 protected String getTargetEntity() {
322 return stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY);
325 protected GenericVnf getVnf() {
326 verifyNotNull(TARGET_INFO_MSG, params.getTarget());
328 String modelInvariantId = params.getTarget().getModelInvariantId();
330 verifyNotNull("modelInvariantId", modelInvariantId);
332 AaiCqResponse aaicq = getCustomQueryData();
333 return aaicq.getGenericVnfByVfModuleModelInvariantId(modelInvariantId);
336 protected ModelVer getVnfModel() {
337 GenericVnf vnf = getVnf();
338 AaiCqResponse aaicq = getCustomQueryData();
339 return aaicq.getModelVerByVersionId(vnf.getModelVersionId());
342 protected String getVserverLink() {
343 String vserver = event.getAai().get(VSERVER_VSERVER_NAME);
344 if (StringUtils.isBlank(vserver)) {
345 throw new IllegalArgumentException("missing " + VSERVER_VSERVER_NAME + " in enrichment data");
348 StandardCoderObject tenant = stepContext.getProperty(AaiGetTenantOperation.getKey(vserver));
349 verifyNotNull("tenant data", tenant);
351 String resourceLink = tenant.getString(RESULT_DATA, 0, RESOURCE_LINK);
352 verifyNotNull("tenant data resource-link", resourceLink);
354 return stripPrefix(resourceLink, 3);
357 protected Integer getVfCount() {
358 if (stepContext.contains(OperationProperties.DATA_VF_COUNT)) {
359 return stepContext.getProperty(OperationProperties.DATA_VF_COUNT);
362 verifyNotNull(TARGET_INFO_MSG, params.getTarget());
364 String modelCustomizationId = params.getTarget().getModelCustomizationId();
365 String modelInvariantId = params.getTarget().getModelInvariantId();
366 String modelVersionId = params.getTarget().getModelVersionId();
368 verifyNotNull("target modelCustomizationId", modelCustomizationId);
369 verifyNotNull("target modelInvariantId", modelInvariantId);
370 verifyNotNull("target modelVersionId", modelVersionId);
372 AaiCqResponse aaicq = getCustomQueryData();
373 return aaicq.getVfModuleCount(modelCustomizationId, modelInvariantId, modelVersionId);
376 protected String getEnrichment(String propName) {
377 String enrichmentKey = propName.substring(ENRICHMENT_PREFIX.length());
378 String value = event.getAai().get(enrichmentKey);
379 verifyNotNull(propName, value);
384 protected Map<String, String> getAdditionalEventParams() {
385 return event.getAdditionalEventParams();
388 protected String getEventPayload() {
389 return event.getPayload();
392 protected GenericVnf getDefaultGenericVnf() {
393 AaiCqResponse aaicq = getCustomQueryData();
394 return aaicq.getDefaultGenericVnf();
397 protected AaiCqResponse getCustomQueryData() {
398 AaiCqResponse aaicq = stepContext.getProperty(AaiCqResponse.CONTEXT_KEY);
399 verifyNotNull("custom query data", aaicq);
404 protected void storeVfCount() {
405 if (!getOperation().containsProperty(OperationProperties.DATA_VF_COUNT)) {
409 int vfcount = getOperation().getProperty(OperationProperties.DATA_VF_COUNT);
410 stepContext.setProperty(OperationProperties.DATA_VF_COUNT, vfcount);
413 protected void verifyNotNull(String propName, Object value) {
415 throw new IllegalArgumentException(
416 "missing " + propName + " for " + getActorName() + "." + getOperationName());
420 protected static String stripPrefix(String resourceLink, int ncomponents) {
422 for (int nslashes = 0; nslashes < ncomponents; ++nslashes) {
423 int idx = resourceLink.indexOf('/', previdx + 1);
431 return resourceLink.substring(Math.max(0, previdx));