From 81043465b2a5332d21ac5b806f785ee69d6f62bf Mon Sep 17 00:00:00 2001 From: Niranjana Date: Thu, 3 Mar 2022 12:45:38 +0000 Subject: Optimize cm-handle registration with CPS-DMI Plugin to upload yang model Issue-ID: CCSDK-3597 Signed-off-by: Niranjana Change-Id: I1d9b0434c72650af164acf9d03a1ed1806668b38 --- sdnr/northbound/addCMHandle/model/pom.xml | 14 +- .../model/src/main/yang/cm-handle-api.yang | 97 +++++++ .../addCMHandle/model/src/main/yang/cm-handle.yang | 109 ++------ sdnr/northbound/addCMHandle/provider/pom.xml | 109 +++----- .../addCMHandle/AddCMHandleProvider.java | 308 +++++++++++++++------ .../sdnr/northbound/addCMHandle/HttpRequester.java | 97 +++++++ .../addCMHandle/models/CpsCmHandleRequestBody.java | 49 ++++ .../OSGI-INF/blueprint/impl-blueprint.xml | 37 --- .../src/main/resources/cm-handle.properties | 14 +- .../org/opendaylight/blueprint/impl-blueprint.xml | 48 ++-- .../addCMHandle/AddCMHandleProviderTest.java | 154 +++++++++-- 11 files changed, 701 insertions(+), 335 deletions(-) create mode 100644 sdnr/northbound/addCMHandle/model/src/main/yang/cm-handle-api.yang create mode 100644 sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/HttpRequester.java create mode 100644 sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/models/CpsCmHandleRequestBody.java delete mode 100644 sdnr/northbound/addCMHandle/provider/src/main/resources/OSGI-INF/blueprint/impl-blueprint.xml (limited to 'sdnr/northbound/addCMHandle') diff --git a/sdnr/northbound/addCMHandle/model/pom.xml b/sdnr/northbound/addCMHandle/model/pom.xml index 0bed82903..ff88c64b7 100644 --- a/sdnr/northbound/addCMHandle/model/pom.xml +++ b/sdnr/northbound/addCMHandle/model/pom.xml @@ -3,7 +3,7 @@ ~ ============LICENSE_START======================================================= ~ ONAP : ccsdk features ~ ================================================================================ - ~ Copyright (C) 2021 Wipro Limited. + ~ Copyright (C) 2021-2022 Wipro Limited. ~ ================================================================================ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. @@ -38,21 +38,13 @@ - org.opendaylight.mdsal.binding.model.ietf - rfc6991 - - - org.opendaylight.mdsal.binding.model.ietf - rfc6991-ietf-inet-types - - org.opendaylight.netconf sal-netconf-connector provided - org.opendaylight.mdsal.binding.model.ietf - rfc6991-ietf-yang-types + org.opendaylight.mdsal + mdsal-binding-dom-codec-api provided diff --git a/sdnr/northbound/addCMHandle/model/src/main/yang/cm-handle-api.yang b/sdnr/northbound/addCMHandle/model/src/main/yang/cm-handle-api.yang new file mode 100644 index 000000000..29014f662 --- /dev/null +++ b/sdnr/northbound/addCMHandle/model/src/main/yang/cm-handle-api.yang @@ -0,0 +1,97 @@ +/* + * Yang model for the CMHandle registration with CPS + * + */ + +module CMHandle-API { + + yang-version "1.1"; + + namespace "org:onap:ccsdk"; + + prefix cmHandle-api; + + description + "Defines the services for cm-handle registration for the mounted devices in SDN-C."; + + revision "2021-06-15" { + description + "YANG Model for CM Handle API"; + } + + /********************************************************************************** + * Data type definitions + * + * The following data type definitions are used to define common data structures, + * define constraints, or to impart special meanings to data objects related to the + * SDN-R controller functions. + **********************************************************************************/ + + typedef action { + type enumeration { + enum "addCMHandle"; + } + description "The action to be taken by SDNR"; + } + + /********************************************************************************** + * All requests will include this standard header + * + * The standard request header is used to define a correlation identification for + * the request that is returned on all responses. This correlation identifier + * (called the service-request-id) is meaningful to the caller and is included on + * all responses from the services. + **********************************************************************************/ + + /********************************************************************************** + * All responses will include this standard header + * + * The standard response header includes the time of completion as well as a + * success|failure indication + **********************************************************************************/ + + + grouping status { + description "The specific response codes are to be aligned with SDC reference doc + (main table removed to avoid duplication and digression from main table). + See SDC and ECOMP Distribution Consumer Interface Agreement"; + container status { + description "The specific response codes are to be aligned with SDC reference doc + (main table removed to avoid duplication and digression from main table). + See SDC and ECOMP Distribution Consumer Interface Agreement"; + leaf code { + description "Response code"; + type uint16; + mandatory true; + } + leaf message { + description "Response message"; + type string; + mandatory true; + } + } + } + + typedef cmHandle-action-status { + type enumeration { + enum "IN_PROGRESS"; + enum "SUCCESSFUL"; + enum "FAILED"; + enum "NOT_FOUND"; + enum "ABORTED"; + enum "MULTIPLE_REQUESTS_FOUND"; + } + description "The status of the cm-handle registration"; + } + + /********************************************************************************** + * Define the addCMHandle service + **********************************************************************************/ + rpc addCMHandle { + description "An operation to register the cm-handle for the mounted devices"; + + output { + uses status; + } + } +} diff --git a/sdnr/northbound/addCMHandle/model/src/main/yang/cm-handle.yang b/sdnr/northbound/addCMHandle/model/src/main/yang/cm-handle.yang index 98e04efd0..451bc9d0b 100644 --- a/sdnr/northbound/addCMHandle/model/src/main/yang/cm-handle.yang +++ b/sdnr/northbound/addCMHandle/model/src/main/yang/cm-handle.yang @@ -1,97 +1,46 @@ -/* - * Yang model for the CMHandle registration with CPS - * - */ +module dmi-registry { -module CMHandle-API { + yang-version 1.1; - yang-version "1.1"; + namespace "org:onap:cps:ncmp"; - namespace "org:onap:ccsdk"; + prefix dmi-reg; - prefix cmHandle-api; + organization "Ericsson Software Tech."; + contact "rahul.tyagi@est.tech"; + + revision "2021-05-20" { description - "Defines the services for cm-handle registration for the mounted devices in SDN-C."; + "Initial Version"; + } - revision "2021-06-15" { - description - "YANG Model for CM Handle API"; - } + container dmi-registry { - /********************************************************************************** - * Data type definitions - * - * The following data type definitions are used to define common data structures, - * define constraints, or to impart special meanings to data objects related to the - * SDN-R controller functions. - **********************************************************************************/ + list cm-handle { - typedef action { - type enumeration { - enum "addCMHandle"; - } - description "The action to be taken by SDNR"; - } + key "id"; - /********************************************************************************** - * All requests will include this standard header - * - * The standard request header is used to define a correlation identification for - * the request that is returned on all responses. This correlation identifier - * (called the service-request-id) is meaningful to the caller and is included on - * all responses from the services. - **********************************************************************************/ + leaf id { + type string; + } - /********************************************************************************** - * All responses will include this standard header - * - * The standard response header includes the time of completion as well as a - * success|failure indication - **********************************************************************************/ + leaf dmi-service-name { + type string; + } + list additional-properties { - grouping status { - description "The specific response codes are to be aligned with SDC reference doc - (main table removed to avoid duplication and digression from main table). - See SDC and ECOMP Distribution Consumer Interface Agreement"; - container status { - description "The specific response codes are to be aligned with SDC reference doc - (main table removed to avoid duplication and digression from main table). - See SDC and ECOMP Distribution Consumer Interface Agreement"; - leaf code { - description "Response code"; - type uint16; - mandatory true; - } - leaf message { - description "Response message"; - type string; - mandatory true; - } - } - } + key "name"; - typedef cmHandle-action-status { - type enumeration { - enum "IN_PROGRESS"; - enum "SUCCESSFUL"; - enum "FAILED"; - enum "NOT_FOUND"; - enum "ABORTED"; - enum "MULTIPLE_REQUESTS_FOUND"; - } - description "The status of the cm-handle registration"; - } + leaf name { + type string; + } - /********************************************************************************** - * Define the addCMHandle service - **********************************************************************************/ - rpc addCMHandle { - description "An operation to register the cm-handle for the mounted devices"; - - output { - uses status; + leaf value { + type string; } - } + } + } + } } diff --git a/sdnr/northbound/addCMHandle/provider/pom.xml b/sdnr/northbound/addCMHandle/provider/pom.xml index 44044d575..d4542c06a 100644 --- a/sdnr/northbound/addCMHandle/provider/pom.xml +++ b/sdnr/northbound/addCMHandle/provider/pom.xml @@ -3,7 +3,7 @@ ~ ============LICENSE_START======================================================= ~ ONAP : ccsdk features ~ ================================================================================ - ~ Copyright (C) 2021 Wipro Limited. + ~ Copyright (C) 2021-2022 Wipro Limited. ~ ================================================================================ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. @@ -41,86 +41,47 @@ org.onap.ccsdk.features.sdnr.northbound addCMHandle-model ${project.version} + + + org.osgi + org.osgi.core + provided + org.opendaylight.mdsal - mdsal-binding-api + mdsal-binding-dom-codec-api + provided org.opendaylight.mdsal - mdsal-dom-api - - - org.opendaylight.yangtools - yang-data-impl - - - junit - junit - test - - - org.testng - testng - test - - - org.mockito - mockito-core - test - - - org.apache.derby - derby - test + mdsal-binding-dom-adapter + provided - org.onap.ccsdk.sli.core - sli-common - ${ccsdk.sli.version} + org.opendaylight.mdsal + mdsal-binding-generator-impl provided - org.onap.ccsdk.sli.core - sli-provider - ${ccsdk.sli.version} + org.opendaylight.mdsal + mdsal-binding-runtime-spi provided - org.onap.ccsdk.sli.core - utils-provider - ${ccsdk.sli.version} + org.opendaylight.mdsal + mdsal-dom-api + provided - org.osgi - org.osgi.core - test + org.opendaylight.mdsal + mdsal-singleton-common-api + provided - org.onap.ccsdk.sli.core - sli-provider-base - ${ccsdk.sli.version} - provided - - - org.onap.ccsdk.features.sdnr.wt - sdnr-wt-netconfnode-state-service-model - 1.2.0 - - - javax - javaee-web-api - 6.0 + org.opendaylight.netconf + netconf-dom-api provided - - - com.sun.jersey - jersey-bundle - 1.19.4 - - - org.opendaylight.mdsal.model - ietf-topology org.opendaylight.netconf @@ -128,20 +89,30 @@ provided - org.opendaylight.mdsal.binding.model.ietf - rfc6991-ietf-yang-types + com.fasterxml.jackson.core + jackson-core provided - org.opendaylight.mdsal - yang-binding + com.fasterxml.jackson.core + jackson-annotations provided - org.opendaylight.mdsal - mdsal-singleton-common-api + com.fasterxml.jackson.core + jackson-databind provided + + org.mockito + mockito-inline + test + + + org.onap.ccsdk.sli.core + sli-common + ${ccsdk.sli.version} + @@ -170,7 +141,7 @@ - + diff --git a/sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/AddCMHandleProvider.java b/sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/AddCMHandleProvider.java index 0d9cc8f3f..ce9378e0b 100644 --- a/sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/AddCMHandleProvider.java +++ b/sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/AddCMHandleProvider.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP : CCSDK * ================================================================================ - * Copyright (C) 2021 Wipro Limited. + * Copyright (C) 2021-2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,48 +20,47 @@ package org.onap.ccsdk.features.sdnr.northbound.addCMHandle; -import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION; - -import com.google.common.base.Preconditions; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.util.concurrent.ListenableFuture; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; +import java.sql.Timestamp; +import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.Properties; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import javax.ws.rs.HttpMethod; -import javax.ws.rs.core.MediaType; import org.eclipse.jdt.annotation.NonNull; -import org.json.JSONObject; -import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfAccessor; -import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeStateListener; -import org.onap.ccsdk.sli.core.sli.provider.MdsalHelper; +import org.onap.ccsdk.features.sdnr.northbound.addCMHandle.HttpRequester; +import org.onap.ccsdk.features.sdnr.northbound.addCMHandle.models.CpsCmHandleRequestBody; +import org.onap.ccsdk.sli.core.utils.common.EnvProperties; import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.binding.api.DataObjectModification; +import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType; import org.opendaylight.mdsal.binding.api.DataTreeChangeListener; import org.opendaylight.mdsal.binding.api.DataTreeIdentifier; import org.opendaylight.mdsal.binding.api.DataTreeModification; +import org.opendaylight.mdsal.binding.api.MountPointService; import org.opendaylight.mdsal.binding.api.NotificationPublishService; import org.opendaylight.mdsal.binding.api.RpcProviderService; -import org.opendaylight.mdsal.dom.api.DOMDataBroker; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.dom.api.DOMMountPointService; +import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev210615.AddCMHandleInput; import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev210615.AddCMHandleOutput; +import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev210615.AddCMHandleOutputBuilder; import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev210615.CMHandleAPIService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode; +import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev210615.status.StatusBuilder; +import org.opendaylight.yang.gen.v1.org.onap.cps.ncmp.rev210520.DmiRegistryBuilder; +import org.opendaylight.yang.gen.v1.org.onap.cps.ncmp.rev210520.dmi.registry.CmHandle; +import org.opendaylight.yang.gen.v1.org.onap.cps.ncmp.rev210520.dmi.registry.CmHandleBuilder; +import org.opendaylight.yang.gen.v1.org.onap.cps.ncmp.rev210520.dmi.registry.CmHandleKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; @@ -69,72 +68,98 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.concepts.ObjectRegistration; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class AddCMHandleProvider implements CMHandleAPIService, NetconfNodeStateListener, AutoCloseable { +public class AddCMHandleProvider implements CMHandleAPIService, AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(AddCMHandleProvider.class); + private final ObjectMapper objMapper = new ObjectMapper(); private final String APPLICATION_NAME = "addCMHandle"; private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR"; private static final String PROPERTIES_FILE_NAME = "cm-handle.properties"; - private static final String PARSING_ERROR = - "Could not create the request message to send to the server; no message will be sent"; - private final ExecutorService executor; - protected DataBroker dataBroker; - protected DOMDataBroker domDataBroker; - protected NotificationPublishService notificationService; - protected RpcProviderService rpcProviderRegistry; - private ObjectRegistration rpcRegistration; - public static final InstanceIdentifier NETCONF_TOPO_IID = InstanceIdentifier.create(NetworkTopology.class) - .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))); private static HashMap config; + private ListenerRegistration listener; + private static final @NonNull InstanceIdentifier NETCONF_NODE_TOPO_IID = + InstanceIdentifier.create(NetworkTopology.class) + .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))) + .child(Node.class); + private static final @NonNull DataTreeIdentifier NETCONF_NODE_TOPO_TREE_ID = + DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, NETCONF_NODE_TOPO_IID); + + private DataBroker dataBroker; + private MountPointService mountPointService; + private DOMMountPointService domMountPointService; + private RpcProviderService rpcProviderRegistry; + @SuppressWarnings("unused") + private NotificationPublishService notificationPublishService; + @SuppressWarnings("unused") + private ClusterSingletonServiceProvider clusterSingletonServiceProvider; + private YangParserFactory yangParserFactory; + private BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer; + private Boolean isInitializationSuccessful = false; + private Long lastNotificationSentOn = Long.valueOf(0); + private List nodeIdList = new ArrayList<>(); public AddCMHandleProvider() { LOG.info("Creating provider for {}", APPLICATION_NAME); - executor = Executors.newFixedThreadPool(1); this.dataBroker = null; - this.domDataBroker = null; - this.notificationService = null; + this.mountPointService = null; + this.domMountPointService = null; this.rpcProviderRegistry = null; - this.rpcRegistration = null; + this.notificationPublishService = null; + this.clusterSingletonServiceProvider = null; + this.yangParserFactory = null; + this.bindingNormalizedNodeSerializer = null; + } public void setDataBroker(DataBroker dataBroker) { this.dataBroker = dataBroker; } - public void setDomDataBroker(DOMDataBroker domDataBroker) { - this.domDataBroker = domDataBroker; - } - public void setRpcProviderRegistry(RpcProviderService rpcProviderRegistry) { this.rpcProviderRegistry = rpcProviderRegistry; } public void setNotificationPublishService(NotificationPublishService notificationPublishService) { - this.notificationService = notificationPublishService; + this.notificationPublishService = notificationPublishService; + } + + public void setMountPointService(MountPointService mountPointService) { + this.mountPointService = mountPointService; + } + + public void setDomMountPointService(DOMMountPointService domMountPointService) { + this.domMountPointService = domMountPointService; + } + + public void setClusterSingletonService(ClusterSingletonServiceProvider clusterSingletonService) { + this.clusterSingletonServiceProvider = clusterSingletonService; + } + + public void setYangParserFactory(YangParserFactory yangParserFactory) { + this.yangParserFactory = yangParserFactory; + } + + public void setBindingNormalizedNodeSerializer(BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer) { + this.bindingNormalizedNodeSerializer = bindingNormalizedNodeSerializer; + LOG.info("Init bindingNormalizedNodeSerializer"); + } + + public Boolean isInitializationSuccessful() { + return isInitializationSuccessful; } public void init() { LOG.info("Initializing {} for {}", this.getClass().getName(), APPLICATION_NAME); - if (rpcRegistration == null) { - if (rpcProviderRegistry != null) { - rpcRegistration = rpcProviderRegistry.registerRpcImplementation(CMHandleAPIService.class, this); - LOG.info("Initialization complete for {}", APPLICATION_NAME); - } else { - LOG.warn("Error initializing {} : rpcRegistry unset", APPLICATION_NAME); - } - } - String propDir = System.getenv(SDNC_CONFIG_DIR); if (propDir == null) { LOG.error("Environment variable SDNC_CONFIG_DIR is not set"); @@ -143,76 +168,175 @@ public class AddCMHandleProvider implements CMHandleAPIService, NetconfNodeState propDir = propDir + "/"; } - // GET configuration from properties file config = new HashMap(); try (FileInputStream fileInput = new FileInputStream(propDir + PROPERTIES_FILE_NAME)) { - Properties properties = new Properties(); + EnvProperties properties = new EnvProperties(); properties.load(fileInput); - for (String param : new String[] {"url", "user", "password", - "authentication, dmi-service-name"}) { + for (String param : new String[] {"cpsUrl", "user", "password", "dmaapUrl", "dmiServiceName", "client", + "timerThreshold"}) { config.put(param, properties.getProperty(param)); } } catch (IOException e) { LOG.error("Error while reading properties file: ", e); } + listener = dataBroker.registerDataTreeChangeListener(NETCONF_NODE_TOPO_TREE_ID, new AddCmHandleListener()); + isInitializationSuccessful = true; + LOG.info("Initialization complete for {}", APPLICATION_NAME); LOG.info("addCMHandle Session Initiated"); } - @Override - public void onCreated(NodeId nNodeId, NetconfNode netconfNode) { - LOG.info("NetConf device connected {}", nNodeId.getValue()); - JSONObject obj = new JSONObject(); - obj.put("cm-handle-id", nNodeId.getValue()); - obj.put("dmi-service-name", config.get("dmi-service-name")); - ClientConfig dmaapClientConfig = new DefaultClientConfig(); - dmaapClientConfig.getProperties().put(ClientConfig.PROPERTY_READ_TIMEOUT, 180000); - dmaapClientConfig.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, 60000); - Client dmaapClient = Client.create(dmaapClientConfig); - String authenticationMethod = config.get("authentication"); - ClientResponse response = null; - try { - if ("basic".equals(authenticationMethod)) { - LOG.debug("Sending message to dmaap-message-router: {}", obj.toString()); - dmaapClient.addFilter(new HTTPBasicAuthFilter(config.get("user"), config.get("password"))); - - response = dmaapClient.resource(config.get("url")).type(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON).post(ClientResponse.class, obj); - } else { - response = dmaapClient.resource(config.get("url")).type(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON).post(ClientResponse.class, obj); + /** + * AddCmHandleListener + */ + private class AddCmHandleListener implements DataTreeChangeListener { + + @Override + public void onDataTreeChanged(@NonNull Collection> changes) { + LOG.info("AddCmHandleListener TreeChange enter changes: {}", changes.size()); + LOG.info("config: " + config); + String nodeId = getNodeId(changes); + if (Objects.nonNull(nodeId) && !(nodeIdList.contains(nodeId))) { + nodeIdList.add(nodeId); + } + Timestamp currentTime = new Timestamp(System.currentTimeMillis()); + Long difference = currentTime.getTime() - lastNotificationSentOn; + if (difference > Long.valueOf(config.get("timerThreshold"))) { + sendNotification(nodeIdList); + nodeIdList.clear(); + } + + } + } + + /** + * Method to get nodeId. + */ + private String getNodeId(@NonNull Collection> changes) { + String nodeIdString = null; + for (final DataTreeModification change : changes) { + + final DataObjectModification root = change.getRootNode(); + try { + ModificationType modificationTyp = root.getModificationType(); + if ((modificationTyp != ModificationType.DELETE)) { + + Node node = root.getDataAfter(); + NodeId nodeId = node != null ? node.getNodeId() : null; + if (nodeId == null) { + LOG.info("without nodeid"); + } else { + nodeIdString = nodeId.getValue(); + LOG.info("AddCmHandle for nodeId: {}", nodeIdString); + } + } + + } catch (NullPointerException | IllegalStateException e) { + LOG.info("Data not available at ", e); } - LOG.info("Received response from dmaap-message-router: \n {}", response.toString()); - } catch (Exception e) { - LOG.error("Error while posting message to CM_HANDLE topic: ", e); } + return nodeIdString; } - @Override - public void onRemoved(NodeId nNodeId) { + /** + * Method called when cm-handle notification is to be sent. + */ + protected void sendNotification(List nodeIdList) { + + String sendNotificationTo = config.get("client"); + lastNotificationSentOn = new Timestamp(System.currentTimeMillis()).getTime(); + if (sendNotificationTo.equalsIgnoreCase("CPS")) { + sendNotificationToCps(nodeIdList); + + } + if (sendNotificationTo.equalsIgnoreCase("DMAAP")) { + sendNotificationToDmaap(nodeIdList); + } + + else { + sendNotificationToCps(nodeIdList); + sendNotificationToDmaap(nodeIdList); + } + lastNotificationSentOn = new Timestamp(System.currentTimeMillis()).getTime(); - LOG.info("NetConf device removed - nNodeId = {}", nNodeId); } - @Override - public void onStateChange(NodeId nNodeId, NetconfNode netconfNode) { - LOG.info("NetConf device state changed nNodeId = {}}", nNodeId); + /** + * Method called when cm-handle notification is to be sent to CPS. + */ + protected String sendNotificationToCps(List nodeIdList) { + + LOG.info("Sending Notification to CPS"); + String userCredential = config.get("user") + ":" + config.get("password"); + String url = config.get("cpsUrl"); + String requestBody = null; + CpsCmHandleRequestBody cpsCmHandleRequestBody = new CpsCmHandleRequestBody(nodeIdList); + LOG.info("url {}", url); + LOG.info("userCredential: {}", userCredential); + try { + requestBody = objMapper.writeValueAsString(cpsCmHandleRequestBody); + LOG.info("requestBody{} ", requestBody); + } catch (JsonProcessingException e) { + LOG.error("ERROR: {}", e); + } + String response = HttpRequester.sendPostRequest(url, userCredential, requestBody); + LOG.info("response from CPS: {} ", response); + return response; + + } + + /** + * Method called when cm-handle notification is to be sent to Dmaap. + */ + protected String sendNotificationToDmaap(List nodeIdList) { + + LOG.info("Sending Notification to Dmaap"); + String url = config.get("dmaapUrl"); + Map values = new HashMap<>(); + nodeIdList.forEach(nodeId -> { + CmHandleBuilder cmHandleBuilder = new CmHandleBuilder(); + cmHandleBuilder.setDmiServiceName(config.get("dmiServiceName")); + cmHandleBuilder.setId(nodeId); + CmHandleKey cmHandleKey = new CmHandleKey(nodeId); + values.put(cmHandleKey, cmHandleBuilder.build()); + }); + DmiRegistryBuilder dmiRegistryBuilder = new DmiRegistryBuilder(); + dmiRegistryBuilder.setCmHandle(values); + + String requestBody = null; + LOG.info("url: {}", url); + try { + requestBody = objMapper.writeValueAsString(dmiRegistryBuilder.build()); + LOG.info("requestBody: {}", requestBody); + } catch (JsonProcessingException e) { + LOG.error("ERROR: {}", e); + } + String response = HttpRequester.sendPostRequest(url, null, requestBody); + LOG.info("response from Dmaap: {}", response); + return response; + } /** * Method called when the blueprint container is destroyed. */ + @Override public void close() { - rpcRegistration.close(); + if (Objects.nonNull(listener)) { + listener.close(); + } LOG.debug("AddCMHandleProvider Closed"); } @Override public ListenableFuture> addCMHandle(AddCMHandleInput input) { + StatusBuilder statusBuilder = new StatusBuilder(); + statusBuilder.setMessage("SUCCESS"); + return RpcResultBuilder.success(new AddCMHandleOutputBuilder().setStatus(statusBuilder.build()).build()) + .buildFuture(); - return null; } } diff --git a/sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/HttpRequester.java b/sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/HttpRequester.java new file mode 100644 index 000000000..5f6c68d0d --- /dev/null +++ b/sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/HttpRequester.java @@ -0,0 +1,97 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ================================================================================ + * 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.ccsdk.features.sdnr.northbound.addCMHandle; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Base64; +import java.util.Objects; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HttpRequester { + + private static final String ACCEPT = "Accept"; + private static final String JSON = "application/json"; + private static final String CONTENT = "Content-Type"; + private static final String UTF = "UTF-8"; + private static final String FAILMSG = "Post failed"; + + private static final Logger LOG = LoggerFactory.getLogger(HttpRequester.class); + + /** + * Send Post Request. + */ + public static String sendPostRequest(String requestUrl, String userCredentials, String requestBody) { + String response = ""; + HttpURLConnection connection = null; + BufferedReader br = null; + try { + URL url = new URL(requestUrl); + connection = (HttpURLConnection) url.openConnection(); + connection.setDoOutput(true); + connection.setDoInput(true); + connection.setRequestMethod("POST"); + connection.setRequestProperty(ACCEPT, JSON); + connection.setRequestProperty(CONTENT, JSON); + if (Objects.nonNull(userCredentials)) { + String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userCredentials.getBytes())); + connection.setRequestProperty("Authorization", basicAuth); + } + OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), UTF); + writer.write(requestBody); + writer.close(); + br = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String temp; + int responseCode = connection.getResponseCode(); + LOG.info("response code: {}", responseCode); + response = br.readLine(); + while ((temp = br.readLine()) != null) { + response = response.concat(temp); + } + + if (response == null) { + response = String.valueOf(responseCode); + } + + } catch (Exception e) { + LOG.error("Exc in post {}", e.toString()); + response = FAILMSG; + } finally { + try { + if (br != null) + br.close(); + if (connection != null) + connection.disconnect(); + } catch (Exception exToIgnore) { + LOG.debug("Exc in finally block {}", exToIgnore.toString()); + } + } + + return response; + } + +} diff --git a/sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/models/CpsCmHandleRequestBody.java b/sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/models/CpsCmHandleRequestBody.java new file mode 100644 index 000000000..8bcfaa527 --- /dev/null +++ b/sdnr/northbound/addCMHandle/provider/src/main/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/models/CpsCmHandleRequestBody.java @@ -0,0 +1,49 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ================================================================================ + * 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.ccsdk.features.sdnr.northbound.addCMHandle.models; + +import java.util.List; + +/** + * RequestBody for cm-handle registration with CPS-DMI. + */ +public class CpsCmHandleRequestBody { + + private List cmHandles; + + public CpsCmHandleRequestBody() { + + } + + public CpsCmHandleRequestBody(List cmHandles) { + super(); + this.cmHandles = cmHandles; + } + + public List getCmHandles() { + return cmHandles; + } + + public void setCmHandles(List cmHandles) { + this.cmHandles = cmHandles; + } + +} diff --git a/sdnr/northbound/addCMHandle/provider/src/main/resources/OSGI-INF/blueprint/impl-blueprint.xml b/sdnr/northbound/addCMHandle/provider/src/main/resources/OSGI-INF/blueprint/impl-blueprint.xml deleted file mode 100644 index 8e543d458..000000000 --- a/sdnr/northbound/addCMHandle/provider/src/main/resources/OSGI-INF/blueprint/impl-blueprint.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - diff --git a/sdnr/northbound/addCMHandle/provider/src/main/resources/cm-handle.properties b/sdnr/northbound/addCMHandle/provider/src/main/resources/cm-handle.properties index f027f5939..57742cc7e 100644 --- a/sdnr/northbound/addCMHandle/provider/src/main/resources/cm-handle.properties +++ b/sdnr/northbound/addCMHandle/provider/src/main/resources/cm-handle.properties @@ -2,7 +2,7 @@ # ============LICENSE_START======================================================= # ONAP : ccsdk features # ================================================================================ -# Copyright (C) 2021 Wipro Limited. +# Copyright (C) 2021-2022 Wipro Limited. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,8 +20,10 @@ # -url = https://dmaap-message-router/events/CM_HANDLE -user = user -password = password -authentication = basic -dmi-service-name = dmi-service-name +cpsUrl = http://cps:8783/dmi/v1/inventory/cmHandles +user = ${CPS_USER:-cpsuser} +password = ${CPS_PASSWORD:-cpspassword} +dmaapUrl = http://message-router:3094/events/CM-HANDLE +client = CPS +dmiServiceName = dmi-service-name +timerThreshold = 60000 diff --git a/sdnr/northbound/addCMHandle/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml b/sdnr/northbound/addCMHandle/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml index 9cc6c39ca..149be7d16 100644 --- a/sdnr/northbound/addCMHandle/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml +++ b/sdnr/northbound/addCMHandle/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml @@ -3,7 +3,7 @@ ~ ============LICENSE_START======================================================= ~ ONAP : ccsdk features ~ ================================================================================ - ~ Copyright (C) 2021 Wipro Limited. + ~ Copyright (C) 2021-2022 Wipro Limited. ~ ================================================================================ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. @@ -23,34 +23,38 @@ - + - - - - - + - + - + + interface="org.opendaylight.mdsal.binding.api.RpcProviderService"/> + + - - - + + + + + + - - - - + + + + + + diff --git a/sdnr/northbound/addCMHandle/provider/src/test/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/AddCMHandleProviderTest.java b/sdnr/northbound/addCMHandle/provider/src/test/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/AddCMHandleProviderTest.java index 0dfe88c1f..f1edd4fae 100644 --- a/sdnr/northbound/addCMHandle/provider/src/test/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/AddCMHandleProviderTest.java +++ b/sdnr/northbound/addCMHandle/provider/src/test/java/org/onap/ccsdk/features/sdnr/northbound/addCMHandle/AddCMHandleProviderTest.java @@ -1,33 +1,151 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2021-2022 Wipro Limited. + * ================================================================================ + * 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.ccsdk.features.sdnr.northbound.addCMHandle; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; -import com.sun.jersey.api.client.WebResource; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; -import java.util.concurrent.Future; - -import org.junit.After; -import org.junit.Before; +import org.eclipse.jdt.annotation.NonNull; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener; import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.DataTreeChangeListener; +import org.opendaylight.mdsal.binding.api.MountPointService; +import org.opendaylight.mdsal.binding.api.NotificationPublishService; import org.opendaylight.mdsal.binding.api.RpcProviderService; -import org.opendaylight.yangtools.yang.common.RpcResult; -import org.onap.ccsdk.features.sdnr.northbound.addCMHandle.AddCMHandleProvider; -public class AddCMHandleProviderTest { +import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer; +import org.opendaylight.mdsal.dom.api.DOMMountPointService; +import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AddCMHandleProviderTest extends Mockito { + + private static AddCMHandleProvider addCMHandleProvider; + private static DataBroker dataBrokerNetconf; + private @NonNull static DataTreeChangeListener listener; + private @NonNull static ClusteredDataTreeChangeListener listenerClustered; + + private static final Logger LOG = LoggerFactory.getLogger(AddCMHandleProviderTest.class); + private static List nodeIdList = new ArrayList<>(); + + @SuppressWarnings("unchecked") + @BeforeClass + public static > void before() + throws InterruptedException, IOException { + + LOG.info("Logger: " + LOG.getClass().getName() + " " + LOG.getName()); + dataBrokerNetconf = mock(DataBroker.class); + when(dataBrokerNetconf.registerDataTreeChangeListener(Mockito.any(), Mockito.any())).thenAnswer(invocation -> { + Object pListener = invocation.getArguments()[1]; + LOG.info("Register " + pListener.getClass().getName()); + if (pListener instanceof ClusteredDataTreeChangeListener) { + System.out.println("Clustered listener"); + listenerClustered = (ClusteredDataTreeChangeListener) pListener; + } else if (pListener instanceof DataTreeChangeListener) { + System.out.println("Listener"); + listener = (DataTreeChangeListener) pListener; + } + return new ListenerRegistration() { + @Override + public L getInstance() { + return (L) pListener; + } - private AddCMHandleProvider esProvider; + @Override + public void close() { + } + }; - @Before - public void setUp() throws Exception { - DataBroker dataBroker = mock(DataBroker.class); - RpcProviderService rpcRegistry = mock(RpcProviderService.class); - esProvider = new AddCMHandleProvider(); + }); + + addCMHandleProvider = new AddCMHandleProvider(); + MountPointService mountPointService = mock(MountPointService.class); + DOMMountPointService domMountPointService = mock(DOMMountPointService.class); + RpcProviderService rpcProviderRegistry = mock(RpcProviderService.class); + NotificationPublishService notificationPublishService = mock(NotificationPublishService.class); + ClusterSingletonServiceProvider clusterSingletonServiceProvider = mock(ClusterSingletonServiceProvider.class); + YangParserFactory yangParserFactory = mock(YangParserFactory.class); + BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer = mock(BindingNormalizedNodeSerializer.class); + addCMHandleProvider.setDataBroker(dataBrokerNetconf); + addCMHandleProvider.setMountPointService(mountPointService); + addCMHandleProvider.setDomMountPointService(domMountPointService); + addCMHandleProvider.setNotificationPublishService(notificationPublishService); + addCMHandleProvider.setRpcProviderRegistry(rpcProviderRegistry); + addCMHandleProvider.setClusterSingletonService(clusterSingletonServiceProvider); + addCMHandleProvider.setYangParserFactory(yangParserFactory); + addCMHandleProvider.setBindingNormalizedNodeSerializer(bindingNormalizedNodeSerializer); + addCMHandleProvider.init(); + nodeIdList.add("ncserver1"); + LOG.info("Initialization done"); } - @After - public void tearDown() throws Exception { + @Test + public void initializationTest() { + + LOG.info("Verify init state"); + assertTrue("Devicemanager not initialized", addCMHandleProvider.isInitializationSuccessful()); + } + + @Test + public void sendNotificationToCpsTest() { + + LOG.info("Send notification to Cps test"); + try (MockedStatic utilities = Mockito.mockStatic(HttpRequester.class)) { + utilities.when(() -> HttpRequester.sendPostRequest(any(), any(), any())).thenReturn("Success"); + + assertEquals(addCMHandleProvider.sendNotificationToCps(nodeIdList), "Success"); + } + + } + + @Test + public void sendNotificationToDmaapTest() { + + LOG.info("Send notification to Cps test"); + try (MockedStatic utilities = Mockito.mockStatic(HttpRequester.class)) { + utilities.when(() -> HttpRequester.sendPostRequest(any(), any(), any())).thenReturn("Success"); + + assertEquals(addCMHandleProvider.sendNotificationToCps(nodeIdList), "Success"); + } + + } + + @AfterClass + public static void after() throws InterruptedException, IOException { + LOG.info("Start shutdown"); + addCMHandleProvider.close(); + } } -- cgit 1.2.3-korg