b1bbb6964002a7faa04bd182bdedd850693a8184
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2024-2025 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.util.ArrayList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.UUID;
27 import lombok.Getter;
28 import lombok.RequiredArgsConstructor;
29 import lombok.Setter;
30 import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto;
31 import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
32 import org.onap.policy.clamp.acm.participant.sim.model.InternalData;
33 import org.onap.policy.clamp.acm.participant.sim.model.InternalDatas;
34 import org.onap.policy.clamp.acm.participant.sim.model.SimConfig;
35 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
36 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
37 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
38 import org.onap.policy.clamp.models.acm.concepts.DeployState;
39 import org.onap.policy.clamp.models.acm.concepts.LockState;
40 import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils;
41 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
42 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.springframework.stereotype.Service;
46
47 /**
48  * This class handles implementation of Simulator Service.
49  */
50 @Service
51 @RequiredArgsConstructor
52 public class SimulatorService {
53
54     private final ParticipantIntermediaryApi intermediaryApi;
55
56     private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorService.class);
57     private static final String INTERNAL_STATE = "InternalState";
58
59     @Getter
60     @Setter
61     private SimConfig config = new SimConfig();
62
63     /**
64      * Get AutomationComposition.
65      *
66      * @return the AutomationCompositions
67      */
68     public AutomationCompositions getAutomationCompositions() {
69         var result = new AutomationCompositions();
70         result.setAutomationCompositionList(new ArrayList<>(intermediaryApi.getAutomationCompositions().values()));
71         return result;
72     }
73
74     public AutomationComposition getAutomationComposition(UUID instanceId) {
75         return intermediaryApi.getAutomationComposition(instanceId);
76     }
77
78     /**
79      * Set OutProperties.
80      *
81      * @param instanceId the automationComposition Id
82      * @param elementId the automationComposition Element Id
83      * @param useState the useState
84      * @param operationalState the operationalState
85      * @param outProperties the outProperties
86      */
87     public void setOutProperties(UUID instanceId, UUID elementId, String useState, String operationalState,
88                                  Map<String, Object> outProperties) {
89         intermediaryApi.sendAcElementInfo(instanceId, elementId, useState, operationalState,
90                 outProperties);
91     }
92
93     /**
94      * Get Instance Data List.
95      *
96      * @return the InternalDatas
97      */
98     public InternalDatas getDataList() {
99         var result = new InternalDatas();
100         var map = intermediaryApi.getAutomationCompositions();
101         for (var instance : map.values()) {
102             for (var element : instance.getElements().values()) {
103                 var data = new InternalData();
104                 data.setCompositionId(instance.getCompositionId());
105                 data.setAutomationCompositionId(instance.getInstanceId());
106                 data.setAutomationCompositionElementId(element.getId());
107                 data.setIntProperties(element.getProperties());
108                 data.setOperationalState(element.getOperationalState());
109                 data.setUseState(element.getUseState());
110                 data.setOutProperties(element.getOutProperties());
111                 result.getList().add(data);
112             }
113         }
114         return result;
115     }
116
117     /**
118      * Get Composition Data List.
119      *
120      * @return the InternalDatas
121      */
122     public InternalDatas getCompositionDataList() {
123         var acElementsDefinitions = intermediaryApi.getAcElementsDefinitions();
124         var internalDatas = new InternalDatas();
125         for (var entry : acElementsDefinitions.entrySet()) {
126             for (var acElementsDefinition : entry.getValue().values()) {
127                 var internalData = new InternalData();
128                 internalData.setCompositionId(entry.getKey());
129                 internalData.setCompositionDefinitionElementId(acElementsDefinition.getAcElementDefinitionId());
130                 internalData.setIntProperties(
131                         acElementsDefinition.getAutomationCompositionElementToscaNodeTemplate().getProperties());
132                 internalData.setOutProperties(acElementsDefinition.getOutProperties());
133                 internalDatas.getList().add(internalData);
134             }
135         }
136         return internalDatas;
137     }
138
139     public void setCompositionOutProperties(UUID compositionId, ToscaConceptIdentifier compositionDefinitionElementId,
140                                             Map<String, Object> outProperties) {
141         intermediaryApi.sendAcDefinitionInfo(compositionId, compositionDefinitionElementId, outProperties);
142
143     }
144
145     protected boolean execution(int timeMs, String msg, UUID elementId) {
146         long endTime = System.currentTimeMillis() + timeMs;
147         while (System.currentTimeMillis() < endTime) {
148             try {
149                 if (Thread.currentThread().isInterrupted()) {
150                     LOGGER.debug(msg, elementId);
151                     return false;
152                 }
153                 Thread.sleep(10L);
154             } catch (InterruptedException e) {
155                 LOGGER.debug(msg, elementId);
156                 Thread.currentThread().interrupt();
157                 return false;
158             }
159         }
160         return true;
161     }
162
163     /**
164      * Handle a deploy on a automation composition element.
165      *
166      * @param instanceId the instanceId
167      * @param elementId the elementId
168      * @param outProperties the outProperties
169      */
170     public void deploy(UUID instanceId, UUID elementId, Map<String, Object> outProperties) {
171         if (!execution(getConfig().getDeployTimerMs(),
172                 "Current Thread deploy is Interrupted during execution {}", elementId)) {
173             return;
174         }
175
176         if (getConfig().isDeploySuccess()) {
177             outProperties.put(INTERNAL_STATE, DeployState.DEPLOYED.name());
178             intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
179
180             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
181                     DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed");
182         } else {
183             outProperties.put(INTERNAL_STATE, DeployState.UNDEPLOYED.name());
184             intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
185
186             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
187                     DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!");
188         }
189     }
190
191     /**
192      * Handle an udeploy on a automation composition element.
193      *
194      * @param instanceId the instanceId
195      * @param elementId the elementId
196      * @param outProperties the outProperties
197      */
198     public void undeploy(UUID instanceId, UUID elementId, Map<String, Object> outProperties) {
199         if (!execution(getConfig().getUndeployTimerMs(),
200                 "Current Thread undeploy is Interrupted during execution {}", elementId)) {
201             return;
202         }
203
204         if (getConfig().isUndeploySuccess()) {
205             outProperties.put(INTERNAL_STATE, DeployState.UNDEPLOYED.name());
206             intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
207
208             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
209                     DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed");
210         } else {
211             outProperties.put(INTERNAL_STATE, DeployState.DEPLOYED.name());
212             intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
213
214             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
215                     DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Undeploy failed!");
216         }
217     }
218
219     /**
220      * Handle a lock on a automation composition element.
221      *
222      * @param instanceId the instanceId
223      * @param elementId the elementId
224      */
225     public void lock(UUID instanceId, UUID elementId) {
226         if (!execution(getConfig().getLockTimerMs(),
227                 "Current Thread lock is Interrupted during execution {}", elementId)) {
228             return;
229         }
230
231         if (getConfig().isLockSuccess()) {
232             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
233                     null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked");
234         } else {
235             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
236                     null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!");
237         }
238     }
239
240     /**
241      * Handle an unlock on a automation composition element.
242      *
243      * @param instanceId the instanceId
244      * @param elementId the elementId
245      */
246     public void unlock(UUID instanceId, UUID elementId) {
247         if (!execution(getConfig().getUnlockTimerMs(),
248                 "Current Thread unlock is Interrupted during execution {}", elementId)) {
249             return;
250         }
251
252         if (getConfig().isUnlockSuccess()) {
253             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
254                     null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked");
255         } else {
256             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
257                     null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!");
258         }
259     }
260
261     /**
262      * Handle a delete on a automation composition element.
263      *
264      * @param instanceId the instanceId
265      * @param elementId the elementId
266      */
267     public void delete(UUID instanceId, UUID elementId) {
268         if (!execution(getConfig().getDeleteTimerMs(),
269                 "Current Thread delete is Interrupted during execution {}", elementId)) {
270             return;
271         }
272
273         if (getConfig().isDeleteSuccess()) {
274             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
275                     DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted");
276         } else {
277             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
278                     DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Delete failed!");
279         }
280     }
281
282     /**
283      * Handle an update on a automation composition element.
284      *
285      * @param instanceId the instanceId
286      * @param elementId the elementId
287      */
288     public void update(UUID instanceId, UUID elementId) {
289         if (!execution(getConfig().getUpdateTimerMs(),
290                 "Current Thread update is Interrupted during execution {}", elementId)) {
291             return;
292         }
293
294         if (getConfig().isUpdateSuccess()) {
295             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
296                     DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated");
297         } else {
298             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
299                     DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!");
300         }
301     }
302
303     /**
304      * Handle a prime on a automation composition definition.
305      *
306      * @param composition the information of the Automation Composition Definition
307      */
308     public void prime(CompositionDto composition) {
309         if (!execution(getConfig().getPrimeTimerMs(),
310                 "Current Thread prime is Interrupted during execution {}", composition.compositionId())) {
311             return;
312         }
313
314         if (getConfig().isPrimeSuccess()) {
315             sendOutProperties(composition, AcTypeState.PRIMED.name());
316             intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED,
317                     StateChangeResult.NO_ERROR, "Primed");
318         } else {
319             sendOutProperties(composition, AcTypeState.COMMISSIONED.name());
320             intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED,
321                     StateChangeResult.FAILED, "Prime failed!");
322         }
323     }
324
325     private void sendOutProperties(CompositionDto composition, String data) {
326         for (var elementEntry : composition.outPropertiesMap().entrySet()) {
327             elementEntry.getValue().put(INTERNAL_STATE, data);
328             intermediaryApi.sendAcDefinitionInfo(
329                     composition.compositionId(), elementEntry.getKey(), elementEntry.getValue());
330         }
331     }
332
333     /**
334      * Handle a deprime on a automation composition definition.
335      *
336      * @param composition the information of the Automation Composition Definition
337      */
338     public void deprime(CompositionDto composition) {
339         if (!execution(getConfig().getDeprimeTimerMs(),
340                 "Current Thread deprime is Interrupted during execution {}", composition.compositionId())) {
341             return;
342         }
343
344         if (getConfig().isDeprimeSuccess()) {
345             sendOutProperties(composition, AcTypeState.COMMISSIONED.name());
346             intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED,
347                     StateChangeResult.NO_ERROR, "Deprimed");
348         } else {
349             sendOutProperties(composition, AcTypeState.PRIMED.name());
350             intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED,
351                     StateChangeResult.FAILED, "Deprime failed!");
352         }
353     }
354
355     /**
356      * Handle a migrate on a automation composition element.
357      *
358      * @param instanceId the instanceId
359      * @param elementId the elementId
360      * @param stage the stage
361      */
362     public void migrate(UUID instanceId, UUID elementId, int stage, Map<String, Object> compositionInProperties,
363             Map<String, Object> instanceOutProperties) {
364         if (!execution(getConfig().getMigrateTimerMs(),
365                 "Current Thread migrate is Interrupted during execution {}", elementId)) {
366             return;
367         }
368
369         if (config.isMigrateSuccess()) {
370             var stageSet = ParticipantUtils.findStageSet(compositionInProperties);
371             var nextStage = 1000;
372             for (var s : stageSet) {
373                 if (s > stage) {
374                     nextStage = Math.min(s, nextStage);
375                 }
376             }
377             instanceOutProperties.putIfAbsent("stage", new ArrayList<>());
378             @SuppressWarnings("unchecked")
379             var stageList = (List<Integer>) instanceOutProperties.get("stage");
380             stageList.add(stage);
381             intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, instanceOutProperties);
382             if (nextStage == 1000) {
383                 intermediaryApi.updateAutomationCompositionElementState(
384                         instanceId, elementId,
385                         DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated");
386             } else {
387                 intermediaryApi.updateAutomationCompositionElementStage(
388                         instanceId, elementId,
389                         StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Migrated");
390             }
391         } else {
392             intermediaryApi.updateAutomationCompositionElementState(
393                     instanceId, elementId,
394                     DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!");
395         }
396     }
397
398     /**
399      * Handle a Migrate Precheck on a automation composition element.
400      *
401      * @param instanceId the instanceId
402      * @param elementId the elementId
403      */
404     public void migratePrecheck(UUID instanceId, UUID elementId) {
405         if (!execution(config.getMigratePrecheckTimerMs(),
406                 "Current Thread migrate precheck is Interrupted during execution {}", elementId)) {
407             return;
408         }
409
410         if (config.isMigratePrecheck()) {
411             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
412                     DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migration precheck completed");
413         } else {
414             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
415                     DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migration precheck failed");
416         }
417     }
418
419     /**
420      * Handle a Prepare on a automation composition element.
421      *
422      * @param instanceId the instanceId
423      * @param elementId the elementId
424      */
425     public void prepare(UUID instanceId, UUID elementId) {
426         if (!execution(config.getPrepareTimerMs(),
427                 "Current Thread prepare is Interrupted during execution {}", elementId)) {
428             return;
429         }
430
431         if (config.isPrepare()) {
432             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
433                     DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Prepare completed");
434         } else {
435             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
436                     DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Prepare failed");
437         }
438     }
439
440     /**
441      * Handle a Review on a automation composition element.
442      *
443      * @param instanceId the instanceId
444      * @param elementId the elementId
445      */
446     public void review(UUID instanceId, UUID elementId) {
447         if (!execution(config.getReviewTimerMs(),
448                 "Current Thread review is Interrupted during execution {}", elementId)) {
449             return;
450         }
451
452         if (config.isReview()) {
453             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
454                     DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Review completed");
455         } else {
456             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
457                     DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Review failed");
458         }
459     }
460 }