2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2024 Nordix Foundation.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.drools.apps.controller.usecases;
24 import static org.onap.policy.controlloop.ControlLoopTargetType.PNF;
25 import static org.onap.policy.controlloop.ControlLoopTargetType.VM;
26 import static org.onap.policy.controlloop.ControlLoopTargetType.VNF;
27 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.GENERIC_VNF_IS_CLOSED_LOOP_DISABLED;
28 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.GENERIC_VNF_PROV_STATUS;
29 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.GENERIC_VNF_VNF_ID;
30 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.GENERIC_VNF_VNF_NAME;
31 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.PNF_IS_IN_MAINT;
32 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.PNF_NAME;
33 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.PROV_STATUS_ACTIVE;
34 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VM_NAME;
35 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VNF_NAME;
36 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VSERVER_IS_CLOSED_LOOP_DISABLED;
37 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VSERVER_PROV_STATUS;
38 import static org.onap.policy.drools.apps.controller.usecases.UsecasesConstants.VSERVER_VSERVER_NAME;
40 import java.io.Serial;
41 import java.util.Deque;
44 import java.util.stream.Collectors;
45 import java.util.stream.Stream;
46 import org.drools.core.WorkingMemory;
47 import org.onap.policy.controlloop.ControlLoopException;
48 import org.onap.policy.controlloop.ControlLoopResponse;
49 import org.onap.policy.controlloop.VirtualControlLoopEvent;
50 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
51 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
52 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
53 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
54 import org.onap.policy.controlloop.eventmanager.ActorConstants;
55 import org.onap.policy.controlloop.eventmanager.ClEventManagerWithEvent;
56 import org.onap.policy.controlloop.eventmanager.EventManagerServices;
57 import org.onap.policy.controlloop.eventmanager.StepContext;
58 import org.onap.policy.drools.apps.controller.usecases.step.AaiCqStep2;
59 import org.onap.policy.drools.apps.controller.usecases.step.AaiGetPnfStep2;
60 import org.onap.policy.drools.apps.controller.usecases.step.AaiGetTenantStep2;
61 import org.onap.policy.drools.apps.controller.usecases.step.GetTargetEntityStep2;
62 import org.onap.policy.drools.apps.controller.usecases.step.GuardStep2;
63 import org.onap.policy.drools.apps.controller.usecases.step.LockStep2;
64 import org.onap.policy.drools.apps.controller.usecases.step.Step2;
65 import org.onap.policy.sdnr.PciMessage;
68 * Manager for a single control loop event. Once this has been created, the event can be
69 * retracted from working memory. Processing progresses through each policy, which
70 * involves at least one step. As a step is processed, additional preprocessor steps may
71 * be pushed onto the queue (e.g., locks, A&AI queries, guards).
73 public class UsecasesEventManager extends ClEventManagerWithEvent<Step2> implements StepContext {
76 private static final long serialVersionUID = -1216568161322872641L;
79 * If there's a failure from one of these actors, then the TOSCA processing should be
82 private static final Set<String> ABORT_ACTORS = Set.of(ActorConstants.CL_TIMEOUT_ACTOR, ActorConstants.LOCK_ACTOR);
84 private static final Set<String> VALID_TARGETS = Stream
85 .of(VM_NAME, VNF_NAME, VSERVER_VSERVER_NAME, GENERIC_VNF_VNF_ID, GENERIC_VNF_VNF_NAME, PNF_NAME)
86 .map(String::toLowerCase).collect(Collectors.toSet());
88 private static final Set<String> TRUE_VALUES = Set.of("true", "t", "yes", "y");
91 * Names of Operation properties for which A&AI PNF query is needed.
93 private static final Set<String> PNF_PROPERTIES = Set.of(OperationProperties.AAI_PNF);
96 * Names of Operation properties for which A&AI Tenant query is needed.
98 private static final Set<String> TENANT_PROPERTIES = Set.of(OperationProperties.AAI_VSERVER_LINK);
101 * Names of Operation properties for which A&AI custom query is needed.
103 private static final Set<String> CQ_PROPERTIES = Set.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION,
104 OperationProperties.AAI_VNF, OperationProperties.AAI_SERVICE_MODEL,
105 OperationProperties.AAI_VNF_MODEL, OperationProperties.AAI_SERVICE,
106 OperationProperties.AAI_RESOURCE_VNF, UsecasesConstants.AAI_DEFAULT_GENERIC_VNF);
110 * Constructs the object.
112 * @param services services the manager should use when processing the event
113 * @param params control loop parameters
114 * @param event event to be managed by this object
115 * @param workMem working memory to update if this changes
116 * @throws ControlLoopException if the event is invalid or if a YAML processor cannot
119 public UsecasesEventManager(EventManagerServices services, ControlLoopParams params, VirtualControlLoopEvent event,
120 WorkingMemory workMem) throws ControlLoopException {
122 super(services, params, event, workMem);
124 if (isClosedLoopDisabled(event)) {
125 throw new IllegalStateException("is-closed-loop-disabled is set to true on VServer or VNF");
128 if (isProvStatusInactive(event)) {
129 throw new IllegalStateException("prov-status is not ACTIVE on VServer or VNF");
134 * This is needed to satisfy drools, thus disabling sonar.
137 public Deque<Step2> getSteps() { // NOSONAR
138 return super.getSteps();
142 public void loadPreprocessorSteps() {
143 super.loadPreprocessorSteps();
145 final Deque<Step2> steps = getSteps();
146 final Step2 step = getSteps().peek();
148 // determine if any A&AI queries are needed
151 var needTenant = false;
152 var needTargetEntity = false;
154 for (String propName : step.getPropertyNames()) {
155 needCq = needCq || CQ_PROPERTIES.contains(propName);
156 needPnf = needPnf || PNF_PROPERTIES.contains(propName);
157 needTenant = needTenant || TENANT_PROPERTIES.contains(propName);
158 needTargetEntity = needTargetEntity || OperationProperties.AAI_TARGET_ENTITY.equals(propName);
162 * The Policy's actual operation requires additional, implicit steps, such as
163 * locking and guards.
165 final boolean needPolicySteps = step.isPolicyStep();
169 * NOTE: need to push steps onto the queue in the OPPOSITE order in which they
174 // GUARD must be pushed first
175 if (needPolicySteps) {
176 steps.push(new GuardStep2(step, getClosedLoopControlName()));
181 steps.push(new AaiCqStep2(step));
185 steps.push(new AaiGetPnfStep2(step));
189 steps.push(new AaiGetTenantStep2(step));
192 // LOCK must be pushed after the queries
193 if (needPolicySteps) {
194 steps.push(new LockStep2(step));
197 // GET-TARGET-ENTITY should be pushed last
198 if (needTargetEntity) {
199 steps.push(new GetTargetEntityStep2(step));
204 public boolean isAbort(OperationOutcome outcome) {
205 return (super.isAbort(outcome) && ABORT_ACTORS.contains(outcome.getActor()));
209 * Stores an operation outcome in the DB.
211 * @param outcome operation outcome to store
213 public void storeInDataBase(OperationOutcome2 outcome) {
214 storeInDataBase(outcome, getProperty(OperationProperties.AAI_TARGET_ENTITY));
218 public ControlLoopResponse makeControlLoopResponse(OperationOutcome outcome) {
219 var clRsp = super.makeControlLoopResponse(outcome);
221 Object obj = outcome.getResponse();
222 if (!(obj instanceof PciMessage)) {
226 PciMessage msg = (PciMessage) obj;
227 if (msg.getBody() != null && msg.getBody().getOutput() != null) {
228 clRsp.setPayload(msg.getBody().getOutput().getPayload());
235 protected void checkEventSyntax(VirtualControlLoopEvent event) throws ControlLoopException {
236 super.checkEventSyntax(event);
237 validateAaiData(event);
241 protected void validateTarget(VirtualControlLoopEvent event) throws ControlLoopException {
242 super.validateTarget(event);
244 if (!VALID_TARGETS.contains(event.getTarget().toLowerCase())) {
245 throw new ControlLoopException("target field invalid");
249 private void validateAaiData(VirtualControlLoopEvent event) throws ControlLoopException {
250 Map<String, String> eventAai = event.getAai();
251 if (eventAai == null) {
252 throw new ControlLoopException("AAI is null");
254 if (event.getTargetType() == null) {
255 throw new ControlLoopException("The Target type is null");
257 switch (event.getTargetType()) {
259 validateAaiVmVnfData(eventAai);
262 validateAaiPnfData(eventAai);
265 throw new ControlLoopException("The target type is not supported");
269 private void validateAaiVmVnfData(Map<String, String> eventAai) throws ControlLoopException {
270 if (eventAai.get(GENERIC_VNF_VNF_ID) == null && eventAai.get(VSERVER_VSERVER_NAME) == null
271 && eventAai.get(GENERIC_VNF_VNF_NAME) == null) {
272 throw new ControlLoopException(
273 "generic-vnf.vnf-id or generic-vnf.vnf-name or vserver.vserver-name information missing");
277 private void validateAaiPnfData(Map<String, String> eventAai) throws ControlLoopException {
278 if (eventAai.get(PNF_NAME) == null) {
279 throw new ControlLoopException("AAI PNF object key pnf-name is missing");
284 * Is closed loop disabled for an event.
286 * @param event the event
287 * @return <code>true</code> if the control loop is disabled, <code>false</code>
290 private static boolean isClosedLoopDisabled(VirtualControlLoopEvent event) {
291 Map<String, String> aai = event.getAai();
292 return (isAaiTrue(aai.get(VSERVER_IS_CLOSED_LOOP_DISABLED))
293 || isAaiTrue(aai.get(GENERIC_VNF_IS_CLOSED_LOOP_DISABLED))
294 || isAaiTrue(aai.get(PNF_IS_IN_MAINT)));
298 * Does provisioning status, for an event, have a value other than ACTIVE.
300 * @param event the event
301 * @return {@code true} if the provisioning status is neither ACTIVE nor {@code null},
302 * {@code false} otherwise
304 private static boolean isProvStatusInactive(VirtualControlLoopEvent event) {
305 Map<String, String> aai = event.getAai();
306 return !(PROV_STATUS_ACTIVE.equalsIgnoreCase(aai.getOrDefault(VSERVER_PROV_STATUS, PROV_STATUS_ACTIVE))
307 && PROV_STATUS_ACTIVE.equalsIgnoreCase(
308 aai.getOrDefault(GENERIC_VNF_PROV_STATUS, PROV_STATUS_ACTIVE)));
312 * Determines the boolean value represented by the given AAI field value.
314 * @param aaiValue value to be examined
315 * @return the boolean value represented by the field value, or {@code false} if the
316 * value is {@code null}
318 private static boolean isAaiTrue(String aaiValue) {
319 return (aaiValue != null && TRUE_VALUES.contains(aaiValue.toLowerCase()));
323 protected void loadPolicyStep(ControlLoopOperationParams params) {
324 getSteps().add(new Step2(this, params, getEvent()));