a1564b2f7dc79c1939cc81d002e59f9817357511
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2023 Nordix Foundation.
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  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.clamp.acm.participant.sim.main.handler;
22
23 import java.lang.invoke.MethodHandles;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.UUID;
28 import lombok.Getter;
29 import lombok.RequiredArgsConstructor;
30 import lombok.Setter;
31 import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener;
32 import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
33 import org.onap.policy.clamp.acm.participant.sim.model.InternalData;
34 import org.onap.policy.clamp.acm.participant.sim.model.InternalDatas;
35 import org.onap.policy.clamp.acm.participant.sim.model.SimConfig;
36 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
37 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
38 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
39 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
40 import org.onap.policy.clamp.models.acm.concepts.DeployState;
41 import org.onap.policy.clamp.models.acm.concepts.LockState;
42 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
43 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
44 import org.onap.policy.models.base.PfModelException;
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.stereotype.Component;
49
50 /**
51  * This class handles implementation of automationCompositionElement updates.
52  */
53 @Component
54 @RequiredArgsConstructor
55 public class AutomationCompositionElementHandler implements AutomationCompositionElementListener {
56
57     private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
58
59     private final ParticipantIntermediaryApi intermediaryApi;
60
61     @Getter
62     @Setter
63     private SimConfig config = new SimConfig();
64
65     /**
66      * Callback method to handle an update on a automation composition element.
67      *
68      * @param automationCompositionId the automationComposition Id
69      * @param element the information on the automation composition element
70      * @param properties properties Map
71      * @throws PfModelException in case of a exception
72      */
73     @Override
74     public void deploy(UUID automationCompositionId, AcElementDeploy element, Map<String, Object> properties)
75             throws PfModelException {
76         LOGGER.debug("deploy call");
77
78         if (!execution(config.getDeployTimerMs(), "Current Thread deploy is Interrupted during execution {}",
79                 element.getId())) {
80             return;
81         }
82
83         if (config.isDeploySuccess()) {
84             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
85                     DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed");
86         } else {
87             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
88                     DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!");
89         }
90     }
91
92     private boolean execution(int timeMs, String msg, UUID elementId) {
93         long endTime = System.currentTimeMillis() + timeMs;
94         while (System.currentTimeMillis() < endTime) {
95             try {
96                 if (Thread.currentThread().isInterrupted()) {
97                     LOGGER.debug(msg, elementId);
98                     return false;
99                 }
100                 Thread.sleep(10L);
101             } catch (InterruptedException e) {
102                 LOGGER.debug(msg, elementId);
103                 Thread.currentThread().interrupt();
104                 return false;
105             }
106         }
107         return true;
108     }
109
110     /**
111      * Handle a automation composition element state change.
112      *
113      * @param automationCompositionElementId the ID of the automation composition element
114      */
115     @Override
116     public void undeploy(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException {
117         LOGGER.debug("undeploy call");
118
119         if (!execution(config.getUndeployTimerMs(), "Current Thread undeploy is Interrupted during execution {}",
120                 automationCompositionElementId)) {
121             return;
122         }
123
124         if (config.isUndeploySuccess()) {
125             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
126                     automationCompositionElementId, DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR,
127                     "Undeployed");
128         } else {
129             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
130                     automationCompositionElementId, DeployState.DEPLOYED, null, StateChangeResult.FAILED,
131                     "Undeploy failed!");
132         }
133     }
134
135     @Override
136     public void lock(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException {
137         LOGGER.debug("lock call");
138
139         if (!execution(config.getLockTimerMs(), "Current Thread lock is Interrupted during execution {}",
140                 automationCompositionElementId)) {
141             return;
142         }
143
144         if (config.isLockSuccess()) {
145             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
146                     automationCompositionElementId, null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked");
147         } else {
148             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
149                     automationCompositionElementId, null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!");
150         }
151     }
152
153     @Override
154     public void unlock(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException {
155         LOGGER.debug("unlock call");
156
157         if (!execution(config.getUnlockTimerMs(), "Current Thread unlock is Interrupted during execution {}",
158                 automationCompositionElementId)) {
159             return;
160         }
161
162         if (config.isUnlockSuccess()) {
163             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
164                     automationCompositionElementId, null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked");
165         } else {
166             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
167                     automationCompositionElementId, null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!");
168         }
169     }
170
171     @Override
172     public void delete(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException {
173         LOGGER.debug("delete call");
174
175         if (!execution(config.getDeleteTimerMs(), "Current Thread delete is Interrupted during execution {}",
176                 automationCompositionElementId)) {
177             return;
178         }
179
180         if (config.isDeleteSuccess()) {
181             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
182                     automationCompositionElementId, DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted");
183         } else {
184             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
185                     automationCompositionElementId, DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
186                     "Delete failed!");
187         }
188     }
189
190     @Override
191     public void update(UUID automationCompositionId, AcElementDeploy element, Map<String, Object> properties)
192             throws PfModelException {
193         LOGGER.debug("update call");
194
195         if (!execution(config.getUpdateTimerMs(), "Current Thread update is Interrupted during execution {}",
196                 element.getId())) {
197             return;
198         }
199
200         if (config.isUpdateSuccess()) {
201             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
202                     DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated");
203         } else {
204             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
205                     DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!");
206         }
207     }
208
209     /**
210      * Get AutomationComposition.
211      *
212      * @return the AutomationCompositions
213      */
214     public AutomationCompositions getAutomationCompositions() {
215         var result = new AutomationCompositions();
216         result.setAutomationCompositionList(new ArrayList<>(intermediaryApi.getAutomationCompositions().values()));
217         return result;
218     }
219
220     /**
221      * Set OutProperties.
222      *
223      * @param automationCompositionId the automationComposition Id
224      * @param elementId the automationComposition Element Id
225      * @param useState the useState
226      * @param operationalState the operationalState
227      * @param outProperties the outProperties
228      */
229     public void setOutProperties(UUID automationCompositionId, UUID elementId, String useState, String operationalState,
230             Map<String, Object> outProperties) {
231         intermediaryApi.sendAcElementInfo(automationCompositionId, elementId, useState, operationalState,
232                 outProperties);
233     }
234
235     @Override
236     public void prime(UUID compositionId, List<AutomationCompositionElementDefinition> elementDefinitionList)
237             throws PfModelException {
238         LOGGER.debug("prime call");
239
240         if (!execution(config.getPrimeTimerMs(), "Current Thread prime is Interrupted during execution {}",
241                 compositionId)) {
242             return;
243         }
244
245         if (config.isPrimeSuccess()) {
246             intermediaryApi.updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR,
247                     "Primed");
248         } else {
249             intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.FAILED,
250                     "Prime failed!");
251         }
252     }
253
254     @Override
255     public void deprime(UUID compositionId) throws PfModelException {
256         LOGGER.debug("deprime call");
257
258         if (!execution(config.getDeprimeTimerMs(), "Current Thread deprime is Interrupted during execution {}",
259                 compositionId)) {
260             return;
261         }
262
263         if (config.isDeprimeSuccess()) {
264             intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR,
265                     "Deprimed");
266         } else {
267             intermediaryApi.updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.FAILED,
268                     "Deprime failed!");
269         }
270     }
271
272     /**
273      * Get Instance Data List.
274      *
275      * @return the InternalDatas
276      */
277     public InternalDatas getDataList() {
278         var result = new InternalDatas();
279         var map = intermediaryApi.getAutomationCompositions();
280         for (var instance : map.values()) {
281             for (var element : instance.getElements().values()) {
282                 var data = new InternalData();
283                 data.setAutomationCompositionId(instance.getInstanceId());
284                 data.setAutomationCompositionElementId(element.getId());
285                 data.setIntProperties(element.getProperties());
286                 data.setOperationalState(element.getOperationalState());
287                 data.setUseState(element.getUseState());
288                 data.setOutProperties(element.getOutProperties());
289                 result.getList().add(data);
290             }
291         }
292         return result;
293     }
294
295     @Override
296     public void handleRestartComposition(UUID compositionId,
297             List<AutomationCompositionElementDefinition> elementDefinitionList, AcTypeState state)
298             throws PfModelException {
299         LOGGER.debug("restart composition definition call");
300         switch (state) {
301             case PRIMING:
302                 prime(compositionId, elementDefinitionList);
303                 break;
304
305             case DEPRIMING:
306                 deprime(compositionId);
307                 break;
308
309             default:
310                 intermediaryApi.updateCompositionState(compositionId, state, StateChangeResult.NO_ERROR, "Restarted");
311         }
312     }
313
314     @Override
315     public void handleRestartInstance(UUID automationCompositionId, AcElementDeploy element,
316             Map<String, Object> properties, DeployState deployState, LockState lockState) throws PfModelException {
317         LOGGER.debug("restart instance call");
318         if (!AcmUtils.isInTransitionalState(deployState, lockState)) {
319             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
320                     deployState, lockState, StateChangeResult.NO_ERROR, "Restarted");
321             return;
322         }
323         if (DeployState.DEPLOYING.equals(deployState)) {
324             deploy(automationCompositionId, element, properties);
325             return;
326         }
327         if (DeployState.UNDEPLOYING.equals(deployState)) {
328             undeploy(automationCompositionId, element.getId());
329             return;
330         }
331         if (DeployState.UPDATING.equals(deployState)) {
332             update(automationCompositionId, element, properties);
333             return;
334         }
335         if (DeployState.DELETING.equals(deployState)) {
336             delete(automationCompositionId, element.getId());
337             return;
338         }
339         if (LockState.LOCKING.equals(lockState)) {
340             lock(automationCompositionId, element.getId());
341             return;
342         }
343         if (LockState.UNLOCKING.equals(lockState)) {
344             unlock(automationCompositionId, element.getId());
345         }
346     }
347
348     /**
349      * Get Composition Data List.
350      *
351      * @return the InternalDatas
352      */
353     public InternalDatas getCompositionDataList() {
354         var acElementsDefinitions = intermediaryApi.getAcElementsDefinitions();
355         var internalDatas = new InternalDatas();
356         for (var entry : acElementsDefinitions.entrySet()) {
357             for (var acElementsDefinition : entry.getValue().values()) {
358                 var internalData = new InternalData();
359                 internalData.setCompositionId(entry.getKey());
360                 internalData.setCompositionDefinitionElementId(acElementsDefinition.getAcElementDefinitionId());
361                 internalData.setIntProperties(
362                         acElementsDefinition.getAutomationCompositionElementToscaNodeTemplate().getProperties());
363                 internalData.setOutProperties(acElementsDefinition.getOutProperties());
364                 internalDatas.getList().add(internalData);
365             }
366         }
367         return internalDatas;
368     }
369
370     public void setCompositionOutProperties(UUID compositionId, ToscaConceptIdentifier compositionDefinitionElementId,
371             Map<String, Object> outProperties) {
372         intermediaryApi.sendAcDefinitionInfo(compositionId, compositionDefinitionElementId, outProperties);
373
374     }
375
376     @Override
377     public void migrate(UUID automationCompositionId, AcElementDeploy element, UUID compositionTargetId,
378                         Map<String, Object> properties) throws PfModelException {
379         intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
380             DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated");
381     }
382 }