Upgrade SDC from Titan to Janus Graph
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / lifecycle / CertificationRequestTransition.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.config.BeEcompErrorManager;
27 import org.openecomp.sdc.be.dao.api.ActionStatus;
28 import org.openecomp.sdc.be.dao.jsongraph.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.datatypes.enums.OriginTypeEnum;
32 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
33 import org.openecomp.sdc.be.impl.ComponentsUtils;
34 import org.openecomp.sdc.be.model.*;
35 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement;
36 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaElementLifecycleOperation;
37 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
38 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
39 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
40 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
41 import org.openecomp.sdc.be.user.Role;
42 import org.openecomp.sdc.common.log.wrappers.Logger;
43 import org.openecomp.sdc.common.util.ValidationUtils;
44 import org.openecomp.sdc.exception.ResponseFormat;
45
46 import java.util.*;
47
48 public class CertificationRequestTransition extends LifeCycleTransition {
49
50     private static final Logger log = Logger.getLogger(CertificationRequestTransition.class);
51
52     private ServiceBusinessLogic serviceBusinessLogic;
53
54     public CertificationRequestTransition(ComponentsUtils componentUtils, ToscaElementLifecycleOperation lifecycleOperation, ServiceBusinessLogic serviceBusinessLogic,
55                                           ToscaOperationFacade toscaOperationFacade, JanusGraphDao janusGraphDao) {
56         super(componentUtils, lifecycleOperation, toscaOperationFacade, janusGraphDao);
57
58         // authorized roles
59         Role[] resourceServiceCheckoutRoles = { Role.ADMIN, Role.DESIGNER };
60         addAuthorizedRoles(ComponentTypeEnum.RESOURCE, Arrays.asList(resourceServiceCheckoutRoles));
61         addAuthorizedRoles(ComponentTypeEnum.SERVICE, Arrays.asList(resourceServiceCheckoutRoles));
62         Role[] resourceRoles = { Role.TESTER};
63         addResouceAuthorizedRoles(ResourceTypeEnum.VFCMT, Arrays.asList(resourceRoles));
64
65         this.serviceBusinessLogic = serviceBusinessLogic;
66     }
67
68     @Override
69     public LifeCycleTransitionEnum getName() {
70         return LifeCycleTransitionEnum.CERTIFICATION_REQUEST;
71     }
72
73     @Override
74     public AuditingActionEnum getAuditingAction() {
75         return AuditingActionEnum.CERTIFICATION_REQUEST_RESOURCE;
76     }
77
78     Either<Boolean, ResponseFormat> validateAllResourceInstanceCertified(Component component) {
79         Either<Boolean, ResponseFormat> eitherResult = Either.left(true);
80
81         if (component.isVspArchived()){
82             return Either.right(componentUtils.getResponseFormat(ActionStatus.ARCHIVED_ORIGINS_FOUND, component.getComponentType().name(), component.getName()));
83         }
84
85         List<ComponentInstance> resourceInstance = component.getComponentInstances();
86         if (resourceInstance != null) {
87
88             //Filter components instances with archived origins
89             Optional<ComponentInstance> archivedRIOptional = resourceInstance.stream().filter(ComponentInstanceDataDefinition::isOriginArchived).findAny();
90
91             //RIs with archived origins found, return relevant error
92             if (archivedRIOptional.isPresent()){
93                 return Either.right(componentUtils.getResponseFormat(ActionStatus.ARCHIVED_ORIGINS_FOUND, component.getComponentType().name(), component.getName()));
94             }
95
96             //Continue with searching for non certified RIs
97             Optional<ComponentInstance> nonCertifiedRIOptional = resourceInstance.stream().filter(p -> !ValidationUtils.validateCertifiedVersion(p.getComponentVersion())).findAny();
98             // Uncertified Resource Found
99             if (nonCertifiedRIOptional.isPresent()) {
100                 ComponentInstance nonCertifiedRI = nonCertifiedRIOptional.get();
101                 ResponseFormat resFormat = getRelevantResponseFormatUncertifiedRI(nonCertifiedRI, component.getComponentType());
102                 eitherResult = Either.right(resFormat);
103             }
104
105         }
106         return eitherResult;
107     }
108
109     private ResponseFormat getRelevantResponseFormatUncertifiedRI(ComponentInstance nonCertifiedRI, ComponentTypeEnum componentType) {
110
111         Either<Resource, StorageOperationStatus> eitherResource = toscaOperationFacade.getToscaElement(nonCertifiedRI.getComponentUid());
112         if (eitherResource.isRight()) {
113             return componentUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
114         }
115         ActionStatus actionStatus;
116         Resource resource = eitherResource.left().value();
117         Either<Resource, StorageOperationStatus> status = toscaOperationFacade.findLastCertifiedToscaElementByUUID(resource);
118
119         if (ValidationUtils.validateMinorVersion(nonCertifiedRI.getComponentVersion())) {
120             if (status.isRight() || status.left().value() == null) {
121                 actionStatus = ActionStatus.VALIDATED_RESOURCE_NOT_FOUND;
122             } else {
123                 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
124             }
125         } else {
126             if (status.isRight() || status.left().value() == null) {
127                 actionStatus = ActionStatus.FOUND_LIST_VALIDATED_RESOURCES;
128             } else {
129                 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
130             }
131         }
132         return componentUtils.getResponseFormat(actionStatus, componentType == ComponentTypeEnum.RESOURCE ? "VF" : "service", resource.getName());
133     }
134
135     @Override
136     public Either<? extends Component, ResponseFormat> changeState(ComponentTypeEnum componentType, Component component, ComponentBusinessLogic componentBl, User modifier, User owner, boolean shouldLock, boolean inTransaction) {
137
138         log.debug("start performing certification request for resource {}", component.getUniqueId());
139
140         ActionStatus actionStatus;
141         ResponseFormat responseFormat;
142         Either<? extends Component, ResponseFormat> result = null;
143         try{
144             if (component.isTopologyTemplate()) {
145
146                 Either<Boolean, ResponseFormat> statusCert = validateAllResourceInstanceCertified(component);
147                 if (statusCert.isRight()) {
148                     return Either.right(statusCert.right().value());
149                 }
150
151                 statusCert = validateConfiguredAtomicReqCapSatisfied(component);
152                 if (statusCert.isRight()) {
153                     return Either.right(statusCert.right().value());
154                 }
155             }
156             if (componentType == ComponentTypeEnum.SERVICE) {
157
158                 Either<Service, ResponseFormat> generateHeatEnvResult = serviceBusinessLogic.generateHeatEnvArtifacts((Service) component, modifier, shouldLock, inTransaction);
159
160                 if (generateHeatEnvResult.isRight()) {
161                         return Either.right(generateHeatEnvResult.right().value());
162                     }
163                 Either<Service, ResponseFormat> generateVfModuleResult = serviceBusinessLogic.generateVfModuleArtifacts(generateHeatEnvResult.left().value(), modifier, shouldLock, inTransaction);
164                 if (generateVfModuleResult.isRight()) {
165                         return Either.right(generateVfModuleResult.right().value());
166                 }
167                 component = generateVfModuleResult.left().value();
168
169             }
170
171             Either<Either<ArtifactDefinition, Operation>, ResponseFormat> eitherPopulated = componentBl.populateToscaArtifacts(component, modifier, true, inTransaction, shouldLock);
172             if (eitherPopulated != null && eitherPopulated.isRight()) {
173                 return Either.right(eitherPopulated.right().value());
174             }
175
176             Either<ToscaElement, StorageOperationStatus> certificationRequestResult = lifeCycleOperation.requestCertificationToscaElement(component.getUniqueId(), modifier.getUserId(), owner.getUserId());
177             if (certificationRequestResult.isRight()) {
178                 log.debug("checkout failed on graph");
179                 StorageOperationStatus response = certificationRequestResult.right().value();
180                 actionStatus = componentUtils.convertFromStorageResponse(response);
181
182                 if (response.equals(StorageOperationStatus.ENTITY_ALREADY_EXISTS)) {
183                     actionStatus = ActionStatus.COMPONENT_VERSION_ALREADY_EXIST;
184                 }
185                 responseFormat = componentUtils.getResponseFormatByComponent(actionStatus, component, componentType);
186                 result =  Either.right(responseFormat);
187             }
188             else {
189                 result =  Either.left(ModelConverter.convertFromToscaElement(certificationRequestResult.left().value()));
190             }
191     } finally {
192         if (result == null || result.isRight()) {
193             BeEcompErrorManager.getInstance().logBeDaoSystemError("Change LifecycleState");
194             if (!inTransaction) {
195                 log.debug("operation failed. do rollback");
196                 janusGraphDao.rollback();
197             }
198         } else {
199             if (!inTransaction) {
200                 log.debug("operation success. do commit");
201                 janusGraphDao.commit();
202             }
203         }
204     }
205         return result;
206     }
207
208     private Either<Boolean, ResponseFormat> validateConfiguredAtomicReqCapSatisfied(Component component) {
209         log.debug("Submit for testing validation - Start validating configured req/cap satisfied for inner atomic instances, component id:{}", component.getUniqueId());
210         List<ComponentInstance> componentInstances = component.getComponentInstances();
211         if (componentInstances != null) {
212             // Prepare relationships data structures
213             // Better make it list than set in case we need to count req/cap
214             // occurrences in the future
215             Map<String, List<String>> reqName2Ids = new HashMap<>();
216             Map<String, List<String>> capName2Ids = new HashMap<>();
217             Map<String, Set<String>> requirementsToFulfillBeforeCert = configurationManager.getConfiguration().getRequirementsToFulfillBeforeCert();
218             Map<String, Set<String>> capabilitiesToConsumeBeforeCert = configurationManager.getConfiguration().getCapabilitiesToConsumeBeforeCert();
219             for (ComponentInstance compInst : componentInstances) {
220                 String compInstId = compInst.getUniqueId();
221                 OriginTypeEnum originType = compInst.getOriginType();
222                 if (originType == null) {
223                     log.debug("Origin type is not set for component instance {} - it shouldn't happen. Skipping this component instance...", compInst.getUniqueId());
224                     continue;
225                 }
226                 String compInstType = originType.getValue();
227                 // Validating configured requirements fulfilled
228                 if (null != requirementsToFulfillBeforeCert) {
229                     Set<String> reqToFulfillForType = requirementsToFulfillBeforeCert.get(compInstType);
230                     if (reqToFulfillForType != null) {
231                         for (String reqNameToFulfill : reqToFulfillForType) {
232                             List<String> reqNameList = reqName2Ids.get(reqNameToFulfill);
233                             if (reqNameList == null || !reqNameList.contains(compInstId)) {
234                                 log.debug("Requirement {} wasn't fulfilled for component instance {} of type {}", reqNameToFulfill, compInstId, compInstType);
235                                 ComponentTypeEnum componentType = component.getComponentType();
236                                 String compParam = (componentType == ComponentTypeEnum.RESOURCE) ? "VF" : componentType.getValue().toLowerCase();
237                                 ResponseFormat responseFormat = componentUtils.getResponseFormat(ActionStatus.REQ_CAP_NOT_SATISFIED_BEFORE_CERTIFICATION, component.getName(), compParam, originType.getDisplayValue(), compInst.getName(), "requirement",
238                                         reqNameToFulfill, "fulfilled");
239                                 return Either.right(responseFormat);
240                             }
241                         }
242                     }
243                 }
244                 // Validating configured capabilities consumed
245                 if (null != capabilitiesToConsumeBeforeCert) {
246                     Set<String> capToConsumeForType = capabilitiesToConsumeBeforeCert.get(compInstType);
247                     if (capToConsumeForType != null) {
248                         for (String capNameToConsume : capToConsumeForType) {
249                             List<String> capNameList = capName2Ids.get(capNameToConsume);
250                             if (capNameList == null || !capNameList.contains(compInstId)) {
251                                 log.debug("Capability {} wasn't consumed for component instance {} of type {}", capNameToConsume, compInstId, compInstType);
252                                 ComponentTypeEnum componentType = component.getComponentType();
253                                 String compParam = (componentType == ComponentTypeEnum.RESOURCE) ? "VF" : componentType.getValue().toLowerCase();
254                                 ResponseFormat responseFormat = componentUtils.getResponseFormat(ActionStatus.REQ_CAP_NOT_SATISFIED_BEFORE_CERTIFICATION, component.getName(), compParam, originType.getDisplayValue(), compInst.getName(), "capability",
255                                         capNameToConsume, "consumed");
256                                 return Either.right(responseFormat);
257                             }
258                         }
259                     }
260                 }
261             }
262         }
263         log.debug("Submit for testing validation - validating configured req/cap satisfied for inner atomic instances finished successfully, component id:{}", component.getUniqueId());
264         return Either.left(true);
265     }
266
267     @Override
268     public Either<Boolean, ResponseFormat> validateBeforeTransition(Component component, ComponentTypeEnum componentType, User modifier, User owner, LifecycleStateEnum oldState, LifecycleChangeInfoWithAction lifecycleChangeInfo) {
269         String componentName = component.getComponentMetadataDefinition().getMetadataDataDefinition().getName();
270         log.debug("validate before certification request. resource name={}, oldState={}, owner userId={}", componentName, oldState, owner.getUserId());
271
272         // validate user
273         Either<Boolean, ResponseFormat> userValidationResponse = userRoleValidation(modifier,component, componentType, lifecycleChangeInfo);
274         if (userValidationResponse.isRight()) {
275             return userValidationResponse;
276         }
277
278         // case of "atomic" checkin and certification request - modifier must be
279         // the owner
280         if (oldState.equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT) && !modifier.equals(owner) && !modifier.getRole().equals(Role.ADMIN.name())) {
281             ResponseFormat error = componentUtils.getResponseFormat(ActionStatus.COMPONENT_CHECKOUT_BY_ANOTHER_USER, componentName, componentType.name().toLowerCase(), owner.getFirstName(), owner.getLastName(), owner.getUserId());
282             return Either.right(error);
283         }
284
285         // other states
286         if (oldState.equals(LifecycleStateEnum.CERTIFIED)) {
287             ResponseFormat error = componentUtils.getResponseFormat(ActionStatus.COMPONENT_ALREADY_CERTIFIED, componentName, componentType.name().toLowerCase(), owner.getFirstName(), owner.getLastName(), owner.getUserId());
288             return Either.right(error);
289         }
290         if (oldState.equals(LifecycleStateEnum.CERTIFICATION_IN_PROGRESS)) {
291             ResponseFormat error = componentUtils.getResponseFormat(ActionStatus.COMPONENT_IN_CERT_IN_PROGRESS_STATE, componentName, componentType.name().toLowerCase(), owner.getFirstName(), owner.getLastName(), owner.getUserId());
292             return Either.right(error);
293         }
294         if (oldState.equals(LifecycleStateEnum.READY_FOR_CERTIFICATION)) {
295             ResponseFormat error = componentUtils.getResponseFormat(ActionStatus.COMPONENT_SENT_FOR_CERTIFICATION, componentName, componentType.name().toLowerCase(), owner.getFirstName(), owner.getLastName(), owner.getUserId());
296             return Either.right(error);
297         }
298
299         return Either.left(true);
300     }
301 }