2 * ============LICENSE_START=======================================================
3 * Copyright (C) 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
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.intermediary.handler;
23 import java.util.List;
25 import java.util.UUID;
26 import lombok.RequiredArgsConstructor;
27 import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto;
28 import org.onap.policy.clamp.acm.participant.intermediary.api.ElementState;
29 import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto;
30 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
31 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
32 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
33 import org.onap.policy.clamp.models.acm.concepts.DeployState;
34 import org.onap.policy.clamp.models.acm.concepts.SubState;
35 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration;
36 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionPrepare;
37 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
38 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.springframework.stereotype.Component;
44 @RequiredArgsConstructor
45 public class AcSubStateHandler {
47 private static final Logger LOGGER = LoggerFactory.getLogger(AcSubStateHandler.class);
49 private final CacheProvider cacheProvider;
50 private final ThreadHandler listener;
53 * Handles AutomationComposition Migration Precheck.
55 * @param migrationMsg the AutomationCompositionMigration
57 public void handleAcMigrationPrecheck(AutomationCompositionMigration migrationMsg) {
58 if (migrationMsg.getAutomationCompositionId() == null || migrationMsg.getCompositionTargetId() == null) {
62 var automationComposition = cacheProvider.getAutomationComposition(migrationMsg.getAutomationCompositionId());
63 if (automationComposition == null) {
64 LOGGER.debug("Automation composition {} does not use this participant",
65 migrationMsg.getAutomationCompositionId());
68 automationComposition.setSubState(SubState.MIGRATION_PRECHECKING);
69 for (var participantDeploy : migrationMsg.getParticipantUpdatesList()) {
70 if (cacheProvider.getParticipantId().equals(participantDeploy.getParticipantId())) {
72 callParticipantMigratePrecheck(migrationMsg.getMessageId(), participantDeploy.getAcElementList(),
73 automationComposition, migrationMsg.getCompositionTargetId());
78 private void callParticipantMigratePrecheck(UUID messageId, List<AcElementDeploy> acElements,
79 AutomationComposition automationComposition, UUID compositionTargetId) {
80 var compositionElementMap = cacheProvider.getCompositionElementDtoMap(automationComposition);
81 var instanceElementMap = cacheProvider.getInstanceElementDtoMap(automationComposition);
82 var acElementList = automationComposition.getElements();
83 for (var acElement : acElements) {
84 var element = acElementList.get(acElement.getId());
85 if (element != null) {
86 element.setSubState(SubState.MIGRATION_PRECHECKING);
89 var acCopyMigrateTo = new AutomationComposition(automationComposition);
90 var acElementCopyList = acCopyMigrateTo.getElements();
91 for (var acElement : acElements) {
92 var element = acElementCopyList.get(acElement.getId());
93 if (element != null) {
94 AcmUtils.recursiveMerge(element.getProperties(), acElement.getProperties());
95 element.setDefinition(acElement.getDefinition());
97 element = CacheProvider.createAutomationCompositionElement(acElement);
98 element.setSubState(SubState.MIGRATION_PRECHECKING);
99 acElementCopyList.put(element.getId(), element);
102 var toDelete = acElementCopyList.values().stream()
103 .filter(el -> !SubState.MIGRATION_PRECHECKING.equals(el.getSubState()))
104 .map(AutomationCompositionElement::getId)
106 toDelete.forEach(acElementCopyList::remove);
108 var compositionElementTargetMap = cacheProvider.getCompositionElementDtoMap(acCopyMigrateTo,
109 compositionTargetId);
110 var instanceElementMigrateMap = cacheProvider.getInstanceElementDtoMap(acCopyMigrateTo);
112 for (var acElement : acElements) {
113 var compositionElement = compositionElementMap.get(acElement.getId());
114 var compositionElementTarget = compositionElementTargetMap.get(acElement.getId());
115 var instanceElement = instanceElementMap.get(acElement.getId());
116 var instanceElementMigrate = instanceElementMigrateMap.get(acElement.getId());
118 if (instanceElement == null) {
119 // new element scenario
120 compositionElement = new CompositionElementDto(automationComposition.getCompositionId(),
121 acElement.getDefinition(), Map.of(), Map.of(), ElementState.NOT_PRESENT);
122 instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), acElement.getId(),
123 new ToscaServiceTemplate(), Map.of(), Map.of(), ElementState.NOT_PRESENT);
124 compositionElementTarget = CacheProvider.changeStateToNew(compositionElementTarget);
125 instanceElementMigrate = CacheProvider.changeStateToNew(instanceElementMigrate);
128 listener.migratePrecheck(messageId, compositionElement, compositionElementTarget,
129 instanceElement, instanceElementMigrate);
132 for (var elementId : toDelete) {
133 var compositionDtoTarget =
134 new CompositionElementDto(compositionTargetId,
135 automationComposition.getElements().get(elementId).getDefinition(),
136 Map.of(), Map.of(), ElementState.REMOVED);
137 var instanceDtoTarget =
138 new InstanceElementDto(automationComposition.getInstanceId(), elementId,
139 null, Map.of(), Map.of(), ElementState.REMOVED);
141 listener.migratePrecheck(messageId, compositionElementMap.get(elementId), compositionDtoTarget,
142 instanceElementMap.get(elementId), instanceDtoTarget);
147 * Handle AutomationComposition Prepare message.
149 * @param acPrepareMsg the AutomationCompositionPrepare message
151 public void handleAcPrepare(AutomationCompositionPrepare acPrepareMsg) {
152 if (acPrepareMsg.isPreDeploy()) {
153 for (var participantPrepare : acPrepareMsg.getParticipantList()) {
154 if (cacheProvider.getParticipantId().equals(participantPrepare.getParticipantId())) {
155 cacheProvider.initializeAutomationComposition(acPrepareMsg.getCompositionId(),
156 acPrepareMsg.getAutomationCompositionId(), participantPrepare, DeployState.UNDEPLOYED,
158 callParticipanPrepare(acPrepareMsg.getMessageId(), participantPrepare.getAcElementList(),
159 acPrepareMsg.getAutomationCompositionId());
163 var automationComposition =
164 cacheProvider.getAutomationComposition(acPrepareMsg.getAutomationCompositionId());
165 automationComposition.setSubState(SubState.REVIEWING);
166 callParticipanReview(acPrepareMsg.getMessageId(), automationComposition);
170 private void callParticipanPrepare(UUID messageId, List<AcElementDeploy> acElementList, UUID instanceId) {
171 var automationComposition = cacheProvider.getAutomationComposition(instanceId);
172 for (var elementDeploy : acElementList) {
173 var element = automationComposition.getElements().get(elementDeploy.getId());
174 var compositionInProperties = cacheProvider
175 .getCommonProperties(automationComposition.getCompositionId(), element.getDefinition());
176 var compositionElement = cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(),
177 element, compositionInProperties);
178 var instanceElement = new InstanceElementDto(instanceId, elementDeploy.getId(),
179 elementDeploy.getToscaServiceTemplateFragment(),
180 elementDeploy.getProperties(), element.getOutProperties());
181 listener.prepare(messageId, compositionElement, instanceElement);
185 private void callParticipanReview(UUID messageId, AutomationComposition automationComposition) {
186 for (var element : automationComposition.getElements().values()) {
187 var compositionInProperties = cacheProvider
188 .getCommonProperties(automationComposition.getCompositionId(), element.getDefinition());
189 element.setSubState(SubState.REVIEWING);
190 var compositionElement = cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(),
191 element, compositionInProperties);
192 var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(),
193 null, element.getProperties(), element.getOutProperties());
194 listener.review(messageId, compositionElement, instanceElement);