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