b5866d71ff7e718b4f5ea4efcf80da4d645b42e1
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2023 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.io.Closeable;
24 import java.io.IOException;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.UUID;
28 import java.util.concurrent.ConcurrentHashMap;
29 import java.util.concurrent.ExecutorService;
30 import java.util.concurrent.Executors;
31 import java.util.concurrent.Future;
32 import lombok.RequiredArgsConstructor;
33 import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener;
34 import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
35 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
36 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
37 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
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.StateChangeResult;
41 import org.onap.policy.models.base.PfModelException;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.stereotype.Component;
45
46 @Component
47 @RequiredArgsConstructor
48 public class ThreadHandler implements Closeable {
49     private static final Logger LOGGER = LoggerFactory.getLogger(ThreadHandler.class);
50
51     private final AutomationCompositionElementListener listener;
52     private final ParticipantIntermediaryApi intermediaryApi;
53     private final CacheProvider cacheProvider;
54
55     private final Map<UUID, Future> executionMap = new ConcurrentHashMap<>();
56
57     private final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
58
59     /**
60      * Handle an update on a automation composition element.
61      *
62      * @param messageId the messageId
63      * @param instanceId the automationComposition Id
64      * @param element the information on the automation composition element
65      * @param properties properties Map
66      */
67     public void deploy(UUID messageId, UUID instanceId, AcElementDeploy element, Map<String, Object> properties) {
68         cleanExecution(element.getId(), messageId);
69         var result = executor.submit(() -> this.deployProcess(instanceId, element, properties));
70         executionMap.put(element.getId(), result);
71     }
72
73     private void deployProcess(UUID instanceId, AcElementDeploy element, Map<String, Object> properties) {
74         try {
75             listener.deploy(instanceId, element, properties);
76         } catch (PfModelException e) {
77             LOGGER.error("Automation composition element deploy failed {} {}", instanceId, e.getMessage());
78             intermediaryApi.updateAutomationCompositionElementState(instanceId, element.getId(), DeployState.UNDEPLOYED,
79                     null, StateChangeResult.FAILED, "Automation composition element deploy failed");
80         }
81         executionMap.remove(element.getId());
82     }
83
84     /**
85      * Handle a automation composition element state change.
86      *
87      * @param messageId the messageId
88      * @param instanceId the automationComposition Id
89      * @param elementId the ID of the automation composition element
90      */
91     public void undeploy(UUID messageId, UUID instanceId, UUID elementId) {
92         cleanExecution(elementId, messageId);
93         var result = executor.submit(() -> this.undeployProcess(instanceId, elementId));
94         executionMap.put(elementId, result);
95     }
96
97     private void undeployProcess(UUID instanceId, UUID elementId) {
98         try {
99             listener.undeploy(instanceId, elementId);
100         } catch (PfModelException e) {
101             LOGGER.error("Automation composition element undeploy failed {} {}", instanceId, e.getMessage());
102             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, null,
103                     StateChangeResult.FAILED, "Automation composition element undeploy failed");
104         }
105         executionMap.remove(elementId);
106     }
107
108     /**
109      * Handle a automation composition element lock.
110      *
111      * @param messageId the messageId
112      * @param instanceId the automationComposition Id
113      * @param elementId the ID of the automation composition element
114      */
115     public void lock(UUID messageId, UUID instanceId, UUID elementId) {
116         cleanExecution(elementId, messageId);
117         var result = executor.submit(() -> this.lockProcess(instanceId, elementId));
118         executionMap.put(elementId, result);
119     }
120
121     private void lockProcess(UUID instanceId, UUID elementId) {
122         try {
123             listener.lock(instanceId, elementId);
124         } catch (PfModelException e) {
125             LOGGER.error("Automation composition element lock failed {} {}", instanceId, e.getMessage());
126             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, null, LockState.UNLOCKED,
127                     StateChangeResult.FAILED, "Automation composition element lock failed");
128         }
129         executionMap.remove(elementId);
130     }
131
132     /**
133      * Handle a automation composition element unlock.
134      *
135      * @param messageId the messageId
136      * @param instanceId the automationComposition Id
137      * @param elementId the ID of the automation composition element
138      */
139     public void unlock(UUID messageId, UUID instanceId, UUID elementId) {
140         cleanExecution(elementId, messageId);
141         var result = executor.submit(() -> this.unlockProcess(instanceId, elementId));
142         executionMap.put(elementId, result);
143     }
144
145     private void unlockProcess(UUID instanceId, UUID elementId) {
146         try {
147             listener.unlock(instanceId, elementId);
148         } catch (PfModelException e) {
149             LOGGER.error("Automation composition element unlock failed {} {}", instanceId, e.getMessage());
150             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, null, LockState.LOCKED,
151                     StateChangeResult.FAILED, "Automation composition element unlock failed");
152         }
153         executionMap.remove(elementId);
154     }
155
156     /**
157      * Handle a automation composition element delete.
158      *
159      * @param messageId the messageId
160      * @param instanceId the automationComposition Id
161      * @param elementId the ID of the automation composition element
162      */
163     public void delete(UUID messageId, UUID instanceId, UUID elementId) {
164         cleanExecution(elementId, messageId);
165         var result = executor.submit(() -> this.deleteProcess(instanceId, elementId));
166         executionMap.put(elementId, result);
167     }
168
169     private void deleteProcess(UUID instanceId, UUID elementId) {
170         try {
171             listener.delete(instanceId, elementId);
172         } catch (PfModelException e) {
173             LOGGER.error("Automation composition element delete failed {} {}", instanceId, e.getMessage());
174             intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, DeployState.UNDEPLOYED, null,
175                     StateChangeResult.FAILED, "Automation composition element delete failed");
176         }
177         executionMap.remove(elementId);
178     }
179
180     /**
181      * Handle a automation composition element properties update.
182      *
183      * @param messageId the messageId
184      * @param instanceId the automationComposition Id
185      * @param element the information on the automation composition element
186      * @param properties properties Map
187      */
188     public void update(UUID messageId, UUID instanceId, AcElementDeploy element, Map<String, Object> properties) {
189         cleanExecution(element.getId(), messageId);
190         var result = executor.submit(() -> this.updateProcess(instanceId, element, properties));
191         executionMap.put(element.getId(), result);
192     }
193
194     private void updateProcess(UUID instanceId, AcElementDeploy element, Map<String, Object> properties) {
195         try {
196             listener.update(instanceId, element, properties);
197         } catch (PfModelException e) {
198             LOGGER.error("Automation composition element update failed {} {}", instanceId, e.getMessage());
199             intermediaryApi.updateAutomationCompositionElementState(instanceId, element.getId(), DeployState.DEPLOYED,
200                     null, StateChangeResult.FAILED, "Automation composition element update failed");
201         }
202         executionMap.remove(element.getId());
203     }
204
205     private void cleanExecution(UUID execIdentificationId, UUID messageId) {
206         var process = executionMap.get(execIdentificationId);
207         if (process != null) {
208             if (!process.isDone()) {
209                 process.cancel(true);
210             }
211             executionMap.remove(execIdentificationId);
212         }
213         cacheProvider.getMsgIdentification().put(execIdentificationId, messageId);
214     }
215
216     /**
217      * Handles prime a Composition Definition.
218      *
219      * @param messageId the messageId
220      * @param compositionId the compositionId
221      * @param list the list of AutomationCompositionElementDefinition
222      */
223     public void prime(UUID messageId, UUID compositionId, List<AutomationCompositionElementDefinition> list) {
224         cleanExecution(compositionId, messageId);
225         var result = executor.submit(() -> this.primeProcess(compositionId, list));
226         executionMap.put(compositionId, result);
227     }
228
229     private void primeProcess(UUID compositionId, List<AutomationCompositionElementDefinition> list) {
230         try {
231             listener.prime(compositionId, list);
232             executionMap.remove(compositionId);
233         } catch (PfModelException e) {
234             LOGGER.error("Composition Defintion prime failed {} {}", compositionId, e.getMessage());
235             intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.FAILED,
236                     "Composition Defintion prime failed");
237         }
238     }
239
240     /**
241      * Handles deprime a Composition Definition.
242      *
243      * @param messageId the messageId
244      * @param compositionId the compositionId
245      */
246     public void deprime(UUID messageId, UUID compositionId) {
247         cleanExecution(compositionId, messageId);
248         var result = executor.submit(() -> this.deprimeProcess(compositionId));
249         executionMap.put(compositionId, result);
250     }
251
252     private void deprimeProcess(UUID compositionId) {
253         try {
254             listener.deprime(compositionId);
255             executionMap.remove(compositionId);
256         } catch (PfModelException e) {
257             LOGGER.error("Composition Defintion deprime failed {} {}", compositionId, e.getMessage());
258             intermediaryApi.updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.FAILED,
259                     "Composition Defintion deprime failed");
260         }
261     }
262
263
264     /**
265      * Closes this stream and releases any system resources associated
266      * with it. If the stream is already closed then invoking this
267      * method has no effect.
268      *
269      * @throws IOException if an I/O error occurs
270      */
271     @Override
272     public void close() throws IOException {
273         executor.shutdown();
274     }
275 }