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
9 * http://www.apache.org/licenses/LICENSE-2.0
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========================================================================
19 package com.oransc.rappmanager.acm.service;
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;
50 @RequiredArgsConstructor
51 public class AcmDeployer implements RappDeployer {
53 Logger logger = LoggerFactory.getLogger(AcmDeployer.class);
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;
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());
68 public void primeACMComposition(UUID compositionId, PrimeOrder primeOrder) {
69 AcTypeStateUpdate acTypeStateUpdate = new AcTypeStateUpdate();
70 acTypeStateUpdate.setPrimeOrder(primeOrder);
71 automationCompositionDefinitionApiClient.compositionDefinitionPriming(compositionId, UUID.randomUUID(),
75 public CommissioningResponse createComposition(String compositionPayload) {
76 CommissioningResponse commissioningResponse = null;
78 commissioningResponse =
79 automationCompositionDefinitionApiClient.createCompositionDefinitions(compositionPayload,
81 } catch (Exception e) {
82 logger.warn("Error in creating composition", e);
84 return commissioningResponse;
87 public CommissioningResponse deleteComposition(UUID compositionId) {
89 return automationCompositionDefinitionApiClient.deleteCompositionDefinition(compositionId,
91 } catch (Exception e) {
92 logger.warn("Error in deleting composition {}", compositionId, e);
97 boolean isCompositionInstanceStateEquals(UUID compositionId, UUID compositionIntanceId, DeployState deployState) {
98 return automationCompositionInstanceApiClient.getCompositionInstance(compositionId, compositionIntanceId,
99 UUID.randomUUID()).getDeployState().equals(deployState);
102 boolean waitForCompositionInstanceTargetState(UUID compositionId, RappInstance rappInstance,
103 DeployState deployState) {
104 boolean targetInstanceStateTransition = false;
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(),
110 sendRappInstanceStateEvent(rappInstance, deployState);
111 logger.info("Composition instance {} state is {}", rappInstance.getAcm().getAcmInstanceId(),
113 targetInstanceStateTransition = true;
116 TimeUnit.SECONDS.sleep(acmConfiguration.getRetryInterval());
119 } catch (Exception e) {
120 logger.warn("Unable to get composition instance state for composition {}", compositionId, e);
121 Thread.currentThread().interrupt();
123 return targetInstanceStateTransition;
127 public boolean deployRappInstance(Rapp rapp, RappInstance rappInstance) {
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);
140 } catch (Exception e) {
141 logger.warn("Error in deploying Rapp", e);
143 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMDEPLOYFAILED);
144 rappInstance.setReason("Unable to deploy ACM");
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(),
160 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMUNDEPLOYED);
164 rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMUNDEPLOYFAILED);
165 rappInstance.setReason("Unable to undeploy ACM");
170 public boolean primeRapp(Rapp rapp) {
171 logger.info("Priming rapp {}", rapp.getName());
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);
181 logger.warn("Failed to create automation composition");
183 } catch (Exception e) {
184 logger.warn("Error in creating automation composition", e);
186 rapp.setReason("Unable to create automation composition");
191 public boolean deprimeRapp(Rapp rapp) {
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);
201 } catch (Exception e) {
202 logger.warn("Failed deprime automation composition", e);
204 rapp.setReason("Unable to delete automation composition");
208 boolean waitForCompositionTargetState(UUID compositionId, AcTypeState acTypeState) {
209 boolean targetCompositionStateTransition = false;
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;
218 TimeUnit.SECONDS.sleep(acmConfiguration.getRetryInterval());
221 } catch (Exception e) {
222 logger.warn("Unable to get composition state for composition {}", compositionId, e);
223 Thread.currentThread().interrupt();
225 return targetCompositionStateTransition;
228 boolean isCompositionStateEquals(UUID compositionId, AcTypeState acTypeState) {
229 return automationCompositionDefinitionApiClient.getCompositionDefinition(compositionId, UUID.randomUUID())
230 .getState().equals(acTypeState);
233 public void syncRappInstanceStatus(UUID compositionId, RappInstance rappInstance) {
234 if (rappInstance.getAcm().getAcmInstanceId() != null) {
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());
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);