7adc77f1b2eea4c39dd267cde1366e8119274e56
[sdc.git] /
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 <T extends Component> Either<T, ResponseFormat> changeState(
138         ComponentTypeEnum componentType,
139         Component component,
140         ComponentBusinessLogic componentBl, User modifier, User owner, boolean shouldLock, boolean inTransaction
141     ) {
142
143         log.info("start performing certification change for resource {}", component.getUniqueId());
144         Either<T, ResponseFormat> result = null;
145
146         try {
147             handleValidationsAndArtifactsGenerationBeforeCertifying(componentType, component, componentBl, modifier, shouldLock, inTransaction);
148             Either<ToscaElement, StorageOperationStatus> certificationChangeResult =
149                     lifeCycleOperation.certifyToscaElement(component.getUniqueId(), modifier.getUserId(), owner.getUserId());
150
151             if (certificationChangeResult.isRight()) {
152                 ResponseFormat responseFormat = formatCertificationError(component, certificationChangeResult.right().value(), componentType);
153                 result = Either.right(responseFormat);
154                 return result;
155             }
156
157             ToscaElement certificationResult = certificationChangeResult.left().value();
158             T componentAfterCertification = ModelConverter.convertFromToscaElement(certificationResult);
159             if ( result == null || result.isLeft() ){
160                 //update edges for allotted resource 
161                 StorageOperationStatus status = handleConnectionsForAllotted(componentAfterCertification);
162                 if ( status != StorageOperationStatus.OK){
163                     ResponseFormat responseFormat = formatCertificationError(componentAfterCertification, status, componentType);
164                     result = Either.right(responseFormat);
165                 }
166             }
167             updateCalculatedCapabilitiesRequirements(componentAfterCertification);
168             updateCapReqPropertiesOwnerId(componentAfterCertification);
169             result = Either.left(componentAfterCertification);
170             return result;
171         } finally {
172             if (result == null || result.isRight()) {
173                 BeEcompErrorManager.getInstance().logBeDaoSystemError("Change LifecycleState");
174                 if ( !inTransaction ) {
175                     log.debug("operation failed. do rollback");
176                     janusGraphDao.rollback();
177                 }
178             } else {
179                 if ( !inTransaction ) {
180                     log.debug("operation success. do commit");
181                     janusGraphDao.commit();
182                 }
183             }
184         }
185
186     }
187
188     private void updateCapReqPropertiesOwnerId(Component component) {
189         if(component.isTopologyTemplate() && ToscaUtils.isNotComplexVfc(component)) {
190             toscaOperationFacade.updateCapReqPropertiesOwnerId(component.getUniqueId());
191         }
192     }
193
194     Either<Boolean, ResponseFormat> validateAllResourceInstanceCertified(Component component) {
195         Either<Boolean, ResponseFormat> eitherResult = Either.left(true);
196
197         if (component.isVspArchived()){
198             return Either.right(componentUtils.getResponseFormat(ActionStatus.ARCHIVED_ORIGINS_FOUND, component.getComponentType().name(), component.getName()));
199         }
200
201         List<ComponentInstance> resourceInstance = component.getComponentInstances();
202         if (resourceInstance != null) {
203
204             //Filter components instances with archived origins
205             Optional<ComponentInstance> archivedRIOptional = resourceInstance.stream().filter(ComponentInstanceDataDefinition::isOriginArchived).findAny();
206
207             //RIs with archived origins found, return relevant error
208             if (archivedRIOptional.isPresent()){
209                 return Either.right(componentUtils.getResponseFormat(ActionStatus.ARCHIVED_ORIGINS_FOUND, component.getComponentType().name(), component.getName()));
210             }
211
212             //Continue with searching for non certified RIs
213             Optional<ComponentInstance> nonCertifiedRIOptional = resourceInstance.stream().filter(p -> !ValidationUtils.validateCertifiedVersion(p.getComponentVersion())).findAny();
214             // Uncertified Resource Found
215             if (nonCertifiedRIOptional.isPresent()) {
216                 ComponentInstance nonCertifiedRI = nonCertifiedRIOptional.get();
217                 ResponseFormat resFormat = getRelevantResponseFormatUncertifiedRI(nonCertifiedRI, component.getComponentType());
218                 eitherResult = Either.right(resFormat);
219             }
220
221         }
222         return eitherResult;
223     }
224
225     private ResponseFormat getRelevantResponseFormatUncertifiedRI(ComponentInstance nonCertifiedRI, ComponentTypeEnum componentType) {
226
227         Either<Resource, StorageOperationStatus> eitherResource = toscaOperationFacade.getToscaElement(nonCertifiedRI.getComponentUid());
228         if (eitherResource.isRight()) {
229             return componentUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
230         }
231         ActionStatus actionStatus;
232         Resource resource = eitherResource.left().value();
233         Either<Resource, StorageOperationStatus> status = toscaOperationFacade.findLastCertifiedToscaElementByUUID(resource);
234
235         if (ValidationUtils.validateMinorVersion(nonCertifiedRI.getComponentVersion())) {
236             if (status.isRight() || status.left().value() == null) {
237                 actionStatus = ActionStatus.VALIDATED_RESOURCE_NOT_FOUND;
238             } else {
239                 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
240             }
241         } else {
242             if (status.isRight() || status.left().value() == null) {
243                 actionStatus = ActionStatus.FOUND_LIST_VALIDATED_RESOURCES;
244             } else {
245                 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
246             }
247         }
248         return componentUtils.getResponseFormat(actionStatus, componentType == ComponentTypeEnum.RESOURCE ? "VF" : "service", resource.getName());
249     }
250
251     private void handleValidationsAndArtifactsGenerationBeforeCertifying(ComponentTypeEnum componentType, Component component, ComponentBusinessLogic componentBl, User modifier, boolean shouldLock, boolean inTransaction) {
252         if (component.isTopologyTemplate()) {
253             Either<Boolean, ResponseFormat> statusCert = validateAllResourceInstanceCertified(component);
254             if (statusCert.isRight()) {
255                 throw new ByResponseFormatComponentException(statusCert.right().value());
256             }
257         }
258         if (componentType == ComponentTypeEnum.SERVICE) {
259
260             Either<Service, ResponseFormat> generateHeatEnvResult = serviceBusinessLogic.generateHeatEnvArtifacts((Service) component, modifier, shouldLock, inTransaction);
261
262             if (generateHeatEnvResult.isRight()) {
263                 throw new ByResponseFormatComponentException(generateHeatEnvResult.right().value());
264             }
265             Either<Service, ResponseFormat> generateVfModuleResult = serviceBusinessLogic.generateVfModuleArtifacts(generateHeatEnvResult.left().value(), modifier, shouldLock, inTransaction);
266             if (generateVfModuleResult.isRight()) {
267                 throw new ByResponseFormatComponentException(generateVfModuleResult.right().value());
268             }
269             component = generateVfModuleResult.left().value();
270         }
271
272         componentBl.populateToscaArtifacts(component, modifier, true, inTransaction, shouldLock);
273     }
274
275
276     private void updateCalculatedCapabilitiesRequirements(Component certifiedComponent) {
277         if(certifiedComponent.getComponentType() == ComponentTypeEnum.SERVICE){
278             toscaOperationFacade.updateNamesOfCalculatedCapabilitiesRequirements(certifiedComponent.getUniqueId());
279         }
280     }
281
282     private StorageOperationStatus handleConnectionsForAllotted(Component component){
283         StorageOperationStatus status = StorageOperationStatus.OK;
284         if (component.getComponentType() == ComponentTypeEnum.RESOURCE && component.isTopologyTemplate()  ){
285             List<CategoryDefinition> categories = component.getCategories();
286             Optional<CategoryDefinition> findFirst = categories.stream().filter(c->c.getName().equals(ALLOTTED_CATEGORY)).findFirst();
287             if ( findFirst.isPresent() ){
288                 findInstanceByAllottedProperties(component);
289             }else{
290                 log.debug("Component isn't from allotted category.");
291             }
292         }
293         return status;
294     }
295
296     private void findInstanceByAllottedProperties(Component component) {
297         log.debug("Component is from alloted category. Remove all previous ALLOTTED_OF connections for all instances");
298         nodeTemplateOperation.removeAllAllotedEdges(component.getUniqueId());
299         Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
300         if ( componentInstancesProperties != null ){
301             componentInstancesProperties.entrySet().forEach(e->{
302                 List<ComponentInstanceProperty> props = e.getValue();
303                 Optional<ComponentInstanceProperty> findProp = props.stream().filter(p -> p.getName().equals(DEPENDING_SRV_NAME) ||  p.getName().equals(PROVIDING_SRV_NAME)).findFirst();
304                 if ( findProp.isPresent() ){
305                     log.debug("Find specific properties [{} or {}]on instance {} ", DEPENDING_SRV_NAME,PROVIDING_SRV_NAME, e.getKey()  );
306                     handleAllotedInstance(component.getUniqueId(), e.getKey(), e.getValue() );
307                 }else{
308                     log.debug("Not defined specific properties [{} or {}]on instance {} ", DEPENDING_SRV_NAME,PROVIDING_SRV_NAME, e.getKey()  );
309                 }
310             });
311         }
312     }
313
314     private StorageOperationStatus handleAllotedInstance(String componentId, String instanceId, List<ComponentInstanceProperty> props) {
315         ComponentInstanceProperty serviceUUIDProp = props.stream().filter(p -> p.getName().equals(PROVIDING_SRV_UUID) ||  p.getName().equals(DEPENDING_SRV_UUID)).findFirst().get();
316         if ( serviceUUIDProp.getValue() != null && !serviceUUIDProp.getValue().contains("get_input")){
317             log.debug("Handle Allotted edge on instance {} for service UUID {} ", instanceId,  serviceUUIDProp.getValue() );
318             return  nodeTemplateOperation.createAllottedOfEdge(componentId, instanceId, serviceUUIDProp.getValue());
319         }else{
320             log.debug("An incorrectly defined service UUID for Allotted instance {} . Skip instance", instanceId,  serviceUUIDProp.getValue() );
321             return StorageOperationStatus.OK;
322         }
323     }
324 }