From 6ad41e3ccd398a2721f41ad61c80b7bb03f7d127 Mon Sep 17 00:00:00 2001 From: Ittay Stern Date: Mon, 31 Dec 2018 17:21:27 +0200 Subject: Merge from ECOMP's repository Main Features -------------- - Async-Instantiation jobs mechanism major update; still WIP (package `org.onap.vid.job`) - New features in View/Edit: Activate fabric configuration; show related networks; soft delete - Support AAI service-tree traversal (`AAIServiceTree`) - In-memory cache for SDC models and certain A&AI queries (`CacheProviderWithLoadingCache`) - Upgrade TOSCA Parser and add parsing options; fix malformed TOSCA models - Resolve Cloud-Owner values for MSO - Pass X-ONAP headers to MSO Infrastructure -------------- - Remove codehaus' jackson mapper; use soley fasterxml 2.9.7 - Surefire invokes both TestNG and JUnit tests - Support Kotlin source files - AaiController2 which handles errors in a "Spring manner" - Inline generated-sources and remove jsonschema2pojo Quality -------- - Cumulative bug fixes (A&AI API, UI timeouts, and many more) - Many Sonar issues cleaned-up - Some unused classes removed - Minor changes in vid-automation project, allowing some API verification to run Hard Merges ------------ - HTTP Clients (MSO, A&AI, WebConfig, OutgoingRequestHeadersTest) - Moved `package org.onap.vid.controllers` to `controller`, without plural -- just to keep semantic sync with ECOMP. Reference commit in ECOMP: 3d1141625 Issue-ID: VID-378 Change-Id: I9c8d1e74caa41815891d441fc0760bb5f29c5788 Signed-off-by: Ittay Stern --- .../java/org/onap/vid/services/AAIServiceTree.java | 247 +++++++ .../org/onap/vid/services/AAITreeNodeBuilder.java | 281 ++++++++ .../java/org/onap/vid/services/AaiService.java | 10 +- .../java/org/onap/vid/services/AaiServiceImpl.java | 138 +++- .../services/AsyncInstantiationBusinessLogic.java | 39 +- .../AsyncInstantiationBusinessLogicImpl.java | 767 ++++++++++++++------- .../java/org/onap/vid/services/AuditService.java | 11 +- .../org/onap/vid/services/AuditServiceImpl.java | 127 +++- .../vid/services/BulkInstantiationService.java | 4 - .../vid/services/BulkInstantiationServiceImpl.java | 10 - .../onap/vid/services/ChangeManagementService.java | 6 +- .../vid/services/ChangeManagementServiceImpl.java | 61 +- .../org/onap/vid/services/CloudOwnerService.java | 12 + .../onap/vid/services/CloudOwnerServiceImpl.java | 76 ++ .../java/org/onap/vid/services/CsvService.java | 1 - .../java/org/onap/vid/services/CsvServiceImpl.java | 9 +- .../vid/services/RoleGenaratorServiceImpl.java | 16 +- .../java/org/onap/vid/services/VidServiceImpl.java | 6 +- .../org/onap/vid/services/WorkflowService.java | 1 - 19 files changed, 1456 insertions(+), 366 deletions(-) create mode 100644 vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerServiceImpl.java (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 new file mode 100644 index 000000000..432ab6401 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java @@ -0,0 +1,247 @@ +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; +import org.onap.vid.aai.util.AAITreeConverter; +import org.onap.vid.asdc.AsdcCatalogException; +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.ServiceInstance; +import org.onap.vid.utils.Tree; +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 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.*; + +@Component +public class AAIServiceTree { + + private final AAITreeNodeBuilder aaiTreeNodeBuilder; + + private final AAITreeConverter aaiTreeConverter; + + private final AaiClientInterface aaiClient; + + private final VidService sdcService; + + private final ServiceModelInflator serviceModelInflator; + + private final ObjectMapper mapper = new ObjectMapper(); + + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AAIServiceTree.class); + + public static final Tree AAI_TREE_PATHS = + new Tree<>(new AaiRelationship(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)); + } + + @Inject + public AAIServiceTree(AaiClientInterface aaiClient, AAITreeNodeBuilder aaiTreeNodeBuilder, + AAITreeConverter aaiTreeConverter, VidService sdcService, + ServiceModelInflator serviceModelInflator) { + this.aaiClient = aaiClient; + this.aaiTreeNodeBuilder = aaiTreeNodeBuilder; + this.aaiTreeConverter = aaiTreeConverter; + this.sdcService = sdcService; + this.serviceModelInflator = serviceModelInflator; + } + + public List buildAAITree(String getUrl, Tree pathsToSearch) { + + ConcurrentSkipListSet nodesAccumulator = createNodesAccumulator(); + + List aaiTreeNodes = fetchAAITree(getUrl, pathsToSearch, nodesAccumulator, true); + + enrichNodesWithModelVersionAndModelName(nodesAccumulator); + + return aaiTreeNodes; + } + + public ServiceInstance getServiceInstanceTopology(String globalCustomerId, String serviceType, String serviceInstanceId) { + + String getURL = "business/customers/customer/" + + globalCustomerId + "/service-subscriptions/service-subscription/" + + serviceType + "/service-instances/service-instance/" + serviceInstanceId; + + //Used later to get the nodes UUID + ConcurrentSkipListSet nodesAccumulator = createNodesAccumulator(); + + AAITreeNode aaiTree = fetchAAITree(getURL, AAI_TREE_PATHS, nodesAccumulator, false).get(0); + + //Populate nodes with model-name & model-version (from aai) + enrichNodesWithModelVersionAndModelName(nodesAccumulator); + + final ServiceModel serviceModel = getServiceModel(aaiTree.getModelVersionId()); + + //Populate nodes with model-customization-name (from sdc model) + enrichNodesWithModelCustomizationName(nodesAccumulator, serviceModel); + + return aaiTreeConverter.convertTreeToUIModel(aaiTree, globalCustomerId, serviceType, getInstantiationType(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); + + 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); + } + + return aaiTree; + } + + private ConcurrentSkipListSet createNodesAccumulator() { + return new ConcurrentSkipListSet<>(comparing(AAITreeNode::getUniqueNodeKey)); + } + + private String getInstantiationType(ServiceModel serviceModel) { + if (serviceModel.getService() != null && serviceModel.getService().getInstantiationType() != null) { + return serviceModel.getService().getInstantiationType(); + } else { + return null; + } + } + + private ServiceModel getServiceModel(String modelVersionId) { + try { + final ServiceModel serviceModel = sdcService.getService(modelVersionId); + if (serviceModel == null) { + throw new GenericUncheckedException("Model version '" + modelVersionId + "' not found"); + } + return serviceModel; + } catch (AsdcCatalogException e) { + throw new GenericUncheckedException("Exception while loading model version '" + modelVersionId + "'", e); + } + + } + + void enrichNodesWithModelCustomizationName(Collection nodes, ServiceModel serviceModel) { + final Map customizationNameByVersionId = serviceModelInflator.toNamesByVersionId(serviceModel); + + nodes.forEach(node -> { + final ServiceModelInflator.Names names = customizationNameByVersionId.get(node.getModelVersionId()); + if (names != null) { + node.setKeyInModel(names.getModelKey()); + node.setModelCustomizationName(names.getModelCustomizationName()); + } + }); + } + + + private void enrichNodesWithModelVersionAndModelName(Collection nodes) { + + Collection invariantIDs = getModelInvariantIds(nodes); + + Map modelVersionByModelVersionId = new HashMap<>(); + Map modelNameByModelVersionId = new HashMap<>(); + + JsonNode models = getModels(aaiClient, invariantIDs); + for (JsonNode model: models) { + JsonNode modelVersions = model.get("model-vers").get("model-ver"); + for (JsonNode modelVersion: modelVersions) { + final String modelVersionId = modelVersion.get("model-version-id").asText(); + modelVersionByModelVersionId.put(modelVersionId, modelVersion.get("model-version").asText()); + modelNameByModelVersionId.put(modelVersionId, modelVersion.get("model-name").asText()); + } + } + + nodes.forEach(node -> { + node.setModelVersion(modelVersionByModelVersionId.get(node.getModelVersionId())); + node.setModelName(modelNameByModelVersionId.get(node.getModelVersionId())); + }); + + } + + private JsonNode getModels(AaiClientInterface aaiClient, Collection invariantIDs) { + Response response = aaiClient.getVersionByInvariantId(ImmutableList.copyOf(invariantIDs)); + try { + JsonNode responseJson = 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(); + } + + private Set getModelInvariantIds(Collection nodes) { + return nodes.stream() + .map(AAITreeNode::getModelInvariantId) + .filter(Objects::nonNull) + .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; + + public AaiRelationship(String type) { + this.type = type; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AaiRelationship)) return false; + AaiRelationship that = (AaiRelationship) o; + return Objects.equals(type, that.type); + } + + @Override + public int hashCode() { + return Objects.hash(type); + } + } +} 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 new file mode 100644 index 000000000..41f0144c9 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java @@ -0,0 +1,281 @@ +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.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +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.RelationshipList; +import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.FailureAAITreeNode; +import org.onap.vid.utils.Streams; +import org.onap.vid.utils.Tree; +import org.onap.vid.utils.Unchecked; +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.stream.Collectors; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.*; +import static org.onap.vid.utils.Streams.not; + + +@Component +public class AAITreeNodeBuilder { + + 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"), + PROV_STATUS("prov-status"), + IN_MAINT("in-maint"), + MODEL_VERSION_ID("model-version-id"), + MODEL_CUSTOMIZATION_ID("model-customization-id"), + MODEL_INVARIANT_ID("model-invariant-id"), + RELATIONSHIP_LIST("relationship-list"); + + private final String aaiKey; + + AAIBaseProperties(String aaiKey) { + this.aaiKey = aaiKey; + } + + public String getAaiKey() { + return aaiKey; + } + } + + 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) { + + JsonNode topLevelJson = aaiClient.typedAaiGet(Unchecked.toURI(requestURL), JsonNode.class); + + 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)); + } + } + + 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); + } + return node; + } + + private AAITreeNode jsonToAaiNode(String nodeType, JsonNode topLevelJson, ConcurrentSkipListSet nodesAccumulator, AtomicInteger nodesCounter) { + AAITreeNode node = fillNodeMetaData(nodeType, topLevelJson, nodesCounter); + + nodesAccumulator.add(node); + + return node; + } + + private void getRelatedVfModules(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, String parentURL, AAITreeNode parentNode, AtomicInteger nodesCounter) { + /* + VNFs do not report their direct related-to vf-modules, so try + directly fetching a resource URI. + */ + + threadPool.execute(() -> { + // the response is an array of vf-modules + final JsonNode topLevelJson; + try { + topLevelJson = 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 + 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()) + ); + } 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); + } + } + + 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)); + } + } + ); + } + } + } + + private AAITreeNode fillNodeMetaData(String nodeType, JsonNode model, @NotNull AtomicInteger nodesCounter) { + 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)); + + return node; + } + + private AAITreeNode createFailureNode(Exception exception) { + return FailureAAITreeNode.of(exception); + } + + private String getStringDataFromJsonIfExists(JsonNode model, String key) { + if (model.has(key)) { + return model.get(key).asText(); + } + return null; + } + + private Boolean getBooleanDataFromJsonIfExists(JsonNode model, String key) { + if (model.has(key)) { + return model.get(key).asBoolean(); + } + return false; + } + + private Map aggregateAllOtherProperties(JsonNode model, String 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 -> 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; + } + + 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; + } +} \ 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 d2ee32cbc..bd751c5c2 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 @@ -22,6 +22,7 @@ package org.onap.vid.services; import io.joshworks.restclient.http.HttpResponse; +import org.onap.vid.aai.AaiGetVnfResponse; import org.onap.vid.aai.AaiResponse; import org.onap.vid.aai.AaiResponseTranslator; import org.onap.vid.aai.SubscriberFilteredResults; @@ -32,6 +33,7 @@ import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse; import org.onap.vid.aai.model.PortDetailsTranslator; import org.onap.vid.asdc.beans.Service; import org.onap.vid.model.SubscriberList; +import org.onap.vid.model.aaiTree.RelatedVnf; import org.onap.vid.roles.RoleValidator; import javax.ws.rs.core.Response; @@ -64,7 +66,7 @@ public interface AaiService { AaiResponse getAicZoneForPnf(String globalCustomerId , String serviceType , String serviceId); - Response getVNFData(String globalSubscriberId, String serviceType); + AaiResponse getVNFData(String globalSubscriberId, String serviceType); AaiResponse getTenants(String globalCustomerId, String serviceType, RoleValidator roleValidator); @@ -87,4 +89,10 @@ public interface AaiService { List getPortMirroringSourcePorts(String configurationId); AaiResponse getInstanceGroupsByVnfInstanceId(String vnfInstanceId); + + String getAAIServiceTree(String globalCustomerId, String serviceType, String serviceInstanceId); + + GetTenantsResponse getHomingDataByVfModule(String vnfInstanceId, String vfModuleId); + + List searchGroupMembers(String globalCustomerId, String serviceType, String invariantId, String groupType, String groupRole); } 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 acdf0afb5..fe4a66185 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 @@ -21,38 +21,35 @@ 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.http.HttpStatus; -import org.codehaus.jackson.JsonNode; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.*; -import org.onap.vid.aai.ServiceInstance; -import org.onap.vid.aai.ServiceSubscription; -import org.onap.vid.aai.Services; -import org.onap.vid.aai.model.AaiGetAicZone.AicZones; -import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.AaiGetNetworkCollectionDetails; +import org.onap.vid.aai.model.*; import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.AaiGetRelatedInstanceGroupsByVnfId; import org.onap.vid.aai.model.AaiGetOperationalEnvironments.OperationalEnvironmentList; import org.onap.vid.aai.model.AaiGetPnfs.Pnf; import org.onap.vid.aai.model.AaiGetServicesRequestModel.GetServicesAAIRespone; +import org.onap.vid.aai.model.Properties; import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse; -import org.onap.vid.aai.model.*; import org.onap.vid.asdc.beans.Service; +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.RelatedVnf; import org.onap.vid.roles.RoleValidator; import org.onap.vid.utils.Intersection; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.utils.Tree; import org.springframework.beans.factory.annotation.Autowired; import javax.ws.rs.core.Response; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; -import org.springframework.beans.factory.annotation.Qualifier; /** * Created by Oren on 7/4/17. @@ -62,18 +59,25 @@ public class AaiServiceImpl implements AaiService { private static final String SERVICE_TYPE = "service-subscription.service-type"; private static final String CUSTOMER_ID = "customer.global-customer-id"; private static final String SERVICE_INSTANCE_NAME = "service-instance.service-instance-name"; + private static final String TENANT_NODE_TYPE = "tenant"; + private static final String CLOUD_REGION_NODE_TYPE = "cloud-region"; private int indexOfSubscriberName = 6; @Autowired private AaiClientInterface aaiClient; @Autowired - @Qualifier("aaiClientForCodehausMapping") private AaiOverTLSClientInterface aaiOverTLSClient; @Autowired private AaiResponseTranslator aaiResponseTranslator; + @Autowired + private AAITreeNodeBuilder aaiTreeNode; + + @Autowired + private AAIServiceTree aaiServiceTree; + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AaiServiceImpl.class); private List convertModelToService(Model model) { @@ -277,9 +281,7 @@ public class AaiServiceImpl implements AaiService { new ServiceInstanceSearchResult(serviceInstance.serviceInstanceId, subscriberId, serviceType, serviceInstance.serviceInstanceName, subscriberName, serviceInstance.modelInvariantId, serviceInstance.modelVersionId, serviceSubscription.isPermitted); - if (instanceIdentifier == null) { - results.add(serviceInstanceSearchResult); - } else if (serviceInstanceMatchesIdentifier(instanceIdentifier, serviceInstance)) { + if ((instanceIdentifier == null) || (serviceInstanceMatchesIdentifier(instanceIdentifier, serviceInstance))){ results.add(serviceInstanceSearchResult); } } @@ -345,13 +347,31 @@ public class AaiServiceImpl implements AaiService { } @Override - public Response getVNFData(String globalSubscriberId, String serviceType) { - return aaiClient.getVNFData(globalSubscriberId, serviceType); + public AaiResponse getVNFData(String globalSubscriberId, String serviceType) { + AaiResponse response = aaiClient.getVNFData(globalSubscriberId, serviceType); + return filterChangeManagementVNFCandidatesResponse(response); + } + + private AaiResponse filterChangeManagementVNFCandidatesResponse(AaiResponse response) { + + + if (response != null && response.getT() != null) { + response.getT().results = + response.getT().results.stream() + .filter(result -> ( + result.nodeType.equalsIgnoreCase("generic-vnf") || + result.nodeType.equalsIgnoreCase("service-instance"))) + .collect(Collectors.toList()); + + return response; + } + + return new AaiResponse(); } @Override public AaiResponse getAaiZones() { - return (AaiResponse) aaiClient.getAllAicZones(); + return aaiClient.getAllAicZones(); } @Override @@ -386,14 +406,12 @@ public class AaiServiceImpl implements AaiService { @Override public AaiResponse getNetworkCollectionDetails(String serviceInstanceId){ - AaiResponse getNetworkCollectionDetailsAaiResponse = aaiClient.getNetworkCollectionDetails(serviceInstanceId); - return getNetworkCollectionDetailsAaiResponse; + return aaiClient.getNetworkCollectionDetails(serviceInstanceId); } @Override public AaiResponse getInstanceGroupsByCloudRegion(String cloudOwner, String cloudRegionId, String networkFunction){ - AaiResponse getInstanceGroupsByCloudRegionResponse = aaiClient.getInstanceGroupsByCloudRegion(cloudOwner, cloudRegionId, networkFunction); - return getInstanceGroupsByCloudRegionResponse; + return aaiClient.getInstanceGroupsByCloudRegion(cloudOwner, cloudRegionId, networkFunction); } @Override @@ -452,6 +470,66 @@ public class AaiServiceImpl implements AaiService { return aaiClient.getInstanceGroupsByVnfInstanceId(vnfInstanceId); } + @Override + public GetTenantsResponse getHomingDataByVfModule(String vnfInstanceId, String vfModuleId) { + return aaiClient.getHomingDataByVfModule(vnfInstanceId,vfModuleId); + } + + @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; + + Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(AAITreeNodeBuilder.SERVICE_INSTANCE)); + pathsToSearch.addPath(AAITreeNodeBuilder.toAaiRelationshipList(AAITreeNodeBuilder.GENERIC_VNF, AAITreeNodeBuilder.INSTANCE_GROUP)); + + //get all vnfs related to service-instances from the model-invariant-id + List aaiTree = aaiServiceTree.buildAAITree(getURL, pathsToSearch); + + //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() + .map(RelatedVnf::from) + .map(this::enrichRelatedVnfWithCloudRegionAndTenant) + .collect(Collectors.toList()); + } + + private List filterByInstanceGroupRoleAndType(List aaiTree, String groupRole, String groupType) { + + return aaiTree.stream() + .map(AAITreeNode::getChildren) + .flatMap(Collection::stream) + .filter(vnf -> isInstanceGroupsNotMatchRoleAndType(vnf.getChildren(), groupRole, groupType)) + .collect(Collectors.toList()); + } + + public boolean isInstanceGroupsNotMatchRoleAndType(List instanceGroups, String groupRole, String groupType) { + return instanceGroups.stream() + .map(AAITreeNode::getAdditionalProperties) + .allMatch(props -> + (!(groupRole.equals(props.get("instance-group-role")) && + groupType.equals(props.get("instance-group-type")))) + ); + } + + public RelatedVnf enrichRelatedVnfWithCloudRegionAndTenant(RelatedVnf vnf) { + Map cloudRegionAndTenant = aaiClient.getCloudRegionAndTenantByVnfId(vnf.getInstanceId()); + + if (cloudRegionAndTenant.containsKey(TENANT_NODE_TYPE)) { + vnf.setTenantId(cloudRegionAndTenant.get(TENANT_NODE_TYPE).getTenantId()); + vnf.setTenantName(cloudRegionAndTenant.get(TENANT_NODE_TYPE).getTenantName()); + } + + if (cloudRegionAndTenant.containsKey(CLOUD_REGION_NODE_TYPE)) { + vnf.setLcpCloudRegionId(cloudRegionAndTenant.get(CLOUD_REGION_NODE_TYPE).getCloudRegionId()); + } + + return vnf; + } private List convertGetInstanceGroupsResponseToSimpleResponse(AaiGetRelatedInstanceGroupsByVnfId response) { List instanceGroupInfoList = new ArrayList<>(); for(org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship: response.getRelationshipList().getRelationship()){ @@ -524,4 +602,16 @@ public class AaiServiceImpl implements AaiService { return relationshipValues; } + + public String getAAIServiceTree(String globalCustomerId, String serviceType, String serviceInstanceId) { + ObjectMapper om = new ObjectMapper(); + String result; + try { + org.onap.vid.model.aaiTree.ServiceInstance tree = aaiServiceTree.getServiceInstanceTopology(globalCustomerId, serviceType, serviceInstanceId); + result = om.writeValueAsString(tree); + } catch (Exception e) { + throw new GenericUncheckedException(e); + } + return result; + } } 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 90eb0d2b8..07bf46157 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 @@ -5,12 +5,13 @@ import org.onap.vid.changeManagement.RequestDetailsWrapper; import org.onap.vid.job.Job; import org.onap.vid.model.JobAuditStatus; import org.onap.vid.model.ServiceInfo; -import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; +import org.onap.vid.model.serviceInstantiation.*; +import org.onap.vid.mso.model.*; 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; @@ -22,10 +23,40 @@ public interface AsyncInstantiationBusinessLogic { List pushBulkJob(ServiceInstantiation request, String userId); - RequestDetailsWrapper generateServiceInstantiationRequest(UUID uuid, ServiceInstantiation details, 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); String getServiceInstantiationPath(ServiceInstantiation serviceInstantiationRequest); + String getServiceDeletionPath(String serviceInstanceId); + + String getVnfInstantiationPath(String serviceInstanceId); + + String getNetworkInstantiationPath(String serviceInstanceId); + + String getVfmoduleInstantiationPath(String serviceInstanceId, String vnfInstanceId); + + String getVolumeGroupInstantiationPath(String serviceInstanceId, String vnfInstanceId); + + String getInstanceGroupInstantiationPath(); + + String getInstanceGroupDeletePath(String instanceGroupId); + String getOrchestrationRequestsPath(); ServiceInfo getServiceInfoByJobId(UUID jobUUID); @@ -57,4 +88,6 @@ public interface AsyncInstantiationBusinessLogic { void setMaxRetriesGettingFreeNameFromAai(int maxRetriesGettingFreeNameFromAai); String getUniqueName(String name, ResourceType resourceType); + + } 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 df8e92d66..c4264c6b5 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 @@ -1,42 +1,17 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2018 Nokia. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - 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 com.google.common.collect.ImmutableMap; -import io.joshworks.restclient.http.HttpResponse; -import java.io.IOException; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.io.IOUtils; 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.AaiOverTLSClientInterface; -import org.onap.vid.aai.AaiResponse; -import org.onap.vid.aai.exceptions.InvalidAAIResponseException; -import org.onap.vid.aai.model.AaiNodeQueryResponse; +import org.onap.vid.aai.ExceptionWithRequestInfo; import org.onap.vid.aai.model.ResourceType; import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.domain.mso.CloudConfiguration; -import org.onap.vid.domain.mso.SubscriberInfo; import org.onap.vid.exceptions.DbFailureUncheckedException; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.exceptions.MaxRetriesException; @@ -46,22 +21,25 @@ 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.model.Action; import org.onap.vid.model.JobAuditStatus; import org.onap.vid.model.NameCounter; import org.onap.vid.model.ServiceInfo; -import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; -import org.onap.vid.model.serviceInstantiation.VfModule; -import org.onap.vid.model.serviceInstantiation.Vnf; +import org.onap.vid.model.serviceInstantiation.*; import org.onap.vid.mso.MsoBusinessLogicImpl; import org.onap.vid.mso.MsoProperties; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; +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.rest.AsyncRequestStatus; +import org.onap.vid.mso.rest.SubscriberInfo; +import org.onap.vid.properties.Features; import org.onap.vid.utils.DaoUtils; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.portalsdk.core.service.DataAccessService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; +import org.togglz.core.manager.FeatureManager; import java.sql.Timestamp; import java.time.LocalDateTime; @@ -69,14 +47,19 @@ 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 { +public class AsyncInstantiationBusinessLogicImpl implements + AsyncInstantiationBusinessLogic { private static final int MAX_RETRIES_GETTING_COUNTER = 100; private static final int MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI = 10000; - private static final String NAME_FOR_CHECK_AAI_STATUS = "NAME_FOR_CHECK_AAI_STATUS"; + 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; @@ -84,64 +67,86 @@ public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBu private final JobsBrokerService jobService; + private final CloudOwnerService cloudOwnerService; + private SessionFactory sessionFactory; - private AaiOverTLSClientInterface aaiOverTLSClient; + private AaiClientInterface aaiClient; + + private FeatureManager featureManager; private int maxRetriesGettingFreeNameFromAai = MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI; - private static final EELFLoggerDelegate logger = EELFLoggerDelegate - .getLogger(AsyncInstantiationBusinessLogicImpl.class); + private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AsyncInstantiationBusinessLogicImpl.class); private Map msoStateToJobStatusMap = ImmutableMap.builder() - .put("inprogress", JobStatus.IN_PROGRESS) - .put("failed", JobStatus.FAILED) - .put("pause", JobStatus.PAUSE) - .put("paused", JobStatus.PAUSE) - .put("complete", JobStatus.COMPLETED) - .put("pending", JobStatus.IN_PROGRESS) - .put("pendingmanualtask", JobStatus.PAUSE) - .put("unlocked", JobStatus.IN_PROGRESS) - .build(); + .put("inprogress", JobStatus.IN_PROGRESS) + .put("failed", JobStatus.FAILED) + .put("pause", JobStatus.PAUSE) + .put("paused", JobStatus.PAUSE) + .put("complete", JobStatus.COMPLETED) + .put("pending", JobStatus.IN_PROGRESS) + .put("pendingmanualtask", JobStatus.PAUSE) + .put("unlocked", JobStatus.IN_PROGRESS) + .build(); @Autowired public AsyncInstantiationBusinessLogicImpl(DataAccessService dataAccessService, - JobAdapter jobAdapter, - JobsBrokerService jobService, - SessionFactory sessionFactory, - @Qualifier("aaiClientForFasterXmlMapping") AaiOverTLSClientInterface aaiOverTLSClient) { + JobAdapter jobAdapter, + JobsBrokerService jobService, + SessionFactory sessionFactory, + AaiClientInterface aaiClient, + FeatureManager featureManager, + CloudOwnerService cloudOwnerService) { this.dataAccessService = dataAccessService; this.jobAdapter = jobAdapter; this.jobService = jobService; this.sessionFactory = sessionFactory; - this.aaiOverTLSClient = aaiOverTLSClient; + this.aaiClient = aaiClient; + this.featureManager = featureManager; + this.cloudOwnerService = cloudOwnerService; } @Override public List getAllServicesInfo() { - return dataAccessService - .getList(ServiceInfo.class, filterByCreationDateAndNotDeleted(), orderByCreatedDateAndStatus(), null); + 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 + "' "; + " 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 'IN_PROGRESS' THEN 1\n" + - " WHEN 'PAUSE' THEN 2\n" + - " WHEN 'PENDING' THEN 3\n" + - " WHEN 'STOPPED' THEN 3 END),\n" + - " statusModifiedDate "; + " (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 "; + } + + JobType getJobType(ServiceInstantiation request) { + if (request.isALaCarte()) { + switch (defaultIfNull(request.getAction(), Action.Create)) { + case Delete: + return JobType.ALaCarteService; + case None: + return JobType.ALaCarteService; + default: + return JobType.ALaCarteServiceInstantiation; + } + } else { + return JobType.MacroServiceInstantiation; + } } @Override @@ -151,173 +156,460 @@ public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBu int bulkSize = request.getBulkSize(); UUID templateId = UUID.randomUUID(); for (int i = 0; i < bulkSize; i++) { - Job job = jobAdapter.createJob(JobType.ServiceInstantiation, request, templateId, userId, 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()); uuids.add(jobId); - dataAccessService.saveDomainObject(createServiceInfo(userId, request, jobId, templateId, createdBulkDate), - DaoUtils.getPropsMap()); } return uuids; } - private ServiceInfo createServiceInfo(String userId, ServiceInstantiation serviceInstantiation, UUID jobId, - UUID templateId, Date createdBulkDate) { + private ServiceInfo.ServiceAction getAction(ServiceInstantiation request) { + if (request.getAction() == null) { + //throw new GenericUncheckedException("Required 'action' field not provided at service level"); + return Action.Create.getServiceAction(); + } + return request.getAction().getServiceAction(); + } + + + private String getOptimisticUniqueServiceInstanceName(ServiceInstantiation request) { + return StringUtils.isNotEmpty(request.getInstanceName()) ? getUniqueNameFromDbOnly(request.getInstanceName()) : request.getInstanceName(); + } + + protected ServiceInfo createServiceInfo(String userId, ServiceInstantiation serviceInstantiation, UUID jobId, UUID templateId, Date createdBulkDate, String optimisticUniqueServiceInstanceName, ServiceInfo.ServiceAction serviceAction) { return new ServiceInfo( - userId, Job.JobStatus.PENDING, serviceInstantiation.isPause(), jobId, templateId, - serviceInstantiation.getOwningEntityId(), - serviceInstantiation.getOwningEntityName(), - serviceInstantiation.getProjectName(), - serviceInstantiation.getAicZoneId(), - serviceInstantiation.getAicZoneName(), - serviceInstantiation.getTenantId(), - serviceInstantiation.getTenantName(), - serviceInstantiation.getLcpCloudRegionId(), - null, - serviceInstantiation.getSubscriptionServiceType(), - serviceInstantiation.getSubscriberName(), - null, - serviceInstantiation.getInstanceName(), - serviceInstantiation.getModelInfo().getModelInvariantId(), - serviceInstantiation.getModelInfo().getModelName(), - serviceInstantiation.getModelInfo().getModelVersion(), - createdBulkDate + userId, + serviceInstantiation.isALaCarte(), + Job.JobStatus.PENDING, serviceInstantiation.isPause(), jobId, templateId, + serviceInstantiation.getOwningEntityId(), + serviceInstantiation.getOwningEntityName(), + serviceInstantiation.getProjectName(), + serviceInstantiation.getAicZoneId(), + serviceInstantiation.getAicZoneName(), + serviceInstantiation.getTenantId(), + serviceInstantiation.getTenantName(), + serviceInstantiation.getLcpCloudRegionId(), + null, + serviceInstantiation.getSubscriptionServiceType(), + serviceInstantiation.getSubscriberName(), + serviceInstantiation.getGlobalSubscriberId(), + serviceInstantiation.getInstanceId(), + optimisticUniqueServiceInstanceName, + serviceInstantiation.getModelInfo().getModelVersionId(), + serviceInstantiation.getModelInfo().getModelName(), + serviceInstantiation.getModelInfo().getModelVersion(), + createdBulkDate, + serviceAction ); } @Override - public RequestDetailsWrapper generateServiceInstantiationRequest(UUID jobId, - ServiceInstantiation payload, String userId) { + 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; + } + + @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; + } + + @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)); + } + + @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); + } - ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity owningEntity = new ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity( - payload.getOwningEntityId(), payload.getOwningEntityName()); + 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 + ); + 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 (payload.isUserProvidedNaming()) { + 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); - String finalServiceInstanceName = serviceInstanceName; - updateServiceInfo(jobId, x -> x.setServiceInstanceName(finalServiceInstanceName)); } - ServiceInstantiationRequestDetails.RequestInfo requestInfo = new ServiceInstantiationRequestDetails.RequestInfo( - serviceInstanceName, - payload.getProductFamilyId(), - "VID", - payload.isRollbackOnFailure(), - userId); - - List serviceInstantiationService = new LinkedList<>(); - List> unFilteredInstanceParams = - payload.getInstanceParams() != null ? payload.getInstanceParams() : new LinkedList<>(); - List> filteredInstanceParams = removeUnNeededParams(unFilteredInstanceParams); - ServiceInstantiationRequestDetails.ServiceInstantiationService serviceInstantiationService1 = new ServiceInstantiationRequestDetails.ServiceInstantiationService( - payload.getModelInfo(), - serviceInstanceName, - filteredInstanceParams, - createServiceInstantiationVnfList(payload) - ); - serviceInstantiationService.add(serviceInstantiationService1); - ServiceInstantiationRequestDetails.RequestParameters requestParameters = new ServiceInstantiationRequestDetails.RequestParameters( - payload.getSubscriptionServiceType(), false, serviceInstantiationService); + //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); + } - ServiceInstantiationRequestDetails.Project project = - payload.getProjectName() != null ? new ServiceInstantiationRequestDetails.Project(payload.getProjectName()) - : null; + return serviceInstanceName; + } - ServiceInstantiationRequestDetails requestDetails = new ServiceInstantiationRequestDetails( - payload.getModelInfo(), owningEntity, subscriberInfo, - project, requestInfo, requestParameters); + @Override + public List> buildVnfInstanceParams(List> currentVnfInstanceParams, List vfModules){ + List> filteredVnfInstanceParams = removeUnNeededParams(currentVnfInstanceParams); - RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper( - requestDetails); - debugRequestDetails(requestDetailsWrapper, logger); - return requestDetailsWrapper; + 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()) { - for (String key : instanceParams.get(0).keySet()) { - for (String paramToIgnore : PARAMS_TO_IGNORE) { - if ((key.equalsIgnoreCase(paramToIgnore))) { - keysToRemove.add(key); - } + 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); } - } - for (String key : keysToRemove) { - instanceParams.get(0).remove(key); - } - //TODO will be removed on once we stop using List> - if (instanceParams.get(0).isEmpty()) { - return Collections.emptyList(); - } } - return instanceParams; + + 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 ServiceInstantiationRequestDetails.ServiceInstantiationVnfList createServiceInstantiationVnfList( - ServiceInstantiation payload) { - CloudConfiguration cloudConfiguration = new CloudConfiguration(); - cloudConfiguration.setTenantId(payload.getTenantId()); - cloudConfiguration.setLcpCloudRegionId(payload.getLcpCloudRegionId()); + private ServiceInstantiationVnfList createServiceInstantiationVnfList(ServiceInstantiation payload) { + CloudConfiguration cloudConfiguration = generateCloudConfiguration(payload.getLcpCloudRegionId(), payload.getTenantId()); Map vnfs = payload.getVnfs(); - List vnfList = new ArrayList<>(); + List vnfList = new ArrayList<>(); for (Vnf vnf : vnfs.values()) { Map> vfModules = vnf.getVfModules(); - List convertedUnFilteredVfModules = convertVfModuleMapToList(vfModules); - List filteredVfModules = filterInstanceParamsFromVfModuleAndUniqueNames( - convertedUnFilteredVfModules, vnf.isUserProvidedNaming()); - ServiceInstantiationRequestDetails.ServiceInstantiationVnf serviceInstantiationVnf = new ServiceInstantiationRequestDetails.ServiceInstantiationVnf( - vnf.getModelInfo(), - cloudConfiguration, - vnf.getPlatformName(), - vnf.getLineOfBusiness(), - payload.getProductFamilyId(), - removeUnNeededParams(vnf.getInstanceParams()), - filteredVfModules, - vnf.isUserProvidedNaming() ? getUniqueName(vnf.getInstanceName(), ResourceType.GENERIC_VNF) : null + 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 ServiceInstantiationRequestDetails.ServiceInstantiationVnfList(vnfList); + return new ServiceInstantiationVnfList(vnfList); } - private List convertVfModuleMapToList(Map> vfModules) { - return vfModules.values().stream().flatMap(vfModule -> vfModule.values().stream()).collect(Collectors.toList()); + 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, - boolean isUserProvidedNaming) { + private List filterInstanceParamsFromVfModuleAndUniqueNames(List unFilteredVfModules) { return unFilteredVfModules.stream().map(vfModule -> - new VfModule( - vfModule.getModelInfo(), - getUniqueNameIfNeeded(isUserProvidedNaming, vfModule.getInstanceName(), ResourceType.VF_MODULE), - getUniqueNameIfNeeded(isUserProvidedNaming, vfModule.getVolumeGroupInstanceName(), - ResourceType.VOLUME_GROUP), - removeUnNeededParams(vfModule.getInstanceParams()))) - .collect(Collectors.toList()); + 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(boolean isUserProvidedNaming, String name, ResourceType resourceType) { - return isUserProvidedNaming && !StringUtils.isEmpty(name) ? - getUniqueName(name, resourceType) : null; + private String getUniqueNameIfNeeded(String name, ResourceType resourceType) { + return StringUtils.isNotEmpty(name) ? getUniqueName(name, resourceType) : null; } @Override public String getServiceInstantiationPath(ServiceInstantiation serviceInstantiationRequest) { //in case pause flag is true - use assign , else - use create. return MsoBusinessLogicImpl.validateEndpointPath( - serviceInstantiationRequest.isPause() ? - "mso.restapi.serviceInstanceAssign" : "mso.restapi.serviceInstanceCreate" + serviceInstantiationRequest.isPause() ? + MsoProperties.MSO_REST_API_SERVICE_INSTANCE_ASSIGN : MsoProperties.MSO_REST_API_SERVICE_INSTANCE_CREATE ); } + @Override + public String getServiceDeletionPath(String serviceInstanceId) { + return MsoBusinessLogicImpl.validateEndpointPath( MsoProperties.MSO_DELETE_OR_UNASSIGN_REST_API_SVC_INSTANCE) + "/" + serviceInstanceId; + } + + @Override + public String getVnfInstantiationPath(String serviceInstanceId) { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VNF_INSTANCE). + replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + } + + @Override + public String getNetworkInstantiationPath(String serviceInstanceId) { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE). + replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + } + + @Override + public String getVfmoduleInstantiationPath(String serviceInstanceId, String vnfInstanceId) { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId) + .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + } + + @Override + public String getVolumeGroupInstantiationPath(String serviceInstanceId, String vnfInstanceId) { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId) + .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + } + + @Override + public String getInstanceGroupInstantiationPath() { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP); + } + + @Override + public String getInstanceGroupDeletePath(String instanceGroupId) { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP) + + '/' + instanceGroupId; + } + @Override public String getOrchestrationRequestsPath() { return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ); @@ -333,7 +625,7 @@ public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBu @Override public ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, JobStatus jobStatus) { - auditVidStatus(jobUuid, jobStatus); + auditVidStatus(jobUuid,jobStatus); return updateServiceInfo(jobUuid, x -> setServiceInfoStatus(x, jobStatus)); } @@ -343,12 +635,9 @@ public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBu } public ServiceInfo getServiceInfoByJobId(UUID jobUUID) { - List serviceInfoList = dataAccessService - .getList(ServiceInfo.class, String.format(" where jobId = '%s' ", jobUUID), null, null); + 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()); + throw new GenericUncheckedException("Failed to retrieve job with uuid " + jobUUID + " from ServiceInfo table. Instances found: " + serviceInfoList.size()); } return serviceInfoList.get(0); } @@ -356,46 +645,43 @@ public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBu public List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source) { return dataAccessService.getList( JobAuditStatus.class, - String.format(" where SOURCE = '%s' and JOB_ID = '%s'", source, jobUUID), + 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; + private JobAuditStatus getLatestAuditStatus(UUID jobUUID, JobAuditStatus.SourceStatus source){ + List list = getAuditStatuses(jobUUID,source); + return !list.isEmpty() ? list.get(list.size()-1) : null; } @Override - public void auditVidStatus(UUID jobUUID, JobStatus jobStatus) { + public void auditVidStatus(UUID jobUUID, 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()); + 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) { + 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); + requestId != null ? UUID.fromString(requestId) : null, + additionalInfo); auditStatus(msoStatus); } - private void auditStatus(JobAuditStatus jobAuditStatus) { + private void auditStatus(JobAuditStatus jobAuditStatus){ JobAuditStatus latestStatus = getLatestAuditStatus(jobAuditStatus.getJobId(), jobAuditStatus.getSource()); - if (latestStatus == null || !latestStatus.equals(jobAuditStatus)) { + if (latestStatus == null || !latestStatus.equals(jobAuditStatus)) dataAccessService.saveDomainObject(jobAuditStatus, DaoUtils.getPropsMap()); - } } public Job.JobStatus calcStatus(AsyncRequestStatus asyncRequestStatus) { - String msoRequestState = asyncRequestStatus.request.requestStatus.getRequestState().toLowerCase() - .replaceAll("[^a-z]+", ""); + String msoRequestState = asyncRequestStatus.request.requestStatus.getRequestState().toLowerCase().replaceAll("[^a-z]+", ""); JobStatus jobStatus = msoStateToJobStatusMap.get(msoRequestState); return (jobStatus != null ? jobStatus : JobStatus.IN_PROGRESS); } @@ -404,11 +690,11 @@ public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBu 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.class, + String.format(" where templateId = '%s' and jobStatus = '%s'", + serviceInfo.getTemplateId(), + JobStatus.PENDING), + null, null); serviceInfoList.forEach(si -> updateServiceInfoAndAuditStatus(si.getJobId(), JobStatus.STOPPED)); } @@ -423,9 +709,9 @@ public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBu public void hideServiceInfo(UUID jobUUID) { ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID); if (!serviceInfo.getJobStatus().isFinal()) { - String message = String.format("jobId %s: Service status does not allow hide service, status = %s", - serviceInfo.getJobId(), - serviceInfo.getJobStatus()); + 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); } @@ -434,31 +720,30 @@ public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBu } @Override - public int - - getCounterForName(String name) { + public int getCounterForName(String name) { String hqlSelectNC = "from NameCounter where name = :name"; String hqlUpdateCounter = "update NameCounter set counter = :newCounter " + - "where name= :name " + - "and counter= :prevCounter"; + "where name= :name " + + "and counter= :prevCounter"; Integer counter = null; GenericUncheckedException lastException = null; - for (int i = 0; i < MAX_RETRIES_GETTING_COUNTER && counter == null; i++) { + for (int i = 0; i< MAX_RETRIES_GETTING_COUNTER && counter==null; i++) { try { counter = calcCounter(name, hqlSelectNC, hqlUpdateCounter); - } catch (GenericUncheckedException exception) { + } + catch (GenericUncheckedException exception) { lastException = exception; //do nothing, we will try again in the loop } } - if (counter != null) { + if (counter!=null) { return counter; } - throw lastException != null ? new DbFailureUncheckedException(lastException) : - new DbFailureUncheckedException("Failed to get counter for " + name + " due to unknown error"); + throw lastException!=null ? new DbFailureUncheckedException(lastException) : + new DbFailureUncheckedException("Failed to get counter for "+name+" due to unknown error"); } @@ -466,14 +751,14 @@ public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBu Integer counter; counter = DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> { NameCounter nameCounter = (NameCounter) session.createQuery(hqlSelectNC) - .setText("name", name) - .uniqueResult(); + .setText("name", name) + .uniqueResult(); if (nameCounter != null) { int updatedRows = session.createQuery(hqlUpdateCounter) - .setText("name", nameCounter.getName()) - .setInteger("prevCounter", nameCounter.getCounter()) - .setInteger("newCounter", nameCounter.getCounter() + 1) - .executeUpdate(); + .setText("name", nameCounter.getName()) + .setInteger("prevCounter", nameCounter.getCounter()) + .setInteger("newCounter", nameCounter.getCounter() + 1) + .executeUpdate(); if (updatedRows == 1) { return nameCounter.getCounter() + 1; } @@ -481,7 +766,7 @@ public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBu Object nameAsId = session.save(new NameCounter(name)); //if save success if (nameAsId != null) { - return 1; + return 0; } } //in case of failure return null, in order to continue the loop @@ -506,34 +791,28 @@ public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBu //Prevents unnecessary increasing of the counter while AAI doesn't response isNameFreeInAai(NAME_FOR_CHECK_AAI_STATUS, resourceType); - for (int i = 0; i < getMaxRetriesGettingFreeNameFromAai(); i++) { - int counter = getCounterForName(name); - String newName = formatNameAndCounter(name, counter); + for (int i=0; i aaiResponse = aaiOverTLSClient - .searchNodeTypeByName(name, resourceType); - if (aaiResponse.getStatus() > 399 || aaiResponse.getBody() == null) { - try { - String message = IOUtils.toString(aaiResponse.getRawBody(), "UTF-8"); - throw new InvalidAAIResponseException(aaiResponse.getStatus(), message); - } catch (IOException e) { - throw new InvalidAAIResponseException(aaiResponse.getStatus(), aaiResponse.getStatusText()); - } - } - return CollectionUtils.isEmpty(aaiResponse.getBody().resultData); + private boolean isNameFreeInAai(String name, ResourceType resourceType) throws ExceptionWithRequestInfo { + return !aaiClient.isNodeTypeExistsByName(name, resourceType); } } 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 19569a7fb..01443deab 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 @@ -1,11 +1,18 @@ package org.onap.vid.services; -import org.onap.vid.model.RequestReferencesContainer; -import org.onap.vid.mso.RestObject; +import org.onap.vid.model.JobAuditStatus; +import java.util.List; import java.util.UUID; 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 getAuditStatusFromMsoByJobId(UUID jobId); } 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 b4806f1ce..339a9edd7 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 @@ -1,47 +1,42 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2018 Nokia. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ 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 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.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.UUID; +import java.util.stream.Collectors; @Service public class AuditServiceImpl implements AuditService{ + private final AsyncInstantiationBusinessLogic asyncInstantiationBL; + private final RestMsoImplementation restMso; + @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - public static final String FAILED_MSO_REQUEST_STATUS = "FAILED"; + public AuditServiceImpl(AsyncInstantiationBusinessLogic asyncInstantiationBL, RestMsoImplementation restMso) { + this.asyncInstantiationBL = asyncInstantiationBL; + this.restMso = restMso; + } @Override public void setFailedAuditStatusFromMso(UUID jobUuid, String requestId, int statusCode, String msoResponse){ + final String failedMsoRequestStatus = "FAILED"; String additionalInfo = formatExceptionAdditionalInfo(statusCode, msoResponse); - asyncInstantiationBL.auditMsoStatus(jobUuid, FAILED_MSO_REQUEST_STATUS, requestId, additionalInfo); + asyncInstantiationBL.auditMsoStatus(jobUuid, failedMsoRequestStatus, requestId, additionalInfo); } private String formatExceptionAdditionalInfo(int statusCode, String msoResponse) { @@ -64,4 +59,90 @@ public class AuditServiceImpl implements AuditService{ } return errorMsg; } + + @Override + public List getAuditStatusFromMsoByRequestId(UUID jobId, UUID requestId) { + String filter = "requestId:EQUALS:" + requestId; + return getAuditStatusFromMso(jobId, filter, null); + } + + @Override + public List getAuditStatusFromMsoByServiceInstanceId(UUID jobId, UUID serviceInstanceId) { + String filter = "serviceInstanceId:EQUALS:" + serviceInstanceId; + return getAuditStatusFromMso(jobId, filter, serviceInstanceId); + } + + @Override + public List getAuditStatusFromMsoByJobId(UUID jobId) { + List auditStatuses = asyncInstantiationBL.getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO); + String instanceName = getInstanceNameFromServiceInfo(jobId); + auditStatuses.stream().forEach(status -> + status.setInstanceName(instanceName) + ); + return auditStatuses; + } + + + + private List getAuditStatusFromMso(UUID jobId, String filter, UUID serviceInstanceId) { + + 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); + } + + private String getInstanceNameFromServiceInfo(UUID jobId) { + return asyncInstantiationBL.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) { + 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(); + } + } + } + return new JobAuditStatus(instanceName, jobStatus, requestId, additionalInfo, created, instanceType); + }).collect(Collectors.toList()); + } + + private String extractInstanceName(String instanceName, AsyncRequestStatus.Request request) { + if(request.requestDetails != null && request.requestDetails.requestInfo != null && request.requestDetails.requestInfo.instanceName != null) { + instanceName = request.requestDetails.requestInfo.instanceName; + } + return instanceName; + } + + public static class BadResponseFromMso extends RuntimeException { + private final RestObject msoResponse; + + public BadResponseFromMso(RestObject msoResponse) { + this.msoResponse = msoResponse; + } + + public RestObject getMsoResponse() { + return msoResponse; + } + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/BulkInstantiationService.java b/vid-app-common/src/main/java/org/onap/vid/services/BulkInstantiationService.java index 387edc12d..645a6122d 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/BulkInstantiationService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/BulkInstantiationService.java @@ -1,15 +1,11 @@ package org.onap.vid.services; -import org.onap.vid.model.JobBulk; import org.onap.vid.model.JobModel; -import java.util.Map; import java.util.UUID; public interface BulkInstantiationService { - JobBulk saveBulk(Map bulkRequest); - JobModel getJob(UUID uuid); } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/BulkInstantiationServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/BulkInstantiationServiceImpl.java index 2a868f138..20f719a74 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/BulkInstantiationServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/BulkInstantiationServiceImpl.java @@ -3,14 +3,11 @@ package org.onap.vid.services; import org.onap.vid.job.Job; import org.onap.vid.job.JobAdapter; import org.onap.vid.job.JobsBrokerService; -import org.onap.vid.model.JobBulk; import org.onap.vid.model.JobModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.ws.rs.NotFoundException; -import java.util.List; -import java.util.Map; import java.util.UUID; @Service @@ -25,13 +22,6 @@ public class BulkInstantiationServiceImpl implements BulkInstantiationService { this.jobAdapter = jobAdapter; } - @Override - public JobBulk saveBulk(Map bulkRequest) { - List jobList = jobAdapter.createBulkOfJobs(bulkRequest); - jobList.forEach(jobsBrokerService::add); - return jobAdapter.toModelBulk(jobList); - } - @Override public JobModel getJob(UUID uuid) { Job job = jobsBrokerService.peek(uuid); diff --git a/vid-app-common/src/main/java/org/onap/vid/services/ChangeManagementService.java b/vid-app-common/src/main/java/org/onap/vid/services/ChangeManagementService.java index ab6239fd6..c83e1937f 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/ChangeManagementService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/ChangeManagementService.java @@ -1,8 +1,9 @@ package org.onap.vid.services; +import com.fasterxml.jackson.databind.node.ArrayNode; import org.apache.commons.lang3.tuple.Pair; -import org.json.simple.JSONArray; import org.onap.vid.changeManagement.*; +import org.onap.vid.mso.RestObjectWithRequestInfo; import org.onap.vid.mso.rest.Request; import org.springframework.http.ResponseEntity; import org.springframework.web.multipart.MultipartFile; @@ -13,7 +14,8 @@ import java.util.List; public interface ChangeManagementService { Collection getMSOChangeManagements(); ResponseEntity doChangeManagement(ChangeManagementRequest request, String vnfName); - JSONArray getSchedulerChangeManagements(); + ArrayNode getSchedulerChangeManagements(); + RestObjectWithRequestInfo getSchedulerChangeManagementsWithRequestInfo(); /** * Deleting a scheduled flow. diff --git a/vid-app-common/src/main/java/org/onap/vid/services/ChangeManagementServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/ChangeManagementServiceImpl.java index e4a6b3990..13525f842 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/ChangeManagementServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/ChangeManagementServiceImpl.java @@ -1,20 +1,23 @@ package org.onap.vid.services; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.hibernate.NonUniqueObjectException; import org.json.JSONObject; -import org.json.simple.JSONArray; -import org.json.simple.parser.JSONParser; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.service.DataAccessService; import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.changeManagement.*; +import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.exceptions.NotFoundException; import org.onap.vid.model.VNFDao; import org.onap.vid.model.VidWorkflow; import org.onap.vid.mso.MsoBusinessLogic; import org.onap.vid.mso.MsoResponseWrapperInterface; +import org.onap.vid.mso.RestObject; +import org.onap.vid.mso.RestObjectWithRequestInfo; import org.onap.vid.mso.rest.Request; import org.onap.vid.scheduler.SchedulerProperties; import org.onap.vid.scheduler.SchedulerRestInterfaceIfc; @@ -34,26 +37,27 @@ import java.util.stream.Collectors; @Service public class ChangeManagementServiceImpl implements ChangeManagementService { - private final static String PRIMARY_KEY = "payload"; - private final static Set REQUIRED_KEYS = new HashSet<>(Arrays.asList("request-parameters", "configuration-parameters")); + private static final String PRIMARY_KEY = "payload"; + private static final Set REQUIRED_KEYS = new HashSet<>(Arrays.asList("request-parameters", "configuration-parameters")); private final DataAccessService dataAccessService; private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ChangeManagementServiceImpl.class); private MsoBusinessLogic msoBusinessLogic; private final SchedulerRestInterfaceIfc restClient; + private final CloudOwnerService cloudOwnerService; @Autowired private CsvService csvService; @Autowired - public ChangeManagementServiceImpl(DataAccessService dataAccessService, MsoBusinessLogic msoBusinessLogic, SchedulerRestInterfaceIfc schedulerRestInterface) { + public ChangeManagementServiceImpl(DataAccessService dataAccessService, MsoBusinessLogic msoBusinessLogic, SchedulerRestInterfaceIfc schedulerRestInterface, CloudOwnerService cloudOwnerService) { this.dataAccessService = dataAccessService; this.msoBusinessLogic = msoBusinessLogic; this.restClient = schedulerRestInterface; + this.cloudOwnerService = cloudOwnerService; } @Override public Collection getMSOChangeManagements() { - Collection result = null; return msoBusinessLogic.getOrchestrationRequestsForDashboard(); } @@ -86,14 +90,17 @@ public class ChangeManagementServiceImpl implements ChangeManagementService { try { switch (requestType.toLowerCase()) { case ChangeManagementRequest.UPDATE: { + cloudOwnerService.enrichRequestWithCloudOwner(currentRequestDetails); msoResponseWrapperObject = msoBusinessLogic.updateVnf(currentRequestDetails, serviceInstanceId, vnfInstanceId); break; } case ChangeManagementRequest.REPLACE: { + cloudOwnerService.enrichRequestWithCloudOwner(currentRequestDetails); msoResponseWrapperObject = msoBusinessLogic.replaceVnf(currentRequestDetails, serviceInstanceId, vnfInstanceId); break; } case ChangeManagementRequest.VNF_IN_PLACE_SOFTWARE_UPDATE: { + cloudOwnerService.enrichRequestWithCloudOwner(currentRequestDetails); msoResponseWrapperObject = msoBusinessLogic.updateVnfSoftware(currentRequestDetails, serviceInstanceId, vnfInstanceId); break; } @@ -105,10 +112,10 @@ public class ChangeManagementServiceImpl implements ChangeManagementService { msoResponseWrapperObject = msoBusinessLogic.scaleOutVfModuleInstance(currentRequestDetails, serviceInstanceId, vnfInstanceId); break; } - default: - logger.error("Failure during doChangeManagement with request " + request.toString()); + default: + throw new GenericUncheckedException("Failure during doChangeManagement with request " + request.toString()); } - response = new ResponseEntity(msoResponseWrapperObject.getResponse(), HttpStatus.OK); + response = new ResponseEntity<>(msoResponseWrapperObject.getResponse(), HttpStatus.OK); return response; } catch (Exception e) { logger.error("Failure during doChangeManagement with request " + request.toString(), e); @@ -141,32 +148,26 @@ public class ChangeManagementServiceImpl implements ChangeManagementService { } @Override - public JSONArray getSchedulerChangeManagements() { - JSONArray result = null; - try { - String path = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_GET_SCHEDULES); - org.onap.vid.scheduler.RestObject restObject = new org.onap.vid.scheduler.RestObject<>(); - - String str = new String(); - restObject.set(str); - restClient.Get(str, "", path, restObject); - String restCallResult = restObject.get(); - JSONParser parser = new JSONParser(); - Object parserResult = parser.parse(restCallResult); - result = (JSONArray) parserResult; - } catch (Exception e) { - e.printStackTrace(); - } + public RestObjectWithRequestInfo getSchedulerChangeManagementsWithRequestInfo() { + String path = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_GET_SCHEDULES); + RestObject restObject = new RestObject<>(); + ArrayNode jsonArray = new ArrayNode(new JsonNodeFactory(true)); + restObject.set(jsonArray); + return restClient.Get(jsonArray, path, restObject); + } - return result; + @Override + public ArrayNode getSchedulerChangeManagements() { + RestObjectWithRequestInfo responseWithRequestInfo = getSchedulerChangeManagementsWithRequestInfo(); + return responseWithRequestInfo.getRestObject().get(); } @Override public Pair deleteSchedule(String scheduleId) { try { String path = String.format(SystemProperties.getProperty(SchedulerProperties.SCHEDULER_DELETE_SCHEDULE), scheduleId); - org.onap.vid.scheduler.RestObject restObject = new org.onap.vid.scheduler.RestObject<>(); - String str = new String(); + RestObject restObject = new RestObject<>(); + String str = ""; restObject.set(str); restClient.Delete(str, "", path, restObject); String restCallResult = restObject.get(); @@ -187,11 +188,11 @@ public class ChangeManagementServiceImpl implements ChangeManagementService { continue; } @SuppressWarnings("unchecked") List vnfList = dataAccessService.getList(VNFDao.class, getVnfQueryString(workflowsDetail.getVnfDetails().getUUID(), workflowsDetail.getVnfDetails().getInvariantUUID()), null, null); - if (vnfList.size() == 0) { + if (vnfList.isEmpty()) { vnfList.add(saveNewVnf(workflowsDetail)); } @SuppressWarnings("unchecked") List workflowList = dataAccessService.getList(VidWorkflow.class, String.format(" where wokflowName = '%s'", workflowsDetail.getWorkflowName()), null, null); - if (workflowList.size() == 0) { + if (workflowList.isEmpty()) { vnfWorkflowRelationResponse.getErrors().add("Not Found instance of workflow " + workflowsDetail.getWorkflowName() + " for vnf with UUID " + workflowsDetail.getVnfDetails().getUUID() + " and with invariantUUID " + workflowsDetail.getVnfDetails().getInvariantUUID()); continue; } 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 new file mode 100644 index 000000000..1d453819f --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java @@ -0,0 +1,12 @@ +package org.onap.vid.services; + +import org.onap.vid.mso.model.CloudConfiguration; +import org.onap.vid.mso.rest.RequestDetails; + +public interface CloudOwnerService { + + void enrichRequestWithCloudOwner(RequestDetails msoRequest); + + void enrichCloudConfigurationWithCloudOwner(CloudConfiguration cloudConfiguration, String lcpCloudRegionId); + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerServiceImpl.java new file mode 100644 index 000000000..3acab9ff9 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerServiceImpl.java @@ -0,0 +1,76 @@ +package org.onap.vid.services; + + +import com.google.common.collect.ImmutableList; +import org.apache.commons.lang3.StringUtils; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.aai.AaiClientInterface; +import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.exceptions.NotFoundException; +import org.onap.vid.mso.model.CloudConfiguration; +import org.onap.vid.mso.rest.RequestDetails; +import org.onap.vid.properties.Features; +import org.springframework.beans.factory.annotation.Autowired; +import org.togglz.core.manager.FeatureManager; + +import java.util.List; +import java.util.Map; + +public class CloudOwnerServiceImpl implements CloudOwnerService { + + private static final List CLOUD_CONFIGURATION_PATH = ImmutableList.of("requestDetails", "cloudConfiguration"); + private static final List LCP_CLOUD_REGION_ID_PATH = ImmutableList.of("requestDetails", "cloudConfiguration", "lcpCloudRegionId"); + + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(CloudOwnerService.class); + + private final AaiClientInterface aaiClient; + private final FeatureManager featureManager; + + @Autowired + public CloudOwnerServiceImpl(AaiClientInterface aaiClient, FeatureManager featureManager) { + this.aaiClient = aaiClient; + this.featureManager = featureManager; + } + + @Override + public void enrichRequestWithCloudOwner(RequestDetails msoRequest) { + if (!featureManager.isActive(Features.FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST)) { + return; + } + try { + + //if cloudConfiguration field contains lcpRegion (e.g. in changeManagement scenarios) + if (msoRequest.getCloudConfiguration()!=null && StringUtils.isNotEmpty(msoRequest.getCloudConfiguration().getLcpCloudRegionId())) { + enrichCloudConfigurationWithCloudOwner(msoRequest.getCloudConfiguration(), msoRequest.getCloudConfiguration().getLcpCloudRegionId()); + } + //otherwise the cloudConfiguration is in the additionalProperties field of RequestDetails (e.g. in ng1 view/edit scenario) + else { + enrichRequestWithCloudOwnerByAdditionalProperties(msoRequest); + } + } + catch (Exception e) { + throw new GenericUncheckedException("Failed to enrich requestDetails with cloudOwner", e); + } + } + + protected void enrichRequestWithCloudOwnerByAdditionalProperties(RequestDetails msoRequest) { + String lcpCloudRegionId = null; + try { + lcpCloudRegionId = msoRequest.extractValueByPathUsingAdditionalProperties(LCP_CLOUD_REGION_ID_PATH, String.class); + } + catch (NotFoundException exception) { + LOGGER.debug("Can't find lcp region in RequestDetails. Assume no cloudOwner enrichment is needed. Reason: "+exception.getMessage()); + return; + } + String cloudOwner = aaiClient.getCloudOwnerByCloudRegionId(lcpCloudRegionId); + msoRequest.extractValueByPathUsingAdditionalProperties(CLOUD_CONFIGURATION_PATH, Map.class).put("cloudOwner", cloudOwner); + } + + @Override + public void enrichCloudConfigurationWithCloudOwner(CloudConfiguration cloudConfiguration, String lcpCloudRegionId) { + if (featureManager.isActive(Features.FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST)) { + String cloudOwner = aaiClient.getCloudOwnerByCloudRegionId(lcpCloudRegionId); + cloudConfiguration.setCloudOwner(cloudOwner); + } + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/services/CsvService.java b/vid-app-common/src/main/java/org/onap/vid/services/CsvService.java index 248068fba..6e4a06657 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/CsvService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/CsvService.java @@ -3,7 +3,6 @@ package org.onap.vid.services; import org.json.JSONObject; import org.springframework.web.multipart.MultipartFile; -import java.io.FileNotFoundException; import java.io.IOException; import java.util.List; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/CsvServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/CsvServiceImpl.java index c34bf4e65..6ba152228 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/CsvServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/CsvServiceImpl.java @@ -165,7 +165,7 @@ public class CsvServiceImpl implements CsvService{ * @throws IllegalAccessException * @throws InstantiationException */ - private T putJson(T json, String key, E values) throws IllegalAccessException, InstantiationException { + private T putJson(T json, String key, E values) { if (json instanceof JSONArray){ JSONArray currentJson= ((JSONArray)json); if (values == null) //array of strings (for last item) @@ -176,11 +176,8 @@ public class CsvServiceImpl implements CsvService{ if (keyExistsOrFirstElement(currentJson, key)) { currentJson.put(new JSONObject().put(key, values)); } else { - JSONObject lastItem = lastItemInArray(currentJson); - if(lastItem != null){ - lastItem.put(key, values); - } - + JSONObject lastItem = lastItemInArray(currentJson); + lastItem.put(key, values); } } } 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 500f5ac7f..3ff8db0e5 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 @@ -23,16 +23,11 @@ package org.onap.vid.services; import io.joshworks.restclient.http.HttpResponse; import jline.internal.Log; -import org.onap.vid.aai.AaiClientInterface; -import org.onap.vid.aai.AaiOverTLSClientInterface; -import org.onap.vid.aai.AaiResponse; -import org.onap.vid.aai.ServiceSubscription; -import org.onap.vid.aai.Services; +import org.onap.vid.aai.*; import org.onap.vid.model.ModelConstants; import org.onap.vid.model.Subscriber; import org.onap.vid.model.SubscriberList; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import java.util.HashMap; @@ -46,7 +41,6 @@ public class RoleGenaratorServiceImpl implements RoleGeneratorService { AaiClientInterface client; @Autowired - @Qualifier("aaiClientForCodehausMapping") AaiOverTLSClientInterface aaiOverTLSClient; public static final String DB_NAME = "vid_portal"; @@ -73,8 +67,9 @@ public class RoleGenaratorServiceImpl implements RoleGeneratorService { } private String addAvailableRolesCombination(Boolean firstRun, SubscriberList subscribers) { - String query, availableRoles=""; - HashMap servicesNames = new HashMap(); + String query; + String availableRoles=""; + HashMap servicesNames = new HashMap<>(); for (Subscriber subscriber: subscribers.customer) { AaiResponse subscriberResponse = client.getSubscriberData(subscriber.globalCustomerId); for(ServiceSubscription service: subscriberResponse.getT().serviceSubscriptions.serviceSubscription) { @@ -146,13 +141,12 @@ public class RoleGenaratorServiceImpl implements RoleGeneratorService { } private String insertAvailableRolesToFnRole(){ - String query="INSERT INTO fn_role (ROLE_NAME, ACTIVE_YN, PRIORITY)\r\n" + + return "INSERT INTO fn_role (ROLE_NAME, ACTIVE_YN, PRIORITY)\r\n" + "SELECT RNAME, 'Y', 5\r\n" + "FROM available_roles\r\n" + "WHERE NOT EXISTS (SELECT ROLE_NAME\r\n" + "FROM fn_role \r\n" + "where RNAME = ROLE_NAME);\r\n"; - return query; } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java index 1890a5b37..aedd1b950 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java @@ -52,9 +52,7 @@ public class VidServiceImpl implements VidService { * The Constant LOG. */ private static final EELFLoggerDelegate LOG = EELFLoggerDelegate.getLogger(VidServiceImpl.class); - /** - * The Constant dateFormat. - */ + protected final AsdcClient asdcClient; private final FeatureManager featureManager; @@ -126,7 +124,7 @@ public class VidServiceImpl implements VidService { final Service asdcServiceMetadata = asdcClient.getService(UUID.fromString(uuid)); return getServiceModel(uuid, serviceCsar, tosca, asdcServiceMetadata); } catch (Exception e) { - LOG.error("Failed to download and proccess service from SDC", e); + LOG.error("Failed to download and process service from SDC", e); } return serviceModel; } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/WorkflowService.java b/vid-app-common/src/main/java/org/onap/vid/services/WorkflowService.java index ea139080f..775b6a9d1 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/WorkflowService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/WorkflowService.java @@ -1,6 +1,5 @@ package org.onap.vid.services; -import org.onap.vid.model.Workflow; import java.util.Collection; public interface WorkflowService { -- cgit 1.2.3-korg