Enable long-running processes in ControllerExecutionBB
[so.git] / bpmn / so-bpmn-tasks / src / main / java / org / onap / so / bpmn / infrastructure / decisionpoint / impl / buildingblock / ControllerExecutionBB.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019 Nordix
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19
20 package org.onap.so.bpmn.infrastructure.decisionpoint.impl.buildingblock;
21
22 import com.google.common.base.Strings;
23 import java.util.Optional;
24 import org.onap.logging.filter.base.ONAPComponents;
25 import org.onap.so.bpmn.common.BuildingBlockExecution;
26 import org.onap.so.bpmn.infrastructure.decisionpoint.api.ControllerContext;
27 import org.onap.so.bpmn.infrastructure.decisionpoint.api.ControllerRunnable;
28 import org.onap.so.bpmn.infrastructure.decisionpoint.impl.AbstractControllerExecution;
29 import org.onap.so.client.cds.PayloadConstants;
30 import org.onap.so.db.catalog.beans.ControllerSelectionReference;
31 import org.onap.so.db.catalog.beans.PnfResourceCustomization;
32 import org.onap.so.db.catalog.beans.VnfResourceCustomization;
33 import org.onap.so.db.catalog.client.CatalogDbClient;
34 import org.springframework.beans.factory.annotation.Autowired;
35 import org.springframework.beans.factory.annotation.Value;
36 import org.springframework.stereotype.Component;
37
38 /**
39  * This class is used for {@ref BuildingBlockExecution} API based execution.
40  *
41  * it decides which controller implementation to use based on the parameters, like actor, scope, action.
42  *
43  * The following parameters are expected in the {@ref BuildingBlockExecution} context,
44  * <ul>
45  * <li>action: action to be executed</li>
46  * <li>scope: type of the resource, i.e, pnf, vnf, vf</li>
47  * <li>resource_customization_uuid: resource customization UUID</li>
48  * <li>resource_type: resource type, optional. It's used to find the controller from controller_selection_reference
49  * table. Same as VNF_TYPE in the table</li>
50  * </ul>
51  */
52 @Component
53 public class ControllerExecutionBB extends AbstractControllerExecution<BuildingBlockExecution> {
54
55     @Autowired
56     protected CatalogDbClient catalogDbClient;
57     @Value("${controller-execution.timeout-for-controller-message:P1D}")
58     private String timeoutForControllerMessage;
59
60     public void execute(final BuildingBlockExecution execution) {
61         execution.setVariable(PayloadConstants.TIMEOUT_CONTROLLER_MESSAGE, timeoutForControllerMessage);
62         ControllerContext<BuildingBlockExecution> controllerContext = buildControllerContext(execution);
63         controllerExecute(controllerContext);
64     }
65
66     @Override
67     protected String getParameterFromExecution(BuildingBlockExecution execution, String parameterName) {
68         Object object = execution.getVariable(parameterName);
69         if (object != null) {
70             String paramValue = String.valueOf(object);
71             logger.debug("parameterName: {}, parameterValue: {}", parameterName, paramValue);
72             return paramValue;
73         }
74         return "";
75     }
76
77     /**
78      * this method is used to get the controller actor, there could be few places to get the actor(ordered by priority),
79      *
80      * <ol>
81      * <li>Execution Context, i.e, BuildingBlockExecution</li>
82      * <li>Resource customization table, pnf_resource_customization for PNF or vnf_resource_customization for VNF</li>
83      * <li>controller_selection_reference, resource_type and action will be used to fetch from this table</li>
84      * </ol>
85      *
86      * @param execution BuildingBlockExecution instance
87      * @param controllerScope controller scope, e.g, pnf, vnf, vfModule
88      * @param resourceCustomizationUuid resource customization UUID, e.g, pnfCustomizationUuid, vnfCustomizationUuid
89      * @param controllerAction controller action, e.g, configAssign, configDeploy
90      * @return controller actor name
91      */
92     @Override
93     protected String getControllerActor(BuildingBlockExecution execution, String controllerScope,
94             String resourceCustomizationUuid, String controllerAction) {
95
96         /**
97          * Firstly, check the execution context for actor parameter.
98          */
99         String controllerActor = getParameterFromExecution(execution, CONTROLLER_ACTOR_PARAM);
100
101         /**
102          * If no meaningful controller actor value found in the execution context and the value is not SO-REF-DATA.
103          */
104         if (Strings.isNullOrEmpty(controllerActor) && !isSoRefControllerActor(controllerActor)) {
105
106             /**
107              * For BuildingBlockExecution, we should try to get the resource information from Cached metadata.
108              *
109              * As the current cached metadata doesn't support controller actor, we use the
110              * {@link org.onap.so.db.catalog.client.CatalogDbClient} to fetch information. Once the change is done in
111              * cached metadata, this part should be refactored as well.
112              */
113             if (isPnfResourceScope(controllerScope)) {
114                 PnfResourceCustomization pnfResourceCustomization =
115                         catalogDbClient.getPnfResourceCustomizationByModelCustomizationUUID(resourceCustomizationUuid);
116                 controllerActor = pnfResourceCustomization.getControllerActor();
117             } else if (isServiceResourceScope(controllerScope)) {
118                 return controllerActor;
119             } else if (isVnfResourceScope(controllerScope)) {
120                 VnfResourceCustomization vnfResourceCustomization =
121                         catalogDbClient.getVnfResourceCustomizationByModelCustomizationUUID(resourceCustomizationUuid);
122                 controllerActor = vnfResourceCustomization.getControllerActor();
123             } else {
124                 logger.warn("Unrecognized scope: {}", controllerScope);
125             }
126         }
127
128         /**
129          * Lastly, can NOT find the controller actor information from resource customization table or the return value
130          * is SO-REF-DATA.
131          */
132         if (Strings.isNullOrEmpty(controllerActor) || isSoRefControllerActor(controllerActor)) {
133             String resourceType = getParameterFromExecution(execution, RESOURCE_TYPE_PARAM);
134             ControllerSelectionReference reference = catalogDbClient
135                     .getControllerSelectionReferenceByVnfTypeAndActionCategory(resourceType, controllerAction);
136
137             controllerActor = reference.getControllerName();
138         }
139         return controllerActor;
140     }
141
142     @Override
143     public void controllerExecute(ControllerContext<BuildingBlockExecution> controllerContext) {
144         Optional<ControllerRunnable> optional = getController(controllerContext);
145         if (optional.isPresent()) {
146             ControllerRunnable controller = optional.get();
147             if (controller.ready(controllerContext)) {
148                 controller.prepare(controllerContext);
149                 controller.run(controllerContext);
150             } else {
151                 exceptionBuilder.buildAndThrowWorkflowException(controllerContext.getExecution(), 9001,
152                         "Controller is NOT Ready for the action", ONAPComponents.SO);
153             }
154         } else {
155             exceptionBuilder.buildAndThrowWorkflowException(controllerContext.getExecution(), 9000,
156                     "Unable to find the controller implementation", ONAPComponents.SO);
157         }
158     }
159
160     public void handleFailure(final BuildingBlockExecution execution) {
161         String errorMessage = execution.getVariable(PayloadConstants.CONTROLLER_ERROR_MESSAGE);
162
163         if (Boolean.TRUE.equals(execution.getVariable(PayloadConstants.CONTROLLER_MSG_TIMEOUT_REACHED))) {
164             logger.error(
165                     "timeout-for-controller-message was reached. If the controller is still processing, this property should be reconfigured");
166             errorMessage = "Controller response was not received within configured timeout";
167         } else if (errorMessage == null) {
168             errorMessage = "Controller call failed. No errormessage was captured.";
169         }
170
171         exceptionBuilder.buildAndThrowWorkflowException(execution, 9003, errorMessage, ONAPComponents.SO);
172     }
173 }