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 javax.validation.Valid;
26 import javax.ws.rs.core.Response;
27 import javax.ws.rs.core.Response.Status;
28 import lombok.AllArgsConstructor;
29 import org.onap.policy.clamp.acm.runtime.supervision.SupervisionAcHandler;
30 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
31 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
32 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
33 import org.onap.policy.clamp.models.acm.concepts.DeployState;
34 import org.onap.policy.clamp.models.acm.concepts.LockState;
35 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AcInstanceStateUpdate;
36 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse;
37 import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
38 import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver;
39 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
40 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
41 import org.onap.policy.common.parameters.BeanValidationResult;
42 import org.onap.policy.common.parameters.ObjectValidationResult;
43 import org.onap.policy.common.parameters.ValidationStatus;
44 import org.onap.policy.models.base.PfModelRuntimeException;
45 import org.springframework.stereotype.Service;
46 import org.springframework.transaction.annotation.Transactional;
49 * This class is dedicated to the Instantiation of Commissioned automation composition.
54 public class AutomationCompositionInstantiationProvider {
55 private static final String DO_NOT_MATCH = " do not match with ";
57 private final AutomationCompositionProvider automationCompositionProvider;
58 private final AcDefinitionProvider acDefinitionProvider;
59 private final AcInstanceStateResolver acInstanceStateResolver;
60 private final SupervisionAcHandler supervisionAcHandler;
63 * Create automation composition.
65 * @param compositionId The UUID of the automation composition definition
66 * @param automationComposition the automation composition
67 * @return the result of the instantiation operation
69 public InstantiationResponse createAutomationComposition(UUID compositionId,
70 AutomationComposition automationComposition) {
71 if (!compositionId.equals(automationComposition.getCompositionId())) {
72 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
73 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
75 var checkAutomationCompositionOpt =
76 automationCompositionProvider.findAutomationComposition(automationComposition.getKey().asIdentifier());
77 if (checkAutomationCompositionOpt.isPresent()) {
78 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
79 automationComposition.getKey().asIdentifier() + " already defined");
82 var validationResult = validateAutomationComposition(automationComposition);
83 if (!validationResult.isValid()) {
84 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult());
86 automationComposition = automationCompositionProvider.createAutomationComposition(automationComposition);
88 var response = new InstantiationResponse();
89 response.setInstanceId(automationComposition.getInstanceId());
90 response.setAffectedAutomationComposition(automationComposition.getKey().asIdentifier());
96 * Update automation composition.
98 * @param compositionId The UUID of the automation composition definition
99 * @param automationComposition the automation composition
100 * @return the result of the update
102 public InstantiationResponse updateAutomationComposition(UUID compositionId,
103 AutomationComposition automationComposition) {
104 var response = new InstantiationResponse();
105 var instanceId = automationComposition.getInstanceId();
106 var acToUpdate = automationCompositionProvider.getAutomationComposition(instanceId);
107 if (!compositionId.equals(acToUpdate.getCompositionId())) {
108 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
109 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
111 if (DeployState.UNDEPLOYED.equals(acToUpdate.getDeployState())) {
112 acToUpdate.setElements(automationComposition.getElements());
113 acToUpdate.setName(automationComposition.getName());
114 acToUpdate.setVersion(automationComposition.getVersion());
115 acToUpdate.setDescription(automationComposition.getDescription());
116 acToUpdate.setDerivedFrom(automationComposition.getDerivedFrom());
117 var validationResult = validateAutomationComposition(acToUpdate);
118 if (!validationResult.isValid()) {
119 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult());
121 automationComposition = automationCompositionProvider.updateAutomationComposition(acToUpdate);
122 response.setInstanceId(instanceId);
123 response.setAffectedAutomationComposition(automationComposition.getKey().asIdentifier());
126 } else if ((DeployState.DEPLOYED.equals(acToUpdate.getDeployState())
127 || DeployState.UPDATING.equals(acToUpdate.getDeployState()))
128 && LockState.LOCKED.equals(acToUpdate.getLockState())) {
129 return updateDeployedAutomationComposition(compositionId, automationComposition, acToUpdate);
131 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
132 "Not allowed to update in the state " + acToUpdate.getDeployState());
136 * Update deployed AC Element properties.
138 * @param compositionId The UUID of the automation composition definition
139 * @param automationComposition the automation composition
140 * @param acToBeUpdated the composition to be updated
141 * @return the result of the update
143 public InstantiationResponse updateDeployedAutomationComposition(UUID compositionId,
144 AutomationComposition automationComposition, AutomationComposition acToBeUpdated) {
146 // Iterate and update the element property values
147 for (var dbAcElement : acToBeUpdated.getElements().entrySet()) {
148 var elementId = dbAcElement.getKey();
149 if (automationComposition.getElements().containsKey(elementId)) {
150 dbAcElement.getValue().getProperties()
151 .putAll(automationComposition.getElements().get(elementId).getProperties());
154 var validationResult = validateAutomationComposition(acToBeUpdated);
155 if (!validationResult.isValid()) {
156 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult());
159 // Publish property update event to the participants
160 supervisionAcHandler.update(acToBeUpdated);
162 automationComposition = automationCompositionProvider.updateAutomationComposition(acToBeUpdated);
163 var response = new InstantiationResponse();
164 var instanceId = automationComposition.getInstanceId();
165 response.setInstanceId(instanceId);
166 response.setAffectedAutomationComposition(automationComposition.getKey().asIdentifier());
171 * Validate AutomationComposition.
173 * @param automationComposition AutomationComposition to validate
174 * @return the result of validation
176 private BeanValidationResult validateAutomationComposition(AutomationComposition automationComposition) {
178 var result = new BeanValidationResult("AutomationComposition", automationComposition);
179 var acDefinitionOpt = acDefinitionProvider.findAcDefinition(automationComposition.getCompositionId());
180 if (acDefinitionOpt.isEmpty()) {
181 result.addResult(new ObjectValidationResult("ServiceTemplate", "", ValidationStatus.INVALID,
182 "Commissioned automation composition definition not found"));
185 if (!AcTypeState.PRIMED.equals(acDefinitionOpt.get().getState())) {
186 result.addResult(new ObjectValidationResult("ServiceTemplate", acDefinitionOpt.get().getState(),
187 ValidationStatus.INVALID, "Commissioned automation composition definition not primed"));
190 result.addResult(AcmUtils.validateAutomationComposition(automationComposition,
191 acDefinitionOpt.get().getServiceTemplate()));
193 if (result.isValid()) {
194 for (var element : automationComposition.getElements().values()) {
195 var name = element.getDefinition().getName();
196 var participantId = acDefinitionOpt.get().getElementStateMap().get(name).getParticipantId();
197 element.setParticipantId(participantId);
205 * Get Automation Composition.
207 * @param compositionId The UUID of the automation composition definition
208 * @param instanceId The UUID of the automation composition instance
209 * @return the Automation Composition
211 @Transactional(readOnly = true)
212 public AutomationComposition getAutomationComposition(UUID compositionId, UUID instanceId) {
213 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
214 if (!automationComposition.getCompositionId().equals(compositionId)) {
215 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
216 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
218 return automationComposition;
222 * Delete the automation composition with the given name and version.
224 * @param compositionId The UUID of the automation composition definition
225 * @param instanceId The UUID of the automation composition instance
226 * @return the result of the deletion
228 public InstantiationResponse deleteAutomationComposition(UUID compositionId, UUID instanceId) {
229 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
230 if (!compositionId.equals(automationComposition.getCompositionId())) {
231 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
232 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
234 if (!DeployState.UNDEPLOYED.equals(automationComposition.getDeployState())
235 && !DeployState.DELETING.equals(automationComposition.getDeployState())) {
236 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
237 "Automation composition state is still " + automationComposition.getDeployState());
239 var response = new InstantiationResponse();
240 var acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId());
241 supervisionAcHandler.delete(automationComposition, acDefinition);
242 response.setInstanceId(automationComposition.getInstanceId());
243 response.setAffectedAutomationComposition(automationComposition.getKey().asIdentifier());
248 * Get the requested automation compositions.
250 * @param name the name of the automation composition to get, null for all automation compositions
251 * @param version the version of the automation composition to get, null for all automation compositions
252 * @return the automation compositions
254 @Transactional(readOnly = true)
255 public AutomationCompositions getAutomationCompositions(UUID compositionId, String name, String version) {
256 var automationCompositions = new AutomationCompositions();
257 automationCompositions.setAutomationCompositionList(
258 automationCompositionProvider.getAutomationCompositions(compositionId, name, version));
260 return automationCompositions;
264 * Handle Composition Instance State.
266 * @param compositionId the compositionId
267 * @param instanceId the instanceId
268 * @param acInstanceStateUpdate the AcInstanceStateUpdate
270 public void compositionInstanceState(UUID compositionId, UUID instanceId,
271 @Valid AcInstanceStateUpdate acInstanceStateUpdate) {
272 var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId);
273 if (!compositionId.equals(automationComposition.getCompositionId())) {
274 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
275 automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId);
277 var acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId());
278 var result = acInstanceStateResolver.resolve(acInstanceStateUpdate.getDeployOrder(),
279 acInstanceStateUpdate.getLockOrder(), automationComposition.getDeployState(),
280 automationComposition.getLockState(), automationComposition.getStateChangeResult());
283 supervisionAcHandler.deploy(automationComposition, acDefinition);
287 supervisionAcHandler.undeploy(automationComposition, acDefinition);
291 supervisionAcHandler.lock(automationComposition, acDefinition);
295 supervisionAcHandler.unlock(automationComposition, acDefinition);
299 throw new PfModelRuntimeException(Status.BAD_REQUEST, "Not valid " + acInstanceStateUpdate);