2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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 * ============LICENSE_END=========================================================
20 package org.openecomp.sdc.be.components.lifecycle;
22 import fj.data.Either;
23 import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic;
24 import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
25 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
26 import org.openecomp.sdc.be.config.BeEcompErrorManager;
27 import org.openecomp.sdc.be.dao.api.ActionStatus;
28 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
29 import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
30 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
31 import org.openecomp.sdc.be.impl.ComponentsUtils;
32 import org.openecomp.sdc.be.model.Component;
33 import org.openecomp.sdc.be.model.ComponentInstance;
34 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
35 import org.openecomp.sdc.be.model.LifeCycleTransitionEnum;
36 import org.openecomp.sdc.be.model.LifecycleStateEnum;
37 import org.openecomp.sdc.be.model.Resource;
38 import org.openecomp.sdc.be.model.Service;
39 import org.openecomp.sdc.be.model.User;
40 import org.openecomp.sdc.be.model.category.CategoryDefinition;
41 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement;
42 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeTemplateOperation;
43 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaElementLifecycleOperation;
44 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
45 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
46 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
47 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
48 import org.openecomp.sdc.be.tosca.ToscaUtils;
49 import org.openecomp.sdc.be.user.Role;
50 import org.openecomp.sdc.common.log.wrappers.Logger;
51 import org.openecomp.sdc.common.util.ValidationUtils;
52 import org.openecomp.sdc.exception.ResponseFormat;
54 import java.util.Arrays;
55 import java.util.List;
57 import java.util.Optional;
59 public class CertificationChangeTransition extends LifeCycleTransition {
61 private static final String ALLOTTED_CATEGORY = "Allotted Resource";
62 private static final String DEPENDING_SRV_NAME = "depending_service_name";
63 private static final String PROVIDING_SRV_NAME = "providing_service_name";
64 private static final String PROVIDING_SRV_UUID = "providing_service_uuid";
65 private static final String DEPENDING_SRV_UUID = "depending_service_uuid";
66 private static final Logger log = Logger.getLogger(CertificationChangeTransition.class);
67 private LifecycleStateEnum nextState;
68 private LifeCycleTransitionEnum name;
69 private AuditingActionEnum auditingAction;
70 private NodeTemplateOperation nodeTemplateOperation;
71 private ServiceBusinessLogic serviceBusinessLogic;
73 public CertificationChangeTransition(ServiceBusinessLogic serviceBusinessLogic, LifeCycleTransitionEnum name, ComponentsUtils componentUtils,
74 ToscaElementLifecycleOperation lifecycleOperation, ToscaOperationFacade toscaOperationFacade,
75 JanusGraphDao janusGraphDao) {
76 super(componentUtils, lifecycleOperation, toscaOperationFacade, janusGraphDao);
78 this.serviceBusinessLogic = serviceBusinessLogic;
80 Role[] certificationChangeRoles = {Role.ADMIN, Role.DESIGNER};
81 Role[] resourceRoles = {Role.ADMIN, Role.DESIGNER};
82 addAuthorizedRoles(ComponentTypeEnum.RESOURCE, Arrays.asList(resourceRoles));
83 addAuthorizedRoles(ComponentTypeEnum.SERVICE, Arrays.asList(certificationChangeRoles));
84 this.auditingAction = AuditingActionEnum.CERTIFICATION_SUCCESS_RESOURCE;
85 this.nextState = LifecycleStateEnum.CERTIFIED;
89 public LifeCycleTransitionEnum getName() {
94 public AuditingActionEnum getAuditingAction() {
95 return auditingAction;
98 public NodeTemplateOperation getNodeTemplateOperation() {
99 return nodeTemplateOperation;
102 public void setNodeTemplateOperation(NodeTemplateOperation nodeTemplateOperation) {
103 this.nodeTemplateOperation = nodeTemplateOperation;
106 private ResponseFormat formatCertificationError(Component component, StorageOperationStatus response, ComponentTypeEnum componentType) {
107 BeEcompErrorManager.getInstance().logBeDaoSystemError("Change LifecycleState - Certify failed on graph");
108 log.debug("certification change failed on graph");
109 return componentUtils.getResponseFormatByComponent(componentUtils.convertFromStorageResponse(response), component, componentType);
113 public Either<Boolean, ResponseFormat> validateBeforeTransition(Component component, ComponentTypeEnum componentType, User modifier, User owner,
114 LifecycleStateEnum oldState, LifecycleChangeInfoWithAction lifecycleChangeInfo) {
115 String componentName = component.getComponentMetadataDefinition().getMetadataDataDefinition().getName();
116 log.info("validate before certification change. resource name={}, oldState={}, owner userId={}", componentName, oldState, owner.getUserId());
118 Either<Boolean, ResponseFormat> userValidationResponse = userRoleValidation(modifier, component, componentType, lifecycleChangeInfo);
119 if (userValidationResponse.isRight()) {
120 log.debug("userRoleValidation failed");
121 return userValidationResponse;
123 if (oldState != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT && oldState != LifecycleStateEnum.NOT_CERTIFIED_CHECKIN) {
124 log.debug("Valid states for certification are NOT_CERTIFIED_CHECKIN and NOT_CERTIFIED_CHECKOUT. {} is invalid state", oldState);
125 ResponseFormat error = componentUtils
126 .getResponseFormat(ActionStatus.ILLEGAL_COMPONENT_STATE, componentName, componentType.name().toLowerCase(), oldState.name());
127 return Either.right(error);
129 return Either.left(true);
133 public <T extends Component> Either<T, ResponseFormat> changeState(ComponentTypeEnum componentType, Component component,
134 ComponentBusinessLogic componentBl, User modifier, User owner,
135 boolean shouldLock, boolean inTransaction) {
136 log.info("start performing certification change for resource {}", component.getUniqueId());
137 Either<T, ResponseFormat> result = null;
139 component = handleValidationsBeforeCertifying(componentType, component, modifier, shouldLock, inTransaction);
140 Either<ToscaElement, StorageOperationStatus> certificationChangeResult = lifeCycleOperation
141 .certifyToscaElement(component.getUniqueId(), modifier.getUserId(), owner.getUserId());
142 if (certificationChangeResult.isRight()) {
143 ResponseFormat responseFormat = formatCertificationError(component, certificationChangeResult.right().value(), componentType);
144 result = Either.right(responseFormat);
148 ToscaElement certificationResult = certificationChangeResult.left().value();
149 T componentAfterCertification = ModelConverter.convertFromToscaElement(certificationResult);
150 if (result == null || result.isLeft()) {
151 //update edges for allotted resource
152 StorageOperationStatus status = handleConnectionsForAllotted(componentAfterCertification);
153 if (status != StorageOperationStatus.OK) {
154 ResponseFormat responseFormat = formatCertificationError(componentAfterCertification, status, componentType);
155 result = Either.right(responseFormat);
158 componentBl.populateToscaArtifacts(componentAfterCertification, modifier, true, inTransaction, shouldLock);
159 updateCalculatedCapabilitiesRequirements(componentAfterCertification);
160 updateCapReqPropertiesOwnerId(componentAfterCertification);
161 result = Either.left(componentAfterCertification);
164 if (result == null || result.isRight()) {
165 BeEcompErrorManager.getInstance().logBeDaoSystemError("Change LifecycleState");
166 if (!inTransaction) {
167 log.debug("operation failed. do rollback");
168 janusGraphDao.rollback();
171 if (!inTransaction) {
172 log.debug("operation success. do commit");
173 janusGraphDao.commit();
179 private void updateCapReqPropertiesOwnerId(Component component) {
180 if (component.isTopologyTemplate() && ToscaUtils.isNotComplexVfc(component)) {
181 toscaOperationFacade.updateCapReqPropertiesOwnerId(component.getUniqueId());
185 Either<Boolean, ResponseFormat> validateAllResourceInstanceCertified(Component component) {
186 Either<Boolean, ResponseFormat> eitherResult = Either.left(true);
187 if (component.isVspArchived()) {
189 componentUtils.getResponseFormat(ActionStatus.ARCHIVED_ORIGINS_FOUND, component.getComponentType().name(), component.getName()));
191 List<ComponentInstance> resourceInstance = component.getComponentInstances();
192 if (resourceInstance != null) {
193 //Filter components instances with archived origins
194 Optional<ComponentInstance> archivedRIOptional = resourceInstance.stream().filter(ComponentInstanceDataDefinition::isOriginArchived)
196 //RIs with archived origins found, return relevant error
197 if (archivedRIOptional.isPresent()) {
199 componentUtils.getResponseFormat(ActionStatus.ARCHIVED_ORIGINS_FOUND, component.getComponentType().name(), component.getName()));
201 //Continue with searching for non certified RIs
202 Optional<ComponentInstance> nonCertifiedRIOptional = resourceInstance.stream()
203 .filter(p -> !ValidationUtils.validateCertifiedVersion(p.getComponentVersion())).findAny();
204 // Uncertified Resource Found
205 if (nonCertifiedRIOptional.isPresent()) {
206 ComponentInstance nonCertifiedRI = nonCertifiedRIOptional.get();
207 ResponseFormat resFormat = getRelevantResponseFormatUncertifiedRI(nonCertifiedRI, component.getComponentType());
208 eitherResult = Either.right(resFormat);
214 private ResponseFormat getRelevantResponseFormatUncertifiedRI(ComponentInstance nonCertifiedRI, ComponentTypeEnum componentType) {
215 Either<Resource, StorageOperationStatus> eitherResource = toscaOperationFacade.getToscaElement(nonCertifiedRI.getComponentUid());
216 if (eitherResource.isRight()) {
217 return componentUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
219 ActionStatus actionStatus;
220 Resource resource = eitherResource.left().value();
221 Either<Resource, StorageOperationStatus> status = toscaOperationFacade.findLastCertifiedToscaElementByUUID(resource);
222 if (ValidationUtils.validateMinorVersion(nonCertifiedRI.getComponentVersion())) {
223 if (status.isRight() || status.left().value() == null) {
224 actionStatus = ActionStatus.VALIDATED_RESOURCE_NOT_FOUND;
226 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
229 if (status.isRight() || status.left().value() == null) {
230 actionStatus = ActionStatus.FOUND_LIST_VALIDATED_RESOURCES;
232 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
235 return componentUtils.getResponseFormat(actionStatus, componentType == ComponentTypeEnum.RESOURCE ? "VF" : "service", resource.getName());
238 private Component handleValidationsBeforeCertifying(ComponentTypeEnum componentType, Component component,
239 User modifier, boolean shouldLock, boolean inTransaction) {
240 if (component.isTopologyTemplate()) {
241 Either<Boolean, ResponseFormat> statusCert = validateAllResourceInstanceCertified(component);
242 if (statusCert.isRight()) {
243 throw new ByResponseFormatComponentException(statusCert.right().value());
246 if (componentType == ComponentTypeEnum.SERVICE) {
247 Either<Service, ResponseFormat> generateHeatEnvResult = serviceBusinessLogic
248 .generateHeatEnvArtifacts((Service) component, modifier, shouldLock, inTransaction);
249 if (generateHeatEnvResult.isRight()) {
250 throw new ByResponseFormatComponentException(generateHeatEnvResult.right().value());
252 Either<Service, ResponseFormat> generateVfModuleResult = serviceBusinessLogic
253 .generateVfModuleArtifacts(generateHeatEnvResult.left().value(), modifier, shouldLock, inTransaction);
254 if (generateVfModuleResult.isRight()) {
255 throw new ByResponseFormatComponentException(generateVfModuleResult.right().value());
257 component = generateVfModuleResult.left().value();
262 private void updateCalculatedCapabilitiesRequirements(Component certifiedComponent) {
263 if (certifiedComponent.getComponentType() == ComponentTypeEnum.SERVICE) {
264 toscaOperationFacade.updateNamesOfCalculatedCapabilitiesRequirements(certifiedComponent.getUniqueId());
268 private StorageOperationStatus handleConnectionsForAllotted(Component component) {
269 StorageOperationStatus status = StorageOperationStatus.OK;
270 if (component.getComponentType() == ComponentTypeEnum.RESOURCE && component.isTopologyTemplate()) {
271 List<CategoryDefinition> categories = component.getCategories();
272 Optional<CategoryDefinition> findFirst = categories.stream().filter(c -> c.getName().equals(ALLOTTED_CATEGORY)).findFirst();
273 if (findFirst.isPresent()) {
274 findInstanceByAllottedProperties(component);
276 log.debug("Component isn't from allotted category.");
282 private void findInstanceByAllottedProperties(Component component) {
283 log.debug("Component is from alloted category. Remove all previous ALLOTTED_OF connections for all instances");
284 nodeTemplateOperation.removeAllAllotedEdges(component.getUniqueId());
285 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
286 if (componentInstancesProperties != null) {
287 componentInstancesProperties.entrySet().forEach(e -> {
288 List<ComponentInstanceProperty> props = e.getValue();
289 Optional<ComponentInstanceProperty> findProp = props.stream()
290 .filter(p -> p.getName().equals(DEPENDING_SRV_NAME) || p.getName().equals(PROVIDING_SRV_NAME)).findFirst();
291 if (findProp.isPresent()) {
292 log.debug("Find specific properties [{} or {}]on instance {} ", DEPENDING_SRV_NAME, PROVIDING_SRV_NAME, e.getKey());
293 handleAllotedInstance(component.getUniqueId(), e.getKey(), e.getValue());
295 log.debug("Not defined specific properties [{} or {}]on instance {} ", DEPENDING_SRV_NAME, PROVIDING_SRV_NAME, e.getKey());
301 private StorageOperationStatus handleAllotedInstance(String componentId, String instanceId, List<ComponentInstanceProperty> props) {
302 ComponentInstanceProperty serviceUUIDProp = props.stream()
303 .filter(p -> p.getName().equals(PROVIDING_SRV_UUID) || p.getName().equals(DEPENDING_SRV_UUID)).findFirst().get();
304 if (serviceUUIDProp.getValue() != null && !serviceUUIDProp.getValue().contains("get_input")) {
305 log.debug("Handle Allotted edge on instance {} for service UUID {} ", instanceId, serviceUUIDProp.getValue());
306 return nodeTemplateOperation.createAllottedOfEdge(componentId, instanceId, serviceUUIDProp.getValue());
308 log.debug("An incorrectly defined service UUID for Allotted instance {} . Skip instance", instanceId, serviceUUIDProp.getValue());
309 return StorageOperationStatus.OK;