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;
27 import java.util.concurrent.locks.LockSupport;
29 import lombok.RequiredArgsConstructor;
31 import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto;
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.AcTypeState;
37 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
38 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
39 import org.onap.policy.clamp.models.acm.concepts.DeployState;
40 import org.onap.policy.clamp.models.acm.concepts.LockState;
41 import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils;
42 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
43 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46 import org.springframework.stereotype.Service;
49 * This class handles implementation of Simulator Service.
52 @RequiredArgsConstructor
53 public class SimulatorService {
55 private final ParticipantIntermediaryApi intermediaryApi;
57 private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorService.class);
58 private static final String INTERNAL_STATE = "InternalState";
59 private static final String MIGRATION_PROPERTY = "stage";
60 private static final String PREPARE_PROPERTY = "prepareStage";
64 private SimConfig config = new SimConfig();
67 * Get AutomationComposition.
69 * @return the AutomationCompositions
71 public AutomationCompositions getAutomationCompositions() {
72 var result = new AutomationCompositions();
73 result.setAutomationCompositionList(new ArrayList<>(intermediaryApi.getAutomationCompositions().values()));
77 public AutomationComposition getAutomationComposition(UUID instanceId) {
78 return intermediaryApi.getAutomationComposition(instanceId);
84 * @param instanceId the automationComposition Id
85 * @param elementId the automationComposition Element Id
86 * @param useState the useState
87 * @param operationalState the operationalState
88 * @param outProperties the outProperties
90 public void setOutProperties(UUID instanceId, UUID elementId, String useState, String operationalState,
91 Map<String, Object> outProperties) {
92 intermediaryApi.sendAcElementInfo(instanceId, elementId, useState, operationalState,
97 * Get Instance Data List.
99 * @return the InternalDatas
101 public InternalDatas getDataList() {
102 var result = new InternalDatas();
103 var map = intermediaryApi.getAutomationCompositions();
104 for (var instance : map.values()) {
105 for (var element : instance.getElements().values()) {
106 var data = new InternalData();
107 data.setCompositionId(instance.getCompositionId());
108 data.setAutomationCompositionId(instance.getInstanceId());
109 data.setAutomationCompositionElementId(element.getId());
110 data.setIntProperties(element.getProperties());
111 data.setOperationalState(element.getOperationalState());
112 data.setUseState(element.getUseState());
113 data.setOutProperties(element.getOutProperties());
114 result.getList().add(data);
121 * Get Composition Data List.
123 * @return the InternalDatas
125 public InternalDatas getCompositionDataList() {
126 var acElementsDefinitions = intermediaryApi.getAcElementsDefinitions();
127 var internalDatas = new InternalDatas();
128 for (var entry : acElementsDefinitions.entrySet()) {
129 for (var acElementsDefinition : entry.getValue().values()) {
130 var internalData = new InternalData();
131 internalData.setCompositionId(entry.getKey());
132 internalData.setCompositionDefinitionElementId(acElementsDefinition.getAcElementDefinitionId());
133 internalData.setIntProperties(
134 acElementsDefinition.getAutomationCompositionElementToscaNodeTemplate().getProperties());
135 internalData.setOutProperties(acElementsDefinition.getOutProperties());
136 internalDatas.getList().add(internalData);
139 return internalDatas;
142 public void setCompositionOutProperties(UUID compositionId, ToscaConceptIdentifier compositionDefinitionElementId,
143 Map<String, Object> outProperties) {
144 intermediaryApi.sendAcDefinitionInfo(compositionId, compositionDefinitionElementId, outProperties);
148 protected boolean isInterrupted(int timeMs, String msg, UUID elementId) {
149 long endTime = System.nanoTime() + (timeMs * 1_000_000L);
150 while (System.nanoTime() < endTime) {
151 if (Thread.interrupted()) {
152 LOGGER.debug(msg, elementId);
155 LockSupport.parkNanos(10_000_000L);
161 * Handle deploying an automation composition element.
163 * @param instanceId the instanceId
164 * @param elementId the elementId
165 * @param outProperties the outProperties
167 public void deploy(UUID instanceId, UUID elementId, Map<String, Object> outProperties) {
168 if (isInterrupted(getConfig().getDeployTimerMs(),
169 "Current Thread deploy is Interrupted during execution {}", elementId)) {
173 if (getConfig().isDeploySuccess()) {
174 outProperties.put(INTERNAL_STATE, DeployState.DEPLOYED.name());
175 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
177 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
178 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed");
180 outProperties.put(INTERNAL_STATE, DeployState.UNDEPLOYED.name());
181 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
183 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
184 DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!");
189 * Handle undeploying an automation composition element.
191 * @param instanceId the instanceId
192 * @param elementId the elementId
193 * @param outProperties the outProperties
195 public void undeploy(UUID instanceId, UUID elementId, Map<String, Object> outProperties) {
196 if (isInterrupted(getConfig().getUndeployTimerMs(),
197 "Current Thread undeploy is Interrupted during execution {}", elementId)) {
201 if (getConfig().isUndeploySuccess()) {
202 outProperties.put(INTERNAL_STATE, DeployState.UNDEPLOYED.name());
203 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
205 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
206 DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed");
208 outProperties.put(INTERNAL_STATE, DeployState.DEPLOYED.name());
209 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties);
211 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
212 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Undeploy failed!");
217 * Handle locking an automation composition element.
219 * @param instanceId the instanceId
220 * @param elementId the elementId
222 public void lock(UUID instanceId, UUID elementId) {
223 if (isInterrupted(getConfig().getLockTimerMs(),
224 "Current Thread lock is Interrupted during execution {}", elementId)) {
228 if (getConfig().isLockSuccess()) {
229 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
230 null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked");
232 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
233 null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!");
238 * Handle unlocking an automation composition element.
240 * @param instanceId the instanceId
241 * @param elementId the elementId
243 public void unlock(UUID instanceId, UUID elementId) {
244 if (isInterrupted(getConfig().getUnlockTimerMs(),
245 "Current Thread unlock is Interrupted during execution {}", elementId)) {
249 if (getConfig().isUnlockSuccess()) {
250 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
251 null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked");
253 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
254 null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!");
259 * Handle deleting an automation composition element.
261 * @param instanceId the instanceId
262 * @param elementId the elementId
264 public void delete(UUID instanceId, UUID elementId) {
265 if (isInterrupted(getConfig().getDeleteTimerMs(),
266 "Current Thread delete is Interrupted during execution {}", elementId)) {
270 if (getConfig().isDeleteSuccess()) {
271 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
272 DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted");
274 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
275 DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Delete failed!");
280 * Handle an update on an automation composition element.
282 * @param instanceId the instanceId
283 * @param elementId the elementId
285 public void update(UUID instanceId, UUID elementId) {
286 if (isInterrupted(getConfig().getUpdateTimerMs(),
287 "Current Thread update is Interrupted during execution {}", elementId)) {
291 if (getConfig().isUpdateSuccess()) {
292 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
293 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated");
295 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
296 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!");
301 * Handle a prime on an automation composition definition.
303 * @param composition the information of the Automation Composition Definition
305 public void prime(CompositionDto composition) {
306 if (isInterrupted(getConfig().getPrimeTimerMs(),
307 "Current Thread prime is Interrupted during execution {}", composition.compositionId())) {
311 if (getConfig().isPrimeSuccess()) {
312 sendOutProperties(composition, AcTypeState.PRIMED.name());
313 intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED,
314 StateChangeResult.NO_ERROR, "Primed");
316 sendOutProperties(composition, AcTypeState.COMMISSIONED.name());
317 intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED,
318 StateChangeResult.FAILED, "Prime failed!");
322 private void sendOutProperties(CompositionDto composition, String data) {
323 for (var elementEntry : composition.outPropertiesMap().entrySet()) {
324 elementEntry.getValue().put(INTERNAL_STATE, data);
325 intermediaryApi.sendAcDefinitionInfo(
326 composition.compositionId(), elementEntry.getKey(), elementEntry.getValue());
331 * Handle a deprime on an automation composition definition.
333 * @param composition the information of the Automation Composition Definition
335 public void deprime(CompositionDto composition) {
336 if (isInterrupted(getConfig().getDeprimeTimerMs(),
337 "Current Thread deprime is Interrupted during execution {}", composition.compositionId())) {
341 if (getConfig().isDeprimeSuccess()) {
342 sendOutProperties(composition, AcTypeState.COMMISSIONED.name());
343 intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED,
344 StateChangeResult.NO_ERROR, "Deprimed");
346 sendOutProperties(composition, AcTypeState.PRIMED.name());
347 intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED,
348 StateChangeResult.FAILED, "Deprime failed!");
353 * Handle a migration on an automation composition element.
355 * @param instanceId the instanceId
356 * @param elementId the elementId
357 * @param stage the stage
358 * @param compositionInProperties in Properties from composition definition element
359 * @param instanceOutProperties in Properties from instance element
361 public void migrate(UUID instanceId, UUID elementId, int stage, Map<String, Object> compositionInProperties,
362 Map<String, Object> instanceOutProperties) {
363 if (isInterrupted(getConfig().getMigrateTimerMs(),
364 "Current Thread migrate is Interrupted during execution {}", elementId)) {
368 if (config.isMigrateSuccess()) {
369 var stageSet = ParticipantUtils.findStageSetMigrate(compositionInProperties);
370 var nextStage = 1000;
371 for (var s : stageSet) {
373 nextStage = Math.min(s, nextStage);
376 instanceOutProperties.putIfAbsent(MIGRATION_PROPERTY, new ArrayList<>());
377 @SuppressWarnings("unchecked")
378 var stageList = (List<Integer>) instanceOutProperties.get(MIGRATION_PROPERTY);
379 stageList.add(stage);
380 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, instanceOutProperties);
381 if (nextStage == 1000) {
382 intermediaryApi.updateAutomationCompositionElementState(
383 instanceId, elementId,
384 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated");
386 intermediaryApi.updateAutomationCompositionElementStage(
387 instanceId, elementId,
388 StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Migrated");
391 intermediaryApi.updateAutomationCompositionElementState(
392 instanceId, elementId,
393 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!");
398 * Handle a Migrate Precheck on an automation composition element.
400 * @param instanceId the instanceId
401 * @param elementId the elementId
403 public void migratePrecheck(UUID instanceId, UUID elementId) {
404 if (isInterrupted(config.getMigratePrecheckTimerMs(),
405 "Current Thread migrate precheck is Interrupted during execution {}", elementId)) {
409 if (config.isMigratePrecheck()) {
410 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
411 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migration precheck completed");
413 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
414 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migration precheck failed");
419 * Handle a Prepare on an automation composition element.
421 * @param instanceId the instanceId
422 * @param elementId the elementId
423 * @param stage the stage
424 * @param compositionInProperties in Properties from composition definition element
425 * @param instanceOutProperties in Properties from instance element
427 public void prepare(UUID instanceId, UUID elementId, int stage, Map<String, Object> compositionInProperties,
428 Map<String, Object> instanceOutProperties) {
429 if (isInterrupted(config.getPrepareTimerMs(),
430 "Current Thread prepare is Interrupted during execution {}", elementId)) {
434 if (config.isPrepare()) {
435 var stageSet = ParticipantUtils.findStageSetPrepare(compositionInProperties);
436 var nextStage = 1000;
437 for (var s : stageSet) {
439 nextStage = Math.min(s, nextStage);
442 instanceOutProperties.putIfAbsent(PREPARE_PROPERTY, new ArrayList<>());
443 @SuppressWarnings("unchecked")
444 var stageList = (List<Integer>) instanceOutProperties.get(PREPARE_PROPERTY);
445 stageList.add(stage);
446 intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, instanceOutProperties);
447 if (nextStage == 1000) {
448 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
449 DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Prepare completed");
451 intermediaryApi.updateAutomationCompositionElementStage(
452 instanceId, elementId,
453 StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Prepared");
456 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
457 DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Prepare failed");
462 * Handle a Review on an automation composition element.
464 * @param instanceId the instanceId
465 * @param elementId the elementId
467 public void review(UUID instanceId, UUID elementId) {
468 if (isInterrupted(config.getReviewTimerMs(),
469 "Current Thread review is Interrupted during execution {}", elementId)) {
473 if (config.isReview()) {
474 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
475 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Review completed");
477 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId,
478 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Review failed");
483 * Handle rollback of an automation composition.
485 * @param instanceId AC instance ID
486 * @param elementId AC element ID
488 public void rollback(UUID instanceId, UUID elementId) {
489 if (isInterrupted(getConfig().getRollbackTimerMs(),
490 "Current Thread for rollback was Interrupted during execution {}", instanceId)) {
491 LOGGER.debug("Rollback interrupted");
495 if (config.isRollback()) {
496 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, null,
497 StateChangeResult.NO_ERROR, "Migration rollback done");
499 intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, null,
500 StateChangeResult.FAILED, "Migration rollback failed");