Upgrade ACM to latest release version
[nonrtric/plt/rappmanager.git] / participants / participant-impl-dme / src / main / java / org / oransc / participant / dme / handler / AutomationCompositionElementHandler.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2023 Nordix Foundation.
4  *  Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.oransc.participant.dme.handler;
23
24 import com.fasterxml.jackson.core.JsonProcessingException;
25 import jakarta.validation.Validation;
26 import jakarta.validation.ValidationException;
27 import java.lang.invoke.MethodHandles;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.UUID;
31 import java.util.concurrent.ConcurrentHashMap;
32 import java.util.stream.Collectors;
33 import lombok.AccessLevel;
34 import lombok.Getter;
35 import org.apache.http.HttpStatus;
36 import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
37 import org.onap.policy.clamp.acm.participant.intermediary.api.impl.AcElementListenerV1;
38 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
39 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
40 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
41 import org.onap.policy.clamp.models.acm.concepts.DeployState;
42 import org.onap.policy.clamp.models.acm.concepts.LockState;
43 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
44 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
45 import org.onap.policy.common.utils.coder.Coder;
46 import org.onap.policy.common.utils.coder.CoderException;
47 import org.onap.policy.common.utils.coder.StandardCoder;
48 import org.onap.policy.models.base.PfModelException;
49 import org.oransc.participant.dme.exception.DmeException;
50 import org.oransc.participant.dme.models.ConfigurationEntity;
51 import org.oransc.participant.dme.models.DataConsumerEntity;
52 import org.oransc.participant.dme.models.DataProducerEntity;
53 import org.oransc.participant.dme.models.InfoTypeEntity;
54 import org.oransc.participant.dme.restclient.AcDmeClient;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57 import org.springframework.stereotype.Component;
58
59 @Component
60 public class AutomationCompositionElementHandler extends AcElementListenerV1 {
61
62     private static final Coder CODER = new StandardCoder();
63
64     private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
65
66     private final AcDmeClient acDmeClient;
67
68     // Map of acElement Id and DME services
69     @Getter(AccessLevel.PACKAGE)
70     private final Map<UUID, ConfigurationEntity> configRequestMap = new ConcurrentHashMap<>();
71
72     public AutomationCompositionElementHandler(ParticipantIntermediaryApi intermediaryApi, AcDmeClient acDmeClient) {
73         super(intermediaryApi);
74         this.acDmeClient = acDmeClient;
75     }
76
77     @Override
78     public void undeploy(UUID automationCompositionId, UUID automationCompositionElementId) throws DmeException {
79         var configurationEntity = configRequestMap.get(automationCompositionElementId);
80         if (configurationEntity != null && acDmeClient.isDmeHealthy()) {
81             if (configurationEntity.getDataConsumerEntities() != null) {
82                 acDmeClient.deleteDataConsumer(configurationEntity.getDataConsumerEntities().stream()
83                                                        .map(DataConsumerEntity::getDataConsumerId)
84                                                        .collect(Collectors.toSet()));
85             }
86             if (configurationEntity.getDataProducerEntities() != null) {
87                 acDmeClient.deleteDataProducer(configurationEntity.getDataProducerEntities().stream()
88                                                        .map(DataProducerEntity::getDataProducerId)
89                                                        .collect(Collectors.toSet()));
90             }
91             configRequestMap.remove(automationCompositionElementId);
92             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
93                     automationCompositionElementId, DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR,
94                     "Undeployed");
95         } else {
96             LOGGER.warn("Failed to connect with DME. Service configuration is: {}", configurationEntity);
97             throw new DmeException(HttpStatus.SC_SERVICE_UNAVAILABLE, "Unable to connect with DME");
98         }
99     }
100
101     @Override
102     public void deploy(UUID automationCompositionId, AcElementDeploy element, Map<String, Object> properties)
103             throws DmeException {
104         try {
105             var configurationEntity = CODER.convert(properties, ConfigurationEntity.class);
106             var violations = Validation.buildDefaultValidatorFactory().getValidator().validate(configurationEntity);
107             if (violations.isEmpty()) {
108                 if (acDmeClient.isDmeHealthy()) {
109                     if (configurationEntity.getInfoTypeEntities() != null) {
110                         acDmeClient.createInfoType(configurationEntity.getInfoTypeEntities().stream().collect(
111                                 Collectors.toMap(InfoTypeEntity::getInfoTypeId, InfoTypeEntity::getPayload)));
112                     }
113                     if (configurationEntity.getDataProducerEntities() != null) {
114                         acDmeClient.createDataProducer(configurationEntity.getDataProducerEntities().stream().collect(
115                                 Collectors.toMap(DataProducerEntity::getDataProducerId,
116                                         DataProducerEntity::getPayload)));
117                     }
118                     if (configurationEntity.getDataConsumerEntities() != null) {
119                         acDmeClient.createDataConsumer(configurationEntity.getDataConsumerEntities().stream().collect(
120                                 Collectors.toMap(DataConsumerEntity::getDataConsumerId,
121                                         DataConsumerEntity::getPayload)));
122                     }
123
124                     configRequestMap.put(element.getId(), configurationEntity);
125                     intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
126                             DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed");
127                 } else {
128                     intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
129                             DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Unable to connect with DME ");
130                     throw new DmeException(HttpStatus.SC_SERVICE_UNAVAILABLE, "Unable to connect with DME");
131                 }
132             } else {
133                 LOGGER.error("Violations found in the config request parameters: {}", violations);
134                 throw new ValidationException("Constraint violations in the config request");
135             }
136         } catch (JsonProcessingException | ValidationException | CoderException | DmeException e) {
137             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
138                     DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, e.getMessage());
139             throw new DmeException(HttpStatus.SC_BAD_REQUEST, "Invalid Configuration", e);
140         }
141     }
142
143     @Override
144     public void lock(UUID instanceId, UUID elementId) {
145         intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, null, LockState.LOCKED,
146                 StateChangeResult.NO_ERROR, "Locked");
147     }
148
149     @Override
150     public void unlock(UUID instanceId, UUID elementId) {
151         intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, null, LockState.UNLOCKED,
152                 StateChangeResult.NO_ERROR, "Unlocked");
153     }
154
155     @Override
156     public void delete(UUID instanceId, UUID elementId) {
157         intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, DeployState.DELETED, null,
158                 StateChangeResult.NO_ERROR, "Deleted");
159     }
160
161     @Override
162     public void update(UUID instanceId, AcElementDeploy element, Map<String, Object> properties) {
163         intermediaryApi.updateAutomationCompositionElementState(instanceId, element.getId(), DeployState.DEPLOYED, null,
164                 StateChangeResult.NO_ERROR, "Update not supported");
165     }
166
167     @Override
168     public void prime(UUID compositionId, List<AutomationCompositionElementDefinition> elementDefinitionList) {
169         intermediaryApi.updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed");
170     }
171
172     @Override
173     public void deprime(UUID compositionId) {
174         intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR,
175                 "Deprimed");
176     }
177
178     @Override
179     public void handleRestartComposition(UUID compositionId,
180             List<AutomationCompositionElementDefinition> elementDefinitionList, AcTypeState state) {
181         var finalState = AcTypeState.PRIMED.equals(state) || AcTypeState.PRIMING.equals(state) ? AcTypeState.PRIMED
182                                  : AcTypeState.COMMISSIONED;
183         intermediaryApi.updateCompositionState(compositionId, finalState, StateChangeResult.NO_ERROR, "Restarted");
184     }
185
186     @Override
187     public void handleRestartInstance(UUID automationCompositionId, AcElementDeploy element,
188             Map<String, Object> properties, DeployState deployState, LockState lockState) throws PfModelException {
189         if (DeployState.DEPLOYING.equals(deployState)) {
190             deploy(automationCompositionId, element, properties);
191             return;
192         }
193         if (DeployState.UNDEPLOYING.equals(deployState) || DeployState.DEPLOYED.equals(deployState)
194                     || DeployState.UPDATING.equals(deployState)) {
195             try {
196                 var configurationEntity = CODER.convert(properties, ConfigurationEntity.class);
197                 configRequestMap.put(element.getId(), configurationEntity);
198             } catch (ValidationException | CoderException e) {
199                 throw new DmeException(HttpStatus.SC_BAD_REQUEST, "Invalid Configuration", e);
200             }
201         }
202         if (DeployState.UNDEPLOYING.equals(deployState)) {
203             undeploy(automationCompositionId, element.getId());
204             return;
205         }
206         deployState = AcmUtils.deployCompleted(deployState);
207         lockState = AcmUtils.lockCompleted(deployState, lockState);
208         intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), deployState,
209                 lockState, StateChangeResult.NO_ERROR, "Restarted");
210     }
211
212     @Override
213     public void migrate(UUID automationCompositionId, AcElementDeploy element, UUID compositionTargetId,
214             Map<String, Object> properties) {
215         intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
216                 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated");
217     }
218 }