2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021-2023 Nordix Foundation.
4 * Modifications Copyright (C) 2021 AT&T Intellectual Property. 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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.clamp.acm.runtime.instantiation;
24 import java.util.UUID;
25 import java.util.stream.Collectors;
26 import javax.validation.Valid;
27 import javax.ws.rs.core.Response;
28 import javax.ws.rs.core.Response.Status;
29 import lombok.AllArgsConstructor;
30 import org.onap.policy.clamp.acm.runtime.participants.AcmParticipantProvider;
31 import org.onap.policy.clamp.acm.runtime.supervision.SupervisionAcHandler;
32 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
33 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
34 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
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.concepts.NodeTemplateState;
38 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AcInstanceStateUpdate;
39 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse;
40 import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
41 import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver;
42 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
43 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
44 import org.onap.policy.common.parameters.BeanValidationResult;
45 import org.onap.policy.common.parameters.ObjectValidationResult;
46 import org.onap.policy.common.parameters.ValidationStatus;
47 import org.onap.policy.models.base.PfModelRuntimeException;
48 import org.springframework.stereotype.Service;
49 import org.springframework.transaction.annotation.Transactional;
52 * This class is dedicated to the Instantiation of Commissioned automation composition.
57 public class AutomationCompositionInstantiationProvider {
58 private static final String DO_NOT_MATCH = " do not match with ";
60 private final AutomationCompositionProvider automationCompositionProvider;
61 private final AcDefinitionProvider acDefinitionProvider;
62 private final AcInstanceStateResolver acInstanceStateResolver;
63 private final SupervisionAcHandler supervisionAcHandler;
64 private final AcmParticipantProvider acmParticipantProvider;
67 * Create automation composition.
69 * @param compositionId The UUID of the automation composition definition
70 * @param automationComposition the automation composition
71 * @return the result of the instantiation operation
73 public InstantiationResponse createAutomationComposition(UUID compositionId,
74 AutomationComposition automationComposition) {
75 if (!compositionId.equals(automationComposition.getCompositionId())) {
76 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
77 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
79 var checkAutomationCompositionOpt =
80 automationCompositionProvider.findAutomationComposition(automationComposition.getKey().asIdentifier());
81 if (checkAutomationCompositionOpt.isPresent()) {
82 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
83 automationComposition.getKey().asIdentifier() + " already defined");
86 var validationResult = validateAutomationComposition(automationComposition);
87 if (!validationResult.isValid()) {
88 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult());
90 automationComposition = automationCompositionProvider.createAutomationComposition(automationComposition);
92 var response = new InstantiationResponse();
93 response.setInstanceId(automationComposition.getInstanceId());
94 response.setAffectedAutomationComposition(automationComposition.getKey().asIdentifier());
100 * Update automation composition.
102 * @param compositionId The UUID of the automation composition definition
103 * @param automationComposition the automation composition
104 * @return the result of the update
106 public InstantiationResponse updateAutomationComposition(UUID compositionId,
107 AutomationComposition automationComposition) {
108 var response = new InstantiationResponse();
109 var instanceId = automationComposition.getInstanceId();
110 var acToUpdate = automationCompositionProvider.getAutomationComposition(instanceId);
111 if (!compositionId.equals(acToUpdate.getCompositionId())) {
112 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
113 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
115 if (DeployState.UNDEPLOYED.equals(acToUpdate.getDeployState())) {
116 acToUpdate.setElements(automationComposition.getElements());
117 acToUpdate.setName(automationComposition.getName());
118 acToUpdate.setVersion(automationComposition.getVersion());
119 acToUpdate.setDescription(automationComposition.getDescription());
120 acToUpdate.setDerivedFrom(automationComposition.getDerivedFrom());
121 var validationResult = validateAutomationComposition(acToUpdate);
122 if (!validationResult.isValid()) {
123 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult());
125 automationComposition = automationCompositionProvider.updateAutomationComposition(acToUpdate);
126 response.setInstanceId(instanceId);
127 response.setAffectedAutomationComposition(automationComposition.getKey().asIdentifier());
130 } else if ((DeployState.DEPLOYED.equals(acToUpdate.getDeployState())
131 || DeployState.UPDATING.equals(acToUpdate.getDeployState()))
132 && LockState.LOCKED.equals(acToUpdate.getLockState())) {
133 return updateDeployedAutomationComposition(compositionId, automationComposition, acToUpdate);
135 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
136 "Not allowed to update in the state " + acToUpdate.getDeployState());
140 * Update deployed AC Element properties.
142 * @param compositionId The UUID of the automation composition definition
143 * @param automationComposition the automation composition
144 * @param acToBeUpdated the composition to be updated
145 * @return the result of the update
147 public InstantiationResponse updateDeployedAutomationComposition(UUID compositionId,
148 AutomationComposition automationComposition, AutomationComposition acToBeUpdated) {
150 // Iterate and update the element property values
151 for (var dbAcElement : acToBeUpdated.getElements().entrySet()) {
152 var elementId = dbAcElement.getKey();
153 if (automationComposition.getElements().containsKey(elementId)) {
154 dbAcElement.getValue().getProperties()
155 .putAll(automationComposition.getElements().get(elementId).getProperties());
158 var validationResult = validateAutomationComposition(acToBeUpdated);
159 if (!validationResult.isValid()) {
160 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult());
163 // Publish property update event to the participants
164 supervisionAcHandler.update(acToBeUpdated);
166 automationComposition = automationCompositionProvider.updateAutomationComposition(acToBeUpdated);
167 var response = new InstantiationResponse();
168 var instanceId = automationComposition.getInstanceId();
169 response.setInstanceId(instanceId);
170 response.setAffectedAutomationComposition(automationComposition.getKey().asIdentifier());
175 * Validate AutomationComposition.
177 * @param automationComposition AutomationComposition to validate
178 * @return the result of validation
180 private BeanValidationResult validateAutomationComposition(AutomationComposition automationComposition) {
182 var result = new BeanValidationResult("AutomationComposition", automationComposition);
183 var acDefinitionOpt = acDefinitionProvider.findAcDefinition(automationComposition.getCompositionId());
184 if (acDefinitionOpt.isEmpty()) {
185 result.addResult(new ObjectValidationResult("ServiceTemplate", "", ValidationStatus.INVALID,
186 "Commissioned automation composition definition not found"));
189 if (!AcTypeState.PRIMED.equals(acDefinitionOpt.get().getState())) {
190 result.addResult(new ObjectValidationResult("ServiceTemplate", acDefinitionOpt.get().getState(),
191 ValidationStatus.INVALID, "Commissioned automation composition definition not primed"));
194 var participantIds = acDefinitionOpt.get().getElementStateMap().values().stream()
195 .map(NodeTemplateState::getParticipantId).collect(Collectors.toSet());
197 acmParticipantProvider.verifyParticipantState(participantIds);
199 result.addResult(AcmUtils.validateAutomationComposition(automationComposition,
200 acDefinitionOpt.get().getServiceTemplate()));
202 if (result.isValid()) {
203 for (var element : automationComposition.getElements().values()) {
204 var name = element.getDefinition().getName();
205 var participantId = acDefinitionOpt.get().getElementStateMap().get(name).getParticipantId();
206 element.setParticipantId(participantId);
214 * Get Automation Composition.
216 * @param compositionId The UUID of the automation composition definition
217 * @param instanceId The UUID of the automation composition instance
218 * @return the Automation Composition
220 @Transactional(readOnly = true)
221 public AutomationComposition getAutomationComposition(UUID compositionId, UUID instanceId) {
222 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
223 if (!automationComposition.getCompositionId().equals(compositionId)) {
224 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
225 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
227 return automationComposition;
231 * Delete the automation composition with the given name and version.
233 * @param compositionId The UUID of the automation composition definition
234 * @param instanceId The UUID of the automation composition instance
235 * @return the result of the deletion
237 public InstantiationResponse deleteAutomationComposition(UUID compositionId, UUID instanceId) {
238 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
239 if (!compositionId.equals(automationComposition.getCompositionId())) {
240 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
241 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
243 if (!DeployState.UNDEPLOYED.equals(automationComposition.getDeployState())
244 && !DeployState.DELETING.equals(automationComposition.getDeployState())) {
245 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
246 "Automation composition state is still " + automationComposition.getDeployState());
248 var acDefinition = acDefinitionProvider
249 .getAcDefinition(automationComposition.getCompositionId());
250 if (acDefinition != null) {
251 var participantIds = acDefinition.getElementStateMap().values().stream()
252 .map(NodeTemplateState::getParticipantId).collect(Collectors.toSet());
253 acmParticipantProvider.verifyParticipantState(participantIds);
255 supervisionAcHandler.delete(automationComposition, acDefinition);
256 var response = new InstantiationResponse();
257 response.setInstanceId(automationComposition.getInstanceId());
258 response.setAffectedAutomationComposition(automationComposition.getKey().asIdentifier());
263 * Get the requested automation compositions.
265 * @param name the name of the automation composition to get, null for all automation compositions
266 * @param version the version of the automation composition to get, null for all automation compositions
267 * @return the automation compositions
269 @Transactional(readOnly = true)
270 public AutomationCompositions getAutomationCompositions(UUID compositionId, String name, String version) {
271 var automationCompositions = new AutomationCompositions();
272 automationCompositions.setAutomationCompositionList(
273 automationCompositionProvider.getAutomationCompositions(compositionId, name, version));
275 return automationCompositions;
279 * Handle Composition Instance State.
281 * @param compositionId the compositionId
282 * @param instanceId the instanceId
283 * @param acInstanceStateUpdate the AcInstanceStateUpdate
285 public void compositionInstanceState(UUID compositionId, UUID instanceId,
286 @Valid AcInstanceStateUpdate acInstanceStateUpdate) {
287 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
288 if (!compositionId.equals(automationComposition.getCompositionId())) {
289 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
290 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
292 var acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId());
294 var participantIds = acDefinition.getElementStateMap().values().stream()
295 .map(NodeTemplateState::getParticipantId).collect(Collectors.toSet());
297 acmParticipantProvider.verifyParticipantState(participantIds);
298 var result = acInstanceStateResolver.resolve(acInstanceStateUpdate.getDeployOrder(),
299 acInstanceStateUpdate.getLockOrder(), automationComposition.getDeployState(),
300 automationComposition.getLockState(), automationComposition.getStateChangeResult());
303 supervisionAcHandler.deploy(automationComposition, acDefinition);
307 supervisionAcHandler.undeploy(automationComposition, acDefinition);
311 supervisionAcHandler.lock(automationComposition, acDefinition);
315 supervisionAcHandler.unlock(automationComposition, acDefinition);
319 throw new PfModelRuntimeException(Status.BAD_REQUEST, "Not valid " + acInstanceStateUpdate);