X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=catalog-be%2Fsrc%2Fmain%2Fjava%2Forg%2Fopenecomp%2Fsdc%2Fbe%2Fcomponents%2Fimpl%2FResourceBusinessLogic.java;h=77d17ca76ae02cf7fd54ad6f330491ee11e85b8a;hb=7f07f514eacacfb54d851201c49b24acd9b5e343;hp=d692b4fc81948a80d02b7ebfc75163e4d105cfa1;hpb=30b974a429821c7a065b393b690e2380afce3284;p=sdc.git 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 d692b4fc81..77d17ca76a 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 @@ -19,7 +19,6 @@ */ package org.openecomp.sdc.be.components.impl; -import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toSet; @@ -31,8 +30,6 @@ import static org.openecomp.sdc.be.components.impl.ImportUtils.getPropertyJsonSt import static org.openecomp.sdc.be.tosca.CsarUtils.VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN; import static org.openecomp.sdc.common.api.Constants.DEFAULT_GROUP_VF_MODULE; -import com.google.common.annotations.VisibleForTesting; -import fj.data.Either; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -44,11 +41,13 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Collectors; + import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -86,8 +85,7 @@ import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; -import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao; import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum; import org.openecomp.sdc.be.datamodel.utils.ArtifactUtils; import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter; @@ -102,6 +100,7 @@ import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.CreatedFrom; +import org.openecomp.sdc.be.datatypes.enums.ModelTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; @@ -122,10 +121,12 @@ import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.LifeCycleTransitionEnum; import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.Model; import org.openecomp.sdc.be.model.NodeTypeInfo; import org.openecomp.sdc.be.model.Operation; import org.openecomp.sdc.be.model.ParsedToscaYamlInfo; import org.openecomp.sdc.be.model.PolicyDefinition; +import org.openecomp.sdc.be.model.PolicyTypeDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.RelationshipImpl; import org.openecomp.sdc.be.model.RelationshipInfo; @@ -155,7 +156,6 @@ 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.IInterfaceLifecycleOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; -import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; 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; @@ -186,6 +186,10 @@ import org.springframework.context.annotation.Lazy; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; +import com.google.common.annotations.VisibleForTesting; + +import fj.data.Either; + @org.springframework.stereotype.Component("resourceBusinessLogic") public class ResourceBusinessLogic extends ComponentBusinessLogic { @@ -201,6 +205,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { private static final String CREATE_RESOURCE_VALIDATE_CAPABILITY_TYPES = "Create Resource - validateCapabilityTypesCreate"; private static final String COMPONENT_INSTANCE_WITH_NAME = "component instance with name "; private static final String COMPONENT_INSTANCE_WITH_NAME_IN_RESOURCE = "component instance with name {} in resource {} "; + private static final String VALID_CHARACTERS_ARTIFACT_NAME = "'A-Z', 'a-z', '0-9', '.', '_', '-', '@' and space"; private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(ResourceBusinessLogic.class.getName()); private final ComponentInstanceBusinessLogic componentInstanceBusinessLogic; private final ResourceImportManager resourceImportManager; @@ -214,8 +219,12 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { private final CsarBusinessLogic csarBusinessLogic; private final PropertyBusinessLogic propertyBusinessLogic; private final PolicyBusinessLogic policyBusinessLogic; + private final ModelBusinessLogic modelBusinessLogic; private IInterfaceLifecycleOperation interfaceTypeOperation; private LifecycleBusinessLogic lifecycleBusinessLogic; + private final DataTypeBusinessLogic dataTypeBusinessLogic; + private final PolicyTypeBusinessLogic policyTypeBusinessLogic; + @Autowired private ICapabilityTypeOperation capabilityTypeOperation; @Autowired @@ -227,6 +236,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { @Autowired private SoftwareInformationBusinessLogic softwareInformationBusinessLogic; + @Autowired public ResourceBusinessLogic(final IElementOperation elementDao, final IGroupOperation groupOperation, final IGroupInstanceOperation groupInstanceOperation, final IGroupTypeOperation groupTypeOperation, @@ -244,7 +254,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { final ComponentNameValidator componentNameValidator, final ComponentTagsValidator componentTagsValidator, final ComponentValidator componentValidator, final ComponentIconValidator componentIconValidator, final ComponentProjectCodeValidator componentProjectCodeValidator, - final ComponentDescriptionValidator componentDescriptionValidator, final PolicyBusinessLogic policyBusinessLogic) { + final ComponentDescriptionValidator componentDescriptionValidator, final PolicyBusinessLogic policyBusinessLogic, + final ModelBusinessLogic modelBusinessLogic, + final DataTypeBusinessLogic dataTypeBusinessLogic, final PolicyTypeBusinessLogic policyTypeBusinessLogic) { super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, groupBusinessLogic, interfaceOperation, interfaceLifecycleTypeOperation, artifactsBusinessLogic, artifactToscaOperation, componentContactIdValidator, componentNameValidator, componentTagsValidator, componentValidator, componentIconValidator, componentProjectCodeValidator, componentDescriptionValidator); @@ -260,6 +272,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { this.csarBusinessLogic = csarBusinessLogic; this.propertyBusinessLogic = propertyBusinessLogic; this.policyBusinessLogic = policyBusinessLogic; + this.modelBusinessLogic = modelBusinessLogic; + this.dataTypeBusinessLogic = dataTypeBusinessLogic; + this.policyTypeBusinessLogic = policyTypeBusinessLogic; } static Either rollbackWithEither(final JanusGraphDao janusGraphDao, final ActionStatus actionStatus, @@ -510,7 +525,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { List createdArtifacts = new ArrayList<>(); CsarInfo csarInfo = csarBusinessLogic.getCsarInfo(newResource, oldResource, user, csarUIPayload, csarUUID); lockComponent(lockedResourceId, oldResource, "update Resource From Csar"); - Map nodeTypesInfo = csarInfo.extractNodeTypesInfo(); + Map nodeTypesInfo = csarInfo.extractTypesInfo(); Either>>, ResponseFormat> findNodeTypesArtifactsToHandleRes = findNodeTypesArtifactsToHandle( nodeTypesInfo, csarInfo, oldResource); if (findNodeTypesArtifactsToHandleRes.isRight()) { @@ -561,14 +576,18 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { preparedResource = updateExistingResourceByImport(newResource, oldResource, csarInfo.getModifier(), inTransaction, shouldLock, isNested).left; log.trace("YAML topology file found in CSAR, file name: {}, contents: {}", yamlFileName, yamlFileContent); - handleResourceGenericType(preparedResource); + handleResourceGenericType(preparedResource, yamlFileContent, uploadComponentInstanceInfoMap, + uploadComponentInstanceInfoMap.getSubstitutionMappingNodeType()); handleNodeTypes(yamlFileName, preparedResource, yamlFileContent, shouldLock, nodeTypesArtifactsToHandle, createdArtifacts, nodeTypesInfo, - csarInfo, nodeName); + csarInfo, nodeName, newResource.getModel()); preparedResource = createInputsOnResource(preparedResource, uploadComponentInstanceInfoMap.getInputs()); Map existingNodeTypesByResourceNames = new HashMap<>(); - preparedResource = createResourceInstances(yamlFileName, preparedResource, oldResource, instances, csarInfo.getCreatedNodes(), + final Map instancesToCreate = getInstancesToCreate(uploadComponentInstanceInfoMap, + newResource.getModel()); + preparedResource = createResourceInstances(yamlFileName, preparedResource, oldResource, instancesToCreate, csarInfo.getCreatedNodes(), existingNodeTypesByResourceNames); - preparedResource = createResourceInstancesRelations(csarInfo.getModifier(), yamlFileName, preparedResource, oldResource, instances, + preparedResource = createResourceInstancesRelations(csarInfo.getModifier(), yamlFileName, preparedResource, oldResource, + instancesToCreate, existingNodeTypesByResourceNames); } catch (ComponentException e) { ResponseFormat responseFormat = @@ -717,12 +736,32 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { private Resource handleResourceGenericType(Resource resource) { Resource genericResource = fetchAndSetDerivedFromGenericType(resource); + if (resource.shouldGenerateInputs()) { generateAndAddInputsFromGenericTypeProperties(resource, genericResource); } return genericResource; } + private Resource handleResourceGenericType(final Resource resource, final String topologyTemplateYaml, + final ParsedToscaYamlInfo parsedToscaYamlInfo, final String substitutionMappingNodeType) { + if (processSubstitutableAsNodeType(resource, parsedToscaYamlInfo)) { + final Map substitutableAsNodeType = getSubstitutableAsNodeTypeFromTemplate( + (Map) new Yaml().load(topologyTemplateYaml), substitutionMappingNodeType); + final Resource genericResource = fetchAndSetDerivedFromGenericType(resource, + (String) substitutableAsNodeType.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName())); + + generatePropertiesFromGenericType(resource, genericResource); + generatePropertiesFromNodeType(resource, substitutableAsNodeType); + final String resourceId = resource.getUniqueId(); + resource.getProperties().forEach(propertyDefinition -> propertyDefinition.setUniqueId( + UniqueIdBuilder.buildPropertyUniqueId(resourceId, propertyDefinition.getName()))); + createResourcePropertiesOnGraph(resource); + return genericResource; + } + return handleResourceGenericType(resource); + } + private Either>>, ResponseFormat> findNodeTypesArtifactsToHandle( final Map nodeTypesInfo, final CsarInfo csarInfo, final Resource oldResource) { final Map>> nodeTypesArtifactsToHandle = new HashMap<>(); @@ -788,7 +827,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { componentsUtils.auditResource(responseFormat, csarInfo.getModifier(), resource, AuditingActionEnum.CREATE_RESOURCE); throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status), csarInfo.getCsarUUID()); } else if (StringUtils.isNotEmpty(currVfcToscaName)) { - return (Resource) toscaOperationFacade.getLatestByToscaResourceName(currVfcToscaName).left() + return (Resource) toscaOperationFacade.getLatestByToscaResourceName(currVfcToscaName, resource.getModel()).left() .on(st -> findVfcResource(csarInfo, resource, previousVfcToscaName, null, st)); } return null; @@ -969,7 +1008,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (!nodes.isEmpty()) { for (Entry nodeType : nodes.entrySet()) { final ImmutablePair toscaResourceName = buildNestedToscaResourceName(ResourceTypeEnum.VFC.name(), vfResourceName, - nodeType.getKey()); + nodeType.getKey()); vfcToscaNames.put(nodeType.getKey(), toscaResourceName); } } @@ -1002,7 +1041,22 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { .log(LoggerSupportabilityActions.CREATE_RESOURCE_FROM_YAML, StatusCode.STARTED, "Starting to create Resource From Csar by user {}", user.getUserId()); CsarInfo csarInfo = csarBusinessLogic.getCsarInfo(resource, null, user, csarUIPayload, csarUUID); - Map nodeTypesInfo = csarInfo.extractNodeTypesInfo(); + Map nodeTypesInfo = csarInfo.extractTypesInfo(); + final String model = resource.getModel(); + if (StringUtils.isNotEmpty(model)) { + final Map dataTypesToCreate = getDatatypesToCreate(model, csarInfo.getDataTypes()); + final Map policyTypesToCreate = getPolicytypesToCreate(model, csarInfo.getPolicyTypes()); + if (MapUtils.isNotEmpty(dataTypesToCreate) || MapUtils.isNotEmpty(policyTypesToCreate)) { + createModel(resource, csarInfo.getVfResourceName()); + } + if (MapUtils.isNotEmpty(dataTypesToCreate)) { + dataTypeBusinessLogic.createDataTypeFromYaml(new Yaml().dump(dataTypesToCreate), model, true); + } + if (MapUtils.isNotEmpty(policyTypesToCreate)) { + policyTypeBusinessLogic.createPolicyTypeFromYaml(new Yaml().dump(policyTypesToCreate), model, true); + } + } + Either>>, ResponseFormat> findNodeTypesArtifactsToHandleRes = findNodeTypesArtifactsToHandle( nodeTypesInfo, csarInfo, resource); if (findNodeTypesArtifactsToHandleRes.isRight()) { @@ -1072,23 +1126,69 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { boolean needLock, Map>> nodeTypesArtifactsToHandle, List nodeTypesNewCreatedArtifacts, - Map nodeTypesInfo, CsarInfo csarInfo) { + Map nodeTypesInfo, CsarInfo csarInfo, + final String substitutableAsNodeType) { Either toscaVersion = findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION); if (toscaVersion.isRight()) { throw new ByActionStatusComponentException(ActionStatus.INVALID_TOSCA_TEMPLATE); } Map mapToConvert = new HashMap<>(); mapToConvert.put(TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION.getElementName(), toscaVersion.left().value()); - Map nodeTypes = getNodeTypesFromTemplate(mappedToscaTemplate); + final Map nodeTypes = getNodeTypesFromTemplate(mappedToscaTemplate, substitutableAsNodeType); createNodeTypes(yamlName, resource, needLock, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, mapToConvert, nodeTypes); return csarInfo.getCreatedNodes(); } - private Map getNodeTypesFromTemplate(Map mappedToscaTemplate) { + private Map getNodeTypesFromTemplate(final Map mappedToscaTemplate, final String substitutableAsNodeType) { + final Map nodeTypes = getAllNodeTypesInTemplate(mappedToscaTemplate); + if (StringUtils.isNotEmpty(substitutableAsNodeType)) { + nodeTypes.remove(substitutableAsNodeType); + } + return nodeTypes; + } + + @SuppressWarnings("unchecked") + private Map getSubstitutableAsNodeTypeFromTemplate(final Map mappedToscaTemplate, + final String substitutableAsNodeType) { + return (Map) getAllNodeTypesInTemplate(mappedToscaTemplate).get(substitutableAsNodeType); + } + + private Map getAllNodeTypesInTemplate(final Map mappedToscaTemplate) { return ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES).left().orValue(HashMap::new); } + private void createModel(final Resource resource, final String vfResourcename) { + final String nameForGeneratedModel = resource.getModel() + "_" + vfResourcename + resource.getCsarVersion(); + Model model = new Model(nameForGeneratedModel, resource.getModel(), ModelTypeEnum.NORMATIVE_EXTENSION); + modelBusinessLogic.createModel(model); + resource.setModel(nameForGeneratedModel); + } + + private Map getDatatypesToCreate(final String model, final Map dataTypes) { + final Map dataTypesToCreate = new HashMap<>(); + for (final String dataType : dataTypes.keySet()) { + final Either result = + propertyOperation.getDataTypeByName(dataType, model); + if (result.isRight() && result.right().value().equals(StorageOperationStatus.NOT_FOUND)) { + dataTypesToCreate.put(dataType, dataTypes.get(dataType)); + } + } + return dataTypesToCreate; + } + + private Map getPolicytypesToCreate(final String model, final Map policyTypes) { + final Map policyTypesToCreate = new HashMap<>(); + for (final String policyType : policyTypes.keySet()) { + final Either result = + policyTypeOperation.getLatestPolicyTypeByType(policyType, model); + if (result.isRight() && result.right().value().equals(StorageOperationStatus.NOT_FOUND)) { + policyTypesToCreate.put(policyType, policyTypes.get(policyType)); + } + } + return policyTypesToCreate; + } + private void createNodeTypes(String yamlName, Resource resource, boolean needLock, Map>> nodeTypesArtifactsToHandle, List nodeTypesNewCreatedArtifacts, Map nodeTypesInfo, CsarInfo csarInfo, @@ -1127,7 +1227,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map nestedVfcJsonMap = nodesInfo.get(nodeName).getMappedToscaTemplate(); log.debug("************* Going to create node types from yaml {}", yamlName); createResourcesFromYamlNodeTypesList(yamlName, resource, nestedVfcJsonMap, false, nodesArtifactsToHandle, createdArtifacts, - Collections.emptyMap(), csarInfo); + Collections.emptyMap(), csarInfo, resource.getModel()); log.debug("************* Finished to create node types from yaml {}", yamlName); if (nestedVfcJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE.getElementName())) { log.debug("************* Going to handle complex VFC from yaml {}", yamlName); @@ -1314,6 +1414,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { resourceMetaData.setContactId(user.getUserId()); resourceMetaData.setVendorName(resourceVf.getVendorName()); resourceMetaData.setVendorRelease(resourceVf.getVendorRelease()); + resourceMetaData.setModel(resourceVf.getModel()); // Setting tag final List tags = new ArrayList<>(); tags.add(resourceMetaData.getName()); @@ -1346,6 +1447,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { cvfc.setCreatorUserId(csarInfo.getModifier().getUserId()); cvfc.setVendorName(resourceVf.getVendorName()); cvfc.setVendorRelease(resourceVf.getVendorRelease()); + cvfc.setModel(resourceVf.getModel()); cvfc.setResourceVendorModelNumber(resourceVf.getResourceVendorModelNumber()); cvfc.setToscaResourceName(buildNestedToscaResourceName(ResourceTypeEnum.CVFC.name(), csarInfo.getVfResourceName(), nodeName).getLeft()); cvfc.setInvariantUUID(UniqueIdBuilder.buildInvariantUUID()); @@ -1393,36 +1495,65 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { log.trace("************* createResourceFromYaml before full create resource {}", yamlName); loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, resource.getComponentMetadataForSupportLog(), StatusCode.STARTED, "Starting to add inputs from yaml: {}", yamlName); - 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()) { - generateAndAddInputsFromGenericTypeProperties(resource, genericResource); - } - final Map inputs = parsedToscaYamlInfo.getInputs(); - resource = createInputsOnResource(resource, inputs); - log.trace("************* Finish to add inputs from yaml {}", yamlName); - loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE, - "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."); + if (processSubstitutableAsNodeType(resource, parsedToscaYamlInfo)) { + final Map substitutableAsNodeType = getSubstitutableAsNodeTypeFromTemplate( + (Map) new Yaml().load(topologyTemplateYaml), parsedToscaYamlInfo.getSubstitutionMappingNodeType()); + resource.setToscaResourceName(parsedToscaYamlInfo.getSubstitutionMappingNodeType()); + final Resource genericResource = fetchAndSetDerivedFromGenericType(resource, + (String) substitutableAsNodeType.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName())); + resource = createResourceTransaction(resource, csarInfo.getModifier(), isNormative); + generatePropertiesFromGenericType(resource, genericResource); + generatePropertiesFromNodeType(resource, substitutableAsNodeType); + final String resourceId = resource.getUniqueId(); + resource.getProperties().forEach(propertyDefinition -> propertyDefinition.setUniqueId( + UniqueIdBuilder.buildPropertyUniqueId(resourceId, propertyDefinition.getName()))); + + createResourcePropertiesOnGraph(resource); + final Map instancesToCreate = getInstancesToCreate(parsedToscaYamlInfo, resource.getModel()); + + log.trace("************* Going to create nodes, RI's and Relations from yaml {}", yamlName); + loggerSupportability + .log(LoggerSupportabilityActions.CREATE_RESOURCE_FROM_YAML, resource.getComponentMetadataForSupportLog(), StatusCode.STARTED, + "Start create nodes, RI and Relations from yaml: {}", yamlName); + resource = createRIAndRelationsFromYaml(yamlName, resource, instancesToCreate, topologyTemplateYaml, + nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeTypesArtifactsToCreate, nodeName, + parsedToscaYamlInfo.getSubstitutionMappingNodeType()); + } else { + final Resource genericResource = fetchAndSetDerivedFromGenericType(resource, null); + 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()) { + generateAndAddInputsFromGenericTypeProperties(resource, genericResource); + } + final Map inputs = parsedToscaYamlInfo.getInputs(); + resource = createInputsOnResource(resource, inputs); + + log.trace("************* Finish to add inputs from yaml {}", yamlName); + loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE, + "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."); + } } + final Map instancesToCreate = getInstancesToCreate(parsedToscaYamlInfo); + + log.trace("************* Going to create nodes, RI's and Relations from yaml {}", yamlName); + loggerSupportability + .log(LoggerSupportabilityActions.CREATE_RESOURCE_FROM_YAML, resource.getComponentMetadataForSupportLog(), StatusCode.STARTED, + "Start create nodes, RI and Relations from yaml: {}", yamlName); + resource = createRIAndRelationsFromYaml(yamlName, resource, instancesToCreate, topologyTemplateYaml, + nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeTypesArtifactsToCreate, nodeName, null); } - final Map uploadComponentInstanceInfoMap = parsedToscaYamlInfo.getInstances(); - log.trace("************* Going to create nodes, RI's and Relations from yaml {}", yamlName); - loggerSupportability - .log(LoggerSupportabilityActions.CREATE_RESOURCE_FROM_YAML, resource.getComponentMetadataForSupportLog(), StatusCode.STARTED, - "Start create nodes, RI 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); loggerSupportability.log(LoggerSupportabilityActions.CREATE_RELATIONS, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE, "Finished to create nodes, RI and Relation from yaml: {}", yamlName); @@ -1485,11 +1616,11 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ByResponseFormatComponentException(e.getResponseFormat()); } catch (final ComponentException e) { - log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ResourceBusinessLogic.class.getName(), - "An error has occurred during resource and resource instance creation", e); - rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); - throw new ByResponseFormatComponentException(e.getResponseFormat()); - } catch (final Exception e) { + log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ResourceBusinessLogic.class.getName(), + "An error has occurred during resource and resource instance creation", e); + rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); + throw new ByResponseFormatComponentException(e.getResponseFormat()); + } catch (final Exception e) { log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ResourceBusinessLogic.class.getName(), "An error has occurred during resource and resource instance creation", e); rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); @@ -1504,6 +1635,24 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } + private boolean processSubstitutableAsNodeType(final Resource resource, final ParsedToscaYamlInfo parsedToscaYamlInfo) { + return !resource.getResourceType().isAtomicType() && StringUtils.isNotEmpty(resource.getModel()) + && parsedToscaYamlInfo.getSubstitutionMappingNodeType() != null; + } + + private Map getInstancesToCreate(final ParsedToscaYamlInfo parsedToscaYamlInfo) { + return getInstancesToCreate(parsedToscaYamlInfo, null); + } + + private Map getInstancesToCreate(final ParsedToscaYamlInfo parsedToscaYamlInfo, final String model) { + if (StringUtils.isEmpty(model) || StringUtils.isEmpty(parsedToscaYamlInfo.getSubstitutionMappingNodeType())) { + return parsedToscaYamlInfo.getInstances(); + } + return parsedToscaYamlInfo.getInstances().entrySet().stream() + .filter(entry -> !parsedToscaYamlInfo.getSubstitutionMappingNodeType().equals(entry.getValue().getType())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + private void rollback(boolean inTransaction, Resource resource, List createdArtifacts, List nodeTypesNewCreatedArtifacts) { if (!inTransaction) { @@ -1688,6 +1837,42 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return resource; } + private Resource generatePropertiesFromNodeType(final Resource resource, final Map nodeType) { + final Either, ResultStatusEnum> properties = ImportUtils.getProperties(nodeType); + if (properties.isLeft()) { + final List propertiesList = new ArrayList<>(); + final Map value = properties.left().value(); + if (value != null) { + for (Entry entry : value.entrySet()) { + final String name = entry.getKey(); + final PropertyDefinition propertyDefinition = entry.getValue(); + propertyDefinition.setName(name); + propertiesList.add(propertyDefinition); + resource.getProperties().removeIf(p -> p.getName().equals(name)); + } + } + resource.getProperties().addAll(propertiesList); + } + return resource; + } + + private Resource createResourcePropertiesOnGraph(final Resource resource) { + final List resourceProperties = resource.getProperties(); + for (PropertyDefinition propertyDefinition : resourceProperties) { + final Either addPropertyEither = toscaOperationFacade + .addPropertyToComponent(propertyDefinition.getName(), propertyDefinition, resource); + + if (addPropertyEither.isRight()) { + final String error = String.format("failed to add properties from yaml: {}", addPropertyEither.right().value()); + loggerSupportability.log(LoggerSupportabilityActions.CREATE_PROPERTIES, resource.getComponentMetadataForSupportLog(), + StatusCode.ERROR, + error); + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(addPropertyEither.right().value()), error); + } + } + return resource; + } + private List updateGroupsMembersUsingResource(Map groups, Resource component) { List result = new ArrayList<>(); List componentInstances = component.getComponentInstances(); @@ -1827,10 +2012,10 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { String topologyTemplateYaml, List nodeTypesNewCreatedArtifacts, Map nodeTypesInfo, CsarInfo csarInfo, Map>> nodeTypesArtifactsToCreate, - String nodeName) { + String nodeName, final String substitutableAsNodeType) { log.debug("************* Going to create all nodes {}", yamlName); handleNodeTypes(yamlName, resource, topologyTemplateYaml, false, nodeTypesArtifactsToCreate, nodeTypesNewCreatedArtifacts, nodeTypesInfo, - csarInfo, nodeName); + csarInfo, nodeName, substitutableAsNodeType); log.debug("************* Finished to create all nodes {}", yamlName); log.debug("************* Going to create all resource instances {}", yamlName); Map existingNodeTypesByResourceNames = new HashMap<>(); @@ -1862,10 +2047,10 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { private void handleNodeTypes(String yamlName, Resource resource, String topologyTemplateYaml, boolean needLock, Map>> nodeTypesArtifactsToHandle, List nodeTypesNewCreatedArtifacts, Map nodeTypesInfo, CsarInfo csarInfo, - String nodeName) { + String nodeName, String substitutableAsNodeType) { try { for (Entry nodeTypeEntry : nodeTypesInfo.entrySet()) { - if (nodeTypeEntry.getValue().isNested() && !nodeTypeAlreadyExists(nodeTypeEntry.getKey())) { + if (nodeTypeEntry.getValue().isNested() && !nodeTypeAlreadyExists(nodeTypeEntry.getKey(), resource.getModel())) { handleNestedVfc(resource, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeTypeEntry.getKey()); log.trace("************* finished to create node {}", nodeTypeEntry.getKey()); @@ -1879,7 +2064,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { mappedToscaTemplate = (Map) new Yaml().load(topologyTemplateYaml); } createResourcesFromYamlNodeTypesList(yamlName, resource, mappedToscaTemplate, needLock, nodeTypesArtifactsToHandle, - nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo); + nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, substitutableAsNodeType); } catch (ComponentException e) { ResponseFormat responseFormat = e.getResponseFormat() != null ? e.getResponseFormat() : componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams()); @@ -1892,9 +2077,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { throw e; } } - - private boolean nodeTypeAlreadyExists(final String toscaResourceName) { - return toscaOperationFacade.getLatestByToscaResourceName(toscaResourceName).isLeft(); + + private boolean nodeTypeAlreadyExists(final String toscaResourceName, String modelName) { + return toscaOperationFacade.getLatestByToscaResourceName(toscaResourceName, modelName).isLeft(); } private Either handleVfCsarArtifacts(Resource resource, CsarInfo csarInfo, List createdArtifacts, @@ -2044,7 +2229,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Either, String> artifactPathAndNameList = getValidArtifactNames(csarInfo, collectedWarningMessages); if (artifactPathAndNameList.isRight()) { return Either.right( - getComponentsUtils().getResponseFormatByArtifactId(ActionStatus.ARTIFACT_NAME_INVALID, artifactPathAndNameList.right().value())); + getComponentsUtils().getResponseFormatByArtifactId(ActionStatus.ARTIFACT_NAME_INVALID, artifactPathAndNameList.right().value(), + VALID_CHARACTERS_ARTIFACT_NAME)); } EnumMap> vfCsarArtifactsToHandle = null; if (artifactOperation.isCreateOrLink()) { @@ -2166,7 +2352,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { private boolean isValidArtifactType(ArtifactDefinition artifact) { return artifact.getArtifactType() != null && ArtifactTypeEnum.parse(artifact.getArtifactType()) != ArtifactTypeEnum.VENDOR_LICENSE - && ArtifactTypeEnum.parse(artifact.getArtifactType()) != ArtifactTypeEnum.VF_LICENSE; + && ArtifactTypeEnum.parse(artifact.getArtifactType()) != ArtifactTypeEnum.VF_LICENSE; } private Resource createResourceInstancesRelations(User user, String yamlName, Resource resource, Resource oldResource, @@ -2195,21 +2381,10 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map> instAttributes = new HashMap<>(); List relations = new ArrayList<>(); Map> instInputs = new HashMap<>(); - log.debug("#createResourceInstancesRelations - Before get all datatypes. "); - Either, JanusGraphOperationStatus> allDataTypes = dataTypeCache.getAll(); - if (allDataTypes.isRight()) { - JanusGraphOperationStatus status = allDataTypes.right().value(); - BeEcompErrorManager.getInstance() - .logInternalFlowError("UpdatePropertyValueOnComponentInstance", "Failed to update property value on instance. Status is " + status, - ErrorSeverity.ERROR); - loggerSupportability.log(LoggerSupportabilityActions.CREATE_RELATIONS, resource.getComponentMetadataForSupportLog(), StatusCode.ERROR, - "ERROR while update property value on instance. Status is: " + status); - throw new ByActionStatusComponentException( - componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status)), yamlName); - } Resource finalResource = resource; uploadResInstancesMap.values().forEach( - i -> processComponentInstance(yamlName, finalResource, componentInstancesList, allDataTypes, instProperties, instCapabilities, + i -> processComponentInstance(yamlName, finalResource, componentInstancesList, + componentsUtils.getAllDataTypes(applicationDataTypeCache, resource.getModel()), instProperties, instCapabilities, instRequirements, instDeploymentArtifacts, instArtifacts, instAttributes, existingNodeTypesByResourceNames, instInputs, i)); resource.getComponentInstances().stream().filter(i -> !i.isCreatedFromCsar()).forEach( i -> processUiComponentInstance(oldResource, i, instCapabilities, instRequirements, instDeploymentArtifacts, instArtifacts, @@ -2382,14 +2557,18 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private void handleSubstitutionMappings(Resource resource, Map uploadResInstancesMap) { + Either getResourceRes = null; if (resource.getResourceType() == ResourceTypeEnum.CVFC) { - Either getResourceRes = updateCalculatedCapReqWithSubstitutionMappings(resource, uploadResInstancesMap); - if (getResourceRes.isRight()) { - ResponseFormat responseFormat = componentsUtils - .getResponseFormatByResource(componentsUtils.convertFromStorageResponse(getResourceRes.right().value()), resource); - throw new ByResponseFormatComponentException(responseFormat); - } + getResourceRes = updateCalculatedCapReqWithSubstitutionMappings(resource, uploadResInstancesMap); + } else if (StringUtils.isNotEmpty(resource.getModel()) && resource.getResourceType() == ResourceTypeEnum.VF) { + getResourceRes = updateCalculatedCapReqWithSubstitutionMappingsForVf(resource, uploadResInstancesMap); + } + if (getResourceRes != null && getResourceRes.isRight()) { + ResponseFormat responseFormat = componentsUtils + .getResponseFormatByResource(componentsUtils.convertFromStorageResponse(getResourceRes.right().value()), resource); + throw new ByResponseFormatComponentException(responseFormat); } + } private void addRelationsToRI(String yamlName, Resource resource, Map uploadResInstancesMap, @@ -2426,7 +2605,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private void processComponentInstance(String yamlName, Resource resource, List componentInstancesList, - Either, JanusGraphOperationStatus> allDataTypes, + Map allDataTypes, Map> instProperties, Map>> instCapabilties, Map>> instRequirements, @@ -2464,12 +2643,12 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } if (originResource.getResourceType() != ResourceTypeEnum.CVFC) { ResponseFormat addPropertiesValueToRiRes = addPropertyValuesToRi(uploadComponentInstanceInfo, resource, originResource, - currentCompInstance, instProperties, allDataTypes.left().value()); + currentCompInstance, instProperties, allDataTypes); if (addPropertiesValueToRiRes.getStatus() != 200) { throw new ByResponseFormatComponentException(addPropertiesValueToRiRes); } } else { - addInputsValuesToRi(uploadComponentInstanceInfo, resource, originResource, currentCompInstance, instInputs, allDataTypes.left().value()); + addInputsValuesToRi(uploadComponentInstanceInfo, resource, originResource, currentCompInstance, instInputs, allDataTypes); } } @@ -2492,7 +2671,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return originResource; } - private void processComponentInstanceCapabilities(Either, JanusGraphOperationStatus> allDataTypes, + private void processComponentInstanceCapabilities(Map allDataTypes, Map>> instCapabilties, UploadComponentInstanceInfo uploadComponentInstanceInfo, ComponentInstance currentCompInstance, Resource originResource) { @@ -2502,18 +2681,18 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map> newPropertiesMap = new HashMap<>(); originResource.getCapabilities().forEach((k, v) -> addCapabilities(originCapabilities, k, v)); uploadComponentInstanceInfo.getCapabilities().values().forEach(l -> addCapabilitiesProperties(newPropertiesMap, l)); - updateCapabilityPropertiesValues(allDataTypes, originCapabilities, newPropertiesMap); + updateCapabilityPropertiesValues(originCapabilities, newPropertiesMap, allDataTypes); } else { originCapabilities = originResource.getCapabilities(); } instCapabilties.put(currentCompInstance, originCapabilities); } - private void updateCapabilityPropertiesValues(Either, JanusGraphOperationStatus> allDataTypes, - Map> originCapabilities, - Map> newPropertiesMap) { + private void updateCapabilityPropertiesValues(Map> originCapabilities, + Map> newPropertiesMap, + Map allDataTypes) { originCapabilities.values().stream().flatMap(Collection::stream).filter(c -> newPropertiesMap.containsKey(c.getName())) - .forEach(c -> updatePropertyValues(c.getProperties(), newPropertiesMap.get(c.getName()), allDataTypes.left().value())); + .forEach(c -> updatePropertyValues(c.getProperties(), newPropertiesMap.get(c.getName()), allDataTypes)); } private void addCapabilitiesProperties(Map> newPropertiesMap, List capabilities) { @@ -2557,6 +2736,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Either updateRes = null; Map>> updatedInstCapabilities = new HashMap<>(); Map>> updatedInstRequirements = new HashMap<>(); + StorageOperationStatus status = toscaOperationFacade.deleteAllCalculatedCapabilitiesRequirements(resource.getUniqueId()); if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) { log.debug("Failed to delete all calculated capabilities and requirements of resource {} upon update. Status is {}", @@ -2580,6 +2760,32 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return updateRes; } + private Either updateCalculatedCapReqWithSubstitutionMappingsForVf(final Resource resource, + final Map uploadResInstancesMap) { + Either updateRes = null; + final Map>> updatedInstCapabilities = new HashMap<>(); + final Map>> updatedInstRequirements = new HashMap<>(); + + resource.getComponentInstances().forEach(i -> { + setExternalCapabilities(updatedInstCapabilities, i, uploadResInstancesMap.get(i.getName()).getCapabilitiesNamesToUpdate()); + setExternalRequirements(updatedInstRequirements, i, uploadResInstancesMap.get(i.getName()).getRequirementsNamesToUpdate()); + }); + + final StorageOperationStatus status = toscaOperationFacade.updateCalculatedCapabilitiesRequirements(updatedInstCapabilities, + updatedInstRequirements, resource); + if (status != StorageOperationStatus.OK) { + log.debug( + "Failed to update capabilities and requirements of resource {}. Status is {}", + resource.getUniqueId(), status); + updateRes = Either.right(status); + } + + if (updateRes == null) { + updateRes = Either.left(resource); + } + return updateRes; + } + private void fillUpdatedInstCapabilitiesRequirements(List componentInstances, Map uploadResInstancesMap, Map>> updatedInstCapabilities, @@ -2597,7 +2803,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (isNotEmpty(requirementsNamesToUpdate)) { for (Map.Entry> requirements : instance.getRequirements().entrySet()) { updatedRequirements.put(requirements.getKey(), requirements.getValue().stream().filter( - r -> requirementsNamesToUpdate.containsKey(r.getName()) && !updatedReqNames.contains(requirementsNamesToUpdate.get(r.getName()))) + r -> requirementsNamesToUpdate.containsKey(r.getName()) && !updatedReqNames.contains(requirementsNamesToUpdate.get(r.getName()))) .map(r -> { r.setParentName(r.getName()); r.setName(requirementsNamesToUpdate.get(r.getName())); @@ -2611,6 +2817,54 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } + private void setExternalRequirements( + final Map>> updatedInstRequirements, + final ComponentInstance instance, final Map requirementsNamesToUpdate) { + final Map> updatedRequirements = new HashMap<>(); + final Set updatedReqNames = new HashSet<>(); + if (isNotEmpty(requirementsNamesToUpdate)) { + for (Map.Entry> requirements : instance.getRequirements().entrySet()) { + updatedRequirements.put(requirements.getKey(), + requirements.getValue().stream() + .filter(r -> requirementsNamesToUpdate.containsKey(r.getName()) + && !updatedReqNames.contains(requirementsNamesToUpdate.get(r.getName()))) + .map(r -> { + r.setExternal(true); + r.setExternalName(requirementsNamesToUpdate.get(r.getName())); + updatedReqNames.add(r.getName()); + return r; + }).collect(toList())); + } + } + if (isNotEmpty(updatedRequirements)) { + updatedInstRequirements.put(instance, updatedRequirements); + } + } + + private void setExternalCapabilities( + final Map>> updatedInstCapabilties, + final ComponentInstance instance, Map capabilitiesNamesToUpdate) { + final Map> updatedCapabilities = new HashMap<>(); + final Set updatedCapNames = new HashSet<>(); + if (isNotEmpty(capabilitiesNamesToUpdate)) { + for (Map.Entry> requirements : instance.getCapabilities().entrySet()) { + updatedCapabilities.put(requirements.getKey(), + requirements.getValue().stream() + .filter(c -> capabilitiesNamesToUpdate.containsKey(c.getName()) + && !updatedCapNames.contains(capabilitiesNamesToUpdate.get(c.getName()))) + .map(c -> { + c.setExternal(true); + c.setExternalName(capabilitiesNamesToUpdate.get(c.getName())); + updatedCapNames.add(c.getName()); + return c; + }).collect(toList())); + } + } + if (isNotEmpty(updatedCapabilities)) { + updatedInstCapabilties.put(instance, updatedCapabilities); + } + } + private void fillUpdatedInstCapabilities(Map>> updatedInstCapabilties, ComponentInstance instance, Map capabilitiesNamesToUpdate) { Map> updatedCapabilities = new HashMap<>(); @@ -2618,7 +2872,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (isNotEmpty(capabilitiesNamesToUpdate)) { for (Map.Entry> requirements : instance.getCapabilities().entrySet()) { updatedCapabilities.put(requirements.getKey(), requirements.getValue().stream().filter( - c -> capabilitiesNamesToUpdate.containsKey(c.getName()) && !updatedCapNames.contains(capabilitiesNamesToUpdate.get(c.getName()))) + c -> capabilitiesNamesToUpdate.containsKey(c.getName()) && !updatedCapNames.contains(capabilitiesNamesToUpdate.get(c.getName()))) .map(c -> { c.setParentName(c.getName()); c.setName(capabilitiesNamesToUpdate.get(c.getName())); @@ -2657,19 +2911,19 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { for (UploadReqInfo uploadRegInfo : uploadRegInfoList) { log.debug("Going to create relation {}", uploadRegInfo.getName()); loggerSupportability - .log(LoggerSupportabilityActions.CREATE_RELATIONS, resource.getComponentMetadataForSupportLog(), StatusCode.STARTED, - "Started to create relations on instance: {}", uploadRegInfo.getName()); + .log(LoggerSupportabilityActions.CREATE_RELATIONS, resource.getComponentMetadataForSupportLog(), StatusCode.STARTED, + "Started to create relations on instance: {}", uploadRegInfo.getName()); String regName = uploadRegInfo.getName(); RequirementCapabilityRelDef regCapRelDef = new RequirementCapabilityRelDef(); regCapRelDef.setFromNode(resourceInstanceId); log.debug("try to find available requirement {} ", regName); Either eitherReqStatus = findAviableRequiremen(regName, yamlName, nodesInfoValue, - currentCompInstance, uploadRegInfo.getCapabilityName()); + currentCompInstance, uploadRegInfo.getCapabilityName()); if (eitherReqStatus.isRight()) { log.debug("failed to find available requirement {} status is {}", regName, eitherReqStatus.right().value()); loggerSupportability - .log(LoggerSupportabilityActions.CREATE_RELATIONS, resource.getComponentMetadataForSupportLog(), StatusCode.ERROR, - "ERROR while search available requirement {} status is: {}", regName, eitherReqStatus.right().value()); + .log(LoggerSupportabilityActions.CREATE_RELATIONS, resource.getComponentMetadataForSupportLog(), StatusCode.ERROR, + "ERROR while search available requirement {} status is: {}", regName, eitherReqStatus.right().value()); return eitherReqStatus.right().value(); } RequirementDefinition validReq = eitherReqStatus.left().value(); @@ -2694,11 +2948,11 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (currentCapCompInstance == null) { log.debug("The component instance with name {} not found on resource {} ", uploadRegInfo.getNode(), resource.getUniqueId()); loggerSupportability - .log(LoggerSupportabilityActions.CREATE_RELATIONS, resource.getComponentMetadataForSupportLog(), StatusCode.ERROR, - "ERROR component instance with name: {} not found on resource: {}", uploadRegInfo.getNode(), resource.getUniqueId()); + .log(LoggerSupportabilityActions.CREATE_RELATIONS, resource.getComponentMetadataForSupportLog(), StatusCode.ERROR, + "ERROR component instance with name: {} not found on resource: {}", uploadRegInfo.getNode(), resource.getUniqueId()); BeEcompErrorManager.getInstance() - .logInternalDataError(COMPONENT_INSTANCE_WITH_NAME + uploadRegInfo.getNode() + IN_RESOURCE, resource.getUniqueId(), - ErrorSeverity.ERROR); + .logInternalDataError(COMPONENT_INSTANCE_WITH_NAME + uploadRegInfo.getNode() + IN_RESOURCE, resource.getUniqueId(), + ErrorSeverity.ERROR); return componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); } regCapRelDef.setToNode(currentCapCompInstance.getUniqueId()); @@ -2706,14 +2960,14 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { CapabilityDefinition aviableCapForRel = findAvailableCapabilityByTypeOrName(validReq, currentCapCompInstance, uploadRegInfo); if (aviableCapForRel == null) { log.debug("aviable capability was not found. req name is {} component instance is {}", validReq.getName(), - currentCapCompInstance.getUniqueId()); + currentCapCompInstance.getUniqueId()); loggerSupportability - .log(LoggerSupportabilityActions.CREATE_RELATIONS, resource.getComponentMetadataForSupportLog(), StatusCode.ERROR, - "ERROR available capability was not found. req name is: {} component instance is: {}", validReq.getName(), - currentCapCompInstance.getUniqueId()); + .log(LoggerSupportabilityActions.CREATE_RELATIONS, resource.getComponentMetadataForSupportLog(), StatusCode.ERROR, + "ERROR available capability was not found. req name is: {} component instance is: {}", validReq.getName(), + currentCapCompInstance.getUniqueId()); BeEcompErrorManager.getInstance().logInternalDataError( - "aviable capability was not found. req name is " + validReq.getName() + " component instance is " + currentCapCompInstance - .getUniqueId(), resource.getUniqueId(), ErrorSeverity.ERROR); + "aviable capability was not found. req name is " + validReq.getName() + " component instance is " + currentCapCompInstance + .getUniqueId(), resource.getUniqueId(), ErrorSeverity.ERROR); return componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); } reqAndRelationshipPair.setCapability(aviableCapForRel.getName()); @@ -3155,6 +3409,14 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ToscaArtifactDataDefinition to = new ToscaArtifactDataDefinition(); to.setFile(entry.getValue().getFile()); to.setType(entry.getValue().getType()); + if(isNotEmpty(entry.getValue().getProperties())) { + Map newPropertiesMap = new HashMap<>(); + List artifactPropsInfo = entry.getValue().getProperties(); + for(UploadPropInfo propInfo: artifactPropsInfo) { + newPropertiesMap.put(propInfo.getName(), propInfo.getValue()); + } + to.setProperties(newPropertiesMap); + } toscaArtifacts.put(entry.getKey(), to); } componentInstance.setToscaArtifacts(toscaArtifacts); @@ -3199,9 +3461,10 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (nodeNamespaceMap.containsKey(uploadComponentInstanceInfo.getType())) { refResource = nodeNamespaceMap.get(uploadComponentInstanceInfo.getType()); } else { - Either findResourceEither = toscaOperationFacade - .getByToscaResourceNameMatchingVendorRelease(uploadComponentInstanceInfo.getType(), - ((ResourceMetadataDataDefinition) resource.getComponentMetadataDefinition().getMetadataDataDefinition()).getVendorRelease()); + Either findResourceEither = StringUtils.isEmpty(resource.getModel()) ? + toscaOperationFacade.getByToscaResourceNameMatchingVendorRelease(uploadComponentInstanceInfo.getType(), + ((ResourceMetadataDataDefinition) resource.getComponentMetadataDefinition().getMetadataDataDefinition()).getVendorRelease()): + toscaOperationFacade.getLatestByToscaResourceNameAndModel(uploadComponentInstanceInfo.getType(), resource.getModel()); if (findResourceEither.isRight()) { log.debug("validateResourceInstanceBeforeCreate - not found latest version for resource instance with name {} and type {}", uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); @@ -3277,10 +3540,11 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ImmutablePair result = null; // check if resource already exists (search by tosca name = type) final boolean isNestedResource = isNestedResourceUpdate(csarInfo, nodeName); + final String resourceName = resource.getToscaResourceName(); final Either latestByToscaName = toscaOperationFacade - .getLatestByToscaResourceName(resource.getToscaResourceName()); - if (latestByToscaName.isLeft()) { - Resource foundResource = latestByToscaName.left().value(); + .getLatestByToscaResourceNameAndModel(resourceName, resource.getModel()); + if (latestByToscaName.isLeft() && Objects.nonNull(latestByToscaName.left().value())) { + final Resource foundResource = latestByToscaName.left().value(); // we don't allow updating names of top level types if (!isNestedResource && !StringUtils.equals(resource.getName(), foundResource.getName())) { BeEcompErrorManager.getInstance() @@ -3318,7 +3582,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { final CsarInfo csarInfo, final boolean isNested, final String nodeName) { final Either latestByToscaName = toscaOperationFacade.getLatestByToscaResourceName( - buildNestedToscaResourceName(resource.getResourceType().name(), csarInfo.getVfResourceName(), nodeName).getRight()); + buildNestedToscaResourceName(resource.getResourceType().name(), csarInfo.getVfResourceName(), nodeName).getRight(), resource.getModel()); if (latestByToscaName.isLeft()) { final Resource nestedResource = (Resource) latestByToscaName.left().value(); log.debug(VALIDATE_DERIVED_BEFORE_UPDATE); @@ -3349,7 +3613,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } public boolean isResourceExist(String resourceName) { - Either latestByName = toscaOperationFacade.getLatestByName(resourceName); + Either latestByName = toscaOperationFacade.getLatestByName(resourceName, null); return latestByName.isLeft(); } @@ -3380,6 +3644,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { newResource.setUUID(oldResource.getUUID()); newResource.setNormalizedName(oldResource.getNormalizedName()); newResource.setSystemName(oldResource.getSystemName()); + newResource.setModel(oldResource.getModel()); if (oldResource.getCsarUUID() != null) { newResource.setCsarUUID(oldResource.getCsarUUID()); } @@ -3464,6 +3729,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (newResource.getResourceVendorModelNumber() == null) { newResource.setResourceVendorModelNumber(oldResource.getResourceVendorModelNumber()); } + if (newResource.getModel() == null) { + newResource.setModel(oldResource.getModel()); + } if (newResource.getContactId() == null) { newResource.setContactId(oldResource.getContactId()); } @@ -3480,9 +3748,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (newResource.getResourceType().isAtomicType() && !newResource.getName().equals("Root") && newResource.getResourceType() != ResourceTypeEnum.CVFC) { ResourceTypeEnum updatedResourceType = newResource.getResourceType(); - Component derivedFromResource = getParentComponent(newResource); - if (derivedFromResource.getComponentType() == ComponentTypeEnum.RESOURCE) { - Resource parentResource = (Resource) derivedFromResource; + Optional derivedFromResourceOptional = getParentComponent(newResource); + if (derivedFromResourceOptional.isPresent() && derivedFromResourceOptional.get().getComponentType() == ComponentTypeEnum.RESOURCE) { + Resource parentResource = (Resource) derivedFromResourceOptional.get(); if (!(parentResource.isAbstract() && (ResourceTypeEnum.VFC == parentResource.getResourceType() || ResourceTypeEnum.ABSTRACT == parentResource.getResourceType())) && parentResource.getResourceType() != updatedResourceType && oldResource.getResourceType() != updatedResourceType) { @@ -3497,17 +3765,20 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } - private Component getParentComponent(Resource newResource) { + private Optional getParentComponent(Resource newResource) { + if (newResource.getDerivedFrom() == null) { + return Optional.empty(); + } String toscaResourceNameDerivedFrom = newResource.getDerivedFrom().get(0); Either latestByToscaResourceName = toscaOperationFacade - .getLatestByToscaResourceName(toscaResourceNameDerivedFrom); + .getLatestByToscaResourceName(toscaResourceNameDerivedFrom, newResource.getModel()); if (latestByToscaResourceName.isRight()) { BeEcompErrorManager.getInstance() .logInternalDataError("mergeOldResourceMetadataWithNew", "derived from resource not found", ErrorSeverity.ERROR); log.debug("#mergeOldResourceMetadataWithNew - derived from resource {} not found", toscaResourceNameDerivedFrom); throw new ByActionStatusComponentException(ActionStatus.RESOURCE_NOT_FOUND, toscaResourceNameDerivedFrom); } - return latestByToscaResourceName.left().value(); + return Optional.of(latestByToscaResourceName.left().value()); } private Resource prepareResourceForUpdate(Resource oldResource, Resource newResource, User user, boolean inTransaction, boolean needLock) { @@ -3624,7 +3895,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Resource resource, List validationObjects, AuditingActionEnum actionEnum, Either eitherResult, String type, boolean inTransaction) { - Either eitherCapTypeFound = capabilityTypeOperation.getCapabilityType(type, inTransaction); + Either eitherCapTypeFound = capabilityTypeOperation.getCapabilityType(UniqueIdBuilder.buildCapabilityTypeUid(resource.getModel(), type), inTransaction); if (eitherCapTypeFound.isRight()) { if (eitherCapTypeFound.right().value() == StorageOperationStatus.NOT_FOUND) { BeEcompErrorManager.getInstance().logBeGraphObjectMissingError(CREATE_RESOURCE_VALIDATE_CAPABILITY_TYPES, "Capability Type", type); @@ -3649,7 +3920,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Either eitherResult, Entry> typeEntry, boolean inTransaction) { Either eitherCapTypeFound = capabilityTypeOperation - .getCapabilityType(typeEntry.getKey(), inTransaction); + .getCapabilityType(UniqueIdBuilder.buildCapabilityTypeUid(resource.getModel(), typeEntry.getKey()), inTransaction); if (eitherCapTypeFound.isRight()) { if (eitherCapTypeFound.right().value() == StorageOperationStatus.NOT_FOUND) { BeEcompErrorManager.getInstance() @@ -3749,10 +4020,12 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private Resource createResourceTransaction(Resource resource, User user, boolean isNormative) { - // validate resource name uniqueness - log.debug("validate resource name"); - Either eitherValidation = toscaOperationFacade - .validateComponentNameExists(resource.getName(), resource.getResourceType(), resource.getComponentType()); + final String resourceName = resource.getName(); + final String modelName = resource.getModel(); + final ResourceTypeEnum resourceType = resource.getResourceType(); + final ComponentTypeEnum componentType = resource.getComponentType(); + final Either eitherValidation = toscaOperationFacade + .validateComponentNameAndModelExists(resourceName, modelName, resourceType, componentType); if (eitherValidation.isRight()) { loggerSupportability.log(LoggerSupportabilityActions.VALIDATE_NAME, resource.getComponentMetadataForSupportLog(), StatusCode.ERROR, "ERROR while validate component name {} Status is: {}", resource.getName(), eitherValidation.right().value()); @@ -4423,7 +4696,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { String currentTemplateName = currentResource.getDerivedFrom().get(0); String updatedTemplateName = updateInfoResource.getDerivedFrom().get(0); Either dataModelResponse = toscaOperationFacade - .validateToscaResourceNameExtends(currentTemplateName, updatedTemplateName); + .validateToscaResourceNameExtends(currentTemplateName, updatedTemplateName, currentResource.getModel()); if (dataModelResponse.isRight()) { StorageOperationStatus storageStatus = dataModelResponse.right().value(); BeEcompErrorManager.getInstance().logBeDaoSystemError("Create/Update Resource - validateDerivingFromExtendingType"); @@ -4727,20 +5000,20 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { log.debug("validate resource properties default values"); List properties = resource.getProperties(); if (properties != null) { - iterateOverProperties(properties); + iterateOverProperties(properties, resource.getModel()); } return true; } - public void iterateOverProperties(List properties) { + public void iterateOverProperties(List properties, String model) { String type = null; String innerType = null; for (PropertyDefinition property : properties) { - if (!propertyOperation.isPropertyTypeValid(property)) { + if (!propertyOperation.isPropertyTypeValid(property, model)) { log.info("Invalid type for property {}", property); throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_TYPE, property.getType(), property.getName()); } - Map allDataTypes = getAllDataTypes(applicationDataTypeCache); + Map allDataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, model); type = property.getType(); if (type.equals(ToscaPropertyType.LIST.getType()) || type.equals(ToscaPropertyType.MAP.getType())) { ResponseFormat responseFormat = validateMapOrListPropertyType(property, innerType, allDataTypes);