ca27c82146fafebb1679489cf93f681db75708b6
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021,2022 Nordix Foundation.
4  * ================================================================================
5  * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.clamp.acm.participant.policy.main.handler;
24
25 import java.util.LinkedHashMap;
26 import java.util.Map;
27 import java.util.UUID;
28 import lombok.Setter;
29 import org.apache.http.HttpStatus;
30 import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener;
31 import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
32 import org.onap.policy.clamp.acm.participant.policy.client.PolicyApiHttpClient;
33 import org.onap.policy.clamp.acm.participant.policy.client.PolicyPapHttpClient;
34 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
35 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionOrderedState;
36 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionState;
37 import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessageType;
38 import org.onap.policy.models.base.PfModelException;
39 import org.onap.policy.models.base.PfModelRuntimeException;
40 import org.onap.policy.models.pdp.concepts.DeploymentSubGroup;
41 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.stereotype.Component;
45
46 /**
47  * This class handles implementation of automationCompositionElement updates.
48  */
49 @Component
50 public class AutomationCompositionElementHandler implements AutomationCompositionElementListener {
51
52     private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionElementHandler.class);
53     private final Map<String, String> policyTypeMap = new LinkedHashMap<>();
54     private final Map<String, String> policyMap = new LinkedHashMap<>();
55
56     private final PolicyApiHttpClient apiHttpClient;
57     private final PolicyPapHttpClient papHttpClient;
58
59     @Setter
60     private ParticipantIntermediaryApi intermediaryApi;
61
62     /**
63      * constructor.
64      *
65      * @param apiHttpClient the Policy Api Http Client
66      * @param papHttpClient the Policy Pap Http Client
67      */
68     public AutomationCompositionElementHandler(PolicyApiHttpClient apiHttpClient, PolicyPapHttpClient papHttpClient) {
69         this.papHttpClient = papHttpClient;
70         this.apiHttpClient = apiHttpClient;
71     }
72
73     /**
74      * Callback method to handle a automation composition element state change.
75      *
76      * @param automationCompositionId        the ID of the automation composition
77      * @param automationCompositionElementId the ID of the automation composition element
78      * @param currentState                   the current state of the automation composition element
79      * @param orderedState                   the state to which the automation composition element is changing to
80      */
81     @Override
82     public void automationCompositionElementStateChange(UUID automationCompositionId,
83                                                         UUID automationCompositionElementId,
84                                                         AutomationCompositionState currentState,
85                                                         AutomationCompositionOrderedState orderedState) {
86         switch (orderedState) {
87             case UNINITIALISED:
88                 try {
89                     undeployPolicies(automationCompositionElementId);
90                     deletePolicyData(automationCompositionId, automationCompositionElementId, orderedState);
91                     intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
92                         automationCompositionElementId, orderedState, AutomationCompositionState.UNINITIALISED,
93                         ParticipantMessageType.AUTOMATION_COMPOSITION_STATE_CHANGE);
94                 } catch (PfModelRuntimeException e) {
95                     LOGGER.error("Undeploying/Deleting policy failed {}", automationCompositionElementId, e);
96                 }
97                 break;
98             case PASSIVE:
99                 try {
100                     undeployPolicies(automationCompositionElementId);
101                 } catch (PfModelRuntimeException e) {
102                     LOGGER.error("Undeploying policies failed - no policies to undeploy {}",
103                         automationCompositionElementId);
104                 }
105                 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
106                     automationCompositionElementId, orderedState, AutomationCompositionState.PASSIVE,
107                     ParticipantMessageType.AUTOMATION_COMPOSITION_STATE_CHANGE);
108                 break;
109             case RUNNING:
110                 LOGGER.info("Running state is not supported");
111                 break;
112             default:
113                 LOGGER.debug("Unknown orderedstate {}", orderedState);
114                 break;
115         }
116     }
117
118     private void deletePolicyData(UUID automationCompositionId,
119                                   UUID automationCompositionElementId, AutomationCompositionOrderedState newState) {
120         // Delete all policies of this automationComposition from policy framework
121         for (var policy : policyMap.entrySet()) {
122             apiHttpClient.deletePolicy(policy.getKey(), policy.getValue());
123         }
124         policyMap.clear();
125         // Delete all policy types of this automation composition from policy framework
126         for (var policyType : policyTypeMap.entrySet()) {
127             apiHttpClient.deletePolicyType(policyType.getKey(), policyType.getValue());
128         }
129         policyTypeMap.clear();
130     }
131
132     private void deployPolicies(UUID automationCompositionId, UUID automationCompositionElementId,
133                                 AutomationCompositionOrderedState newState) {
134         var deployFailure = false;
135         // Deploy all policies of this automationComposition from Policy Framework
136         if (!policyMap.entrySet().isEmpty()) {
137             for (var policy : policyMap.entrySet()) {
138                 var deployPolicyResp = papHttpClient.handlePolicyDeployOrUndeploy(policy.getKey(), policy.getValue(),
139                         DeploymentSubGroup.Action.POST).getStatus();
140                 if (deployPolicyResp != HttpStatus.SC_ACCEPTED) {
141                     deployFailure = true;
142                 }
143             }
144             LOGGER.info("Policies deployed to {} successfully", automationCompositionElementId);
145         } else {
146             LOGGER.debug("No policies to deploy to {}", automationCompositionElementId);
147         }
148         if (! deployFailure) {
149             // Update the AC element state
150             intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
151                     automationCompositionElementId, newState, AutomationCompositionState.PASSIVE,
152                     ParticipantMessageType.AUTOMATION_COMPOSITION_STATE_CHANGE);
153         }
154     }
155
156     private void undeployPolicies(UUID automationCompositionElementId) {
157         // Undeploy all policies of this automation composition from Policy Framework
158         if (!policyMap.entrySet().isEmpty()) {
159             for (var policy : policyMap.entrySet()) {
160                 papHttpClient.handlePolicyDeployOrUndeploy(policy.getKey(), policy.getValue(),
161                     DeploymentSubGroup.Action.DELETE);
162             }
163             LOGGER.debug("Undeployed policies from {} successfully", automationCompositionElementId);
164         } else {
165             LOGGER.debug("No policies are deployed to {}", automationCompositionElementId);
166         }
167     }
168
169     /**
170      * Callback method to handle an update on automation composition element.
171      *
172      * @param automationCompositionId the automationComposition Id
173      * @param element the information on the automation composition element
174      * @param properties properties Map
175      * @throws PfModelException in case of an exception
176      */
177     @Override
178     public void automationCompositionElementUpdate(UUID automationCompositionId,
179             AutomationCompositionElement element, Map<String, Object> properties) throws PfModelException {
180         var createPolicyTypeResp = HttpStatus.SC_OK;
181         var createPolicyResp = HttpStatus.SC_OK;
182
183         var automationCompositionDefinition = element.getToscaServiceTemplateFragment();
184         if (automationCompositionDefinition.getToscaTopologyTemplate() != null) {
185             if (automationCompositionDefinition.getPolicyTypes() != null) {
186                 for (var policyType : automationCompositionDefinition.getPolicyTypes().values()) {
187                     policyTypeMap.put(policyType.getName(), policyType.getVersion());
188                 }
189                 LOGGER.info("Found Policy Types in automation composition definition: {} , Creating Policy Types",
190                     automationCompositionDefinition.getName());
191                 createPolicyTypeResp = apiHttpClient.createPolicyType(automationCompositionDefinition).getStatus();
192             }
193             if (automationCompositionDefinition.getToscaTopologyTemplate().getPolicies() != null) {
194                 for (var gotPolicyMap : automationCompositionDefinition.getToscaTopologyTemplate().getPolicies()) {
195                     for (ToscaPolicy policy : gotPolicyMap.values()) {
196                         policyMap.put(policy.getName(), policy.getVersion());
197                     }
198                 }
199                 LOGGER.info("Found Policies in automation composition definition: {} , Creating Policies",
200                     automationCompositionDefinition.getName());
201                 createPolicyResp = apiHttpClient.createPolicy(automationCompositionDefinition).getStatus();
202             }
203             if (createPolicyTypeResp == HttpStatus.SC_OK && createPolicyResp == HttpStatus.SC_OK) {
204                 LOGGER.info("PolicyTypes/Policies for the automation composition element : {} are created "
205                         + "successfully", element.getId());
206                 deployPolicies(automationCompositionId, element.getId(), element.getOrderedState());
207             } else {
208                 LOGGER.error("Creation of PolicyTypes/Policies failed. Policies will not be deployed.");
209             }
210         }
211     }
212 }