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 java.util.Arrays;
24 import java.util.List;
26 import java.util.Optional;
27 import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic;
28 import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
29 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
30 import org.openecomp.sdc.be.config.BeEcompErrorManager;
31 import org.openecomp.sdc.be.dao.api.ActionStatus;
32 import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
33 import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
34 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
35 import org.openecomp.sdc.be.impl.ComponentsUtils;
36 import org.openecomp.sdc.be.model.Component;
37 import org.openecomp.sdc.be.model.ComponentInstance;
38 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
39 import org.openecomp.sdc.be.model.LifeCycleTransitionEnum;
40 import org.openecomp.sdc.be.model.LifecycleStateEnum;
41 import org.openecomp.sdc.be.model.Resource;
42 import org.openecomp.sdc.be.model.Service;
43 import org.openecomp.sdc.be.model.User;
44 import org.openecomp.sdc.be.model.category.CategoryDefinition;
45 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement;
46 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeTemplateOperation;
47 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaElementLifecycleOperation;
48 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
49 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
50 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
51 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
52 import org.openecomp.sdc.be.tosca.ToscaUtils;
53 import org.openecomp.sdc.be.user.Role;
54 import org.openecomp.sdc.common.log.wrappers.Logger;
55 import org.openecomp.sdc.common.util.ValidationUtils;
56 import org.openecomp.sdc.exception.ResponseFormat;
58 public class CertificationChangeTransition extends LifeCycleTransition {
60 private static final String ALLOTTED_CATEGORY = "Allotted Resource";
61 private static final String DEPENDING_SRV_NAME = "depending_service_name";
62 private static final String PROVIDING_SRV_NAME = "providing_service_name";
63 private static final String PROVIDING_SRV_UUID = "providing_service_uuid";
64 private static final String DEPENDING_SRV_UUID = "depending_service_uuid";
65 private static final Logger log = Logger.getLogger(CertificationChangeTransition.class);
66 private LifecycleStateEnum nextState;
67 private LifeCycleTransitionEnum name;
68 private AuditingActionEnum auditingAction;
69 private NodeTemplateOperation nodeTemplateOperation;
70 private ServiceBusinessLogic serviceBusinessLogic;
72 public CertificationChangeTransition(ServiceBusinessLogic serviceBusinessLogic, LifeCycleTransitionEnum name, ComponentsUtils componentUtils,
73 ToscaElementLifecycleOperation lifecycleOperation, ToscaOperationFacade toscaOperationFacade,
74 JanusGraphDao janusGraphDao) {
75 super(componentUtils, lifecycleOperation, toscaOperationFacade, janusGraphDao);
77 this.serviceBusinessLogic = serviceBusinessLogic;
79 Role[] certificationChangeRoles = {Role.ADMIN, Role.DESIGNER};
80 Role[] resourceRoles = {Role.ADMIN, Role.DESIGNER};
81 addAuthorizedRoles(ComponentTypeEnum.RESOURCE, Arrays.asList(resourceRoles));
82 addAuthorizedRoles(ComponentTypeEnum.SERVICE, Arrays.asList(certificationChangeRoles));
83 this.auditingAction = AuditingActionEnum.CERTIFICATION_SUCCESS_RESOURCE;
84 this.nextState = LifecycleStateEnum.CERTIFIED;
88 public LifeCycleTransitionEnum getName() {
93 public AuditingActionEnum getAuditingAction() {
94 return auditingAction;
97 public NodeTemplateOperation getNodeTemplateOperation() {
98 return nodeTemplateOperation;
101 public void setNodeTemplateOperation(NodeTemplateOperation nodeTemplateOperation) {
102 this.nodeTemplateOperation = nodeTemplateOperation;
105 private ResponseFormat formatCertificationError(Component component, StorageOperationStatus response, ComponentTypeEnum componentType) {
106 BeEcompErrorManager.getInstance().logBeDaoSystemError("Change LifecycleState - Certify failed on graph");
107 log.debug("certification change failed on graph");
108 return componentUtils.getResponseFormatByComponent(componentUtils.convertFromStorageResponse(response), component, componentType);
112 public Either<Boolean, ResponseFormat> validateBeforeTransition(Component component, ComponentTypeEnum componentType, User modifier, User owner,
113 LifecycleStateEnum oldState, LifecycleChangeInfoWithAction lifecycleChangeInfo) {
114 String componentName = component.getComponentMetadataDefinition().getMetadataDataDefinition().getName();
115 log.info("validate before certification change. resource name={}, oldState={}, owner userId={}", componentName, oldState, owner.getUserId());
117 Either<Boolean, ResponseFormat> userValidationResponse = userRoleValidation(modifier, component, componentType, lifecycleChangeInfo);
118 if (userValidationResponse.isRight()) {
119 log.debug("userRoleValidation failed");
120 return userValidationResponse;
122 if (oldState != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT && oldState != LifecycleStateEnum.NOT_CERTIFIED_CHECKIN) {
123 log.debug("Valid states for certification are NOT_CERTIFIED_CHECKIN and NOT_CERTIFIED_CHECKOUT. {} is invalid state", oldState);
124 ResponseFormat error = componentUtils
125 .getResponseFormat(ActionStatus.ILLEGAL_COMPONENT_STATE, componentName, componentType.name().toLowerCase(), oldState.name());
126 return Either.right(error);
128 return Either.left(true);
132 public <T extends Component> Either<T, ResponseFormat> changeState(ComponentTypeEnum componentType, Component component,
133 ComponentBusinessLogic componentBl, User modifier, User owner,
134 boolean shouldLock, boolean inTransaction) {
135 log.info("start performing certification change for resource {}", component.getUniqueId());
136 Either<T, ResponseFormat> result = null;
138 handleValidationsAndArtifactsGenerationBeforeCertifying(componentType, component, componentBl, modifier, shouldLock, inTransaction);
139 Either<ToscaElement, StorageOperationStatus> certificationChangeResult = lifeCycleOperation
140 .certifyToscaElement(component.getUniqueId(), modifier.getUserId(), owner.getUserId());
141 if (certificationChangeResult.isRight()) {
142 ResponseFormat responseFormat = formatCertificationError(component, certificationChangeResult.right().value(), componentType);
143 result = Either.right(responseFormat);
146 ToscaElement certificationResult = certificationChangeResult.left().value();
147 T componentAfterCertification = ModelConverter.convertFromToscaElement(certificationResult);
148 if (result == null || result.isLeft()) {
149 //update edges for allotted resource
150 StorageOperationStatus status = handleConnectionsForAllotted(componentAfterCertification);
151 if (status != StorageOperationStatus.OK) {
152 ResponseFormat responseFormat = formatCertificationError(componentAfterCertification, status, componentType);
153 result = Either.right(responseFormat);
156 updateCalculatedCapabilitiesRequirements(componentAfterCertification);
157 updateCapReqPropertiesOwnerId(componentAfterCertification);
158 result = Either.left(componentAfterCertification);
161 if (result == null || result.isRight()) {
162 BeEcompErrorManager.getInstance().logBeDaoSystemError("Change LifecycleState");
163 if (!inTransaction) {
164 log.debug("operation failed. do rollback");
165 janusGraphDao.rollback();
168 if (!inTransaction) {
169 log.debug("operation success. do commit");
170 janusGraphDao.commit();
176 private void updateCapReqPropertiesOwnerId(Component component) {
177 if (component.isTopologyTemplate() && ToscaUtils.isNotComplexVfc(component)) {
178 toscaOperationFacade.updateCapReqPropertiesOwnerId(component.getUniqueId());
182 Either<Boolean, ResponseFormat> validateAllResourceInstanceCertified(Component component) {
183 Either<Boolean, ResponseFormat> eitherResult = Either.left(true);
184 if (component.isVspArchived()) {
186 componentUtils.getResponseFormat(ActionStatus.ARCHIVED_ORIGINS_FOUND, component.getComponentType().name(), component.getName()));
188 List<ComponentInstance> resourceInstance = component.getComponentInstances();
189 if (resourceInstance != null) {
190 //Filter components instances with archived origins
191 Optional<ComponentInstance> archivedRIOptional = resourceInstance.stream().filter(ComponentInstanceDataDefinition::isOriginArchived)
193 //RIs with archived origins found, return relevant error
194 if (archivedRIOptional.isPresent()) {
196 componentUtils.getResponseFormat(ActionStatus.ARCHIVED_ORIGINS_FOUND, component.getComponentType().name(), component.getName()));
198 //Continue with searching for non certified RIs
199 Optional<ComponentInstance> nonCertifiedRIOptional = resourceInstance.stream()
200 .filter(p -> !ValidationUtils.validateCertifiedVersion(p.getComponentVersion())).findAny();
201 // Uncertified Resource Found
202 if (nonCertifiedRIOptional.isPresent()) {
203 ComponentInstance nonCertifiedRI = nonCertifiedRIOptional.get();
204 ResponseFormat resFormat = getRelevantResponseFormatUncertifiedRI(nonCertifiedRI, component.getComponentType());
205 eitherResult = Either.right(resFormat);
211 private ResponseFormat getRelevantResponseFormatUncertifiedRI(ComponentInstance nonCertifiedRI, ComponentTypeEnum componentType) {
212 Either<Resource, StorageOperationStatus> eitherResource = toscaOperationFacade.getToscaElement(nonCertifiedRI.getComponentUid());
213 if (eitherResource.isRight()) {
214 return componentUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
216 ActionStatus actionStatus;
217 Resource resource = eitherResource.left().value();
218 Either<Resource, StorageOperationStatus> status = toscaOperationFacade.findLastCertifiedToscaElementByUUID(resource);
219 if (ValidationUtils.validateMinorVersion(nonCertifiedRI.getComponentVersion())) {
220 if (status.isRight() || status.left().value() == null) {
221 actionStatus = ActionStatus.VALIDATED_RESOURCE_NOT_FOUND;
223 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
226 if (status.isRight() || status.left().value() == null) {
227 actionStatus = ActionStatus.FOUND_LIST_VALIDATED_RESOURCES;
229 actionStatus = ActionStatus.FOUND_ALREADY_VALIDATED_RESOURCE;
232 return componentUtils.getResponseFormat(actionStatus, componentType == ComponentTypeEnum.RESOURCE ? "VF" : "service", resource.getName());
235 private void handleValidationsAndArtifactsGenerationBeforeCertifying(ComponentTypeEnum componentType, Component component,
236 ComponentBusinessLogic componentBl, User modifier, boolean shouldLock,
237 boolean inTransaction) {
238 if (component.isTopologyTemplate()) {
239 Either<Boolean, ResponseFormat> statusCert = validateAllResourceInstanceCertified(component);
240 if (statusCert.isRight()) {
241 throw new ByResponseFormatComponentException(statusCert.right().value());
244 if (componentType == ComponentTypeEnum.SERVICE) {
245 Either<Service, ResponseFormat> generateHeatEnvResult = serviceBusinessLogic
246 .generateHeatEnvArtifacts((Service) component, modifier, shouldLock, inTransaction);
247 if (generateHeatEnvResult.isRight()) {
248 throw new ByResponseFormatComponentException(generateHeatEnvResult.right().value());
250 Either<Service, ResponseFormat> generateVfModuleResult = serviceBusinessLogic
251 .generateVfModuleArtifacts(generateHeatEnvResult.left().value(), modifier, shouldLock, inTransaction);
252 if (generateVfModuleResult.isRight()) {
253 throw new ByResponseFormatComponentException(generateVfModuleResult.right().value());
255 component = generateVfModuleResult.left().value();
257 componentBl.populateToscaArtifacts(component, modifier, true, inTransaction, shouldLock);
260 private void updateCalculatedCapabilitiesRequirements(Component certifiedComponent) {
261 if (certifiedComponent.getComponentType() == ComponentTypeEnum.SERVICE) {
262 toscaOperationFacade.updateNamesOfCalculatedCapabilitiesRequirements(certifiedComponent.getUniqueId());
266 private StorageOperationStatus handleConnectionsForAllotted(Component component) {
267 StorageOperationStatus status = StorageOperationStatus.OK;
268 if (component.getComponentType() == ComponentTypeEnum.RESOURCE && component.isTopologyTemplate()) {
269 List<CategoryDefinition> categories = component.getCategories();
270 Optional<CategoryDefinition> findFirst = categories.stream().filter(c -> c.getName().equals(ALLOTTED_CATEGORY)).findFirst();
271 if (findFirst.isPresent()) {
272 findInstanceByAllottedProperties(component);
274 log.debug("Component isn't from allotted category.");
280 private void findInstanceByAllottedProperties(Component component) {
281 log.debug("Component is from alloted category. Remove all previous ALLOTTED_OF connections for all instances");
282 nodeTemplateOperation.removeAllAllotedEdges(component.getUniqueId());
283 Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
284 if (componentInstancesProperties != null) {
285 componentInstancesProperties.entrySet().forEach(e -> {
286 List<ComponentInstanceProperty> props = e.getValue();
287 Optional<ComponentInstanceProperty> findProp = props.stream()
288 .filter(p -> p.getName().equals(DEPENDING_SRV_NAME) || p.getName().equals(PROVIDING_SRV_NAME)).findFirst();
289 if (findProp.isPresent()) {
290 log.debug("Find specific properties [{} or {}]on instance {} ", DEPENDING_SRV_NAME, PROVIDING_SRV_NAME, e.getKey());
291 handleAllotedInstance(component.getUniqueId(), e.getKey(), e.getValue());
293 log.debug("Not defined specific properties [{} or {}]on instance {} ", DEPENDING_SRV_NAME, PROVIDING_SRV_NAME, e.getKey());
299 private StorageOperationStatus handleAllotedInstance(String componentId, String instanceId, List<ComponentInstanceProperty> props) {
300 ComponentInstanceProperty serviceUUIDProp = props.stream()
301 .filter(p -> p.getName().equals(PROVIDING_SRV_UUID) || p.getName().equals(DEPENDING_SRV_UUID)).findFirst().get();
302 if (serviceUUIDProp.getValue() != null && !serviceUUIDProp.getValue().contains("get_input")) {
303 log.debug("Handle Allotted edge on instance {} for service UUID {} ", instanceId, serviceUUIDProp.getValue());
304 return nodeTemplateOperation.createAllottedOfEdge(componentId, instanceId, serviceUUIDProp.getValue());
306 log.debug("An incorrectly defined service UUID for Allotted instance {} . Skip instance", instanceId, serviceUUIDProp.getValue());
307 return StorageOperationStatus.OK;