Catalog alignment
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / lifecycle / CertificationChangeTransition.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
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  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.components.lifecycle;
22
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;
54
55 import java.util.Arrays;
56 import java.util.List;
57 import java.util.Map;
58 import java.util.Optional;
59
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";
66
67     private static final Logger log = Logger.getLogger(CertificationChangeTransition.class);
68
69     private LifecycleStateEnum nextState;
70     private LifeCycleTransitionEnum name;
71     private AuditingActionEnum auditingAction;
72     private NodeTemplateOperation nodeTemplateOperation;
73     private ServiceBusinessLogic serviceBusinessLogic;
74
75     public CertificationChangeTransition(ServiceBusinessLogic serviceBusinessLogic, LifeCycleTransitionEnum name, ComponentsUtils componentUtils, ToscaElementLifecycleOperation lifecycleOperation, ToscaOperationFacade toscaOperationFacade, JanusGraphDao janusGraphDao) {
76         super(componentUtils, lifecycleOperation, toscaOperationFacade, janusGraphDao);
77
78         this.name = name;
79         this.serviceBusinessLogic = serviceBusinessLogic;
80
81         // authorized roles
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));
86
87         this.auditingAction = AuditingActionEnum.CERTIFICATION_SUCCESS_RESOURCE;
88         this.nextState = LifecycleStateEnum.CERTIFIED;
89     }
90
91     @Override
92     public LifeCycleTransitionEnum getName() {
93         return name;
94     }
95
96     @Override
97     public AuditingActionEnum getAuditingAction() {
98         return auditingAction;
99     }
100
101     public NodeTemplateOperation getNodeTemplateOperation() {
102         return nodeTemplateOperation;
103     }
104
105     public void setNodeTemplateOperation(NodeTemplateOperation nodeTemplateOperation) {
106         this.nodeTemplateOperation = nodeTemplateOperation;
107     }
108
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");
112
113         return componentUtils.getResponseFormatByComponent(componentUtils.convertFromStorageResponse(response), component, componentType);
114     }
115
116     @Override
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());
120
121         // validate user
122         Either<Boolean, ResponseFormat> userValidationResponse = userRoleValidation(modifier,component, componentType, lifecycleChangeInfo);
123         if (userValidationResponse.isRight()) {
124             log.debug("userRoleValidation failed");
125             return userValidationResponse;
126         }
127
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);
132         }
133         return Either.left(true);
134     }
135
136     @Override
137     public Either<? extends Component, ResponseFormat> changeState(ComponentTypeEnum componentType, Component component, ComponentBusinessLogic componentBl, User modifier, User owner, boolean shouldLock, boolean inTransaction) {
138
139         log.info("start performing certification change for resource {}", component.getUniqueId());
140         Either<? extends Component, ResponseFormat> result = null;
141
142         try {
143             handleValidationsAndArtifactsGenerationBeforeCertifying(componentType, component, componentBl, modifier, shouldLock, inTransaction);
144             Either<ToscaElement, StorageOperationStatus> certificationChangeResult =
145                     lifeCycleOperation.certifyToscaElement(component.getUniqueId(), modifier.getUserId(), owner.getUserId());
146
147             if (certificationChangeResult.isRight()) {
148                 ResponseFormat responseFormat = formatCertificationError(component, certificationChangeResult.right().value(), componentType);
149                 result = Either.right(responseFormat);
150                 return result;
151             }
152
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);
161                 }
162             }
163             updateCalculatedCapabilitiesRequirements(componentAfterCertification);
164             updateCapReqPropertiesOwnerId(componentAfterCertification);
165             result = Either.left(componentAfterCertification);
166             return result;
167         } finally {
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();
173                 }
174             } else {
175                 if ( !inTransaction ) {
176                     log.debug("operation success. do commit");
177                     janusGraphDao.commit();
178                 }
179             }
180         }
181
182     }
183
184     private void updateCapReqPropertiesOwnerId(Component component) {
185         if(component.isTopologyTemplate() && ToscaUtils.isNotComplexVfc(component)) {
186             toscaOperationFacade.updateCapReqPropertiesOwnerId(component.getUniqueId());
187         }
188     }
189
190     Either<Boolean, ResponseFormat> validateAllResourceInstanceCertified(Component component) {
191         Either<Boolean, ResponseFormat> eitherResult = Either.left(true);
192
193         if (component.isVspArchived()){
194             return Either.right(componentUtils.getResponseFormat(ActionStatus.ARCHIVED_ORIGINS_FOUND, component.getComponentType().name(), component.getName()));
195         }
196
197         List<ComponentInstance> resourceInstance = component.getComponentInstances();
198         if (resourceInstance != null) {
199
200             //Filter components instances with archived origins
201             Optional<ComponentInstance> archivedRIOptional = resourceInstance.stream().filter(ComponentInstanceDataDefinition::isOriginArchived).findAny();
202
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()));
206             }
207
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);
215             }
216
217         }
218         return eitherResult;
219     }
220
221     private ResponseFormat getRelevantResponseFormatUncertifiedRI(ComponentInstance nonCertifiedRI, ComponentTypeEnum componentType) {
222
223         Either<Resource, StorageOperationStatus> eitherResource = toscaOperationFacade.getToscaElement(nonCertifiedRI.getComponentUid());
224         if (eitherResource.isRight()) {
225             return componentUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
226         }
227         ActionStatus actionStatus;
228         Resource resource = eitherResource.left().value();
229         Either<Resource, StorageOperationStatus> status = toscaOperationFacade.findLastCertifiedToscaElementByUUID(resource);
230
231         if (ValidationUtils.validateMinorVersion(nonCertifiedRI.getComponentVersion())) {
232             if (status.isRight() || status.left().value() == null) {
233                 actionStatus = ActionStatus.VALIDATED_RESOURCE_NOT_FOUND;
234             } else {
235                 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
236             }
237         } else {
238             if (status.isRight() || status.left().value() == null) {
239                 actionStatus = ActionStatus.FOUND_LIST_VALIDATED_RESOURCES;
240             } else {
241                 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
242             }
243         }
244         return componentUtils.getResponseFormat(actionStatus, componentType == ComponentTypeEnum.RESOURCE ? "VF" : "service", resource.getName());
245     }
246
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());
252             }
253         }
254         if (componentType == ComponentTypeEnum.SERVICE) {
255
256             Either<Service, ResponseFormat> generateHeatEnvResult = serviceBusinessLogic.generateHeatEnvArtifacts((Service) component, modifier, shouldLock, inTransaction);
257
258             if (generateHeatEnvResult.isRight()) {
259                 throw new ByResponseFormatComponentException(generateHeatEnvResult.right().value());
260             }
261             Either<Service, ResponseFormat> generateVfModuleResult = serviceBusinessLogic.generateVfModuleArtifacts(generateHeatEnvResult.left().value(), modifier, shouldLock, inTransaction);
262             if (generateVfModuleResult.isRight()) {
263                 throw new ByResponseFormatComponentException(generateVfModuleResult.right().value());
264             }
265             component = generateVfModuleResult.left().value();
266         }
267
268         componentBl.populateToscaArtifacts(component, modifier, true, inTransaction, shouldLock);
269     }
270
271
272     private void updateCalculatedCapabilitiesRequirements(Component certifiedComponent) {
273         if(certifiedComponent.getComponentType() == ComponentTypeEnum.SERVICE){
274             toscaOperationFacade.updateNamesOfCalculatedCapabilitiesRequirements(certifiedComponent.getUniqueId());
275         }
276     }
277
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);
285             }else{
286                 log.debug("Component isn't from allotted category.");
287             }
288         }
289         return status;
290     }
291
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() );
303                 }else{
304                     log.debug("Not defined specific properties [{} or {}]on instance {} ", DEPENDING_SRV_NAME,PROVIDING_SRV_NAME, e.getKey()  );
305                 }
306             });
307         }
308     }
309
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());
315         }else{
316             log.debug("An incorrectly defined service UUID for Allotted instance {} . Skip instance", instanceId,  serviceUUIDProp.getValue() );
317             return StorageOperationStatus.OK;
318         }
319     }
320 }