9275f791d318e5302418890040a5119574c4f863
[policy/drools-applications.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.policy.drools.apps.controller.usecases.step;
22
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.LinkedList;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.concurrent.atomic.AtomicReference;
29 import java.util.function.BiConsumer;
30 import java.util.function.Consumer;
31 import lombok.Getter;
32 import lombok.Setter;
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;
50
51 /**
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
59  * steps.
60  */
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";
67
68     private static final Map<String, BiConsumer<Step2, String>> PROPERTY_LOADER;
69     private static final Map<String, Consumer<Step2>> PROPERTY_SAVER;
70
71     static {
72         /*
73          * Populate map for PROPERTY_LOADER.
74          */
75         Map<String, BiConsumer<Step2, String>> map = new HashMap<>();
76
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);
91
92         map.put(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, Step2::loadDefaultGenericVnf);
93
94         PROPERTY_LOADER = Collections.unmodifiableMap(map);
95
96
97         /*
98          * Populate map for PROPERTY_SAVER.
99          */
100         Map<String, Consumer<Step2>> map2 = new HashMap<>();
101
102         map2.put(OperationProperties.DATA_VF_COUNT, Step2::storeVfCount);
103
104         PROPERTY_SAVER = Collections.unmodifiableMap(map2);
105     }
106
107
108     protected final StepContext stepContext;
109     protected final VirtualControlLoopEvent event;
110
111     /**
112      * {@code True} if the associated preprocessing steps have been loaded, {@code false}
113      * otherwise.
114      */
115     @Getter
116     @Setter
117     private boolean preprocessed;
118
119     /**
120      * Actions to take to store the Operation's properties back into the context.
121      */
122     private List<Consumer<Step2>> postProcessors = new LinkedList<>();
123
124
125     /**
126      * Constructs the object. This is used when constructing the step for the policy's
127      * actual operation.
128      *
129      * @param stepContext the step's context
130      * @param params operation parameters
131      * @param event the event being processed
132      */
133     public Step2(StepContext stepContext, ControlLoopOperationParams params, VirtualControlLoopEvent event) {
134         super(params, new AtomicReference<>());
135         this.stepContext = stepContext;
136         this.event = event;
137     }
138
139     /**
140      * Constructs the object using information from another step. This is used when
141      * constructing a preprocessing step.
142      *
143      * @param otherStep step whose information should be used
144      * @param actor actor name
145      * @param operation operation name
146      */
147     public Step2(Step2 otherStep, String actor, String operation) {
148         super(otherStep, actor, operation);
149         this.stepContext = otherStep.stepContext;
150         this.event = otherStep.event;
151     }
152
153     /**
154      * Determines if starting this step indicates acceptance of the event. The default
155      * method simply invokes {@link #isPolicyStep()}.
156      *
157      * @return {@code true} if this step accepts the event, {@code false} if it is still
158      *         indeterminate
159      */
160     public boolean acceptsEvent() {
161         return isPolicyStep();
162     }
163
164     /**
165      * Indicates that the step succeeded with the given outcome. Invoked by the rules. The
166      * default method invokes the post processors.
167      *
168      * @param outcome operation's outcome
169      */
170     public void success(OperationOutcome outcome) {
171         for (Consumer<Step2> proc : postProcessors) {
172             proc.accept(this);
173         }
174     }
175
176     /**
177      * Gets the names of the properties required by the operation. The default method just
178      * delegates to the operation to identify the properties.
179      *
180      * @return the names of the properties required by the operation
181      */
182     public List<String> getPropertyNames() {
183         return getOperation().getPropertyNames();
184     }
185
186     /**
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}.
189      */
190     public void setProperties() {
191         postProcessors.clear();
192
193         for (String propName : getPropertyNames()) {
194             // identify the saver, if any
195             Consumer<Step2> saver = PROPERTY_SAVER.get(propName);
196             if (saver != null) {
197                 postProcessors.add(saver);
198             }
199
200
201             // load data
202             if (propName.startsWith(ENRICHMENT_PREFIX)) {
203                 loadEnrichment(propName);
204                 continue;
205             }
206
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());
211             }
212
213             loader.accept(this, propName);
214         }
215     }
216
217     protected void loadCloudRegion(String propName) {
218         getOperation().setProperty(propName, getCloudRegion());
219     }
220
221     protected void loadTenant(String propName) {
222         getOperation().setProperty(propName, getTenant());
223     }
224
225     protected void loadPnf(String propName) {
226         getOperation().setProperty(propName, getPnf());
227     }
228
229     protected void loadResourceVnf(String propName) {
230         getOperation().setProperty(propName, getResourceVnf());
231     }
232
233     protected void loadService(String propName) {
234         getOperation().setProperty(propName, getService());
235     }
236
237     protected void loadServiceModel(String propName) {
238         getOperation().setProperty(propName, getServiceModel());
239     }
240
241     protected void loadTargetEntity(String propName) {
242         getOperation().setProperty(propName, getTargetEntity());
243     }
244
245     protected void loadVnf(String propName) {
246         getOperation().setProperty(propName, getVnf());
247     }
248
249     protected void loadVnfModel(String propName) {
250         getOperation().setProperty(propName, getVnfModel());
251     }
252
253     protected void loadVserverLink(String propName) {
254         getOperation().setProperty(propName, getVserverLink());
255     }
256
257     protected void loadVfCount(String propName) {
258         getOperation().setProperty(propName, getVfCount());
259     }
260
261     protected void loadEnrichment(String propName) {
262         getOperation().setProperty(propName, getEnrichment(propName));
263     }
264
265     protected void loadAdditionalEventParams(String propName) {
266         getOperation().setProperty(propName, getAdditionalEventParams());
267     }
268
269     protected void loadEventPayload(String propName) {
270         getOperation().setProperty(propName, getEventPayload());
271     }
272
273     protected void loadOptCdsGrpcAaiProperties(String propName) {
274         // do nothing
275     }
276
277     protected void loadDefaultGenericVnf(String propName) {
278         getOperation().setProperty(propName, getDefaultGenericVnf());
279     }
280
281     protected CloudRegion getCloudRegion() {
282         AaiCqResponse aaicq = getCustomQueryData();
283         return aaicq.getDefaultCloudRegion();
284     }
285
286     protected Tenant getTenant() {
287         AaiCqResponse aaicq = getCustomQueryData();
288         return aaicq.getDefaultTenant();
289     }
290
291     protected StandardCoderObject getPnf() {
292         return stepContext.getProperty(AaiGetPnfOperation.getKey(getTargetEntity()));
293     }
294
295     protected GenericVnf getResourceVnf() {
296         verifyNotNull(TARGET_INFO_MSG, params.getTarget());
297
298         String resourceId = params.getTarget().getResourceID();
299
300         verifyNotNull("Target resource ID", resourceId);
301
302         AaiCqResponse aaicq = getCustomQueryData();
303         return aaicq.getGenericVnfByModelInvariantId(resourceId);
304     }
305
306     protected ServiceInstance getService() {
307         AaiCqResponse aaicq = getCustomQueryData();
308         return aaicq.getServiceInstance();
309     }
310
311     protected ModelVer getServiceModel() {
312         AaiCqResponse aaicq = getCustomQueryData();
313         ServiceInstance service = aaicq.getServiceInstance();
314         return aaicq.getModelVerByVersionId(service.getModelVersionId());
315     }
316
317     /**
318      * The default method assumes there is only one target entity and that it's stored
319      * within the step's context.
320      */
321     protected String getTargetEntity() {
322         return stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY);
323     }
324
325     protected GenericVnf getVnf() {
326         verifyNotNull(TARGET_INFO_MSG, params.getTarget());
327
328         String modelInvariantId = params.getTarget().getModelInvariantId();
329
330         verifyNotNull("modelInvariantId", modelInvariantId);
331
332         AaiCqResponse aaicq = getCustomQueryData();
333         return aaicq.getGenericVnfByVfModuleModelInvariantId(modelInvariantId);
334     }
335
336     protected ModelVer getVnfModel() {
337         GenericVnf vnf = getVnf();
338         AaiCqResponse aaicq = getCustomQueryData();
339         return aaicq.getModelVerByVersionId(vnf.getModelVersionId());
340     }
341
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");
346         }
347
348         StandardCoderObject tenant = stepContext.getProperty(AaiGetTenantOperation.getKey(vserver));
349         verifyNotNull("tenant data", tenant);
350
351         String resourceLink = tenant.getString(RESULT_DATA, 0, RESOURCE_LINK);
352         verifyNotNull("tenant data resource-link", resourceLink);
353
354         return stripPrefix(resourceLink, 3);
355     }
356
357     protected Integer getVfCount() {
358         if (stepContext.contains(OperationProperties.DATA_VF_COUNT)) {
359             return stepContext.getProperty(OperationProperties.DATA_VF_COUNT);
360         }
361
362         verifyNotNull(TARGET_INFO_MSG, params.getTarget());
363
364         String modelCustomizationId = params.getTarget().getModelCustomizationId();
365         String modelInvariantId = params.getTarget().getModelInvariantId();
366         String modelVersionId = params.getTarget().getModelVersionId();
367
368         verifyNotNull("target modelCustomizationId", modelCustomizationId);
369         verifyNotNull("target modelInvariantId", modelInvariantId);
370         verifyNotNull("target modelVersionId", modelVersionId);
371
372         AaiCqResponse aaicq = getCustomQueryData();
373         return aaicq.getVfModuleCount(modelCustomizationId, modelInvariantId, modelVersionId);
374     }
375
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);
380
381         return value;
382     }
383
384     protected Map<String, String> getAdditionalEventParams() {
385         return event.getAdditionalEventParams();
386     }
387
388     protected String getEventPayload() {
389         return event.getPayload();
390     }
391
392     protected GenericVnf getDefaultGenericVnf() {
393         AaiCqResponse aaicq = getCustomQueryData();
394         return aaicq.getDefaultGenericVnf();
395     }
396
397     protected AaiCqResponse getCustomQueryData() {
398         AaiCqResponse aaicq = stepContext.getProperty(AaiCqResponse.CONTEXT_KEY);
399         verifyNotNull("custom query data", aaicq);
400
401         return aaicq;
402     }
403
404     protected void storeVfCount() {
405         if (!getOperation().containsProperty(OperationProperties.DATA_VF_COUNT)) {
406             return;
407         }
408
409         int vfcount = getOperation().getProperty(OperationProperties.DATA_VF_COUNT);
410         stepContext.setProperty(OperationProperties.DATA_VF_COUNT, vfcount);
411     }
412
413     protected void verifyNotNull(String propName, Object value) {
414         if (value == null) {
415             throw new IllegalArgumentException(
416                             "missing " + propName + " for " + getActorName() + "." + getOperationName());
417         }
418     }
419
420     protected static String stripPrefix(String resourceLink, int ncomponents) {
421         int previdx = -1;
422         for (int nslashes = 0; nslashes < ncomponents; ++nslashes) {
423             int idx = resourceLink.indexOf('/', previdx + 1);
424             if (idx < 0) {
425                 break;
426             }
427
428             previdx = idx;
429         }
430
431         return resourceLink.substring(Math.max(0, previdx));
432     }
433 }