From e601bbdc43bae9a08e2e10c5139a6f76b47860d7 Mon Sep 17 00:00:00 2001 From: Einat Vinouze Date: Tue, 16 Jul 2019 17:17:36 +0300 Subject: Implant vid-app-common org.onap.vid.job (main and test) Issue-ID: VID-378 Change-Id: I41b0bdc2c4e3635f3f3319b1cd63cefc61912dfc Signed-off-by: Einat Vinouze Signed-off-by: Ittay Stern --- .../java/org/onap/vid/services/AAIServiceTree.java | 124 ++-- .../org/onap/vid/services/AAITreeNodeBuilder.java | 341 +++++----- .../java/org/onap/vid/services/AaiService.java | 2 +- .../java/org/onap/vid/services/AaiServiceImpl.java | 47 +- .../services/AsyncInstantiationBusinessLogic.java | 66 +- .../AsyncInstantiationBusinessLogicImpl.java | 711 +++++++-------------- .../java/org/onap/vid/services/AuditService.java | 24 +- .../org/onap/vid/services/AuditServiceImpl.java | 189 ++++-- .../org/onap/vid/services/CloudOwnerService.java | 4 +- .../vid/services/RoleGenaratorServiceImpl.java | 2 +- .../java/org/onap/vid/services/VersionService.kt | 66 ++ 11 files changed, 771 insertions(+), 805 deletions(-) create mode 100644 vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt (limited to 'vid-app-common/src/main/java/org/onap/vid/services') diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java b/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java index 6199c4e58..d62d5d5d4 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,7 +21,6 @@ package org.onap.vid.services; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.AaiClientInterface; @@ -31,21 +30,24 @@ import org.onap.vid.asdc.parser.ServiceModelInflator; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.model.aaiTree.ServiceInstance; import org.onap.vid.utils.Tree; +import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import javax.inject.Inject; import javax.ws.rs.core.Response; import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; +import java.util.stream.Stream; -import static java.lang.Thread.sleep; import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toSet; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; -import static org.onap.vid.services.AAITreeNodeBuilder.*; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; @Component public class AAIServiceTree { @@ -60,38 +62,58 @@ public class AAIServiceTree { private final ServiceModelInflator serviceModelInflator; - private final ObjectMapper mapper = new ObjectMapper(); + private final ExecutorService executorService; private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AAIServiceTree.class); public static final Tree AAI_TREE_PATHS = - new Tree<>(new AaiRelationship(SERVICE_INSTANCE)); + new Tree<>(new AaiRelationship(NodeType.SERVICE_INSTANCE)); static { - AAI_TREE_PATHS.addPath(toAaiRelationshipList(GENERIC_VNF, VG)); - AAI_TREE_PATHS.addPath(toAaiRelationshipList(NETWORK)); - AAI_TREE_PATHS.addPath(toAaiRelationshipList(GENERIC_VNF, NETWORK)); - AAI_TREE_PATHS.addPath(toAaiRelationshipList(INSTANCE_GROUP)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.VOLUME_GROUP)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.VF_MODULE)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.NETWORK, NodeType.VPN_BINDING)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.NETWORK, NodeType.VPN_BINDING)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.INSTANCE_GROUP, NodeType.GENERIC_VNF)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.COLLECTION_RESOURCE, NodeType.INSTANCE_GROUP)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.CONFIGURATION, NodeType.NETWORK, NodeType.VPN_BINDING)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.CONFIGURATION, NodeType.VPN_BINDING)); + } + + public static List toAaiRelationshipList(NodeType... types) { + return Stream.of(types).map(AAIServiceTree.AaiRelationship::new).collect(Collectors.toList()); } @Inject public AAIServiceTree(AaiClientInterface aaiClient, AAITreeNodeBuilder aaiTreeNodeBuilder, AAITreeConverter aaiTreeConverter, VidService sdcService, - ServiceModelInflator serviceModelInflator) { + ServiceModelInflator serviceModelInflator, ExecutorService executorService) { this.aaiClient = aaiClient; this.aaiTreeNodeBuilder = aaiTreeNodeBuilder; this.aaiTreeConverter = aaiTreeConverter; this.sdcService = sdcService; this.serviceModelInflator = serviceModelInflator; + this.executorService = executorService; + } + + List buildAAITreeForUniqueResource(String getUrl, NodeType nodeType) { + return buildAAITreeForUniqueResourceFromCustomQuery(getUrl, null, HttpMethod.GET, nodeType); + } + + List buildAAITreeForUniqueResourceFromCustomQuery(String url, String payload, HttpMethod method, NodeType nodeType) { + Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(nodeType)); + return buildAAITree(url, payload, method, pathsToSearch, false); } - public List buildAAITree(String getUrl, Tree pathsToSearch) { + public List buildAAITree(String url, String payload, HttpMethod method, Tree pathsToSearch, boolean enrichWithModelVersion) { ConcurrentSkipListSet nodesAccumulator = createNodesAccumulator(); - List aaiTreeNodes = fetchAAITree(getUrl, pathsToSearch, nodesAccumulator, true); + List aaiTreeNodes = fetchAAITree(url, payload, method, pathsToSearch, nodesAccumulator); - enrichNodesWithModelVersionAndModelName(nodesAccumulator); + if (enrichWithModelVersion) { + enrichNodesWithModelVersionAndModelName(nodesAccumulator); + } return aaiTreeNodes; } @@ -105,7 +127,7 @@ public class AAIServiceTree { //Used later to get the nodes UUID ConcurrentSkipListSet nodesAccumulator = createNodesAccumulator(); - AAITreeNode aaiTree = fetchAAITree(getURL, AAI_TREE_PATHS, nodesAccumulator, false).get(0); + AAITreeNode aaiTree = fetchAAITree(getURL, null, HttpMethod.GET, AAI_TREE_PATHS, nodesAccumulator).get(0); //Populate nodes with model-name & model-version (from aai) enrichNodesWithModelVersionAndModelName(nodesAccumulator); @@ -115,28 +137,28 @@ public class AAIServiceTree { //Populate nodes with model-customization-name (from sdc model) enrichNodesWithModelCustomizationName(nodesAccumulator, serviceModel); - return aaiTreeConverter.convertTreeToUIModel(aaiTree, globalCustomerId, serviceType, getInstantiationType(serviceModel)); + return aaiTreeConverter.convertTreeToUIModel(aaiTree, globalCustomerId, serviceType, getInstantiationType(serviceModel), getInstanceRole(serviceModel), getInstanceType(serviceModel)); } - private List fetchAAITree(String getUrl, Tree pathsToSearch, - ConcurrentSkipListSet nodesAccumulator, boolean partialTreeOnTimeout) { - ThreadPoolExecutor threadPool = getThreadPool(); - - List aaiTree = aaiTreeNodeBuilder.buildNode(SERVICE_INSTANCE, - getUrl, defaultIfNull(nodesAccumulator, createNodesAccumulator()), - threadPool, new ConcurrentLinkedQueue<>(), - new AtomicInteger(0), pathsToSearch); - - boolean timeoutOccurred = waitForTreeFetch(threadPool); + private String getInstanceType(ServiceModel serviceModel){ + if (serviceModel != null && serviceModel.getService() != null) { + return serviceModel.getService().getServiceType(); + } + return ""; + } - if (timeoutOccurred) { - if (!partialTreeOnTimeout) { - throw new GenericUncheckedException("Timeout on fetchAAITree. Fetched " + nodesAccumulator.size() + " nodes for url: " + getUrl); - } - LOGGER.warn(EELFLoggerDelegate.errorLogger, "Timeout on fetchAAITree for url: " + getUrl); + private String getInstanceRole(ServiceModel serviceModel) { + if (serviceModel != null && serviceModel.getService() != null) { + return serviceModel.getService().getServiceRole(); } + return ""; + } - return aaiTree; + private List fetchAAITree(String url, String payload, HttpMethod method, Tree pathsToSearch, + ConcurrentSkipListSet nodesAccumulator) { + return aaiTreeNodeBuilder.buildNode(NodeType.fromString(pathsToSearch.getRootValue().type), + url, payload, method, defaultIfNull(nodesAccumulator, createNodesAccumulator()), + executorService, pathsToSearch); } private ConcurrentSkipListSet createNodesAccumulator() { @@ -204,12 +226,12 @@ public class AAIServiceTree { private JsonNode getModels(AaiClientInterface aaiClient, Collection invariantIDs) { Response response = aaiClient.getVersionByInvariantId(ImmutableList.copyOf(invariantIDs)); try { - JsonNode responseJson = mapper.readTree(response.readEntity(String.class)); + JsonNode responseJson = JACKSON_OBJECT_MAPPER.readTree(response.readEntity(String.class)); return responseJson.get("model"); } catch (Exception e) { LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to getVersionByInvariantId from A&AI", e); } - return mapper.createObjectNode(); + return JACKSON_OBJECT_MAPPER.createObjectNode(); } private Set getModelInvariantIds(Collection nodes) { @@ -219,30 +241,6 @@ public class AAIServiceTree { .collect(toSet()); } - private boolean waitForTreeFetch(ThreadPoolExecutor threadPool) { - int timer = 60; - try { - //Stop fetching information if it takes more than 1 minute - while (threadPool.getActiveCount() != 0 && - timer > 0) { - sleep(1000); - timer--; - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new GenericUncheckedException(e); - } - threadPool.shutdown(); - return (timer == 0); - } - - private ThreadPoolExecutor getThreadPool() { - //Use at least one thread, and never more than 75% of the available thread. - int cores = Math.max((int)(Runtime.getRuntime().availableProcessors() * 0.75), 1); - BlockingQueue queue = new LinkedBlockingQueue<>(); - return new ThreadPoolExecutor(1, cores, 10, TimeUnit.SECONDS, queue); - } - public static class AaiRelationship { public final String type; @@ -251,6 +249,10 @@ public class AAIServiceTree { this.type = type; } + public AaiRelationship(NodeType nodeType) { + this.type = nodeType.getType(); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java b/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java index e06088264..d53eba8d3 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,66 +21,49 @@ package org.onap.vid.services; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.NotNull; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.aai.AaiClientInterface; import org.onap.vid.aai.ExceptionWithRequestInfo; import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipData; import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList; +import org.onap.vid.aai.util.AAITreeNodeUtils; +import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.model.aaiTree.FailureAAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; +import org.onap.vid.mso.model.CloudConfiguration; +import org.onap.vid.properties.VidProperties; import org.onap.vid.utils.Streams; import org.onap.vid.utils.Tree; import org.onap.vid.utils.Unchecked; +import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import javax.inject.Inject; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.*; +import java.util.concurrent.*; import java.util.stream.Collectors; import java.util.stream.Stream; import static java.util.stream.Collectors.*; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; import static org.onap.vid.utils.Streams.not; @Component public class AAITreeNodeBuilder { + private static final String RESULTS = "results"; private AaiClientInterface aaiClient; - private final ObjectMapper mapper = new ObjectMapper(); - private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AAITreeNodeBuilder.class); - //List of all the node types the tree should include - public static final String SERVICE_INSTANCE = "service-instance"; - public static final String GENERIC_VNF = "generic-vnf"; - public static final String NETWORK = "l3-network"; - public static final String FAILURE = "failure_node"; - public static final String COLLECTION_RESOURCE = "collection"; - public static final String CONFIGURATION = "configuration"; - public static final String PNF = "pnf"; - public static final String VF_MODULE = "vf-module"; - public static final String INSTANCE_GROUP = "instance-group"; - public static final String PORT = "l-interface"; - public static final String VG = "volume-group"; - public static final String VLAN_TAG = "vlan-tag"; - - //Hashmap that defines the node-type and the tag that should be used to find it's ID key in the JSON. - private static HashMap nodeTypeToIdKeyMap = generateTypeToIdKeyMap(); - - //Hashmap that defines the node-type and the tag that should be used to find it's NAMR key in the JSON. - private static HashMap nodeTypeToNameKeyMap = generateTypeToNameKeyMap(); public enum AAIBaseProperties { ORCHESTRATION_STATUS("orchestration-status"), @@ -102,63 +85,121 @@ public class AAITreeNodeBuilder { } } - public static List toAaiRelationshipList(String... types) { - return Stream.of(types).map(AAIServiceTree.AaiRelationship::new).collect(Collectors.toList()); - } - @Inject public AAITreeNodeBuilder(AaiClientInterface aaiClient) { this.aaiClient = aaiClient; } - public List buildNode(String nodeType, - String requestURL, - ConcurrentSkipListSet nodesAccumulator, ExecutorService threadPool, - ConcurrentLinkedQueue visitedNodes, - AtomicInteger nodesCounter, - Tree pathsTree) { + List buildNode(NodeType nodeType, + String requestURL, + String payload, + HttpMethod method, + ConcurrentSkipListSet nodesAccumulator, + ExecutorService threadPool, + Tree pathsTree) { - JsonNode topLevelJson = aaiClient.typedAaiGet(Unchecked.toURI(requestURL), JsonNode.class); + JsonNode jsonNode = aaiClient.typedAaiRest(Unchecked.toURI(requestURL), JsonNode.class, payload, method, false); - if (topLevelJson.has(nodeType) && topLevelJson.get(nodeType).isArray()) { - return Streams.fromIterable(topLevelJson.get(nodeType)) - .map(item -> parseNodeAndGetChildren(nodeType, requestURL, item, - nodesAccumulator, threadPool, visitedNodes, nodesCounter, pathsTree)) - .collect(toList()); - } else { - return ImmutableList.of(parseNodeAndGetChildren(nodeType, requestURL, topLevelJson, - nodesAccumulator, threadPool, visitedNodes, nodesCounter, pathsTree)); + List>> nodes = getNodesWithRelationships(jsonNode, nodeType, nodesAccumulator, pathsTree); + + String timeout = SystemProperties.getProperty(VidProperties.VID_THREAD_TIMEOUT); + long timeoutNum = Long.parseLong(StringUtils.defaultIfEmpty(timeout, "30")); + + for (Pair> entry : nodes) { + fetchChildrenAsync(threadPool, nodesAccumulator, entry.getKey(), entry.getValue(), pathsTree, timeoutNum); + + if (getNextLevelInPathsTree(pathsTree, NodeType.VF_MODULE.getType()) != null) { + getRelatedVfModules(threadPool, nodesAccumulator, requestURL, entry.getKey()); + } } + + return nodes.stream() + .map(Pair::getKey) + .collect(Collectors.toList()); } - private AAITreeNode parseNodeAndGetChildren(String nodeType, - String requestURL, - JsonNode topLevelJson, - ConcurrentSkipListSet nodesAccumulator, ExecutorService threadPool, - ConcurrentLinkedQueue visitedNodes, - AtomicInteger nodesCounter, - Tree pathsTree) { - AAITreeNode node = jsonToAaiNode(nodeType, topLevelJson, nodesAccumulator, nodesCounter); - - RelationshipList relationships = mapper.convertValue(topLevelJson.get(AAIBaseProperties.RELATIONSHIP_LIST.getAaiKey()), RelationshipList.class); - if (relationships != null) { - getChildren(threadPool, nodesAccumulator, relationships.getRelationship(), visitedNodes, node, nodesCounter, pathsTree); - } - if (StringUtils.equals(node.getType(), GENERIC_VNF)) { - getRelatedVfModules(threadPool, nodesAccumulator, requestURL, node, nodesCounter); + private List>> getNodesWithRelationships(JsonNode jsonNode, NodeType nodeType, + ConcurrentSkipListSet nodesAccumulator, + Tree pathsTree) { + if (isListOfKeyResults(jsonNode)) { + return Streams.fromIterable(jsonNode.get(RESULTS)) + .filter(item -> item.has(nodeType.getType())) + .map(item -> item.get(nodeType.getType())) + .map(item -> parseNodeAndFilterRelationships(item, nodeType, nodesAccumulator, pathsTree)) + .collect(Collectors.toList()); + } else if (isArray(jsonNode, nodeType)) { + return Streams.fromIterable(jsonNode.get(nodeType.getType())) + .map(item -> parseNodeAndFilterRelationships(item, nodeType, nodesAccumulator, pathsTree)) + .collect(Collectors.toList()); + } else { + return ImmutableList.of(parseNodeAndFilterRelationships(jsonNode, nodeType, nodesAccumulator, pathsTree)); } - return node; } - private AAITreeNode jsonToAaiNode(String nodeType, JsonNode topLevelJson, ConcurrentSkipListSet nodesAccumulator, AtomicInteger nodesCounter) { - AAITreeNode node = fillNodeMetaData(nodeType, topLevelJson, nodesCounter); + Pair> parseNodeAndFilterRelationships(JsonNode jsonNode, NodeType nodeType, + ConcurrentSkipListSet nodesAccumulator, + Tree pathsTree) { + AAITreeNode node = createAaiNode(nodeType, jsonNode, nodesAccumulator); + + enrichPlacementData(node); + + List filteredRelationships = getFilteredRelationships(jsonNode, pathsTree); + + return ImmutablePair.of(node, filteredRelationships); + } + + boolean isArray(JsonNode json, NodeType nodeType) { + return json != null && json.has(nodeType.getType()) && json.get(nodeType.getType()).isArray(); + } + + boolean isListOfKeyResults(JsonNode jsonNode) { + return jsonNode != null && jsonNode.has(RESULTS) && jsonNode.get(RESULTS).isArray(); + } + + AAITreeNode createAaiNode(NodeType nodeType, JsonNode jsonNode, ConcurrentSkipListSet nodesAccumulator) { + AAITreeNode node = jsonNodeToAaiNode(nodeType, jsonNode); nodesAccumulator.add(node); return node; } - private void getRelatedVfModules(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, String parentURL, AAITreeNode parentNode, AtomicInteger nodesCounter) { + private void addChildren(AAITreeNode node, Future> children) { + try { + node.addChildren(children.get()); + } catch (Exception e) { + node.getChildren().add(createFailureNode(e)); + } + } + + private Map convertRelationshipDataToMap(List relationshipData) { + return relationshipData.stream().collect( + Collectors.toMap(RelationshipData::getKey, RelationshipData::getValue)); + } + + void enrichPlacementData(AAITreeNode node){ + Optional tenantRelationShip = AAITreeNodeUtils.findFirstRelationshipByRelatedTo(node.getRelationshipList(), "tenant"); + enrichPlacementDataUsingTenantInfo(node, tenantRelationShip); + } + + void enrichPlacementDataUsingTenantInfo(AAITreeNode node, Optional tenantRelationShip) { + //no tenant relationship in this node - so no placement data + if (!tenantRelationShip.isPresent()) { + return; + } + try { + Map relationshipsDataMap = convertRelationshipDataToMap(tenantRelationShip.get().getRelationDataList()); + node.setCloudConfiguration(new CloudConfiguration( + relationshipsDataMap.get("cloud-region.cloud-region-id"), + relationshipsDataMap.get("tenant.tenant-id"), + relationshipsDataMap.get("cloud-region.cloud-owner"))); + } + catch (Exception exception) { + LOGGER.error("Failed to extract placement form tenant relationship of {}:{}", node.getType(), node.getId(), exception); + } + } + + private void getRelatedVfModules(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, String parentURL, AAITreeNode parentNode) { /* VNFs do not report their direct related-to vf-modules, so try directly fetching a resource URI. @@ -166,73 +207,100 @@ public class AAITreeNodeBuilder { threadPool.execute(() -> { // the response is an array of vf-modules - final JsonNode topLevelJson; + final JsonNode jsonNode; try { - topLevelJson = aaiClient.typedAaiGet(Unchecked.toURI(parentURL + "/vf-modules"), JsonNode.class); + jsonNode = aaiClient.typedAaiGet(Unchecked.toURI(parentURL + "/vf-modules"), JsonNode.class); } catch (ExceptionWithRequestInfo e) { if (e.getHttpCode().equals(404)) { // it's ok, as we're just optimistically fetching - // the /vf-modules uri; 404 says this time it was - // a bad guess + // the /vf-modules uri; 404 says this time it was a bad guess return; } else { throw e; } } - if (topLevelJson != null) { - parentNode.getChildren().addAll( - Streams.fromIterable(topLevelJson.get(VF_MODULE)) - .map(vfModuleNode -> jsonToAaiNode(VF_MODULE, vfModuleNode, nodesAccumulator, nodesCounter)) - .collect(toList()) - ); + if (isArray(jsonNode, NodeType.VF_MODULE)) { + + //create list of AAITreeNode represent the VfModules from AAI result + List vfModules = Streams.fromIterable(jsonNode.get(NodeType.VF_MODULE.getType())) + .map(vfModuleNode -> createAaiNode(NodeType.VF_MODULE, vfModuleNode, nodesAccumulator)) + .collect(toList()); + //enrich each of the VfModule with placement info + vfModules.forEach(vfModule-> enrichPlacementDataUsingTenantInfo( + vfModule, + AAITreeNodeUtils.findFirstRelationshipByRelatedTo(vfModule.getRelationshipList(), "vserver") + )); + //add all VfModules to children list of parent node + parentNode.getChildren().addAll(vfModules); } else { LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to get vf-modules for vnf " + parentNode.getId()); } }); } - private void getChildren(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, - List relationships, ConcurrentLinkedQueue visitedNodes, AAITreeNode parent, AtomicInteger nodesCounter, Tree pathsTree) { - for (Relationship relationship : relationships) { - createChildNode(threadPool, nodesAccumulator, relationship, visitedNodes, parent, nodesCounter, pathsTree); + List getFilteredRelationships(JsonNode json, Tree pathsTree) { + RelationshipList relationshipList = JACKSON_OBJECT_MAPPER.convertValue(json.get(AAIBaseProperties.RELATIONSHIP_LIST.getAaiKey()), RelationshipList.class); + if (relationshipList != null) { + return relationshipList.getRelationship().stream() + .filter(rel -> getNextLevelInPathsTree(pathsTree, rel.getRelatedTo()) != null) + .filter(rel -> !Objects.equals(rel.getRelatedTo(), NodeType.VF_MODULE.getType())) // vf-modules are handled separately + .collect(toList()); } + + return Collections.emptyList(); } - private void createChildNode(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, - Relationship relationship, ConcurrentLinkedQueue visitedNodes, AAITreeNode parent, AtomicInteger nodesCounter, Tree pathsTree) { - String newNodeType = relationship.getRelatedTo(); - Tree subTree = pathsTree.getSubTree(new AAIServiceTree.AaiRelationship(newNodeType)); - if (subTree!=null) { - String newNodeUrl = relationship.getRelatedLink(); - if (!visitedNodes.contains(newNodeUrl)) { - visitedNodes.add(newNodeUrl); - threadPool.execute(() -> { - try { - parent.addChildren(buildNode(newNodeType, newNodeUrl, nodesAccumulator, threadPool, visitedNodes, nodesCounter, subTree)); - } catch (Exception e) { - parent.getChildren().add(createFailureNode(e)); - } - } - ); + void fetchChildrenAsync(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, + AAITreeNode node, List relationships, Tree pathsTree, long timeout) { + + if (!relationships.isEmpty()) { + List>> tasks = relationships.stream() + .map(relationship -> + (Callable>) () -> + getChildNode(threadPool, nodesAccumulator, relationship.getRelatedTo(), + relationship.getRelatedLink(), pathsTree)) + .collect(Collectors.toList()); + + try { + int depth = pathsTree.getChildrenDepth(); + threadPool.invokeAll(tasks, timeout * depth, TimeUnit.SECONDS) + .forEach(future -> + addChildren(node, future) + ); + } catch (Exception e) { + throw new GenericUncheckedException(e); } } } - private AAITreeNode fillNodeMetaData(String nodeType, JsonNode model, @NotNull AtomicInteger nodesCounter) { + private List getChildNode(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, + String childNodeType, String childNodeUrl, + Tree pathsTree) { + + Tree subTree = getNextLevelInPathsTree(pathsTree, childNodeType); + + return buildNode(NodeType.fromString(childNodeType), childNodeUrl, null, HttpMethod.GET, nodesAccumulator, threadPool, subTree); + } + + Tree getNextLevelInPathsTree(Tree pathsTree, String nodeType) { + return pathsTree.getSubTree(new AAIServiceTree.AaiRelationship(nodeType)); + } + + //ADD TEST + private AAITreeNode jsonNodeToAaiNode(NodeType nodeType, JsonNode jsonNode) { AAITreeNode node = new AAITreeNode(); node.setType(nodeType); - node.setUniqueNumber(nodesCounter.getAndIncrement()); - node.setOrchestrationStatus(getStringDataFromJsonIfExists(model, AAIBaseProperties.ORCHESTRATION_STATUS.getAaiKey())); - node.setProvStatus(getStringDataFromJsonIfExists(model, AAIBaseProperties.PROV_STATUS.getAaiKey())); - node.setInMaint(getBooleanDataFromJsonIfExists(model, AAIBaseProperties.IN_MAINT.getAaiKey())); - node.setModelVersionId(getStringDataFromJsonIfExists(model, AAIBaseProperties.MODEL_VERSION_ID.getAaiKey())); - node.setModelCustomizationId(getStringDataFromJsonIfExists(model, AAIBaseProperties.MODEL_CUSTOMIZATION_ID.getAaiKey())); - node.setModelInvariantId(getStringDataFromJsonIfExists(model, AAIBaseProperties.MODEL_INVARIANT_ID.getAaiKey())); - node.setId(getStringDataFromJsonIfExists(model, nodeTypeToIdKeyMap.get(nodeType))); - node.setName(getStringDataFromJsonIfExists(model, nodeTypeToNameKeyMap.get(nodeType))); - node.setAdditionalProperties(aggregateAllOtherProperties(model, nodeType)); - + node.setOrchestrationStatus(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.ORCHESTRATION_STATUS.getAaiKey())); + node.setProvStatus(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.PROV_STATUS.getAaiKey())); + node.setInMaint(getBooleanDataFromJsonIfExists(jsonNode, AAIBaseProperties.IN_MAINT.getAaiKey())); + node.setModelVersionId(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.MODEL_VERSION_ID.getAaiKey())); + node.setModelCustomizationId(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.MODEL_CUSTOMIZATION_ID.getAaiKey())); + node.setModelInvariantId(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.MODEL_INVARIANT_ID.getAaiKey())); + node.setId(getStringDataFromJsonIfExists(jsonNode, nodeType.getId())); + node.setName(getStringDataFromJsonIfExists(jsonNode, nodeType.getName())); + node.setAdditionalProperties(aggregateAllOtherProperties(jsonNode, nodeType)); + node.setRelationshipList(JACKSON_OBJECT_MAPPER.convertValue(jsonNode.get(AAIBaseProperties.RELATIONSHIP_LIST.getAaiKey()), RelationshipList.class)); return node; } @@ -241,7 +309,7 @@ public class AAITreeNodeBuilder { } private String getStringDataFromJsonIfExists(JsonNode model, String key) { - if (model.has(key)) { + if (!NodeType.NONE.equals(key) && model.has(key)) { return model.get(key).asText(); } return null; @@ -254,48 +322,17 @@ public class AAITreeNodeBuilder { return false; } - private Map aggregateAllOtherProperties(JsonNode model, String nodeType) { + Map aggregateAllOtherProperties(JsonNode model, NodeType nodeType) { Set ignoreProperties = Stream.of(AAIBaseProperties.values()) .map(AAIBaseProperties::getAaiKey).collect(toSet()); - return Streams.fromIterator(model.fields()) - .filter(not(field -> StringUtils.equals(field.getKey(), nodeTypeToIdKeyMap.get(nodeType)))) - .filter(not(field -> StringUtils.equals(field.getKey(), nodeTypeToNameKeyMap.get(nodeType)))) + .filter(not(field -> StringUtils.equals(field.getKey(), nodeType.getId()))) + .filter(not(field -> StringUtils.equals(field.getKey(), nodeType.getName()))) .filter(not(field -> ignoreProperties.contains(field.getKey()))) - .collect(toMap(Map.Entry::getKey, v -> v.getValue().asText())); - } - - private static HashMap generateTypeToIdKeyMap() { - HashMap result = new HashMap<>(); - result.put(SERVICE_INSTANCE, "service-instance-id"); - result.put(GENERIC_VNF, "vnf-id"); - result.put(NETWORK, "network-id"); - result.put(COLLECTION_RESOURCE, "collection-id"); - result.put(CONFIGURATION, "configuration-id"); - result.put(PNF, "pnf-id"); - result.put(VF_MODULE, "vf-module-id"); - result.put(INSTANCE_GROUP, "id"); - result.put(PORT, "l-interface-id"); - result.put(VG, "volume-group-id"); - result.put(VLAN_TAG, "vlan-id"); - - return result; + .collect(toMap(Map.Entry::getKey, v -> ifTextualGetAsText(v.getValue()))); } - private static HashMap generateTypeToNameKeyMap() { - HashMap result = new HashMap<>(); - result.put(SERVICE_INSTANCE, "service-instance-name"); - result.put(GENERIC_VNF, "vnf-name"); - result.put(NETWORK, "network-name"); - result.put(COLLECTION_RESOURCE, "collection-name"); - result.put(CONFIGURATION, "configuration-name"); - result.put(PNF, "pnf-name"); - result.put(VF_MODULE, "vf-module-name"); - result.put(INSTANCE_GROUP, "instance-group-name"); - result.put(PORT, "l-interface-name"); - result.put(VG, "volume-group-name"); - result.put(VLAN_TAG, "vlan-name"); - - return result; + private Object ifTextualGetAsText(JsonNode jsonNode) { + return jsonNode.isTextual() ? jsonNode.asText() : jsonNode; } -} +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java b/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java index 910b34112..76efbd0ea 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java @@ -48,7 +48,7 @@ public interface AaiService { SubscriberFilteredResults getFullSubscriberList(RoleValidator roleValidator); - AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator); + AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator, boolean omitServiceInstances); AaiResponse getServiceInstanceSearchResults(String subscriberId, String instanceIdentifier, RoleValidator roleProvider, List owningEntities, List projects); diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java index d01f0f7ad..961f11096 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java @@ -24,6 +24,7 @@ package org.onap.vid.services; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.joshworks.restclient.http.HttpResponse; +import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpStatus; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.*; @@ -39,16 +40,19 @@ import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.ServiceInstanceSearchResult; import org.onap.vid.model.SubscriberList; import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.model.aaiTree.RelatedVnf; import org.onap.vid.roles.RoleValidator; import org.onap.vid.utils.Intersection; import org.onap.vid.utils.Tree; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; import javax.ws.rs.core.Response; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.*; +import java.util.concurrent.ExecutorService; import java.util.stream.Collectors; /** @@ -68,6 +72,8 @@ public class AaiServiceImpl implements AaiService { private AaiResponseTranslator aaiResponseTranslator; private AAITreeNodeBuilder aaiTreeNode; private AAIServiceTree aaiServiceTree; + private ExecutorService executorService; + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AaiServiceImpl.class); @@ -77,13 +83,15 @@ public class AaiServiceImpl implements AaiService { AaiOverTLSClientInterface aaiOverTLSClient, AaiResponseTranslator aaiResponseTranslator, AAITreeNodeBuilder aaiTreeNode, - AAIServiceTree aaiServiceTree) + AAIServiceTree aaiServiceTree, + ExecutorService executorService) { this.aaiClient = aaiClient; this.aaiOverTLSClient = aaiOverTLSClient; this.aaiResponseTranslator = aaiResponseTranslator; this.aaiTreeNode = aaiTreeNode; this.aaiServiceTree = aaiServiceTree; + this.executorService = executorService; } private List convertModelToService(Model model) { @@ -220,8 +228,8 @@ public class AaiServiceImpl implements AaiService { } @Override - public AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator) { - AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId); + public AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator, boolean omitServiceInstances) { + AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId, omitServiceInstances); String subscriberGlobalId = subscriberResponse.getT().globalCustomerId; for (ServiceSubscription serviceSubscription : subscriberResponse.getT().serviceSubscriptions.serviceSubscription) { String serviceType = serviceSubscription.serviceType; @@ -254,7 +262,7 @@ public class AaiServiceImpl implements AaiService { private List getServicesBySubscriber(String subscriberId, String instanceIdentifier, RoleValidator roleValidator) { - AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId); + AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId, false); String subscriberGlobalId = subscriberResponse.getT().globalCustomerId; String subscriberName = subscriberResponse.getT().subscriberName; ServiceSubscriptions serviceSubscriptions = subscriberResponse.getT().serviceSubscriptions; @@ -483,26 +491,37 @@ public class AaiServiceImpl implements AaiService { @Override public List searchGroupMembers(String globalCustomerId, String serviceType, String invariantId, String groupType, String groupRole) { String getURL = "business/customers/customer/" + - globalCustomerId + "/service-subscriptions/service-subscription/" + - serviceType + "/service-instances?model-invariant-id=" + invariantId; + globalCustomerId + "/service-subscriptions/service-subscription/" + + serviceType + "/service-instances?model-invariant-id=" + invariantId; - Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(AAITreeNodeBuilder.SERVICE_INSTANCE)); - pathsToSearch.addPath(AAITreeNodeBuilder.toAaiRelationshipList(AAITreeNodeBuilder.GENERIC_VNF, AAITreeNodeBuilder.INSTANCE_GROUP)); + Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(NodeType.SERVICE_INSTANCE)); + pathsToSearch.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.INSTANCE_GROUP)); //get all vnfs related to service-instances from the model-invariant-id - List aaiTree = aaiServiceTree.buildAAITree(getURL, pathsToSearch); + List aaiTree = aaiServiceTree.buildAAITree(getURL, null, HttpMethod.GET, pathsToSearch, true); //filter by instance-group-role & instance-group-type properties (from getAdditionalProperties) //only vnfs has related instance-group with the same groupType & groupRole - are filtered out. List filteredVnfs = filterByInstanceGroupRoleAndType(aaiTree, groupRole, groupType); //convert vnfs to expected result - return filteredVnfs.stream() + List convertedVnfs = filteredVnfs.stream() .map(RelatedVnf::from) - .map(this::enrichRelatedVnfWithCloudRegionAndTenant) .collect(Collectors.toList()); + + try { + return executorService.submit(() -> + convertedVnfs.parallelStream() + .map(this::enrichRelatedVnfWithCloudRegionAndTenant) + .collect(Collectors.toList()) + ).get(); + } catch (Exception e) { + LOGGER.error(EELFLoggerDelegate.errorLogger, "Search group Members - Failed to enrich vnf with cloud region", e); + return convertedVnfs; + } } + private List filterByInstanceGroupRoleAndType(List aaiTree, String groupRole, String groupType) { return aaiTree.stream() @@ -544,10 +563,10 @@ public class AaiServiceImpl implements AaiService { } private void getInstanceGroupInfoFromRelationship(org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship, List instanceGroupInfoList) { - if(relationship.getRelatedTo().equals("instance-group")){ + if(StringUtils.equals(relationship.getRelatedTo(),"instance-group")){ for(org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelatedToProperty relatedToProperty: relationship.getRelatedToPropertyList()){ - if(relatedToProperty.getPropertyKey().equals("instance-group.instance-group-name")){ - instanceGroupInfoList.add(new InstanceGroupInfo(relatedToProperty.getPropertyValue())); + if(StringUtils.equals(relatedToProperty.getKey(),"instance-group.instance-group-name")){ + instanceGroupInfoList.add(new InstanceGroupInfo(relatedToProperty.getValue())); } } } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java index 603f13867..1202fc9e3 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,17 +21,15 @@ package org.onap.vid.services; import org.onap.vid.aai.model.ResourceType; -import org.onap.vid.changeManagement.RequestDetailsWrapper; import org.onap.vid.job.Job; -import org.onap.vid.model.JobAuditStatus; +import org.onap.vid.job.impl.JobSharedData; import org.onap.vid.model.ServiceInfo; -import org.onap.vid.model.serviceInstantiation.*; -import org.onap.vid.mso.model.*; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.mso.RestObject; import org.onap.vid.mso.rest.AsyncRequestStatus; import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.UUID; import java.util.function.Consumer; @@ -43,23 +41,7 @@ public interface AsyncInstantiationBusinessLogic { List pushBulkJob(ServiceInstantiation request, String userId); - RequestDetailsWrapper generateMacroServiceInstantiationRequest(UUID uuid, ServiceInstantiation details, String optimisticUniqueServiceInstanceName, String userId); - - RequestDetailsWrapper generateALaCarteServiceInstantiationRequest(UUID uuid, ServiceInstantiation details, String optimisticUniqueServiceInstanceName, String userId); - - RequestDetailsWrapper generateALaCarteServiceDeletionRequest(UUID uuid, ServiceInstantiation details, String userId); - - RequestDetailsWrapper generateVnfInstantiationRequest(Vnf vnfDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId); - - RequestDetailsWrapper generateVfModuleInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String vgInstanceId, String userId); - - RequestDetailsWrapper generateVolumeGroupInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String userId); - - RequestDetailsWrapper generateNetworkInstantiationRequest(Network networkDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId); - - RequestDetailsWrapper generateInstanceGroupInstantiationRequest(InstanceGroup request, ModelInfo serviceModelInfo, String serviceInstanceId, String userId); - - List> buildVnfInstanceParams(List> currentVnfInstanceParams, List vfModules); + boolean isPartOfBulk(UUID jobId); String getServiceInstantiationPath(ServiceInstantiation serviceInstantiationRequest); @@ -67,32 +49,34 @@ public interface AsyncInstantiationBusinessLogic { String getVnfInstantiationPath(String serviceInstanceId); + String getVnfDeletionPath(String serviceInstanceId, String vnfInstanceId); + String getNetworkInstantiationPath(String serviceInstanceId); String getVfmoduleInstantiationPath(String serviceInstanceId, String vnfInstanceId); + String getVfModuleReplacePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId); + + String getVfModuleDeletePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId); + String getVolumeGroupInstantiationPath(String serviceInstanceId, String vnfInstanceId); String getInstanceGroupInstantiationPath(); + String getInstanceGroupMemberInstantiationPath(String vnfGroupInstanceId); + String getInstanceGroupDeletePath(String instanceGroupId); - String getOrchestrationRequestsPath(); + String getInstanceGroupMemberDeletePath(String vnfGroupInstanceId); - ServiceInfo getServiceInfoByJobId(UUID jobUUID); + String getNetworkDeletePath(String serviceInstanceId, String networkInstanceId); - List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source); + String getOrchestrationRequestsPath(); ServiceInfo updateServiceInfo(UUID jobUUID, Consumer serviceUpdater); ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, Job.JobStatus jobStatus); - void auditVidStatus(UUID jobUUID, Job.JobStatus jobStatus); - - void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus); - - void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo); - Job.JobStatus calcStatus(AsyncRequestStatus asyncRequestStatus); void handleFailedInstantiation(UUID jobUUID); @@ -109,5 +93,21 @@ public interface AsyncInstantiationBusinessLogic { String getUniqueName(String name, ResourceType resourceType); + ServiceInstantiation prepareServiceToBeUnique(ServiceInstantiation serviceInstantiation); + + ServiceInstantiation enrichBulkForRetry(ServiceInstantiation serviceInstantiation, UUID jobId); + + List retryJob(UUID jobId, String userId); + + List retryJob(ServiceInstantiation request, UUID oldJobId, String userId); + + void addResourceInfo(JobSharedData sharedData, Job.JobStatus jobStatus, String instanceId); + + void addFailedResourceInfo(JobSharedData sharedData, RestObject msoResponse); + + void updateResourceInfo(JobSharedData sharedData, Job.JobStatus jobStatus, AsyncRequestStatus message); + + ServiceInstantiation getBulkForRetry(UUID jobId); + String getResumeRequestPath(String requestId); } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java index 73056db71..92a6d5fd7 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java @@ -20,18 +20,28 @@ package org.onap.vid.services; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.ImmutableList; +import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; +import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; +import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; import org.apache.commons.lang3.StringUtils; import org.hibernate.SessionFactory; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.portalsdk.core.service.DataAccessService; import org.onap.vid.aai.AaiClientInterface; import org.onap.vid.aai.ExceptionWithRequestInfo; import org.onap.vid.aai.model.ResourceType; -import org.onap.vid.changeManagement.RequestDetailsWrapper; +import org.onap.vid.dal.AsyncInstantiationRepository; import org.onap.vid.exceptions.DbFailureUncheckedException; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.exceptions.MaxRetriesException; @@ -41,37 +51,26 @@ import org.onap.vid.job.Job.JobStatus; import org.onap.vid.job.JobAdapter; import org.onap.vid.job.JobType; import org.onap.vid.job.JobsBrokerService; +import org.onap.vid.job.impl.JobSharedData; import org.onap.vid.model.Action; -import org.onap.vid.model.JobAuditStatus; import org.onap.vid.model.NameCounter; +import org.onap.vid.model.ResourceInfo; import org.onap.vid.model.ServiceInfo; -import org.onap.vid.model.serviceInstantiation.*; +import org.onap.vid.model.serviceInstantiation.BaseResource; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; import org.onap.vid.mso.MsoBusinessLogicImpl; import org.onap.vid.mso.MsoProperties; -import org.onap.vid.mso.model.*; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.RequestParameters; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.*; -import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails.RequestParametersVfModule; -import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails.UserParamMap; +import org.onap.vid.mso.MsoUtil; +import org.onap.vid.mso.RestObject; import org.onap.vid.mso.rest.AsyncRequestStatus; -import org.onap.vid.mso.rest.SubscriberInfo; +import org.onap.vid.mso.rest.RequestStatus; import org.onap.vid.properties.Features; import org.onap.vid.utils.DaoUtils; +import org.onap.vid.utils.TimeUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.togglz.core.manager.FeatureManager; -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.util.*; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; -import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; -import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; -import static org.onap.vid.utils.Logging.debugRequestDetails; - @Service public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBusinessLogic { @@ -79,9 +78,6 @@ public class AsyncInstantiationBusinessLogicImpl implements private static final int MAX_RETRIES_GETTING_COUNTER = 100; private static final int MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI = 10000; public static final String NAME_FOR_CHECK_AAI_STATUS = "NAME_FOR_CHECK_AAI_STATUS"; - private static final String VID_SOURCE = "VID"; - - private final DataAccessService dataAccessService; private final JobAdapter jobAdapter; @@ -89,12 +85,17 @@ public class AsyncInstantiationBusinessLogicImpl implements private final CloudOwnerService cloudOwnerService; + private final AsyncInstantiationRepository asyncInstantiationRepository; + private SessionFactory sessionFactory; private AaiClientInterface aaiClient; private FeatureManager featureManager; + private AuditService auditService; + + private int maxRetriesGettingFreeNameFromAai = MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI; private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AsyncInstantiationBusinessLogicImpl.class); @@ -107,51 +108,34 @@ public class AsyncInstantiationBusinessLogicImpl implements .put("pending", JobStatus.IN_PROGRESS) .put("pendingmanualtask", JobStatus.PAUSE) .put("unlocked", JobStatus.IN_PROGRESS) + .put("aborted", JobStatus.COMPLETED_WITH_ERRORS) + .put("rolledback", JobStatus.FAILED) + .put("rolledbacktoassigned", JobStatus.FAILED) + .put("rolledbacktocreated", JobStatus.FAILED) .build(); @Autowired - public AsyncInstantiationBusinessLogicImpl(DataAccessService dataAccessService, - JobAdapter jobAdapter, + public AsyncInstantiationBusinessLogicImpl(JobAdapter jobAdapter, JobsBrokerService jobService, SessionFactory sessionFactory, AaiClientInterface aaiClient, FeatureManager featureManager, - CloudOwnerService cloudOwnerService) { - this.dataAccessService = dataAccessService; + CloudOwnerService cloudOwnerService, AsyncInstantiationRepository asyncInstantiationRepository, + AuditService auditService) { this.jobAdapter = jobAdapter; this.jobService = jobService; this.sessionFactory = sessionFactory; this.aaiClient = aaiClient; this.featureManager = featureManager; this.cloudOwnerService = cloudOwnerService; + this.asyncInstantiationRepository = asyncInstantiationRepository; + this.auditService = auditService; } @Override public List getAllServicesInfo() { - return dataAccessService.getList(ServiceInfo.class, filterByCreationDateAndNotDeleted(), orderByCreatedDateAndStatus(), null); - } - - private String filterByCreationDateAndNotDeleted() { - LocalDateTime minus3Months = LocalDateTime.now().minusMonths(3); - Timestamp filterDate = Timestamp.valueOf(minus3Months); - return " where" + - " hidden = false" + - " and deleted_at is null" + // don't fetch deleted - " and created >= '" + filterDate + "' "; - } - - private String orderByCreatedDateAndStatus() { - return " createdBulkDate DESC ,\n" + - " (CASE jobStatus\n" + - " WHEN 'COMPLETED' THEN 0\n" + - " WHEN 'FAILED' THEN 0\n" + - " WHEN 'COMPLETED_WITH_ERRORS' THEN 0\n" + - " WHEN 'IN_PROGRESS' THEN 1\n" + - " WHEN 'PAUSE' THEN 2\n" + - " WHEN 'PENDING' THEN 3\n" + - " WHEN 'STOPPED' THEN 3 END),\n" + - " statusModifiedDate "; + return asyncInstantiationRepository.getAllServicesInfo(); } JobType getJobType(ServiceInstantiation request) { @@ -171,19 +155,26 @@ public class AsyncInstantiationBusinessLogicImpl implements @Override public List pushBulkJob(ServiceInstantiation request, String userId) { + List uuids = new ArrayList<>(); Date createdBulkDate = Calendar.getInstance().getTime(); int bulkSize = request.getBulkSize(); UUID templateId = UUID.randomUUID(); for (int i = 0; i < bulkSize; i++) { - ServiceInfo.ServiceAction serviceAction = getAction(request); - JobType jobType = getJobType(request); - final String optimisticUniqueServiceInstanceName = getOptimisticUniqueServiceInstanceName(request); - Job job = jobAdapter.createServiceInstantiationJob(jobType, request, templateId, userId, optimisticUniqueServiceInstanceName, i); - UUID jobId = jobService.add(job); - dataAccessService.saveDomainObject(createServiceInfo(userId, request, jobId, templateId, createdBulkDate, optimisticUniqueServiceInstanceName, serviceAction), DaoUtils.getPropsMap()); - auditVidStatus(jobId, job.getStatus()); + ServiceInstantiation requestPerJob = prepareServiceToBeUnique(request); + ServiceInfo.ServiceAction serviceAction = getAction(requestPerJob); + JobType jobType = getJobType(requestPerJob); + final String optimisticUniqueServiceInstanceName = bulkSize>1 ? //only bulk with more than 1 service need to get multiple names + getOptimisticUniqueServiceInstanceName(requestPerJob.getInstanceName()) : requestPerJob.getInstanceName(); + Job job = jobAdapter.createServiceInstantiationJob(jobType, requestPerJob, templateId, userId, request.getTestApi(), optimisticUniqueServiceInstanceName, i); + UUID jobId = job.getUuid(); + + asyncInstantiationRepository.saveServiceInfo(createServiceInfo(userId, requestPerJob, jobId, templateId, createdBulkDate, optimisticUniqueServiceInstanceName, serviceAction)); + asyncInstantiationRepository.addJobRequest(jobId, requestPerJob); + auditService.auditVidStatus(jobId, job.getStatus()); uuids.add(jobId); + + jobService.add(job); } return uuids; } @@ -197,8 +188,8 @@ public class AsyncInstantiationBusinessLogicImpl implements } - private String getOptimisticUniqueServiceInstanceName(ServiceInstantiation request) { - return StringUtils.isNotEmpty(request.getInstanceName()) ? getUniqueNameFromDbOnly(request.getInstanceName()) : request.getInstanceName(); + private String getOptimisticUniqueServiceInstanceName(String instanceName) { + return StringUtils.isNotEmpty(instanceName) ? getUniqueNameFromDbOnly(instanceName) : instanceName; } protected ServiceInfo createServiceInfo(String userId, ServiceInstantiation serviceInstantiation, UUID jobId, UUID templateId, Date createdBulkDate, String optimisticUniqueServiceInstanceName, ServiceInfo.ServiceAction serviceAction) { @@ -224,359 +215,32 @@ public class AsyncInstantiationBusinessLogicImpl implements serviceInstantiation.getModelInfo().getModelName(), serviceInstantiation.getModelInfo().getModelVersion(), createdBulkDate, - serviceAction - ); - } - - - @Override - public RequestDetailsWrapper generateMacroServiceInstantiationRequest(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName, String userId) { - String serviceInstanceName = generateServiceName(jobId, payload, optimisticUniqueServiceInstanceName); - - List serviceInstantiationServiceList = generateServiceInstantiationServicesList(payload, serviceInstanceName, createServiceInstantiationVnfList(payload)); - - RequestParameters requestParameters = new RequestParameters(payload.getSubscriptionServiceType(), false, serviceInstantiationServiceList); - - ServiceInstantiationRequestDetails requestDetails = generateServiceInstantiationRequestDetails(payload,requestParameters,serviceInstanceName, userId); - - RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails); - debugRequestDetails(requestDetailsWrapper, logger); - - return requestDetailsWrapper; + serviceAction, + false); } @Override - public RequestDetailsWrapper generateALaCarteServiceInstantiationRequest(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName, String userId) { - String serviceInstanceName = generateServiceName(jobId, payload, optimisticUniqueServiceInstanceName); - - List userParams = generateUserParamList(); - - RequestParameters requestParameters = new RequestParameters(payload.getSubscriptionServiceType(), true, userParams, payload.getTestApi()); - - ServiceInstantiationRequestDetails requestDetails = generateServiceInstantiationRequestDetails(payload,requestParameters,serviceInstanceName, userId); - - RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails); - debugRequestDetails(requestDetailsWrapper, logger); - return requestDetailsWrapper; - } - - - @Override - public RequestDetailsWrapper generateALaCarteServiceDeletionRequest(UUID jobId, ServiceInstantiation payload, String userId){ - - ServiceDeletionRequestDetails.RequestParameters requestParameters = new ServiceDeletionRequestDetails.RequestParameters( true, payload.getTestApi()); - - ServiceDeletionRequestDetails.RequestInfo requestInfo = new ServiceDeletionRequestDetails.RequestInfo( - VID_SOURCE, - userId); - - ServiceDeletionRequestDetails requestDetails = new ServiceDeletionRequestDetails(payload.getModelInfo(), requestInfo, requestParameters); - - RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails); - debugRequestDetails(requestDetailsWrapper, logger); - return requestDetailsWrapper; + public boolean isPartOfBulk(UUID jobId) { + if (jobId == null) { + return false; } - - @Override - public RequestDetailsWrapper generateVnfInstantiationRequest(Vnf vnfDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) { - - VnfInstantiationRequestDetails.RequestInfo requestInfo = new VnfInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(vnfDetails.getInstanceName(), ResourceType.GENERIC_VNF), - vnfDetails.getProductFamilyId(), - VID_SOURCE, - vnfDetails.isRollbackOnFailure(), - userId); - CloudConfiguration cloudConfiguration = generateCloudConfiguration(vnfDetails.getLcpCloudRegionId(), vnfDetails.getTenantId()); - VnfInstantiationRequestDetails.Platform platform = new VnfInstantiationRequestDetails.Platform(vnfDetails.getPlatformName()); - VnfInstantiationRequestDetails.LineOfBusiness lineOfBusiness = new VnfInstantiationRequestDetails.LineOfBusiness(vnfDetails.getLineOfBusiness()); - VnfInstantiationRequestDetails.RequestParameters requestParameters = new VnfInstantiationRequestDetails.RequestParameters(generateUserParamList()); - VnfInstantiationRequestDetails.RelatedInstance serviceInstance = new VnfInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - List relatedInstanceList = new ArrayList<>(); - relatedInstanceList.add(serviceInstance); - return new RequestDetailsWrapper<>(new VnfInstantiationRequestDetails(vnfDetails.getModelInfo(), cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters)); + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobId); + UUID templateId = serviceInfo.getTemplateId(); + if (templateId != null) { + return getNumberOfJobsInBulk(templateId) > 1; } + return false; - @Override - public RequestDetailsWrapper generateVfModuleInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String vgInstanceId, String userId) { - - VfModuleInstantiationRequestDetails.RequestInfo requestInfo = new VfModuleInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(vfModuleDetails.getInstanceName(), ResourceType.VF_MODULE), - null, - VID_SOURCE, - vfModuleDetails.isRollbackOnFailure(), - userId); - - //cloud configuration - CloudConfiguration cloudConfiguration = generateCloudConfiguration(vfModuleDetails.getLcpCloudRegionId(), vfModuleDetails.getTenantId()); - - //request parameters - List> userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.getInstanceParams()), vfModuleDetails.getSupplementaryParams()); - RequestParametersVfModule requestParameters = new RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload()); - - //related instance list - VfModuleInstantiationRequestDetails.RelatedInstance serviceInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - VfModuleInstantiationRequestDetails.RelatedInstance vnfInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(vnfModelInfo, vnfInstanceId); - List relatedInstanceList = new ArrayList<>(); - relatedInstanceList.add(serviceInstance); - relatedInstanceList.add(vnfInstance); - if (vgInstanceId != null) { - ModelInfo volumeGroupModel = new ModelInfo(); - volumeGroupModel.setModelType("volumeGroup"); - VfModuleInstantiationRequestDetails.RelatedInstance volumeGroupInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(volumeGroupModel, vgInstanceId, vfModuleDetails.getVolumeGroupInstanceName()); - relatedInstanceList.add(volumeGroupInstance); - } - - return new RequestDetailsWrapper<>(new VfModuleInstantiationRequestDetails(vfModuleDetails.getModelInfo(), cloudConfiguration, requestInfo, relatedInstanceList, requestParameters)); } - protected CloudConfiguration generateCloudConfiguration(String lcpCloudRegionId, String tenantId) { - CloudConfiguration cloudConfiguration = new CloudConfiguration(); - cloudConfiguration.setLcpCloudRegionId(lcpCloudRegionId); - cloudConfiguration.setTenantId(tenantId); - cloudOwnerService.enrichCloudConfigurationWithCloudOwner(cloudConfiguration, lcpCloudRegionId); - return cloudConfiguration; - } - - @Override - public RequestDetailsWrapper generateVolumeGroupInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String userId) { - VolumeGroupRequestDetails.RequestInfo requestInfo = new VolumeGroupRequestDetails.RequestInfo( - getUniqueNameIfNeeded(vfModuleDetails.getVolumeGroupInstanceName(), ResourceType.VOLUME_GROUP), - null, - VID_SOURCE, - vfModuleDetails.isRollbackOnFailure(), - userId); - CloudConfiguration cloudConfiguration = generateCloudConfiguration(vfModuleDetails.getLcpCloudRegionId(), vfModuleDetails.getTenantId()); - - List> userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.getInstanceParams()), vfModuleDetails.getSupplementaryParams()); - RequestParametersVfModule requestParameters = new RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload()); - - VfModuleInstantiationRequestDetails.RelatedInstance serviceInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - VfModuleInstantiationRequestDetails.RelatedInstance vnfInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(vnfModelInfo, vnfInstanceId); - List relatedInstancs = ImmutableList.of(serviceInstance, vnfInstance); - - ModelInfo modelInfo = vfModuleDetails.getModelInfo(); - modelInfo.setModelType("volumeGroup"); - return new RequestDetailsWrapper<>(new VolumeGroupRequestDetails(modelInfo, cloudConfiguration, requestInfo, relatedInstancs, requestParameters)); - } - - protected List> aggregateAllInstanceParams(Map instanceParams, Map supplementaryParams) { - Map instanceParamsFinal = defaultIfNull(instanceParams, new HashMap<>()); - Map supplementaryParamsFinal = defaultIfNull(supplementaryParams, new HashMap<>()); - - if (!(instanceParamsFinal.isEmpty() && supplementaryParamsFinal.isEmpty())) { - //remove duplicate keys from instanceParams if exist in supplementaryParams - instanceParamsFinal = instanceParams.entrySet().stream().filter(m-> - !supplementaryParamsFinal.containsKey(m.getKey()) - ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - //aggregate the 2 collections and format them as UserParamMap - UserParamMap aggregatedParams = new UserParamMap<>(); - aggregatedParams.putAll(instanceParamsFinal); - aggregatedParams.putAll(supplementaryParamsFinal); - - return ImmutableList.of(aggregatedParams); - } - - return Collections.emptyList(); - } - - @Override - public RequestDetailsWrapper generateNetworkInstantiationRequest(Network networkDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) { - - NetworkInstantiationRequestDetails.RequestInfo requestInfo = new NetworkInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(networkDetails.getInstanceName(), ResourceType.L3_NETWORK), - networkDetails.getProductFamilyId(), - VID_SOURCE, - networkDetails.isRollbackOnFailure(), - userId); - CloudConfiguration cloudConfiguration = generateCloudConfiguration(networkDetails.getLcpCloudRegionId(), networkDetails.getTenantId()); - NetworkInstantiationRequestDetails.Platform platform = new NetworkInstantiationRequestDetails.Platform(networkDetails.getPlatformName()); - NetworkInstantiationRequestDetails.LineOfBusiness lineOfBusiness = new NetworkInstantiationRequestDetails.LineOfBusiness(networkDetails.getLineOfBusiness()); - NetworkInstantiationRequestDetails.RequestParameters requestParameters = new NetworkInstantiationRequestDetails.RequestParameters(generateUserParamList()); - NetworkInstantiationRequestDetails.RelatedInstance serviceInstance = new NetworkInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - List relatedInstanceList = new ArrayList<>(); - relatedInstanceList.add(serviceInstance); - return new RequestDetailsWrapper<>(new NetworkInstantiationRequestDetails(networkDetails.getModelInfo(), cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters)); - } - - @Override - public RequestDetailsWrapper generateInstanceGroupInstantiationRequest(InstanceGroup instanceGroupDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) { - InstanceGroupInstantiationRequestDetails.RequestInfo requestInfo = new InstanceGroupInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(instanceGroupDetails.getInstanceName(), ResourceType.INSTANCE_GROUP), - null, - "VID", - instanceGroupDetails.isRollbackOnFailure(), - userId); - InstanceGroupInstantiationRequestDetails.RequestParameters requestParameters = new InstanceGroupInstantiationRequestDetails.RequestParameters(generateUserParamList()); - InstanceGroupInstantiationRequestDetails.RelatedInstance serviceInstance = new InstanceGroupInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - List relatedInstanceList = ImmutableList.of(serviceInstance); - return new RequestDetailsWrapper<>(new InstanceGroupInstantiationRequestDetails(instanceGroupDetails.getModelInfo(), requestInfo, relatedInstanceList, requestParameters)); - } - - // TODO - private List generateUserParamList() { - return Collections.emptyList(); - } - - protected List generateServiceInstantiationServicesList(ServiceInstantiation payload, String serviceInstanceName, ServiceInstantiationVnfList vnfList) { - List serviceInstantiationServiceList = new LinkedList<>(); - List> unFilteredInstanceParams = defaultIfNull(payload.getInstanceParams(), Collections.emptyList()); - List> filteredInstanceParams = removeUnNeededParams(unFilteredInstanceParams); - ServiceInstantiationService serviceInstantiationService = new ServiceInstantiationService( - payload.getModelInfo(), - serviceInstanceName, - filteredInstanceParams, - vnfList + private int getNumberOfJobsInBulk(UUID templateId) { + String hqlSelectJob = "from JobDaoImpl where templateId = :templateId"; + return DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> + session.createQuery(hqlSelectJob) + .setText("templateId", templateId.toString()) + .list() + .size() ); - serviceInstantiationServiceList.add(serviceInstantiationService); - return serviceInstantiationServiceList; - } - - private ServiceInstantiationRequestDetails generateServiceInstantiationRequestDetails(ServiceInstantiation payload, RequestParameters requestParameters, String serviceInstanceName, String userId) { - ServiceInstantiationRequestDetails.RequestInfo requestInfo = new ServiceInstantiationRequestDetails.RequestInfo(serviceInstanceName, - payload.getProductFamilyId(), - VID_SOURCE, - payload.isRollbackOnFailure(), - userId); - ServiceInstantiationOwningEntity owningEntity = new ServiceInstantiationOwningEntity(payload.getOwningEntityId(), payload.getOwningEntityName()); - SubscriberInfo subscriberInfo = generateSubscriberInfo(payload); - Project project = payload.getProjectName() != null ? new Project(payload.getProjectName()) : null; - return new ServiceInstantiationRequestDetails(payload.getModelInfo(), owningEntity, subscriberInfo, project, requestInfo, requestParameters); - } - - - protected SubscriberInfo generateSubscriberInfo(ServiceInstantiation payload) { - SubscriberInfo subscriberInfo = new SubscriberInfo(); - subscriberInfo.setGlobalSubscriberId(payload.getGlobalSubscriberId()); - return subscriberInfo; - } - - protected String generateServiceName(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName) { - String serviceInstanceName = null; - if(StringUtils.isNotEmpty(optimisticUniqueServiceInstanceName)) { - serviceInstanceName = peekServiceName(jobId, payload, optimisticUniqueServiceInstanceName); - } - return serviceInstanceName; - } - - protected String peekServiceName(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName) { - String serviceInstanceName; - // unique name already exist in service info. If it's free in AAI we use it - if (isNameFreeInAai(optimisticUniqueServiceInstanceName, ResourceType.SERVICE_INSTANCE)) { - serviceInstanceName = optimisticUniqueServiceInstanceName; - } - //otherwise we used the original service instance name (from payload) to get a new unique name from DB and AAI - else { - serviceInstanceName = getUniqueName(payload.getInstanceName(), ResourceType.SERVICE_INSTANCE); - } - - //update serviceInfo with new name if needed - try { - updateServiceInfo(jobId, x -> x.setServiceInstanceName(serviceInstanceName)); - } catch (Exception e) { - logger.error("Failed updating service name {} in serviceInfo", serviceInstanceName, e); - } - - return serviceInstanceName; - } - - @Override - public List> buildVnfInstanceParams(List> currentVnfInstanceParams, List vfModules){ - List> filteredVnfInstanceParams = removeUnNeededParams(currentVnfInstanceParams); - - if (!featureManager.isActive(Features.FLAG_SHIFT_VFMODULE_PARAMS_TO_VNF)) { - return filteredVnfInstanceParams; - } - - Map vnfInstanceParams = extractActualInstanceParams(filteredVnfInstanceParams); - vfModules.stream() - .map(x->extractActualInstanceParams(x.getInstanceParams())) - .forEach(vnfInstanceParams::putAll); - return vnfInstanceParams.isEmpty() ? Collections.emptyList() : ImmutableList.of(vnfInstanceParams); - } - - //Make sure we always get a one Map from InstanceParams - private Map extractActualInstanceParams(List> originalInstanceParams) { - if (originalInstanceParams==null || originalInstanceParams.isEmpty() || originalInstanceParams.get(0)==null) { - return new HashMap<>(); - } - return originalInstanceParams.get(0); - } - - private List> removeUnNeededParams(List> instanceParams) { - List keysToRemove = new ArrayList<>(); - if (instanceParams == null || instanceParams.isEmpty()) { - return Collections.emptyList(); - } - - for (String key : instanceParams.get(0).keySet()) { - for (String paramToIgnore : PARAMS_TO_IGNORE) - if ((key.equalsIgnoreCase(paramToIgnore))) { - keysToRemove.add(key); - } - } - - Map result = instanceParams.get(0).entrySet().stream() - .filter(entry->!keysToRemove.contains(entry.getKey())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - return result.isEmpty() ? Collections.emptyList() : Collections.singletonList(result); - } - - private ServiceInstantiationVnfList createServiceInstantiationVnfList(ServiceInstantiation payload) { - CloudConfiguration cloudConfiguration = generateCloudConfiguration(payload.getLcpCloudRegionId(), payload.getTenantId()); - - Map vnfs = payload.getVnfs(); - List vnfList = new ArrayList<>(); - for (Vnf vnf : vnfs.values()) { - Map> vfModules = vnf.getVfModules(); - List convertedUnFilteredVfModules = convertVfModuleMapToList(vfModules); - List filteredVfModules = filterInstanceParamsFromVfModuleAndUniqueNames(convertedUnFilteredVfModules); - ServiceInstantiationVnf serviceInstantiationVnf = new ServiceInstantiationVnf( - vnf.getModelInfo(), - cloudConfiguration, - vnf.getPlatformName(), - vnf.getLineOfBusiness(), - payload.getProductFamilyId(), - buildVnfInstanceParams(vnf.getInstanceParams(), filteredVfModules), - filteredVfModules, - getUniqueNameIfNeeded(vnf.getInstanceName(), ResourceType.GENERIC_VNF) - ); - vnfList.add(serviceInstantiationVnf); - } - - return new ServiceInstantiationVnfList(vnfList); - } - - private List convertVfModuleMapToList(Map> vfModules) { - ObjectMapper mapper = new ObjectMapper(); - return vfModules.values().stream().flatMap(vfModule -> - vfModule.values().stream().map(item -> { - List> aggregatedParams = aggregateAllInstanceParams(extractActualInstanceParams(item.getInstanceParams()), item.getSupplementaryParams()); - List> aggregatedParamsConverted = mapper.convertValue(aggregatedParams, new TypeReference>(){}); - - return new VfModuleMacro( - item.getModelInfo(), - item.getInstanceName(), - item.getVolumeGroupInstanceName(), - aggregatedParamsConverted); - } - ) - ).collect(Collectors.toList()); - } - - private List filterInstanceParamsFromVfModuleAndUniqueNames(List unFilteredVfModules) { - return unFilteredVfModules.stream().map(vfModule -> - new VfModuleMacro( - vfModule.getModelInfo(), - getUniqueNameIfNeeded(vfModule.getInstanceName(), ResourceType.VF_MODULE), - getUniqueNameIfNeeded(vfModule.getVolumeGroupInstanceName(), ResourceType.VOLUME_GROUP), - removeUnNeededParams(vfModule.getInstanceParams()))) - .collect(Collectors.toList()); - } - - private String getUniqueNameIfNeeded(String name, ResourceType resourceType) { - return StringUtils.isNotEmpty(name) ? getUniqueName(name, resourceType) : null; } @Override @@ -599,6 +263,13 @@ public class AsyncInstantiationBusinessLogicImpl implements replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); } + @Override + public String getVnfDeletionPath(String serviceInstanceId, String vnfInstanceId) { + return (MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VNF_INSTANCE) + + '/' + vnfInstanceId) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId).replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + } + @Override public String getNetworkInstantiationPath(String serviceInstanceId) { return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE). @@ -612,6 +283,24 @@ public class AsyncInstantiationBusinessLogicImpl implements .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); } + @Override + public String getVfModuleReplacePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId) + { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId) + .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId) + + "/" + vfModuleInstanceId + + "/replace"; + } + + @Override + public String getVfModuleDeletePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId) { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId) + .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId) + + "/" + vfModuleInstanceId; + } + @Override public String getVolumeGroupInstantiationPath(String serviceInstanceId, String vnfInstanceId) { return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE) @@ -625,79 +314,64 @@ public class AsyncInstantiationBusinessLogicImpl implements } @Override - public String getInstanceGroupDeletePath(String instanceGroupId) { + public String getInstanceGroupMemberInstantiationPath(String vnfGroupInstanceId) { return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP) - + '/' + instanceGroupId; + + '/' + vnfGroupInstanceId + "/addMembers"; } @Override - public String getOrchestrationRequestsPath() { - return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ); + public String getInstanceGroupDeletePath(String instanceGroupId) { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP) + + '/' + instanceGroupId; } @Override - public ServiceInfo updateServiceInfo(UUID jobUUID, Consumer serviceUpdater) { - ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID); - serviceUpdater.accept(serviceInfo); - dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap()); - return serviceInfo; + public String getInstanceGroupMemberDeletePath(String vnfGroupInstanceId){ + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP) + + '/' + vnfGroupInstanceId + "/removeMembers"; } @Override - public ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, JobStatus jobStatus) { - auditVidStatus(jobUuid,jobStatus); - return updateServiceInfo(jobUuid, x -> setServiceInfoStatus(x, jobStatus)); - } - - private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) { - serviceInfo.setJobStatus(jobStatus); - serviceInfo.setStatusModifiedDate(new Date()); - } - - public ServiceInfo getServiceInfoByJobId(UUID jobUUID) { - List serviceInfoList = dataAccessService.getList(ServiceInfo.class, String.format(" where jobId = '%s' ", jobUUID), null, null); - if (serviceInfoList.size() != 1) { - throw new GenericUncheckedException("Failed to retrieve job with uuid " + jobUUID + " from ServiceInfo table. Instances found: " + serviceInfoList.size()); - } - return serviceInfoList.get(0); + public String getNetworkDeletePath(String serviceInstanceId, String networkInstanceId) { + return (MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE) + + "/" + networkInstanceId) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); } - public List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source) { - return dataAccessService.getList( - JobAuditStatus.class, - String.format(" where SOURCE = '%s' and JOB_ID = '%s'",source, jobUUID), - " CREATED_DATE ", null); - } - - private JobAuditStatus getLatestAuditStatus(UUID jobUUID, JobAuditStatus.SourceStatus source){ - List list = getAuditStatuses(jobUUID,source); - return !list.isEmpty() ? list.get(list.size()-1) : null; + @Override + public String getResumeRequestPath(String requestId) { + return MsoBusinessLogicImpl.validateEndpointPath("mso.restapi.resume.orc.req") + .replaceFirst("", requestId); } @Override - public void auditVidStatus(UUID jobUUID, JobStatus jobStatus){ - JobAuditStatus vidStatus = new JobAuditStatus(jobUUID, jobStatus.toString(), JobAuditStatus.SourceStatus.VID); - auditStatus(vidStatus); + public String getOrchestrationRequestsPath() { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ); } @Override - public void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus){ - auditMsoStatus(jobUUID, msoRequestStatus.requestStatus.getRequestState(), msoRequestStatus.requestId, msoRequestStatus.requestStatus.getStatusMessage()); + public ServiceInfo updateServiceInfo(UUID jobUUID, Consumer serviceUpdater) { + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID); + serviceUpdater.accept(serviceInfo); + asyncInstantiationRepository.saveServiceInfo(serviceInfo); + return serviceInfo; } @Override - public void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo){ - JobAuditStatus msoStatus = new JobAuditStatus(jobUUID, jobStatus, JobAuditStatus.SourceStatus.MSO, - requestId != null ? UUID.fromString(requestId) : null, - additionalInfo); - auditStatus(msoStatus); + public ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, JobStatus jobStatus) { + auditService.auditVidStatus(jobUuid, jobStatus); + return updateServiceInfo(jobUuid, x -> setServiceInfoStatus(x, jobStatus)); } - private void auditStatus(JobAuditStatus jobAuditStatus){ - JobAuditStatus latestStatus = getLatestAuditStatus(jobAuditStatus.getJobId(), jobAuditStatus.getSource()); - if (latestStatus == null || !latestStatus.equals(jobAuditStatus)) - dataAccessService.saveDomainObject(jobAuditStatus, DaoUtils.getPropsMap()); + private boolean isRetryEnabledForStatus(JobStatus jobStatus) { + return featureManager.isActive(Features.FLAG_1902_RETRY_JOB) && + (jobStatus==JobStatus.COMPLETED_WITH_ERRORS || jobStatus==JobStatus.FAILED); + } + private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) { + serviceInfo.setJobStatus(jobStatus); + serviceInfo.setStatusModifiedDate(new Date()); + serviceInfo.setRetryEnabled(isRetryEnabledForStatus(jobStatus)); } public Job.JobStatus calcStatus(AsyncRequestStatus asyncRequestStatus) { @@ -708,13 +382,8 @@ public class AsyncInstantiationBusinessLogicImpl implements @Override public void handleFailedInstantiation(UUID jobUUID) { - ServiceInfo serviceInfo = updateServiceInfoAndAuditStatus(jobUUID, JobStatus.FAILED); - List serviceInfoList = dataAccessService.getList( - ServiceInfo.class, - String.format(" where templateId = '%s' and jobStatus = '%s'", - serviceInfo.getTemplateId(), - JobStatus.PENDING), - null, null); + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID); + List serviceInfoList = asyncInstantiationRepository.getServiceInfoByTemplateIdAndJobStatus(serviceInfo.getTemplateId(), JobStatus.PENDING); serviceInfoList.forEach(si -> updateServiceInfoAndAuditStatus(si.getJobId(), JobStatus.STOPPED)); } @@ -727,16 +396,16 @@ public class AsyncInstantiationBusinessLogicImpl implements @Override public void hideServiceInfo(UUID jobUUID) { - ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID); + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID); if (!serviceInfo.getJobStatus().isFinal()) { - String message = String.format( "jobId %s: Service status does not allow hide service, status = %s", + String message = String.format("jobId %s: Service status does not allow hide service, status = %s", serviceInfo.getJobId(), serviceInfo.getJobStatus()); logger.error(EELFLoggerDelegate.errorLogger, message); throw new OperationNotAllowedException(message); } serviceInfo.setHidden(true); - dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap()); + asyncInstantiationRepository.saveServiceInfo(serviceInfo); } @Override @@ -818,7 +487,84 @@ public class AsyncInstantiationBusinessLogicImpl implements } } - throw new MaxRetriesException("find unused name for "+name, getMaxRetriesGettingFreeNameFromAai()); + throw new MaxRetriesException("can't find unused name for "+name, getMaxRetriesGettingFreeNameFromAai()); + } + + @Override + public ServiceInstantiation prepareServiceToBeUnique(ServiceInstantiation serviceInstantiation) { + try { + ServiceInstantiation clonedServiceInstantiation = JACKSON_OBJECT_MAPPER.readValue( + JACKSON_OBJECT_MAPPER.writeValueAsBytes(serviceInstantiation), ServiceInstantiation.class); + clonedServiceInstantiation.setBulkSize(1); + return replaceAllTrackById(clonedServiceInstantiation); + } catch (IOException e) { + throw new GenericUncheckedException(e); + } + + } + + private T replaceAllTrackById(T resource) { + resource.setTrackById(UUID.randomUUID().toString()); + resource.getChildren().forEach(this::replaceAllTrackById); + return resource; + } + + @Override + public List retryJob(ServiceInstantiation request, UUID jobId, String userId ) { + updateServiceInfo(jobId, si->si.setRetryEnabled(false)); + return pushBulkJob(request, userId); + } + + @Override + public List retryJob(UUID jobId, String userId) { + ServiceInstantiation serviceInstantiationRequest = asyncInstantiationRepository.getJobRequest(jobId); + enrichBulkForRetry(serviceInstantiationRequest, jobId); + + try { + logger.debug(EELFLoggerDelegate.debugLogger, "retry ServiceInstantiation request: "+ + JACKSON_OBJECT_MAPPER.writeValueAsString(serviceInstantiationRequest)); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "failed to log retry of ServiceInstantiation request ", e); + } + return retryJob(serviceInstantiationRequest, jobId, userId); + } + + @Override + public ServiceInstantiation getBulkForRetry(UUID jobId) { + return enrichBulkForRetry( asyncInstantiationRepository.getJobRequest(jobId), jobId); + } + + @Override + public void addResourceInfo(JobSharedData sharedData, Job.JobStatus jobStatus, String instanceId) { + String trackById = ((BaseResource) sharedData.getRequest()).getTrackById(); + ResourceInfo resourceInfo = new ResourceInfo(trackById, sharedData.getRootJobId(), instanceId, jobStatus, null); + asyncInstantiationRepository.saveResourceInfo(resourceInfo); + } + + @Override + public void addFailedResourceInfo(JobSharedData sharedData, RestObject msoResponse) { + String trackById = ((BaseResource) sharedData.getRequest()).getTrackById(); + String errorMessage = MsoUtil.formatExceptionAdditionalInfo(msoResponse.getStatusCode(), msoResponse.getRaw()); + AsyncRequestStatus asyncRequestStatus = convertMessageToAsyncRequestStatus(errorMessage); + ResourceInfo resourceInfo = new ResourceInfo(trackById, sharedData.getRootJobId(), null, JobStatus.FAILED, asyncRequestStatus); + + asyncInstantiationRepository.saveResourceInfo(resourceInfo); + } + + @Override + public void updateResourceInfo(JobSharedData sharedData, JobStatus jobStatus, AsyncRequestStatus message) { + ResourceInfo resourceInfo = asyncInstantiationRepository.getResourceInfoByTrackId(((BaseResource) sharedData.getRequest()).getTrackById()); + resourceInfo.setJobStatus(jobStatus); + if (jobStatus.isFailure()) { + resourceInfo.setErrorMessage(message); + } + asyncInstantiationRepository.saveResourceInfo(resourceInfo); + } + + public AsyncRequestStatus convertMessageToAsyncRequestStatus(String message) { + RequestStatus requestStatus = new RequestStatus("FAILED", message, TimeUtils.zonedDateTimeToString(ZonedDateTime.now())); + AsyncRequestStatus.Request request = new AsyncRequestStatus.Request(requestStatus); + return new AsyncRequestStatus(request); } protected String getUniqueNameFromDbOnly(String name) { @@ -835,4 +581,35 @@ public class AsyncInstantiationBusinessLogicImpl implements return !aaiClient.isNodeTypeExistsByName(name, resourceType); } + @Override + public ServiceInstantiation enrichBulkForRetry(ServiceInstantiation serviceInstantiation, UUID jobId){ + Map resourceInfoByTrackId = asyncInstantiationRepository.getResourceInfoByRootJobId(jobId); + + return setResourceStatus(resourceInfoByTrackId, serviceInstantiation); + } + + protected String readStatusMsg(ResourceInfo resourceInfo){ + if(resourceInfo!=null && resourceInfo.getErrorMessage()!=null && resourceInfo.getErrorMessage().request != null &&resourceInfo.getErrorMessage().request.requestStatus != null ) { + return resourceInfo.getErrorMessage().request.requestStatus.getStatusMessage(); + } + return null; + } + + private T setResourceStatus(Map resourceInfoByTrackId, T resource) { + ResourceInfo resourceInfo = resourceInfoByTrackId.get(resource.getTrackById()); + if(resourceInfo != null) { + boolean failed = resourceInfo.getJobStatus().isFailure(); + resource.setIsFailed(failed); + resource.setStatusMessage(readStatusMsg(resourceInfo)); + if (!failed) { + // if(resource.getAction().equals(Action.Delete)){ + // TODO not yet implemented- completed after delete should remove the node + resource.setAction(Action.None); + resource.setInstanceId(resourceInfo.getInstanceId()); + } + } + resource.getChildren().forEach(child -> setResourceStatus(resourceInfoByTrackId, child)); + return resource; + } + } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AuditService.java b/vid-app-common/src/main/java/org/onap/vid/services/AuditService.java index ef60c321d..6370b1862 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AuditService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AuditService.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,19 +20,31 @@ package org.onap.vid.services; -import org.onap.vid.model.JobAuditStatus; - import java.util.List; import java.util.UUID; +import org.onap.vid.job.Job; +import org.onap.vid.model.JobAuditStatus; +import org.onap.vid.mso.rest.AsyncRequestStatus; public interface AuditService { void setFailedAuditStatusFromMso(UUID jobUuid, String requestId, int statusCode, String msoResponse); - List getAuditStatusFromMsoByRequestId(UUID jobId, UUID requestId); - List getAuditStatusFromMsoByServiceInstanceId(UUID jobId, UUID serviceInstanceId); + List getAuditStatusFromMsoByInstanceId(JobAuditStatus.ResourceTypeFilter resourceTypeFilter, UUID instanceId, UUID jobId); List getAuditStatusFromMsoByJobId(UUID jobId); + + void auditVidStatus(UUID jobUUID, Job.JobStatus jobStatus); + + void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus); + + void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo); + + List retrieveRequestsFromMsoByServiceIdAndRequestTypeAndScope(String instanceId, String requestType, String modelType); + + List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source); + + JobAuditStatus getResourceAuditStatus(String trackById); } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.java index 7fb126e23..287a771d3 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,22 +20,20 @@ package org.onap.vid.services; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.lang3.StringUtils; -import org.onap.vid.exceptions.GenericUncheckedException; +import static org.apache.commons.lang3.ObjectUtils.notEqual; + +import org.jetbrains.annotations.NotNull; +import org.onap.vid.dal.AsyncInstantiationRepository; +import org.onap.vid.job.Job; import org.onap.vid.model.JobAuditStatus; -import org.onap.vid.mso.MsoBusinessLogicImpl; -import org.onap.vid.mso.MsoProperties; -import org.onap.vid.mso.RestMsoImplementation; -import org.onap.vid.mso.RestObject; +import org.onap.vid.mso.*; import org.onap.vid.mso.rest.AsyncRequestStatus; import org.onap.vid.mso.rest.AsyncRequestStatusList; import org.springframework.stereotype.Service; import javax.inject.Inject; -import java.io.IOException; import java.util.List; +import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; @@ -43,41 +41,20 @@ import java.util.stream.Collectors; @Service public class AuditServiceImpl implements AuditService{ - private final AsyncInstantiationBusinessLogic asyncInstantiationBL; private final RestMsoImplementation restMso; + private final AsyncInstantiationRepository asyncInstantiationRepository; @Inject - public AuditServiceImpl(AsyncInstantiationBusinessLogic asyncInstantiationBL, RestMsoImplementation restMso) { - this.asyncInstantiationBL = asyncInstantiationBL; + public AuditServiceImpl(RestMsoImplementation restMso, AsyncInstantiationRepository asyncInstantiationRepository) { this.restMso = restMso; + this.asyncInstantiationRepository = asyncInstantiationRepository; } @Override public void setFailedAuditStatusFromMso(UUID jobUuid, String requestId, int statusCode, String msoResponse){ final String failedMsoRequestStatus = "FAILED"; - String additionalInfo = formatExceptionAdditionalInfo(statusCode, msoResponse); - asyncInstantiationBL.auditMsoStatus(jobUuid, failedMsoRequestStatus, requestId, additionalInfo); - } - - private String formatExceptionAdditionalInfo(int statusCode, String msoResponse) { - String errorMsg = "Http Code:" + statusCode; - if (!StringUtils.isEmpty(msoResponse)) { - String filteredJson; - try { - ObjectMapper objectMapper = new ObjectMapper(); - filteredJson = StringUtils.defaultIfEmpty( - objectMapper.readTree(msoResponse).path("serviceException").toString().replaceAll("[\\{\\}]","") , - msoResponse - ); - } catch (JsonParseException e) { - filteredJson = msoResponse; - } catch (IOException e) { - throw new GenericUncheckedException(e); - } - - errorMsg = errorMsg + ", " + filteredJson; - } - return errorMsg; + String additionalInfo = MsoUtil.formatExceptionAdditionalInfo(statusCode, msoResponse); + auditMsoStatus(jobUuid, failedMsoRequestStatus, requestId, additionalInfo); } @Override @@ -87,64 +64,133 @@ public class AuditServiceImpl implements AuditService{ } @Override - public List getAuditStatusFromMsoByServiceInstanceId(UUID jobId, UUID serviceInstanceId) { - String filter = "serviceInstanceId:EQUALS:" + serviceInstanceId; - return getAuditStatusFromMso(jobId, filter, serviceInstanceId); + public List getAuditStatusFromMsoByInstanceId(JobAuditStatus.ResourceTypeFilter resourceTypeFilter, UUID instanceId, UUID jobId) { + String filter = resourceTypeFilter.getFilterBy() + ":EQUALS:" + instanceId; + return getAuditStatusFromMso(jobId, filter, instanceId); } @Override public List getAuditStatusFromMsoByJobId(UUID jobId) { - List auditStatuses = asyncInstantiationBL.getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO); + List auditStatuses = getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO); String instanceName = getInstanceNameFromServiceInfo(jobId); auditStatuses.stream().forEach(status -> - status.setInstanceName(instanceName) + status.setInstanceName(instanceName) ); return auditStatuses; } + @Override + public void auditVidStatus(UUID jobUUID, Job.JobStatus jobStatus){ + JobAuditStatus vidStatus = new JobAuditStatus(jobUUID, jobStatus.toString(), JobAuditStatus.SourceStatus.VID); + auditStatus(vidStatus); + } + @Override + public void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus){ + auditMsoStatus(jobUUID, msoRequestStatus.requestStatus.getRequestState(), msoRequestStatus.requestId, msoRequestStatus.requestStatus.getStatusMessage()); + } + + @Override + public void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo){ + JobAuditStatus msoStatus = new JobAuditStatus(jobUUID, jobStatus, JobAuditStatus.SourceStatus.MSO, + requestId != null ? UUID.fromString(requestId) : null, + additionalInfo); + auditStatus(msoStatus); + } - private List getAuditStatusFromMso(UUID jobId, String filter, UUID serviceInstanceId) { + private void auditStatus(JobAuditStatus jobAuditStatus){ + JobAuditStatus latestStatus = getLatestAuditStatus(jobAuditStatus.getJobId(), jobAuditStatus.getSource()); + if (notEqual(jobAuditStatus, latestStatus)) { + jobAuditStatus.setOrdinal(nextOrdinalAfter(latestStatus)); + asyncInstantiationRepository.addJobAudiStatus(jobAuditStatus); + } + } + + protected int nextOrdinalAfter(JobAuditStatus jobAuditStatus) { + return jobAuditStatus == null ? 0 : (jobAuditStatus.getOrdinal() + 1); + } + + private JobAuditStatus getLatestAuditStatus(UUID jobUUID, JobAuditStatus.SourceStatus source){ + List list = getAuditStatuses(jobUUID, source); + return !list.isEmpty() ? list.get(list.size()-1) : null; + } + + public List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source) { + return asyncInstantiationRepository.getAuditStatuses(jobUUID, source); + } + + @Override + //modelType is requestScope in MSO response + public List retrieveRequestsFromMsoByServiceIdAndRequestTypeAndScope(String instanceId, String requestType, String modelType) { + String filter = JobAuditStatus.ResourceTypeFilter.SERVICE.getFilterBy() + ":EQUALS:" + instanceId; + List msoStatuses = getAsyncRequestStatusListFromMso(filter); + return msoStatuses.stream() + .filter(x -> Objects.equals(x.request.requestType, requestType) && Objects.equals(x.request.requestScope, modelType)) + .map(x -> x.request) + .collect(Collectors.toList()); + } + + private List getAuditStatusFromMso(UUID jobId, String filter, UUID instanceId) { + + List msoStatuses = getAsyncRequestStatusListFromMso(filter); + + //add service name from service info for each audit status (in case that serviceInstanceId is null all statuses belong to service) + String userInstanceName = (instanceId == null && jobId != null) ? getInstanceNameFromServiceInfo(jobId) : null; + return convertMsoResponseStatusToJobAuditStatus(msoStatuses, userInstanceName); + } + + @NotNull + private List getAsyncRequestStatusListFromMso(String filter) { String path = MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQS) + "filter=" + filter; RestObject msoResponse = restMso.GetForObject(path , AsyncRequestStatusList.class); if (msoResponse.getStatusCode() >= 400 || msoResponse.get() == null) { throw new BadResponseFromMso(msoResponse); } - - //add service name from service info for each audit status (in case that serviceInstanceId is null all statuses belong to service) - String userInstanceName = serviceInstanceId == null ? getInstanceNameFromServiceInfo(jobId): null; - return convertMsoResponseStatusToJobAuditStatus(msoResponse.get().getRequestList(), userInstanceName); + return msoResponse.get().getRequestList(); } private String getInstanceNameFromServiceInfo(UUID jobId) { - return asyncInstantiationBL.getServiceInfoByJobId(jobId).getServiceInstanceName(); + return asyncInstantiationRepository.getServiceInfoByJobId(jobId).getServiceInstanceName(); } protected List convertMsoResponseStatusToJobAuditStatus(List msoStatuses, String defaultName){ - return msoStatuses.stream().map(status -> { - UUID requestId = null; - String instanceName = defaultName; - String jobStatus = null; - String additionalInfo = null; - String created = null; - String instanceType = null; - - AsyncRequestStatus.Request request = status.request; - if(request != null) { + return msoStatuses.stream().map(status -> + convertAsyncRequestStatusToJobAuditStatus(status, defaultName) + ).collect(Collectors.toList()); + } + + private JobAuditStatus convertAsyncRequestStatusToJobAuditStatus(AsyncRequestStatus status, String defaultName){ + if (status == null) { + return null; + } + + UUID requestId = null; + String instanceName = defaultName; + String jobStatus = null; + String additionalInfo = null; + String created = null; + String instanceType = null; + + AsyncRequestStatus.Request request = status.request; + if(request != null) { + if (request.requestId != null) { requestId = UUID.fromString(request.requestId); - instanceName = extractInstanceName(instanceName, request); - instanceType = request.requestScope; - if(request.requestStatus != null) { - jobStatus = request.requestStatus.getRequestState(); - additionalInfo = request.requestStatus.getStatusMessage(); - if(!request.requestStatus.getAdditionalProperties().isEmpty()) { - created = request.requestStatus.getAdditionalProperties().get("finishTime") != null? request.requestStatus.getAdditionalProperties().get("finishTime").toString() : request.requestStatus.getTimestamp(); - } + } + instanceName = extractInstanceName(instanceName, request); + instanceType = request.requestScope; + if(request.requestStatus != null) { + jobStatus = request.requestStatus.getRequestState(); + additionalInfo = request.requestStatus.getStatusMessage(); + if(!request.requestStatus.getAdditionalProperties().isEmpty() && + request.requestStatus.getAdditionalProperties().get("finishTime") != null) { + created = request.requestStatus.getAdditionalProperties().get("finishTime").toString(); + } else { + created = request.requestStatus.getTimestamp(); } } - return new JobAuditStatus(instanceName, jobStatus, requestId, additionalInfo, created, instanceType); - }).collect(Collectors.toList()); + } + return new JobAuditStatus(instanceName, jobStatus, requestId, additionalInfo, created, instanceType); } private String extractInstanceName(String instanceName, AsyncRequestStatus.Request request) { @@ -154,6 +200,13 @@ public class AuditServiceImpl implements AuditService{ return instanceName; } + @Override + public JobAuditStatus getResourceAuditStatus(String trackById) { + AsyncRequestStatus asyncRequestStatus = asyncInstantiationRepository.getResourceInfoByTrackId(trackById).getErrorMessage(); + return convertAsyncRequestStatusToJobAuditStatus(asyncRequestStatus, null); + } + + public static class BadResponseFromMso extends RuntimeException { private final RestObject msoResponse; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java b/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java index 199fff0c7..f6b82c734 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/vid-app-common/src/main/java/org/onap/vid/services/RoleGenaratorServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/RoleGenaratorServiceImpl.java index 790dbfa55..a24a72e46 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/RoleGenaratorServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/RoleGenaratorServiceImpl.java @@ -71,7 +71,7 @@ public class RoleGenaratorServiceImpl implements RoleGeneratorService { String availableRoles=""; HashMap servicesNames = new HashMap<>(); for (Subscriber subscriber: subscribers.customer) { - AaiResponse subscriberResponse = client.getSubscriberData(subscriber.globalCustomerId); + AaiResponse subscriberResponse = client.getSubscriberData(subscriber.globalCustomerId, true); for(ServiceSubscription service: subscriberResponse.getT().serviceSubscriptions.serviceSubscription) { servicesNames.put(service.serviceType,""); String roleName = "'" + subscriber.subscriberName + ModelConstants.ROLE_DELIMITER + service.serviceType + "'"; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt b/vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt new file mode 100644 index 000000000..2fb3e0c08 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt @@ -0,0 +1,66 @@ +package org.onap.vid.services + +import com.fasterxml.jackson.module.kotlin.readValue +import org.apache.commons.lang3.StringUtils +import org.apache.commons.lang3.StringUtils.substringAfterLast +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.portalsdk.core.util.SystemProperties +import org.onap.vid.model.VersionAndFeatures +import org.onap.vid.utils.JACKSON_OBJECT_MAPPER +import org.springframework.stereotype.Service +import java.util.regex.Pattern +import javax.inject.Inject +import javax.servlet.ServletContext + +@Service +class VersionService +@Inject +constructor(internal var servletContext: ServletContext) { + + private val Logger = EELFLoggerDelegate.getLogger(VersionService::class.java) + + private val versionAndFeatures: VersionAndFeatures by lazy { + loadVersionAndFeatures() + } + + private fun readBuildNumber(): String { + val resource = servletContext.getResource("/app/vid/scripts/constants/version.json") + return JACKSON_OBJECT_MAPPER.readValue>(resource)["Version"]!! + } + + //protected so can be easily tested in UT + protected fun readFeatureSet(): String { + return SystemProperties.getProperty("features.set.filename") + } + + //protected so can be easily tested in UT + protected fun buildDisplayVersion(features: String, build: String): String { + val matcher = Pattern.compile("([^/]+?)(\\.features|$)").matcher(features) + val majorByFeatures = if (matcher.find()) matcher.group(1) else features + + val buildByVersion = StringUtils.defaultIfBlank(substringAfterLast(build, "."), build) + + return StringUtils.join(majorByFeatures, ".", buildByVersion) + } + + fun retrieveVersionAndFeatures(): VersionAndFeatures { + return try { + versionAndFeatures + } catch (exception: Exception) { + Logger.error("Failed to read build number or feature properties settings from version file", exception) + VersionAndFeatures.unknown + } + } + + private fun loadVersionAndFeatures(): VersionAndFeatures { + val featureSet = readFeatureSet(); + val build = readBuildNumber(); + val displayVersion = buildDisplayVersion(featureSet, build) + return VersionAndFeatures(featureSet, build, displayVersion) + } + + //might throw an exception + fun retrieveBuildNumber(): String { + return versionAndFeatures.build + } +} -- cgit 1.2.3-korg