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=========================================================
21 package org.openecomp.sdc.be.components.lifecycle;
23 import fj.data.Either;
24 import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic;
25 import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
26 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
27 import org.openecomp.sdc.be.config.BeEcompErrorManager;
28 import org.openecomp.sdc.be.dao.api.ActionStatus;
29 import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
30 import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
31 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
32 import org.openecomp.sdc.be.impl.ComponentsUtils;
33 import org.openecomp.sdc.be.model.Component;
34 import org.openecomp.sdc.be.model.ComponentInstance;
35 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
36 import org.openecomp.sdc.be.model.LifeCycleTransitionEnum;
37 import org.openecomp.sdc.be.model.LifecycleStateEnum;
38 import org.openecomp.sdc.be.model.Resource;
39 import org.openecomp.sdc.be.model.Service;
40 import org.openecomp.sdc.be.model.User;
41 import org.openecomp.sdc.be.model.category.CategoryDefinition;
42 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement;
43 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeTemplateOperation;
44 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaElementLifecycleOperation;
45 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
46 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
47 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
48 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
49 import org.openecomp.sdc.be.tosca.ToscaUtils;
50 import org.openecomp.sdc.be.user.Role;
51 import org.openecomp.sdc.common.log.wrappers.Logger;
52 import org.openecomp.sdc.common.util.ValidationUtils;
53 import org.openecomp.sdc.exception.ResponseFormat;
55 import java.util.Arrays;
56 import java.util.List;
58 import java.util.Optional;
60 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";
67 private static final Logger log = Logger.getLogger(CertificationChangeTransition.class);
69 private LifecycleStateEnum nextState;
70 private LifeCycleTransitionEnum name;
71 private AuditingActionEnum auditingAction;
72 private NodeTemplateOperation nodeTemplateOperation;
73 private ServiceBusinessLogic serviceBusinessLogic;
75 public CertificationChangeTransition(ServiceBusinessLogic serviceBusinessLogic, LifeCycleTransitionEnum name, ComponentsUtils componentUtils, ToscaElementLifecycleOperation lifecycleOperation, ToscaOperationFacade toscaOperationFacade, JanusGraphDao janusGraphDao) {
76 super(componentUtils, lifecycleOperation, toscaOperationFacade, janusGraphDao);
79 this.serviceBusinessLogic = serviceBusinessLogic;
82 Role[] certificationChangeRoles = { Role.ADMIN, Role.DESIGNER };
83 Role[] resourceRoles = { Role.ADMIN, Role.DESIGNER};
84 addAuthorizedRoles(ComponentTypeEnum.RESOURCE, Arrays.asList(resourceRoles));
85 addAuthorizedRoles(ComponentTypeEnum.SERVICE, Arrays.asList(certificationChangeRoles));
87 this.auditingAction = AuditingActionEnum.CERTIFICATION_SUCCESS_RESOURCE;
88 this.nextState = LifecycleStateEnum.CERTIFIED;
92 public LifeCycleTransitionEnum getName() {
97 public AuditingActionEnum getAuditingAction() {
98 return auditingAction;
101 public NodeTemplateOperation getNodeTemplateOperation() {
102 return nodeTemplateOperation;
105 public void setNodeTemplateOperation(NodeTemplateOperation nodeTemplateOperation) {
106 this.nodeTemplateOperation = nodeTemplateOperation;
109 private ResponseFormat formatCertificationError(Component component, StorageOperationStatus response, ComponentTypeEnum componentType) {
110 BeEcompErrorManager.getInstance().logBeDaoSystemError("Change LifecycleState - Certify failed on graph");
111 log.debug("certification change failed on graph");
113 return componentUtils.getResponseFormatByComponent(componentUtils.convertFromStorageResponse(response), component, componentType);
117 public Either<Boolean, ResponseFormat> validateBeforeTransition(Component component, ComponentTypeEnum componentType, User modifier, User owner, LifecycleStateEnum oldState, LifecycleChangeInfoWithAction lifecycleChangeInfo) {
118 String componentName = component.getComponentMetadataDefinition().getMetadataDataDefinition().getName();
119 log.info("validate before certification change. resource name={}, oldState={}, owner userId={}", componentName, oldState, owner.getUserId());
122 Either<Boolean, ResponseFormat> userValidationResponse = userRoleValidation(modifier,component, componentType, lifecycleChangeInfo);
123 if (userValidationResponse.isRight()) {
124 log.debug("userRoleValidation failed");
125 return userValidationResponse;
128 if (oldState != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT && oldState != LifecycleStateEnum.NOT_CERTIFIED_CHECKIN) {
129 log.debug("Valid states for certification are NOT_CERTIFIED_CHECKIN and NOT_CERTIFIED_CHECKOUT. {} is invalid state", oldState);
130 ResponseFormat error = componentUtils.getResponseFormat(ActionStatus.ILLEGAL_COMPONENT_STATE, componentName, componentType.name().toLowerCase(), oldState.name());
131 return Either.right(error);
133 return Either.left(true);
137 public Either<? extends Component, ResponseFormat> changeState(ComponentTypeEnum componentType, Component component, ComponentBusinessLogic componentBl, User modifier, User owner, boolean shouldLock, boolean inTransaction) {
139 log.info("start performing certification change for resource {}", component.getUniqueId());
140 Either<? extends Component, ResponseFormat> result = null;
143 handleValidationsAndArtifactsGenerationBeforeCertifying(componentType, component, componentBl, modifier, shouldLock, inTransaction);
144 Either<ToscaElement, StorageOperationStatus> certificationChangeResult =
145 lifeCycleOperation.certifyToscaElement(component.getUniqueId(), modifier.getUserId(), owner.getUserId());
147 if (certificationChangeResult.isRight()) {
148 ResponseFormat responseFormat = formatCertificationError(component, certificationChangeResult.right().value(), componentType);
149 result = Either.right(responseFormat);
153 ToscaElement certificationResult = certificationChangeResult.left().value();
154 Component componentAfterCertification = ModelConverter.convertFromToscaElement(certificationResult);
155 if ( result == null || result.isLeft() ){
156 //update edges for allotted resource
157 StorageOperationStatus status = handleConnectionsForAllotted(componentAfterCertification);
158 if ( status != StorageOperationStatus.OK){
159 ResponseFormat responseFormat = formatCertificationError(componentAfterCertification, status, componentType);
160 result = Either.right(responseFormat);
163 updateCalculatedCapabilitiesRequirements(componentAfterCertification);
164 updateCapReqPropertiesOwnerId(componentAfterCertification);
165 result = Either.left(componentAfterCertification);
168 if (result == null || result.isRight()) {
169 BeEcompErrorManager.getInstance().logBeDaoSystemError("Change LifecycleState");
170 if ( !inTransaction ) {
171 log.debug("operation failed. do rollback");
172 janusGraphDao.rollback();
175 if ( !inTransaction ) {
176 log.debug("operation success. do commit");
177 janusGraphDao.commit();
184 private void updateCapReqPropertiesOwnerId(Component component) {
185 if(component.isTopologyTemplate() && ToscaUtils.isNotComplexVfc(component)) {
186 toscaOperationFacade.updateCapReqPropertiesOwnerId(component.getUniqueId());
190 Either<Boolean, ResponseFormat> validateAllResourceInstanceCertified(Component component) {
191 Either<Boolean, ResponseFormat> eitherResult = Either.left(true);
193 if (component.isVspArchived()){
194 return Either.right(componentUtils.getResponseFormat(ActionStatus.ARCHIVED_ORIGINS_FOUND, component.getComponentType().name(), component.getName()));
197 List<ComponentInstance> resourceInstance = component.getComponentInstances();
198 if (resourceInstance != null) {
200 //Filter components instances with archived origins
201 Optional<ComponentInstance> archivedRIOptional = resourceInstance.stream().filter(ComponentInstanceDataDefinition::isOriginArchived).findAny();
203 //RIs with archived origins found, return relevant error
204 if (archivedRIOptional.isPresent()){
205 return Either.right(componentUtils.getResponseFormat(ActionStatus.ARCHIVED_ORIGINS_FOUND, component.getComponentType().name(), component.getName()));
208 //Continue with searching for non certified RIs
209 Optional<ComponentInstance> nonCertifiedRIOptional = resourceInstance.stream().filter(p -> !ValidationUtils.validateCertifiedVersion(p.getComponentVersion())).findAny();
210 // Uncertified Resource Found
211 if (nonCertifiedRIOptional.isPresent()) {
212 ComponentInstance nonCertifiedRI = nonCertifiedRIOptional.get();
213 ResponseFormat resFormat = getRelevantResponseFormatUncertifiedRI(nonCertifiedRI, component.getComponentType());
214 eitherResult = Either.right(resFormat);
221 private ResponseFormat getRelevantResponseFormatUncertifiedRI(ComponentInstance nonCertifiedRI, ComponentTypeEnum componentType) {
223 Either<Resource, StorageOperationStatus> eitherResource = toscaOperationFacade.getToscaElement(nonCertifiedRI.getComponentUid());
224 if (eitherResource.isRight()) {
225 return componentUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
227 ActionStatus actionStatus;
228 Resource resource = eitherResource.left().value();
229 Either<Resource, StorageOperationStatus> status = toscaOperationFacade.findLastCertifiedToscaElementByUUID(resource);
231 if (ValidationUtils.validateMinorVersion(nonCertifiedRI.getComponentVersion())) {
232 if (status.isRight() || status.left().value() == null) {
233 actionStatus = ActionStatus.VALIDATED_RESOURCE_NOT_FOUND;
235 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
238 if (status.isRight() || status.left().value() == null) {
239 actionStatus = ActionStatus.FOUND_LIST_VALIDATED_RESOURCES;
241 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
244 return componentUtils.getResponseFormat(actionStatus, componentType == ComponentTypeEnum.RESOURCE ? "VF" : "service", resource.getName());
247 private void handleValidationsAndArtifactsGenerationBeforeCertifying(ComponentTypeEnum componentType, Component component, ComponentBusinessLogic componentBl, User modifier, boolean shouldLock, boolean inTransaction) {
248 if (component.isTopologyTemplate()) {
249 Either<Boolean, ResponseFormat> statusCert = validateAllResourceInstanceCertified(component);
250 if (statusCert.isRight()) {
251 throw new ByResponseFormatComponentException(statusCert.right().value());
254 if (componentType == ComponentTypeEnum.SERVICE) {
256 Either<Service, ResponseFormat> generateHeatEnvResult = serviceBusinessLogic.generateHeatEnvArtifacts((Service) component, modifier, shouldLock, inTransaction);
258 if (generateHeatEnvResult.isRight()) {
259 throw new ByResponseFormatComponentException(generateHeatEnvResult.right().value());
261 Either<Service, ResponseFormat> generateVfModuleResult = serviceBusinessLogic.generateVfModuleArtifacts(generateHeatEnvResult.left().value(), modifier, shouldLock, inTransaction);
262 if (generateVfModuleResult.isRight()) {
263 throw new ByResponseFormatComponentException(generateVfModuleResult.right().value());
265 component = generateVfModuleResult.left().value();
268 componentBl.populateToscaArtifacts(component, modifier, true, inTransaction, shouldLock);
272 private void updateCalculatedCapabilitiesRequirements(Component certifiedComponent) {
273 if(certifiedComponent.getComponentType() == ComponentTypeEnum.SERVICE){
274 toscaOperationFacade.updateNamesOfCalculatedCapabilitiesRequirements(certifiedComponent.getUniqueId());
278 private StorageOperationStatus handleConnectionsForAllotted(Component component){
279 StorageOperationStatus status = StorageOperationStatus.OK;
280 if (component.getComponentType() == ComponentTypeEnum.RESOURCE && component.isTopologyTemplate() ){
281 List<CategoryDefinition> categories = component.getCategories();
282 Optional<CategoryDefinition> findFirst = categories.stream().filter(c->c.getName().equals(ALLOTTED_CATEGORY)).findFirst();
283 if ( findFirst.isPresent() ){
284 findInstanceByAllottedProperties(component);
286 log.debug("Component isn't from allotted category.");
292 private void findInstanceByAllottedProperties(Component component) {
293 log.debug("Component is from alloted category. Remove all previous ALLOTTED_OF connections for all instances");
294 nodeTemplateOperation.removeAllAllotedEdges(component.getUniqueId());
295 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
296 if ( componentInstancesProperties != null ){
297 componentInstancesProperties.entrySet().forEach(e->{
298 List<ComponentInstanceProperty> props = e.getValue();
299 Optional<ComponentInstanceProperty> findProp = props.stream().filter(p -> p.getName().equals(DEPENDING_SRV_NAME) || p.getName().equals(PROVIDING_SRV_NAME)).findFirst();
300 if ( findProp.isPresent() ){
301 log.debug("Find specific properties [{} or {}]on instance {} ", DEPENDING_SRV_NAME,PROVIDING_SRV_NAME, e.getKey() );
302 handleAllotedInstance(component.getUniqueId(), e.getKey(), e.getValue() );
304 log.debug("Not defined specific properties [{} or {}]on instance {} ", DEPENDING_SRV_NAME,PROVIDING_SRV_NAME, e.getKey() );
310 private StorageOperationStatus handleAllotedInstance(String componentId, String instanceId, List<ComponentInstanceProperty> props) {
311 ComponentInstanceProperty serviceUUIDProp = props.stream().filter(p -> p.getName().equals(PROVIDING_SRV_UUID) || p.getName().equals(DEPENDING_SRV_UUID)).findFirst().get();
312 if ( serviceUUIDProp.getValue() != null && !serviceUUIDProp.getValue().contains("get_input")){
313 log.debug("Handle Allotted edge on instance {} for service UUID {} ", instanceId, serviceUUIDProp.getValue() );
314 return nodeTemplateOperation.createAllottedOfEdge(componentId, instanceId, serviceUUIDProp.getValue());
316 log.debug("An incorrectly defined service UUID for Allotted instance {} . Skip instance", instanceId, serviceUUIDProp.getValue() );
317 return StorageOperationStatus.OK;