Merge "Pass rAppInstanceId to k8s participant and create the invoker with the instanc...
[nonrtric/plt/rappmanager.git] / rapp-manager-acm / src / main / java / com / oransc / rappmanager / acm / service / AcmDeployer.java
1 /*-
2  * ============LICENSE_START======================================================================
3  * Copyright (C) 2023 Nordix Foundation. All rights reserved.
4  * Copyright (C) 2023-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  * ============LICENSE_END========================================================================
18  */
19
20 package com.oransc.rappmanager.acm.service;
21
22 import com.google.gson.Gson;
23 import com.oransc.rappmanager.acm.configuration.ACMConfiguration;
24 import com.oransc.rappmanager.acm.rest.AutomationCompositionDefinitionApiClient;
25 import com.oransc.rappmanager.acm.rest.AutomationCompositionInstanceApiClient;
26 import com.oransc.rappmanager.dme.service.DmeAcmInterceptor;
27 import com.oransc.rappmanager.models.RappDeployer;
28 import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
29 import com.oransc.rappmanager.models.rapp.Rapp;
30 import com.oransc.rappmanager.models.rapp.RappEvent;
31 import com.oransc.rappmanager.models.rappinstance.RappACMInstance;
32 import com.oransc.rappmanager.models.rappinstance.RappInstance;
33 import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine;
34 import java.util.UUID;
35 import java.util.concurrent.TimeUnit;
36 import lombok.RequiredArgsConstructor;
37 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
38 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
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.messages.rest.commissioning.AcTypeStateUpdate;
42 import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse;
43 import org.onap.policy.clamp.models.acm.messages.rest.commissioning.PrimeOrder;
44 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AcInstanceStateUpdate;
45 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
46 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse;
47 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50 import org.springframework.stereotype.Service;
51 import org.springframework.web.client.RestClientException;
52
53 @Service
54 @RequiredArgsConstructor
55 public class AcmDeployer implements RappDeployer {
56
57     Logger logger = LoggerFactory.getLogger(AcmDeployer.class);
58
59     private final AutomationCompositionDefinitionApiClient automationCompositionDefinitionApiClient;
60     private final AutomationCompositionInstanceApiClient automationCompositionInstanceApiClient;
61     private final RappCsarConfigurationHandler rappCsarConfigurationHandler;
62     private final RappInstanceStateMachine rappInstanceStateMachine;
63     private final ACMConfiguration acmConfiguration;
64     private final Gson gson;
65     private final DmeAcmInterceptor dmeAcmInterceptor;
66
67     void updateACMInstanceState(UUID compositionId, RappACMInstance rappACMInstance, DeployOrder deployOrder) {
68         AcInstanceStateUpdate acInstanceStateUpdate = new AcInstanceStateUpdate();
69         acInstanceStateUpdate.setDeployOrder(deployOrder);
70         automationCompositionInstanceApiClient.compositionInstanceState(compositionId,
71                 rappACMInstance.getAcmInstanceId(), acInstanceStateUpdate, UUID.randomUUID());
72     }
73
74     public void primeACMComposition(UUID compositionId, PrimeOrder primeOrder) {
75         AcTypeStateUpdate acTypeStateUpdate = new AcTypeStateUpdate();
76         acTypeStateUpdate.setPrimeOrder(primeOrder);
77         automationCompositionDefinitionApiClient.compositionDefinitionPriming(compositionId, UUID.randomUUID(),
78                 acTypeStateUpdate);
79     }
80
81     public CommissioningResponse createComposition(String compositionPayload) {
82         CommissioningResponse commissioningResponse = null;
83         try {
84             ToscaServiceTemplate toscaServiceTemplate = gson.fromJson(compositionPayload, ToscaServiceTemplate.class);
85             dmeAcmInterceptor.injectToscaServiceTemplate(toscaServiceTemplate);
86             commissioningResponse = automationCompositionDefinitionApiClient.createCompositionDefinitions(
87                     gson.toJson(toscaServiceTemplate), UUID.randomUUID());
88         } catch (Exception e) {
89             logger.warn("Error in creating composition", e);
90         }
91         return commissioningResponse;
92     }
93
94     public CommissioningResponse deleteComposition(UUID compositionId) {
95         try {
96             return automationCompositionDefinitionApiClient.deleteCompositionDefinition(compositionId,
97                     UUID.randomUUID());
98         } catch (Exception e) {
99             logger.warn("Error in deleting composition {}", compositionId, e);
100         }
101         return null;
102     }
103
104     boolean isCompositionInstanceStateEquals(UUID compositionId, UUID compositionIntanceId, DeployState deployState) {
105         return automationCompositionInstanceApiClient.getCompositionInstance(compositionId, compositionIntanceId,
106                 UUID.randomUUID()).getDeployState().equals(deployState);
107     }
108
109     boolean waitForCompositionInstanceTargetState(UUID compositionId, RappInstance rappInstance,
110             DeployState deployState) {
111         boolean targetInstanceStateTransition = false;
112         try {
113             for (int i = 0; i < acmConfiguration.getMaxRetries(); i++) {
114                 logger.debug("Composition instance state check {}", i + 1);
115                 if (isCompositionInstanceStateEquals(compositionId, rappInstance.getAcm().getAcmInstanceId(),
116                         deployState)) {
117                     sendRappInstanceStateEvent(rappInstance, deployState);
118                     logger.info("Composition instance {} state is {}", rappInstance.getAcm().getAcmInstanceId(),
119                             deployState);
120                     targetInstanceStateTransition = true;
121                     break;
122                 } else {
123                     TimeUnit.SECONDS.sleep(acmConfiguration.getRetryInterval());
124                 }
125             }
126         } catch (Exception e) {
127             logger.warn("Unable to get composition instance state for composition {}", compositionId, e);
128             Thread.currentThread().interrupt();
129         }
130         return targetInstanceStateTransition;
131     }
132
133     @Override
134     public boolean deployRappInstance(Rapp rapp, RappInstance rappInstance) {
135         try {
136             String instantiationPayload = rappCsarConfigurationHandler.getInstantiationPayload(rapp, rappInstance,
137                             rapp.getCompositionId());
138             AutomationComposition automationComposition =
139                     gson.fromJson(instantiationPayload, AutomationComposition.class);
140             if (rappInstance.isDMEEnabled()) {
141                 dmeAcmInterceptor.injectAutomationComposition(automationComposition, rapp, rappInstance);
142             }
143
144             InstantiationResponse instantiationResponse =
145                     automationCompositionInstanceApiClient.createCompositionInstance(rapp.getCompositionId(),
146                             gson.toJson(automationComposition), UUID.randomUUID());
147             if (instantiationResponse.getInstanceId() != null) {
148                 rappInstance.getAcm().setAcmInstanceId(instantiationResponse.getInstanceId());
149                 updateACMInstanceState(rapp.getCompositionId(), rappInstance.getAcm(), DeployOrder.DEPLOY);
150                 return true;
151             }
152         } catch (Exception e) {
153             logger.warn("Error in deploying Rapp", e);
154         }
155         rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMDEPLOYFAILED);
156         rappInstance.setReason("Unable to deploy ACM");
157         return false;
158     }
159
160     @Override
161     public boolean undeployRappInstance(Rapp rapp, RappInstance rappInstance) {
162         AutomationComposition automationComposition =
163                 automationCompositionInstanceApiClient.getCompositionInstance(rapp.getCompositionId(),
164                         rappInstance.getAcm().getAcmInstanceId(), UUID.randomUUID());
165         if (automationComposition.getDeployState().equals(DeployState.DEPLOYED) && automationComposition.getLockState()
166                                                                                            .equals(LockState.LOCKED)) {
167             updateACMInstanceState(rapp.getCompositionId(), rappInstance.getAcm(), DeployOrder.UNDEPLOY);
168             if (waitForCompositionInstanceTargetState(rapp.getCompositionId(), rappInstance, DeployState.UNDEPLOYED)) {
169                 automationCompositionInstanceApiClient.deleteCompositionInstance(
170                         automationComposition.getCompositionId(), automationComposition.getInstanceId(),
171                         UUID.randomUUID());
172                 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMUNDEPLOYED);
173                 return true;
174             }
175         }
176         rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMUNDEPLOYFAILED);
177         rappInstance.setReason("Unable to undeploy ACM");
178         return false;
179     }
180
181     @Override
182     public boolean primeRapp(Rapp rapp) {
183         logger.info("Priming rapp {}", rapp.getName());
184         try {
185             String compositionPayload = rappCsarConfigurationHandler.getAcmCompositionPayload(rapp);
186             CommissioningResponse commissioningResponse = createComposition(compositionPayload);
187             if (commissioningResponse != null && commissioningResponse.getCompositionId() != null) {
188                 rapp.setCompositionId(commissioningResponse.getCompositionId());
189                 logger.info("Priming automation Composition");
190                 primeACMComposition(commissioningResponse.getCompositionId(), PrimeOrder.PRIME);
191                 return true;
192             } else {
193                 logger.warn("Failed to create automation composition");
194             }
195         } catch (Exception e) {
196             logger.warn("Error in creating automation composition", e);
197         }
198         rapp.setReason("Unable to create automation composition");
199         return false;
200     }
201
202     @Override
203     public boolean deprimeRapp(Rapp rapp) {
204         try {
205             primeACMComposition(rapp.getCompositionId(), PrimeOrder.DEPRIME);
206             if (waitForCompositionTargetState(rapp.getCompositionId(), AcTypeState.COMMISSIONED)) {
207                 CommissioningResponse commissioningResponse = deleteComposition(rapp.getCompositionId());
208                 if (commissioningResponse != null) {
209                     rapp.setCompositionId(null);
210                     return true;
211                 }
212             }
213         } catch (Exception e) {
214             logger.warn("Failed deprime automation composition", e);
215         }
216         rapp.setReason("Unable to delete automation composition");
217         return false;
218     }
219
220     boolean waitForCompositionTargetState(UUID compositionId, AcTypeState acTypeState) {
221         boolean targetCompositionStateTransition = false;
222         try {
223             for (int i = 0; i < acmConfiguration.getMaxRetries(); i++) {
224                 logger.debug("Composition state check {}", i + 1);
225                 if (isCompositionStateEquals(compositionId, acTypeState)) {
226                     logger.debug("Composition {} state is {}", compositionId, acTypeState);
227                     targetCompositionStateTransition = true;
228                     break;
229                 } else {
230                     TimeUnit.SECONDS.sleep(acmConfiguration.getRetryInterval());
231                 }
232             }
233         } catch (Exception e) {
234             logger.warn("Unable to get composition state for composition {}", compositionId, e);
235             Thread.currentThread().interrupt();
236         }
237         return targetCompositionStateTransition;
238     }
239
240     boolean isCompositionStateEquals(UUID compositionId, AcTypeState acTypeState) {
241         return automationCompositionDefinitionApiClient.getCompositionDefinition(compositionId, UUID.randomUUID())
242                        .getState().equals(acTypeState);
243     }
244
245     public void syncRappInstanceStatus(UUID compositionId, RappInstance rappInstance) {
246         if (rappInstance.getAcm().getAcmInstanceId() != null) {
247             try {
248                 AutomationComposition compositionInstance =
249                         automationCompositionInstanceApiClient.getCompositionInstance(compositionId,
250                                 rappInstance.getAcm().getAcmInstanceId(), UUID.randomUUID());
251                 sendRappInstanceStateEvent(rappInstance, compositionInstance.getDeployState());
252             } catch (RestClientException exception) {
253                 logger.warn("Unable to get the ACM details for rapp instance {}", rappInstance.getRappInstanceId());
254             }
255         }
256     }
257
258     void sendRappInstanceStateEvent(RappInstance rappInstance, DeployState deployState) {
259         if (deployState.equals(DeployState.DEPLOYED)) {
260             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMDEPLOYED);
261             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEDEPLOYED);
262         } else if (deployState.equals(DeployState.UNDEPLOYED)) {
263             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMUNDEPLOYED);
264             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEUNDEPLOYED);
265         } else if (deployState.equals(DeployState.DEPLOYING)) {
266             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DEPLOYING);
267         } else if (deployState.equals(DeployState.UNDEPLOYING)) {
268             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.UNDEPLOYING);
269         }
270     }
271 }