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