2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.clamp.acm.participant.sim.main.handler;
23 import java.util.ArrayList;
24 import java.util.List;
26 import java.util.UUID;
28 import lombok.RequiredArgsConstructor;
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;
48 * This class handles implementation of Simulator Service.
51 @RequiredArgsConstructor
52 public class SimulatorService {
54 private final ParticipantIntermediaryApi intermediaryApi;
56 private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorService.class);
57 private static final String INTERNAL_STATE = "InternalState";
58 private static final String MIGRATION_PROPERTY = "stage";
59 private static final String PREPARE_PROPERTY = "prepareStage";
63 private SimConfig config = new SimConfig();
66 * Get AutomationComposition.
68 * @return the AutomationCompositions
70 public AutomationCompositions getAutomationCompositions() {
71 var result = new AutomationCompositions();
72 result.setAutomationCompositionList(new ArrayList<>(intermediaryApi.getAutomationCompositions().values()));
76 public AutomationComposition getAutomationComposition(UUID instanceId) {
77 return intermediaryApi.getAutomationComposition(instanceId);
83 * @param instanceId the automationComposition Id
84 * @param elementId the automationComposition Element Id
85 * @param useState the useState
86 * @param operationalState the operationalState
87 * @param outProperties the outProperties
89 public void setOutProperties(UUID instanceId, UUID elementId, String useState, String operationalState,
90 Map<String, Object> outProperties) {
91 intermediaryApi.sendAcElementInfo(instanceId, elementId, useState, operationalState,
96 * Get Instance Data List.
98 * @return the InternalDatas
100 public InternalDatas getDataList() {
101 var result = new InternalDatas();
102 var map = intermediaryApi.getAutomationCompositions();
103 for (var instance : map.values()) {
104 for (var element : instance.getElements().values()) {
105 var data = new InternalData();
106 data.setCompositionId(instance.getCompositionId());
107 data.setAutomationCompositionId(instance.getInstanceId());
108 data.setAutomationCompositionElementId(element.getId());
109 data.setIntProperties(element.getProperties());
110 data.setOperationalState(element.getOperationalState());
111 data.setUseState(element.getUseState());
112 data.setOutProperties(element.getOutProperties());
113 result.getList().add(data);
120 * Get Composition Data List.
122 * @return the InternalDatas
124 public InternalDatas getCompositionDataList() {
125 var acElementsDefinitions = intermediaryApi.getAcElementsDefinitions();
126 var internalDatas = new InternalDatas();
127 for (var entry : acElementsDefinitions.entrySet()) {
128 for (var acElementsDefinition : entry.getValue().values()) {
129 var internalData = new InternalData();
130 internalData.setCompositionId(entry.getKey());
131 internalData.setCompositionDefinitionElementId(acElementsDefinition.getAcElementDefinitionId());
132 internalData.setIntProperties(
133 acElementsDefinition.getAutomationCompositionElementToscaNodeTemplate().getProperties());
134 internalData.setOutProperties(acElementsDefinition.getOutProperties());
135 internalDatas.getList().add(internalData);
138 return internalDatas;
141 public void setCompositionOutProperties(UUID compositionId, ToscaConceptIdentifier compositionDefinitionElementId,
142 Map<String, Object> outProperties) {
143 intermediaryApi.sendAcDefinitionInfo(compositionId, compositionDefinitionElementId, outProperties);
147 protected boolean execution(int timeMs, String msg, UUID elementId) {
148 long endTime = System.currentTimeMillis() + timeMs;
149 while (System.currentTimeMillis() < endTime) {
151 if (Thread.currentThread().isInterrupted()) {
152 LOGGER.debug(msg, elementId);
156 } catch (InterruptedException e) {
157 LOGGER.debug(msg, elementId);
158 Thread.currentThread().interrupt();
166 * Handle a deploy on a automation composition element.
168 * @param instanceId the instanceId
169 * @param elementId the elementId
170 * @param outProperties the outProperties
172 public void deploy(UUID instanceId, UUID elementId, Map<String, Object> outProperties) {
173 if (!execution(getConfig().getDeployTimerMs(),
174 "Current Thread deploy is Interrupted during execution {}", elementId)) {
178 if (getConfig().isDeploySuccess()) {
179 outProperties.put(INTERNAL_STATE, DeployState.DEPLOYED.name());
180 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
182 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
183 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed");
185 outProperties.put(INTERNAL_STATE, DeployState.UNDEPLOYED.name());
186 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
188 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
189 DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!");
194 * Handle an udeploy on a automation composition element.
196 * @param instanceId the instanceId
197 * @param elementId the elementId
198 * @param outProperties the outProperties
200 public void undeploy(UUID instanceId, UUID elementId, Map<String, Object> outProperties) {
201 if (!execution(getConfig().getUndeployTimerMs(),
202 "Current Thread undeploy is Interrupted during execution {}", elementId)) {
206 if (getConfig().isUndeploySuccess()) {
207 outProperties.put(INTERNAL_STATE, DeployState.UNDEPLOYED.name());
208 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
210 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
211 DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed");
213 outProperties.put(INTERNAL_STATE, DeployState.DEPLOYED.name());
214 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
216 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
217 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Undeploy failed!");
222 * Handle a lock on a automation composition element.
224 * @param instanceId the instanceId
225 * @param elementId the elementId
227 public void lock(UUID instanceId, UUID elementId) {
228 if (!execution(getConfig().getLockTimerMs(),
229 "Current Thread lock is Interrupted during execution {}", elementId)) {
233 if (getConfig().isLockSuccess()) {
234 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
235 null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked");
237 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
238 null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!");
243 * Handle an unlock on a automation composition element.
245 * @param instanceId the instanceId
246 * @param elementId the elementId
248 public void unlock(UUID instanceId, UUID elementId) {
249 if (!execution(getConfig().getUnlockTimerMs(),
250 "Current Thread unlock is Interrupted during execution {}", elementId)) {
254 if (getConfig().isUnlockSuccess()) {
255 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
256 null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked");
258 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
259 null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!");
264 * Handle a delete on a automation composition element.
266 * @param instanceId the instanceId
267 * @param elementId the elementId
269 public void delete(UUID instanceId, UUID elementId) {
270 if (!execution(getConfig().getDeleteTimerMs(),
271 "Current Thread delete is Interrupted during execution {}", elementId)) {
275 if (getConfig().isDeleteSuccess()) {
276 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
277 DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted");
279 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
280 DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Delete failed!");
285 * Handle an update on a automation composition element.
287 * @param instanceId the instanceId
288 * @param elementId the elementId
290 public void update(UUID instanceId, UUID elementId) {
291 if (!execution(getConfig().getUpdateTimerMs(),
292 "Current Thread update is Interrupted during execution {}", elementId)) {
296 if (getConfig().isUpdateSuccess()) {
297 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
298 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated");
300 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
301 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!");
306 * Handle a prime on a automation composition definition.
308 * @param composition the information of the Automation Composition Definition
310 public void prime(CompositionDto composition) {
311 if (!execution(getConfig().getPrimeTimerMs(),
312 "Current Thread prime is Interrupted during execution {}", composition.compositionId())) {
316 if (getConfig().isPrimeSuccess()) {
317 sendOutProperties(composition, AcTypeState.PRIMED.name());
318 intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED,
319 StateChangeResult.NO_ERROR, "Primed");
321 sendOutProperties(composition, AcTypeState.COMMISSIONED.name());
322 intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED,
323 StateChangeResult.FAILED, "Prime failed!");
327 private void sendOutProperties(CompositionDto composition, String data) {
328 for (var elementEntry : composition.outPropertiesMap().entrySet()) {
329 elementEntry.getValue().put(INTERNAL_STATE, data);
330 intermediaryApi.sendAcDefinitionInfo(
331 composition.compositionId(), elementEntry.getKey(), elementEntry.getValue());
336 * Handle a deprime on a automation composition definition.
338 * @param composition the information of the Automation Composition Definition
340 public void deprime(CompositionDto composition) {
341 if (!execution(getConfig().getDeprimeTimerMs(),
342 "Current Thread deprime is Interrupted during execution {}", composition.compositionId())) {
346 if (getConfig().isDeprimeSuccess()) {
347 sendOutProperties(composition, AcTypeState.COMMISSIONED.name());
348 intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED,
349 StateChangeResult.NO_ERROR, "Deprimed");
351 sendOutProperties(composition, AcTypeState.PRIMED.name());
352 intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED,
353 StateChangeResult.FAILED, "Deprime failed!");
358 * Handle a migrate on a automation composition element.
360 * @param instanceId the instanceId
361 * @param elementId the elementId
362 * @param stage the stage
363 * @param compositionInProperties in Properties from composition definition element
364 * @param instanceOutProperties in Properties from instance element
366 public void migrate(UUID instanceId, UUID elementId, int stage, Map<String, Object> compositionInProperties,
367 Map<String, Object> instanceOutProperties) {
368 if (!execution(getConfig().getMigrateTimerMs(),
369 "Current Thread migrate is Interrupted during execution {}", elementId)) {
373 if (config.isMigrateSuccess()) {
374 var stageSet = ParticipantUtils.findStageSetMigrate(compositionInProperties);
375 var nextStage = 1000;
376 for (var s : stageSet) {
378 nextStage = Math.min(s, nextStage);
381 instanceOutProperties.putIfAbsent(MIGRATION_PROPERTY, new ArrayList<>());
382 @SuppressWarnings("unchecked")
383 var stageList = (List<Integer>) instanceOutProperties.get(MIGRATION_PROPERTY);
384 stageList.add(stage);
385 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, instanceOutProperties);
386 if (nextStage == 1000) {
387 intermediaryApi.updateAutomationCompositionElementState(
388 instanceId, elementId,
389 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated");
391 intermediaryApi.updateAutomationCompositionElementStage(
392 instanceId, elementId,
393 StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Migrated");
396 intermediaryApi.updateAutomationCompositionElementState(
397 instanceId, elementId,
398 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!");
403 * Handle a Migrate Precheck on a automation composition element.
405 * @param instanceId the instanceId
406 * @param elementId the elementId
408 public void migratePrecheck(UUID instanceId, UUID elementId) {
409 if (!execution(config.getMigratePrecheckTimerMs(),
410 "Current Thread migrate precheck is Interrupted during execution {}", elementId)) {
414 if (config.isMigratePrecheck()) {
415 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
416 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migration precheck completed");
418 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
419 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migration precheck failed");
424 * Handle a Prepare on a automation composition element.
426 * @param instanceId the instanceId
427 * @param elementId the elementId
428 * @param stage the stage
429 * @param compositionInProperties in Properties from composition definition element
430 * @param instanceOutProperties in Properties from instance element
432 public void prepare(UUID instanceId, UUID elementId, int stage, Map<String, Object> compositionInProperties,
433 Map<String, Object> instanceOutProperties) {
434 if (!execution(config.getPrepareTimerMs(),
435 "Current Thread prepare is Interrupted during execution {}", elementId)) {
439 if (config.isPrepare()) {
440 var stageSet = ParticipantUtils.findStageSetPrepare(compositionInProperties);
441 var nextStage = 1000;
442 for (var s : stageSet) {
444 nextStage = Math.min(s, nextStage);
447 instanceOutProperties.putIfAbsent(PREPARE_PROPERTY, new ArrayList<>());
448 @SuppressWarnings("unchecked")
449 var stageList = (List<Integer>) instanceOutProperties.get(PREPARE_PROPERTY);
450 stageList.add(stage);
451 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, instanceOutProperties);
452 if (nextStage == 1000) {
453 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
454 DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Prepare completed");
456 intermediaryApi.updateAutomationCompositionElementStage(
457 instanceId, elementId,
458 StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Prepared");
461 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
462 DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Prepare failed");
467 * Handle a Review on a automation composition element.
469 * @param instanceId the instanceId
470 * @param elementId the elementId
472 public void review(UUID instanceId, UUID elementId) {
473 if (!execution(config.getReviewTimerMs(),
474 "Current Thread review is Interrupted during execution {}", elementId)) {
478 if (config.isReview()) {
479 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
480 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Review completed");
482 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
483 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Review failed");