2cba379c460f20d43f53509e223642cc06e06b32
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2023-2024 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.Map;
26 import java.util.UUID;
27 import lombok.Getter;
28 import lombok.Setter;
29 import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto;
30 import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto;
31 import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto;
32 import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
33 import org.onap.policy.clamp.acm.participant.intermediary.api.impl.AcElementListenerV2;
34 import org.onap.policy.clamp.acm.participant.sim.model.InternalData;
35 import org.onap.policy.clamp.acm.participant.sim.model.InternalDatas;
36 import org.onap.policy.clamp.acm.participant.sim.model.SimConfig;
37 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
38 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
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 public class AutomationCompositionElementHandler extends AcElementListenerV2 {
55
56     private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
57
58     @Getter
59     @Setter
60     private SimConfig config = new SimConfig();
61
62     public AutomationCompositionElementHandler(ParticipantIntermediaryApi intermediaryApi) {
63         super(intermediaryApi);
64     }
65
66     /**
67      * Handle a deploy on a automation composition element.
68      *
69      * @param compositionElement the information of the Automation Composition Definition Element
70      * @param instanceElement the information of the Automation Composition Instance Element
71      * @throws PfModelException from Policy framework
72      */
73     @Override
74     public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
75             throws PfModelException {
76         LOGGER.debug("deploy call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement);
77
78         if (!execution(config.getDeployTimerMs(), "Current Thread deploy is Interrupted during execution {}",
79             instanceElement.elementId())) {
80             return;
81         }
82
83         if (config.isDeploySuccess()) {
84             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
85                 instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR,
86                 "Deployed");
87         } else {
88             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
89                 instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
90                 "Deploy failed!");
91         }
92     }
93
94     private boolean execution(int timeMs, String msg, UUID elementId) {
95         long endTime = System.currentTimeMillis() + timeMs;
96         while (System.currentTimeMillis() < endTime) {
97             try {
98                 if (Thread.currentThread().isInterrupted()) {
99                     LOGGER.debug(msg, elementId);
100                     return false;
101                 }
102                 Thread.sleep(10L);
103             } catch (InterruptedException e) {
104                 LOGGER.debug(msg, elementId);
105                 Thread.currentThread().interrupt();
106                 return false;
107             }
108         }
109         return true;
110     }
111
112     /**
113      * Handle a automation composition element state change.
114      *
115      * @param compositionElement the information of the Automation Composition Definition Element
116      * @param instanceElement the information of the Automation Composition Instance Element
117      * @throws PfModelException from Policy framework
118      */
119     @Override
120     public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
121         throws PfModelException {
122         LOGGER.debug("undeploy call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement);
123
124         if (!execution(config.getUndeployTimerMs(), "Current Thread undeploy is Interrupted during execution {}",
125             instanceElement.elementId())) {
126             return;
127         }
128
129         if (config.isUndeploySuccess()) {
130             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
131                 instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR,
132                     "Undeployed");
133         } else {
134             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
135                 instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.FAILED,
136                     "Undeploy failed!");
137         }
138     }
139
140     @Override
141     public void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
142         throws PfModelException {
143         LOGGER.debug("lock call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement);
144
145         if (!execution(config.getLockTimerMs(), "Current Thread lock is Interrupted during execution {}",
146             instanceElement.elementId())) {
147             return;
148         }
149
150         if (config.isLockSuccess()) {
151             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
152                 instanceElement.elementId(), null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked");
153         } else {
154             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
155                 instanceElement.elementId(), null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!");
156         }
157     }
158
159     @Override
160     public void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
161         throws PfModelException {
162         LOGGER.debug("unlock call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement);
163
164         if (!execution(config.getUnlockTimerMs(), "Current Thread unlock is Interrupted during execution {}",
165             instanceElement.elementId())) {
166             return;
167         }
168
169         if (config.isUnlockSuccess()) {
170             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
171                 instanceElement.elementId(), null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked");
172         } else {
173             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
174                 instanceElement.elementId(), null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!");
175         }
176     }
177
178     @Override
179     public void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
180         throws PfModelException {
181         LOGGER.debug("delete call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement);
182
183         if (!execution(config.getDeleteTimerMs(), "Current Thread delete is Interrupted during execution {}",
184             instanceElement.elementId())) {
185             return;
186         }
187
188         if (config.isDeleteSuccess()) {
189             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
190                 instanceElement.elementId(), DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted");
191         } else {
192             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
193                 instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
194                 "Delete failed!");
195         }
196     }
197
198     @Override
199     public void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement,
200                        InstanceElementDto instanceElementUpdated) throws PfModelException {
201         LOGGER.debug("update call compositionElement: {}, instanceElement: {}, instanceElementUpdated: {}",
202             compositionElement, instanceElement, instanceElementUpdated);
203
204         if (!execution(config.getUpdateTimerMs(), "Current Thread update is Interrupted during execution {}",
205             instanceElement.elementId())) {
206             return;
207         }
208
209         if (config.isUpdateSuccess()) {
210             intermediaryApi.updateAutomationCompositionElementState(
211                 instanceElement.instanceId(), instanceElement.elementId(),
212                 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated");
213         } else {
214             intermediaryApi.updateAutomationCompositionElementState(
215                 instanceElement.instanceId(), instanceElement.elementId(),
216                 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!");
217         }
218     }
219
220     /**
221      * Get AutomationComposition.
222      *
223      * @return the AutomationCompositions
224      */
225     public AutomationCompositions getAutomationCompositions() {
226         var result = new AutomationCompositions();
227         result.setAutomationCompositionList(new ArrayList<>(intermediaryApi.getAutomationCompositions().values()));
228         return result;
229     }
230
231     public AutomationComposition getAutomationComposition(UUID instanceId) {
232         return intermediaryApi.getAutomationComposition(instanceId);
233     }
234
235     /**
236      * Set OutProperties.
237      *
238      * @param automationCompositionId the automationComposition Id
239      * @param elementId the automationComposition Element Id
240      * @param useState the useState
241      * @param operationalState the operationalState
242      * @param outProperties the outProperties
243      */
244     public void setOutProperties(UUID automationCompositionId, UUID elementId, String useState, String operationalState,
245             Map<String, Object> outProperties) {
246         intermediaryApi.sendAcElementInfo(automationCompositionId, elementId, useState, operationalState,
247                 outProperties);
248     }
249
250     @Override
251     public void prime(CompositionDto composition) throws PfModelException {
252         LOGGER.debug("prime call composition: {}", composition);
253
254         if (!execution(config.getPrimeTimerMs(), "Current Thread prime is Interrupted during execution {}",
255             composition.compositionId())) {
256             return;
257         }
258
259         if (config.isPrimeSuccess()) {
260             intermediaryApi.updateCompositionState(composition.compositionId(),
261                 AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed");
262         } else {
263             intermediaryApi.updateCompositionState(composition.compositionId(),
264                 AcTypeState.COMMISSIONED, StateChangeResult.FAILED, "Prime failed!");
265         }
266     }
267
268     @Override
269     public void deprime(CompositionDto composition) throws PfModelException {
270         LOGGER.debug("deprime call composition: {}", composition);
271
272         if (!execution(config.getDeprimeTimerMs(), "Current Thread deprime is Interrupted during execution {}",
273             composition.compositionId())) {
274             return;
275         }
276
277         if (config.isDeprimeSuccess()) {
278             intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED,
279                 StateChangeResult.NO_ERROR, "Deprimed");
280         } else {
281             intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED,
282                 StateChangeResult.FAILED, "Deprime failed!");
283         }
284     }
285
286     /**
287      * Get Instance Data List.
288      *
289      * @return the InternalDatas
290      */
291     public InternalDatas getDataList() {
292         var result = new InternalDatas();
293         var map = intermediaryApi.getAutomationCompositions();
294         for (var instance : map.values()) {
295             for (var element : instance.getElements().values()) {
296                 var data = new InternalData();
297                 data.setCompositionId(instance.getCompositionId());
298                 data.setCompositionDefinitionElementId(element.getDefinition());
299                 data.setAutomationCompositionId(instance.getInstanceId());
300                 data.setAutomationCompositionElementId(element.getId());
301                 data.setIntProperties(element.getProperties());
302                 data.setOperationalState(element.getOperationalState());
303                 data.setUseState(element.getUseState());
304                 data.setOutProperties(element.getOutProperties());
305                 result.getList().add(data);
306             }
307         }
308         return result;
309     }
310
311     @Override
312     public void handleRestartComposition(CompositionDto composition, AcTypeState state) throws PfModelException {
313         LOGGER.debug("restart composition definition call");
314         switch (state) {
315             case PRIMING:
316                 prime(composition);
317                 break;
318
319             case DEPRIMING:
320                 deprime(composition);
321                 break;
322
323             default:
324                 intermediaryApi.updateCompositionState(composition.compositionId(), state,
325                     StateChangeResult.NO_ERROR, "Restarted");
326         }
327     }
328
329     @Override
330     public void handleRestartInstance(CompositionElementDto compositionElement, InstanceElementDto instanceElement,
331         DeployState deployState, LockState lockState) throws PfModelException {
332         LOGGER.debug("restart instance call");
333         if (!AcmUtils.isInTransitionalState(deployState, lockState)) {
334             intermediaryApi.updateAutomationCompositionElementState(
335                 instanceElement.instanceId(), instanceElement.elementId(), deployState, lockState,
336                 StateChangeResult.NO_ERROR, "Restarted");
337             return;
338         }
339         if (DeployState.DEPLOYING.equals(deployState)) {
340             deploy(compositionElement, instanceElement);
341             return;
342         }
343         if (DeployState.UNDEPLOYING.equals(deployState)) {
344             undeploy(compositionElement, instanceElement);
345             return;
346         }
347         if (DeployState.UPDATING.equals(deployState)) {
348             update(compositionElement, instanceElement, instanceElement);
349             return;
350         }
351         if (DeployState.DELETING.equals(deployState)) {
352             delete(compositionElement, instanceElement);
353             return;
354         }
355         if (LockState.LOCKING.equals(lockState)) {
356             lock(compositionElement, instanceElement);
357             return;
358         }
359         if (LockState.UNLOCKING.equals(lockState)) {
360             unlock(compositionElement, instanceElement);
361         }
362     }
363
364     /**
365      * Get Composition Data List.
366      *
367      * @return the InternalDatas
368      */
369     public InternalDatas getCompositionDataList() {
370         var acElementsDefinitions = intermediaryApi.getAcElementsDefinitions();
371         var internalDatas = new InternalDatas();
372         for (var entry : acElementsDefinitions.entrySet()) {
373             for (var acElementsDefinition : entry.getValue().values()) {
374                 var internalData = new InternalData();
375                 internalData.setCompositionId(entry.getKey());
376                 internalData.setCompositionDefinitionElementId(acElementsDefinition.getAcElementDefinitionId());
377                 internalData.setIntProperties(
378                         acElementsDefinition.getAutomationCompositionElementToscaNodeTemplate().getProperties());
379                 internalData.setOutProperties(acElementsDefinition.getOutProperties());
380                 internalDatas.getList().add(internalData);
381             }
382         }
383         return internalDatas;
384     }
385
386     public void setCompositionOutProperties(UUID compositionId, ToscaConceptIdentifier compositionDefinitionElementId,
387             Map<String, Object> outProperties) {
388         intermediaryApi.sendAcDefinitionInfo(compositionId, compositionDefinitionElementId, outProperties);
389
390     }
391
392     @Override
393     public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget,
394                         InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate)
395         throws PfModelException {
396         LOGGER.debug("migrate call compositionElement: {}, compositionElementTarget: {}, instanceElement: {},"
397                 + " instanceElementMigrate: {}",
398             compositionElement, compositionElementTarget, instanceElement, instanceElementMigrate);
399
400         if (!execution(config.getMigrateTimerMs(), "Current Thread migrate is Interrupted during execution {}",
401             instanceElement.elementId())) {
402             return;
403         }
404
405         if (config.isMigrateSuccess()) {
406             intermediaryApi.updateAutomationCompositionElementState(
407                 instanceElement.instanceId(), instanceElement.elementId(),
408                 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated");
409         } else {
410             intermediaryApi.updateAutomationCompositionElementState(
411                 instanceElement.instanceId(), instanceElement.elementId(),
412                 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!");
413         }
414     }
415 }