From 13af621442b4c74d9e63ede8e42dbae48aaa64c9 Mon Sep 17 00:00:00 2001 From: "andre.schmid" Date: Tue, 8 Oct 2019 18:27:36 +0100 Subject: Onboard PNF software version Change-Id: Id9e32e01f6c2f4c39c8ff10816d982cbb3063bf7 Issue-ID: SDC-2589 Signed-off-by: andre.schmid --- .../openecomp/sdc/be/components/csar/CsarInfo.java | 88 +++++++------- .../be/components/csar/PnfSoftwareInformation.java | 68 +++++++++++ .../sdc/be/components/csar/PnfSoftwareVersion.java | 45 +++++++ .../SoftwareInformationArtifactYamlParser.java | 89 ++++++++++++++ .../be/components/impl/PropertyBusinessLogic.java | 122 +++++++++++++++++++ .../be/components/impl/ResourceBusinessLogic.java | 61 +++++++--- .../impl/SoftwareInformationBusinessLogic.java | 129 +++++++++++++++++++++ .../impl/exceptions/BusinessLogicException.java | 32 +++++ 8 files changed, 571 insertions(+), 63 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/PnfSoftwareInformation.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/PnfSoftwareVersion.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/SoftwareInformationArtifactYamlParser.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/SoftwareInformationBusinessLogic.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/BusinessLogicException.java (limited to 'catalog-be/src/main/java/org') diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarInfo.java index 1d49394b17..05c36b3ae0 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarInfo.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarInfo.java @@ -21,9 +21,17 @@ */ package org.openecomp.sdc.be.components.csar; +import com.google.common.annotations.VisibleForTesting; import fj.data.Either; +import lombok.Getter; +import lombok.Setter; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; +import org.openecomp.sdc.be.config.NonManoArtifactType; +import org.openecomp.sdc.be.config.NonManoConfiguration; +import org.openecomp.sdc.be.config.NonManoConfigurationManager; +import org.openecomp.sdc.be.config.NonManoFolderType; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.model.NodeTypeInfo; import org.openecomp.sdc.be.model.Resource; @@ -42,17 +50,31 @@ import static org.openecomp.sdc.be.components.impl.ImportUtils.*; public class CsarInfo { private static final Logger log = Logger.getLogger(CsarInfo.class); + @Getter + @Setter private String vfResourceName; + @Getter + @Setter private User modifier; + @Getter + @Setter private String csarUUID; + @Getter + @Setter private Map csar; + @Getter private String mainTemplateName; + @Getter private String mainTemplateContent; + @Getter private Map mappedToscaMainTemplate; + @Getter private Map createdNodesToscaResourceNames; private Queue cvfcToCreateQueue; private boolean isUpdate; + @Getter private Map createdNodes; + private final NonManoConfiguration nonManoConfiguration; @SuppressWarnings("unchecked") public CsarInfo(User modifier, String csarUUID, Map csar, String vfResourceName, String mainTemplateName, String mainTemplateContent, boolean isUpdate){ @@ -67,46 +89,12 @@ public class CsarInfo { this.cvfcToCreateQueue = new PriorityQueue<>(); this.isUpdate = isUpdate; this.createdNodes = new HashMap<>(); + this.nonManoConfiguration = NonManoConfigurationManager.getInstance().getNonManoConfiguration(); } - public String getVfResourceName() { - return vfResourceName; - } - - public void setVfResourceName(String vfResourceName) { - this.vfResourceName = vfResourceName; - } - - public User getModifier() { - return modifier; - } - - public void setModifier(User modifier) { - this.modifier = modifier; - } - - public String getCsarUUID() { - return csarUUID; - } - - public void setCsarUUID(String csarUUID) { - this.csarUUID = csarUUID; - } - - public Map getCsar() { - return csar; - } - - public void setCsar(Map csar) { - this.csar = csar; - } - - public Map getMappedToscaMainTemplate() { - return mappedToscaMainTemplate; - } - - public Map getCreatedNodesToscaResourceNames() { - return createdNodesToscaResourceNames; + @VisibleForTesting + CsarInfo(final NonManoConfiguration nonManoConfiguration) { + this.nonManoConfiguration = nonManoConfiguration; } public void addNodeToQueue(String nodeName) { @@ -132,10 +120,6 @@ public class CsarInfo { this.isUpdate = isUpdate; } - public Map getCreatedNodes() { - return createdNodes; - } - public Map extractNodeTypesInfo() { Map nodeTypesInfo = new HashMap<>(); List> globalSubstitutes = new ArrayList<>(); @@ -236,11 +220,19 @@ public class CsarInfo { } } - public String getMainTemplateName() { - return mainTemplateName; - } - - public String getMainTemplateContent() { - return mainTemplateContent; + /** + * Gets the software information yaml path from the csar file map. + * + * @return the software information yaml path if it is present in the csar file map + */ + public Optional getSoftwareInformationPath() { + if (MapUtils.isEmpty(csar)) { + return Optional.empty(); + } + final NonManoFolderType softwareInformationType = + nonManoConfiguration.getNonManoType(NonManoArtifactType.ONAP_SW_INFORMATION); + return csar.keySet().stream() + .filter(filePath -> filePath.startsWith(softwareInformationType.getPath())) + .findFirst(); } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/PnfSoftwareInformation.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/PnfSoftwareInformation.java new file mode 100644 index 0000000000..8595fc9698 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/PnfSoftwareInformation.java @@ -0,0 +1,68 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.csar; + +import java.util.LinkedHashSet; +import java.util.Set; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +/** + * Represents the Pnf software information non-mano yaml + */ +@Getter +@Setter +public class PnfSoftwareInformation { + + private String description; + private String provider; + private String version; + @Setter(AccessLevel.NONE) + private Set softwareVersionSet = new LinkedHashSet<>(); + + /** + * Adds a {@link PnfSoftwareVersion} instance to the software version set + * @param softwareVersion the pnf software version to add + */ + public void addToSoftwareVersionSet(final PnfSoftwareVersion softwareVersion) { + softwareVersionSet.add(softwareVersion); + } + + public Set getSoftwareVersionSet() { + return new LinkedHashSet<>(softwareVersionSet); + } + + /** + * Stores the software information yaml field names. + */ + @AllArgsConstructor + @Getter + public enum PnfSoftwareInformationField { + DESCRIPTION("description"), + PROVIDER("provider"), + VERSION("version"), + PNF_SOFTWARE_INFORMATION("pnf_software_information"); + + private final String fieldName; + + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/PnfSoftwareVersion.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/PnfSoftwareVersion.java new file mode 100644 index 0000000000..0dc4679e53 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/PnfSoftwareVersion.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.csar; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +@AllArgsConstructor +@EqualsAndHashCode +@Getter +public class PnfSoftwareVersion { + + private final String version; + private final String description; + + /** + * Stores the pnf software version yaml fields. + */ + @Getter + @AllArgsConstructor + public enum PnfSoftwareVersionField { + DESCRIPTION("description"), + PNF_SOFTWARE_VERSION("pnf_software_version"); + + private final String fieldName; + } +} \ No newline at end of file diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/SoftwareInformationArtifactYamlParser.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/SoftwareInformationArtifactYamlParser.java new file mode 100644 index 0000000000..ec34e21945 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/SoftwareInformationArtifactYamlParser.java @@ -0,0 +1,89 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.csar; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import org.apache.commons.collections.CollectionUtils; +import org.onap.sdc.tosca.services.YamlUtil; +import org.openecomp.sdc.be.components.csar.PnfSoftwareInformation.PnfSoftwareInformationField; +import org.openecomp.sdc.be.components.csar.PnfSoftwareVersion.PnfSoftwareVersionField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.error.YAMLException; + +/** + * Handles the parsing of the non-mano software information file. + */ +public class SoftwareInformationArtifactYamlParser { + private static final Logger LOGGER = LoggerFactory.getLogger(SoftwareInformationArtifactYamlParser.class); + + private SoftwareInformationArtifactYamlParser() { + + } + + /** + * Parses the non-mano software information yaml file. + * + * @param softwareInformationYamlFileBytes the file byte array + * @return an {@code Optional} if the file was successful parsed, otherwise {@code + * Optional.empty()} + */ + @SuppressWarnings("unchecked") + public static Optional parse(final byte[] softwareInformationYamlFileBytes) { + final Map softwareVersionYamlObject; + try (final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(softwareInformationYamlFileBytes)) { + final Object yaml = YamlUtil.read(byteArrayInputStream); + if (!(yaml instanceof Map)) { + return Optional.empty(); + } + + softwareVersionYamlObject = (Map) yaml; // unchecked warning suppressed + } catch (final IOException | YAMLException e) { + LOGGER.warn("Could not parse the software information yaml file", e); + return Optional.empty(); + } + + final PnfSoftwareInformation pnfSoftwareInformation = new PnfSoftwareInformation(); + pnfSoftwareInformation.setDescription( + (String) softwareVersionYamlObject.get(PnfSoftwareInformationField.DESCRIPTION.getFieldName())); + pnfSoftwareInformation.setProvider( + (String) softwareVersionYamlObject.get(PnfSoftwareInformationField.PROVIDER.getFieldName())); + pnfSoftwareInformation.setVersion( + (String) softwareVersionYamlObject.get(PnfSoftwareInformationField.VERSION.getFieldName())); + final List> pnfSoftwareInformationYaml = (List>) softwareVersionYamlObject + .get(PnfSoftwareInformationField.PNF_SOFTWARE_INFORMATION.getFieldName()); // unchecked warning suppressed + + if (CollectionUtils.isNotEmpty(pnfSoftwareInformationYaml)) { + pnfSoftwareInformationYaml.forEach(stringStringMap -> { + final String description = stringStringMap.get(PnfSoftwareVersionField.DESCRIPTION.getFieldName()); + final String version = stringStringMap.get(PnfSoftwareVersionField.PNF_SOFTWARE_VERSION.getFieldName()); + pnfSoftwareInformation.addToSoftwareVersionSet(new PnfSoftwareVersion(version, description)); + }); + } + + return Optional.of(pnfSoftwareInformation); + } + + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java index 950971ef0b..1391e205cd 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java @@ -32,6 +32,7 @@ import javax.servlet.ServletContext; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.tuple.ImmutablePair; +import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; @@ -51,18 +52,21 @@ import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ToscaOperationException; import org.openecomp.sdc.be.model.operations.api.IElementOperation; import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation; import org.openecomp.sdc.be.model.operations.api.IGroupOperation; import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; +import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter; import org.openecomp.sdc.be.model.tosca.validators.PropertyTypeValidator; import org.openecomp.sdc.be.resources.data.EntryData; import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.beans.factory.annotation.Autowired; @@ -216,6 +220,75 @@ public class PropertyBusinessLogic extends BaseBusinessLogic { } + /** + * Copies a list of properties to a component. + * + * @param component the component to add the copied properties + * @param propertiesToCopyList the properties to be copied + * @return the updated component with the copied properties. + * @throws ToscaOperationException when a problem happens during the copy operation + */ + public Component copyPropertyToComponent(final Component component, + final List propertiesToCopyList) throws ToscaOperationException { + return copyPropertyToComponent(component, propertiesToCopyList, true); + } + + /** + * Copies a list of properties to a component. + * + * @param component the component to add the copied properties + * @param propertiesToCopyList the properties to be copied + * @param refreshComponent refresh the component from database after update + * @return the component refreshed from database if refreshComponent is {@code true}, the same component reference + * otherwise + * @throws ToscaOperationException when a problem happens during the copy operation + */ + public Component copyPropertyToComponent(final Component component, + final List propertiesToCopyList, + final boolean refreshComponent) throws ToscaOperationException { + if (CollectionUtils.isEmpty(propertiesToCopyList)) { + return component; + } + + for (final PropertyDefinition propertyDefinition : propertiesToCopyList) { + copyPropertyToComponent(component, propertyDefinition); + } + + if (refreshComponent) { + return toscaOperationFacade.getToscaElement(component.getUniqueId()).left().value(); + } + + return component; + } + + /** + * Copies one property to a component. + * + * @param component the component to add the copied property + * @param propertyDefinition the property to be copied + * @throws ToscaOperationException when a problem happens during the copy operation + */ + private void copyPropertyToComponent(final Component component, + final PropertyDefinition propertyDefinition) throws ToscaOperationException { + final PropertyDefinition copiedPropertyDefinition = new PropertyDefinition(propertyDefinition); + final String componentId = component.getUniqueId(); + final String propertyName = copiedPropertyDefinition.getName(); + copiedPropertyDefinition.setUniqueId( + UniqueIdBuilder.buildPropertyUniqueId(componentId, propertyName) + ); + copiedPropertyDefinition.setParentUniqueId(componentId); + final Either operationResult = toscaOperationFacade + .addPropertyToComponent(propertyName, copiedPropertyDefinition, component); + if (operationResult.isRight()) { + final String error = String.format( + "Failed to add copied property '%s' to component '%s'. Operation status: '%s'", + propertyDefinition.getUniqueId(), componentId, operationResult.right().value() + ); + log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, PropertyBusinessLogic.class.getName(), "catalog-be", error); + throw new ToscaOperationException(error, operationResult.right().value()); + } + } + /** * Get property of component * @@ -477,6 +550,55 @@ public class PropertyBusinessLogic extends BaseBusinessLogic { } + /** + * Finds a component by id, + * + * @param componentId the component id to find + * @return an Optional if the component with given id was found, otherwise Optional.empty() + * @throws BusinessLogicException when a problem happens during the find operation + */ + public Optional findComponentById(final String componentId) throws BusinessLogicException { + final Either status = toscaOperationFacade.getToscaElement(componentId); + if (status.isRight()) { + final StorageOperationStatus operationStatus = status.right().value(); + if (operationStatus == StorageOperationStatus.NOT_FOUND) { + return Optional.empty(); + } + final ResponseFormat responseFormat = componentsUtils.getResponseFormat(operationStatus); + throw new BusinessLogicException(responseFormat); + } + return Optional.ofNullable(status.left().value()); + } + + /** + * Updates a component property. + * + * @param componentId the component id that owns the property + * @param propertyDefinition the existing property to update + * @return the updated property + * @throws BusinessLogicException if the component was not found or if there was a problem during the update + * operation. + */ + public PropertyDefinition updateComponentProperty(final String componentId, + final PropertyDefinition propertyDefinition) + throws BusinessLogicException { + final Component component = findComponentById(componentId).orElse(null); + if (component == null) { + throw new BusinessLogicException( + componentsUtils.getResponseFormatByResource(ActionStatus.RESOURCE_NOT_FOUND, componentId)); + } + final Either updateResultEither = + toscaOperationFacade.updatePropertyOfComponent(component, propertyDefinition); + if (updateResultEither.isRight()) { + final ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(updateResultEither.right().value()), component.getName() + ); + throw new BusinessLogicException(responseFormat); + } + + return updateResultEither.left().value(); + } + private boolean isPropertyExistInComponent(List properties, String propertyName) { if(CollectionUtils.isEmpty(properties)) { return false; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java index 12345e7802..bf848bf8f3 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java @@ -33,6 +33,7 @@ import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaStr import static org.openecomp.sdc.be.components.impl.ImportUtils.getPropertyJsonStringValue; import static org.openecomp.sdc.be.tosca.CsarUtils.VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN; +import fj.data.Either; import java.util.ArrayList; import java.util.Collection; import java.util.EnumMap; @@ -48,8 +49,7 @@ import java.util.Set; import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Collectors; - -import fj.data.Either; +import javax.servlet.ServletContext; import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -62,6 +62,7 @@ import org.openecomp.sdc.be.components.csar.CsarInfo; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationInfo; import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; +import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; @@ -131,6 +132,7 @@ import org.openecomp.sdc.be.model.category.CategoryDefinition; import org.openecomp.sdc.be.model.category.SubCategoryDefinition; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ToscaOperationException; import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.StorageException; import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation; @@ -159,21 +161,23 @@ import org.openecomp.sdc.common.api.ArtifactTypeEnum; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.datastructure.Wrapper; import org.openecomp.sdc.common.kpi.api.ASDCKpiApi; +import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.common.util.GeneralUtility; import org.openecomp.sdc.common.util.ValidationUtils; import org.openecomp.sdc.exception.ResponseFormat; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.web.context.WebApplicationContext; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; -import javax.servlet.ServletContext; - @org.springframework.stereotype.Component("resourceBusinessLogic") public class ResourceBusinessLogic extends ComponentBusinessLogic { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ResourceBusinessLogic.class); + private static final String DELETE_RESOURCE = "Delete Resource"; private static final String IN_RESOURCE = " in resource {} "; private static final String PLACE_HOLDER_RESOURCE_TYPES = "validForResourceTypes"; @@ -200,6 +204,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { private final MergeInstanceUtils mergeInstanceUtils; private final UiComponentDataConverter uiComponentDataConverter; private final CsarBusinessLogic csarBusinessLogic; + private final PropertyBusinessLogic propertyBusinessLogic; + private final SoftwareInformationBusinessLogic softwareInformationBusinessLogic; @Autowired public ResourceBusinessLogic(IElementOperation elementDao, @@ -215,7 +221,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ResourceDataMergeBusinessLogic resourceDataMergeBusinessLogic, CsarArtifactsAndGroupsBusinessLogic csarArtifactsAndGroupsBusinessLogic, MergeInstanceUtils mergeInstanceUtils, UiComponentDataConverter uiComponentDataConverter, CsarBusinessLogic csarBusinessLogic, - ArtifactsOperations artifactToscaOperation) { + ArtifactsOperations artifactToscaOperation, PropertyBusinessLogic propertyBusinessLogic, + SoftwareInformationBusinessLogic softwareInformationBusinessLogic) { super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, groupBusinessLogic, interfaceOperation, interfaceLifecycleTypeOperation, artifactsBusinessLogic, artifactToscaOperation); this.componentInstanceBusinessLogic = componentInstanceBusinessLogic; @@ -227,6 +234,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { this.mergeInstanceUtils = mergeInstanceUtils; this.uiComponentDataConverter = uiComponentDataConverter; this.csarBusinessLogic = csarBusinessLogic; + this.propertyBusinessLogic = propertyBusinessLogic; + this.softwareInformationBusinessLogic = softwareInformationBusinessLogic; } public LifecycleBusinessLogic getLifecycleBusinessLogic() { @@ -1346,26 +1355,37 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } try { log.trace("************* createResourceFromYaml before full create resource {}", yamlName); - Resource genericResource = fetchAndSetDerivedFromGenericType(resource); - resource = createResourceTransaction(resource, - csarInfo.getModifier(), isNormative); + final Resource genericResource = fetchAndSetDerivedFromGenericType(resource); + resource = createResourceTransaction(resource, csarInfo.getModifier(), isNormative); log.trace("************* createResourceFromYaml after full create resource {}", yamlName); log.trace("************* Going to add inputs from yaml {}", yamlName); - if (resource.shouldGenerateInputs()) + if (resource.shouldGenerateInputs()) { generateAndAddInputsFromGenericTypeProperties(resource, genericResource); - - Map inputs = parsedToscaYamlInfo.getInputs(); + } + final Map inputs = parsedToscaYamlInfo.getInputs(); resource = createInputsOnResource(resource, inputs); log.trace("************* Finish to add inputs from yaml {}", yamlName); + if (resource.getResourceType() == ResourceTypeEnum.PNF) { + log.trace("************* Adding generic properties to PNF"); + resource = (Resource) propertyBusinessLogic.copyPropertyToComponent(resource, genericResource.getProperties()); + log.trace("************* Adding software information to PNF"); + softwareInformationBusinessLogic.setSoftwareInformation(resource, csarInfo); + log.trace("************* Removing non-mano software information file from PNF"); + if (csarInfo.getSoftwareInformationPath().isPresent() && + !softwareInformationBusinessLogic.removeSoftwareInformationFile(csarInfo)) { + log.warn(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR , ResourceBusinessLogic.class.getName(), + "catalog-be", "Could not remove the software information file."); + } + } Map uploadComponentInstanceInfoMap = parsedToscaYamlInfo .getInstances(); - log.trace("************* Going to create nodes, RI's and Relations from yaml {}", yamlName); - + log.trace("************* Going to create nodes, Resource Instances and Relations from yaml {}", yamlName); resource = createRIAndRelationsFromYaml(yamlName, resource, uploadComponentInstanceInfoMap, topologyTemplateYaml, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeTypesArtifactsToCreate, nodeName); - log.trace("************* Finished to create nodes, RI and Relation from yaml {}", yamlName); + + log.trace("************* Finished to create nodes, Resource Instances and Relations from yaml {}", yamlName); // validate update vf module group names Either, ResponseFormat> validateUpdateVfGroupNamesRes = groupBusinessLogic .validateUpdateVfGroupNames(parsedToscaYamlInfo.getGroups(), resource.getSystemName()); @@ -1373,6 +1393,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ByResponseFormatComponentException(validateUpdateVfGroupNamesRes.right().value()); } + // add groups to resource Map groups; log.trace("************* Going to add groups from yaml {}", yamlName); @@ -1411,9 +1432,19 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ASDCKpiApi.countCreatedResourcesKPI(); return resource; - } catch(ComponentException|StorageException e) { + } catch (final ComponentException | StorageException e) { rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); throw e; + } catch (final ToscaOperationException e) { + LOGGER.error("An error has occurred during resource and resource instance creation", e); + rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); + log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR + , ResourceBusinessLogic.class.getName(), "catalog-be", e.getMessage()); + throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR); + } catch (final BusinessLogicException e) { + LOGGER.error("An error has occurred during resource and resource instance creation", e); + rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); + throw new ByResponseFormatComponentException(e.getResponseFormat()); } finally { if (!inTransaction) { janusGraphDao.commit(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/SoftwareInformationBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/SoftwareInformationBusinessLogic.java new file mode 100644 index 0000000000..9355921252 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/SoftwareInformationBusinessLogic.java @@ -0,0 +1,129 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.impl; + +import static java.util.stream.Collectors.toList; +import static org.openecomp.sdc.be.components.impl.ImportUtils.getPropertyJsonStringValue; + +import java.util.List; +import java.util.Optional; +import org.apache.commons.collections.CollectionUtils; +import org.openecomp.sdc.be.components.csar.CsarInfo; +import org.openecomp.sdc.be.components.csar.PnfSoftwareInformation; +import org.openecomp.sdc.be.components.csar.PnfSoftwareVersion; +import org.openecomp.sdc.be.components.csar.SoftwareInformationArtifactYamlParser; +import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component("softwareInformationBusinessLogic") +public class SoftwareInformationBusinessLogic { + + private final PropertyBusinessLogic propertyBusinessLogic; + private static final String SOFTWARE_VERSION_PROPERTY_NAME = "software_versions"; + + @Autowired + public SoftwareInformationBusinessLogic(final PropertyBusinessLogic propertyBusinessLogic) { + this.propertyBusinessLogic = propertyBusinessLogic; + } + + /** + * Adds the software information from a csar package to the resource {@link SoftwareInformationBusinessLogic#SOFTWARE_VERSION_PROPERTY_NAME} + * property.
The csar package must contain the expected non-mano yaml file with the software information. Also + * the resource must have the {@link SoftwareInformationBusinessLogic#SOFTWARE_VERSION_PROPERTY_NAME} property. + * + * @param resource the resource to add the software information + * @param csarInfo the csar package representation + * @return if the expected property exists in the resource and the csar package contains the software information + * file, an Optional with the updated property; otherwise Optional.empty(). + * @throws BusinessLogicException when there was a problem while updating the property + */ + public Optional setSoftwareInformation(final Resource resource, + final CsarInfo csarInfo) throws BusinessLogicException { + final Optional softwareInformation = csarInfo.getSoftwareInformationPath(); + if (!softwareInformation.isPresent()) { + return Optional.empty(); + } + final PropertyDefinition propertyDefinition = findSoftwareVersionPropertyDefinition(resource).orElse(null); + if (propertyDefinition == null) { + return Optional.empty(); + } + final byte[] softwareInformationYaml = csarInfo.getCsar().get(softwareInformation.get()); + final PnfSoftwareInformation pnfSoftwareInformation = + parseSoftwareInformation(softwareInformationYaml).orElse(null); + if (pnfSoftwareInformation == null) { + return Optional.empty(); + } + + final List versionList = pnfSoftwareInformation.getSoftwareVersionSet().stream() + .map(PnfSoftwareVersion::getVersion).collect(toList()); + final String softwareVersionInformation = + getPropertyJsonStringValue(versionList, ToscaPropertyType.LIST.getType()); + propertyDefinition.setValue(softwareVersionInformation); + + final PropertyDefinition updatedPropertyDefinition = + propertyBusinessLogic.updateComponentProperty(resource.getUniqueId(), propertyDefinition); + return Optional.ofNullable(updatedPropertyDefinition); + } + + /** + * Parses the non-mano software information yaml file. + * + * @param softwareInformationYaml the file byte array + * @return an {@code Optional} if the file was successful parsed, otherwise {@code + * Optional.empty()} + */ + private Optional parseSoftwareInformation(byte[] softwareInformationYaml) { + return SoftwareInformationArtifactYamlParser.parse(softwareInformationYaml); + } + + /** + * Finds the {@link SoftwareInformationBusinessLogic#SOFTWARE_VERSION_PROPERTY_NAME} property in a Resource + * @param resource the resource to search for the property + * @return an {@code Optional} if the property was found, otherwise {@code Optional.empty()} + */ + private Optional findSoftwareVersionPropertyDefinition(final Resource resource) { + if (CollectionUtils.isEmpty(resource.getProperties())) { + return Optional.empty(); + } + return resource.getProperties().stream() + .filter(propertyDefinition -> propertyDefinition.getName().equals(SOFTWARE_VERSION_PROPERTY_NAME)) + .findFirst(); + } + + /** + * Removes the non-mano software information file from the csar package + * + * @param csarInfo the csar package representation + * @return {@code true} if the file was removed, otherwise {@code false} + */ + public boolean removeSoftwareInformationFile(final CsarInfo csarInfo) { + final Optional softwareInformation = csarInfo.getSoftwareInformationPath(); + if (!softwareInformation.isPresent()) { + return false; + } + + csarInfo.getCsar().remove(softwareInformation.get()); + return true; + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/BusinessLogicException.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/BusinessLogicException.java new file mode 100644 index 0000000000..acf80cb5d0 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/BusinessLogicException.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.impl.exceptions; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.openecomp.sdc.exception.ResponseFormat; + +@AllArgsConstructor +public class BusinessLogicException extends Exception { + + @Getter + private final ResponseFormat responseFormat; + +} -- cgit 1.2.3-korg