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
10 * http://www.apache.org/licenses/LICENSE-2.0
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========================================================================
20 package com.oransc.rappmanager.acm.service;
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;
54 @RequiredArgsConstructor
55 public class AcmDeployer implements RappDeployer {
57 Logger logger = LoggerFactory.getLogger(AcmDeployer.class);
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;
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());
74 public void primeACMComposition(UUID compositionId, PrimeOrder primeOrder) {
75 AcTypeStateUpdate acTypeStateUpdate = new AcTypeStateUpdate();
76 acTypeStateUpdate.setPrimeOrder(primeOrder);
77 automationCompositionDefinitionApiClient.compositionDefinitionPriming(compositionId, UUID.randomUUID(),
81 public CommissioningResponse createComposition(String compositionPayload) {
82 CommissioningResponse commissioningResponse = null;
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);
91 return commissioningResponse;
94 public CommissioningResponse deleteComposition(UUID compositionId) {
96 return automationCompositionDefinitionApiClient.deleteCompositionDefinition(compositionId,
98 } catch (Exception e) {
99 logger.warn("Error in deleting composition {}", compositionId, e);
104 boolean isCompositionInstanceStateEquals(UUID compositionId, UUID compositionIntanceId, DeployState deployState) {
105 return automationCompositionInstanceApiClient.getCompositionInstance(compositionId, compositionIntanceId,
106 UUID.randomUUID()).getDeployState().equals(deployState);
109 boolean waitForCompositionInstanceTargetState(UUID compositionId, RappInstance rappInstance,
110 DeployState deployState) {
111 boolean targetInstanceStateTransition = false;
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(),
117 sendRappInstanceStateEvent(rappInstance, deployState);
118 logger.info("Composition instance {} state is {}", rappInstance.getAcm().getAcmInstanceId(),
120 targetInstanceStateTransition = true;
123 TimeUnit.SECONDS.sleep(acmConfiguration.getRetryInterval());
126 } catch (Exception e) {
127 logger.warn("Unable to get composition instance state for composition {}", compositionId, e);
128 Thread.currentThread().interrupt();
130 return targetInstanceStateTransition;
134 public boolean deployRappInstance(Rapp rapp, RappInstance rappInstance) {
136 String instantiationPayload =
137 rappCsarConfigurationHandler.getInstantiationPayload(rapp, rappInstance.getAcm(),
138 rapp.getCompositionId());
139 AutomationComposition automationComposition =
140 gson.fromJson(instantiationPayload, AutomationComposition.class);
141 if (rappInstance.isDMEEnabled()) {
142 dmeAcmInterceptor.injectAutomationComposition(automationComposition, rapp, rappInstance);
145 InstantiationResponse instantiationResponse =
146 automationCompositionInstanceApiClient.createCompositionInstance(rapp.getCompositionId(),
147 gson.toJson(automationComposition), UUID.randomUUID());
148 if (instantiationResponse.getInstanceId() != null) {
149 rappInstance.getAcm().setAcmInstanceId(instantiationResponse.getInstanceId());
150 updateACMInstanceState(rapp.getCompositionId(), rappInstance.getAcm(), DeployOrder.DEPLOY);
153 } catch (Exception e) {
154 logger.warn("Error in deploying Rapp", e);
156 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMDEPLOYFAILED);
157 rappInstance.setReason("Unable to deploy ACM");
162 public boolean undeployRappInstance(Rapp rapp, RappInstance rappInstance) {
163 AutomationComposition automationComposition =
164 automationCompositionInstanceApiClient.getCompositionInstance(rapp.getCompositionId(),
165 rappInstance.getAcm().getAcmInstanceId(), UUID.randomUUID());
166 if (automationComposition.getDeployState().equals(DeployState.DEPLOYED) && automationComposition.getLockState()
167 .equals(LockState.LOCKED)) {
168 updateACMInstanceState(rapp.getCompositionId(), rappInstance.getAcm(), DeployOrder.UNDEPLOY);
169 if (waitForCompositionInstanceTargetState(rapp.getCompositionId(), rappInstance, DeployState.UNDEPLOYED)) {
170 automationCompositionInstanceApiClient.deleteCompositionInstance(
171 automationComposition.getCompositionId(), automationComposition.getInstanceId(),
173 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMUNDEPLOYED);
177 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMUNDEPLOYFAILED);
178 rappInstance.setReason("Unable to undeploy ACM");
183 public boolean primeRapp(Rapp rapp) {
184 logger.info("Priming rapp {}", rapp.getName());
186 String compositionPayload = rappCsarConfigurationHandler.getAcmCompositionPayload(rapp);
187 CommissioningResponse commissioningResponse = createComposition(compositionPayload);
188 if (commissioningResponse != null && commissioningResponse.getCompositionId() != null) {
189 rapp.setCompositionId(commissioningResponse.getCompositionId());
190 logger.info("Priming automation Composition");
191 primeACMComposition(commissioningResponse.getCompositionId(), PrimeOrder.PRIME);
194 logger.warn("Failed to create automation composition");
196 } catch (Exception e) {
197 logger.warn("Error in creating automation composition", e);
199 rapp.setReason("Unable to create automation composition");
204 public boolean deprimeRapp(Rapp rapp) {
206 primeACMComposition(rapp.getCompositionId(), PrimeOrder.DEPRIME);
207 if (waitForCompositionTargetState(rapp.getCompositionId(), AcTypeState.COMMISSIONED)) {
208 CommissioningResponse commissioningResponse = deleteComposition(rapp.getCompositionId());
209 if (commissioningResponse != null) {
210 rapp.setCompositionId(null);
214 } catch (Exception e) {
215 logger.warn("Failed deprime automation composition", e);
217 rapp.setReason("Unable to delete automation composition");
221 boolean waitForCompositionTargetState(UUID compositionId, AcTypeState acTypeState) {
222 boolean targetCompositionStateTransition = false;
224 for (int i = 0; i < acmConfiguration.getMaxRetries(); i++) {
225 logger.debug("Composition state check {}", i + 1);
226 if (isCompositionStateEquals(compositionId, acTypeState)) {
227 logger.debug("Composition {} state is {}", compositionId, acTypeState);
228 targetCompositionStateTransition = true;
231 TimeUnit.SECONDS.sleep(acmConfiguration.getRetryInterval());
234 } catch (Exception e) {
235 logger.warn("Unable to get composition state for composition {}", compositionId, e);
236 Thread.currentThread().interrupt();
238 return targetCompositionStateTransition;
241 boolean isCompositionStateEquals(UUID compositionId, AcTypeState acTypeState) {
242 return automationCompositionDefinitionApiClient.getCompositionDefinition(compositionId, UUID.randomUUID())
243 .getState().equals(acTypeState);
246 public void syncRappInstanceStatus(UUID compositionId, RappInstance rappInstance) {
247 if (rappInstance.getAcm().getAcmInstanceId() != null) {
249 AutomationComposition compositionInstance =
250 automationCompositionInstanceApiClient.getCompositionInstance(compositionId,
251 rappInstance.getAcm().getAcmInstanceId(), UUID.randomUUID());
252 sendRappInstanceStateEvent(rappInstance, compositionInstance.getDeployState());
253 } catch (RestClientException exception) {
254 logger.warn("Unable to get the ACM details for rapp instance {}", rappInstance.getRappInstanceId());
259 void sendRappInstanceStateEvent(RappInstance rappInstance, DeployState deployState) {
260 if (deployState.equals(DeployState.DEPLOYED)) {
261 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMDEPLOYED);
262 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEDEPLOYED);
263 } else if (deployState.equals(DeployState.UNDEPLOYED)) {
264 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMUNDEPLOYED);
265 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEUNDEPLOYED);
266 } else if (deployState.equals(DeployState.DEPLOYING)) {
267 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DEPLOYING);
268 } else if (deployState.equals(DeployState.UNDEPLOYING)) {
269 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.UNDEPLOYING);