From 0566f581c0f310384f42838c388f57234ed1d60e Mon Sep 17 00:00:00 2001 From: Yuli Shlosberg Date: Sun, 26 Nov 2017 19:05:23 +0200 Subject: [PATCH] sync 1.1.0 to master Change-Id: I6e040f039895dd2ced55f95824473946b226fb5d Issue-ID: SDC-707 Signed-off-by: Yuli Shlosberg --- asdc-tests/pom.xml | 2 +- .../be/components/impl/ArtifactsBusinessLogic.java | 10 +- .../be/components/impl/ComponentBusinessLogic.java | 5 + .../impl/ComponentInstanceBusinessLogic.java | 18 +- .../be/components/impl/ResourceBusinessLogic.java | 561 +++++++++++++-------- .../sdc/be/info/ArtifactTemplateInfo.java | 10 +- .../be/tosca/CapabiltyRequirementConvertor.java | 434 ++++++++++++---- .../java/org/openecomp/sdc/be/tosca/CsarUtils.java | 10 +- .../openecomp/sdc/be/tosca/ToscaExportHandler.java | 372 ++++++++++---- .../org/openecomp/sdc/be/tosca/ToscaUtils.java | 56 +- catalog-be/src/main/webapp/WEB-INF/web.xml | 4 +- .../org/openecomp/sdc/be/model/UploadInfo.java | 10 + .../model/jsontitan/operations/BaseOperation.java | 71 ++- .../operations/NodeTemplateOperation.java | 2 +- .../jsontitan/operations/NodeTypeOperation.java | 149 +++++- .../operations/ToscaElementLifecycleOperation.java | 2 +- .../jsontitan/operations/ToscaOperationFacade.java | 62 ++- .../be/model/jsontitan/utils/ModelConverter.java | 36 +- .../be/datatypes/tosca/ToscaDataDefinition.java | 10 + .../build/scripts/generate-cassandra-init-cql.sh | 2 +- .../zusammen-generate-cassandra-init-cql.sh | 2 +- sdc-os-chef/pom.xml | 69 ++- sdc-os-chef/scripts/docker_run.sh | 35 +- sdc-os-chef/scripts/docker_sanity_run.sh | 122 +++++ sdc-os-chef/scripts/sanity_run.sh | 117 +++++ .../cassandra-actions/attributes/default.rb | 2 +- .../files/default/alter_dox_db.cql | 8 - .../files/default/create_dox_db.cql | 60 --- .../recipes/03-createDoxKeyspace.rb | 2 +- .../files/default/Files/VNFs/Huawei_vPCRF.csar | Bin 0 -> 3836 bytes .../files/default/Files/VNFs/Huawei_vSPGW.csar | Bin 0 -> 3907 bytes .../files/default/Files/VNFs/ZteEpcMmeVf.csar | Bin 0 -> 4790 bytes .../files/default/Files/VNFs/ZteEpcSpgwVf.csar | Bin 0 -> 2804 bytes .../files/default/Files/VNFs/cscf_si.csar | Bin 0 -> 50982 bytes .../sdc-sanity/files/default/Files/VNFs/vCSCF.csar | Bin 0 -> 4290 bytes .../files/default/Files/VNFs/vCSCF_v3.0.csar | Bin 44851 -> 44977 bytes .../sdc-sanity/files/default/Files/VNFs/vSBC.csar | Bin 0 -> 3771 bytes .../sdc-sanity/files/default/Files/VNFs/vfw.zip | Bin 0 -> 3522 bytes .../sdc-sanity/files/default/Files/VNFs/vvg.zip | Bin 0 -> 944 bytes .../sdc-sanity/files/default/conf/logback.xml | 25 + .../sdc-sanity/files/default/startTest.sh | 4 +- .../recipes/sanityTests_3_sanity_execution.rb | 2 +- .../sdc/ci/tests/api/ComponentBaseTest.java | 71 ++- .../org/openecomp/sdc/ci/tests/run/StartTest.java | 5 +- .../org/openecomp/sdc/ci/tests/sanity/Onboard.java | 14 +- .../sdc/ci/tests/utils/rest/ResponseParser.java | 2 +- test-apis-ci/src/main/resources/logback.xml | 4 +- 47 files changed, 1704 insertions(+), 666 deletions(-) create mode 100644 sdc-os-chef/scripts/docker_sanity_run.sh create mode 100644 sdc-os-chef/scripts/sanity_run.sh delete mode 100644 sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default/alter_dox_db.cql delete mode 100644 sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default/create_dox_db.cql create mode 100644 sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/Huawei_vPCRF.csar create mode 100644 sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/Huawei_vSPGW.csar create mode 100644 sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/ZteEpcMmeVf.csar create mode 100644 sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/ZteEpcSpgwVf.csar create mode 100644 sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/cscf_si.csar create mode 100644 sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vCSCF.csar create mode 100644 sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vSBC.csar create mode 100644 sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vfw.zip create mode 100644 sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vvg.zip create mode 100644 sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/conf/logback.xml diff --git a/asdc-tests/pom.xml b/asdc-tests/pom.xml index bfb7920d51..a37d1e8a9c 100644 --- a/asdc-tests/pom.xml +++ b/asdc-tests/pom.xml @@ -268,7 +268,7 @@ org.openecomp.sdc.sdc-distribution-client sdc-distribution-client - 1.1.9-SNAPSHOT + 1.1.32 compile diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java index 74bb55b63d..b7344e9911 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java @@ -191,7 +191,12 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { } public static enum ArtifactOperationEnum { - Create(), Update(), Delete(), Download(); + Create(), Update(), Delete(), Download(), Link(); + + public static boolean isCreateOrLink(ArtifactOperationEnum operation) { + return (operation.equals(Create) || operation.equals(Link)); + + } } public class ArtifactOperationInfo { @@ -3648,12 +3653,13 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { Either artifactfromES; ESArtifactData esArtifactData; if (esArtifactId != null && !esArtifactId.isEmpty() && artifactDefinition.getPayloadData() == null) { + log.debug("Try to fetch artifact from cassandra with id : {}", esArtifactId); artifactfromES = artifactCassandraDao.getArtifact(esArtifactId); if (artifactfromES.isRight()) { CassandraOperationStatus resourceUploadStatus = artifactfromES.right().value(); StorageOperationStatus storageResponse = DaoStatusConverter.convertCassandraStatusToStorageStatus(resourceUploadStatus); ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(storageResponse); - log.debug("Error when getting artifact from ES, error: {}", actionStatus.name()); + log.debug("Error when getting artifact from ES, error: {} esid : {}", actionStatus.name(), esArtifactId); return Either.right(componentsUtils.getResponseFormatByArtifactId(actionStatus, artifactDefinition.getArtifactDisplayName())); } esArtifactData = artifactfromES.left().value(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java index a34bf00a7a..108e03c274 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java @@ -1178,6 +1178,11 @@ public abstract class ComponentBusinessLogic extends BaseBusinessLogic { return text; } + public Either shouldUpgradeToLatestDerived(Component clonedComponent) { + //general implementation. Must be error for service, VF . In ResourceBuisnessLogic exist override + return Either.right(ActionStatus.GENERAL_ERROR); + } + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java index 6dc83bfc2b..66d8668fea 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java @@ -32,7 +32,6 @@ import java.util.UUID; import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.config.BeEcompErrorManager; @@ -42,15 +41,12 @@ import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; -import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; -import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.info.CreateAndAssotiateInfo; import org.openecomp.sdc.be.model.ArtifactDefinition; import org.openecomp.sdc.be.model.Component; @@ -60,26 +56,20 @@ import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.GroupDefinition; -import org.openecomp.sdc.be.model.GroupInstance; import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.LifecycleStateEnum; import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames; -import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; -import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.User; -import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; +import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.IComponentInstanceOperation; 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.PropertyOperation; -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.resources.data.ComponentInstanceData; -import org.openecomp.sdc.be.resources.data.PropertyValueData; -import org.openecomp.sdc.be.tosca.ToscaUtils; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; import org.openecomp.sdc.common.api.ArtifactTypeEnum; import org.openecomp.sdc.common.api.Constants; @@ -150,7 +140,7 @@ public abstract class ComponentInstanceBusinessLogic extends BaseBusinessLogic { containerComponent = validateComponentExists.left().value(); } - if (ToscaUtils.isAtomicType(containerComponent)) { + if (ModelConverter.isAtomicComponent(containerComponent)) { log.debug("Cannot attach resource instances to container resource of type {}", containerComponent.assetType()); return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES, containerComponent.assetType())); } @@ -209,7 +199,7 @@ public abstract class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } org.openecomp.sdc.be.model.Component containerComponent = validateComponentExists.left().value(); - if (ToscaUtils.isAtomicType(containerComponent)) { + if (ModelConverter.isAtomicComponent(containerComponent)) { log.debug("Cannot attach resource instances to container resource of type {}", containerComponent.assetType()); return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES, containerComponent.assetType())); } 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 0ae546479a..1ab7ffb007 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 @@ -111,6 +111,7 @@ import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.category.CategoryDefinition; import org.openecomp.sdc.be.model.category.SubCategoryDefinition; import org.openecomp.sdc.be.model.heat.HeatParameterType; +import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.ICacheMangerOperation; import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation; import org.openecomp.sdc.be.model.operations.api.IElementOperation; @@ -595,6 +596,14 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { log.trace("YAML topology file found in CSAR, file name: {}, contents: {}", yamlFileName, yamlFileContent); + Either genericResourceEither = handleResourceGenericType(preparedResource); + if (genericResourceEither.isRight()) { + log.debug("failed to get resource generic type. status is {}", genericResourceEither.right().value()); + ResponseFormat responseFormat = genericResourceEither.right().value(); + componentsUtils.auditResource(genericResourceEither.right().value(), csarInfo.getModifier(), preparedResource, "", "", updateResource, null); + return Either.right(responseFormat); + } + parseNodeTypeInfoYamlEither = this.handleNodeTypes(yamlFileName, preparedResource, yamlFileContent, shouldLock, nodeTypesArtifactsToHandle, createdArtifacts, nodeTypesInfo, csarInfo, nodeName); if (parseNodeTypeInfoYamlEither.isRight()) { ResponseFormat responseFormat = parseNodeTypeInfoYamlEither.right().value(); @@ -687,6 +696,17 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return result; } + private Either handleResourceGenericType(Resource resource) { + Either genericResourceEither = fetchAndSetDerivedFromGenericType(resource); + if (genericResourceEither.isRight()) { + return genericResourceEither; + } + if (resource.shouldGenerateInputs()) { + generateInputsFromGenericTypeProperties(resource, genericResourceEither.left().value()); + } + return genericResourceEither; + } + private Either>>, ResponseFormat> findNodeTypesArtifactsToHandle(Map nodeTypesInfo, CsarInfo csarInfo, Resource oldResource) { Map> extractedVfcsArtifacts = CsarUtils.extractVfcsArtifactsFromCsar(csarInfo.getCsar()); @@ -888,7 +908,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { handleNodeTypeArtifactsRes = Either.right(handleNodeTypeArtifactsRequestRes.right().value()); break; } - if (curOperation == ArtifactOperationEnum.Create) { + if (ArtifactOperationEnum.isCreateOrLink(curOperation)) { createdArtifacts.addAll(handleNodeTypeArtifactsRequestRes.left().value()); } handledNodeTypeArtifacts.addAll(handleNodeTypeArtifactsRequestRes.left().value()); @@ -917,6 +937,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { vfcToscaNames.put(nodeType.getKey(), toscaResourceName); } } + for(NodeTypeInfo cvfc : nodeTypesInfo.values()){ + vfcToscaNames.put(cvfc.getType(), buildNestedToscaResourceName(ResourceTypeEnum.CVFC.name(), vfResourceName, cvfc.getType())); + } return vfcToscaNames; } @@ -1107,7 +1130,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.right(validateRes.right().value()); } // VF / PNF "derivedFrom" should be null (or ignored) - if (ToscaUtils.isAtomicType(resource)) { + if (ModelConverter.isAtomicComponent(resource)) { Either validateDerivedFromNotEmpty = validateDerivedFromNotEmpty(user, resource, AuditingActionEnum.CREATE_RESOURCE); if (validateDerivedFromNotEmpty.isRight()) { return Either.right(validateDerivedFromNotEmpty.right().value()); @@ -1233,7 +1256,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } if(result == null){ newComplexVfc = buildCvfcRes.left().value(); - Either oldComplexVfcRes = toscaOperationFacade.getLatestByToscaResourceName(newComplexVfc.getToscaResourceName()); + Either oldComplexVfcRes = toscaOperationFacade.getFullLatestComponentByToscaResourceName(newComplexVfc.getToscaResourceName()); if(oldComplexVfcRes.isRight() && oldComplexVfcRes.right().value() != StorageOperationStatus.NOT_FOUND){ log.debug("Failed to fetch previous complex VFC by tosca resource name {}. Status is {}. ", newComplexVfc.getToscaResourceName(), oldComplexVfcRes.right().value()); result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); @@ -1461,7 +1484,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { String nameWithouNamespacePrefix = nodeName.substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length()); String[] findTypes = nameWithouNamespacePrefix.split("\\."); String resourceType = findTypes[0]; - return resourceVfName + "-" + nameWithouNamespacePrefix.substring(resourceType.length() + 1) + "Cvfc"; + String resourceName = resourceVfName + "-" + nameWithouNamespacePrefix.substring(resourceType.length() + 1); + return addCvfcSuffixToResourceName(resourceName); } private Either createResourceAndRIsFromYaml(String yamlName, Resource resource, ParsedToscaYamlInfo parsedToscaYamlInfo, AuditingActionEnum actionEnum, boolean isNormative, @@ -1869,25 +1893,27 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { log.debug("************* Going to create all nodes {}", yamlName); Either, ResponseFormat> createdResourcesFromdNodeTypeMap = this.handleNodeTypes(yamlName, resource, topologyTemplateYaml, false, nodeTypesArtifactsToCreate, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeName); + log.debug("************* Finished to create all nodes {}", yamlName); if (createdResourcesFromdNodeTypeMap.isRight()) { log.debug("failed to resources from node types status is {}", createdResourcesFromdNodeTypeMap.right().value()); return Either.right(createdResourcesFromdNodeTypeMap.right().value()); } - log.debug("************* Finished to create all nodes {}", yamlName); log.debug("************* Going to create all resource instances {}", yamlName); createResourcesInstancesEither = createResourceInstances(csarInfo.getModifier(), yamlName, resource, uploadComponentInstanceInfoMap, true, false, csarInfo.getCreatedNodes()); + log.debug("************* Finished to create all resource instances {}", yamlName); if (createResourcesInstancesEither.isRight()) { log.debug("failed to create resource instances status is {}", createResourcesInstancesEither.right().value()); result = createResourcesInstancesEither; return createResourcesInstancesEither; } - log.debug("************* Finished to create all resource instances for {}", yamlName); resource = createResourcesInstancesEither.left().value(); log.debug("************* Going to create all relations {}", yamlName); createResourcesInstancesEither = createResourceInstancesRelations(csarInfo.getModifier(), yamlName, resource, uploadComponentInstanceInfoMap); + log.debug("************* Finished to create all relations {}", yamlName); + if (createResourcesInstancesEither.isRight()) { log.debug("failed to create relation between resource instances status is {}", createResourcesInstancesEither.right().value()); result = createResourcesInstancesEither; @@ -1895,7 +1921,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } else { resource = createResourcesInstancesEither.left().value(); } - log.debug("************* Finished to create all relations {}", yamlName); log.debug("************* Going to create positions {}", yamlName); Either, ResponseFormat> eitherSetPosition = compositionBusinessLogic.setPositionsForComponentInstances(resource, csarInfo.getModifier().getUserId()); @@ -1987,6 +2012,14 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (eitherCreateResult.isRight()) { return Either.right(eitherCreateResult.right().value()); } + Either eitherGerResource = toscaOperationFacade.getToscaElement(resource.getUniqueId()); + if (eitherGerResource.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(eitherGerResource.right().value()), resource); + + return Either.right(responseFormat); + + } + resource = eitherGerResource.left().value(); Either, ResponseFormat> artifacsMetaCsarStatus = CsarValidationUtils.getArtifactsMeta(csarInfo.getCsar(), csarInfo.getCsarUUID(), componentsUtils); if (artifacsMetaCsarStatus.isLeft()) { @@ -1994,7 +2027,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { String artifactsFileName = artifacsMetaCsarStatus.left().value().getKey(); String artifactsContents = artifacsMetaCsarStatus.left().value().getValue(); Either createArtifactsFromCsar = Either.left(resource); - if (artifactOperation.getArtifactOperationEnum() == ArtifactOperationEnum.Create) + if (ArtifactOperationEnum.isCreateOrLink(artifactOperation.getArtifactOperationEnum())) createArtifactsFromCsar = createResourceArtifactsFromCsar(csarInfo, resource, artifactsContents, artifactsFileName, createdArtifacts, shouldLock, inTransaction); else createArtifactsFromCsar = updateResourceArtifactsFromCsar(csarInfo, resource, artifactsContents, artifactsFileName, createdArtifacts, shouldLock, inTransaction); @@ -2074,7 +2107,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private void addNonMetaCreatedArtifactsToSupportRollback(ArtifactOperationInfo operation, List createdArtifacts, Either, ResponseFormat> eitherNonMetaArtifacts) { - if (operation.getArtifactOperationEnum() == ArtifactOperationEnum.Create && createdArtifacts != null && eitherNonMetaArtifacts.isLeft()) { + if (ArtifactOperationEnum.isCreateOrLink(operation.getArtifactOperationEnum()) && createdArtifacts != null && eitherNonMetaArtifacts.isLeft()) { Either eitherResult = eitherNonMetaArtifacts.left().value(); if (eitherResult.isLeft()) { createdArtifacts.add(eitherResult.left().value()); @@ -2140,16 +2173,27 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map> parsedGroup = new HashMap>(); for (List parsedGroupTemplateList : parsedArifactsCollection) { + for (ArtifactTemplateInfo parsedGroupTemplate : parsedGroupTemplateList) { - parsedGroupTemplate.setGroupName(""); - Set parsedArtifactsNames = new HashSet(); - parsedArtifactsNames.add(parsedGroupTemplate); - List relatedGroupTemplateList = parsedGroupTemplate.getRelatedArtifactsInfo(); - if (relatedGroupTemplateList != null && !relatedGroupTemplateList.isEmpty()) { - createArtifactsGroupSet(parsedGroupTemplateList, parsedArtifactsNames); + if(parsedGroupTemplate.getGroupName() != null){ + parsedGroupTemplate.setGroupName(""); + Set parsedArtifactsNames = new HashSet(); + parsedArtifactsNames.add(parsedGroupTemplate); + List relatedGroupTemplateList = parsedGroupTemplate.getRelatedArtifactsInfo(); + if (relatedGroupTemplateList != null && !relatedGroupTemplateList.isEmpty()) { + createArtifactsGroupSet(parsedGroupTemplateList, parsedArtifactsNames); + } + parsedGroup.put(parsedGroupTemplate, parsedArtifactsNames); + }else{ + List arrtifacts = new ArrayList(); + arrtifacts.add(parsedGroupTemplate); + Either resStatus = createGroupDeploymentArtifactsFromCsar(csarInfo, resource, arrtifacts, createdNewArtifacts, createdDeplymentArtifactsAfterDelete, labelCounter, shouldLock, inTransaction); + if (resStatus.isRight()) + return resStatus; + } - parsedGroup.put(parsedGroupTemplate, parsedArtifactsNames); } + } ///////////////////////////////// find artifacts to @@ -2670,42 +2714,40 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { resStatus = createDeploymentArtifactsFromCsar(csarInfo, resource, artifactsGroup, artifactsUUIDGroup, groupTemplateInfo, createdNewArtifacts, artifactsFromResource, labelCounter, shouldLock, inTransaction); if (resStatus.isRight()) return resStatus; - - Map members = new HashMap(); - associateMembersToArtifacts(createdNewArtifacts, artifactsFromResource, heatGroups, artifactsGroup, members); - - List artifactsList = new ArrayList(artifactsGroup); - List artifactsUUIDList = new ArrayList(artifactsUUIDGroup); - - GroupDefinition groupDefinition = new GroupDefinition(); - groupDefinition.setName(groupName); - groupDefinition.setType(Constants.DEFAULT_GROUP_VF_MODULE); - groupDefinition.setArtifacts(artifactsList); - groupDefinition.setArtifactsUuid(artifactsUUIDList); - - if (!members.isEmpty()) - groupDefinition.setMembers(members); - - List properties = new ArrayList(); - GroupProperty prop = new GroupProperty(); - prop.setName(Constants.IS_BASE); - prop.setValue(Boolean.toString(groupTemplateInfo.isBase())); - properties.add(prop); - - List createdArtifacts = new ArrayList<>(); - createdArtifacts.addAll(createdNewArtifacts); - createdArtifacts.addAll(artifactsFromResource); - Either getLatestGroupTypeRes = groupTypeOperation.getLatestGroupTypeByType(Constants.DEFAULT_GROUP_VF_MODULE, true); - if (getLatestGroupTypeRes.isRight()) { - return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(getLatestGroupTypeRes.right().value()))); + if(groupName != null && !groupName.isEmpty()){ + Map members = new HashMap(); + associateMembersToArtifacts(createdNewArtifacts, artifactsFromResource, heatGroups, artifactsGroup, members); + + List artifactsList = new ArrayList(artifactsGroup); + List artifactsUUIDList = new ArrayList(artifactsUUIDGroup); + + GroupDefinition groupDefinition = new GroupDefinition(); + groupDefinition.setName(groupName); + groupDefinition.setType(Constants.DEFAULT_GROUP_VF_MODULE); + groupDefinition.setArtifacts(artifactsList); + groupDefinition.setArtifactsUuid(artifactsUUIDList); + + if (!members.isEmpty()) + groupDefinition.setMembers(members); + + List properties = new ArrayList(); + GroupProperty prop = new GroupProperty(); + prop.setName(Constants.IS_BASE); + prop.setValue(Boolean.toString(groupTemplateInfo.isBase())); + properties.add(prop); + + List createdArtifacts = new ArrayList<>(); + createdArtifacts.addAll(createdNewArtifacts); + createdArtifacts.addAll(artifactsFromResource); + Either getLatestGroupTypeRes = groupTypeOperation.getLatestGroupTypeByType(Constants.DEFAULT_GROUP_VF_MODULE, true); + if (getLatestGroupTypeRes.isRight()) { + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(getLatestGroupTypeRes.right().value()))); + } + properties = createVfModuleAdditionalProperties(groupTemplateInfo.isBase(), groupName, properties, createdArtifacts, artifactsList, getLatestGroupTypeRes.left().value()); + groupDefinition.convertFromGroupProperties(properties); + + needToAdd.add(groupDefinition); } - properties = createVfModuleAdditionalProperties(groupTemplateInfo.isBase(), groupName, properties, createdArtifacts, artifactsList, getLatestGroupTypeRes.left().value()); - groupDefinition.convertFromGroupProperties(properties); - - // Either createGroup = groupBusinessLogic.createGroup(resource.getUniqueId(), user.getUserId(), ComponentTypeEnum.RESOURCE, groupDefinition, inTransaction); - // if (createGroup.isRight()) - // return Either.right(createGroup.right().value()); - needToAdd.add(groupDefinition); } ComponentParametersView componentParametersView = new ComponentParametersView(); componentParametersView.disableAll(); @@ -2858,7 +2900,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { EnumMap> vfCsarArtifactsToHandle = null; - if (artifactOperation.getArtifactOperationEnum() == ArtifactOperationEnum.Create) { + if (ArtifactOperationEnum.isCreateOrLink(artifactOperation.getArtifactOperationEnum())) { vfCsarArtifactsToHandle = new EnumMap<>(ArtifactOperationEnum.class); vfCsarArtifactsToHandle.put(artifactOperation.getArtifactOperationEnum(), artifactPathAndNameList); } else { @@ -2989,42 +3031,36 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { log.debug("createDeploymentArtifactsFromCsar end"); if (resStatus.isRight()) return resStatus; - - Map members = new HashMap(); - associateMembersToArtifacts(createdArtifacts, null, heatGroups, artifactsGroup, members); - - List artifactsList = new ArrayList(artifactsGroup); - List artifactsUUIDList = new ArrayList(artifactsUUIDGroup); - - GroupDefinition groupDefinition = new GroupDefinition(); - groupDefinition.setName(groupName); - groupDefinition.setType(Constants.DEFAULT_GROUP_VF_MODULE); - groupDefinition.setArtifacts(artifactsList); - groupDefinition.setArtifactsUuid(artifactsUUIDList); - - if (!members.isEmpty()) - groupDefinition.setMembers(members); - List properties = new ArrayList(); - GroupProperty prop = new GroupProperty(); - prop.setName(Constants.IS_BASE); - prop.setValue(Boolean.toString(groupTemplateInfo.isBase())); - properties.add(prop); - Either getLatestGroupTypeRes = groupTypeOperation.getLatestGroupTypeByType(Constants.DEFAULT_GROUP_VF_MODULE, true); - if (getLatestGroupTypeRes.isRight()) { - return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(getLatestGroupTypeRes.right().value()))); + if(groupName != null && !groupName.isEmpty()){ + Map members = new HashMap(); + associateMembersToArtifacts(createdArtifacts, null, heatGroups, artifactsGroup, members); + + List artifactsList = new ArrayList(artifactsGroup); + List artifactsUUIDList = new ArrayList(artifactsUUIDGroup); + + GroupDefinition groupDefinition = new GroupDefinition(); + groupDefinition.setName(groupName); + groupDefinition.setType(Constants.DEFAULT_GROUP_VF_MODULE); + groupDefinition.setArtifacts(artifactsList); + groupDefinition.setArtifactsUuid(artifactsUUIDList); + + if (!members.isEmpty()) + groupDefinition.setMembers(members); + List properties = new ArrayList(); + GroupProperty prop = new GroupProperty(); + prop.setName(Constants.IS_BASE); + prop.setValue(Boolean.toString(groupTemplateInfo.isBase())); + properties.add(prop); + Either getLatestGroupTypeRes = groupTypeOperation.getLatestGroupTypeByType(Constants.DEFAULT_GROUP_VF_MODULE, true); + if (getLatestGroupTypeRes.isRight()) { + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(getLatestGroupTypeRes.right().value()))); + } + properties = createVfModuleAdditionalProperties(groupTemplateInfo.isBase(), groupName, properties, createdArtifacts, artifactsList, getLatestGroupTypeRes.left().value()); + groupDefinition.convertFromGroupProperties(properties); + log.debug("createGroup start"); + + needToCreate.add(groupDefinition); } - properties = createVfModuleAdditionalProperties(groupTemplateInfo.isBase(), groupName, properties, createdArtifacts, artifactsList, getLatestGroupTypeRes.left().value()); - groupDefinition.convertFromGroupProperties(properties); - log.debug("createGroup start"); - - // Since in these groups we handle only artifacts, then no need to - // fetch component instances - - // Either createGroup = groupBusinessLogic.createGroup(comp, user, ComponentTypeEnum.RESOURCE, groupDefinition, inTransaction); - // log.debug("createGroup end"); - // if (createGroup.isRight()) - // return Either.right(createGroup.right().value()); - needToCreate.add(groupDefinition); } ComponentParametersView componentParametersView = new ComponentParametersView(); @@ -3496,7 +3532,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID_FORMAT, artifactFileName)); } - allGroups.addAll(artifactTemplateInfoList); + if(!artifactsTypeKey.equalsIgnoreCase(ArtifactTemplateInfo.CSAR_ARTIFACT)) + allGroups.addAll(artifactTemplateInfoList); artifactsMap.put(artifactsTypeKey, artifactTemplateInfoList); } int counter = groupBusinessLogic.getNextVfModuleNameCounter(resource.getGroups()); @@ -3602,10 +3639,40 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } else { originResource = originCompMap.get(currentCompInstance.getComponentUid()); } - if (originResource.getCapabilities() != null && !originResource.getCapabilities().isEmpty()) - instCapabilties.put(currentCompInstance, originResource.getCapabilities()); if (originResource.getRequirements() != null && !originResource.getRequirements().isEmpty()) instRequirements.put(currentCompInstance, originResource.getRequirements()); + if (MapUtils.isNotEmpty(originResource.getCapabilities())) { + Map> originCapabilities ; + if (MapUtils.isNotEmpty(uploadComponentInstanceInfo.getCapabilities())) { + originCapabilities = new HashMap<>(); + originResource.getCapabilities().entrySet().stream().forEach(e ->{ + List list = e.getValue().stream().map(l -> new CapabilityDefinition(l)).collect(Collectors.toList()); + originCapabilities.put(e.getKey(), list); + }); + Map> newPropertiesMap = new HashMap<>(); + for(List capabilities : uploadComponentInstanceInfo.getCapabilities().values()){ + for(UploadCapInfo capability :capabilities){ + if(CollectionUtils.isNotEmpty(capability.getProperties())){ + newPropertiesMap.put(capability.getName(), capability.getProperties().stream().collect(Collectors.toMap(p->p.getName(), p->p))); + } + } + } + for (List capabilities : originCapabilities.values()) { + List filteredCapabilities = capabilities.stream().filter(c -> newPropertiesMap.containsKey(c.getName())).collect(Collectors.toList()); + for(CapabilityDefinition cap : filteredCapabilities){ + Either updateRes = updatePropertyValues(cap.getProperties(),newPropertiesMap.get(cap.getName()), allDataTypes.left().value()); + if(updateRes.isRight()){ + log.debug("Failed to update capability properties of capability {} . Status is {}. ", cap.getName(), updateRes.right().value()); + return Either.right(updateRes.right().value()); + } + } + } + } + else{ + originCapabilities = originResource.getCapabilities(); + } + instCapabilties.put(currentCompInstance, originCapabilities); + } if (originResource.getDeploymentArtifacts() != null && !originResource.getDeploymentArtifacts().isEmpty()) instDeploymentArtifacts.put(resourceInstanceId, originResource.getDeploymentArtifacts()); if (originResource.getArtifacts() != null && !originResource.getArtifacts().isEmpty()) @@ -3618,14 +3685,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.right(addPropertiesValueToRiRes); } } else { - Either genericResourceEither = fetchAndSetDerivedFromGenericType(originResource); - if (genericResourceEither.isRight()) { - return genericResourceEither; - } - log.trace("************* Going to add inputs from from original resource {} to resource instance. ", originResource.getName()); - if (originResource.shouldGenerateInputs()) - generateInputsFromGenericTypeProperties(originResource, genericResourceEither.left().value()); - ResponseFormat addInputValueToRiRes = addInputsValuesToRi(uploadComponentInstanceInfo, resource, originResource, currentCompInstance, yamlName, instInputs, allDataTypes.left().value()); if (addInputValueToRiRes.getStatus() != 200) { return Either.right(addInputValueToRiRes); @@ -3724,25 +3783,54 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.right(responseFormat); } + if(resource.getResourceType() == ResourceTypeEnum.CVFC){ + eitherGetResource = toscaOperationFacade.getToscaFullElement(resource.getUniqueId()); + if (eitherGetResource.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(eitherGetResource.right().value()), resource); + return Either.right(responseFormat); + } + eitherGetResource = updateCalculatedCapReqWithSubstitutionMappings(eitherGetResource.left().value(), uploadResInstancesMap); + if (eitherGetResource.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(eitherGetResource.right().value()), resource); + return Either.right(responseFormat); + } + } + log.debug("************* in create relations, getResource start"); - eitherGetResource = toscaOperationFacade.getToscaElement(resource.getUniqueId()); log.debug("************* in create relations, getResource end"); if (eitherGetResource.isRight()) { ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(eitherGetResource.right().value()), resource); - return Either.right(responseFormat); - } - resource = eitherGetResource.left().value(); - if(resource.getResourceType() == ResourceTypeEnum.CVFC){ - eitherGetResource = updateCalculatedCapReqWithSubstitutionMappings(resource, uploadResInstancesMap); - if (eitherGetResource.isRight()) { - ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(eitherGetResource.right().value()), resource); - return Either.right(responseFormat); + return Either.left(eitherGetResource.left().value()); + } + + private Either updatePropertyValues(List properties, Map newProperties, Map allDataTypes) { + for(ComponentInstanceProperty property : properties){ + Either updateRes = updatePropertyValue(property ,newProperties.get(property.getName()), allDataTypes); + if(updateRes.isRight()){ + log.debug("Failed to update capability property {} . Status is {}. ", property.getName(), updateRes.right().value()); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(updateRes.right().value()))); } } - return Either.left(eitherGetResource.left().value()); + return Either.left(true); + } + + private Either updatePropertyValue(ComponentInstanceProperty property, UploadPropInfo propertyInfo, Map allDataTypes) { + String value = null; + List getInputs = null; + boolean isValidate = true; + if (null != propertyInfo && null != propertyInfo.getValue()) { + getInputs = propertyInfo.getGet_input(); + isValidate = getInputs == null || getInputs.isEmpty(); + if (isValidate) { + value = ImportUtils.getPropertyJsonStringValue(propertyInfo.getValue(), property.getType()); + } else + value = ImportUtils.getPropertyJsonStringValue(propertyInfo.getValue(), ToscaTagNamesEnum.GET_INPUT.getElementName()); + } + property.setValue(value); + return validatePropValueBeforeCreate(property, value, isValidate, null, allDataTypes); } private Either updateCalculatedCapReqWithSubstitutionMappings(Resource resource, Map uploadResInstancesMap) { @@ -3763,7 +3851,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } if(updateRes == null){ - updateRes = toscaOperationFacade.getToscaElement( resource.getUniqueId()); + updateRes = Either.left(resource); } return updateRes; } @@ -4010,25 +4098,28 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private ResponseFormat addPropertyValuesToRi(UploadComponentInstanceInfo uploadComponentInstanceInfo, Resource resource, Resource originResource, ComponentInstance currentCompInstance, String yamlName, - Map> instProperties, Map allDataTypes) { + Map> instProperties, Map allDataTypes) { Map> propMap = uploadComponentInstanceInfo.getProperties(); - if (propMap != null && propMap.size() > 0) { - Map currPropertiesMap = new HashMap(); + Map currPropertiesMap = new HashMap(); - List listFromMap = originResource.getProperties(); - if (listFromMap == null || listFromMap.isEmpty()) { - log.debug("failed to find properties "); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND); - return responseFormat; - } - for (PropertyDefinition prop : listFromMap) { - String propName = prop.getName(); - if (!currPropertiesMap.containsKey(propName)) { - currPropertiesMap.put(propName, prop); - } + List listFromMap = originResource.getProperties(); + if ((propMap != null && !propMap.isEmpty()) && (listFromMap == null || listFromMap.isEmpty())) { + log.debug("failed to find properties "); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND); + return responseFormat; + } + if(listFromMap == null || listFromMap.isEmpty()){ + return componentsUtils.getResponseFormat(ActionStatus.OK); + } + for (PropertyDefinition prop : listFromMap) { + String propName = prop.getName(); + if (!currPropertiesMap.containsKey(propName)) { + currPropertiesMap.put(propName, prop); } - List instPropList = new ArrayList<>(); + } + List instPropList = new ArrayList<>(); + if (propMap != null && propMap.size() > 0) { for (List propertyList : propMap.values()) { UploadPropInfo propertyInfo = propertyList.get(0); @@ -4104,14 +4195,14 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // delete overriden property currPropertiesMap.remove(property.getName()); } - // add rest of properties - if (!currPropertiesMap.isEmpty()) { - for (PropertyDefinition value : currPropertiesMap.values()) { - instPropList.add(new ComponentInstanceProperty(value)); - } + } + // add rest of properties + if (!currPropertiesMap.isEmpty()) { + for (PropertyDefinition value : currPropertiesMap.values()) { + instPropList.add(new ComponentInstanceProperty(value)); } - instProperties.put(currentCompInstance.getUniqueId(), instPropList); } + instProperties.put(currentCompInstance.getUniqueId(), instPropList); return componentsUtils.getResponseFormat(ActionStatus.OK); } @@ -4264,6 +4355,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.left(validRegDef); } + @SuppressWarnings("unchecked") public Either parseResourceInfoFromYaml(String yamlFileName, Resource resource, String resourceYml, Map createdNodesToscaResourceNames, Map nodeTypesInfo, String nodeName) { Map mappedToscaTemplate; @@ -4317,7 +4409,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map nodeNamespaceMap) { Either eitherResource = null; - log.debug("{} - going to create resource instanse from CSAR", yamlName); + log.debug("createResourceInstances is {} - going to create resource instanse from CSAR", yamlName); if (uploadResInstancesMap == null || uploadResInstancesMap.isEmpty()) { ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE); @@ -4332,13 +4424,13 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Iterator> nodesInfoValue = uploadResInstancesMap.entrySet().iterator(); Map resourcesInstancesMap = new HashMap<>(); while (nodesInfoValue.hasNext()) { - log.debug("*************Going to create resource instances from {}", yamlName); + log.debug("*************Going to create resource instances {}", yamlName); Entry uploadComponentInstanceInfoEntry = nodesInfoValue.next(); UploadComponentInstanceInfo uploadComponentInstanceInfo = uploadComponentInstanceInfoEntry.getValue(); // updating type if the type is node type name - we need to take the // updated name - log.debug("*************Going to create resource instance {}", uploadComponentInstanceInfo.getName()); + log.debug("*************Going to create resource instances {}", uploadComponentInstanceInfo.getName()); if (nodeNamespaceMap.containsKey(uploadComponentInstanceInfo.getType())) { uploadComponentInstanceInfo.setType(nodeNamespaceMap.get(uploadComponentInstanceInfo.getType()).getToscaResourceName()); } @@ -4355,7 +4447,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ComponentTypeEnum containerComponentType = resource.getComponentType(); NodeTypeEnum containerNodeType = containerComponentType.getNodeType(); - //************ + if (containerNodeType.equals(NodeTypeEnum.Resource) && MapUtils.isNotEmpty(uploadComponentInstanceInfo.getCapabilities()) && MapUtils.isNotEmpty(refResource.getCapabilities())) { setCapabilityNamesTypes(refResource.getCapabilities(), uploadComponentInstanceInfo.getCapabilities()); Either>, ResponseFormat> getValidComponentInstanceCapabilitiesRes = getValidComponentInstanceCapabilities(refResource.getUniqueId(), refResource.getCapabilities(), uploadComponentInstanceInfo.getCapabilities()); @@ -4365,9 +4457,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { componentInstance.setCapabilities(getValidComponentInstanceCapabilitiesRes.left().value()); } } - //*********************** if (!existingnodeTypeMap.containsKey(uploadComponentInstanceInfo.getType())) { - log.debug("createResourceInstances - not found latest version for resource instance with name {} and type ", uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); + log.debug("createResourceInstances - not found lates version for resource instance with name {} and type ", uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_NODE_TEMPLATE, yamlName, uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); return Either.right(responseFormat); } @@ -4417,30 +4508,28 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.left(eitherGerResource.left().value()); } - + private void setCapabilityNamesTypes(Map> originCapabilities, Map> uploadedCapabilities) { for(Entry> currEntry : uploadedCapabilities.entrySet()){ if(originCapabilities.containsKey(currEntry.getKey())){ currEntry.getValue().stream().forEach(cap -> cap.setType(currEntry.getKey())); } } - for(Map.Entry> capabilities : originCapabilities.entrySet()){ capabilities.getValue().stream().forEach(cap -> {if(uploadedCapabilities.containsKey(cap.getName())){uploadedCapabilities.get(cap.getName()).stream().forEach(c -> {c.setName(cap.getName());c.setType(cap.getType());});};}); - } + } + } - - private Either validateResourceInstanceBeforeCreate(String yamlName, UploadComponentInstanceInfo uploadComponentInstanceInfo, Map nodeNamespaceMap) { - log.debug("going to validate resource instance with name {} and type {} before create", uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); + log.debug("validateResourceInstanceBeforeCreate - going to validate resource instance with name {} and type before create", uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); Resource refResource = null; if (nodeNamespaceMap.containsKey(uploadComponentInstanceInfo.getType())) { refResource = nodeNamespaceMap.get(uploadComponentInstanceInfo.getType()); } else { Either findResourceEither = toscaOperationFacade.getLatestCertifiedNodeTypeByToscaResourceName(uploadComponentInstanceInfo.getType()); if (findResourceEither.isRight()) { - log.debug("not found lates version for resource instance with name {} and type {}", uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); + log.debug("validateResourceInstanceBeforeCreate - not found lates version for resource instance with name {} and type ", uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(findResourceEither.right().value())); return Either.right(responseFormat); } @@ -4449,17 +4538,16 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } String componentState = refResource.getComponentMetadataDefinition().getMetadataDataDefinition().getState(); if (componentState.equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) { - log.debug("component instance of component {} can not be created because the component is in an illegal state {}.", refResource.getName(), componentState); + log.debug("validateResourceInstanceBeforeCreate - component instance of component {} can not be created because the component is in an illegal state {}.", refResource.getName(), componentState); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.ILLEGAL_COMPONENT_STATE, refResource.getComponentType().getValue(), refResource.getName(), componentState); return Either.right(responseFormat); } - if (!ToscaUtils.isAtomicType(refResource) && refResource.getResourceType() != ResourceTypeEnum.CVFC) { - log.debug("ref resource type is {}", refResource.getResourceType()); + if (!ModelConverter.isAtomicComponent(refResource) && refResource.getResourceType() != ResourceTypeEnum.CVFC) { + log.debug("validateResourceInstanceBeforeCreate - ref resource type is ", refResource.getResourceType()); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_NODE_TEMPLATE, yamlName, uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); return Either.right(responseFormat); } - log.debug("validate resource instance with name {} and type {} before create, successful",uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); return Either.left(refResource); } @@ -4788,32 +4876,30 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return result; } - @SuppressWarnings("unchecked") - private Either>, ResponseFormat> createCapModuleFromYaml(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { - Map> moduleCap = new HashMap>(); - Either>, ResponseFormat> response = Either.left(moduleCap); - Either, ResultStatusEnum> toscaRequirements = ImportUtils.findFirstToscaListElement(nodeTemplateJsonMap, ToscaTagNamesEnum.CAPABILITIES); - if (toscaRequirements.isLeft()) { - List jsonCapabilities = toscaRequirements.left().value(); - - for (Object jsonCapObj : jsonCapabilities) { - // Requirement - Map capJsonWrapper = (Map) jsonCapObj; - String capName = capJsonWrapper.keySet().iterator().next(); - Either eitherCap = createModuleNodeTemplateCap(capJsonWrapper.get(capName)); + private Either>, ResponseFormat> createReqModuleFromYaml(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { + Map> moduleRequirements = new HashMap>(); + Either>, ResponseFormat> response = Either.left(moduleRequirements); + Either, ResultStatusEnum> requirementsListRes = ImportUtils.findFirstToscaListElement(nodeTemplateJsonMap, ToscaTagNamesEnum.REQUIREMENTS); + + if (requirementsListRes.isLeft()) { + for (Object jsonReqObj : requirementsListRes.left().value()) { + String reqName = ((Map) jsonReqObj).keySet().iterator().next(); + Object reqJson = ((Map) jsonReqObj).get(reqName); + Either eitherCap = addModuleNodeTemplateReq(nodeTemplateInfo, moduleRequirements, reqJson, reqName); if (eitherCap.isRight()) { - log.info("error when creating Requirement:{}, for node:{}", capName, nodeTemplateInfo); return Either.right(eitherCap.right().value()); - } else { - UploadCapInfo requirementDef = eitherCap.left().value(); - requirementDef.setName(capName); - if (moduleCap.containsKey(capName)) { - moduleCap.get(capName).add(requirementDef); - } else { - List list = new ArrayList(); - list.add(requirementDef); - moduleCap.put(capName, list); + } + } + } else { + Either, ResultStatusEnum> requirementsMapRes = ImportUtils.findFirstToscaMapElement(nodeTemplateJsonMap, ToscaTagNamesEnum.REQUIREMENTS); + if (requirementsMapRes.isLeft()) { + for (Map.Entry entry: requirementsMapRes.left().value().entrySet()) { + String reqName = entry.getKey(); + Object reqJson = entry.getValue(); + Either eitherCap = addModuleNodeTemplateReq(nodeTemplateInfo, moduleRequirements, reqJson, reqName); + if (eitherCap.isRight()) { + return Either.right(eitherCap.right().value()); } } } @@ -4821,31 +4907,49 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return response; } - @SuppressWarnings("unchecked") - private Either>, ResponseFormat> createReqModuleFromYaml(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { - Map> moduleRequirements = new HashMap>(); - Either>, ResponseFormat> response = Either.left(moduleRequirements); - Either, ResultStatusEnum> toscaRequirements = ImportUtils.findFirstToscaListElement(nodeTemplateJsonMap, ToscaTagNamesEnum.REQUIREMENTS); - if (toscaRequirements.isLeft()) { - List jsonRequirements = toscaRequirements.left().value(); - - for (Object jsonRequirementObj : jsonRequirements) { - // Requirement - Map requirementJsonWrapper = (Map) jsonRequirementObj; - String requirementName = requirementJsonWrapper.keySet().iterator().next(); - Either eitherRequirement = createModuleNodeTemplateReg(requirementJsonWrapper.get(requirementName)); - if (eitherRequirement.isRight()) { - log.info("error when creating Requirement:{}, for node:{}", requirementName, nodeTemplateInfo); - return Either.right(eitherRequirement.right().value()); - } else { - UploadReqInfo requirementDef = eitherRequirement.left().value(); - requirementDef.setName(requirementName); - if (moduleRequirements.containsKey(requirementName)) { - moduleRequirements.get(requirementName).add(requirementDef); - } else { - List list = new ArrayList(); - list.add(requirementDef); - moduleRequirements.put(requirementName, list); + private Either addModuleNodeTemplateReq(UploadComponentInstanceInfo nodeTemplateInfo,Map> moduleRequirements, Object requirementJson, String requirementName) { + + Either eitherRequirement = createModuleNodeTemplateReg(requirementJson); + if (eitherRequirement.isRight()) { + log.info("error when creating Requirement:{}, for node:{}", requirementName, nodeTemplateInfo); + return Either.right(eitherRequirement.right().value()); + } else { + UploadReqInfo requirementDef = eitherRequirement.left().value(); + requirementDef.setName(requirementName); + if (moduleRequirements.containsKey(requirementName)) { + moduleRequirements.get(requirementName).add(requirementDef); + } else { + List list = new ArrayList(); + list.add(requirementDef); + moduleRequirements.put(requirementName, list); + } + } + return Either.left(eitherRequirement.left().value()); + } + + @SuppressWarnings("unchecked") + private Either>, ResponseFormat> createCapModuleFromYaml(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { + Map> moduleCap = new HashMap<>(); + Either>, ResponseFormat> response = Either.left(moduleCap); + Either, ResultStatusEnum> capabilitiesListRes = ImportUtils.findFirstToscaListElement(nodeTemplateJsonMap, ToscaTagNamesEnum.CAPABILITIES); + if (capabilitiesListRes.isLeft()) { + for (Object jsonCapObj : capabilitiesListRes.left().value()) { + String key = ((Map) jsonCapObj).keySet().iterator().next(); + Object capJson = ((Map) jsonCapObj).get(key); + Either eitherCap = addModuleNodeTemplateCap(nodeTemplateInfo, moduleCap, capJson, key); + if (eitherCap.isRight()) { + return Either.right(eitherCap.right().value()); + } + } + } else { + Either, ResultStatusEnum> capabilitiesMapRes = ImportUtils.findFirstToscaMapElement(nodeTemplateJsonMap, ToscaTagNamesEnum.CAPABILITIES); + if (capabilitiesMapRes.isLeft()) { + for (Map.Entry entry: capabilitiesMapRes.left().value().entrySet()) { + String capName = entry.getKey(); + Object capJson = entry.getValue(); + Either eitherCap = addModuleNodeTemplateCap(nodeTemplateInfo, moduleCap, capJson, capName); + if (eitherCap.isRight()) { + return Either.right(eitherCap.right().value()); } } } @@ -4853,6 +4957,26 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return response; } + private Either addModuleNodeTemplateCap(UploadComponentInstanceInfo nodeTemplateInfo, Map> moduleCap, Object capJson, String key) { + + Either eitherCap = createModuleNodeTemplateCap(capJson); + if (eitherCap.isRight()) { + log.info("error when creating Capability:{}, for node:{}", key, nodeTemplateInfo); + return Either.right(eitherCap.right().value()); + } else { + UploadCapInfo capabilityDef = eitherCap.left().value(); + capabilityDef.setKey(key); + if (moduleCap.containsKey(key)) { + moduleCap.get(key).add(capabilityDef); + } else { + List list = new ArrayList(); + list.add(capabilityDef); + moduleCap.put(key, list); + } + } + return Either.left( eitherCap.left().value()); + } + @SuppressWarnings("unchecked") private Either createModuleNodeTemplateCap(Object capObject) { UploadCapInfo capTemplateInfo = new UploadCapInfo(); @@ -5065,6 +5189,11 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { result = Either.right(validateFieldsResponse.right().value()); return result; } + + validateFieldsResponse = validateCapabilityTypesCreate(user, getCapabilityTypeOperation(), newResource, AuditingActionEnum.IMPORT_RESOURCE, inTransaction); + if (validateFieldsResponse.isRight()) { + return Either.right(validateFieldsResponse.right().value()); + } // contact info normalization newResource.setContactId(newResource.getContactId().toLowerCase()); @@ -5201,7 +5330,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { resource.setCreatorUserId(user.getUserId()); resource.setCreatorFullName(user.getFirstName() + " " + user.getLastName()); resource.setContactId(resource.getContactId().toLowerCase()); - if (StringUtils.isEmpty(resource.getToscaResourceName()) && !ToscaUtils.isAtomicType(resource)) { + if (StringUtils.isEmpty(resource.getToscaResourceName()) && !ModelConverter.isAtomicComponent(resource)) { String resourceSystemName; if(csarInfo != null && StringUtils.isNotEmpty(csarInfo.getVfResourceName())){ resourceSystemName = ValidationUtils.convertToSystemName(csarInfo.getVfResourceName()); @@ -5370,11 +5499,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } try { if (resource.deriveFromGeneric()) { - Either genericResourceEither = fetchAndSetDerivedFromGenericType(resource); + Either genericResourceEither = handleResourceGenericType(resource); if (genericResourceEither.isRight()) return genericResourceEither; - if (resource.shouldGenerateInputs()) - generateInputsFromGenericTypeProperties(resource, genericResourceEither.left().value()); } Either respStatus = createResourceTransaction(resource, user, isNormative, inTransaction); @@ -5739,7 +5866,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // list // This code is not called from import resources, because of root // VF "derivedFrom" should be null (or ignored) - if (ToscaUtils.isAtomicType(currentResource)) { + if (ModelConverter.isAtomicComponent(currentResource)) { Either derivedFromNotEmptyEither = validateDerivedFromNotEmpty(null, newResource, null); if (derivedFromNotEmptyEither.isRight()) { log.debug("for updated resource {}, derived from field is empty", newResource.getName()); @@ -5953,7 +6080,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // validate template (derived from) log.debug("validate derived from"); - if (!ToscaUtils.isAtomicType(resource) && resource.getResourceType() != ResourceTypeEnum.CVFC) { + if (!ModelConverter.isAtomicComponent(resource) && resource.getResourceType() != ResourceTypeEnum.CVFC) { resource.setDerivedFrom(null); } eitherValidation = validateDerivedFromExist(user, resource, actionEnum); @@ -6173,10 +6300,23 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { * return Either.left(true); } */ - private Either validateResourceName(Resource currentResource, Resource updateInfoResource, boolean hasBeenCertified) { + private boolean isResourceNameEquals(Resource currentResource, Resource updateInfoResource) { String resourceNameUpdated = updateInfoResource.getName(); String resourceNameCurrent = currentResource.getName(); - if (!resourceNameCurrent.equals(resourceNameUpdated)) { + if (resourceNameCurrent.equals(resourceNameUpdated)) + return true; + // In case of CVFC type we should support the case of old VF with CVFC instances that were created without the "Cvfc" suffix + return (currentResource.getResourceType().equals(ResourceTypeEnum.CVFC) + && resourceNameUpdated.equals(addCvfcSuffixToResourceName(resourceNameCurrent))); + } + + private String addCvfcSuffixToResourceName(String resourceName) { + return resourceName+"Cvfc"; + } + + private Either validateResourceName(Resource currentResource, Resource updateInfoResource, boolean hasBeenCertified) { + String resourceNameUpdated = updateInfoResource.getName(); + if (!isResourceNameEquals(currentResource, updateInfoResource)) { if (!hasBeenCertified) { Either validateResourceNameResponse = validateComponentName(null, updateInfoResource, null); if (validateResourceNameResponse.isRight()) { @@ -7222,5 +7362,20 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { UiComponentDataTransfer dataTransfer = UiComponentDataConverter.getUiDataTransferFromResourceByParams(resource, dataParamsToReturn); return Either.left(dataTransfer); } + @Override + public Either shouldUpgradeToLatestDerived(Component clonedComponent) { + Resource resource = (Resource) clonedComponent; + if (ModelConverter.isAtomicComponent(resource.getResourceType())) { + Either shouldUpgradeToLatestDerived = toscaOperationFacade.shouldUpgradeToLatestDerived(resource); + if (shouldUpgradeToLatestDerived.isRight()) { + return Either.right(componentsUtils.convertFromStorageResponse(shouldUpgradeToLatestDerived.right().value())); + } + return Either.left(shouldUpgradeToLatestDerived.left().value()); + } else { + return super.shouldUpgradeToLatestDerived(clonedComponent); + } + } + + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/info/ArtifactTemplateInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/info/ArtifactTemplateInfo.java index fa051a9e3d..0f1bf4603d 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/info/ArtifactTemplateInfo.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/info/ArtifactTemplateInfo.java @@ -49,11 +49,11 @@ public class ArtifactTemplateInfo { public static final String ENV = "env"; public static final String IS_BASE = "isBase"; - private static final String CSAR_HEAT = "HEAT"; - private static final String CSAR_ARTIFACT = "artifacts"; - private static final String CSAR_NETWORK = "network"; - private static final String CSAR_VOLUME = "volume"; - private static final String CSAR_NESTED = "nested"; + public static final String CSAR_HEAT = "HEAT"; + public static final String CSAR_ARTIFACT = "artifacts"; + public static final String CSAR_NETWORK = "network"; + public static final String CSAR_VOLUME = "volume"; + public static final String CSAR_NESTED = "nested"; private static final Object DESC = "description"; private static Logger log = LoggerFactory.getLogger(ArtifactTemplateInfo.class.getName()); String type; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabiltyRequirementConvertor.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabiltyRequirementConvertor.java index 649f083903..41268188f9 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabiltyRequirementConvertor.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabiltyRequirementConvertor.java @@ -22,11 +22,16 @@ package org.openecomp.sdc.be.tosca; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; @@ -34,9 +39,14 @@ import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.RequirementDefinition; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.tosca.ToscaUtils.SubstituitionEntry; import org.openecomp.sdc.be.tosca.model.SubstitutionMapping; import org.openecomp.sdc.be.tosca.model.ToscaCapability; import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate; @@ -47,14 +57,29 @@ import org.openecomp.sdc.be.tosca.model.ToscaTemplateCapability; import org.openecomp.sdc.common.util.ValidationUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import fj.data.Either; - +/** + * Allows to convert requirements\capabilities of a component to requirements\capabilities of a substitution mappings section of a tosca template + * + */ +@org.springframework.stereotype.Component("capabilty-requirement-convertor") +@Scope(value = "singleton") public class CapabiltyRequirementConvertor { + + private static final String NO_CAPABILITIES = "No Capabilities for node type"; private static CapabiltyRequirementConvertor instance; - public final static String PATH_DELIMITER = "."; + private static Logger logger = LoggerFactory.getLogger(CapabiltyRequirementConvertor.class.getName()); + public static final String PATH_DELIMITER = "."; + + @Autowired + private ToscaOperationFacade toscaOperationFacade; protected CapabiltyRequirementConvertor() { @@ -66,9 +91,13 @@ public class CapabiltyRequirementConvertor { } return instance; } - - private static Logger log = LoggerFactory.getLogger(CapabiltyRequirementConvertor.class.getName()); - + /** + * Allows to convert capabilities of a component to capabilities of a substitution mappings section of a tosca template + * @param componentInstance + * @param dataTypes + * @param nodeTemplate + * @return + */ public Either convertComponentInstanceCapabilties(ComponentInstance componentInstance, Map dataTypes, ToscaNodeTemplate nodeTemplate) { Map> capabilitiesInst = componentInstance.getCapabilities(); @@ -77,12 +106,10 @@ public class CapabiltyRequirementConvertor { capabilitiesInst.entrySet().forEach(e -> { List capList = e.getValue(); if (capList != null && !capList.isEmpty()) { - capList.forEach(c -> { - convertOverridenProperties(componentInstance, dataTypes, capabilties, c); - }); + capList.forEach(c -> convertOverridenProperties(componentInstance, dataTypes, capabilties, c)); } }); - if (capabilties != null && !capabilties.isEmpty()) { + if (MapUtils.isNotEmpty(capabilties)) { nodeTemplate.setCapabilities(capabilties); } } @@ -92,15 +119,16 @@ public class CapabiltyRequirementConvertor { private void convertOverridenProperties(ComponentInstance componentInstance, Map dataTypes, Map capabilties, CapabilityDefinition c) { List properties = c.getProperties(); if (properties != null && !properties.isEmpty()) { - properties.stream().filter(p -> (p.getValueUniqueUid() != null)).forEach(p -> { - convertOverridenProperty(componentInstance, dataTypes, capabilties, c, p); - }); + properties + .stream() + .filter(p -> p.getValue() != null || p.getDefaultValue() != null) + .forEach(p -> convertOverridenProperty(componentInstance, dataTypes, capabilties, c, p)); } } private void convertOverridenProperty(ComponentInstance componentInstance, Map dataTypes, Map capabilties, CapabilityDefinition c, ComponentInstanceProperty p) { - if (log.isDebugEnabled()) { - log.debug("Exist overriden property {} for capabity {} with value {}", p.getName(), c.getName(), p.getValue()); + if (logger.isDebugEnabled()) { + logger.debug("Exist overriden property {} for capabity {} with value {}", p.getName(), c.getName(), p.getValue()); } ToscaTemplateCapability toscaTemplateCapability = capabilties.get(c.getName()); if (toscaTemplateCapability == null) { @@ -117,109 +145,224 @@ public class CapabiltyRequirementConvertor { } private Object convertInstanceProperty(Map dataTypes, ComponentInstance componentInstance, ComponentInstanceProperty prop) { - log.debug("Convert property {} for instance {}", prop.getName(), componentInstance.getUniqueId()); + logger.debug("Convert property {} for instance {}", prop.getName(), componentInstance.getUniqueId()); String propertyType = prop.getType(); String innerType = null; if (prop.getSchema() != null && prop.getSchema().getProperty() != null) { innerType = prop.getSchema().getProperty().getType(); } - Object convertedValue = PropertyConvertor.getInstance().convertToToscaObject(propertyType, prop.getValue(), innerType, dataTypes); - return convertedValue; + String propValue = prop.getValue() == null ? prop.getDefaultValue() : prop.getValue(); + return PropertyConvertor.getInstance().convertToToscaObject(propertyType, propValue, innerType, dataTypes); } - + /** + * Allows to convert requirements of a node type to tosca template requirements representation + * @param component + * @param nodeType + * @return + */ public Either convertRequirements(Component component, ToscaNodeType nodeType) { List> toscaRequirements = convertRequirementsAsList(component); if (!toscaRequirements.isEmpty()) { nodeType.setRequirements(toscaRequirements); } - log.debug("Finish convert Requirements for node type"); + logger.debug("Finish convert Requirements for node type"); return Either.left(nodeType); } - public Either convertSubstitutionMappingRequirements(Component component, SubstitutionMapping substitutionMapping) { - Map toscaRequirements = convertSubstitutionMappingRequirementsAsMap(component); - if (!toscaRequirements.isEmpty()) { - substitutionMapping.setRequirements(toscaRequirements); + /** + * Allows to convert component requirements to the tosca template substitution mappings requirements + * @param componentsCache + * @param component + * @param substitutionMappings + * @return + */ + public Either convertSubstitutionMappingRequirements(Map componentsCache, Component component, SubstitutionMapping substitutionMappings) { + Either result = Either.left(substitutionMappings); + Either, ToscaError> toscaRequirementsRes = convertSubstitutionMappingRequirementsAsMap(componentsCache, component); + if(toscaRequirementsRes.isRight()){ + result = Either.right(toscaRequirementsRes.right().value()); + logger.error("Failed convert requirements for the component {}. ", component.getName()); + } else if (MapUtils.isNotEmpty(toscaRequirementsRes.left().value())) { + substitutionMappings.setRequirements(toscaRequirementsRes.left().value()); + result = Either.left(substitutionMappings); + logger.debug("Finish convert requirements for the component {}. ", component.getName()); } - log.debug("Finish convert Requirements for node type"); - - return Either.left(substitutionMapping); + return result; } private List> convertRequirementsAsList(Component component) { Map> requirements = component.getRequirements(); List> toscaRequirements = new ArrayList<>(); if (requirements != null) { - boolean isNodeType = ToscaUtils.isAtomicType(component); for (Map.Entry> entry : requirements.entrySet()) { - entry.getValue().stream().filter(r -> (!isNodeType || (isNodeType && component.getUniqueId().equals(r.getOwnerId())) || (isNodeType && r.getOwnerId() == null))).forEach(r -> { - ImmutablePair pair = convertRequirement(component, isNodeType, r); + entry.getValue().stream().filter(r -> filter(component, r.getOwnerId())).forEach(r -> { + ImmutablePair pair = convertRequirement(component, ModelConverter.isAtomicComponent(component), r); Map requirement = new HashMap<>(); requirement.put(pair.left, pair.right); toscaRequirements.add(requirement); }); - - log.debug("Finish convert Requirements for node type"); + logger.debug("Finish convert Requirements for node type"); } } else { - log.debug("No Requirements for node type"); + logger.debug("No Requirements for node type"); } return toscaRequirements; } - private String getSubPathByFirstDelimiterAppearance(String path) { - return path.substring(path.indexOf(PATH_DELIMITER) + 1); + private boolean filter(Component component, String ownerId) { + return !ModelConverter.isAtomicComponent(component) || isNodeTypeOwner(component, ownerId) || (ModelConverter.isAtomicComponent(component) && ownerId == null); + } + + private boolean isNodeTypeOwner(Component component, String ownerId) { + return ModelConverter.isAtomicComponent(component) && component.getUniqueId().equals(ownerId); } private String getSubPathByLastDelimiterAppearance(String path) { return path.substring(path.lastIndexOf(PATH_DELIMITER) + 1); } - - //This function calls on Substitution Mapping region - the component is always non-atomic - private Map convertSubstitutionMappingRequirementsAsMap(Component component) { + + private Either, ToscaError> convertSubstitutionMappingRequirementsAsMap(Map componentsCache, Component component) { Map> requirements = component.getRequirements(); - Map toscaRequirements = new HashMap<>(); + Either, ToscaError> result; if (requirements != null) { - for (Map.Entry> entry : requirements.entrySet()) { - entry.getValue().stream().forEach(r -> { - String fullReqName; - String sourceCapName; - if(ToscaUtils.isComplexVfc(component)){ - fullReqName = r.getName(); - sourceCapName = r.getParentName(); - } else { - fullReqName = getRequirementPath(r); - sourceCapName = getSubPathByFirstDelimiterAppearance(fullReqName); - } - log.debug("the requirement {} belongs to resource {} ", fullReqName, component.getUniqueId()); - if(sourceCapName!= null){ - toscaRequirements.put(fullReqName, new String[]{r.getOwnerName(), sourceCapName}); - } - }); - log.debug("Finish convert Requirements for node type"); - } + result = buildAddSubstitutionMappingsRequirements(componentsCache, component, requirements); } else { - log.debug("No Requirements for node type"); + result = Either.left(Maps.newHashMap()); + logger.debug("No requirements for substitution mappings section of a tosca template of the component {}. ", component.getName()); } - return toscaRequirements; + return result; } - private String getRequirementPath(RequirementDefinition r) { - List pathArray = Lists.reverse(r.getPath().stream() - .map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path))) - .collect(Collectors.toList())); - return new StringBuilder().append(String.join(PATH_DELIMITER, pathArray)).append(PATH_DELIMITER).append(r.getName()).toString(); + private Either, ToscaError> buildAddSubstitutionMappingsRequirements(Map componentsCache, Component component, Map> requirements) { + + Map toscaRequirements = new HashMap<>(); + Either, ToscaError> result = null; + for (Map.Entry> entry : requirements.entrySet()) { + Optional failedToAddRequirement = entry.getValue() + .stream() + .filter(r->!addEntry(componentsCache, toscaRequirements, component, r.getName(), r.getParentName(), r.getPath())) + .findAny(); + if(failedToAddRequirement.isPresent()){ + logger.error("Failed to convert requirement {} for substitution mappings section of a tosca template of the component {}. ", + failedToAddRequirement.get().getName(), component.getName()); + result = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR); + } + logger.debug("Finish convert requirements for the component {}. ", component.getName()); + } + if(result == null){ + result = Either.left(toscaRequirements); + } + return result; + } + + private Either, ToscaError> buildAddSubstitutionMappingsCapabilities(Map componentsCache, Component component, Map> capabilities) { + Map toscaRequirements = new HashMap<>(); + Either, ToscaError> result = null; + for (Map.Entry> entry : capabilities.entrySet()) { + Optional failedToAddRequirement = entry.getValue() + .stream() + .filter(c->!addEntry(componentsCache, toscaRequirements, component, c.getName(), c.getParentName(), c.getPath())) + .findAny(); + if(failedToAddRequirement.isPresent()){ + logger.error("Failed to convert capalility {} for substitution mappings section of a tosca template of the component {}. ", + failedToAddRequirement.get().getName(), component.getName()); + result = Either.right(ToscaError.NODE_TYPE_CAPABILITY_ERROR); + } + logger.debug("Finish convert capalilities for the component {}. ", component.getName()); + } + if(result == null){ + result = Either.left(toscaRequirements); + } + return result; } + private boolean addEntry(Map componentsCache, Map capReqMap, Component component, String name, String parentName, List path){ + + SubstituitionEntry entry = new SubstituitionEntry(name, parentName, ""); + + if(shouldBuildSubstitutionName(component, path) && !buildSubstitutedNamePerInstance(componentsCache, component, name, path, entry)){ + return false; + } + logger.debug("The requirement/capability {} belongs to the component {} ", entry.getFullName(), component.getUniqueId()); + if (entry.getSourceName() != null) { + addEntry(capReqMap, component, path, entry); + } + logger.debug("Finish convert the requirement/capability {} for the component {}. ", entry.getFullName(), component.getName()); + return true; + + } + + private boolean shouldBuildSubstitutionName(Component component, List path) { + return !ToscaUtils.isComplexVfc(component) && CollectionUtils.isNotEmpty(path) && path.iterator().hasNext(); + } + + private boolean buildSubstitutedNamePerInstance(Map componentsCache, Component component, String name, List path, SubstituitionEntry entry) { + Optional ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst(); + if(ci.isPresent()){ + Either buildSubstitutedName = buildSubstitutedName(componentsCache, name, path, ci.get()); + if(buildSubstitutedName.isRight()){ + return false; + } + entry.setFullName(ci.get().getNormalizedName() + '.' + buildSubstitutedName.left().value()); + entry.setSourceName(buildSubstitutedName.left().value()); + } else { + return false; + } + return true; + } + + private void addEntry(Map toscaRequirements, Component component, List capPath, SubstituitionEntry entry) { + Optional findFirst = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(Iterables.getLast(capPath))).findFirst(); + if (findFirst.isPresent()) { + entry.setOwner(findFirst.get().getNormalizedName()); + } + toscaRequirements.put(entry.getFullName(), new String[] { entry.getOwner(), entry.getSourceName() }); + } + + private Either buildSubstitutedName(Map componentsCache, String name, List path, ComponentInstance instance) { + + Either result = null; + Either getOriginRes = getOriginComponent(componentsCache, instance); + if(getOriginRes.isRight()){ + logger.debug("Failed to build substituted name for the capability/requirement {}. Failed to get an origin component with uniqueId {}", name, instance.getComponentUid()); + result = Either.right(false); + } + if(result == null){ + result = buildSubstitutedName(componentsCache, getOriginRes.left().value(), Lists.newArrayList(path.subList(0, path.size()-1)), name); + } + return result; + } + + private String getRequirementPath(Component component, RequirementDefinition r) { + + // Evg : for the last in path take real instance name and not "decrypt" unique id. ( instance name can be change and not equal to id..) + // dirty quick fix. must be changed as capability redesign + List capPath = r.getPath(); + String lastInPath = capPath.get(capPath.size() - 1); + Optional findFirst = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(lastInPath)).findFirst(); + if (findFirst.isPresent()) { + String lastInPathName = findFirst.get().getNormalizedName(); + + if (capPath.size() > 1) { + List pathArray = Lists.reverse(capPath.stream().map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path))).collect(Collectors.toList())); + + return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(String.join(PATH_DELIMITER, pathArray.subList(1, pathArray.size() ))).append(PATH_DELIMITER).append(r.getName()).toString(); + }else{ + return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(r.getName()).toString(); + } + } + return ""; + } + private ImmutablePair convertRequirement(Component component, boolean isNodeType, RequirementDefinition r) { String name = r.getName(); if (!isNodeType) { - name = getRequirementPath(r); + name = getRequirementPath(component, r); } - log.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId()); + logger.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId()); ToscaRequirement toscaRequirement = new ToscaRequirement(); List occurences = new ArrayList<>(); @@ -230,78 +373,101 @@ public class CapabiltyRequirementConvertor { occurences.add(Integer.valueOf(r.getMaxOccurrences())); } toscaRequirement.setOccurrences(occurences); - // toscaRequirement.setOccurrences(createOcurrencesRange(requirementDefinition.getMinOccurrences(), - // requirementDefinition.getMaxOccurrences())); toscaRequirement.setNode(r.getNode()); toscaRequirement.setCapability(r.getCapability()); toscaRequirement.setRelationship(r.getRelationship()); - ImmutablePair pair = new ImmutablePair(name, toscaRequirement); - return pair; + return new ImmutablePair<>(name, toscaRequirement); } + /** + * Allows to convert capabilities of a node type to tosca template capabilities + * @param component + * @param dataTypes + * @return + */ public Map convertCapabilities(Component component, Map dataTypes) { Map> capabilities = component.getCapabilities(); Map toscaCapabilities = new HashMap<>(); if (capabilities != null) { - boolean isNodeType = ToscaUtils.isAtomicType(component); + boolean isNodeType = ModelConverter.isAtomicComponent(component); for (Map.Entry> entry : capabilities.entrySet()) { - entry.getValue().stream().filter(c -> (!isNodeType || (isNodeType && component.getUniqueId().equals(c.getOwnerId())) || (isNodeType && c.getOwnerId() == null) )).forEach(c -> { - convertCapabilty(component, toscaCapabilities, isNodeType, c, dataTypes); - - }); + entry.getValue().stream().filter(c -> filter(component, c.getOwnerId())).forEach(c -> convertCapabilty(component, toscaCapabilities, isNodeType, c, dataTypes)); } } else { - log.debug("No Capabilities for node type"); + logger.debug(NO_CAPABILITIES); } return toscaCapabilities; } - - //This function calls on Substitution Mapping region - the component is always non-atomic - public Map convertSubstitutionMappingCapabilities(Component component, Map dataTypes) { - Map> capabilities = component.getCapabilities(); - Map toscaCapabilities = new HashMap<>(); + + /** + * Allows to convert capabilities of a server proxy node type to tosca template capabilities + * @param component + * @param proxyComponent + * @param instanceProxy + * @param dataTypes + * @return + */ + public Map convertProxyCapabilities(Component component, Component proxyComponent, ComponentInstance instanceProxy, Map dataTypes) { + Map> capabilities = instanceProxy.getCapabilities(); + Map toscaCapabilities = new HashMap<>(); if (capabilities != null) { + boolean isNodeType = ModelConverter.isAtomicComponent(component); for (Map.Entry> entry : capabilities.entrySet()) { - entry.getValue().stream().forEach(c -> { - String fullCapName; - String sourceReqName; - if(ToscaUtils.isComplexVfc(component)){ - fullCapName = c.getName(); - sourceReqName = c.getParentName(); - } else { - fullCapName = getCapabilityPath(c); - sourceReqName = getSubPathByFirstDelimiterAppearance(fullCapName); - } - log.debug("the capabilty {} belongs to resource {} ", fullCapName, component.getUniqueId()); - if(sourceReqName!= null){ - toscaCapabilities.put(fullCapName, new String[]{c.getOwnerName(), sourceReqName}); - } - }); + entry.getValue().stream().forEach(c -> convertCapabilty(proxyComponent, toscaCapabilities, isNodeType, c, dataTypes)); } } else { - log.debug("No Capabilities for node type"); + logger.debug(NO_CAPABILITIES); } return toscaCapabilities; } - - private String getCapabilityPath(CapabilityDefinition c) { - List pathArray = Lists.reverse(c.getPath().stream() - .map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path))) - .collect(Collectors.toList())); - return new StringBuilder().append(String.join(PATH_DELIMITER, pathArray)).append(PATH_DELIMITER).append(c.getName()).toString(); + + /** + * Allows to convert component capabilities to the tosca template substitution mappings capabilities + * @param componentsCache + * @param component + * @return + */ + public Either, ToscaError> convertSubstitutionMappingCapabilities(Map componentsCache, Component component) { + Map> capabilities = component.getCapabilities(); + Either, ToscaError> res = null; + if (capabilities != null) { + res = buildAddSubstitutionMappingsCapabilities(componentsCache, component, capabilities); + } else { + logger.debug(NO_CAPABILITIES); + res = Either.left(new HashMap<>()); + } + return res; } - - + private String getCapabilityPath(CapabilityDefinition c, Component component) { + // Evg : for the last in path take real instance name and not "decrypt" unique id. ( instance name can be change and not equal to id..) + // dirty quick fix. must be changed as capability redesign + List capPath = c.getPath(); + String lastInPath = capPath.get(capPath.size() - 1); + Optional findFirst = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(lastInPath)).findFirst(); + if (findFirst.isPresent()) { + String lastInPathName = findFirst.get().getNormalizedName(); + + if (capPath.size() > 1) { + List pathArray = Lists.reverse(capPath.stream().map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path))).collect(Collectors.toList())); + + return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(String.join(PATH_DELIMITER, pathArray.subList(1, pathArray.size() ))).append(PATH_DELIMITER).append(c.getName()).toString(); + }else{ + return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(c.getName()).toString(); + } + } + return ""; + } + private void convertCapabilty(Component component, Map toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map dataTypes) { String name = c.getName(); if (!isNodeType) { - name = getCapabilityPath(c); + name = getCapabilityPath(c, component); } - log.debug("the capabilty {} belongs to resource {} ", name, component.getUniqueId()); + logger.debug("the capabilty {} belongs to resource {} ", name, component.getUniqueId()); ToscaCapability toscaCapability = new ToscaCapability(); toscaCapability.setDescription(c.getDescription()); toscaCapability.setType(c.getType()); @@ -327,5 +493,61 @@ public class CapabiltyRequirementConvertor { } toscaCapabilities.put(name, toscaCapability); } + + Either buildSubstitutedName(Map originComponents, Component originComponent, List path, String name) { + StringBuilder substitutedName = new StringBuilder(); + boolean nameBuiltSuccessfully = true; + Either result; + if(CollectionUtils.isNotEmpty(path) && !ToscaUtils.isComplexVfc(originComponent)){ + Collections.reverse(path); + Iterator instanceIdIter = path.iterator(); + nameBuiltSuccessfully = appendNameRecursively(originComponents, originComponent, instanceIdIter, substitutedName); + } + if(nameBuiltSuccessfully){ + result = Either.left(substitutedName.append(name).toString()); + } else { + result = Either.right(nameBuiltSuccessfully); + } + return result; + } + + private boolean appendNameRecursively(Map originComponents, Component originComponent, Iterator instanceIdIter, StringBuilder substitutedName) { + if(CollectionUtils.isNotEmpty(originComponent.getComponentInstances()) && instanceIdIter.hasNext()){ + String instanceId = instanceIdIter.next(); + Optional instanceOpt = originComponent.getComponentInstances().stream().filter(i -> i.getUniqueId().equals(instanceId)).findFirst(); + if(!instanceOpt.isPresent()){ + logger.debug("Failed to find an instance with uniqueId {} on a component with uniqueId {}", instanceId, originComponent.getUniqueId()); + return false; + } + Either getOriginRes = getOriginComponent(originComponents, instanceOpt.get()); + if(getOriginRes.isRight()){ + return false; + } + appendNameRecursively(originComponents, getOriginRes.left().value(), instanceIdIter, substitutedName); + substitutedName.append(instanceOpt.get().getNormalizedName()).append('.'); + return true; + } + return true; + } + + private Either getOriginComponent(Map originComponents, ComponentInstance instance) { + Either result; + Either getOriginRes; + if(originComponents.containsKey(instance.getComponentUid())){ + result = Either.left(originComponents.get(instance.getComponentUid())); + } else { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreComponentInstances(false); + getOriginRes = toscaOperationFacade.getToscaElement(instance.getComponentUid(), filter); + if(getOriginRes.isRight()){ + logger.debug("Failed to get an origin component with uniqueId {}", instance.getComponentUid()); + result = Either.right(false); + } else { + result = Either.left(getOriginRes.left().value()); + originComponents.put(getOriginRes.left().value().getUniqueId(), getOriginRes.left().value()); + } + } + return result; + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java index a0cc347e09..2f4a385f69 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java @@ -52,6 +52,7 @@ import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaElementLifecycleOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; import org.openecomp.sdc.be.resources.data.ESArtifactData; @@ -146,7 +147,8 @@ public class CsarUtils { ImportUtils.Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + "([\\d\\w\\_\\-\\.\\s]+)" + DEL_PATTERN + "([\\d\\w\\_\\-\\.\\s]+)" + DEL_PATTERN + - "([\\d\\w\\_\\-\\.\\s]+)" + DEL_PATTERN; + "([\\d\\w\\_\\-\\.\\s]+)" + DEL_PATTERN + + "([\\d\\w\\_\\-\\.\\s]+)"; public static final String VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN = ARTIFACTS + DEL_PATTERN+ // Artifact Group (i.e Deployment/Informational) @@ -274,7 +276,7 @@ public class CsarUtils { zip.putNextEntry(new ZipEntry(DEFINITIONS_PATH + fileName)); zip.write(mainYaml); //US798487 - Abstraction of complex types - if (!ToscaUtils.isAtomicType(component)){ + if (!ModelConverter.isAtomicComponent(component)){ log.debug("Component {} is complex - generating abstract type for it..", component.getName()); writeComponentInterface(component, zip, fileName); } @@ -331,7 +333,7 @@ public class CsarUtils { zip.write(content); // add component interface to zip - if (!ToscaUtils.isAtomicType(innerComponent)) { + if (!ModelConverter.isAtomicComponent(innerComponent)) { writeComponentInterface(innerComponent, zip, icFileName); } } @@ -452,7 +454,7 @@ public class CsarUtils { } //if not atomic - insert inner components as well - if(!ToscaUtils.isAtomicType(componentRI)) { + if(!ModelConverter.isAtomicComponent(componentRI)) { addInnerComponentsToCache(componentCache, componentRI); } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java index 8e0c312f1a..1f29eb2113 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.function.Supplier; @@ -42,10 +43,29 @@ import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; -import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; +import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceInput; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.GroupDefinition; +import org.openecomp.sdc.be.model.GroupInstance; +import org.openecomp.sdc.be.model.GroupProperty; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.RequirementAndRelationshipPair; +import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; +import org.openecomp.sdc.be.model.RequirementDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.category.CategoryDefinition; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.tosca.converters.ToscaValueBaseConverter; import org.openecomp.sdc.be.tosca.model.IToscaMetadata; @@ -87,10 +107,10 @@ public class ToscaExportHandler { @Autowired private ToscaOperationFacade toscaOperationFacade; - - private CapabiltyRequirementConvertor capabiltyRequirementConvertor = CapabiltyRequirementConvertor.getInstance(); + @Autowired + private CapabiltyRequirementConvertor capabiltyRequirementConvertor; private PropertyConvertor propertyConvertor = PropertyConvertor.getInstance(); - + Map originComponents = new HashMap<>(); private static Logger log = LoggerFactory.getLogger(ToscaExportHandler.class.getName()); @@ -105,9 +125,9 @@ public class ToscaExportHandler { public static final String VOLUME_GROUP_KEY = "volume_group"; public static final String VF_MODULE_TYPE_BASE = "Base"; public static final String VF_MODULE_TYPE_EXPANSION = "Expansion"; - public static final List>> DEFAULT_IMPORTS = ConfigurationManager.getConfigurationManager().getConfiguration().getDefaultImports(); - - + private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration"; + private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}"; + protected static final List>> DEFAULT_IMPORTS = ConfigurationManager.getConfigurationManager().getConfiguration().getDefaultImports(); public Either exportComponent(Component component) { @@ -122,15 +142,16 @@ public class ToscaExportHandler { } public Either exportComponentInterface(Component component) { - if(null == DEFAULT_IMPORTS) { - log.debug("convertToToscaTemplate - failed to get Default Imports section from configuration"); + if (null == DEFAULT_IMPORTS) { + log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION); return Either.right(ToscaError.GENERAL_ERROR); } ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION); toscaTemplate.setImports(new ArrayList<>(DEFAULT_IMPORTS)); Map nodeTypes = new HashMap<>(); - Either toscaTemplateRes = convertInterfaceNodeType(component, toscaTemplate, nodeTypes); + Either toscaTemplateRes = convertInterfaceNodeType(component, toscaTemplate, + nodeTypes); if (toscaTemplateRes.isRight()) { return Either.right(toscaTemplateRes.right().value()); } @@ -179,8 +200,8 @@ public class ToscaExportHandler { } private Either convertToToscaTemplate(Component component) { - if(null == DEFAULT_IMPORTS) { - log.debug("convertToToscaTemplate - failed to get Default Imports section from configuration"); + if (null == DEFAULT_IMPORTS) { + log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION); return Either.right(ToscaError.GENERAL_ERROR); } @@ -190,7 +211,7 @@ public class ToscaExportHandler { toscaTemplate.setMetadata(convertMetadata(component)); toscaTemplate.setImports(new ArrayList<>(DEFAULT_IMPORTS)); Map nodeTypes = new HashMap<>(); - if (ToscaUtils.isAtomicType(component)) { + if (ModelConverter.isAtomicComponent(component)) { log.trace("convert component as node type"); return convertNodeType(component, toscaTemplate, nodeTypes); } else { @@ -208,6 +229,15 @@ public class ToscaExportHandler { return Either.right(importsRes.right().value()); } toscaNode = importsRes.left().value().left; + /*Either, ToscaError> nodeTypesMapEither = createProxyNodeTypes(component); + if (nodeTypesMapEither.isRight()) { + log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", + nodeTypesMapEither.right().value()); + return Either.right(nodeTypesMapEither.right().value()); + } + Map nodeTypesMap = nodeTypesMapEither.left().value(); + if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) + toscaNode.setNode_types(nodeTypesMap);*/ Map componentCache = importsRes.left().value().right; Either, TitanOperationStatus> dataTypesEither = dataTypeCache.getAll(); @@ -240,9 +270,9 @@ public class ToscaExportHandler { topologyTemplate.setNode_templates(nodeTemplates.left().value()); } - Map groupsMap = null; + Map groupsMap; if (groups != null && !groups.isEmpty()) { - groupsMap = new HashMap(); + groupsMap = new HashMap<>(); for (GroupDefinition group : groups) { ToscaGroupTemplate toscaGroup = convertGroup(group); groupsMap.put(group.getName(), toscaGroup); @@ -252,7 +282,7 @@ public class ToscaExportHandler { topologyTemplate.addGroups(groupsMap); } SubstitutionMapping substitutionMapping = new SubstitutionMapping(); - String toscaResourceName = null; + String toscaResourceName; switch (component.getComponentType()) { case RESOURCE: toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition() @@ -263,19 +293,19 @@ public class ToscaExportHandler { + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName(); break; default: - log.debug("Not supported component type {}", component.getComponentType()); + log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType()); return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE); } substitutionMapping.setNode_type(toscaResourceName); - Either capabilities = convertCapabilities(component, substitutionMapping, - dataTypes); + Either capabilities = convertCapabilities(component, substitutionMapping); if (capabilities.isRight()) { return Either.right(capabilities.right().value()); } substitutionMapping = capabilities.left().value(); - Either requirements = capabiltyRequirementConvertor.convertSubstitutionMappingRequirements(component, substitutionMapping); + Either requirements = capabiltyRequirementConvertor + .convertSubstitutionMappingRequirements(originComponents, component, substitutionMapping); if (requirements.isRight()) { return Either.right(requirements.right().value()); } @@ -356,19 +386,19 @@ public class ToscaExportHandler { private Either>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) { - if(null == DEFAULT_IMPORTS) { - log.debug("convertToToscaTemplate - failed to get Default Imports section from configuration"); + if (null == DEFAULT_IMPORTS) { + log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION); return Either.right(ToscaError.GENERAL_ERROR); } Map componentCache = new HashMap<>(); - if (!ToscaUtils.isAtomicType(component)) { + if (!ModelConverter.isAtomicComponent(component)) { List componentInstances = component.getComponentInstances(); if (componentInstances != null && !componentInstances.isEmpty()) { - List>> additionalImports = - toscaTemplate.getImports() == null ? new ArrayList<>(DEFAULT_IMPORTS) : new ArrayList<>(toscaTemplate.getImports()); + List>> additionalImports = toscaTemplate.getImports() == null + ? new ArrayList<>(DEFAULT_IMPORTS) : new ArrayList<>(toscaTemplate.getImports()); List> dependecies = new ArrayList<>(); @@ -386,9 +416,8 @@ public class ToscaExportHandler { importsListMember.put(keyNameBuilder.toString(), interfaceFiles); additionalImports.add(importsListMember); - componentInstances.forEach(ci -> { - createDependency(componentCache, additionalImports, dependecies, ci); - }); + componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependecies, ci)); + originComponents.putAll(componentCache); toscaTemplate.setDependencies(dependecies); toscaTemplate.setImports(additionalImports); } @@ -407,7 +436,8 @@ public class ToscaExportHandler { Component componentRI = componentCache.get(ci.getComponentUid()); if (componentRI == null) { // all resource must be only once! - Either resource = toscaOperationFacade.getToscaFullElement(ci.getComponentUid()); + Either resource = toscaOperationFacade + .getToscaFullElement(ci.getComponentUid()); if (resource.isRight()) { log.debug("Failed to fetch resource with id {} for instance {}"); } @@ -429,7 +459,7 @@ public class ToscaExportHandler { dependecies.add(new ImmutableTriple(artifactName, artifactDefinition.getEsId(), fetchedComponent)); - if(!ToscaUtils.isAtomicType(componentRI)) { + if (!ModelConverter.isAtomicComponent(componentRI)) { importsListMember = new HashMap<>(); Map interfaceFiles = new HashMap<>(); interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName)); @@ -442,8 +472,7 @@ public class ToscaExportHandler { } public static String getInterfaceFilename(String artifactName) { - String interfaceFileName = artifactName.substring(0, artifactName.lastIndexOf('.')) + ToscaExportHandler.TOSCA_INTERFACE_NAME; - return interfaceFileName; + return artifactName.substring(0, artifactName.lastIndexOf('.')) + ToscaExportHandler.TOSCA_INTERFACE_NAME; } private Either convertNodeType(Component component, ToscaTemplate toscaNode, @@ -466,7 +495,7 @@ public class ToscaExportHandler { toscaNodeType = properties.left().value(); log.debug("Properties converted for {}", component.getUniqueId()); - //Extracted to method for code reuse + // Extracted to method for code reuse return convertReqCapAndTypeName(component, toscaNode, nodeTypes, toscaNodeType, dataTypes); } @@ -496,7 +525,7 @@ public class ToscaExportHandler { } } - //Extracted to method for code reuse + // Extracted to method for code reuse return convertReqCapAndTypeName(component, toscaNode, nodeTypes, toscaNodeType, dataTypes); } @@ -510,15 +539,13 @@ public class ToscaExportHandler { toscaNodeType = capabilities.left().value(); log.debug("Capabilities converted for {}", component.getUniqueId()); - Either requirements = capabiltyRequirementConvertor.convertRequirements(component, - toscaNodeType); + Either requirements = capabiltyRequirementConvertor.convertRequirements(component, toscaNodeType); if (requirements.isRight()) { return Either.right(requirements.right().value()); } toscaNodeType = requirements.left().value(); log.debug("Requirements converted for {}", component.getUniqueId()); - String toscaResourceName; switch (component.getComponentType()) { case RESOURCE: @@ -530,7 +557,7 @@ public class ToscaExportHandler { + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName(); break; default: - log.debug("Not supported component type {}", component.getComponentType()); + log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType()); return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE); } @@ -558,7 +585,8 @@ public class ToscaExportHandler { nodeTemplate.setType(componentInstance.getToscaComponentName()); Either requirements = convertComponentInstanceRequirements(component, - componentInstance, component.getComponentInstancesRelations(), nodeTemplate, componentCache.get(componentInstance.getComponentUid())); + componentInstance, component.getComponentInstancesRelations(), nodeTemplate, + componentCache.get(componentInstance.getComponentUid())); if (requirements.isRight()) { convertNodeTemplatesRes = Either.right(requirements.right().value()); break; @@ -634,8 +662,9 @@ public class ToscaExportHandler { List instanceInputsList = componentInstancesInputs.get(instanceUniqueId); if (instanceInputsList != null) { instanceInputsList.forEach(input -> { - - Supplier supplier = () -> input.getValue() != null && !input.getValue().isEmpty()? input.getValue(): input.getDefaultValue(); + + Supplier supplier = () -> input.getValue() != null && !input.getValue().isEmpty() + ? input.getValue() : input.getDefaultValue(); convertAndAddValue(dataTypes, componentInstance, props, input, supplier); }); } @@ -724,7 +753,8 @@ public class ToscaExportHandler { Supplier supplGroupType = () -> groupInstance.getType(); Supplier supplDescription = () -> groupInstance.getDescription(); - Supplier> supplProperties = () -> groupInstance.convertToGroupInstancesProperties(); + Supplier> supplProperties = () -> groupInstance + .convertToGroupInstancesProperties(); Supplier supplgroupName = () -> groupInstance.getGroupName(); Supplier supplInvariantUUID = () -> groupInstance.getInvariantUUID(); Supplier supplGroupUUID = () -> groupInstance.getGroupUUID(); @@ -751,7 +781,8 @@ public class ToscaExportHandler { toscaMetadata = new VfModuleToscaMetadata(); Map properties = fillGroupProperties(props.get()); - if(!properties.containsKey(VF_MODULE_DESC_KEY) || StringUtils.isEmpty((String) properties.get(VF_MODULE_DESC_KEY))){ + if (!properties.containsKey(VF_MODULE_DESC_KEY) + || StringUtils.isEmpty((String) properties.get(VF_MODULE_DESC_KEY))) { properties.put(VF_MODULE_DESC_KEY, description.get()); } toscaGroup.setProperties(properties); @@ -765,7 +796,7 @@ public class ToscaExportHandler { private Map fillGroupProperties(List groupProps) { Map properties = new HashMap<>(); - if(groupProps != null){ + if (groupProps != null) { for (GroupProperty gp : groupProps) { if (gp.getName().equals(Constants.IS_BASE)) { Boolean isBase = Boolean.parseBoolean(gp.getValue()); @@ -800,72 +831,233 @@ public class ToscaExportHandler { private ToscaNodeType createNodeType(Component component) { ToscaNodeType toscaNodeType = new ToscaNodeType(); - if (ToscaUtils.isAtomicType(component)){ - if (((Resource) component).getDerivedFrom() != null){ + if (ModelConverter.isAtomicComponent(component)) { + if (((Resource) component).getDerivedFrom() != null) { toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0)); } - toscaNodeType.setDescription(component.getDescription()); // or name?? + toscaNodeType.setDescription(component.getDescription()); // or + // name?? } else { - String derivedFrom = null != component.getDerivedFromGenericType()? component.getDerivedFromGenericType() : "tosca.nodes.Root"; + String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType() + : "tosca.nodes.Root"; toscaNodeType.setDerived_from(derivedFrom); } return toscaNodeType; } - //TODO save the capability(type or name) info on relation data - private Either convertComponentInstanceRequirements(Component component, - ComponentInstance componentInstance, List relations, - ToscaNodeTemplate nodeTypeTemplate, Component originComponent) { + /*private Either, ToscaError> createProxyNodeTypes(Component container) { - List instancesList = component.getComponentInstances(); - List> toscaRequirements = new ArrayList<>(); - Map> reqMap = originComponent.getRequirements(); + Map nodeTypesMap = null; + Either, ToscaError> res = Either.left(nodeTypesMap); - relations.stream().filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).forEach(rel -> { - ComponentInstance toComponentInstance = instancesList.stream() - .filter(i -> rel.getToNode().equals(i.getUniqueId())).findFirst().orElse(null); - if (toComponentInstance == null) { - log.debug("Failed to find relation between node {} to node {}", componentInstance.getName(), - rel.getToNode()); - return; - } - RequirementAndRelationshipPair reqAndRelationshipPair = rel.getRelationships().get(0); - ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement(); - toscaRequirement.setNode(toComponentInstance.getName()); - Optional findAny = reqMap.values().stream().flatMap(e -> e.stream()) - .filter(e -> e.getName().equals(reqAndRelationshipPair.getRequirement())).findAny(); - if (findAny.isPresent()) { - RequirementDefinition reqDefinition = findAny.get(); - toscaRequirement.setCapability(reqDefinition.getCapability()); - toscaRequirement.setRelationship(reqDefinition.getRelationship()); - } else { - // reqMap represents calculated requirements! if not found there, export data directly from the relation definition - log.debug("Failed to find requirement {} definition for node {}", reqAndRelationshipPair.getRequirement(), componentInstance.getName()); - return; + List componetInstances = container.getComponentInstances(); + + if (componetInstances == null || componetInstances.isEmpty()) + return res; + Map serviceProxyInstanceList = new HashMap<>(); + List proxyInst = componetInstances.stream().filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name())).collect(Collectors.toList()); + if(proxyInst != null && !proxyInst.isEmpty()){ + for(ComponentInstance inst: proxyInst){ + serviceProxyInstanceList.put(inst.getToscaComponentName(), inst); } - Map toscaReqMap = new HashMap<>(); - toscaReqMap.put(reqAndRelationshipPair.getRequirement(), toscaRequirement); - toscaRequirements.add(toscaReqMap); + } + + if (serviceProxyInstanceList.isEmpty()) + return res; + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreCapabilities(false); + filter.setIgnoreComponentInstances(false); + Either serviceProxyOrigin = toscaOperationFacade + .getLatestByName("serviceProxy"); + if (serviceProxyOrigin.isRight()) { + log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", + serviceProxyOrigin.right().value()); + return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE); + } + Component origComponent = serviceProxyOrigin.left().value(); + + nodeTypesMap = new HashMap<>(); + for (Entry entryProxy : serviceProxyInstanceList.entrySet()) { + Component serviceComponent = null; + ComponentParametersView componentParametersView = new ComponentParametersView(); + componentParametersView.disableAll(); + componentParametersView.setIgnoreCategories(false); + Either service = toscaOperationFacade + .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView); + if (service.isRight()) { + log.debug("Failed to fetch resource with id {} for instance {}"); + } else + serviceComponent = service.left().value(); + + ToscaNodeType toscaNodeType = createProxyNodeType(origComponent, serviceComponent, entryProxy.getValue()); + nodeTypesMap.put(entryProxy.getKey(), toscaNodeType); + } + + return Either.left(nodeTypesMap); + }*/ + + private ToscaNodeType createProxyNodeType(Component origComponent, Component proxyComponent, + ComponentInstance instance) { + ToscaNodeType toscaNodeType = new ToscaNodeType(); + String derivedFrom = ((Resource) origComponent).getToscaResourceName(); + + toscaNodeType.setDerived_from(derivedFrom); + Either, TitanOperationStatus> dataTypesEither = dataTypeCache.getAll(); + if (dataTypesEither.isRight()) { + log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value()); + } + Map dataTypes = dataTypesEither.left().value(); + Map capabilities = this.capabiltyRequirementConvertor + .convertProxyCapabilities(origComponent, proxyComponent, instance, dataTypes); + + toscaNodeType.setCapabilities(capabilities); - }); + return toscaNodeType; + } + private Either convertComponentInstanceRequirements(Component component, + ComponentInstance componentInstance, List relations, + ToscaNodeTemplate nodeTypeTemplate, Component originComponent) { + + List> toscaRequirements = new ArrayList<>(); + if(!addRequirements(component, componentInstance, relations, originComponent, toscaRequirements)){ + log.debug("Failed to convert component instance requirements for the component instance {}. ", componentInstance.getName()); + return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR); + } if (!toscaRequirements.isEmpty()) { nodeTypeTemplate.setRequirements(toscaRequirements); } - log.debug("Finish convert Requirements for node type"); + log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName()); return Either.left(nodeTypeTemplate); } + private boolean addRequirements(Component component, ComponentInstance componentInstance, List relations, Component originComponent, + List> toscaRequirements) { + boolean result; + List filteredRelations = relations.stream().filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList()); + if(CollectionUtils.isEmpty(filteredRelations)){ + result = true; + } else { + result = !filteredRelations.stream().filter(rel -> !addRequirement(component,componentInstance, originComponent, component.getComponentInstances(), rel, toscaRequirements)).findFirst().isPresent(); + } + return result; + } + + private boolean addRequirement(Component component,ComponentInstance fromInstance, Component originComponent, List instancesList, RequirementCapabilityRelDef rel, List> toscaRequirements){ + + boolean result = true; + Map originComponents = new HashMap<>(); + Map> reqMap = originComponent.getRequirements(); + RequirementAndRelationshipPair reqAndRelationshipPair = rel.getRelationships().get(0); + Either getOriginRes = null; + Optional reqOpt = null; + Component toOriginComponent = null; + Optional cap = null; + Either buildCapNameRes = null; + Either buildReqNameRes = null; + + ComponentInstance toInstance = instancesList.stream().filter(i -> rel.getToNode().equals(i.getUniqueId())).findFirst().orElse(null); + if (toInstance == null) { + log.debug("Failed to find a relation from the node {} to the node {}", fromInstance.getName(), rel.getToNode()); + result = false; + } + if(result){ - private Either convertCapabilities(Component component, SubstitutionMapping substitutionMapping, Map dataTypes) { - Map toscaCapabilities = capabiltyRequirementConvertor.convertSubstitutionMappingCapabilities(component, dataTypes); + if(component.getComponentType().equals(ComponentTypeEnum.SERVICE)) { + reqOpt = findRequirement(reqMap, reqAndRelationshipPair); + } + else { + reqOpt = findRequirement(reqMap, reqAndRelationshipPair.getRequirementUid()); + } + if(!reqOpt.isPresent()){ + log.debug("Failed to find a requirement with uniqueId {} on a component with uniqueId {}", reqAndRelationshipPair.getRequirementUid(), originComponent.getUniqueId()); + result = false; + } + } + if(result){ + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreComponentInstances(false); + filter.setIgnoreCapabilities(false); + getOriginRes = toscaOperationFacade.getToscaElement(toInstance.getComponentUid(), filter); + if(getOriginRes.isRight()){ + log.debug("Failed to build substituted name for the requirement {}. Failed to get an origin component with uniqueId {}", reqOpt.get().getName(), toInstance.getComponentUid()); + result = false; + } + } + if(result){ + toOriginComponent = getOriginRes.left().value(); + cap = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream().filter(c -> c.getName().equals(reqAndRelationshipPair.getCapability())).findFirst(); + if(!cap.isPresent()){ + log.debug("Failed to find a capability with name {} on a component with uniqueId {}", reqAndRelationshipPair.getCapability(), originComponent.getUniqueId()); + result = false; + } + } + if(result){ + buildCapNameRes = capabiltyRequirementConvertor.buildSubstitutedName(originComponents, toOriginComponent, cap.get().getPath(), reqAndRelationshipPair.getCapability()); + if(buildCapNameRes.isRight()){ + log.debug("Failed to build a substituted capability name for the capability with name {} on a component with uniqueId {}", reqAndRelationshipPair.getCapability(), originComponent.getUniqueId()); + result = false; + } + } + if(result){ + buildReqNameRes = capabiltyRequirementConvertor.buildSubstitutedName(originComponents, originComponent, reqOpt.get().getPath(), reqAndRelationshipPair.getRequirement()); + if(buildReqNameRes.isRight()){ + log.debug("Failed to build a substituted requirement name for the requirement with name {} on a component with uniqueId {}", reqAndRelationshipPair.getRequirement(), originComponent.getUniqueId()); + result = false; + } + } + if(result){ + ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement(); + Map toscaReqMap = new HashMap<>(); + toscaRequirement.setNode(toInstance.getName()); + toscaRequirement.setCapability(buildCapNameRes.left().value()); + toscaReqMap.put(buildReqNameRes.left().value(), toscaRequirement); + toscaRequirements.add(toscaReqMap); + } + return result; + } - if (!toscaCapabilities.isEmpty()) { - substitutionMapping.setCapabilities(toscaCapabilities); + private Optional findRequirement(Map> reqMap, String reqId) { + for(List reqList: reqMap.values()){ + Optional reqOpt = reqList.stream().filter(r -> r.getUniqueId().equals(reqId)).findFirst(); + if(reqOpt.isPresent()){ + return reqOpt; + } } - log.debug("Finish convert Capabilities for node type"); + return Optional.empty(); + } + + private Optional findRequirement(Map> reqMap, RequirementAndRelationshipPair reqAndRelationshipPair) { + for(List reqList: reqMap.values()){ + Optional reqOpt = reqList.stream().filter(r -> + isRequirmentBelongTo(reqAndRelationshipPair, r)) + .findFirst(); + if(reqOpt.isPresent()){ + return reqOpt; + } + } + return Optional.empty(); + } + + private boolean isRequirmentBelongTo(RequirementAndRelationshipPair reqAndRelationshipPair, RequirementDefinition r) { + return StringUtils.isNotEmpty(r.getOwnerId()) && r.getOwnerId().equals(reqAndRelationshipPair.getRequirementOwnerId()) + && StringUtils.isNotEmpty(r.getName()) && r.getName().equals(reqAndRelationshipPair.getRequirement()); + } - return Either.left(substitutionMapping); + private Either convertCapabilities(Component component, SubstitutionMapping substitutionMappings) { + + Either result = Either.left(substitutionMappings);; + Either, ToscaError> toscaCapabilitiesRes = capabiltyRequirementConvertor + .convertSubstitutionMappingCapabilities(originComponents, component); + if(toscaCapabilitiesRes.isRight()){ + result = Either.right(toscaCapabilitiesRes.right().value()); + log.error("Failed convert capabilities for the component {}. ", component.getName()); + } else if (MapUtils.isNotEmpty(toscaCapabilitiesRes.left().value())) { + substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value()); + log.debug("Finish convert capabilities for the component {}. ", component.getName()); + } + log.debug("Finished to convert capabilities for the component {}. ", component.getName()); + return result; } private Either convertCapabilities(Component component, ToscaNodeType nodeType, @@ -896,12 +1088,12 @@ public class ToscaExportHandler { return null; } else { // skip not relevant for Tosca property - if (property.getName().equals("dependencies")) { + if ("dependencies".equals(property.getName())) { return null; } NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag); - return property.getName().equals("_defaultp_") + return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode; } } @@ -928,7 +1120,7 @@ public class ToscaExportHandler { protected Set createPropertySet(Class type, BeanAccess bAccess) throws IntrospectionException { Collection fields = getPropertiesMap(type, BeanAccess.FIELD).values(); - return new LinkedHashSet(fields); + return new LinkedHashSet<>(fields); } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaUtils.java index 24586d9ea0..0c54e7229e 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaUtils.java @@ -34,17 +34,6 @@ import org.openecomp.sdc.be.model.Component; public class ToscaUtils { - public static boolean isAtomicType(Component component) { - ComponentTypeEnum componentType = component.getComponentType(); - if (ComponentTypeEnum.RESOURCE.equals(componentType)) { - ResourceTypeEnum resourceType = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition()).getResourceType(); - if (ResourceTypeEnum.CP == resourceType || ResourceTypeEnum.VL == resourceType || ResourceTypeEnum.VFC == resourceType || ResourceTypeEnum.VFCMT == resourceType || ResourceTypeEnum.ABSTRACT == resourceType) { - return true; - } - } - return false; - } - public static boolean isComplexVfc(Component component) { if (ComponentTypeEnum.RESOURCE == component.getComponentType()) { ResourceTypeEnum resourceType = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition()).getResourceType(); @@ -55,7 +44,7 @@ public class ToscaUtils { return false; } - public static Map objectToMap(Object objectToConvert, Class clazz) throws IllegalArgumentException, IllegalAccessException { + public static Map objectToMap(Object objectToConvert, Class clazz) throws IllegalArgumentException, IllegalAccessException { Map map = new HashMap<>(); List fields = new ArrayList<>(); @@ -76,4 +65,47 @@ public class ToscaUtils { } return fields; } + + public static class SubstituitionEntry{ + + private String fullName = ""; + private String sourceName = ""; + private String owner = ""; + + public SubstituitionEntry() {} + + public SubstituitionEntry(String fullName, String sourceName, String owner) { + if(fullName != null) + this.fullName = fullName; + if(sourceName != null) + this.sourceName = sourceName; + if(owner != null) + this.owner = owner; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getSourceName() { + return sourceName; + } + + public void setSourceName(String sourceName) { + this.sourceName = sourceName; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + } + } diff --git a/catalog-be/src/main/webapp/WEB-INF/web.xml b/catalog-be/src/main/webapp/WEB-INF/web.xml index 16c6fd6756..5ed38e6bc1 100644 --- a/catalog-be/src/main/webapp/WEB-INF/web.xml +++ b/catalog-be/src/main/webapp/WEB-INF/web.xml @@ -95,7 +95,7 @@ swagger.api.basepath - http://localhost:8080/sdc2/rest + /sdc2/rest @@ -129,7 +129,7 @@ swagger.api.basepath - http://localhost:8080/sdc + /sdc diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadInfo.java index 75707ee77c..52a7ec073e 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadInfo.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadInfo.java @@ -22,10 +22,20 @@ package org.openecomp.sdc.be.model; public abstract class UploadInfo { + private String key; + private String type; private String name; + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + public String getType() { return type; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java index 1726c397ad..79360f6e10 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java @@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; @@ -44,6 +45,7 @@ import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; import org.openecomp.sdc.be.dao.jsongraph.utils.IdBuilderUtils; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupInstanceDataDefinition; @@ -1338,32 +1340,49 @@ public abstract class BaseOperation { // return StorageOperationStatus.OK; // } - protected GroupInstanceDataDefinition buildGroupInstanceDataDefinition(GroupDataDefinition group, ComponentInstanceDataDefinition componentInstance) { - - String componentInstanceName = componentInstance.getName(); - Long creationDate = System.currentTimeMillis(); - GroupInstanceDataDefinition groupInstance = new GroupInstanceDataDefinition(); - String groupUid = group.getUniqueId(); - - groupInstance.setGroupUid(groupUid); - groupInstance.setType(group.getType()); - groupInstance.setCustomizationUUID(generateCustomizationUUID()); - groupInstance.setCreationTime(creationDate); - groupInstance.setModificationTime(creationDate); - groupInstance.setName(buildGroupInstanceName(componentInstanceName, group.getName())); - groupInstance.setGroupName(group.getName()); - groupInstance.setNormalizedName(ValidationUtils.normalizeComponentInstanceName(groupInstance.getName())); - groupInstance.setUniqueId(UniqueIdBuilder.buildResourceInstanceUniuqeId(componentInstance.getUniqueId(), groupUid, groupInstance.getNormalizedName())); - groupInstance.setArtifacts(group.getArtifacts()); - groupInstance.setArtifactsUuid(group.getArtifactsUuid()); - groupInstance.setProperties(group.getProperties()); - convertPropertiesToInstanceProperties(groupInstance.getProperties()); - groupInstance.setInvariantUUID(group.getInvariantUUID()); - groupInstance.setGroupUUID(group.getGroupUUID()); - groupInstance.setVersion(group.getVersion()); - - return groupInstance; - } + protected GroupInstanceDataDefinition buildGroupInstanceDataDefinition(GroupDataDefinition group, ComponentInstanceDataDefinition componentInstance, Map instDeplArtifMap) { + + String componentInstanceName = componentInstance.getName(); + Long creationDate = System.currentTimeMillis(); + GroupInstanceDataDefinition groupInstance = new GroupInstanceDataDefinition(); + String groupUid = group.getUniqueId(); + + groupInstance.setGroupUid(groupUid); + groupInstance.setType(group.getType()); + groupInstance.setCustomizationUUID(generateCustomizationUUID()); + groupInstance.setCreationTime(creationDate); + groupInstance.setModificationTime(creationDate); + groupInstance.setName(buildGroupInstanceName(componentInstanceName, group.getName())); + groupInstance.setGroupName(group.getName()); + groupInstance.setNormalizedName(ValidationUtils.normalizeComponentInstanceName(groupInstance.getName())); + groupInstance.setUniqueId(UniqueIdBuilder.buildResourceInstanceUniuqeId(componentInstance.getUniqueId(), groupUid, groupInstance.getNormalizedName())); + groupInstance.setArtifacts(group.getArtifacts()); + +// List fixedArtifactsUuid; +// List artifactsUuid = group.getArtifactsUuid(); +// if (instDeplArtifMap != null) { +// fixedArtifactsUuid = new ArrayList<>(); +// artifactsUuid.forEach(u -> { +// Optional findFirst = instDeplArtifMap.values().stream().filter(a -> u.equals(a.getUniqueId())).findFirst(); +// if (findFirst.isPresent()) { +// fixedArtifactsUuid.add(findFirst.get().getArtifactUUID()); +// } else { +// fixedArtifactsUuid.add(u); +// } +// }); +// } else { +// fixedArtifactsUuid = artifactsUuid; +// } + groupInstance.setArtifactsUuid(group.getArtifactsUuid()); + groupInstance.setProperties(group.getProperties()); + convertPropertiesToInstanceProperties(groupInstance.getProperties()); + groupInstance.setInvariantUUID(group.getInvariantUUID()); + groupInstance.setGroupUUID(group.getGroupUUID()); + groupInstance.setVersion(group.getVersion()); + + return groupInstance; + } + protected String buildGroupInstanceName(String instanceName, String groupName) { return ValidationUtils.normalizeComponentInstanceName(instanceName) + ".." + groupName; diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java index b642410548..7ff42ae42e 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java @@ -793,7 +793,7 @@ public class NodeTemplateOperation extends BaseOperation { for (Map.Entry> groupArtifacts : groupInstancesArtifacts.entrySet()) { Optional groupOptional = groups.stream().filter(g -> g.getUniqueId().equals(groupArtifacts.getKey())).findFirst(); if (groupOptional.isPresent()) { - GroupInstanceDataDefinition groupInstance = buildGroupInstanceDataDefinition((GroupDataDefinition)groupOptional.get(), (ComponentInstanceDataDefinition)componentInstance); + GroupInstanceDataDefinition groupInstance = buildGroupInstanceDataDefinition((GroupDataDefinition) groupOptional.get(), (ComponentInstanceDataDefinition) componentInstance, null); groupInstance.setGroupInstanceArtifacts(groupArtifacts.getValue().stream().map(a -> a.getUniqueId()).collect(Collectors.toList())); groupInstance.setGroupInstanceArtifactsUuid(groupArtifacts.getValue().stream().map(a -> a.getArtifactUUID()).collect(Collectors.toList())); groupInstanceToCreate.put(groupInstance.getName(), groupInstance); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java index d986d77450..e530144fe0 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java @@ -21,6 +21,7 @@ package org.openecomp.sdc.be.model.jsontitan.operations; import fj.data.Either; +import java.util.stream.Collectors; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; @@ -58,8 +59,10 @@ import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.regex.Pattern; @org.springframework.stereotype.Component("node-type-operation") @@ -757,25 +760,49 @@ public class NodeTypeOperation extends ToscaElementOperation { return DaoStatusConverter.convertTitanStatusToStorageStatus(error); } // must be only one - GraphVertex newDerived = getParentResources.left().value().get(0); - derivedResources.add(newDerived); - StorageOperationStatus updateStatus = updateDataFromNewDerived(derivedResources, nodeTypeV, (NodeType)toscaElementToUpdate); - if (updateStatus != StorageOperationStatus.OK) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update data for {} from new derived {} ", nodeTypeV.getUniqueId(), newDerived.getUniqueId(), updateStatus); - return updateStatus; - } + GraphVertex newDerivedV = getParentResources.left().value().get(0); + return updateDerived(toscaElementToUpdate, nodeTypeV, firstDerivedInChain, newDerivedV, false); + } + } + return StorageOperationStatus.OK; + } - Either deleteEdge = titanDao.deleteEdge(nodeTypeV, firstDerivedInChain, EdgeLabelEnum.DERIVED_FROM); - if (deleteEdge.isRight()) { - TitanOperationStatus deleteError = deleteEdge.right().value(); - log.debug("Failed to disassociate element {} from derived {} , error {}", nodeTypeV.getUniqueId(), firstDerivedInChain.getUniqueId(), deleteError); - return DaoStatusConverter.convertTitanStatusToStorageStatus(deleteError); - } + /** + * + * @param toscaElementToUpdate + * @param nodeTypeV + * @param preDerivedV + * @param newDerivedV + * @param mergeValues + * @return + */ + protected StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex nodeTypeV, GraphVertex preDerivedV, GraphVertex newDerivedV, boolean mergeValues) { + Set preDerivedChainIdList = new HashSet(); + preDerivedChainIdList.add(preDerivedV.getUniqueId()); + Either childVertex = titanDao.getChildVertex(preDerivedV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse); + while (childVertex.isLeft()) { + GraphVertex currentChield = childVertex.left().value(); + preDerivedChainIdList.add(currentChield.getUniqueId()); + childVertex = titanDao.getChildVertex(currentChield, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse); + } - titanDao.createEdge(nodeTypeV, newDerived, EdgeLabelEnum.DERIVED_FROM, new HashMap<>()); - } + List derivedResources = new ArrayList<>(); + derivedResources.add(newDerivedV); + StorageOperationStatus updateStatus = updateDataFromNewDerived(derivedResources, nodeTypeV, (NodeType) toscaElementToUpdate, mergeValues, preDerivedChainIdList); + if (updateStatus != StorageOperationStatus.OK) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update data for {} from new derived {} ", nodeTypeV.getUniqueId(), newDerivedV.getUniqueId(), updateStatus); + return updateStatus; + } + + Either deleteEdge = titanDao.deleteEdge(nodeTypeV, preDerivedV, EdgeLabelEnum.DERIVED_FROM); + if (deleteEdge.isRight()) { + TitanOperationStatus deleteError = deleteEdge.right().value(); + log.debug("Failed to disassociate element {} from derived {} , error {}", nodeTypeV.getUniqueId(), preDerivedV.getUniqueId(), deleteError); + return DaoStatusConverter.convertTitanStatusToStorageStatus(deleteError); } + titanDao.createEdge(nodeTypeV, newDerivedV, EdgeLabelEnum.DERIVED_FROM, new HashMap<>()); + return StorageOperationStatus.OK; } @@ -800,20 +827,20 @@ public class NodeTypeOperation extends ToscaElementOperation { } - private StorageOperationStatus updateDataFromNewDerived(List newDerived, GraphVertex nodeTypeV, NodeType nodeToUpdate) { + private StorageOperationStatus updateDataFromNewDerived(List newDerived, GraphVertex nodeTypeV, NodeType nodeToUpdate, boolean mergeValues, Set preDerivedChainIdList) { EnumSet edgeLabels = EnumSet.of(EdgeLabelEnum.CAPABILITIES, EdgeLabelEnum.REQUIREMENTS, EdgeLabelEnum.PROPERTIES, EdgeLabelEnum.ATTRIBUTES, EdgeLabelEnum.CAPABILITIES_PROPERTIES, EdgeLabelEnum.ADDITIONAL_INFORMATION); StorageOperationStatus status = null; - for (EdgeLabelEnum edge : edgeLabels){ - status = updateDataByType(newDerived, nodeTypeV, edge, nodeToUpdate); + for (EdgeLabelEnum edge : edgeLabels) { + status = updateDataByType(newDerived, nodeTypeV, edge, nodeToUpdate, mergeValues, preDerivedChainIdList); if (status != StorageOperationStatus.OK) { break; } } return status; - + } - private StorageOperationStatus updateDataByType(List newDerivedList, GraphVertex nodeTypeV, EdgeLabelEnum label, NodeType nodeElement) { + private StorageOperationStatus updateDataByType(List newDerivedList, GraphVertex nodeTypeV, EdgeLabelEnum label, NodeType nodeElement, boolean mergeValues, Set preDerivedChainIdList) { log.debug("Update data from derived for element {} type {}", nodeTypeV.getUniqueId(), label); Either dataFromGraph = getDataVertex(nodeTypeV, label); if (dataFromGraph.isRight()) { @@ -824,9 +851,23 @@ public class NodeTypeOperation extends ToscaElementOperation { GraphVertex dataV = dataFromGraph.left().value(); Map mapFromGraph = (Map) dataV.getJson(); - mapFromGraph.entrySet().removeIf(e -> e.getValue().getOwnerId() != null); + Map valuesFrmPrev = null; + if (isSimpleHierarchy(label)) { + if (mergeValues) { + valuesFrmPrev = mapFromGraph.entrySet().stream().filter(e -> e.getValue().getOwnerId() != null).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + mapFromGraph.entrySet().removeIf(e -> preDerivedChainIdList.contains(e.getValue().getOwnerId())); + } else { + final Map valuesFrmPrevFinal = new HashMap<>(); + mapFromGraph.entrySet().stream().forEach(e -> { + T value = e.getValue(); + value = ToscaDataDefinition.removeAndCollectByOwnerId(value, preDerivedChainIdList); + valuesFrmPrevFinal.put(e.getKey(), value); + }); + valuesFrmPrev = valuesFrmPrevFinal; + mapFromGraph.entrySet().removeIf(e->e.getValue().isEmpty()); + } - Either, StorageOperationStatus> dataFromDerived = getDataFromDerived(newDerivedList, label); if (dataFromDerived.isRight()) { return dataFromDerived.right().value(); @@ -845,10 +886,74 @@ public class NodeTypeOperation extends ToscaElementOperation { } return StorageOperationStatus.OK; } + + private boolean isSimpleHierarchy(EdgeLabelEnum label) { + switch (label) { + case PROPERTIES: + case ATTRIBUTES: + case ADDITIONAL_INFORMATION: + case ARTIFACTS: + case GROUPS: + case INPUTS: + return true; + default: + return false; + } + } + @Override public void fillToscaElementVertexData(GraphVertex elementV, T toscaElementToUpdate, JsonParseFlagEnum flag) { fillMetadata(elementV, (NodeType) toscaElementToUpdate); } + public Either shouldUpdateDerivedVersion(ToscaElement toscaElementToUpdate, GraphVertex nodeTypeV) { + NodeType nodeType = (NodeType) toscaElementToUpdate; + + Either childVertex = titanDao.getChildVertex(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.NoParse); + if (childVertex.isRight()) { + TitanOperationStatus getchildError = childVertex.right().value(); + if (getchildError == TitanOperationStatus.NOT_FOUND) { + log.debug("derived resource for element {} not found", nodeTypeV.getUniqueId()); + return Either.right(StorageOperationStatus.OK); + } + + log.debug("Failed to fetch derived resource for element {} error {}", nodeTypeV.getUniqueId(), getchildError); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getchildError)); + } + GraphVertex firstDerivedInChain = childVertex.left().value(); + + String currentVersion = (String) firstDerivedInChain.getMetadataProperty(GraphPropertyEnum.VERSION); + + Map props = new HashMap<>(); + props.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, nodeType.getDerivedFrom().get(0)); + props.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + + Map propsHasNot = new HashMap<>(); + propsHasNot.put(GraphPropertyEnum.IS_DELETED, true); + Either, TitanOperationStatus> byCriteria = titanDao.getByCriteria(VertexTypeEnum.NODE_TYPE, props, propsHasNot, JsonParseFlagEnum.NoParse); + if (byCriteria.isRight()) { + log.debug("Failed to fetch derived by props {} error {}", props, byCriteria.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(byCriteria.right().value())); + } + List lastDerived = byCriteria.left().value(); + // now supported only one derived!!! Change in future!(Evg) + GraphVertex derivedFromHighest = lastDerived.get(0); + String highestVersion = (String) derivedFromHighest.getMetadataProperty(GraphPropertyEnum.VERSION); + if (!highestVersion.equals(currentVersion)) { + + // need to update to latest version of derived from + StorageOperationStatus updateDerived = updateDerived(toscaElementToUpdate, nodeTypeV, firstDerivedInChain, derivedFromHighest, true); + + if (updateDerived != StorageOperationStatus.OK) { + log.debug("Failed to update {} to highest derived {} from error {}", nodeTypeV.getUniqueId(), derivedFromHighest.getUniqueId(), updateDerived); + return Either.right(updateDerived); + } + return getToscaElement(nodeTypeV.getUniqueId(), new ComponentParametersView()); + } + // no version changes + return Either.right(StorageOperationStatus.OK); + } + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementLifecycleOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementLifecycleOperation.java index 51d122524c..f34975b073 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementLifecycleOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementLifecycleOperation.java @@ -1120,7 +1120,7 @@ public class ToscaElementLifecycleOperation extends BaseOperation { Map groupInstanceToCreate = new HashMap<>(); for(GroupDataDefinition group:filteredGroups){ CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "create new groupInstance {} ", group.getName()); - GroupInstanceDataDefinition groupInstance = buildGroupInstanceDataDefinition(group, vfInst); + GroupInstanceDataDefinition groupInstance = buildGroupInstanceDataDefinition(group, vfInst, instDeplArtifMap); List artifactsUid = new ArrayList<>(); List artifactsId = new ArrayList<>(); for (ArtifactDataDefinition artifact : instDeplArtifMap.values()) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java index b11036df49..394231938a 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java @@ -275,8 +275,11 @@ public class ToscaOperationFacade { public Either getLatestByToscaResourceName(String toscaResourceName) { return getLatestByName(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName); - } + + public Either getFullLatestComponentByToscaResourceName(String toscaResourceName) { + return getLatestByName(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName, JsonParseFlagEnum.ParseAll); + } public Either getLatestByName(String resourceName) { return getLatestByName(GraphPropertyEnum.NAME, resourceName); @@ -536,6 +539,39 @@ public class ToscaOperationFacade { return getToscaElementByOperation(highestResource); } + private Either getLatestByName(GraphPropertyEnum property, String nodeName, JsonParseFlagEnum parseFlag) { + Either result; + + Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); + Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); + + propertiesToMatch.put(property, nodeName); + propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + + propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); + + Either, TitanOperationStatus> highestResources = titanDao.getByCriteria(null, propertiesToMatch, propertiesNotToMatch, parseFlag); + if (highestResources.isRight()) { + TitanOperationStatus status = highestResources.right().value(); + log.debug("failed to find resource with name {}. status={} ", nodeName, status); + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); + return result; + } + + List resources = highestResources.left().value(); + double version = 0.0; + GraphVertex highestResource = null; + for (GraphVertex vertex : resources) { + Object versionObj = vertex.getMetadataProperty(GraphPropertyEnum.VERSION); + double resourceVersion = Double.valueOf((String) versionObj); + if (resourceVersion > version) { + version = resourceVersion; + highestResource = vertex; + } + } + return getToscaElementByOperation(highestResource); + } + public Either, StorageOperationStatus> getBySystemName(ComponentTypeEnum componentType, String systemName) { Either, StorageOperationStatus> result = null; @@ -2216,4 +2252,28 @@ public class ToscaOperationFacade { return status; } + public Either shouldUpgradeToLatestDerived(Resource clonedResource) { + String componentId = clonedResource.getUniqueId(); + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + + } + GraphVertex nodeTypeV = getVertexEither.left().value(); + + ToscaElement toscaElementToUpdate = ModelConverter.convertToToscaElement(clonedResource); + + Either shouldUpdateDerivedVersion = nodeTypeOperation.shouldUpdateDerivedVersion(toscaElementToUpdate, nodeTypeV); + if ( shouldUpdateDerivedVersion.isRight() && StorageOperationStatus.OK != shouldUpdateDerivedVersion.right().value() ){ + log.debug("Failed to update derived version for node type {} derived {}, error: {}", componentId, clonedResource.getDerivedFrom().get(0), shouldUpdateDerivedVersion.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + } + if ( shouldUpdateDerivedVersion.isLeft() ){ + return Either.left(ModelConverter.convertFromToscaElement(shouldUpdateDerivedVersion.left().value())); + } + return Either.left(clonedResource); + } + + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java index 03a5f41d55..973b0ce069 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java @@ -94,6 +94,22 @@ public class ModelConverter { return null; } } + + public static boolean isAtomicComponent(Component component) { + ComponentTypeEnum componentType = component.getComponentType(); + if (!componentType.equals(ComponentTypeEnum.RESOURCE)) { + return false; + } + Resource resource = (Resource) component; + ResourceTypeEnum resType = resource.getResourceType(); + return isAtomicComponent(resType); + } + + public static boolean isAtomicComponent(ResourceTypeEnum resourceType) { + if (resourceType == null || resourceType == ResourceTypeEnum.VF || resourceType == ResourceTypeEnum.PNF || resourceType == ResourceTypeEnum.CVFC) + return false; + return true; + } // ********************************************************** public static VertexTypeEnum getVertexType(Component component) { @@ -117,11 +133,7 @@ public class ModelConverter { return vertexType; } - public static boolean isAtomicComponent(ResourceTypeEnum resourceType) { - if (resourceType == null || resourceType == ResourceTypeEnum.VF || resourceType == ResourceTypeEnum.PNF || resourceType == ResourceTypeEnum.CVFC) - return false; - return true; - } + private static Service convertToService(ToscaElement toscaElement) { Service service = new Service(); @@ -303,6 +315,7 @@ public class ModelConverter { relationshipPair.setCapabilityOwnerId(relation.getCapabilityOwnerId()); relationshipPair.setCapabilityUid(relation.getCapabilityId()); + relationshipPair.setCapability(relation.getCapability()); relationshipPair.setRequirementOwnerId(relation.getRequirementOwnerId()); relationshipPair.setRequirementUid(relation.getRequirementId()); relationshipPair.setRequirement(relation.getRequirement()); @@ -991,18 +1004,7 @@ public class ModelConverter { toscaElement.setMetadataValue(JsonPresentationFields.CONTACT_ID, component.getContactId()); } - public static boolean isAtomicComponent(Component component) { - ComponentTypeEnum componentType = component.getComponentType(); - if (!componentType.equals(ComponentTypeEnum.RESOURCE)) { - return false; - } - Resource resource = (Resource) component; - ResourceTypeEnum resType = resource.getResourceType(); - if (resType == ResourceTypeEnum.VFC || resType == ResourceTypeEnum.VFCMT || resType == ResourceTypeEnum.VL || resType == ResourceTypeEnum.CP || resType == ResourceTypeEnum.ABSTRACT) { - return true; - } - return false; - } + private static void setComponentInstancesToComponent(TopologyTemplate topologyTemplate, Component component) { diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/tosca/ToscaDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/tosca/ToscaDataDefinition.java index df73adaa4a..b8d164e4aa 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/tosca/ToscaDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/tosca/ToscaDataDefinition.java @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.stream.Collectors; import org.codehaus.jackson.annotate.JsonCreator; @@ -104,4 +105,13 @@ public abstract class ToscaDataDefinition { public boolean findUidMatch(String uid){ return uid.equals(getToscaPresentationValue(JsonPresentationFields.UNIQUE_ID)); } + public T removeByOwnerId(Set ownerIdList) { + return (T) this; + } + public static T removeAndCollectByOwnerId(T complexStructure, Set ownerIdList) { + return complexStructure.removeByOwnerId(ownerIdList); + } + public boolean isEmpty(){ + return false; + } } diff --git a/openecomp-be/tools/build/scripts/generate-cassandra-init-cql.sh b/openecomp-be/tools/build/scripts/generate-cassandra-init-cql.sh index eaa9a3f59d..06065b1368 100644 --- a/openecomp-be/tools/build/scripts/generate-cassandra-init-cql.sh +++ b/openecomp-be/tools/build/scripts/generate-cassandra-init-cql.sh @@ -26,7 +26,7 @@ usage() { echo "Usage: $0 keyspace yes/no, for example: $0 ca main() { - if [ $3 == 'yes' ]; then + if [ "$3" = "yes" ]; then echo "CREATE KEYSPACE IF NOT EXISTS dox WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };" fi echo "USE dox;" diff --git a/openecomp-be/tools/build/scripts/zusammen-generate-cassandra-init-cql.sh b/openecomp-be/tools/build/scripts/zusammen-generate-cassandra-init-cql.sh index b215fb3ce7..8cb422a121 100644 --- a/openecomp-be/tools/build/scripts/zusammen-generate-cassandra-init-cql.sh +++ b/openecomp-be/tools/build/scripts/zusammen-generate-cassandra-init-cql.sh @@ -27,7 +27,7 @@ usage() { echo "Usage: $0 keyspace yes/no, for example: $0 ca main() { - if [ $3 == 'yes' ]; then + if [ "$3" = "yes" ]; then echo "CREATE KEYSPACE IF NOT EXISTS $KEYSPACE_ZUSAMMEN WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 3 };" fi echo "USE $KEYSPACE_ZUSAMMEN;" diff --git a/sdc-os-chef/pom.xml b/sdc-os-chef/pom.xml index f0bf6ec9ff..a14dfc5ae1 100644 --- a/sdc-os-chef/pom.xml +++ b/sdc-os-chef/pom.xml @@ -33,24 +33,17 @@ - - ${project.basedir}\sdc-cassandra\chef-repo\cookbooks\cassandra-actions\attributes\ - false - - **/default.rb - - ${project.parent.basedir}/sdc-os-chef/sdc-backend/chef-repo/cookbooks/sdc-catalog-be/files/default false - Artifact-Generator.properties - error-configuration.yaml - ecomp-error-configuration.yaml - logback.xml - - + Artifact-Generator.properties + error-configuration.yaml + ecomp-error-configuration.yaml + logback.xml + + ${project.parent.basedir}/sdc-os-chef/sdc-backend @@ -74,6 +67,17 @@ normatives.tar.gz + + ${project.basedir}/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/attributes/ + false + + **/default.rb + + + + ${project.basedir}/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default/tools + false + ${project.basedir}/sdc-sanity @@ -104,7 +108,7 @@ ${project.basedir}\sdc-cassandra\chef-repo\cookbooks\cassandra-actions\attributes\default.rb - normal['version'] = "${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}" + normal['version'] ="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}" @@ -255,6 +259,7 @@ + copy-resources-test-apis-ci validate @@ -273,6 +278,33 @@ + + + + copy-dox-files + validate + + copy-resources + + + ${basedir}/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default + + + ${project.parent.basedir}/openecomp-be + + tools/build/** + + + + ${project.parent.basedir}/openecomp-be + + tools/install/** + + + + + + copy-normatives validate @@ -306,11 +338,10 @@ nexus3.onap.org:10001 - docker - docker - - - + docker + docker + + diff --git a/sdc-os-chef/scripts/docker_run.sh b/sdc-os-chef/scripts/docker_run.sh index ed4246d72c..79173c9654 100755 --- a/sdc-os-chef/scripts/docker_run.sh +++ b/sdc-os-chef/scripts/docker_run.sh @@ -56,19 +56,36 @@ fi RELEASE=latest LOCAL=false -SKIPTESTS=false +RUNTESTS=false DEBUG_PORT="--publish 4000:4000" while [ $# -gt 0 ] do case $1 in - -r | --release ) shift 1 ; RELEASE=$1 ; shift 1 ;; - -e | --environment ) shift 1 ; DEP_ENV=$1 ; shift 1 ;; - -p | --port ) shift 1 ; PORT=$1 ; shift 1 ;; - -l | --local ) LOCAL=true ; shift 1 ;; - -s | --skipTests ) SKIPTESTS=true ; shift 1 ;; - -h | --help ) usage ; exit 0 ;; - * ) usage ; exit 1 ;; + -r | --release ) + shift 1 ; + RELEASE=$1; + shift 1;; + -e | --environment ) + shift 1; + DEP_ENV=$1; + shift 1 ;; + -p | --port ) + shift 1 ; + PORT=$1; + shift 1 ;; + -l | --local ) + LOCAL=true; + shift 1;; + -t | --runTests ) + RUNTESTS=true; + shift 1 ;; + -h | --help ) + usage; + exit 0;; + * ) + usage; + exit 1;; esac done @@ -187,7 +204,7 @@ echo -e "" # sanityDocker echo "docker run sdc-sanity..." -if [ ${SKIPTESTS} = false ]; then +if [ ${RUNTESTS} = true ]; then echo "Triger sanity docker, please wait..." if [ ${LOCAL} = false ]; then docker pull ${PREFIX}/sdc-sanity:${RELEASE} diff --git a/sdc-os-chef/scripts/docker_sanity_run.sh b/sdc-os-chef/scripts/docker_sanity_run.sh new file mode 100644 index 0000000000..339b538f7a --- /dev/null +++ b/sdc-os-chef/scripts/docker_sanity_run.sh @@ -0,0 +1,122 @@ +#!/bin/bash + + +function usage { + echo "usage: docker_run.sh [ -r|--release ] [ -e|--environment ] [ -p|--port ] [ -l|--local ] [ -s|--skipTests ] [ -h|--help ]" +} + + +function cleanup { + echo "performing old dockers cleanup" + docker_ids=`docker ps -a | egrep -v "openecomp/sdc-simulator" | egrep "ecomp-nexus:${PORT}/sdc|sdc|Exit" | awk '{print $1}'` + for X in ${docker_ids} + do + docker rm -f ${X} + done +} + + +function dir_perms { + mkdir -p /data/logs/BE/SDC/SDC-BE + mkdir -p /data/logs/FE/SDC/SDC-FE + chmod -R 777 /data/logs +} + +function monitor_docker { + +echo monitor $1 Docker +sleep 10 +TIME_OUT=800 +INTERVAL=20 +TIME=0 +while [ "$TIME" -lt "$TIME_OUT" ]; do + +MATCH=`docker logs --tail 30 $1 | grep "DOCKER STARTED"` +echo MATCH is -- $MATCH + +if [ -n "$MATCH" ] + then + echo DOCKER start finished in $TIME seconds + break + fi + + echo Sleep: $INTERVAL seconds before testing if $1 DOCKER is up. Total wait time up now is: $TIME seconds. Timeout is: $TIME_OUT seconds + sleep $INTERVAL + TIME=$(($TIME+$INTERVAL)) +done + +if [ "$TIME" -ge "$TIME_OUT" ] + then + echo -e "\e[1;31mTIME OUT: DOCKER was NOT fully started in $TIME_OUT seconds... Could cause problems ...\e[0m" +fi + + +} + + +RELEASE=latest +LOCAL=false +SKIPTESTS=false +DEBUG_PORT="--publish 4000:4000" + +[ -f /opt/config/env_name.txt ] && DEP_ENV=$(cat /opt/config/env_name.txt) || DEP_ENV=__ENV-NAME__ +[ -f /opt/config/nexus_username.txt ] && NEXUS_USERNAME=$(cat /opt/config/nexus_username.txt) || NEXUS_USERNAME=release +[ -f /opt/config/nexus_password.txt ] && NEXUS_PASSWD=$(cat /opt/config/nexus_password.txt) || NEXUS_PASSWD=sfWU3DFVdBr7GVxB85mTYgAW +[ -f /opt/config/nexus_docker_repo.txt ] && NEXUS_DOCKER_REPO=$(cat /opt/config/nexus_docker_repo.txt) || NEXUS_DOCKER_REPO=ecomp-nexus:${PORT} + +while test $# -gt 0; do + case $1 in + -r | --release ) + shift + RELEASE=$1 + ;; + -e | --environment ) + shift + DEP_ENV=$1 + ;; + -p | --port ) + shift + PORT=$1 + ;; + -l | --local ) + shift + LOCAL=true + ;; + -s | --skipTests ) + shift + SKIPTESTS=true + ;; + -h | --help ) + usage + exit + ;; + * ) + usage + exit 1 + esac +done + +[ -f /opt/config/nexus_username.txt ] && docker login -u $NEXUS_USERNAME -p $NEXUS_PASSWD $NEXUS_DOCKER_REPO + + + + +export IP=`ifconfig eth0 | awk -F: '/inet addr/ {gsub(/ .*/,"",$2); print $2}'` +export PREFIX=${NEXUS_DOCKER_REPO}'/openecomp' + +if [ ${LOCAL} = true ]; then + PREFIX='openecomp' +fi + +echo "" + + +# sanityDocker +echo "docker run sdc-frontend..." +if [ ${SKIPTESTS} = false ]; then +echo "Triger sanity docker, please wait..." + if [ ${LOCAL} = false ]; then + docker pull ${PREFIX}/sdc-sanity:${RELEASE} + fi + docker run --detach --name sdc-sanity --env HOST_IP=${IP} --env ENVNAME="${DEP_ENV}" --env http_proxy=${http_proxy} --env https_proxy=${https_proxy} --env no_proxy=${no_proxy} --log-driver=json-file --log-opt max-size=100m --log-opt max-file=10 --ulimit memlock=-1:-1 --memory 1.2g --memory-swap=1.2g --ulimit nofile=4096:100000 --volume /etc/localtime:/etc/localtime:ro --volume /data/logs/sdc-sanity/target:/var/lib/tests/target --volume /data/logs/sdc-sanity/ExtentReport:/var/lib/tests/ExtentReport --volume /data/environments:/root/chef-solo/environments --publish 8849:8849 --publish 9560:9560 ${PREFIX}/sdc-sanity:${RELEASE} +fi diff --git a/sdc-os-chef/scripts/sanity_run.sh b/sdc-os-chef/scripts/sanity_run.sh new file mode 100644 index 0000000000..17d1642c73 --- /dev/null +++ b/sdc-os-chef/scripts/sanity_run.sh @@ -0,0 +1,117 @@ +#!/bin/bash + + +function usage { + echo "usage: docker_run.sh [ -r|--release ] [ -e|--environment ] [ -p|--port ] [ -l|--local ] [ -s|--skipTests ] [ -h|--help ]" +} + + +function cleanup { + echo "performing old dockers cleanup" + docker_ids=`docker ps -a | egrep -v "openecomp/sdc-simulator" | egrep "ecomp-nexus:${PORT}/sdc-sanity|sdc-sanity|Exit" | awk '{print $1}'` + for X in ${docker_ids} + do + docker rm -f ${X} + done +} + + +function dir_perms { + mkdir -p /data/logs/BE/SDC/SDC-BE + mkdir -p /data/logs/FE/SDC/SDC-FE + chmod -R 777 /data/logs +} + +function monitor_docker { + +echo monitor $1 Docker +sleep 5 +TIME_OUT=900 +INTERVAL=20 +TIME=0 +while [ "$TIME" -lt "$TIME_OUT" ]; do + +MATCH=`docker logs --tail 30 $1 | grep "DOCKER STARTED"` +echo MATCH is -- $MATCH + +if [ -n "$MATCH" ] + then + echo DOCKER start finished in $TIME seconds + break + fi + + echo Sleep: $INTERVAL seconds before testing if $1 DOCKER is up. Total wait time up now is: $TIME seconds. Timeout is: $TIME_OUT seconds + sleep $INTERVAL + TIME=$(($TIME+$INTERVAL)) +done + +if [ "$TIME" -ge "$TIME_OUT" ] + then + echo -e "\e[1;31mTIME OUT: DOCKER was NOT fully started in $TIME_OUT seconds... Could cause problems ...\e[0m" +fi + + +} + + +RELEASE=latest +LOCAL=false +SKIPTESTS=false +DEBUG_PORT="--publish 4000:4000" + +[ -f /opt/config/env_name.txt ] && DEP_ENV=$(cat /opt/config/env_name.txt) || DEP_ENV=__ENV-NAME__ +[ -f /opt/config/nexus_username.txt ] && NEXUS_USERNAME=$(cat /opt/config/nexus_username.txt) || NEXUS_USERNAME=release +[ -f /opt/config/nexus_password.txt ] && NEXUS_PASSWD=$(cat /opt/config/nexus_password.txt) || NEXUS_PASSWD=sfWU3DFVdBr7GVxB85mTYgAW +[ -f /opt/config/nexus_docker_repo.txt ] && NEXUS_DOCKER_REPO=$(cat /opt/config/nexus_docker_repo.txt) || NEXUS_DOCKER_REPO=ecomp-nexus:${PORT} + +while [ "$1" != "" ]; do + case $1 in + -r | --release ) + shift + RELEASE=${1} + ;; + -e | --environment ) + shift + DEP_ENV=${1} + ;; + -p | --port ) + shift + PORT=${1} + ;; + -l | --local ) + shift + LOCAL=true + ;; + -s | --skipTests ) + shift + SKIPTESTS=true + ;; + -h | --help ) + usage + exit + ;; + * ) + usage + exit 1 + esac + shift +done + +[ -f /opt/config/nexus_username.txt ] && docker login -u $NEXUS_USERNAME -p $NEXUS_PASSWD $NEXUS_DOCKER_REPO + +export IP=`ifconfig eth0 | awk -F: '/inet addr/ {gsub(/ .*/,"",$2); print $2}'` +export PREFIX=${NEXUS_DOCKER_REPO}'/openecomp' + +if [ ${LOCAL} = true ]; then + PREFIX='openecomp' +fi + +## sanityDocker +echo "docker run sdc-sanity..." +if [ ${SKIPTESTS} = false ]; then +echo "Triger sanity docker, please wait..." + if [ ${LOCAL} = false ]; then + docker pull ${PREFIX}/sdc-sanity:${RELEASE} + fi + docker run --detach --name sdc-sanity --env HOST_IP=${IP} --env ENVNAME="${DEP_ENV}" --env http_proxy=${http_proxy} --env https_proxy=${https_proxy} --env no_proxy=${no_proxy} --log-driver=json-file --log-opt max-size=100m --log-opt max-file=10 --ulimit memlock=-1:-1 --memory 1g --memory-swap=1g --ulimit nofile=4096:100000 --volume /etc/localtime:/etc/localtime:ro --volume /data/logs/sdc-sanity/target:/var/lib/tests/target --volume /data/logs/sdc-sanity/ExtentReport:/var/lib/tests/ExtentReport --volume /data/logs/sdc-sanity/outputCsar:/var/lib/tests/outputCsar --volume /data/environments:/root/chef-solo/environments --publish 9560:9560 ${PREFIX}/sdc-sanity:${RELEASE} +fi \ No newline at end of file diff --git a/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/attributes/default.rb b/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/attributes/default.rb index 646a14dc27..6bac10e196 100644 --- a/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/attributes/default.rb +++ b/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/attributes/default.rb @@ -1 +1 @@ -normal['version'] = "1.2.0" +normal['version'] ="1.2.0" diff --git a/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default/alter_dox_db.cql b/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default/alter_dox_db.cql deleted file mode 100644 index 70daf8bc6b..0000000000 --- a/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default/alter_dox_db.cql +++ /dev/null @@ -1,8 +0,0 @@ -USE dox; -ALTER TABLE vsp_information ADD questionnaire_data text; -ALTER TABLE vsp_information ADD vlm_version frozen; -ALTER TABLE vsp_information ADD onboarding_method text; -ALTER TABLE vsp_process ADD type text; -alter table entitlement_pool ADD version_uuid text; -alter table license_key_group ADD version_uuid text; -delete from application_config where namespace='vsp.monitoring' and key = 'component.ceilometer'; diff --git a/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default/create_dox_db.cql b/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default/create_dox_db.cql deleted file mode 100644 index e9aea31f7c..0000000000 --- a/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default/create_dox_db.cql +++ /dev/null @@ -1,60 +0,0 @@ -USE dox; -CREATE TYPE IF NOT EXISTS version (major int, minor int); -CREATE TYPE IF NOT EXISTS user_candidate_version (version frozen, user text); -CREATE TABLE IF NOT EXISTS version_info (entity_type text, entity_id text, active_version frozen, status text, candidate frozen, viewable_versions set>, latest_final_version frozen, PRIMARY KEY (entity_type, entity_id)); -CREATE TABLE IF NOT EXISTS version_info_deleted (entity_type text, entity_id text, active_version frozen, status text, candidate frozen, viewable_versions set>, latest_final_version frozen, PRIMARY KEY (entity_type, entity_id)); -CREATE TABLE IF NOT EXISTS unique_value (type text, value text, PRIMARY KEY ((type, value))); -CREATE TYPE IF NOT EXISTS choice_or_other (result text); -CREATE TYPE IF NOT EXISTS multi_choice_or_other (results set); -CREATE TABLE IF NOT EXISTS vendor_license_model (vlm_id text, version frozen, vendor_name text, description text, icon text, PRIMARY KEY ((vlm_id, version))); -CREATE TABLE IF NOT EXISTS license_agreement (vlm_id text, version frozen, la_id text, name text, description text, lic_term frozen, req_const text, fg_ids set, PRIMARY KEY ((vlm_id, version), la_id)); -CREATE TABLE IF NOT EXISTS feature_group (vlm_id text, version frozen, fg_id text, name text, description text, part_num text, ep_ids set, lkg_ids set, ref_la_ids set, PRIMARY KEY ((vlm_id, version), fg_id)); -CREATE TABLE IF NOT EXISTS license_key_group (vlm_id text, version frozen, lkg_id text,name text,description text, type text, operational_scope frozen, ref_fg_ids set, version_uuid text, PRIMARY KEY ((vlm_id, version), lkg_id)); -CREATE TABLE IF NOT EXISTS entitlement_pool (vlm_id text, version frozen, ep_id text,name text,description text,threshold float,threshold_unit text,entitlement_metric frozen,increments text,aggregation_func frozen, operational_scope frozen, time frozen,manufacturer_ref_num text,ref_fg_ids set, version_uuid text, PRIMARY KEY ((vlm_id, version), ep_id)); -CREATE TABLE IF NOT EXISTS vsp_information (VSP_ID text, version frozen, NAME text,DESCRIPTION text,CATEGORY text,SUB_CATEGORY text,ICON text,PACKAGE_NAME text,PACKAGE_VERSION text,vendor_name text, vendor_id text,LICENSE_AGREEMENT text,FEATURE_GROUPS list,VALIDATION_DATA text,CONTENT_DATA blob, questionnaire_data text, vlm_version frozen, is_old_version text, onboarding_method text, PRIMARY KEY ((VSP_ID, version))); -CREATE TABLE IF NOT EXISTS package_details (VSP_ID text, version frozen,DISPLAY_NAME text,vsp_name text,vsp_description text,VENDOR_NAME text,CATEGORY text,SUB_CATEGORY text,VENDOR_RELEASE text,PACKAGE_CHECKSUM text,PACKAGE_TYPE text,TRANSLATE_CONTENT blob,PRIMARY KEY ((VSP_ID, version))); -CREATE TABLE IF NOT EXISTS vsp_network (vsp_id text, version frozen, network_id text, composition_data text, questionnaire_data text, PRIMARY KEY ((vsp_id, version), network_id)); -CREATE TABLE IF NOT EXISTS vsp_component (vsp_id text, version frozen, component_id text, composition_data text, questionnaire_data text, PRIMARY KEY ((vsp_id, version), component_id)); -CREATE TABLE IF NOT EXISTS vsp_component_nic (vsp_id text, version frozen, component_id text, nic_id text, composition_data text, questionnaire_data text, PRIMARY KEY ((vsp_id, version), component_id, nic_id)); -CREATE TABLE IF NOT EXISTS vsp_component_image (vsp_id text, version frozen, component_id text, image_id text, composition_data text, questionnaire_data text, PRIMARY KEY ((vsp_id, version), component_id, image_id)); -CREATE TABLE IF NOT EXISTS vsp_process (vsp_id text, version frozen, component_id text, process_id text, name text, description text, type text, artifact_name text, artifact blob, PRIMARY KEY ((vsp_id, version), component_id, process_id)); -CREATE TABLE IF NOT EXISTS vsp_service_artifact (vsp_id text, version frozen, name text, content_data blob, PRIMARY KEY ((vsp_id, version), name)); -CREATE TABLE IF NOT EXISTS vsp_service_template (vsp_id text, version frozen, base_name text static, name text, content_data blob, PRIMARY KEY ((vsp_id, version), name)); -CREATE TABLE IF NOT EXISTS vsp_enriched_service_template (vsp_id text, version frozen, base_name text static, name text, content_data blob, PRIMARY KEY ((vsp_id, version), name)); -CREATE TABLE IF NOT EXISTS vsp_enriched_service_artifact (vsp_id text, version frozen, name text, content_data blob, PRIMARY KEY ((vsp_id, version), name)); -CREATE TABLE IF NOT EXISTS application_config (namespace text, key text, value text, PRIMARY KEY (namespace, key)); -CREATE TABLE IF NOT EXISTS dox.Action (actionUUID text, actionInvariantUUID text, version frozen, status text, name text, vendor_list set, category_list set, timestamp timestamp, user text, supportedModels set, supportedComponents set, data text, PRIMARY KEY ((actionInvariantUUID, version))); -CREATE INDEX IF NOT EXISTS action_supportedComponents ON dox.Action (supportedComponents); -CREATE INDEX IF NOT EXISTS action_category_list ON dox.Action (category_list); -CREATE INDEX IF NOT EXISTS action_supportedModels ON dox.Action (supportedModels); -CREATE INDEX IF NOT EXISTS action_vendor_list ON dox.Action (vendor_list); -CREATE INDEX IF NOT EXISTS action_actionUUID ON dox.Action (actionUUID); -CREATE TABLE IF NOT EXISTS dox.ecompcomponent(id text PRIMARY KEY, name text); -CREATE TABLE IF NOT EXISTS vsp_component_artifact (vsp_id text, version frozen, component_id text, artifact_type text, artifact_id text, name text, description text, artifact blob, PRIMARY KEY ((vsp_id, version), component_id, artifact_type, artifact_id)); -CREATE INDEX IF NOT EXISTS action_name ON dox.Action (name); -CREATE TABLE IF NOT EXISTS action_artifact(artifactuuid text, effective_version int, artifact blob, PRIMARY KEY(artifactuuid, effective_version)) WITH CLUSTERING ORDER BY (effective_version DESC); -CREATE TABLE IF NOT EXISTS vsp_orchestration_template_candidate (vsp_id text, version frozen, files_data_structure text, content_data blob, PRIMARY KEY ((vsp_id, version))); -CREATE TABLE IF NOT EXISTS vsp_deployment_flavor (vsp_id text, version frozen, deployment_flavor_id text, composition_data text, questionnaire_data text, PRIMARY KEY ((vsp_id, version), deployment_flavor_id)); -CREATE TABLE IF NOT EXISTS vsp_component_compute (vsp_id text, version frozen, component_id text, compute_id text, composition_data text, questionnaire_data text, PRIMARY KEY ((vsp_id, version), component_id, compute_id)); -CREATE TABLE IF NOT EXISTS vsp_component_dependency_model (vsp_id text, version frozen, dependency_id text, sourcecomponent_id text, targetcomponent_id text, relation text, PRIMARY KEY ((vsp_id, version), dependency_id)); -CREATE TABLE IF NOT EXISTS activity_log (item_id text, version_id text, activity_id text, type text, user text, timestamp timestamp, success boolean, message text, comment text, PRIMARY KEY (item_id, version_id, activity_id)); -CREATE TABLE IF NOT EXISTS migration (id text, ismigrated boolean, primary key(id)); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.schemaTemplates', 'composition.network', '{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "name": { "type": "string"<#if !manual>, "enum": [ "${network.name}" ], "default": "${network.name}" }, "dhcp": { "type": "boolean"<#if !manual>, "enum": [ ${network.dhcp?c} ], "default": ${network.dhcp?c} } }, "additionalProperties": false, "required": [ "name", "dhcp" ] }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.schemaTemplates', 'composition.component', '{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "name": { "type": "string"<#if !manual>, "enum": [ "${component.name}" ], "default": "${component.name}" }, "displayName": { "type": "string"<#if !manual && component.displayName??>, "enum": [ "${component.displayName}" ], "default": "${component.displayName}" }, "vfcCode": { "type": "string" }, "nfcCode": { "type": "string" }, "nfcFunction": { "type": "string" }, "description": { "type": "string" } }, "additionalProperties": false, "required": [ "name"<#if !manual && component.displayName??>, "displayName" ] }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.schemaTemplates', 'composition.compute', '{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "name": { "type": "string" <#if !manual>, "enum": [ "${compute.name}" ], "default": "${compute.name}" }, "description": { "type": "string", "maxLength": 300 } } }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.schemaTemplates', 'composition.deployment', '{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "model": { "type": "string", "maxLength": 30, "pattern": "^[A-Za-z0-9_,-]*$" }, "description": { "type": "string", "maxLength": 300 }, "featureGroupId":{ "type": "string", "enum": [<#if featureGroupIds??> <#list featureGroupIds as featureGroupId> "${featureGroupId}"<#sep>, ] }, "componentComputeAssociations": { "type": "array", "properties": { "vfcid": { "type": "string" }, "computeFlavorid": { "type": "string" } }, "additionalProperties": false } }, "additionalProperties": false, "required": [ "model" ] }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.schemaTemplates', 'composition.image', '{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "fileName": { "type": "string" }, "description": { "type": "string" } }, "additionalProperties": false }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.schemaTemplates', 'composition.nic', '{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "name": { "type": "string", "enum": [ "${nic.name}" ], "default": "${nic.name}" }, "description": { "type": "string" }<#if !manual><#if nic.networkId??>, "networkId": { "type": "string", "enum": [ "${nic.networkId}" ], "default": "${nic.networkId}" } <#elseif manual><#if nic.networkId??>, "networkId": { "type": "string", "enum": [ "${nic.networkId}" ], "default": "${nic.networkId}" } <#else>, "networkId": { "type": "string", "enum": [<#list networkIds as networkId> "${networkId}"<#sep>, ] } , "networkDescription": { "type": "string" }, "networkType": { "type": "string", "enum": [ "${nic.networkType}" ], "default": "${nic.networkType}" } }, "additionalProperties": false, "required": [ "name" ] }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.schemaTemplates', 'questionnaire.nic', '{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "protocols": { "type": "object", "properties": { "protocols": { "type": "array", "items": { "type": "string", "enum": [ "", "TCP", "UDP", "SCTP", "IPsec" ], "default": "" }, "minItems": 1 }, "protocolWithHighestTrafficProfile": { "$ref": "#/properties/protocols/properties/protocols/items" } }, "additionalProperties": false }, "ipConfiguration": { "type": "object", "properties": { "ipv4Required": { "type": "boolean", "default": true }, "ipv6Required": { "type": "boolean", "default": false } }, "additionalProperties": false }, "network": { "type": "object", "properties": { "networkDescription": { "type": "string", "pattern": "[A-Za-z]+", "maxLength": 300 } }, "additionalProperties": false }, "sizing": { "type": "object", "definitions": { "peakAndAvg": { "type": "object", "properties": { "peak": { "type": "number" }, "avg": { "type": "number" } }, "additionalProperties": false }, "packetsAndBytes": { "type": "object", "properties": { "packets": { "$ref": "#/properties/sizing/definitions/peakAndAvg" }, "bytes": { "$ref": "#/properties/sizing/definitions/peakAndAvg" } }, "additionalProperties": false } }, "properties": { "describeQualityOfService": { "type": "string" }, "inflowTrafficPerSecond": { "$ref": "#/properties/sizing/definitions/packetsAndBytes" }, "outflowTrafficPerSecond": { "$ref": "#/properties/sizing/definitions/packetsAndBytes" }, "flowLength": { "$ref": "#/properties/sizing/definitions/packetsAndBytes" }, "acceptableJitter": { "type": "object", "properties": { "mean": { "type": "number" }, "max": { "type": "number" }, "variable": { "type": "number" } }, "additionalProperties": false }, "acceptablePacketLoss": { "type": "number", "minimum": 0, "maximum": 100 } }, "additionalProperties": false } }, "additionalProperties": false }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.schemaTemplates', 'questionnaire.vsp', '{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "general": { "type": "object", "properties": { "affinityData": { "type": "string", "enum": [ "", "Affinity", "Anti Affinity", "None" ], "default": "" }, "availability": { "type": "object", "properties": { "useAvailabilityZonesForHighAvailability": { "type": "boolean", "default": false } }, "additionalProperties": false }, "regionsData": { "type": "object", "properties": { "multiRegion": { "type": "boolean", "default": false }, "regions": { "type": "array", "items": { "type": "string", "enum": [ "", "Alphareta", "Birmingham", "Dallas", "Fairfield CA", "Hayward CA", "Lisle", "Mission", "San Diego", "Secaucus" ], "default": "" } } }, "additionalProperties": false }, "storageDataReplication": { "type": "object", "properties": { "storageReplicationAcrossRegion": { "type": "boolean", "default": false }, "storageReplicationSize": { "type": "number", "maximum": 100, "exclusiveMaximum": true }, "storageReplicationFrequency": { "type": "number", "minimum": 5 }, "storageReplicationSource": { "type": "string", "maxLength": 300 }, "storageReplicationDestination": { "type": "string", "maxLength": 300 } }, "additionalProperties": false } }, "additionalProperties": false } }, "additionalProperties": false }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.schemaTemplates', 'questionnaire.component', '{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "general": { "type": "object", "properties": { "hypervisor": { "type": "object", "properties": { "hypervisor": { "type": "string", "enum": [ "KVM", "VMWare ESXi" ], "default": "KVM" }, "drivers": { "type": "string", "maxLength": 300, "pattern": "^[A-Za-z0-9_,-]*$" }, "containerFeaturesDescription": { "type": "string", "maxLength": 1000, "pattern": "^[A-Za-z0-9_, -]*$" } }, "additionalProperties": false }, "image": { "type": "object", "properties": { "providedBy": { "type": "string", "enum": [ "AIC", "Vendor" ], "default": "AIC" } }, "additionalProperties": false }, "disk": { "type": "object" , "properties": { "bootDiskSizePerVM": { "type": "number", "maximum": 100 }, "ephemeralDiskSizePerVM": { "type": "number", "maximum": 400 } }, "additionalProperties": false }, "recovery": { "type": "object", "properties": { "pointObjective": { "type": "number", "minimum": 0, "exclusiveMinimum": true, "maximum": 15, "exclusiveMaximum ": true }, "timeObjective": { "type": "number", "minimum": 0, "exclusiveMinimum": true, "maximum": 300, "exclusiveMaximum ": true }, "vmProcessFailuresHandling": { "type": "string" } }, "additionalProperties": false }, "dnsConfiguration": { "type": "string" }, "vmCloneUsage": { "type": "string", "maxLength": 300 } }, "additionalProperties": false }, "compute": { "type": "object", "properties": { "numOfVMs": { "type": "object", "properties": { "minimum": { "type": "number", "minimum": 0, "maximum": 100 }, "maximum": { "type": "number", "minimum": <#if (componentQuestionnaireData.compute.numOfVMs.minimum)?? && (componentQuestionnaireData.compute.numOfVMs.minimum)?is_number && ((componentQuestionnaireData.compute.numOfVMs.minimum) > 0 && (componentQuestionnaireData.compute.numOfVMs.minimum) <= 100)> ${componentQuestionnaireData.compute.numOfVMs.minimum}<#else> 0 , "exclusiveMinimum": true, "maximum": 100 } }, "additionalProperties": false }, "guestOS": { "type": "object", "properties": { "name": { "type": "string", "maxLength": 50 }, "bitSize": { "type": "number", "enum": [ 64, 32 ], "default": 64 }, "tools": { "type": "string" } }, "additionalProperties": false } }, "additionalProperties": false }, "highAvailabilityAndLoadBalancing": { "type": "object", "properties": { "isComponentMandatory": { "type": "string", "enum": ["","YES", "NO"], "default": "" }, "highAvailabilityMode": { "type": "string", "enum": ["","geo-activeactive", "geo-activestandby", "local-activeactive", "local-activestandby"], "default": "" }, "failureLoadDistribution": { "type": "string", "maxLength": 1000 }, "nkModelImplementation": { "type": "string", "maxLength": 1000 }, "architectureChoice": { "type": "string", "maxLength": 1000 }, "slaRequirements": { "type": "string", "maxLength": 1000 }, "horizontalScaling": { "type": "string", "maxLength": 1000 }, "loadDistributionMechanism": { "type": "string", "maxLength": 1000 } }, "additionalProperties": false }, "network": { "type": "object", "properties": { "networkCapacity": { "type": "object", "properties": { "protocolWithHighestTrafficProfileAcrossAllNICs": { "type": "string", "enum": [ "", "TCP", "UDP", "SCTP", "IPsec" ], "default": "" }, "networkTransactionsPerSecond": { "type": "number" } }, "additionalProperties": false } }, "additionalProperties": false }, "storage": { "type": "object", "properties": { "backup": { "type": "object", "properties": { "backupType": { "type": "string", "enum": [ "On Site", "Off Site" ], "default": "On Site" }, "backupStorageSize": { "type": "number" }, "backupSolution": { "type": "string" }, "backupNIC": { "type": "string", "enum": [ ""<#if nicNames??><#list nicNames as nicName> , "${nicName}" ], "default": "" } }, "additionalProperties": false }, "snapshotBackup": { "type": "object", "properties": { "snapshotFrequency": { "type": "number", "default": 24, "minimum": 1, "exclusiveMinimum": true } }, "additionalProperties": false }, "logBackup": { "type": "object", "properties": { "sizeOfLogFiles": { "type": "number", "maximum": 5, "exclusiveMaximum": true }, "logBackupFrequency": { "type": "number", "maximum": 4, "exclusiveMaximum": true }, "logRetentionPeriod": { "type": "number", "maximum": 15, "exclusiveMaximum": true }, "logFileLocation": { "type": "string", "maxLength": 300 } }, "additionalProperties": false } }, "additionalProperties": false } }, "additionalProperties": false }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.schemaTemplates', 'questionnaire.compute', '{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "vmSizing": { "type": "object", "properties": { "numOfCPUs": { "type": "number", "minimum": 0, "exclusiveMinimum": true, "maximum": 16, "default": 2 }, "fileSystemSizeGB": { "type": "number", "minimum": 0, "exclusiveMinimum": true, "default": 5 }, "persistentStorageVolumeSize": { "type": "number", "minimum": 0, "exclusiveMinimum": true }, "ioOperationsPerSec": { "type": "number", "minimum": 0, "exclusiveMinimum": true }, "cpuOverSubscriptionRatio": { "type": "string", "enum": [ "1:1", "4:1", "16:1" ], "default": "4:1" }, "memoryRAM": { "type": "string", "enum": [ "1 GB", "2 GB", "4 GB", "8 GB" ], "default": "1 GB" } }, "additionalProperties": false } } }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.schemaTemplates', 'questionnaire.image', '{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "format": { "type": "string", "enum": [ "aki","ami","ari","iso","qcow2","raw", "vdi","vhd","vmdk" ] }, "version": { "type": "string" }, "md5": { "type": "string" } }, "additionalProperties": false, "required": [ "version" ] }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.monitoring', 'compute.ceilometer', '{ "ceilometerMetricList": [ { "name": "instance", "type": "Gauge", "unit": "instance", "category": "compute", "description": "Existence of instance" }, { "name": "memory", "type": "Gauge", "unit": "MB", "category": "compute", "description": "Volume of RAM allocated to the instance" }, { "name": "memory.usage", "type": "Gauge", "unit": "MB", "category": "compute", "description": "Volume of RAM used by the instance from the amount of its allocated memory" }, { "name": "memory.resident", "type": "Gauge", "unit": "MB", "category": "compute", "description": "Volume of RAM used by the instance on the physical machine" }, { "name": "cpu", "type": "Cumulative", "unit": "ns", "category": "compute", "description": "CPU time used" }, { "name": "cpu_util", "type": "Gauge", "unit": "%", "category": "compute", "description": "Average CPU utilization" }, { "name": "cpu.delta", "type": "Delta", "unit": "ns", "category": "compute", "description": "CPU time used since previous datapoint" }, { "name": "vcpus", "type": "Gauge", "unit": "vcpu", "category": "compute", "description": "Number of virtual CPUs allocated to the instance" }, { "name": "disk.latency", "type": "Gauge", "unit": "ms", "category": "disk", "description": "Average disk latency" }, { "name": "disk.iops", "type": "Gauge", "unit": "count/s", "category": "disk", "description": "Average disk iops" }, { "name": "disk.device.latency", "type": "Gauge", "unit": "ms", "category": "disk", "description": "Average disk latency per device" }, { "name": "disk.device.iops", "type": "Gauge", "unit": "count/s", "category": "disk", "description": "Average disk iops per device" }, { "name": "disk.capacity", "type": "Gauge", "unit": "B", "category": "disk", "description": "The amount of disk that the instance can see" }, { "name": "disk.allocation", "type": "Gauge", "unit": "B", "category": "disk", "description": "The amount of disk occupied by the instance on the host machine" }, { "name": "disk.usage", "type": "Gauge", "unit": "B", "category": "disk", "description": "The physical size in bytes of the image container on the host" }, { "name": "disk.device.capacity", "type": "Gauge", "unit": "B", "category": "disk", "description": "The amount of disk per device that the instance can see" }, { "name": "disk.device.allocation", "type": "Gauge", "unit": "B", "category": "disk", "description": "The amount of disk per device occupied by the instance on the host machine" }, { "name": "disk.device.usage", "type": "Gauge", "unit": "B", "category": "disk", "description": "The physical size in bytes of the image container on the host per device" }, { "name": "disk.device.read.requests", "type": "Cumulative", "unit": "request", "category": "disk", "description": "Number of read requests" }, { "name": "disk.device.read.requests.rate", "type": "Gauge", "unit": "request/s", "category": "disk", "description": "Average rate of read requests" }, { "name": "disk.device.write.requests", "type": "Cumulative", "unit": "request", "category": "disk", "description": "Number of write requests" }, { "name": "disk.device.write.requests.rate", "type": "Gauge", "unit": "request/s", "category": "disk", "description": "Average rate of write requests" }, { "name": "disk.device.read.bytes", "type": "Cumulative", "unit": "B", "category": "disk", "description": "Volume of reads" }, { "name": "disk.device.read.bytes.rate", "type": "Gauge", "unit": "B/s", "category": "disk", "description": "Average rate of reads" }, { "name": "disk.device.write.bytes", "type": "Cumulative", "unit": "B", "category": "disk", "description": "Volume of writes" }, { "name": "disk.device.write.bytes.rate", "type": "Gauge", "unit": "B/s", "category": "disk", "description": "Average rate of writes" }, { "name": "disk.write.requests", "type": "Cumulative", "unit": "request", "category": "compute", "description": "Number of write requests" }, { "name": "disk.write.requests.rate", "type": "Gauge", "unit": "request/s", "category": "compute", "description": "Average rate of write requests" }, { "name": "disk.read.bytes", "type": "Cumulative", "unit": "B", "category": "compute", "description": "Volume of reads" }, { "name": "disk.read.bytes.rate", "type": "Gauge", "unit": "B/s", "category": "compute", "description": "Average rate of reads" }, { "name": "disk.write.bytes", "type": "Cumulative", "unit": "B", "category": "compute", "description": "Volume of writes" }, { "name": "disk.write.bytes.rate", "type": "Gauge", "unit": "B/s", "category": "compute", "description": "Average rate of writes" }, { "name": "disk.read.requests", "type": "Cumulative", "unit": "request", "category": "compute", "description": "Number of read requests" }, { "name": "disk.root.size", "type": "Gauge", "unit": "GB", "category": "compute", "description": "Size of root disk" }, { "name": "disk.ephemeral.size", "type": "Gauge", "unit": "GB", "category": "compute", "description": "Size of ephemeral disk" } ] }'); -INSERT INTO application_config (namespace,key,value) VALUES ('vsp.monitoring', 'port.ceilometer', '{ "ceilometerMetricList": [ { "name": "network.incoming.bytes", "type": "Cumulative", "unit": "B", "category": "network", "description": "Number of incoming bytes" }, { "name": "network.incoming.bytes.rate", "type": "Gauge", "unit": "B/s", "category": "network", "description": "Average rate of incoming bytes" }, { "name": "network.outgoing.bytes", "type": "Cumulative", "unit": "B", "category": "network", "description": "Number of outgoing bytes" }, { "name": "network.outgoing.bytes.rate", "type": "Gauge", "unit": "B/s", "category": "network", "description": "Average rate of outgoing bytes" }, { "name": "network.incoming.packets", "type": "Cumulative", "unit": "packet", "category": "network", "description": "Number of incoming packets" }, { "name": "network.incoming.packets.rate", "type": "Gauge", "unit": "packet/s", "category": "network", "description": "Average rate of incoming packets" }, { "name": "network.outpoing.packets", "type": "Cumulative", "unit": "packet", "category": "network", "description": "Number of outgoing packets" }, { "name": "network.outgoing.packets.rate", "type": "Gauge", "unit": "packet/s", "category": "network", "description": "Average rate of outgoing packets" } ] }'); -USE zusammen_dox; -CREATE TABLE IF NOT EXISTS item (item_id text primary key, item_info text, creation_time timestamp, modification_time timestamp); -CREATE TABLE IF NOT EXISTS version (space text, item_id text, version_id text,base_version_id text,info text,relations text,creation_time timestamp,modification_time timestamp,PRIMARY KEY (( space, item_id ), version_id)); -CREATE TABLE IF NOT EXISTS version_elements (space text,item_id text,version_id text,element_ids set,PRIMARY KEY (( space, item_id, version_id ))); -CREATE TABLE IF NOT EXISTS element_namespace (space text, item_id text, element_id text, namespace text, PRIMARY KEY ((space, item_id, element_id))); -CREATE TABLE IF NOT EXISTS element (space text,item_id text,version_id text,element_id text,parent_id text,namespace text,info text,relations text,data blob,searchable_data blob,visualization blob,sub_element_ids set,PRIMARY KEY (( space, item_id, version_id, element_id ))); diff --git a/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/recipes/03-createDoxKeyspace.rb b/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/recipes/03-createDoxKeyspace.rb index 68c1870832..789f658694 100644 --- a/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/recipes/03-createDoxKeyspace.rb +++ b/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/recipes/03-createDoxKeyspace.rb @@ -22,7 +22,7 @@ bash "onboard-db-schema-creation" do code <<-EOH cd /tmp/tools/build/scripts chmod +x onboard-db-schema-creation.sh - /tmp/tools/build/scripts/onboard-db-schema-creation.sh + bash /tmp/tools/build/scripts/onboard-db-schema-creation.sh EOH end diff --git a/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/Huawei_vPCRF.csar b/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/Huawei_vPCRF.csar new file mode 100644 index 0000000000000000000000000000000000000000..6f997bcf98b200a7ed021ab857126d827b0465f0 GIT binary patch literal 3836 zcmWIWW@Zs#0D-$pRJ_3qD8U7!9g9jb(-MVhWtqp0Hns&h$A%goCx$;{6~ zsN`U1j}7*ox?zjvT^0t0lco#|DrhQw6EpLIQ;W(nlT$-da|?13OH%bJ6LWLkM*HXA zG7#Ax{;Is=M&*hPdF^+$DQ@%fZcZq1KdsUh>HX$Rq0z?7`?cpi8vh|41Z?>BLA7JhyaCt6?EocX}-bk%D@QlYzxmu2zXJ=ga}>GrXl&-9Qw zV!|@(;_r_FcljiwZ-+2VsDzAEAsffGderv+Vz44W9*|0J^^@L;g; zHYHCM|BeY;+JYwK2Z#H6)e9YYuCdmy{8xCmeAaW_$m-J>o zzq|Y3mTLFbGX+;H@~tHOm;L%A`egN52K5RzNObpve^o;#?#TAT2DeTwQV z;l~fOQ;$6SESj`fSIfg^#vOy7MQbN+Dg5|;X7$cpanf(6ZO{4L7V7^nMfCD&?)8O< z_r=XKYJ=U)o5Nq|ow=v3DD`OOg2t0a@4DG%1{_p=bSPfWJX8JG^DfUZJ zUu1ehIZ73xHRryJKJ|Uswt1`x1KWBr*>6IMeXM)U(Rd(Rtef>)S7rMOu#oi zLpM`fE@$(%7il>&nMA&1Xf6GYW!En zSN(nF?0d%GScgHXP{m;xcg@VzGo^gp)Xs`bus07@7o2%esO_wXLf>5t^W zt8K?>cX-zO30HT9UcFv_{PGnI@tlO;Cs`$#c`edSv|E!Mp& zyKcSV>Qb-Sv##^0`t7dKIBBZY5w7bO6B>D2{s4n)&8B>XEavUkPp`<7pPjXZVOvPQ z+{t#I$Nq;4)aF(*Zx28FHZ4lkS$dghUcb+Lk5igUE``sNDqcVJ!sYNd;qTW^S#!oq z`sawI3rRCx56b!DF2cU?(4wzl27jML2fp5N|9bAyb4ELSUNG&lH9o&e`TWuCKFvZA z=e0B#*DYPJBg<*F}rNwqMJ4 z+AhKORr<4v8ny#k<{0j%{(4>pz=ScCCS1H?`bc5vAB?vnovIM&GK? zh|Rs447U4cFgeXl^Z97o-0`S-xuAbl{=fGXkE+uy9{JuU<6U#!YLbI`^52EindCn@ zuMfL(`$w>bMtaVvhz7|i8y(gLAKPY=x?x7C_5-{9)gSr!?bq(*IpF?f)3%U`6LWIk zT`^DIy>OP(HnWi1XLr23dufNCwL71`pG?(qlfnj#toN-9cJBH%3Fdi^TBnQaE9_6* z91=8h2wUY7b{?_K)$JSn@ewvID&mVrv~sjgiHuCMP0O^w#<71rRLZqXOO zAN!XPR*-Tq%=QiT-v1@NqZ?Q(?gC;lAjVcC=B9=A?&V@K6lnSFa8Ge>LCzL|OI%6H z9dYv0Ql=jDes^O2k8jVkN+p*4Y@6x8YAa?Ev|^pu`!dhX>(|}rXza4`}!eUbQB-AwR5YEp)E8QhGOZ3qaeb|@i3=FS)Cwl=) zK{((CvO@fWogH<3Q%e$45=#={?Pv~$T_M5V653jm3W17Rfmjk#F<7r&E>Lf5k0aM1 z0|AEjm9BOhHXd!B5WS{pdQ@TayykTqF04zH=K5J%tz&!cfX|x^oEL)pJ}Axop?~k% zIwRh;=jSw*`ovp^=ik>^ax`pR*>T|qwl*KGxfV}d!>acs`Qe_n$=jtZwsf+3rvD3A zlKAHOTzuoxqQ1jEzk2iGrAz03%sYs;6e z0P&H{#_UZXo2>yf3%PHBZ2I)Ojf;-CUS@>RL33(P-Pmyn$#iTz5SZy8R|cV(j;-h~?ZK>pk?k>H z!)_0{kC@hW`ht8Uy3gz8USN2Nl~k#LXoOAJ5;n{xPzrG7#z^MKUg-$z07ndrj@N?l z5f)&}3@{5o5mkU`0U~Q4TXiYiR(mbbFS~Dlb9%0hpaZ;FfuX^`zz&4xm>3u&K%G_w E0GjkHkN^Mx literal 0 HcmV?d00001 diff --git a/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/Huawei_vSPGW.csar b/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/Huawei_vSPGW.csar new file mode 100644 index 0000000000000000000000000000000000000000..e7eed4b7c674afcc62dfcff698131049a62c7050 GIT binary patch literal 3907 zcmeHKi9b~98$Tn588 zi)^JC49Su`OM@vz%5SEAuDNml1Mm5q^F7P+KHv8_=Y7A=d5j_JIK==~>rUMP`E~OD z10NH0ys&5#!V!y6G5*KyY&7&=cKl2`eIyEf5sgK=UtG2X1H9K=AkQ_2f&nf7s8$4k z9e-G!L7*?1BE7uPjz}}4n};g`i&XYSxVcVR!-+&yF@O5ASGRc{Ot_ZZ7??_Hx4A2V zNFCcw)a^JCB+L0i>!**<*ZkY+Ce{U{#%iMk%!k3oB2=SQzkQe776FBHCBun`8eY7y z$!P;;;kg>yfr^6k**1Au>5@1{@krr@Q=`uL+%vZH*dQJ7Slo$PZ=Q#$RZ3Cr zbb6%hVL3c`{`=&JuDQj9+#7`Oo?h}o^!}^&OCA-UTW^ro_H}_lAQ9#!F1lejP>x1s zeSCKz@z*$EeQ%qhNEQd{KfVmsjQY5b3s;sqlPL`L1XMD(6dlA!gqp;Q({)X|6c>K8=o7Q~48+LdyGy1A1tu`B;inZ^3F8E`< z^lPNi?N4ROhU+d9BWhl2e^9FRaay!$bIw<9dl*B3DUem(PlUsiqr{wIWV3HVMQ_A~ z9Y(v5YD^oU0-=v)q#wVY4xuAbaV5QituU6&Ct5?N-t#YmF-3Z zVq=we(%7Lskw(htz%q1M-yt)z`aB`>+2hbOsCA=;P#LZwIPqXV@=)G3wOjHPufsz) z59bflx$jV<%o}=g-VN>UC>AjjmHMKMu};FJJbiC;7@u)HIEmKaq-ZSXl>s*K2_@mY z0`l+DtZ{yS|J@a%tWlxP%fPJj75aWW-#r-z-{>R{?0I`i z+{Sc+H6!`qj|Y>5{8@FV#HNBHGUt^duS@5>B1z7gUa9r%xgWVTU7Xu|b}(fd{;AuH zyMfj1EXy%H*v?T12ReRFxiHTyhKqDaL<+dBKHF9W6+}Q?TC{k6BJXAbI%lu6xYo(< z@{#aiF;;?LQreXc9U z(Z|L<<+#}xGcZRk%Z54$^ehbK%D<;d%sWCEvX>?GV#m?^KU|MQCdtsz`qq+RAbUa~ zsj1X66!$aA0~!)G-s#wPPi;!69#N&$tBMd%GX$Ts715x?+O~(Ol(w{V`}WFBzkMLj z-+CX8`B?cn{<@%d`#JlZ676RDT_YMN{f4JDfBUTO(?=D39|V0wuSl=%4O(m#FO&=5 zLGbqKST0TrI#lx8U{7k&fy^^mt_OXU^Yrz2C*bMU6&Tux2shoMteIs*UO*P$6=8>g*9D9YYeh((=;kLTI z5TlD{VTYm&bv`AmTX#?BB8Sh&=L zm?vgXQ$3wMXOLKg69S9)=U*HQFigxKO)nd2u}mXYj@Y!)_*Y+LH)da(2pzsERbha> z{^wSij*fnvS9@TUkf((@Z*(jyoh>@Kx0V;2oIbd2Kl-7v!yCDQJ8m(t+_ZUat?<~R zj*07!dRPRPggrN>eQS5mKb3wdZ6Lbu;Y-C&a|((`-jP0k`|k554&Pth6NS<}JLlrl zMF7|omoWsyaTNHk0)tf$u$u61U@JHH0NG#nK!5}=G*bC2RgMZ;LO-8J8LVq|-z$p} zcHi<$U+g6cyZ6}cpyb-)RL~NhP4sK%D5S7?U#*Z?^3EFN*+0CmmY`WVj-7QQz_%R) zr-JtQ1cT*`mT@_z)sjCu>uqLHwHlKfik%05S;cvtrh;~APa$<7%gD~NGEcMfm~gMo z^Jhexp2TpoBD%!k4Pr$EBmHJvW?F4-FEO!ZK literal 0 HcmV?d00001 diff --git a/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/ZteEpcMmeVf.csar b/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/ZteEpcMmeVf.csar new file mode 100644 index 0000000000000000000000000000000000000000..bf0e775102a5e5a20ac689edc160c5c7dc9f1c0f GIT binary patch literal 4790 zcmeHLX*`r|7oQ;+TdQTrQ+A;=CHqce8xyi-A7h5GjtD7}JsJB}whGyoBqTz1T9C0b zmaHLU-@T*f?a5O;AKnk|x96VUb^mAX-?`5Joa?&JIoBCY82KT3!2U(;tqS}0<-a#- z63X9j!JrXH7v~F_f64V>HU1_?OOm^SLSq~-E*M9LACe%zeM2qSP|MSjEeZgjhaUhC z{Yg^U&d~y4r+w4H*#+ZrbAPtZEiB4e8+F4KgGA||?6GzT7nI;FguUGdLoLUCwqv-~ zX9Y!**NL`6WktRGd6-Vuq#~v(0Nz}%)SJ0Nv#Q#LtBL0r8nRfb>|9^X%Y=^3iCM(3 zgSBFvn$PREKMBH+?}=-~%Q8P=@<|qMq1g0mY3sG*U_dqH)1X_Tn(v8kAy3u@MqRz3 zdokY9aJ-prV$u6^(8<*%0J)LKMmU$+1#MkObKqONj!>!^+`tgU4AbTqrG^z-_aHAi>fiM&vu=h#WaFD zjRi%`s==l7t5UDZsvgNm4Yc&j9`{|*MkZmyr?ovw=&%{O^?aw~eF@m>RxJ*j$Sm2K z1?=aI*-w=lxxMp|wy{E({`&QYI>!Ac@Q%hZjtG7QwY)ekVxe$qYl&H9tLzZ&v6-of zgUkuzVG5>!d?Ss|l~^pec^2Q^nneg;@`3ZHwkBKZr42WHz8U(!u7TpcZTlMsxq*z$ z>#^?*o^Ia@;ag>J^r{kzGa98R)%Lwq9U$j2zynN3ts<8YW)4ifhF`5kJ5Ak+L?CPy zb~;y-^xA9E(Pe|%PT&)h5s}deR?&P($WxTVJ9je|fchKhAjYG5nAdkYjr>mCD=2=L zJ8%SCI942rzv@y~b86QuxEI;Ar5Ecr~**7A~Cgk_b(+5okjaY-t!y3)_8Jk`~(Oamu2pE8mN9Z#ym_7-Nc+I zXGeE5Y#YHR6JYSchdSm=>{v z9UDN<2&8a!>V`fr?s=0uN06uOS5%| zbfxrItW{nw!XKV%Nv3E&G0@{`0e#2oaE*qW6Y106lBjhScNmP&tn7_X$DdL6af`o3 zn}hUV5lSxb*QZC6D9(s3J?wTn-<=LSmYS+8(rC&02JQa|DHvFtKBn$;kB=guTojuFAu zFKwKN7lex0gnco+U9UJeO{3XXNhHUWAAg&o+1Djdk17puJ%WH|fEd)UCrmrmXcymi zWu}ZUAl{iHuQt(<8mdfxQ5siPJxeyU|$WtvZ5Sm(&48EmIBbcllzC;5;}l#i^s zy}`cNdX$@}af8bV_Bgnkl8L+gh<|+Rko`heXBz%(q?n z^=xa2=#^NS3F3tY{ij}>V0XEq53hHpV$Aru+w{`@XdjWH53VBXsi?idE*lP?ACNAk zm?aK_Oq$%gMHv<6CZUNg+>imF^*OjVyQ#mK@t5Ts@sPyz6AnbP1qlzb5XuG?axTIX^aU%o=HYlj2D8XxCfy<9#B@_c9CUp zJ2H0-87wy}S|QP5nmPR{Q&@lY>y9m%82Z{+%G>p&uBN~M zE#Xe$5$BvebX>n%+hbPuUEuf10|Mk5X~8NwhUK)#0RUAh0D$YKdICpa9DY|k(sWgw z6Cm`JTlx@!uZD$}1#RU`CyAsi3@_%+l>hPe+EhLj9Z=s`_u75#x@0_I`jF#L6(h_cOegPSeP3}2%bFpdP|#&{eBbg-`TAM+ zm2|5P787gE&D^bS?=iK}p>;bs$&8DJO$74eGw}ZQ*~FcdEm2X?GlYm*mh3RaoeRZn z8~JN0TTyyR!wb)VAY4{T-ca=7U8vpdTUj<9E7N5eHtSu~bPOs&dXL1C+S1d;DcP%9 zR_T#>U2MG_$?{#dmpv0Icij^ziB+CYE*cVyqiY7>OAsx)3=^t}@^&+mnfnvmx%`l5 zZN)rFcFAmtn2FWZo&KaK;3=%p$uBGl> z;Kj)G6sppeuUyImeZ^$A?br8)JFh^=OlH1$mvG9*ldUnQGm1TrA6sT2%uvK+9vB(b z{;)$bTx^*Z15aojb5VKU`#=#DAv-c57F_J?Xf9t7aKhTxw5z9g#m7_bTnxr&{E3!j z#ieY$GzlUKePvFwq%6sh4^OLI2L$69SswxVy2>fb6IKgzUTDSLCc>QEh6_q`~7~)45mk??jzex__+|-|jGsQQ)z|IIS=FD7m1oi+* zjs*StO?;x1IbfoUTrZ1ge4^M7Vk##Js~5TYSHOww6#cxzgQc8e`*E!Q$`w z$JJlj3J$4nj7LrlMd^O!Z`{>FE6q7FLicvd1ZTIF+QCm_CtYPqtsdApsZXZ9kcx&u zs~eX@$_)(T!n(1sIIlz#+;LO51#hTYFg3UE zv-;3FiaYVoT^zNL#$=br90R>0kN&X!=Y#_O2kZAwp#LV3f0M|+N#y^KL;!%FJIbS^ zFx1h|R+K*vN4X#@5iW?o+D{O`6Q>T#abg{@B?)P*>MnUj2Cm-4aX+GkzlJim2{qm!F_PK%N`XaxXYh!$wCpBR}GFiYs zwbJ`XmHq43pKzeDrUtNmdjv+?u6wePl zXvoj0nd>h%_YFxo{C78hS911~_CeNcDMK0#5-Z(v!B;`@Kky*yujTBZ`@*EZM1IF) zk3Psl(0OBPs7L@(=gLRz^L)pHJU@E}{+oA8|G@LVd-S{5`tH&G>*8_bmqcImCszqy5Tm-#m8J#A?Dpjr7j?b%sr_lXZO9A$miFIv&K zDnPB*PFL;6F&$HHgK4X^dS@lh*%FZ!a+v!?#hwENX7l_{-krj-;-}}Wq}7VO@0R61 z=LiXLn*H=;Xyg|wR-d*h>g-GR>?-ooUU)6~kwccF?2>(bS__zUlqx>m{%vwdy?#Y; z+xo1Y$`!VLk!~mbn$)*jES|M)$AiA_Cqi!uEL(C+O73l+nOC!=QaR^V6`$)I{BF&0 zOGLH=wjEe(JSBpc$1;BZR}CSRjej@|exCin_W8Vtwd{cd&S!Z&R@`a)rWAEOK{l}Z zMaqrbTY|ejoD0*jom|2jthZpbs>tG|h~+$Pb)g$l7k-^m`z@?qP2V-2uhB8|%Tm7d z!YX{}?EvQ8Hr0REEt7trvi>t?Zn?3PDr{d_*IM^%Ns zTh_a;FgN<5zu<{z`49E2OMY{=Pk0*i*nPv&pb3he`AJrcVt3Id^a$0?F3>m zAjX!ka??V4_i`OF5NZAHbYF3Iz$8Acn@2qbqy%CPsqXYLuz#w?`{SG1$1*Ob_HSQ8g!9q! zhy)JjkLHWfd_h9KU|_g4!yl!X<_9LM5dUCjM_u34lEjq6l0>AEI=NWaTlCRF;Y46b zy#$zpBrz3(_3GsU^`4#Kn}5qd;`sX-E2`^{j59>UxGFI%AWaNU=^<{36ci$5)3PChnsqxq|_;^+KgLOW)B{P_B{&a3)r zN6V9!+!lKqStQ3r7ck#pX^y$|(&f~Yqf2J=r_WJxG`W0&Lsr;jyZ7JvuUAX-G%}7H zH#T`=rOM^#i8i_{o#C+D6J?UoHLuQ`3(dD)pMOY9}PhpY>0OboN|^JjtSp14Q++1u&n04Z@z#6z7Ek|?yT|r{=%1NJtgZ9Cf1KcO6}tXq zuFHFy->%voCqJEPIoZ79bz?z~e)K)DnR8~{^3f|gyZ7XBqr3edRjV8okEXp5ezkWO zUv~BEhdt_jFI8{LTTX4d87FtCr*Qt0c`T{nPd%q(GtW%^;um>2Gdk$_4rS51m2vrV z9p;9ANo>mf-O2rB<>PeLHA%L~`By5EdiLz(&);Wr^L&k+JFAs|$BH9-I^rAlPwTmF zzb0`tQ-_ibn@!Tm{)hsV%1!E1Q@4pHSike{Ip;CUYD)6{+zlTlMkKC$o+oWsfEPu*`Hm>sJK4ZUvcmCG!@C6^3_RpRCI9%yW z*~3>cTW>$r5B_$~F0k>0mvLVH<#i5mp@F*c4_>`_&z@BC?R)W)82<}lOC!p+glXyV z2QL-fR>`z$nt|^3$5zT)L<(dNM()4!Cx+AXA5(xgBa=M?uGR*q6#)VQ5DKO3!Ns5e z7G-3RV2FI1QhC_>G9x;TFdbV91!g+P94#P5ZrNa~RzT%4vaRuN{MzpTZI$Pq*9)R= z9^Ll(GLS~L6|>4hwzVIa2eH|dn}%!;w-V2Z!_Jo(lP543A=AkAVAd_j_V_Vlw+EMx zKFVfwWA_oZ!Ukp&D3+G9ViY~dUfIaRyJe~CWkwi1?=}yZkL(r90t#jUD59=lT7W37 tkgYn-8X6d>bD5FYNb!;0Q+qP}nw(X>2+qT)Abn>V7zV|z4pL@RZ?K}RARcow_ zG2gkKs(K2u=8}^H27v_l{YR*#F8RlY|9XQ2zy=VocQiBBH*|EMQ&xfi0H!awQJ=55 zQFn5M0ssVg1Oxy8LH=AV_kZ>XRqm3YNTf00?g9Y#EhvB4!_dLdSl7Xf*4@nZkL`My zsMWWs|HF3a+U*km3<>=6AAM^FGXqN_x_^A>zpg_1r&T8QHcqy>&ieKae>{K;00aOI zK&>kwaYD1-?)14Z_fxR`{R8@zmb7mAR+iF{T#y6w@LxP~`b%xeR3QC)1zv#K0@NS; zg2bo}oW9@ghoWnBu_;C_x$D7N9FpFfUJq|@dTd1uHdm>c;i6yzmjtu~4K4F1+AT@- zgy22XD@M0YZ45rdWE9w+KV?ym7BF-wJUQwIq-n!f=3R_`BZ4+gWygFaFA zdR|inp@pBlgIZ+7 zpCxe6)!}{M(*}b=7s?FKPPP-kQ3qYG9j_x9vi!dDTKS2RbHqWD%>^tIQE5Y&PjHiu zX$QZMe0wHw0+`0S1&7Pdnr?D0gDN$};$K9h%ZOhY3oFtXG|1FX&)pVx=ZF1R@0>fH zt5UNqOMo{RPo08!<7{X9t2&oshLF{tYV3Y8i1h!Vj)S4T<)4Zy#?(Rf^Fs%_u1{t)Uu7_YaC^V=VTOKye_ARCP-e3gK! zTo6`5V^>X#I8ewdp)XD2>;XX6+@q;XM-SG4o_Bp7jB2h8nB<()4YJ%Fb5aiq>@+iz zpPc|K7j?l+94yRKo1yz}e|29kEvhWh0kU{7(rMpm zTv9a#3o$P8A+6BvjnTJf7Uw_xr(>LA{y4W+siD_lknhs z@zG*dFn!voKinkK2}fhd&31Esvh@#bNHt0&a!WBjD1ZR~+CDP}*?-W+-qDuklZ=i| z4u3H5Qc1gFo*&-pSrz&*50bP?Re(M=Bm$3|G92#(AF+9qS-pK#+nKa#=-kJ}Sy8d# zxg5>wrcZ8-vBTjglc{8~{z3yZi>MeVvLY#Ly9Tf^oC|tUV)1s6lfp_VSCAKwx_$vF z)$1n+R!6zH2?n42BDsniHTh9)3NX>3!dJ;P^|2Awmp3<3@=DXJ9md-75umAbV`88S z{&g4)XZ@6;vf{Em`MBz2Mir(fh~pEp04(k#rgO}~aP6WXRV?KFXSO6c4NR$01RJ_j zufboj>$mu@NX;pa?r5|pBxiG@vY24~a-dJoSK9Uj`XF5hdyAMZixODWMzL(>EsoaO zES%u)gwy*KA`$Y22|o|Kuj*vKYffsTn8~j#Zsj~XM6CY^x!3uD<)AJLe|N7r`r5ju zdEt$`?SQ8rxwa}UQh9aSv9NWj2{N#g+g6#X^n3vn9S!6`eSWZ0Jb#1aAgb)vCa z8^Bx|Y0aXZ;2U?I;B(;cjK+SWC;lbyi8W$Cg-&PR#hBkk}o;NjLUbAE{XxjG0Gr^%%qVt^vNCRq0Q$t8I zR07TE70=tTef{cInn%5RfCZ2jt<<|&#(GrjJ1->Cvh<~r9t7>+3f8Prw}bk84Ux() zKJ2yCBOp>2p(GG(2gT*kprF6sO=pHR*CoQsr)k!0pIWA^+ree*5#>ZXWSK68yoeku z5#aWrArQUxm=3qo>j@q=i^uKhX;G*&DM-dG##zuk-ngjRPG{~M*t!vm+$}3s7_=NA zONs8JYVOJB?4#s8M)70wLDfb_@TWxxXSH6s2o7eQellpMxA&8E-GZ|pUR^S5W5&uL za900??xT|eD~6ks9mcyK_nzoQO=Pp!F{st}=JqTXju+rRqV0F7A}6}7@cN9hhEE~+ z57FkLZ{|qz8FGJS{m4F;0D5?k4<$Q3onxTb69SyvFL>c74$T)t5St_3qTDWxOcUJn zUpDtnjq(QnuZ2;IDOS2&dn6G_w!kZ zt6=p@+=_4GIT07OHxr9`*W5ezf35C8xuC;$NNzr+7W zivO%ze*kY%l(hLw65X$=k^aIO5FIhVVpQ&>{`@HZDtl_m6;V9S$txX8Q|u%XKeyAI z5JwWjq3ECVkL&JVy0e(26Od7}Q<2fl8IGAtIy?G{Z>|l}#{}ZXhstw>RMv z``BzfUU%CCM<6bWpjfxq%bWbaI7psdST^`2Q8g)PxMW3iH;3MM;9`T zb(%R^YZh2R$;wL5dgz`kfuTNH)*N*weDiBGt4jTvq*~mp0O%CG3owlDpj+v5DrBhE z=W=I#V7Q)pJ^23Q`3>f~wr$5&7W=YT0Gp$XM@j(@EDr9Znz{kBgv`R2*jH6Q7L_`V zCrDb_ZKLBmZQ|+NY`2#F-T^1QZ8j(&T*0eRTmfF;bM$h(`c>#+%k6ho`{ma!4dQn| z0}VC}F*l27u8K2IhX>r{=y(Orh*CmrhG46fvht`7)>!k|(4M-|E+oYz>uZS5lfC#M zE}JD+OwW?FjDA;D`1>m%P0__G&q7Cz0$ z(o9B|tIx*nhn<(j1HpDgp=(w#?+h8|wXv7F;2s#g9||`GK~mLfAx#ZtR77SyEAC#$ z013e!uLhNr(=)?Cjdvyrg8oUbVN;W!1XWwRxApYW1B z%=lHCpv$uqrK4-fPIyoD!^iaU0B@fS<*m2`$yLJpj}Gk5&iG#&OxS-SvAvC@(VxBL zzh8^}Ki2;4f@%Jn^8cZYCH#Lp>8S5u@vmL&4_h7qn9rul?^CG$*7H{S{}p#MG4j>{ z^w7cE93rrKthI1XD6GV zBO1KrYf|FuBLlPz3^3q64Br$rTU_&igs{ctXnk5oBLXdD!y4jRa2j$bsx6V7n|y`Y za?;}C644kEdi_Y-t(2qhWLuPJz#;^lyJhM=HkzrD;C?m2ep50Yv8eXm;Jyr}n|3)* zGp_3BsoWIh3XKzM+7z;J|W2lnzS zeqTZ9`D+4Z(H`QL{j{jkXA-0NTUPz2rbj!j&-%0d4!-t+jDTAA1LCq&AcjSnCuKI1 zTGJmPZ=@X;-lue)g}=FSSO+Iqi@4`__Zi8SBE{$h@voTe#e(egsYWjsW2s!Go7RMm z_w%-T5Dg&Mz<5D0TahXmA-WJUf`at-F_0vqz4k>4^PY#auf_)UfXqy&u-e5k@d7?> zm^H|sV?`E;nRlcvRj&KK#G+$ozuA$c>eTo}R3F$+!9eJ+PX*b64AeVKaBt6|P-S(W zIxci>nEnBi*^Yk-wEM9#T9n9|oc^hG5XYM9D*^C*NQr0h2X{yMa?3rCIm|ru-WNfy^_djL@G30=vy~Lh<_-frM{XUtY+U=Z=EY+tje-l~ zobj4NDo?qvig+7pW*OQqXh|^cVF^P`7Tr=%qg+*rm+2kj&S?7r?w&qtZpqz#KEFNl z?;{QWe|Sd5$Wg%1QQX?m$i!aX(agsBKSbLHqokzl*rsAqJz;Pi_E#0040Q z4FrGgVQ6FRY-I09<7i~{d4&6YP_wekQs^_s5`gZ)dV}jXk~PvsGKC7}NmMu~YAa01 zPQI;N;xaZdj%$>b`rf0;l;Nbs1^?ZOcrszjLqR=xdMLKr>_ZqhOi-T z-(Fsj9=AoW#Kzgg^VEMQJF*p>)>a+>4}07maHd_y4yIlyCT2|`GKq87VyJf>>19Rl z@$nvX&x^l2zooW>9To+T1GYCGxT38`p^ebt71(tn>AK{G!o-3D_61iEV6>MjQ3}cc zik983csfA$q?x=Km6+vSPZ5SU z5k&Y0A)5oKPOoZgE%wxmd9YaadrsiKH<_{T#Z?@WCz);$%La|D-Zx%A+gzuO{FOiV z(bF#rdnR6Yj!nlZ-;r9DzB3!gdM>c&#{@g<+BUf3IIH7CIxZ8DQ;ugnrQ>8j-Ucn3 zC{A^rORW%zh0x=>jZ|LHUQu)XFlyk~e9e%NcBzj2gMt4znFBURyo-JMfBZ8yu>LRn zZ|g?m;9yE)VdVCw?>npq=%F`&5AZ^%t^L+kVI051IiAkQ$65^|8c6yJlQ;!DtV@=` zrsJDJ31_^ta^b2cAKJ_N#}O^T$M)inCil8^r3BUvKs3Ae9s((7SaPTf{p{1CJW}W@ zVyTS&Y8#M=Y2lJTk1JEs6j`|BUF@N}@5WG$%vSW49b?U)g z`#Y^%m7O%s1Reh&6W%%a8tJy=>2N1tXR`aI#Y|7}Wtv-#}c|4*j< zZM3R52H8)e1wBjrf-AWaorvR9hK4SZqSr`%jn6c{IPnw@Dt~t|Rbawbl0P|l&Ys%d zWE!3@3C{Nr62T5>1a8ww*ex|3q$m;dSW3>u#nl}}*MP|MU&{CqN!|jUmp`=2kI>nI zLp*aUc6d2bt8HWX)Ss2zm0keVeB>*uZ-?nfGT6}jg51KbQGx3HjFrgxGhAh*Cs^w%Ec;$hc&{+D_os?j^OfBoWZ0tpLz?I z|A!(`MnH^1q;*4ULoazgSN?oD24M zKlUuvHbCdB>)R!iVy!$vUM^L4#!22vkADRVEEc&P5Nd$0_HGANSLTWF<2q##FKd?kw0lIgk!92oPU60xUvz2lQg)E1w zo}(>EEKCU2vE3O=k0vvovn`jMy0#bf%A7`Xe-;Q?=DNEBjkEXPJ2Y(rV$;BtHxSgH zc@oYa5c2Z?2e_2tItd$D#)hp=*ipd<4wXPSlsyjmcW^{ixAR)m&X3x4WsNb4$E^6) z+1dXj&Zp75c)Obv3%x7t^wA?Ae0`BZ5lfj z;vi|1^UMO#jW0fyD3&4WZbuWv)6L_RjPRkM3_KCuR(<~o3@+r=1YTSpqM`0ZlBVC( zsZMNL4daYD0?AC_`a{>>W5qUQ723|Eb|Xsw26|I+yTIHh1TH?q z)%vYdvLBE#>W(Fghp$ElLb(Pgi6}NwPoN0Sfi6|X2z4J6Wp`75yp5a9@oI^m=Q|pObG~u!@gA7 zP;liI{{D^K_*PZA3+-~?yW-j%poAyt7T6gkdmV^m3RFIk4_sRYMh2H$5hfoP2mMF_ zoOw>lBL?%>SX5m?;9`WMdCDVv4D%?5iQ&c~v<|jBSn+T$JNU;&rd!y zs$b#44i9#v3F0c6=E>9MfIbw1KA|?->r<`CzW4o{{(`YB&y1(0K;6@d^)}Zwj4NLe zP^q(_9|2$uqIFB!3Er-eJjGppdhBq{tLLRltQKI73z}G5_X#%7(cW~XDpBA3%e_c( zu-=b}PZpf~X2joSgRQ+0jiITLp~Y`9M8!&5f8HttJ;&LDvArGu#HrPuBvVC79g##P zy3VZlJv|wfnj-AloIe*#*HoX^lSiZnk~J1~xDpp4BT3600wTMoqlEd#3m33E83`;n zplhZ(swrcwv@<~(pd)IA+QS}HyFE0DOet|VZU|^_ie0yp2h%xZM`d{GH6S-P2xQFT z@T|fmpcbQmIE2XPs0>{)^Udajd5)C?f*QH#Mk}qdV-(% zw{~x6$r1%4`h-qrWVG)9M4PATLW$bi9n#_Nu9A>ZgcMyu*|vXuJa3C53R0s1MQ#`Z z210|XvqA^VgN=f7aSK#1IDDMcCt+=`wH&a)3OG1DXZ~TE%RUO z7G3KPEM)=dg?kGH&<5JDUK3E?l?`;$`IaJeH;Mq~2ZucFGl7GCMHGhOeSSjsrEQBvLgmN zt6?Q>W-};iio?>gEP%Kj3MWf|b> zH)K|pzsv4FRb6r!nF;YpI-1$vHTSdRPK!-8D2UOG(b14EjZ4zhjEYZ6(v8a1D$?)t z&m^aXNUO@5iyO-u>u|=a{7V7WqRe#V{RG7KDSw|ze*pVEUb3=;>63@_r3VL?@sTBX zZ2@*ogJ*)D7%~=UvAIS-fOj|N4q+%xGQHe8e$oaEt%)4yG(u~HxPnn7FD;LsbYMf_ zVpait+|GCEBcrV#JC4dh@%{>@)!a`<<`ahEr?C8OIREJP{(p2#Wz2Mc_Dn8RW7Ch4 zG=MbuY+0a>qR@RtL-HeLQog#6|SYFLNJzEnZzr~qQqcnUI?obzA!2{Nina zvSzPR=6jfcNL)?EmdvKTrNhUUW52C_*!IPdq0!_g^p=nv_p(y*P;9cnb3PM&>SJ#*3w^x}=zZbWGVuFo-*!{_9TiFui6j%kL8nSSrj=KSB!;Qsk~>i>3L_%}bs zICcHd_#MeQpYnH3oPTWb&B$2a${(pu2-0$8>N{6vvXp)mr$6GK$K*>zjtk$V{}m1N19jM zmt+iAh+w*NP^d(XRB&zkCs2WY?GliA*D~KJ0RSqV0RS*R4P*V;= z$lB=7*(R;6+XdDShdbd1m-lcM8EJF`%f)C$6_MO<)HRA1H~fTEQYdXKRtBs!IGhic z?ezeXKwQ_zf_*l_1h3aC!x%Kr`=}*}qbe*~4XKR;OYM!~{3p`W${i9it2qRv!EeIL z578jVVA6g8)57i}W=s+(PW*V(4S_UiHF?r z5am=poJKYs;!7YB0Hx!T531J57ku<1;q1T+fBECfUdWh*@ey(de9e9boEZ$hAq z@I*mra?7S=3uk4*+?@TAFsYnP{C3nu>VZ=SjYAxkhXp>GuRK-FGTFk6mMeK_hsu!h zK&rnRFr3)u4eL~)7Eg;x-#n0tTDc>s!gO=wkAikHcGv5pWts@tN2tUtIX_s#Mj}_| zkqnY7{qghXU3+zFeP(7Hr3aUK5l-Y3-Feff-U^;9=Kxi1vj!_0oe1W<6M%n&XS8oG z*H2zMYh7HBEDfyV(6y!2wTp?l44LL^AYGXxvbq36FIHZkZ&5p_Vk z=W7OHJEh-dLV9EXeVGL~dYqw1;u0@7LWDmQgn+4Ps&8@GV9NEyBl0J{_XB;9=Q0Ww zoW*wvMFR=2)j-&&G`$?qeWJp;wC)){1A4(Nha2o`mA9ckb+`k~z=$Ets5jo-?o#OL8O-$JM-cgq% zkg;c3vX>o85xL(7ZUJLW4l?zM$cV)Gz6P63=o!SWQPpte7IVqTRc8 zMpYRJGp1MUiZ1?o+BsuGckVv%@ekJ|!zQOL8c+G&egU0T>ZQ|uJWgg+BoDGB_|?OT z?f6JF{xCI7A{~dnwmcOh>5gEsNyoVstw9ec{{X>1)t#SNGf49`Z4wF)g0BSOJc3

Z7tQiJGrva$?pW@IRKiANVkKxAE4hfW`K@NH_{N;_x+zxLi^S5oIw#x7wv zeb%N93PW{qMO&pS~oo%{JH_S}KN5Gg@N$s0=i z2sQZv!WFIzHNCZ&l>A+u%Doyn)RF1}ZvGN7Cb_a-kZ&n5$I1W%Mk(zksOaN@PdBU) zuha8X>Os_~B?nR!S&BWYamE7M_s{BDjOQBgBQC-gfPbc%MbvfoZz*4&-{dpRKCehl0f3(FE9?I4N79DrUkVjzF!I{8#m2yMp;n}BaAy2 zUyHvKCg06lCYh9dGm)P%?b|x@V)75?=8EUvPar}}J+qEg>-DK=e; zG4NGCcDbAB-9VJzK!6ylq%@Iyy+jJUJmq3A>^LW%2x~Yb4F>H*syvZ)!k6(~kF4Pr zZw3Sir$x*3iU^;Z!{5Zp5qtQohw{G!xRTu3O(Ket45)sKsFl671vGkJLb(e@i+MXi zrbc-;mb59QaXot$eV^z)f9#KnA_q~TUTHyo>sSJyMzdEbU#;Ria0sG*9Qk6&JeR|w zsvdmlbO%~Fv~SbC`R;mgT^>yA@nuPhurJ!;!{U`Tr4@=nfG&k)94e((m`LVNPMcT& zGVGz~Tr&t9s4)PY*>6LU@9V706ztlAet9)EHsz=zC>gvPt5yzig>1|Om@gyd6UoUk zHOahM>6GVBLd^SgHBBE-=ehm$7!goPbyMiOdqZE016#)$rC_PJGV3zSn^ZRUE#LP^ zkMk&z;7^q!L~#V-ay9TM3rBICYm(_#MlNtUxcjFTLRSx%%PY!Ljl|oR@X9HNM3``r zmnErbesQQ}sRO+>wV3Jpe}!!$O}JwYa^Pa@M;?*iK?D_@^rywo!lhT9QPR!wD-ZK8 zO|^wsND@{{}frEXw z|F%FJ(Y3~vY`opvPW>>w0my1al5CU-aOL}sXia@Ts>a+oJxcqvOOA3chFd7E3c~je zo^)uV^F>?DaBC`n`Y8UI3+t32`|#GaU1eJmY!w&{rSPpvRjY7F2BS|S5wd$(>2d^d#{s^bOj zE{T|hHB#4)wx{h`k86PY!by@`9-EaH0gA8BhH4Mvo~}qn^RZjT*&Y@dQ@3mpa_wr) zAB_{McP9Cs9*sU&cCpr~wpk{c7dgG^G^Wjiq#;5AyQ*(eGcPG;p3aT1>3xq{&0f4I zMvt&Ftb%2YB>Pv{VuvR$_J2NM)WHIUgK~UMLrTal)$da{LK=U~oD!}CTuyg&0Pg7z zKD6H;Sk_giBt}`ARntZ%_m?UgMVFIbaJp&2TxfZX^jHgqM2y3;a^M;!-2RFkwwo%1 zo@m&r&h9mh1e%1)#Wy3^P>&1m1>ij1)mzA64%L_Ebg+VKjln|Qx)70IrT$Jct`5v4 z{9`TLp*|;8R^D4YJHZSAL&7mLQ%LHy1-fxj`p*Z+Zpo}GX-h0DvcyKG>kbpk zq^GAPt*~mobph5FLYi!ie(b(2LI<}W+*b>1`ZsZwoE{7q*5vPg`L-YIiNjTBYY|D0 zKUOzo5H3M+*1lZ=TZyPr(0q&I8+*{pEt26^P10zG zzLcoGj^iQg)<*YS-|&(miZ~@SA($4vdZ>xoINgSCo9|(_FY%$aFNqPo%I$CAv9}1! zTD70brh48nci5FVUXjGN>MW)zVk4Y%60b~VqlTL&*Em!XriL$$C?ZS3v)? z=mrb$17KE8i?k)u6>|rJdcO8h0Vgj}Gf4}G&NY+~Kh9mcBGkQ{bC3nI?(+KDZ=pMR zqv~Wm9FGv<^*!UZodshNy(s@c(=^twkegAvWiZl}6d)QLHdN#Am(n($Oppc-sd=FA zqS|p{fMjh?QO&B~NRWNdp~c%K>3iG*0SxtqXSzr0A%r5Xc?#x8edxUMtmk*PK7VQ3 zZB_}ZCS7aAYFS9yqhigfxN_K`LgA9~h1!Qj)<{V(Tv?bOm5u`qgByB00yPXcZ4P?{ zq8_Se`(Zzv1f+0X?Ib-zD`Lt{A{Ih?xxKzY!P{Bg{BlQ1cVF-E5GTPFlIEdNbm*>q zT{LpNI8Orl1rk#hJegS2o^}6zlVy0!s7L<@m8N}YHdr`VL#1k_ga0#_b%X5#B!G@A zp@M+BLaLmdE0T~i=YZKgFeuF{y49TDt+@HJDuHKhAx zE){dU-YrVW_JFqCI9^}24{smlPYHykPd(RJIhAO3#kGrd2w zR`%_?AXh`>*dkmaDN>pXbAK>j9NF8vLqQDdAJh(pUO=?>z ztv&#;ko)sIk+LxR_uf7mJ>E{UIZ7`BN-Mhco_)fNupP|e{hM0cPT=f4(-39U7hn=! z4|7q%Vpj!4&7j4VP+E8_curI}cH|wPpbqb|nt}K+UBd;@VT-$c527JmDk%K29DK-* z$J{eO{ck*cf*1s4@Dm5aAj3hx$pukL*zp8W+WLG&V5wxrNZz@aJRFy}&JBekVs`)q zxbG*Y>Xt7qh8bRizh3TXwrWfWK4HjkIJhOaw5xo56|>AvolWE0*C|%iDzZ&p<)(nt z(^D^$Gl|iA_DN=jG@GZ`eMK?m>N#WFO)3 zG;T@rMq99qQ%g(^KEXjqeu3lOtTz^Vb8~mb5B-7TlxYKkWP^K*oTG*;H5JMak)GLz zoja5TScT)H1yS<=bjLAuor=vQmRGIWnCFY($P33yR#K(`QQb`&Kq#A6$(HeDl+;&< z*$!{9F~Yu+5rZWJTdN|9sunzS2z7M^uA9SJk~6N$S#<(rS0XJZ&G`ML5Cx1)`JNHk zkwyIpubr}rpFk~!CdE#eMlPUYWW;`DdfxmXb@64 zpLIPpb0Z95Zn_Tqr67$UTZ^$W{LX;*0?ab4uEruU%&`44&NDlPyq}Qhqdx#Ew<1Qy72=KLwU+ zX6c~hSB>Q+(8jZj1()En1Q=8Tl+;9z037GpF=K6Tt3U>YIy?LgyC$mP2XU!p>RDrB z=SJ^j9&}nlIDLta>%8k_66mPEq2So86-lNHMj#rR?;{%5AU`#42Y3X_0zZ_M4nmZ% z$%>(rVTJR{Y#o=+Z20UL(2VscUTGu2Az zs9aU@Pq4EMxJ5XcCV_W9XV{#nwqEIzDNFzWGzJ{31)_NNfYTZG3uVi++O~-j6(S>; z=GN=I?cPpq!&7M)F_rmH$#FKg%0q5&IC^3)a`Nw_FSSvgs^>3IQ=Y3Q{4g@s>{1Np~_<}hHwY(4YY9oGzfYs>Kdm|nwN z&96~$=!iD|IXw$#oBpkaZ@lYMe%@!;sa#VL4`Um5+#0A$?GR3fw^5~B7^On?8SpO| zuDAV>H8uo(jebNY(&1nI2H0Dx(=9;4#U036MLHutlCfBIy)FlNewINg7$C-SDXr^D zHue9iMJvT3J@h~wy;EEZdmS4FVQu4`IRq*eRxK{rKM^6f!>h=w<#Oss((E%%%RR^) z-@}^3dmd@`Z+Dy2L(>K`240mAQGa&`zhw=zX?qhVw!M;VfZONQOFfW$42U5cnM;^3 zpPjyK(Vgw?e4n5F-qDu1!h_BGvGZh2Ax zpb<%p9RdTRQs)t1&H+}4v_{s6vFhQ$XPmBA_y!Z+ z>Is1kH*N@8QROk4hZWUY|B*91g3}YaFu*Wm3$i>x@lW@da@Xr zg~E6yms+g44O)Pm;U!B(NTj~^Ygv7!R_E5EuvPvU2lpK40j(9GvJ2ZUkoq3d?E+M_ z7~-}g^*l1$E4s(QTBwDJM(Z2_9?kXX_qsu(b+&LNLP zt}iIM=W4oMiWhqxk#jf+N1 zNFJ?Uf*`-Y_{@@253x=U-J1}|-|*@Lo)uwIiZ2qThrQZRZiXot*E~O2p;Hntjnm z3a5wTYjTQ)!5~dsovXb97}sELvj}8H;fWJeM@(KwS!}vTg1?DlWW5uY=h9SkmuXV<7H@h2 zkgiy7urc0`Q1FdhRI<>X#+Z~PWCL8nCFo0dMNsd;g~D6~0F?#$>Os-~iqni5;+3AI z)7Jk*g?h!;4d6klJ?Ufzai1?1{hBbY%J4i8vjql=r6^lSb(7S~1Z(2aylbj4{*YWW z{X_!Azo&)VY{2Ug>~635&fDo(>9OH)hu#;RkA2eE@!QEV5)`m#*d0+PZg#1A<*@Bvek4QQd0ve1$16s zHP4wfO4^c433JftQ3f6GCcjDy*sm`B6(kjb^Vi7pb%bs|L@h0!L6C#j_-)ig7EO;O zZCOI?9?tFOR-`dg#9x8kWr7N^Q_Kv&q^ZrONLDZ@ExvJ`kD0OGUa>G=QWfigJKK9a z5wssnH}ODW;}heO=#AP{GiT=&XjQd2Fvu_H8gV z%@Jp8uG=_PG&s_gh#vl0Yp^k1IzuzNV5EE_ z$Vn;_uBaRyR_uElH_3xw50b(|&(6>U@$_;tow!S~cV(VEgW{jhU2j8F6bHG|=H3PBSAc9)%kB6{W4PZs65vPP-k8Tgbrbe0~$iy0Xi?xvjFon$y%fHHJSXCF4GLgVVCMKWj zg*T&fYC@mWlrtn1|7eG0BBq~84bR649FY~9#^W>F*(UQgx9D3KAM(Cr$Y0|sxV>Um zZ3xx>@G_`OegrRhkp2fjh!`9#9(_^! zEDycfJqw$KhZ4d{G-~bT38cyj@ek7O?$Z?>&o#IL!tkvAQ|$$~vwD$2&)LU#?a8e< z?~6ZCw{Z%n5GyZnqFd z)|%^=Efm*ZQ>Z+Aq|NB05Tc?ilVY%Ls@heO7MRzTKHPCs0X)c{jora0Th#qivUxl? z*ezh>&1{c3 z9vm0`RL|Kyg#*2`GteoT?#Jm3Q4N(&g@48YG?t(E-iJVQNLSFdv)Kg9RQ9As_`=v3O9g;E)#JHQQ z)DT25yoOeI0jbpOr#ht6Y)y(){R1;YjPQrasgHiLj$SHVIKO-^)v_=m;s8DJKrJ9J z4gAdW1UOlA%NTr#W+Mnz(l~vimvr^VIG&H;j{vVoIhq9CYxR>J8D za|sQgd<23T>b|PKS3Dw?k@nQn?;Yn^`EMjkUlK=M@?)o2H6N#h&AQ$7e>AjzzB~~3 zw$m1yO7v1*M=xmMayGP`Q?`e;xv}cft4i=MV(5_srjTQ5X_>sDo2Eo=+|)`4v~+7n zS3=$%NNirk8N;m}QNWf`sC^exq+}nO5^+rG>=8BmA9jLAON;utuuyI^_$*gOSPp`~ zT3-6)iy$1QH$hN3fMRf-Y8@@K{Epqtn@=#TvbWlQ+}v8JGQGMF>^3PVh^s_l6>@wu z>V*W)t)mP)3P~xn;?gM`*8UV&H2RWO6XG1@H^*&KLk* zAO-MCt`nTDC^PRJS}&@MG?H}fnDH$I4#FFf%v$F0&v?n@Ggx5zL{{mz^nF)xfBb8k z?p_dmq!R6PvXoMD$n*a4)ZJw=aR)+rmzppDl)ZV?ImZL^L84=Pb79eI3&kwU!BTLr zY2N*X)?xLK)TCC~i*WxJn27$LG*G_lX{hmaW?X@Y|tON(ZQ+QT8yEDfyoc^v8R)Fa}Czv9ZB7tnj(7xa3Q2w`!F>wz0&dJIxY*xoDAfAB>Lm-XkAP+x)^c=P+4_~t?uh!!Z zV2M>AgvpxZ%gbgC(#+8|!~luJzqqvp5VX9p7Qr;P(hgraun@Y!$;8~dSeFGT8j)tl z3EZSvpPoCv;~4PGi*K5ca#Qr);#&m#=;gQcl#3+kFv{8tQD+M^U$-a4)ei+uMQ z(fGj20_N0o>bg=2xB2uEZ013dJaq{BGK(0EnHilXcB4#R8GK-8>p9OXA=7j;k7I0y z&R6)5HkQX2g`0sn!>>YV2T{I@u1;(xaq-v^!t$K=`S4% z<(_VI`F-ej)Ayh{W7PF2b5rBb^ z(BOJe<3o6Q;mx7zL;PXJF4uz8+_hdGz~pvXZLYIcMjoTz1Ol{2Z`5S_T?9BoqXiD% zcf+ng9*g1iXtTr9qg$z@JNf-PH1+YubyjJ_!{!vXcZlh119}KnLwolI z4(}YXLhNI&w=`I(o|_H*cZC3Jv6vBUN442sKfBcqr6@#MalCH3Q+s4tE%@KO8#HO+ z**Fx%XEueSb%6reOO{EEy2p-3MiI8Kx@D}$V?@gj)fYAZORIE6EK`GtWK{PVY|$qN zhkGtB&XqEaJiEEK`dQE4E1Z1vc-k;BZkjH^Nqh5n6C&)1tWxuWGvFKhcNT>CWhC!C zoKE_1DfoCWMrBUA^a~*f=WKO(G35?C%>W#-S1dIRUNE&#myCv-QvEj)sb^RD@Z~e6 z_^$6RTPQ9V{p7&dx=HDGJwc}Q48&jb*OnCw)yf@^AOSJ4;v$edyH4kI;%t=Sc-vHW z`SMI27IDw9l66~x9MXJqs8Q$9qKk$$)R+TuRE4J`yO_FNuzGunf%dqOZdc(BjlI0-@e<-JuLlE285ePKziYiUn|N6FxJeR+5SmzmMdBcDo)r+q-G4%|iAIqj3Wz0L5X zEZzv>4o=EK3MCK(ZdrZlD=?8wbJN&Q((V5a=%n3TL=xJlV*)S!%>2s_sa*$$1crBe zVvK|@(XN@cr{5!YWgnMf<9gnuP0bi)^^P6<9Vp#xx&U69AHqc^Tf@2tff_G z37o_YS==D2`ZkBr>!dx!!6M=Rqw5`mbm_Kb;a+Xqwr$(CZQHhO+cwu~+qT`k+ID~a z?sM)w`=0o2#8W@2V#f0;D`(c2BXf9fTqM>p;lrqhhzDb!$T%4%>2Jy{9+ zJ055ZQ7`BUDW-IXrgp%u^Fc#G;OlHXa2WQv#$!<~)SYPe49c0$sq_ zXhjko`Qfq;Ss6R5ArBiBGcNd2NyPM7%3QB8EiMw&AZ8TXsWs8nqei8$n|vA>ni7OT z8#9c;7f^eens+Tg;ts+hVWEo$kaB797`iPWbbn)frwQgMg-gId41Nlj<;1n6{Z92w+qYXZBfUz8k5*vBdSs1 zQ-G2KV^?|}Gwq|bc%DWX>s*?t8sb%vj{xcNrj7nu_%=6EKOaiQjRfrzIyDVn2_ro{ zYv0FGP8lQv;$n&nyV}RwBAuq`{sIEVS6E%%fffNuPuhehA2SNW`KJ(0sg)8?GOSkA zJl^0^2H>w+BrAC2vrWoki;y@R04%x)4Y4@cT$}NvQ_pe)w`jut797#1n{Zxh4)4rc zq`173mTf#?X#=A0*})znRlh@Q$?MSqsZ%_5;QKhOk6H2`D_#&%9F(%>)bF{PAmmmCzgt>QqKT5cNnbADDQ}E@p-TvDLHowL2Oh&T(0$1uCUZ6D+6QD4 zl4#3G=&-UG=3+L+KLi6jNe#)u)s>5DZ#Vm`OYesil-e0-j-(Y59wEqS%WxA98fz^Y zow+sO4a>7o;L^s;64)hD>axahlGK3+1Mi#m5@`H}Wf6_bRq$OZ4$;aD>R6gO#Xi+X zaRz|riUMWctWqv?p1wy{lzp5>nrQgKFd;k1Q%Lb_*up-6sFS(%b{-BBHp@lQSx?0{ zW6W!UE*)?9xHx+A+z1YM@!|~$VGa?8@QE87ST0tEFYlIw6lZEHwl56P54X5VqP=EMIw%j1r zO!>%A8vErbW)4eut`MLQ&n+=DXW3E;eu{)&`S-Mny_Lj#S2ZOVBh4#eh27v_SM?Qf zDL}^h^96g76CI&DrX-XD8dZbd%+Fn6B;aYKA^O`kj$is2Q=0Yk(OP(dZl5~&(^>z# z8NWG;?OgEq4R4Y{N3nsWJ%@`r8^o#ayR~CiBYI36ZDU5Z_I9aA(lzj%YE{e7uQONY zrc?8^;d{Zt6IUu1nOw-zC1c&Gdmi`Uu8-9zpl&?OQ`6s*~-+dh#(Ynq`-93QOIAv>=qD!B@1TrymjHk9iV#Odf> zf}@T|X&N%t6Rz_q5#Qa+SfGS#-M8@KG{@=puepEO6@2riOd;M)GU&A-le{yxT*s}K z&pzb{&8Ik73cRzj`66g)GIe?AlOFaDI(A6YOF~GRsacqYg#gx47MBl(&<|~)7jWCE zp;q@7)Bh}*Sl_l>g{+>c&=~#+MDUXDE?L=G(euX=ODRc}5@4=EXW?BhO&YOSQCyFj z7{yMq8J3i}#wegULfN{B+yL^34PNz#P7@zuP!qj`i3wS826g7zOUa-i?M-XDD1a{y?!rj`Z0>0)p2bS@IjNJ=WktR#sF%Dl9A~VKFAQD| z39F(F?RO;i&elfztyJ-Mu_+!V#2a7O8FG<$WMlvYO~`-)USEdu3*k!kyT@WD)i=3A z;YyV1#c}VH2Z8IUKPJ@{IAUc-bDLq?p~EdwO>2e=czl8RA=(y%PMiSCz^AQs7An0u z^X(9-Wl38_Ix(;!Pog~5k9+`+yPR6)SDeX&Ws6Z*!PeA{^SxfzD?TKcJbLUnU^#TG zps>YuEXc?5)Bqspe?JSQEXQ;3ad8n^&Kra3y?r<4>HS;&-p%Fp@gHvEe=z^78!u}5 zgZUUZ004sjd^P?z=Ko1u{1@y~b?i3qkwdTVsR;GNa{CIteVNw^MopE*vBq`r8vW{~crkV?tTC|{X-vZkg?_6JhvHxZF! z=xdUOoa#qp*o5JPNrY}J_EH%N9V!rNDJ7B};R6o?r7mX$(TlH;6JS~FCh8B>D|pgW ztZ!?u0UMUHQim)t1m5tqE7*3}^Z?0Vp<-B$pe5$vtF@bJAmkQo*;mrk5_qRmDW*t# z@xh2_uD&bBOm;kZKhrO^Pf)v`vS@P1<^fi~7Ff&{?jZhf^2Zt(ZM~GcRrp*6G-r_$fUJQH~}99v7FanReBGx6<)%xim+r3`A_s z*5NveRdCpD4cnBd+0~4k?(N7<$6f(8eF8c z@V)f#EC;kF~~7taL;0h;6pM*&BevMSTw(cLYQHFKKs^@3eR zYX6yj@_BIv_dmW9=Wta?Q^F7YPSkcJ0K=_j!1qLDlzr?5T zO;1xtQrSCZc;}z#uk-!WWTvQL`2;~ZEKym^nnQ&dW@Ur0v`%1 zT0?w@=?XSAxFDJ032Yfv$U&9V$d9=M0ZsG<;_rh~Li^k+6%M7g3zYW~jkr?kxJuiu+UNJ5S;MvYI0NWm z`p^ev)js;=m|v!^jG<4DM*P`5Ud39^%a63S)C2~NP{3*0Q6uRLFMby%~hz%c-4;m!h|?e9^yv@qioH* zl1e+JKnBI5DmnP}WdWLkpmWdxi=6*+Dd`C>4BazRXr$#vavyE)){bXQV)xKYT+ zli)WL!4SHp)eT9_aTEM~4Ge}4D6cibFKpQdO*>A})!kYxG6ycr^^&6@m&zxAS0XIim3>+M{lfSPg zjbLB$mK5P2MG|XCJ|&zQrUgBF2(em5=jtD|K$7JUH2KU24o=Y~4l}DoO`g;;!w$rc z^6B9Yw!{{Br6*hwO?J&$JH=FbTR$-xmbA4j??5O?#S2SVbEk2yN`LTNHNpt?iIS~4 zPy@{znQYKLFHrr)e%ydAhOVJPrS_No#y_BJsdIwMlF1i5htfDNazzh>;^3DYM@y?0=O&{M!+|36E-)DiJ z*R;dMctoTIi}1EroEscb4lKe9GXhL-e+zvKAleu}fN@rUkv_&4K#;MW0TC~HFzg4* z@h_zbFZje?F$uu>#J_+g@`H%!V~7C=AZ(+7H}pwYL;3q!VNtBJh68Qj(X4@bv9lv>##+_F$ zQG1g2d#>y4HeB5foG)lCOVbvlDe@!`X&E@xzPzt7bm;r$ZhRhlEe0Hsl3QA;zyIHA z`^PT|U~cF9uhgvn5!!0ZO^hNxNz9R&|9TDnwc=+L?LWD8wEvEiyU?(jnWsno`ud7A zWza?BN7sFxa*taPK0q_dY(yzfb+zEqoqO5gxm4v!Pa>c!m)?f_>yhi^xxT;?!a)Lx z)j7(+fJ|30FC7UyG%(llWxk5H#m+TRE{ie|^SAx|{0ivd_!Z~@-2XI0@ue~v;f7Pg+T-(vx;Lt^z{q= zVF!N_is$D8MrXKbBzO?=QU`J-Ai;0o_92X;Nsl_N5c-UCmMz^k(-=q?+6?{*WQumQ zK>$D#YtE9$z$&K-#+d1oXr;fSuDYdoNXU;xy1{#P@Q}%X%~2{Q@itBOj&|CvbWij$<&UMj5>H4lxR?j zu$dUU`_fn|Q)9t*z&xEnxSH6W-g0ascsw9Z#AVCY$5XS)m5#Me{mHTCK#c;T4vRu_ ztE?;5PFt*O)=mqoZPrd3tVIP@Vzn_kT&^`iF|}f&Fmc8ig_=fxVY;$cT{kiz`rf%c z3DH;$J48iOeOg_p&Tc1S_Ikniu&75+e#yguUF|F>ESfSz+S#;7B;q-5W5R}&^kHl! zgh*CoX}J63Q*niQLhAmOOgwRvNIZnl`4cR=l17!GWRfn_e`EB-1HQ{zD6*3V8VMYNulVyImo6<+c1NJ?-4=@^BAPFA}!Xl4{hxu!v zpPb?X>wdu9C)T>aP{c`A(URulh>b#g17y{ocC+hy@xAq$>RAD1uh31m-=v`Hm{fat zj?>dW$g8E-7oM{C&e0Gv+h_L^XP-olGZ=5-Nq>{8r%rN+OwX zpiR->3YaRv;2+T!LH*6Cb*OBNxgqj*#xrZCwe{UL%0|YS=a?4A@*+NFWYDuGjAN|l zs(0(|Q)aK{@pU288R+Wi|&X0VgqPG&P|(#i~yyX&WQli*~~i?8`X!uF^cjWUZ^!JOtgk+>gB90lQ?dZ`$o`*9{17R$ zg=s!3opy)4@j-aQAYx(|^j`-DQe65Y&hu7Y*U~T)Qu!wj{U6!BIogj+&X5PDgcPJk za^*EV6!|$kbPz~w<@2c%)5bOY+e9E7SFdUf{E^Lj2MLgZSL3AOxU7G91V~B1*GP%{ zpH+Qe)32+##1`cVLWq>m1$OsP5-AQpDdfRX7XwLJ^hIdYm7rJ`18G|DCq&~06s23{ zC_w6GETlO!1kQnR%PGm~D8s5KM`fT^n~B+I3>G3cn*(L692YQIZAN9VR+~xKYz&lA z6S^8FEuiS)^t|a{R8{BoU1GHar1muVpIbb7BYDN9$=oK(_$|?3FA*zrIGd@8U5{pK z6V_XVx&$oQU@uWCwm6$LLXpkZ=vDV2s9-?QeGSwjh#C+_j7WHC{(1C?LRA8$gQzO0 zPGL|IoI(plCG+6FLa%B_q)&p2L)Cz;9x>D_Ne!xM$WV_M6_BD1T|Kz3UxK$GoPww# zseCqHk$B$0wy7%0!k0ajE8C#$HjJLaban&@4mIg**M+d+VSa2s7O~;a8Aeb*T~A+Poh(+ zdKs_l)39q^0wNoem>z617VYt>(`Ed`SLN?NHApaySD60KiuP0KoWfY4UI3 z@l)XVxAs_6UyEI!NA|f^(-sN;RY3#8e3IRDxZZIVs33-|WhsC|L}f~?#u&7b^l(L<6FvVPB+zGV+wN+x|M2mE z;q878t&5Mao$1|I&9o@j|E_7ujc#svn#hqn0SfS%O#A5v(6&q+B&Rxd;~@3+87Lrt z6OtYI`#}(7GFmgxij=mbGm&0r;9ae5k8=_x1s1wVQ({6MUJr39F%SZ`x-F(KOMAM@ zRF2i0oF?-S(UHW7nXW2gn z9NKtkIAI!R(TQJ!pNl&(vDHk2^fczv@C_W9GLQ?dFl_l&a=G1>*6;W0-t&gQ*Fh=n z?&l315n*i2Q`>9yu8xKi6mKnTBq!{jVvYN9RC-^&zLdt7=zAhTcBuTz6csQOCm|fC z+F`QXG@j!wzo&3$hFqp%Jf-I=dg0MJrgt$=QkRgN&R0=%h`^fUA@`^T8hc zJfn%iKy5tbzOAl<;jw9LUZct#&TNO0T<$?9)GKQtV8Q}sFFcIF35 zj)*z49w0_Bbd)oep5ED&LQj3GaR`k@S{0@^XnpPrb}-0B)8N&eDK1XMn>N-DuGlPO zUu};(l{Q^!;I(nR>z|<3^Yj$FLfc}2>n+`HnI7K!Az^G2+!BiRw+pJoB|EbEYVKpe(4tuqh&f)1T?~$L-RUTPx+`C%qc04OYpj#T z+H@2|i9Xa;>UZIb7|sf9Iht}%R45p;B=90u7EKaa1JV=q*0?LQd-Sk2K9(A2K1b3F z7H$1=J`p=R$|_B73AbVeWPK#I&MRuAeMqAdH%K_jWSA7#CAV|9d^5TdS{J*!ax*$( zLFei(vMhO*eOQ@H8?>=86U6%Ao+4mf;l+m|YQO1RM3w7MSzPUT?*^$-Sug9-w@HY@ zirZ|5tKHVgDJ*j?x0UC}8TxE&f55#0e<6I^9QJanu!Om@*3^Xz8h{Sot9JH_vYF}R zl;lnkvY@+V#ZCm-0c7YRj<2KF^oas5!*p-6Hf?Y5>jC}4k=g!@l?}3o^swmb_x23^ zIiJxC6?@&q@4ytb@IETz6BO2wpZjdJA$O1y6;9p0(Vx5M-+~IdThF6ZvNx4)%PL*O zurM_)h=$M*3|+zP91sm&{g)1qUbB}8)40s*LAG#3JnDNpt=&lS!% zQkqZY#$0q6>s%=vceZm#1?7eT=PT2%)uhnC4lmm$r$EN6-#l$$x}K*M^1|S%@PVn8 z`EfhM!Lt3KI5`=nQ95#kSI-;xW7ED62ayAgkrmG8l3S-A6)8Qn{X98QsJ>tQQ7wi} zt9dBnvLT$9696lB5hnm&-CFp+mtkC3lvvFHVp!>yK}pwpm9f$-fShdf3t*^Q0^mPA z1+>+qw$7`m_GQUJF(2iH!iLWa7;rMn!$_UYD{(XD3o<;-MZ=EI3pj8z%fnEe%`0#< z=L_H~$^;LiOW3CDR&>9s?O9tfd5w`?;$?P)SOehx*Nw07f}FLzOdku#iu2#vioXji zJDVj|>8+Z7px?nS4`jv?zp%rI0=NMGi8sOSb0+RP!4BX-M!JffdM!HZB=z}^(~wK$6v?GH ze^Q2@Sjh69Arn8f=Ks4e@uLs^ndNk;u4VTl4ScWb>MJA52wEeu2p4CR4vg4T_mf-s*@D$|Q*-ZgsxA-cvXlxNN=;PYWo`o{hk)f~Z};Xd zv&6#K;;x=NF;psyQ(PfcDU&OiuOBH1B_vu}#65X}+dl)CH0jBtJV$xo3JW0=H5qxG z0t2Nj64Eb{}Qj}()|S0dxI zsW~!r^Y6{fPC+vz`dJc{RRXCX15mj~;-`m$e}PDFL5V04Wpwv4QT%9LTK$B9K$ZiH z&rRn2(rm>w`aAgEKt8xQBj-Ky$9DKkNmvztTTEDVJ>hqmx-mF0ix{f0!U1esd-XinFM1W{CG}fPLh!N)dI^qI)o9!p zGk;ga2pVb!ETw9aR?!D0uiBTkWpeXz2mxrXrFcqxnw`|i(;BN|ekUd|JJXZkoehbS z;qLGHt69Waxv}bnIFY6d6ON!5)Nmw3HWK>=)5|bv)0brV?)_B$RVhZ7MEJFhl?hHT zBd`PhKF*=YfXvX6{eH&TCpu)h0XmL@dj6ZvQpg!5yB)q3`*s52HsBeTfBLkJo~q+h z0{>V^m4n2#(7^JNA}=R9dnO)$<|WShGa?`g);>NUSE)WoIR4tdSQ0%$QJj$bDm4*` zvdeApULrAiD3Ew;kN_8`_l%0-CyyMeR(o+5)o~zE6-2^#f=St2#+?srBY1 ze=64k_%k%0L5<60N1UHdim~m0KEo>2&NxlQuI%J37G?u$WJYb;A3bQ~g7pEU!aVl?Vsdo%>&Jwh&Uc7BV<}dnpy9$e6Eq8B0 z7V2uProVQ#F}FLMuE{NZXSeu%FD&z9abD?bp|53gm#}(0qs)$N*uf2_kaCx7$=n4m z%7QrsT7|Y;UQN7oF67+4a868WW=A;ql8MmMMHl!gxy}jTVwE3x0?}P#2HVWCRIun2 zc^Zj;Qdt1kx`_bmN*LK!$N)Ddf*+#s1#)OW2P3umP6i!6t4sMDK8XWqUJYDrUE>_( z9k<5$xbbqk;?s_NGnzf_=&cmHTz=EKYJBJ!)Vvq+r%8In)%ic+>cL#{T+MH9MNodM z9*lJeuX}pSXw_N#?UB}Elb@%Ve9CP7s%u_~+nG41+5Rp;P`m!3V^}Gj$))dPT*uAE z`=3v+e<;={!=+~BhhkrU#w8&9Z;Jh2{3dgbbH(2(>+PC+)(O~U?6h|X5%d%=%vk+e$c@Z#3BkYjR?eqPo6?3)`{qSXgD_a0F1-O zCA=~xZCIO7TnVqOVBfrJ0lilZgDwx>ydclaka(8lP8ve7e7>Z9Sf4+|UXYh1xp}BW zi6w~(s9t}vR}e>wof79%P;tl}#jzwsz-O!YY_44BB?C1seR)HN6)qv*OA_sPK{knB z1=zaFGjfi-?hh&=!4$a^`sRKn;7{hw5pNdDPS5BMzC2 zmxNN{K+@Q!irqx*%~! zYTCd9Z98KO4)4q$b?LlHoi1#rS1GecmXdg!>+5>Q#XKF)KXF@;{DZ(BvIBK-z+368 zDA0^;Pz57M zXc)6+OY15NqU8NIqetS`FRBO=AzG6$BH^l z1b@i4eoYjV$H4#j3kYUqa`O1wBko)WPJMIo;=J8};XDp1Nmy<#+yLnE7-DTDFOygv8Mx z1q)z1YVa)Hw)3|w%zK$pAvrRdI+;^3x?Fh|HZMA@{8-8yHdXN4;^bzGt5rCpgbi&! zaWF#kTN#1q!8;a%LbIs5A3L@u{~x90E!Hw?xZl0h14^lVihc;$p;V{hZ?KhgT{tHb zY9jUak`s=XuH*i$@L!Jnm{b|2?gWRaKJG;{eAFXNHgZF2)*b;i9e=jqWTaONd9)9d z8OsKZm4}^%TL9a$1WVMW=qz0bPrYpL%PAJ%D#32aqL$i zca~@^_Hc{0T8Is8k{edF;EB_MZ~j*BJ#1fsKz->{Sp+-cfYGI@#p}!k7ZiXct|7X| zQ?8!?s-El{ylzs9yDpo(u4v9kkfaS!}TmGaA&plxtG&= zv9`!^%o-9fy{%+f zb;SV3U_#||_Diy>!C6)DnA&$%dYAOi+6Lav{R!9Js;sAG1 zc)gqI;K4YpZ>9iaGmjxlsT+oITa0>Y*RFLe-^>%d&0DYF_MoctUs(_Z->7$47JYdG z;Qh|lx*t6mh+ha%-(-%0dFfP&?K+C=yl@nor~~ctsvOpy+(lGT$o5yrt)Sf(8^S>8)Xy$Jzi#`V zyTCt%I3OU6rKO+4!K$Av;HUHG-$L8k@Lw9cM$P6&W5a)K>lw&=j_M2jrcmUIPWfjK zDDe-LKOCO6OkM4xqXBu^;ox$JmXY8mtXzJ`J>kgnIcaJuP(R6BmI?U@YE-5qbq~GD z&EDqX<>BDq=olQkd8rU8Ny^xT<+rl7&- zaSVm5vq<5fJ?~Kcb7W#$Gr+0OQKLd%%X|!illHi%TV-xQyzu@Z3Aq3r#e>FCtCEJY z9hrc^Da*yAfT4~dg`Mmy494X&OZh}I@2FH)5giCD+7(?r3T4oad(yQNoVu#aDO6VG zI}50{@M&KjyPqh3P_<{lA*t^1dk7jpb#3XJ^d+3Vq-||MFmUE$$D5>akt{|2%})s~ z-70h<@wS^Z-s|H|LQ|ny)X?KV+}5~1tl}O-bGMTY!cg?ID%BQALux%dJ4X8S15pFl zu(o~as!n*~S$7d^c&Xg7Tita4T>B)HiHFj|#WjMuVPVPB_$$p$tsEJVp|;|%-BM3d z`+>?FnrMJmwJNH^%0hWXT?a1dlRwucq*?*vP2^Dn;;X9EP?AVN6E`qN7((+}DBqw- zIb~HL@te#IephzXDg}t|94@5XYV*mql)~YK;CuU*{!KtasHdH?xq9wnKHK6s<|J{Z zG_gwmXkg_e+xY56l}Tz2lWh59qZ_P?K9Pt}iK%MXCQ`ru2x!7jze_u~sQU*-T0zm- z{>9yx^VgvX*YO-3wOb{}$X>%Fw2zpY@(Jur;sWeezWDCPNaV|JNWhHu)(JAiKOMK>{$qcLI2c;&M;>t0bO zpk?S#@5%5uyXv6T_vgDF0<43(ZHl;Dr=Fj1S5l0yp^2mS#lWBHMHq!2NkjTDXx3Kt zm_a=i5%J%RI)GI?Q6iKfP?g72V}%)znQJMAr0IdVowJhB0CvNg7;9oeR`;p3IIFDy zV2*^30^hZMzU1Fy`kUwDX+v*sEEBU+3%&v_^f8 zqP_1vTu36V$VX{{IF{Qj@~t+QU$|Su*%D|pyvUsiMZIr)>r82o11W*&)>LGPHvnHy z_b&m8@S$8SJt&N0ST@6^x69N+zq$*)!#l6N8L|+s0^=^LK+*x2dW@(BMy)M(?TmG= zwr54PnVT&9=pt|K*AGN|!2Lr0a;Tw_X_w$XWG7)?Q8iiA$Y8^m=|TU&|Kz^npWTvj z>-l}}Rd25XSkQe+OYExbHzgUS3ob}Az4y*m{bvMVwOe?Xsrn4|I*g|$q?F$4m0iQz zj7Kk*FXm!P#{KxjMgLU~s>1B~nvYv1ZQCeL_G)BxqJ=9<|CiCb6ZVD0tc{H@79Z~Q z1xScTm!Hq@6;v?Z`LE!jtY9gl9F78tc-7H#L+TYh(n0r6e84WXz{i;Xk`2%JDRcY&&dxp!&jCI7o#R zOL$A(yC=iav!81P`^Wod#=G zi=a+fm!ahSO>mKA3k7*WUenKyzTpV=W1Dzp<0L z!&@xAS))aD`cEX4@x5HmWXP~ep`;v>SO~+?+o;604)v(w=vL5C^LcLlPQ8r=$M0c7 z2j9>v2+b30XPKp?`rXfax50q&u9#sV-@HJU#lyW9Uhqz1dxieXU~$hQz1D5N8&C#7 zl8pdWDTB{M-uRZ; zXNFF%CmW~l%;gladHznFew>>H7ZFkZIwUtDgE8OWFz`Acci86$I#SW)3PQcI$U5)< z$~%|Ja#SFN({tw5O&~;=oE|I!h84F>=K+G+n2gm~>MX6Dy+Uy?r}T}%og+0AEAkCU z<8D)Js>QYJU?^ats7?2lsV^Gbq8^8kawg7FtJd&4)0s6YY3PC)B59i0M9auooOR2D zflySMA<;ic2sB#8L10&T&`ayVuO>U?ZV+Fi8m~)GkbP;^DQSr|(#UA0G$-aMWAL_F zSr7_JHl*kGat(Au@BQ+c$B3EZ%@RFjA11s+JzlDYrHjtmj#-hj-Mwp;-Ztl2=?2U= z2jY;E_m^VkgC0yc*C&>{d^LZ1%Hdvj7T%(%9@4Z$WUXJ4HYdl~*hZ zZhL_*eI3}6!6fS2*R0tlOAoe3qcNgEw=BxbstblsO7)>9g(0~5r@D|mTDrt#My^Cr z?BL&%9vN7*dDb@aCUPhcbkoy%7o(3(1GMhXJ|0Z;-JaVjW{v{Hz68X1d_G>zhzj3A_SL$JMka{a2W-6K1o`b$$?mUsqbDy^sWd7 zb6Ei!4T$D92*=YMf`9a5x~x2X=@@=Bkd~QH2vpQ1Y_E70yDfu1;h^*lW(c8cdE?hh zV5(E{VQbGIMFgga7N2*)Ub?6s@l=emDHGc-qYr~h8JNkO$CsK5DA8Z^?2YXt#fTOz z$waMe^ZgGo{v!=LBH{hre+mR~C;$NP{~-;3i1A-^IHa~=i^Kr$Goz+X9=93TZc)OW zADZRwPYyyHtUA3e0n_zl=+%}y(Zlq#?!XO`MHsKHV#9QjeOqldoSW@vDK(MRTAG^1 zvm#2a5wFE&)>b!VtDCizBaP0Mf?D(FZw{@{oFT1QX)!IE-c4x$m;qVLah-u3IZ*hO_c(!YW5l+^C}Z#b7P9a|u(|MRWDuu}Ebl zHi{_Cy;iBtYQ5@~4I10dz+0wk9kn<^r>MNcwQM(w0 zXY>g<@0W^Oyub*S3UFcA9}bI{msAUrmFo8GB|sx_T_LuE3FzcxhAL)nS_?T4c;U;& zXPGevvYr%=Jik+`I=HdRjQKnn4JaeG#}rFU&WE7-Y!C01tas@}&%gTSfC?!o=fyZ1 zL*~C))X)u4G#u0wBz5~VeS@@`{vISLIPRSD6UF;YkDh0PTXg6yRLeQfJeqU{OH!SB z(j2xbfk!Mg6r|?O-Eu|~w^bgqlpXW4>cSC^m^o&5swa}zv<{7T0zDwfJ%28kZ&xZ} zyT2Bp4c_Xrg|V`jr6uC@NHxM|GJ~l^9W^NVS2Tca9}Z<9HL7}wR~NgC+iTbV1;%=I zaJ+NgLse>~AZdeP$r}No!~2aNaO#{kC#U9hhl$dtD!%6$ zMRVmG8uJsc<9!AU3S8RPYYR|}cDLc3H46oMrlYZJ^GuVH85%MZYw0X9i%^%dqb+Sj z#DSRjpp$&tb1|q!m1aei9p_dK5(pPf7-C9!ff8dcqDV%dRyqw%mphvlmltpOcjLg_ zK(t#n?g;g$TjO5qgL?oe_Fa-O;58maBL)e?CQW$y87PQuehC&v6H?;pi|05Ck=owO zs%y>s@~$@b-XiMI-}sghU(oeDcs)JyIc4_^b{*TERGuY}3|<{t+-|rhb#xMCZD$N1 z4wa|QsH@B#joQ40(%9&zfMS(d$eUtOD)6>4bWk&In(kOLhB*Zh|BJSzL}mB4No8;; zN@slILTpJ)zvd%pdSdPzjr25t-7*1ym0`ulX7X4b)VH3a#0Z%S}IfAm`vyapx*hYxZ4`3I`O_D}zv(IeI=zt_xk-^C0(R(BsLJuuN{t9_f z8kb_K=BCO+o*K?`*hMOkhEA!?_=j|MOPb(UgN+fjh<7E(Ck9B>mP%eBktaai#sV9v zL(-N>7DoI%8PC>8dCmynsJRhS8c=c(6^ahjtVD}Bpcha;Sbj5nn5(VvmU);K`aT}_ zu!cbGFaGa@obIS2@9|1g!8=}moK`vIrTR%*uqZe zKnneTUQb_66-?oF(2gDGo{K+H=3RYHrvG5bx(#0K{7y2OQTq}ME2DUDHtMtjd0)6)eUp+W=0sx zfTwu?CWIB0j=2n3n~Mdh&`ZEyZ@^y$ECiz>6&fHUREMWPWhC^4ujx4V`lbxPn@de* zn2LD~e`r`v;8jQ9a789e(ib&0zfI^hH3|@U{n|wg1e%0}DP9kGs%g_ z4@Uj-Y8Kg1ut^P?$#OuY{?$lX1v3sU@EmW<6oAMis#a7I=7|Qh+1o2cPXs7WMjGa$O7lkEIA9d zmkBaZt|{dMFr_J|t~u=+n?Xfrd&J~TST7T!j_9cKj^^&eEpq1M;U^v13L3g`%}yM2 z{;mj2?A4dVs|Wf!AYO}UEFa!*?h2ljCDYA1g!GGcPs*8IKm(RNP zJ~;B`6$@Gcg&jxk9pB*hd2gxnWfT^*;Exb?MN1egW z%hVLv<-sedok7^_<4=KGcgpWy?t2a_4YXl)DqNa`_?tRpO6{fHyMD3 zP}CELPl|M!+J8OnEqA>0*r{tR6-{UG=nKg$-N3A;iEGKO(szhzZ|rhUFk=eI7l27? z&FV%2*ok+@Ye|9@xnJ zi7SdoF{>tsBJi^om|zCjm{Kr=z9(V<;zR;v2coQdXjLUPIBqFRm2#2A9F!+_7Og|&aN)+Nn5C-BR@T1%NVIr zn5G(+3X`19vt4d7-B-z`f7 z&)qKDWN>4E=cD#9`s76zRk@_z@9}m2&TFeDGIMpP+=m5WI)ua70M0uRF0GjwGm5^S zg)RWhpR+|NQ-eIygZ@IF-9)u*8HDykxPUsFGBBo<60ytasg7^(9W8C;DWkni=22Jw zvgxQFIx{I0<5NrUC&oLgZQ3MU+*Od6j!=6R^;R0Z(ozN?`l1x_ucZ)5bWPQ{PmM%h zGeoLsJ;zb~L!bt%?q-Xw3oZM|mxWoA#5 z8aHll*t)r@Jy0~FlS{fuIrBhOnk_IVh0qHn22M!^K zB1m_K0+P}t9nuJhG)PLLbclcmeAf~0n~>*ueAoK^de=LiS>w4l^V>6f_RQ>=YtQVb zN5rm&$8DdfC*?{W->BP`{K~MlCo0;-;w($vXcK14Wc-%I_}hs^wdKr#_Yn8U&Q~k4 zU8lR+--mbZ;6#TNE3l46lUg1% z+(^DRKw9FC90g`t2R*7(9~biN)CV#zoN(VNh2=QjM1Ygi!Lr7a!GcNW)S-cmlPg4& zna-O1a5Ne5nH9xY(@5GrDTc=k$)N+SH__j%jhyJiu$>zOV?&>kV}QaR=Ou$7E=MH3 z2~8HOD`!T3M9B-1_gg{p{(&#}%S$-hO$u;7jhAvs^gnn|CyCY}*C(56)Y$rv+XSi0 zE`+G>y3SO^@{0MJ)C%OBm+>=GFj4+_p}`ibZ0!0pKKRn9E(|KELACX8)QPY0@ulsu z)gs+@SY(8-^CIUhGk%(Ptx$Q-KbMwI)@NXgSC}Sb_LH#7L-ssQE+KjdZ**WSJ_wJ~T zxpAkhNqtXz@7CEDm^+;PkYbxZp%W8P^nE5d6R65qYa5Mnoh1>~yYxOzhST`9iZg z=|rRO*AC&Y)5+iGlbtrxifp}JcpybSpPR){jNW?ZAzkbGbWOqkJMGj&ke=Hku7q{? zv?tswbdpQ@ywVe>H#U%NoCv$DPq}33tMy>i3M7hqS@-x%RtsON9ZY?z7yN5wdG$2_ zP#0zv22KVJMqrTL`SVFoM;>C_&Ggp8KJJg9FIShUKxX4dB+>!l5o& z*tUrstJUl$1E#oyW-5%4L@Xvgnr=0v_kDM)Sbgg8bVjv$w>3O!<@CktN{aSikBz-` z=38l~Jp0)O=!IR*LGoXmM0xRYt%{@32R11XmxZv|Ss9!0TE}QYy$j)B6|r__0-xzJ zWy8@)?S5RYrLX!dPhsYF6-OCXT*McsER!ba@H!*#VFr`)+A!?m2cFzuIG0&XI6 z;&IdWOP(^8AXpb6o)Nc~7PN$z+g;XUbff1XE(Sy=PGTqdV+8h|G#GWRaF-{hN`@*!) zgE!j!oP`&(X@$DwwV|HLiGZzFii=GPc!2|4)j8@}+d6@4%=AEZ&<0+M5Viyyn6^4U z4Uqa0W{8zxL?R!LHYv|ul1H;NMn}nziM2h+gr9TliEf>F&jyQl-9vFBseG7CW=imR zQByFo^4Hj5hQdq=$1GZdM`<%6F&* zjwDvT@NZP9fJ6XW>J=@M=m9YDq6#vS5-O^J3SBbHU2H6jAq%ps z3JRqxU2<}L@WtO`w*w<_cNuXV92#zKwZ=RKIeiCx~p@8r{wD`U=r#F_>Kf% zK9CR_}GAjGPd~)X5*#+W84nO;c}3iSbi}jflJ{C(%cSYmf>I@K#6A ziS~+oR(In$uj2Y99cb71yTR0aQIaR?k}D~q%G=ucnCtHqcKlAnN56jNrqqcGGt?SqFqp=|C9D15JZdJ$-KAA}|=f5}LP~916^+bUz zb_krRHx^aoxBc_*E=l1HZR{r9TL%h>;Wh0T{sQmd*Oz7swnlHK2QX`>@5}JwIMbuN zvDCI^j?pMupb0=TFT&G>_h_c!-9skSFKT+ni?%MHd~>85Ovzxp`b#*k9>k$v&zS@h$m}*JYLs3ZzeKV(TZqf$P4?+wu>5HAnCh z$Dm+DS#p1MyjOq#yMq%{RQR!KLT5H*QmSX&qV>5k4X%(REDGq}Efaqck|soVO>Ni6 z6nkRqC@{f;eX`pj5q4fyT)t0HYSLV8$4keQ_)S`c(@+H8(o$rWGfoOqHAN+8<&y`2 zsZ(G>yb%#PtYrfpnJ#^E~>oSnCg(W-0C?s!a23rIW@Mn z+(#iAy1^QC{QA-#4k1ro8iq=~O)3Gklv~uMvNw^$Y}IB&PcJBUMT}aN4@6OOMZUZ1 z9qQSQ(L{BtKF{;v!{d0HXFFwLOJz2N#AEmMO^eoVyrb6X(M_cce4#JY8iDY|rSvT-Z2t5r#vqtbIl8&Ch?V2(@7%eEcy69&&_v z_lgylS9I7P^O|`@k7q^6Cu-7StOe31R4KWcDeIQC)v0$i$E}eq3Wqa$kCm0kc3lP$ z3~_pydA2I*T&giE2o?M0V!1t$cSsDm8Z;C~Ws_S&wK} z;9}~D>2g-BFxI`LSLM9Dp5ej@5_ad?73Q-{KFLCy*_pkIC|ZxY9IIdkqO$GZ$-GZy;vTSksa~9ruczO zwQ&6E!H4+fr~B5<(|krm0>FowNWl6fYHJq5P0R(>L{0SeMc9Fdi`ek_%9IXktTbkL zme3EnWfocoS?d_|(>%5&LM$-BUyO<@X5{lB^CS3<+rF?ZJ}GnOY;7LbTD21XH>1KF zf#eF#U6BRvAMeeysN4jnIzu&0>rlJYZS5RQavwQXQftq7-^l$EqV`s~^Q$TPP;tOI zkp%gMT3nRI9M<8`ldn5Ji;WNOm|E-f(R9yGyNyQSdOsN*;wn3CA$ci``*6ekm;g=G zHX^%P7^_rRq6;skg9{!%W$E*4JO@(TA_?@?JuNthuQx?6g6XkQCF#<`lbLyK!b9&EgI?Wzh@_sz6Pr52atdZ2|_IXu;#?PQepq2@uh0j)I}%SPA4k0+$XYFlvLjYNmkyMxMb z$I`3GO^4De6OzN2zfHB{C+s1?7!zZ^X*CYDzcW@tn%Az75u&LH$+a90AR4UPb)vV( zCr^qM@_6XoX)o+|pLHBKI4yhMu&oQHaLDIbl;Nz-qrAM8B^HRVb=0~YoWc6%2Qu#Q z_Ps|%)p1+|<-G;fCIYYOm}rCzEi%DYn=QMcb#r=jVCTM0~^KA z&y#_}6>!l_4iRDD8jq$eSZ#8Qo~Ezpp$eI}K2jLj?p`Cc!uJXv)voztMwL!mnTLNc zQ+m!ug!FO^OS)7To`bYT#N!&X{{9EQY&r~`mwSjXio!nl$2N8{jZ%AX3 zYew~(kaP7GOvjVUMkOHMs-)Pr(czJavoJq9x8CeEB04c{o9_!6yYX_#NOhju3jDE` zb`Rb9;mgR`uXz@dW~C|#QuY#$@Zx-7}s)BoON@_k?_*LJGS{DKy-s}?U95+hl# zEcxhFMz}_>p}t3q`q)m%+nV7-Gle5kPBVkL$KxhCUMtyMZ((()H%jd-=bvOg64XVp z6xkho@dkECB{mXCRZ$m@SV<59G6NnWCO{u*K_4>TP!e?QC{4C>Qv>%PrH=^ekfWw! zM2~L^u!*62QU`q!lr2W!5xGk{>tv=^HPyAU!d8EBEOmk@&BxQ%Tmuq0-gwHt<{po< zWRdHkC;##7Zhr!+SD8Bp9yvPql8LAXwgGN@5oQ`>vfkastD4(*GPM=I zjJe71AdgmEbSp+bTW^wwnM(NiKDYEnX#2X`Y|dOvM}_88!H}=5B@0KUzmVX7_B6t) z*2RXu6N#iLjhPNvh|ZZb!G$ZmNpftL%V5f;d|x-KABGvEcS*~&D2%IrJ1uo zS5fb9%dcA~tRm?KzA>Pnmb>)@kCi0+sZZgqRQQf^3PvI`+!Y~mnYCDdS9@<8m z2Z!ZBwSd8qXjw?Hh9A{KaYW=q(tOjqID2hjJrh+*$r^)=pRpW#eLLF0O7D);X7rBU zK_|y{w40S)74WU5T_fMNZM~Z^?9Sa6ooEWMgszfK>M%~Y4Lk^T2{0j)&&Cn#uEDu$ z-D6I`LNoF+!8HV-+xK}_vinq8-P0i!%S*swGV;r%ZHeaao+OTQ8hK9|#^kH`dRNCD zvm1Y@_cYlAk{CN74}S<)k#Gs?1hhQIX~_yNLG+ zDg(&5A-3^fY?cstAuFk$y4P%(kH(cN*z>E)mhyv+B4t7_p3j*^Ebh^w-c3L5^-M%x zm?n+)Ds7(8J6k3~RaiTCT+;?Xg$3)L9+o;&VK3;fw&TC_S4u1L?*^roGETGm+KKBJ za@B^d0kF*?N;uJW;o|b?FRPo64?|M(_ui+@f6UHG^{1W^bO$^+z7l`<+@6p+be}8r zd5K>dh76y(CP|L}06Qjf0Pdp7{#q%5#4%F5Ipzt~cabe)D$NgYP8AZ*pRp4d3v!?* z@#`ps%c|nd@@4js`6BUAEn?G@bBsc6N7C)1+nH^Ac8~QJdCDP!a7z{uGt3T`7>z=t zu51Q8!b>8Lcv$#h^e5A3K?Bbqb;p{F=)QDuBB#W zBS=uVDD+?!n=XA~VZrJ^jie!o!VjOXO?&Re*7joC{tHC!jX|Dpa#Q|(E6Dxe6%97q zQeoU}4Ov{A2Pr}QM182a7 zZWdG%6;zWJJm%2Z1y?RxR4xzsRer32=#m=wBE3y;wQnc~_fiTski^jDWQ1oODBsv9 z9nBj|$6CIVhq-Q;0`_GO^=D%AlcfE5+w$2?v{+^qoC?Mo7e!;RRLtEln#89r@&pba zbpjB#dUc!nHDT*jg6d<;eCT&RwZcJ#_@QmlN3eu=S7YF)P%2`evdHrm@MhJVjVk zLSI@Bd2?p-t4BkyGHeQcxbD@}qDC5$i`waKu&&nYehThtrDHeZW0&^Mvz(sFsBauQE3F+wC#1)8se z#;*@mv*H{oJ0FW7`})^LT))kYoK{x$U3yvQkC;e>A2-)Er^f?0z&l$2la{fM?IeNqYvT`2e(U#d&dc*4@K`;z0Y`b8x=DEips~r zRz>sHfDdKf8bSK&xe5#>-(Jqlo`v>@tY(KNJCZ0J&$(22QLA+~RPP*p%C_iP>UJc{ zCRHY^Vh$G1Y9~3s4tT3#F!}`}WY{WNPV~BQ?kjdN{I%Bsv;nx)H|{~+qza1nwO+%g zb)A_ps&MJwlod3$5sEJeVj^zM{&M6q zVI=Q;gKR$)CD_O7@W6~F23NjWzt0+&(t<;8Oj6}1GRINZ5)_!l(lU)tN3n9`OKAVB z0@LWa3dC9HNsH=zT*IuAt0P3xW+errO;Dp<(&>*1R zruPBrZ5^`)O^A7gPHSVyxXb~=a#pc26D$|fl5(U-T2?`v$s=#ihb=O~W2oYkj#<;n zkxGG6y`Eo6TW)y}0}gXPHPWmSx8jz8s6Ok%>Z&CV3Ku8N?iNPI&<(ETzO}2j4i$YO zF=|2ysJAh4oy$ftz|Iu$Y|SKiHFVnu&HFJ$u+`Aq|GRQ%M1>IX2r_Vh(9qSez z_ey%*2sO;tF`q?bOQhgL!nZNJbw%&C({s$V7_TL>n6MDQD{I>;1d|K1-8-n< zkdW+f3hVH~i3q#p>OW#GCL(*gn3YYvZ7tWQnq)-Qna|U1c1lH5C!99r&;Y`b&7ziC zQf=@szfO*ZS09{Na(}aB?K*iNRK3mnt=?uVq4_lbQg6`&HSkJ}E9ii|QYACs{m+zI zR*8Ght2>EHbh-p6_o*Y^>jqHzEHARf3KEF%*L>RMLU3En*kGBcs`;kzsWHitwb1HX zVr~YSuufLoYlf%q`$%8Tqg#x4$1i8s_A;wcGBd^TGA`kg!mXjXmC;LC61J2SIbI_u z37FGnMK+)8r9V=7lU}SdduvKaJu0_V8mAG3V1Y2q@c88Gk+qO!C{aqX-jvYX{|qup{cERHR-Rymh?!>f97@uX>er1)C-62n22FX{c>z{&(a zp*=q@jKj`Nhfw|LFNj4&qd&+$p@036hqPWnj#t;mN*_GE!@+20!7~czw19g1FzK~C zA@JXY8)I+z#S#ku{ddQad$=#ykZ%>zcl7;WG-_jm{+m)}1uLQS;ip%xqdf;~(x1dg zj;T=-nt|q1E#|kGgLTw{Yx(4;*>WTwC1r%is!?kIf6B3#9|H7UwHk$wJ^iu{Ng9F` zqqNZ~!kjA1LFAvyZ)nUtUPjHlHqvllH9^dmoUNg_SES;#oQ*L7?A)khsYpd9;nlL03 zH*q}l#@@YJi-(kIApJa++EWnY<7qsO7NR)W6Yl)Dm@`r}mQeRqio?2gJ*!*)R-un! zSa9%t$NnLE>3hC35r)GrwtQFlOkp7mqoH{W`}F7xODU*FT?L7+HXK#=MobRiH(pQw zyeSyQf@<%*aeLTuE<~KB@i|49RN{L!{}IbQR02B|!NNQqyp_*GI}2;f0&YV#rlcqV zMagw;Hsj4-bX}%Ua6Yr||HS#Gw?2qweK2-Id3%p?qw>DfwS7DpbzCE8F4H6 z$Z`G_BL>@xb+_7U(iq8l$Y!9~9C>pGhc=lKN*UIP7zbMthOCffg4co+KgIjQ-FbRQ z18)0LaW6R<#mS?W61HWQbXC7%B%SgYaI!hFiG;A}X|;ckh9Kx^okSNhv*?Wi-<}}o zjb3vf+W)xRND3Ff#So>J>SX7cW?}}bKMZ?c9wrx49|ZRa0#ifR5PPR36|=b4M{}4m zW($cr9R!CTl@H1*I!``yAKmUXPAw9(`*i=op=9&T z>m9-+4P=8HUHqB-U%STnZ`)eJ*ygqz0vazY93IToyU);9Bc}oSRvj7)fZM?htxSMT z=>MDxYIt%Qpt*oUu>a=zWi_SeWB_*f4RCs4B6J`73(H(J1o&wR5J`Y|8YqB71Bm~S zJqKW5W%Xu3VD2H9LyR_Mwl<;{%~26z~lDxhKMexshg4vYex{wG|pqa6#t z14oF%m8_+w-pYLffRzIA)&)>Fz((#rfjS$299aP5DXX#RJ=(UW@;q<(KqA-qJtvLhtZo`KKiRwI@(r zKwA4BNR9>$mVb7P13N)c3_!j-fyneP9tH3}7T^v4#adk~*(u(?7k*t9XKvkA5k&x0 z6<|Nh1z<1qzXAS3P_AwXXh}~4bTl9X8s=h|6-*pOjT~ic98Ju?296+GoBztuvwjCf z)BX#ztGSxe%3<;bs5~6-vX=jM`A+*s@?T^Aew)tXXacxe_|*}utu8Yewp8|58lck! zFq!8f9iRgLixa11H?p;JWpQvYXR$PKWp(|N#*oj4!p{IUR6;J+MF2Q?^>;LkO{`2D zO;{YQ?O04fKnJ;s&N~tv*+qa3H86tkU8oBf81ny;jxEr8|8454s0_F#B3lCJ0YJQ1 zn*!jzn!lz3vH2f#LW(}<-vek!0g)4kr-1@U?15t$e@EvZ62RF0XS2}4=+3?anuHn= z28Q)F{Hcf`02gEb9RV8?kn>g8^(x#_wE#9JfX#IQ`#RCzV?$>?Jz(a$ibAH3{=o+T z`3scF1qx)ue@np*Y{Ft>ZenD46#-c8c?BZ?JQI*6jtd0%f%*UM*aHx-GXP)7{iswe zrTYM^BM{jxz^?-1``^L;p0@vNS{=rhEs>Y1MD4uG3mbyui(^nSPTFjm&A*vK>m@Q zi&U(r{x?s472Ltq0pL1|9oW_mFcX@IgB77)>Y-C&%bSE2gtWk*J**(iX7 z{(QE}E?$0l(723s*+I-17OC>NB3#D$$AiInxT{=woWV5$9q!*6{f0Yp>~S9FDmMye zIKk@w0q0_ou9jt>L;em>CfjQLb9+5hAO6qx*Pmvg0Fve=fhPu)}6sHTKowEHTS-ZaQQ-}GlXE@AbG$`|=_9v&_+t&ocjcB>p@Ov=EoijGo~XJiUN(ZfSJ3D877_=`6SEi?iI9 zPBxt{0(6Of`Ebb@2(sT9$ho5?mjN!D>7N0d1Y86-Ylf?Z7&_jc2B;7thg>jVzD)MA zt@CL{3LxRQnDLV3^JSdNhP7un=wTNMaHW~;WwgsCsAp*G;b#V^=W{{D;IfhFSuSrN z*Qv?rX`ZVY2el_W4N%5)NB&_jc%I-@_JyaJDS+h1pPA3B4bQ_s%YE4x@C+s@3h;V# zwQ1mGkjt-Q&pM+&+yvR8YtY`;z1&CCJ6OanOBNF_qG;5x!7e0=p5}QO!P-uH$Rf z_X)BFSN}}L*-V|K2{T`1)HsR^iiTr@r(Nq`_qN=JBlgNlMP80O>(Luj`rKch$;9T& zjvDYcR5&^rVoZ?$T#KTm(o-da7BZYm^tz}_s zJYNDaZ$!L<^Mhllf%MTaoDas1R>`M=5$7~nv!x-woS~MRIcm%4t8`l#AVb&61NEEf zXe=69%%N(!8EeYg#GG>$HV4X#cao_y)3ja{85!L9eoMkjas;EyBs!d=4zZ@@Mq6Vj zfjdlNCDtG&@$;T)CXW->2gT)U881QHi7|nb7OLTxTygB*PE7ea6g6g>lGl?HjTAcu zTLsZY>)8mG1owKT?lc|Sj;9(1&thxy)&zoV!jCA-F}Ga>@GQBImMN&a-~T9!-^SZ$ z;J~@AnU;eJnzNyOAsnB<(Gbs+XqK=#KnGIbonGN2t(ww?ojF`Y)qU&j))Z*Qy{xoL z2wU4>+pz+&(G%TSLjz?F;rB{Acz6nu2yJK2-+JQh3DIFHH&_|^ZAkzX4@KW&(IR@RMV=Mi*We zE`+}k4eotc7(X^O!@6W=n-Xx7iI_oEF;KB)VcuE8xO)hNlXG}_#C zv5M(Ht27-xiL`GpdI_Lg%*LU-+6SM6yy`J~Sp+TFVdyHq#oP;s_`X_gFBO8j&=z8f zIvx=1!|S6KaQ)Oq0$Q^NmjoYJdtO;H=y3l3g#G_=VLu&FZImyLsMi5uzhsmCOUlC% z|Hq&T1)|C>$1??F$`yz={scOkZvKV5qT~GkX80~L`{j_*jt zqDH&8Xa@_-2C#59;ZJ!$rFoGDs4&ou0S#C%YogFp6zm8x1$JMcGYldOJbTt3-TgeC zpIV(PLlleI-8vW;XvF^)4+bXPQ~UxRRGo${10I9yenB^IGXFVoofY-Z3GjSTdjMkR zC$e9N(CP4xsSp-U_}6vPS51b{=@1$yfQVmz5%H>V5IS0*{`xhr2n4D+Jm^~hr#%4s z&1o(Be0s_v=u~{w7<*a|U`7U5#MN;1xC9+>0ro>j-2YOeKS#OqHNtGX8vAlB{N|=2 zp{2jB5W{mmJ>SrOcAoRCLD~F=w)U&|(5`ev@o&PPvgXf@be=U9e}bOxRseUdgg;fQ RkO9uG!2w&GEdZNg{y(QSE}j4Y literal 0 HcmV?d00001 diff --git a/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vCSCF.csar b/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vCSCF.csar new file mode 100644 index 0000000000000000000000000000000000000000..347b8bcced51fc503570823a34d24a997b0263ef GIT binary patch literal 4290 zcmeH~i91w%8^_Nu9)rqQo-rv~Oc)}iwD5$OEM=JxS!yhk!OSQVjja^LSc)u>JxzMT z5HgY_p-d8yB}+{)QYK_4^^Trb<}J_l{saBabZfax<-ivK-PkgmiJUFA|8#G}ktMof1t5YQ{ae&cf3;6=8}*C#i8d1Uu=bZQ!?ml6_*j z;a1_kL^+M<3g)dMxIm$~pu`yTt;YIW3u z)KlK!C)#gpNWD3??Fl9rLPKJG!=1$j#4-$@P7O?J@{B{0djs>u33>N%R$903ta$Ifo} z;FQQJO(YQ9dSEu%-Et~gl{;t6%JUwlzRFIM^nR53IBI;c;VYuJDk0%Afq%5M@_L|v zqh?)k_?~U3>geDO_$C%el`&(dE$tL%4Xf#mE3~j`IH7yN4e#Mn z-#P6sy*5}`ZCWbRTs<+8O|BdiE!g!2&B{2b$_`a&@v*RJh~Mleki4Ta9)HN%9H#qx z)V4cOO{X#a_Lmy1Bj#q`BtMyN>J_p!Y6t+~&cI_}WA)On!e?*v6gkgAE%3}6#XTyg ztu!s~-#ion3mpD@@P$YYkqM|WW5!sNzaOs4$!QiUDS7I>*F56EdMo|&pX>j|?@+hK z-?7Y^XTIyCv^&bki$a7#w3><}uDVzk-DotTQusc1BBvE_^y1zt8dVCFcmiS}61tWk+g52} z7Yh=0vMu@Who=AQly1gkiU*xnVDWsDqk=y2lmwlZv1ssO?ZX7=@<^5ZgfITj2Av*P z+I~`Gx;9*exvGhwL4IRb{FS%yn^Rj{LQPt?qgm=Yoj1iJ7|x#Ci5z*_9HIBhsX@O-i@yOd2#7ta#2C zte8mb%!h*;xjj9C>Ab{&t&}cSMWwNqNMRW5gUYCd$NJ{}akY_GneCsJ;6; zlnLFy`YgC*V&XteJ8oXSCvFUN@3dr9?#%ezpjdn(c~g%^w{W+OiW7u^7z{WG>Nulb zP)%un8kiKCY^Hz@T5I zH|FJh0S`H}>LcG2;CA`I1+k*C(n+rqxBX1g5aDtkV!$;+?~OEl9bGpX`y$`E!h9HF zu}bnXm*k8xcipeQRkhdYl-3CBnD`Kq)R_8*-8z{YFSQ!ytPUF&flL^!*iZ}miXGdb}RJp>!jIzW5Rj* zfm@mQHI`!Fw@{hJBB>U7X)(KHuCvGZ98>pT(^{F%{`uj)nP8Ikn!x8ly1bvj2`qHU zhAkbWFEs&Q?qx&Qpa_aYt@Lu;1g(_3`htSK<8PwRS1`NEMNoqTi6IAXm$U6`)bKkr zRcXMa=~i2U%&bo0e$lv19i5 z-@itqww010%1vjy{4BRuG>`QaR;`hnjtcQkw)IFm0#RL$)ezkt7G?4^81DKt99}-e zBA>UP-OFUSLjCCB9^n%jff={76;i`lvQ%kz zYM-JY3&r%v{Af+z$YMO8(wJ!M5tO2Ykn_9^yKg`+%BnDvfIyUeq}|zaKU<4$e!z54 z{ovzr@4q<30*GfH@NfOyQa`pdp#K=IZch-9{eBMwz=6S`hqN3-8)(@E`Q6N2y5^4k zYfs1>TZt2kyF=uTp41nT-C)=TTDIuaAVwGc1y}Ud`pD(zOS44(6n(W4XsL+crXDBc z2JJk!LS3e>tZB9Kikn)*>1kIZ;j!Etk2c1pB@Xn+xQD;wisk0~S_pA-h<~ik`FTYT zC`V0~NPkwDbXRiTCyeC3dC9JjR?~-N($XJLEA)$6a4#j?GW`38S+>WJ|6H#CR@0Pa vz|w~r{S~mHFx)62-Ua~hbGBw40O;q)76AMQ=Ilc~ literal 0 HcmV?d00001 diff --git a/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vCSCF_v3.0.csar b/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vCSCF_v3.0.csar index 1c52cca12d80b57b5a7cd3c1c32c666186c59b1e..094810a3f78d8344dbae838534999300d9fd95db 100644 GIT binary patch delta 1549 zcmdmdk7?t5rVSp;gcuk&7*_XYdwWcrbiIy=fuTlla?~=d`nM6M`)(PC-2E*2vr%b* z&Z;+27kb=smoL7wY3rLCj$(CJ%Yv4M{@;6DrKLrILpdZZKv(SG_j$i9p5I#F@yzh3 z-0^0OQ!^LcI(Bh!Trtmm;r6$aB9CwFT3llz6I$&b_I%E!HudEX45H7xyP#ZSmzPvp zc%SPqL-F^2+Bq6Jk*r+x@3fY#4S70GM=?uw9y{~;Ua_iBh4V`UZ)~<;xisafG+$Xl zrq0Df+1=p>Q#Wt;K5g=vl9ki0>mAGp_7o1f*?YAu@_c#6g%|VEx61rKI>B$^>Pc?- z?u&oN&O5Ya?M|_oEG4d@Tq;*l|NmVa;DNvaGA)di(Gf2ue$F4 zFLP$bj2!#9r&O|LEq<9Wy){~G=BLuX`L8_IS&CNw5s5Y{H=VkqtYt;`gT2;*O>?Yk zo4&}{Ij%FWZu%p?w|TMoyqNrN-`JE2J?npEh0OB#ztro!8DC6gnquDl$veN=7wHu@ z1~nGXy(uPtcJH}&%&e&kuHTxLu{7dQCEwPkIB#>>qzt6gUVwOw}X&+C&{I3)Ts>+2roFN_CfbTn@- zSD(yKUp8;L+J`EGv(r{T{&gWIEu-}IJl#%(?F%~;^aCdpY@Mg;$#Az#W8viK8r(AR z6)y31$7=qdyL3ZYyS-TWD-C zOFTVO`p4Gb&@#8kQ&*quU+w(Wd%~qB7JHT?tT+&~z)*^r_aD>b=PQnYlV=NR^4z;p zZZvt0CeMLRo)e@tN36+Yl(uIOVZbaz85mR;R3_h9YplY>pa7I-U|?jBV7RRNQG_M> zGGoO3JwnLzWd3zpOiU{$A6zM>mzx&g&Bz2Z6*cWM0L@SVo5lb(^#DkV6p9s-^b%h% n1Fewi_;nMRo;-7%7GufeBkOD!7fxneufY`yEbQ&pf(!!yzU<4! delta 1454 zcmdmZpK0?wrVSp;#F!X37=%|udA~4leVEL|!0=3ffkA~~viv%=`lk_r`L_%N>Yj%` z;pYiFc6iEm-YctaT?i3J@SU#`7)!_{dLce?Py%EEW~5Wl}Czq?v_9Qy>GL! ztC2hRs|+izNwZcm`OLa=ur2t{{OGK(GZB1RzOPn)RJrkv_sX7xxgK!|2Wl+$tCj!w z{i;~@z~3wr=QCfQ&(8=5*~IXv{^2T}Z{7=iw+U?hcz*FjW?rUiyoEklj_yFe zjGjKqvpeFmZS}{v?PsUWKK_r{wKnSTC!KF!MQ?80EFy4tvC5{;zLQSeJE{=td*0l$ z`qMKr{rf!6FW)?E`TvW+fvL%EfgjHV3qPK3VZ60oVd(z5JF`_YR=O1%`H#5uR{B=^36;>`2#g-f;Cd;lApWLvFWi&;O>=cf|tQ=veSAS#_Y-U>ovH5d4YjrEl3&wq3oq~ diff --git a/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vSBC.csar b/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vSBC.csar new file mode 100644 index 0000000000000000000000000000000000000000..ee60eed872a06b56c670d79c521b8242226f7e63 GIT binary patch literal 3771 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 literal 0 HcmV?d00001 diff --git a/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vvg.zip b/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/Files/VNFs/vvg.zip new file mode 100644 index 0000000000000000000000000000000000000000..dc9ef5d823aa500de7dc5c13aa03e2578cd6d9ff GIT binary patch literal 944 zcmWIWW@h1H0D*5Imfkz$>zmDiY!K!F;-tjl)cCTpbiLHPvVz2-#N5=9)S_Z5E(L|M z{G8I<)cE4es#GflLjwb#P+opnVti&^aYWmmciv$Go;!a<|1_w12$x*E#vYK8+0GEldNV0$;kFcyEsfh= z?4Q0&e&fYOcS@doe78b~H}lZ0l{^dI8K{ZxY5M!_+lHHWbHBBpNzz)B?eRfL>3n13 z^b3*&b`w9c-ZS{{V$V^I*cG>CvF~AZPU#X_afEZ}h5c!_%uY)Q`}Q8$q{aMUPl$gk z+m08D9a%dUeHLfbnw-4!frVdVx?Ky$arI37yGCpeZ6sDye>78^Q@PE3jrV)oX^%5R zbnTh-CC|KiVizt~6a8Fby4*bZI`4TiOuPEJ*(QE0Dx2-ygvCWvN9=zf}cg zS*#4ozce*X*tvP)oDEBlsMQ=~^*n8Q)rg@co|)G$`^%U87yjCOU;bpz`J0~QT}#3$ zUG}X1dARg8-;&igug*7q%#IqWPbZd!&H;vI2{2?qq3Y}C=jrAe9HN(1oS#?Q=gW1- zK%n)zt?P*>n+EIFMcUzy+?Fh{n(FY+L#;8Ws{As`TGJP6(w@~CzvmV0bQPWKVBW%} zyQgLE)q88I)mURE^4vLiSI7Ls)>#&-qkCBdI#RmI9~7ubZt946G$p&D-1Geok1*Zh z3oRcie(Gqx@m<9C^;<~CowtuZsx1EcL3cXmDV6`ija>8n>)EnjJ)S9cW5 + + + + + %d{yyyy-MM-dd HH:mm:ss} | %-5p | [%thread] %logger{5}:%L - %msg%n + + + + + logFile.log + true + + %d{yyyy-MM-dd HH:mm:ss} | %-5p | [%thread] %logger{5}:%L - %msg%n + + + + + + + + + + + \ No newline at end of file diff --git a/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/startTest.sh b/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/startTest.sh index 933f9af6e4..76338b2082 100644 --- a/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/startTest.sh +++ b/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/files/default/startTest.sh @@ -93,7 +93,7 @@ if [ ${REMOTE_DEBUG} == "true" ]; then JAVA_OPTION="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=${debug_port}" ; fi -cmd="java $JAVA_OPTION -DdisplayException=true -Dtargetlog=${TARGET_LOG_DIR} -Dfilepath=${FILES_TEST} -Dconfig.resource=${CONF_FILE} -Ddebug=${DEBUG} -Dlog4j.configuration=${LOGS_PROP_FILE} -cp $JAR_FILE ${MainClass} $SUITE_FILE &" +cmd="java $JAVA_OPTION -Xms1024m -Xmx1024m -DdisplayException=true -Dtargetlog=${TARGET_LOG_DIR} -Dfilepath=${FILES_TEST} -Dconfig.resource=${CONF_FILE} -Ddebug=${DEBUG} -Dlog4j.configuration=${LOGS_PROP_FILE} -cp $JAR_FILE ${MainClass} $SUITE_FILE &" if [ $DEBUG == "true" ] @@ -108,7 +108,7 @@ if [ ${RERUN} == "true" ]; then echo "Prepare" ${TARGET_DIR}/${fileName} "file to rerun all failed tests ..."; prepareFailedXmlFile ${TARGET_DIR}/${fileName} $SUITE_FILE; SUITE_FILE=${fileName}; - cmd="java $JAVA_OPTION -DdisplayException=true -Dtargetlog=${TARGET_LOG_DIR} -Dfilepath=${FILES_TEST} -Dconfig.resource=${CONF_FILE} -Ddebug=${DEBUG} -Dlog4j.configuration=${LOGS_PROP_FILE} -cp $JAR_FILE ${MainClass} $SUITE_FILE &" + cmd="java $JAVA_OPTION -Xms1024m -Xmx1024m -DdisplayException=true -Dtargetlog=${TARGET_LOG_DIR} -Dfilepath=${FILES_TEST} -Dconfig.resource=${CONF_FILE} -Ddebug=${DEBUG} -Dlog4j.configuration=${LOGS_PROP_FILE} -cp $JAR_FILE ${MainClass} $SUITE_FILE &" $cmd; fi fi diff --git a/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/recipes/sanityTests_3_sanity_execution.rb b/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/recipes/sanityTests_3_sanity_execution.rb index c4323c233f..53482a7dd7 100644 --- a/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/recipes/sanityTests_3_sanity_execution.rb +++ b/sdc-os-chef/sdc-sanity/chef-repo/cookbooks/sdc-sanity/recipes/sanityTests_3_sanity_execution.rb @@ -6,7 +6,7 @@ cwd "#{tests_base}" code <<-EOH cd "#{tests_base}" jar_file=`ls test-apis*-jar-with-dependencies.jar` - ./startTest.sh $jar_file #{ci_test_suite} > #{tests_base}/target/startTest.out 2>&1 + ./startTest.sh $jar_file #{ci_test_suite} > #{tests_base}/target/startTest.log 2>&1 echo "return code from startTest.sh = [$?]" EOH timeout 72000 diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/ComponentBaseTest.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/ComponentBaseTest.java index b545145be8..fcbf3b2fee 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/ComponentBaseTest.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/ComponentBaseTest.java @@ -20,25 +20,15 @@ package org.openecomp.sdc.ci.tests.api; -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertNotNull; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.stream.Collectors; - +import com.aventstack.extentreports.ExtentTest; +import com.aventstack.extentreports.Status; +import com.thinkaurelius.titan.core.TitanFactory; +import com.thinkaurelius.titan.core.TitanGraph; +import com.thinkaurelius.titan.core.TitanVertex; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.ImmutableTriple; -import org.apache.log4j.Logger; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.junit.rules.TestName; @@ -47,11 +37,7 @@ import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.Product; -import org.openecomp.sdc.be.model.Resource; -import org.openecomp.sdc.be.model.Service; -import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.ci.tests.config.Config; import org.openecomp.sdc.ci.tests.datatypes.ResourceReqDetails; import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum; @@ -61,13 +47,8 @@ import org.openecomp.sdc.ci.tests.utils.cassandra.CassandraUtils; import org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils; import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; import org.openecomp.sdc.ci.tests.utils.general.FileHandling; -import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils; -import org.openecomp.sdc.ci.tests.utils.rest.CatalogRestUtils; -import org.openecomp.sdc.ci.tests.utils.rest.CategoryRestUtils; -import org.openecomp.sdc.ci.tests.utils.rest.ProductRestUtils; -import org.openecomp.sdc.ci.tests.utils.rest.ResourceRestUtils; -import org.openecomp.sdc.ci.tests.utils.rest.ResponseParser; -import org.openecomp.sdc.ci.tests.utils.rest.ServiceRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.*; +import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.ITestContext; import org.testng.ITestResult; @@ -78,20 +59,23 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.aventstack.extentreports.ExtentTest; -import com.aventstack.extentreports.Status; -import com.thinkaurelius.titan.core.TitanFactory; -import com.thinkaurelius.titan.core.TitanGraph; -import com.thinkaurelius.titan.core.TitanVertex; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertNotNull; + + -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.LoggerContext; public abstract class ComponentBaseTest { // private static Logger logger = LoggerFactory.getLogger(ComponentBaseTest.class.getName()); - - protected static Logger logger= Logger.getLogger(ComponentBaseTest.class); + protected static Logger logger= LoggerFactory.getLogger(ComponentBaseTest.class); // public ComponentBaseTest(TestName testName, String className) { @@ -118,12 +102,15 @@ public abstract class ComponentBaseTest { public ComponentBaseTest(TestName name, String name2) { // TODO Auto-generated constructor stub - LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); - lc.getLogger("com.thinkaurelius").setLevel(Level.INFO); - lc.getLogger("com.datastax").setLevel(Level.INFO); - lc.getLogger("io.netty").setLevel(Level.INFO); - lc.getLogger("c.d").setLevel(Level.INFO); - } +// LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); +// lc.getLogger("com.thinkaurelius").setLevel(Level.INFO); +// lc.getLogger("com.datastax").setLevel(Level.INFO); +// lc.getLogger("io.netty").setLevel(Level.INFO); +// lc.getLogger("c.d").setLevel(Level.INFO); +// lc.getLogger("o.a.h").setLevel(Level.INFO); +// lc.getLogger("o.o.s.c.t.d.h").setLevel(Level.INFO); + +} public static String getReportFolder() { return REPORT_FOLDER; diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/run/StartTest.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/run/StartTest.java index 9bb14d7f50..8bc967c877 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/run/StartTest.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/run/StartTest.java @@ -34,8 +34,9 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.openecomp.sdc.ci.tests.config.Config; import org.openecomp.sdc.ci.tests.utils.Utils; //import org.junit.runner.JUnitCore; @@ -94,7 +95,7 @@ public class StartTest { } public StartTest() { - logger = Logger.getLogger(StartTest.class.getName()); + logger = LoggerFactory.getLogger(StartTest.class.getName()); } public static void enableLogger() { diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/sanity/Onboard.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/sanity/Onboard.java index 8764779c02..0f339b811c 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/sanity/Onboard.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/sanity/Onboard.java @@ -21,9 +21,9 @@ package org.openecomp.sdc.ci.tests.sanity; - - - +import com.aventstack.extentreports.Status; +import com.clearspring.analytics.util.Pair; +import fj.data.Either; import org.junit.Rule; import org.junit.rules.TestName; import org.openecomp.sdc.be.datatypes.enums.AssetTypeEnum; @@ -52,11 +52,6 @@ import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; -import com.aventstack.extentreports.Status; -import com.clearspring.analytics.util.Pair; - -import fj.data.Either; - import java.io.File; @@ -86,7 +81,8 @@ public class Onboard extends ComponentBaseTest { @Test(dataProviderClass = OnboardingDataProviders.class, dataProvider = "VNF_List") public void onboardVNFShotFlow(String filepath, String vnfFile) throws Exception, Throwable { setLog(vnfFile); - System.out.println("print - >" + makeDistributionValue); + logger.info("Onboarding - > " + vnfFile); +// System.out.println("Onboarding - > " + vnfFile); runOnboardToDistributionFlow(filepath, vnfFile); } diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResponseParser.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResponseParser.java index 7789231c22..c4b9764c96 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResponseParser.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResponseParser.java @@ -187,7 +187,7 @@ public class ResponseParser { Resource resource = null; try { // TODO Andrey L. uncomment line below in case to ignore on unknown properties, not recommended -// mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); resource = mapper.readValue(response, Resource.class); logger.debug(resource.toString()); diff --git a/test-apis-ci/src/main/resources/logback.xml b/test-apis-ci/src/main/resources/logback.xml index 4723bc24cb..4b5e23c776 100644 --- a/test-apis-ci/src/main/resources/logback.xml +++ b/test-apis-ci/src/main/resources/logback.xml @@ -15,9 +15,9 @@ - + - + -- 2.16.6