36c16bed9e43ece1f4f386c525897bc7c2be1ab2
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / csar / CsarBusinessLogic.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  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22 package org.openecomp.sdc.be.components.csar;
23
24 import static org.openecomp.sdc.common.api.Constants.DEFAULT_MODEL_NAME;
25
26 import fj.data.Either;
27 import java.util.Map;
28 import java.util.Optional;
29 import org.apache.commons.lang3.tuple.ImmutablePair;
30 import org.openecomp.sdc.be.components.impl.BaseBusinessLogic;
31 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
32 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
33 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
34 import org.openecomp.sdc.be.config.BeEcompErrorManager;
35 import org.openecomp.sdc.be.dao.api.ActionStatus;
36 import org.openecomp.sdc.be.model.Component;
37 import org.openecomp.sdc.be.model.NodeTypeInfo;
38 import org.openecomp.sdc.be.model.ParsedToscaYamlInfo;
39 import org.openecomp.sdc.be.model.Resource;
40 import org.openecomp.sdc.be.model.Service;
41 import org.openecomp.sdc.be.model.User;
42 import org.openecomp.sdc.be.model.VendorSoftwareProduct;
43 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
44 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
45 import org.openecomp.sdc.be.model.operations.StorageException;
46 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
47 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
48 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
49 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
50 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
51 import org.openecomp.sdc.be.model.operations.impl.CsarOperation;
52 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
53 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
54 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
55 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
56 import org.openecomp.sdc.common.log.wrappers.Logger;
57 import org.openecomp.sdc.exception.ResponseFormat;
58 import org.springframework.beans.factory.annotation.Autowired;
59
60 @org.springframework.stereotype.Component("csarBusinessLogic")
61 public class CsarBusinessLogic extends BaseBusinessLogic {
62
63     private static final Logger log = Logger.getLogger(CsarBusinessLogic.class);
64     private static final String CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID = "Creating resource from CSAR: fetching CSAR with id ";
65     private static final String FAILED = " failed";
66     private final YamlTemplateParsingHandler yamlHandler;
67     private CsarOperation csarOperation;
68     private ModelOperation modelOperation;
69
70     @Autowired
71     public CsarBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation,
72                              IGroupTypeOperation groupTypeOperation, InterfaceOperation interfaceOperation,
73                              InterfaceLifecycleOperation interfaceLifecycleTypeOperation, YamlTemplateParsingHandler yamlHandler,
74                              ArtifactsOperations artifactToscaOperation, ModelOperation modelOperation) {
75         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
76             artifactToscaOperation);
77         this.yamlHandler = yamlHandler;
78         this.modelOperation = modelOperation;
79     }
80
81     @Autowired
82     public void setCsarOperation(CsarOperation csarOperation) {
83         this.csarOperation = csarOperation;
84     }
85
86     public void validateCsarBeforeCreate(Resource resource, AuditingActionEnum auditingAction, User user, String csarUUID) {
87         // check if VF with the same Csar UUID or with he same name already
88
89         // exists
90         StorageOperationStatus status = toscaOperationFacade.validateCsarUuidUniqueness(csarUUID);
91         if (status == StorageOperationStatus.ENTITY_ALREADY_EXISTS) {
92             log.debug("Failed to create resource {}, csarUUID {} already exist for a different VF ", resource.getSystemName(), csarUUID);
93             auditAndThrowException(resource, user, auditingAction, ActionStatus.VSP_ALREADY_EXISTS, csarUUID);
94         } else if (status != StorageOperationStatus.OK) {
95             log.debug("Failed to validate uniqueness of CsarUUID {} for resource", csarUUID, resource.getSystemName());
96             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status));
97         }
98     }
99
100     public void validateCsarBeforeCreate(Service resource, String csarUUID) {
101         // check if VF with the same Csar UUID or with he same name already
102
103         // exists
104         StorageOperationStatus status = toscaOperationFacade.validateCsarUuidUniqueness(csarUUID);
105         log.debug("enter validateCsarBeforeCreate,get status:{}", status);
106         if (status == StorageOperationStatus.ENTITY_ALREADY_EXISTS) {
107             log.debug("Failed to create resource {}, csarUUID {} already exist for a different VF ", resource.getSystemName(), csarUUID);
108         } else if (status != StorageOperationStatus.OK) {
109             log.debug("Failed to validate uniqueness of CsarUUID '{}' for resource '{}'", csarUUID, resource.getSystemName());
110             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status));
111         }
112     }
113
114     public OnboardedCsarInfo getCsarInfo(Resource resource, Resource oldResource, User user, Map<String, byte[]> payload, String csarUUID) {
115         Map<String, byte[]> csar = payload;
116         if (csar == null) {
117             final var vendorSoftwareProduct = getCsar(resource, user);
118             validateModel(resource, vendorSoftwareProduct);
119
120             csar = vendorSoftwareProduct.getFileMap();
121         }
122         ImmutablePair<String, String> toscaYamlCsarStatus = validateAndParseCsar(resource, user, csar, csarUUID).left()
123             .on(this::throwComponentException);
124         String checksum = CsarValidationUtils.getToscaYamlChecksum(csar, csarUUID, componentsUtils).left()
125             .on(r -> logAndThrowComponentException(r, "Failed to calculate checksum for casrUUID {} error {} ", csarUUID));
126         if (oldResource != null && !checksum
127             .equals(oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().getImportedToscaChecksum())) {
128             log.debug(
129                 "The checksum of main template yaml of csar with csarUUID {} is not equal to the previous one, existing checksum is {}, new one is {}.",
130                 csarUUID, oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().getImportedToscaChecksum(), checksum);
131             oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().setImportedToscaChecksum(checksum);
132         }
133         return new OnboardedCsarInfo(user, csarUUID, resource.getCsarVersionId(), csar, resource.getName(), toscaYamlCsarStatus.getKey(),
134             toscaYamlCsarStatus.getValue(), true);
135     }
136
137     private void validateModel(final Resource resource, final VendorSoftwareProduct vendorSoftwareProduct) {
138         if (resource.getModel() == null) {
139             if (!vendorSoftwareProduct.getModelList().isEmpty()) {
140                 var modelStringList = String.join(", ", vendorSoftwareProduct.getModelList());
141                 throw new ByActionStatusComponentException(ActionStatus.VSP_MODEL_NOT_ALLOWED, DEFAULT_MODEL_NAME, modelStringList);
142             }
143             return;
144         }
145         if (!vendorSoftwareProduct.getModelList().contains(resource.getModel())) {
146             var modelStringList =
147                 vendorSoftwareProduct.getModelList().isEmpty() ? DEFAULT_MODEL_NAME : String.join(", ", vendorSoftwareProduct.getModelList());
148             throw new ByActionStatusComponentException(ActionStatus.VSP_MODEL_NOT_ALLOWED, resource.getModel(), modelStringList);
149         }
150     }
151
152     public ServiceCsarInfo getCsarInfo(Service service, Service oldResource, User user, Map<String, byte[]> payload, String csarUUID) {
153         Map<String, byte[]> csar = getCsar(service, user, payload, csarUUID);
154         ImmutablePair<String, String> toscaYamlCsarStatus = validateAndParseCsar(service, user, csar, csarUUID).left()
155             .on(this::throwComponentException);
156         String checksum = CsarValidationUtils.getToscaYamlChecksum(csar, csarUUID, componentsUtils).left()
157             .on(r -> logAndThrowComponentException(r, "Failed to calculate checksum for casrUUID {} error {} ", csarUUID));
158         if (oldResource != null && !checksum
159             .equals(oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().getImportedToscaChecksum())) {
160             log.debug(
161                 "The checksum of main template yaml of csar with csarUUID {} is not equal to the previous one, existing checksum is {}, new one is {}.",
162                 csarUUID, oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().getImportedToscaChecksum(), checksum);
163             oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().setImportedToscaChecksum(checksum);
164         }
165         return new ServiceCsarInfo(user, csarUUID, csar, service.getName(), service.getModel(), toscaYamlCsarStatus.getKey(),
166             toscaYamlCsarStatus.getValue(), true, modelOperation);
167     }
168
169     public ParsedToscaYamlInfo getParsedToscaYamlInfo(String topologyTemplateYaml, String yamlName, Map<String, NodeTypeInfo> nodeTypesInfo,
170                                                       CsarInfo csarInfo, String nodeName, Component component) {
171         return yamlHandler
172             .parseResourceInfoFromYAML(yamlName, topologyTemplateYaml, csarInfo.getCreatedNodesToscaResourceNames(), nodeTypesInfo, nodeName,
173                 component, getInterfaceTemplateYaml(csarInfo).orElse(""));
174     }
175
176     private Optional<String> getInterfaceTemplateYaml(CsarInfo csarInfo) {
177         String[] yamlFile;
178         String interfaceTemplateYaml = "";
179         if (csarInfo.getMainTemplateName().contains(".yml")) {
180             yamlFile = csarInfo.getMainTemplateName().split(".yml");
181             interfaceTemplateYaml = yamlFile[0] + "-interface.yml";
182         } else if (csarInfo.getMainTemplateName().contains(".yaml")) {
183             yamlFile = csarInfo.getMainTemplateName().split(".yaml");
184             interfaceTemplateYaml = yamlFile[0] + "-interface.yaml";
185         }
186         if (csarInfo.getCsar().containsKey(interfaceTemplateYaml)) {
187             return Optional.of(new String(csarInfo.getCsar().get(interfaceTemplateYaml)));
188         }
189         return Optional.empty();
190     }
191
192     private String logAndThrowComponentException(ResponseFormat responseFormat, String logMessage, String... params) {
193         log.debug(logMessage, params, responseFormat);
194         throw new ByResponseFormatComponentException(responseFormat);
195     }
196
197     private ImmutablePair<String, String> throwComponentException(ResponseFormat responseFormat) {
198         throw new ByResponseFormatComponentException(responseFormat);
199     }
200
201     private Either<ImmutablePair<String, String>, ResponseFormat> validateAndParseCsar(Component component, User user, Map<String, byte[]> csar,
202                                                                                        String csarUUID) {
203         Either<Boolean, ResponseFormat> validateCsarStatus = CsarValidationUtils.validateCsar(csar, csarUUID, componentsUtils);
204         if (validateCsarStatus.isRight()) {
205             ResponseFormat responseFormat = validateCsarStatus.right().value();
206             log.debug("Error when validate csar with ID {}, error: {}", csarUUID, responseFormat);
207             BeEcompErrorManager.getInstance().logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED);
208             if (component instanceof Resource) {
209                 componentsUtils.auditResource(responseFormat, user, (Resource) component, AuditingActionEnum.CREATE_RESOURCE);
210             }
211             return Either.right(responseFormat);
212         }
213         Either<ImmutablePair<String, String>, ResponseFormat> toscaYamlCsarStatus = CsarValidationUtils.getToscaYaml(csar, csarUUID, componentsUtils);
214         if (toscaYamlCsarStatus.isRight()) {
215             ResponseFormat responseFormat = toscaYamlCsarStatus.right().value();
216             log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
217             BeEcompErrorManager.getInstance().logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED);
218             if (component instanceof Resource) {
219                 componentsUtils.auditResource(responseFormat, user, (Resource) component, AuditingActionEnum.CREATE_RESOURCE);
220             }
221             return Either.right(responseFormat);
222         }
223         return toscaYamlCsarStatus;
224     }
225
226     private Map<String, byte[]> getCsar(Component component, User user, Map<String, byte[]> payload, String csarUUID) {
227         if (payload != null) {
228             return payload;
229         }
230         Either<Map<String, byte[]>, StorageOperationStatus> csar = csarOperation.findVspLatestPackage(csarUUID, user);
231         if (csar.isRight()) {
232             StorageOperationStatus value = csar.right().value();
233             log.debug("#getCsar - failed to fetch csar with ID {}, error: {}", csarUUID, value);
234             BeEcompErrorManager.getInstance().logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED);
235             ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(value), csarUUID);
236             if (component instanceof Resource) {
237                 Resource newResource = (Resource) component;
238                 componentsUtils.auditResource(responseFormat, user, newResource, AuditingActionEnum.CREATE_RESOURCE);
239             }
240             throw new StorageException(csar.right().value());
241         }
242         return csar.left().value();
243     }
244
245     private VendorSoftwareProduct getCsar(final Resource resource, final User user) {
246         final Optional<VendorSoftwareProduct> vendorSoftwareProductOpt;
247         try {
248             if (resource.getCsarVersionId() == null) {
249                 vendorSoftwareProductOpt = csarOperation.findLatestVsp(resource.getCsarUUID(), user);
250             } else {
251                 vendorSoftwareProductOpt = csarOperation.findVsp(resource.getCsarUUID(), resource.getCsarVersionId(), user);
252             }
253         } catch (final Exception exception) {
254             log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, CsarBusinessLogic.class.getName(), exception.getMessage());
255             auditGetCsarError(resource, user, resource.getCsarUUID(), StorageOperationStatus.GENERAL_ERROR);
256             throw new ByActionStatusComponentException(ActionStatus.VSP_FIND_ERROR, resource.getCsarUUID(), resource.getCsarVersionId());
257         }
258         if (vendorSoftwareProductOpt.isEmpty()) {
259             auditGetCsarError(resource, user, resource.getCsarUUID(), StorageOperationStatus.CSAR_NOT_FOUND);
260             throw new ByActionStatusComponentException(ActionStatus.VSP_NOT_FOUND, resource.getCsarUUID(), resource.getCsarVersionId());
261         }
262         return vendorSoftwareProductOpt.get();
263     }
264
265     private void auditGetCsarError(Component component, User user, String csarUUID, StorageOperationStatus storageOperationStatus) {
266         log.debug("#getCsar - failed to fetch csar with ID {}, error: {}", csarUUID, storageOperationStatus);
267         BeEcompErrorManager.getInstance().logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED);
268         var responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(storageOperationStatus), csarUUID);
269         if (component instanceof Resource) {
270             componentsUtils.auditResource(responseFormat, user, (Resource) component, AuditingActionEnum.CREATE_RESOURCE);
271         }
272     }
273
274     private void auditAndThrowException(Resource resource, User user, AuditingActionEnum auditingAction, ActionStatus status, String... params) {
275         ResponseFormat errorResponse = componentsUtils.getResponseFormat(status, params);
276         componentsUtils.auditResource(errorResponse, user, resource, auditingAction);
277         throw new ByResponseFormatComponentException(errorResponse, params);
278     }
279
280     private Either<ImmutablePair<String, String>, ResponseFormat> validateAndParseCsar(Service service, User user, Map<String, byte[]> payload,
281                                                                                        String csarUUID) {
282         Map<String, byte[]> csar = getCsar(service, user, payload, csarUUID);
283         Either<Boolean, ResponseFormat> validateCsarStatus = CsarValidationUtils.validateCsar(csar, csarUUID, componentsUtils);
284         if (validateCsarStatus.isRight()) {
285             ResponseFormat responseFormat = validateCsarStatus.right().value();
286             log.debug("Error when validate csar with ID {}, error: {}", csarUUID, responseFormat);
287             BeEcompErrorManager.getInstance().logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED);
288             return Either.right(responseFormat);
289         }
290         Either<ImmutablePair<String, String>, ResponseFormat> toscaYamlCsarStatus = CsarValidationUtils.getToscaYaml(csar, csarUUID, componentsUtils);
291         if (toscaYamlCsarStatus.isRight()) {
292             ResponseFormat responseFormat = toscaYamlCsarStatus.right().value();
293             log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
294             BeEcompErrorManager.getInstance().logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED);
295             return Either.right(responseFormat);
296         }
297         return toscaYamlCsarStatus;
298     }
299 }