4c5baf6fd718a925edd564de4e5d04b13be5e34f
[policy/clamp.git] /
1 /*-
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
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.intermediary.handler;
22
23 import java.util.List;
24 import java.util.Map;
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.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40 import org.springframework.stereotype.Component;
41
42 @Component
43 @RequiredArgsConstructor
44 public class AcSubStateHandler {
45
46     private static final Logger LOGGER = LoggerFactory.getLogger(AcSubStateHandler.class);
47
48     private final CacheProvider cacheProvider;
49     private final ThreadHandler listener;
50
51     /**
52      * Handles AutomationComposition Migration Precheck.
53      *
54      * @param migrationMsg the AutomationCompositionMigration
55      */
56     public void handleAcMigrationPrecheck(AutomationCompositionMigration migrationMsg) {
57         if (migrationMsg.getAutomationCompositionId() == null || migrationMsg.getCompositionTargetId() == null) {
58             return;
59         }
60
61         var automationComposition = cacheProvider.getAutomationComposition(migrationMsg.getAutomationCompositionId());
62         if (automationComposition == null) {
63             LOGGER.debug("Automation composition {} does not use this participant",
64                     migrationMsg.getAutomationCompositionId());
65             return;
66         }
67         automationComposition.setSubState(SubState.MIGRATION_PRECHECKING);
68         for (var participantDeploy : migrationMsg.getParticipantUpdatesList()) {
69             if (cacheProvider.getParticipantId().equals(participantDeploy.getParticipantId())) {
70
71                 callParticipantMigratePrecheck(migrationMsg.getMessageId(), participantDeploy.getAcElementList(),
72                     automationComposition, migrationMsg.getCompositionTargetId());
73             }
74         }
75     }
76
77     private void callParticipantMigratePrecheck(UUID messageId, List<AcElementDeploy> acElements,
78             AutomationComposition automationComposition, UUID compositionTargetId) {
79         var compositionElementMap = cacheProvider.getCompositionElementDtoMap(automationComposition);
80         var instanceElementMap = cacheProvider.getInstanceElementDtoMap(automationComposition);
81         var acElementList = automationComposition.getElements();
82         for (var acElement : acElements) {
83             var element = acElementList.get(acElement.getId());
84             if (element != null) {
85                 element.setSubState(SubState.MIGRATION_PRECHECKING);
86             }
87         }
88         var acCopyMigrateTo = new AutomationComposition(automationComposition);
89         var acElementCopyList = acCopyMigrateTo.getElements();
90         for (var acElement : acElements) {
91             var element = acElementCopyList.get(acElement.getId());
92             if (element != null) {
93                 AcmUtils.recursiveMerge(element.getProperties(), acElement.getProperties());
94                 element.setDefinition(acElement.getDefinition());
95             } else {
96                 element = CacheProvider.createAutomationCompositionElement(acElement);
97                 element.setSubState(SubState.MIGRATION_PRECHECKING);
98                 acElementCopyList.put(element.getId(), element);
99             }
100         }
101         var toDelete = acElementCopyList.values().stream()
102                 .filter(el -> !SubState.MIGRATION_PRECHECKING.equals(el.getSubState()))
103                 .map(AutomationCompositionElement::getId)
104                 .toList();
105         toDelete.forEach(acElementCopyList::remove);
106
107         var compositionElementTargetMap = cacheProvider.getCompositionElementDtoMap(acCopyMigrateTo,
108             compositionTargetId);
109         var instanceElementMigrateMap = cacheProvider.getInstanceElementDtoMap(acCopyMigrateTo);
110
111         for (var acElement : acElements) {
112             var compositionElement = compositionElementMap.get(acElement.getId());
113             var compositionElementTarget = compositionElementTargetMap.get(acElement.getId());
114             var instanceElement = instanceElementMap.get(acElement.getId());
115             var instanceElementMigrate = instanceElementMigrateMap.get(acElement.getId());
116
117             if (instanceElement == null) {
118                 // new element scenario
119                 compositionElement = new CompositionElementDto(automationComposition.getCompositionId(),
120                         acElement.getDefinition(), Map.of(), Map.of(), ElementState.NOT_PRESENT);
121                 instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), acElement.getId(),
122                         Map.of(), Map.of(), ElementState.NOT_PRESENT);
123                 compositionElementTarget = CacheProvider.changeStateToNew(compositionElementTarget);
124                 instanceElementMigrate = CacheProvider.changeStateToNew(instanceElementMigrate);
125             }
126
127             listener.migratePrecheck(messageId, compositionElement, compositionElementTarget,
128                     instanceElement, instanceElementMigrate);
129         }
130
131         for (var elementId : toDelete) {
132             var compositionDtoTarget =
133                     new CompositionElementDto(compositionTargetId,
134                             automationComposition.getElements().get(elementId).getDefinition(),
135                             Map.of(), Map.of(), ElementState.REMOVED);
136             var instanceDtoTarget =
137                     new InstanceElementDto(automationComposition.getInstanceId(), elementId,
138                             Map.of(), Map.of(), ElementState.REMOVED);
139
140             listener.migratePrecheck(messageId, compositionElementMap.get(elementId), compositionDtoTarget,
141                     instanceElementMap.get(elementId), instanceDtoTarget);
142         }
143     }
144
145     /**
146      * Handle AutomationComposition Prepare message.
147      *
148      * @param acPrepareMsg the AutomationCompositionPrepare message
149      */
150     public void handleAcPrepare(AutomationCompositionPrepare acPrepareMsg) {
151         if (acPrepareMsg.isPreDeploy()) {
152             for (var participantPrepare : acPrepareMsg.getParticipantList()) {
153                 if (cacheProvider.getParticipantId().equals(participantPrepare.getParticipantId())) {
154                     cacheProvider.initializeAutomationComposition(acPrepareMsg.getCompositionId(),
155                         acPrepareMsg.getAutomationCompositionId(), participantPrepare, DeployState.UNDEPLOYED,
156                         SubState.PREPARING);
157                     callParticipanPrepare(acPrepareMsg.getMessageId(), participantPrepare.getAcElementList(),
158                         acPrepareMsg.getAutomationCompositionId());
159                 }
160             }
161         } else {
162             var automationComposition =
163                 cacheProvider.getAutomationComposition(acPrepareMsg.getAutomationCompositionId());
164             automationComposition.setSubState(SubState.REVIEWING);
165             callParticipanReview(acPrepareMsg.getMessageId(), automationComposition);
166         }
167     }
168
169     private void callParticipanPrepare(UUID messageId, List<AcElementDeploy> acElementList, UUID instanceId) {
170         var automationComposition = cacheProvider.getAutomationComposition(instanceId);
171         for (var elementDeploy : acElementList) {
172             var element = automationComposition.getElements().get(elementDeploy.getId());
173             var compositionInProperties = cacheProvider
174                 .getCommonProperties(automationComposition.getCompositionId(), element.getDefinition());
175             var compositionElement = cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(),
176                 element, compositionInProperties);
177             var instanceElement = new InstanceElementDto(instanceId, elementDeploy.getId(),
178                 elementDeploy.getProperties(), element.getOutProperties());
179             listener.prepare(messageId, compositionElement, instanceElement);
180         }
181     }
182
183     private void callParticipanReview(UUID messageId, AutomationComposition automationComposition) {
184         for (var element : automationComposition.getElements().values()) {
185             var compositionInProperties = cacheProvider
186                 .getCommonProperties(automationComposition.getCompositionId(), element.getDefinition());
187             element.setSubState(SubState.REVIEWING);
188             var compositionElement = cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(),
189                 element, compositionInProperties);
190             var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(),
191                 element.getProperties(), element.getOutProperties());
192             listener.review(messageId, compositionElement, instanceElement);
193         }
194     }
195 }