aboutsummaryrefslogtreecommitdiffstats
path: root/sdnr/wt/netconfnode-state-service/provider/src/main/java
diff options
context:
space:
mode:
authorherbert <herbert.eiselt@highstreet-technologies.com>2020-01-30 10:39:37 +0100
committerherbert <herbert.eiselt@highstreet-technologies.com>2020-02-01 13:30:27 +0100
commitcbbc3520048bbc539b137cac011776506b3e0f70 (patch)
tree8b72e076b091001e88286a59e5b79479a9194560 /sdnr/wt/netconfnode-state-service/provider/src/main/java
parent84cf604e3f06942a62ae0478327ec6100787761e (diff)
SDN-R add updated app
add updated netconfnode-state-service Issue-ID: SDNC-1033 Signed-off-by: herbert <herbert.eiselt@highstreet-technologies.com> Change-Id: If1639bb61dc58e90b769c0dd100d49eeddf83fc9 Signed-off-by: herbert <herbert.eiselt@highstreet-technologies.com>
Diffstat (limited to 'sdnr/wt/netconfnode-state-service/provider/src/main/java')
-rw-r--r--sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/GenericTransactionUtils.java139
-rw-r--r--sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfAccessorImpl.java164
-rw-r--r--sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfNodeStateServiceImpl.java625
-rw-r--r--sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/AkkaConfig.java86
-rw-r--r--sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterConfig.java141
-rw-r--r--sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterNodeInfo.java81
-rw-r--r--sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfo.java91
-rw-r--r--sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfoCollection.java45
-rw-r--r--sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/GeoConfig.java162
-rw-r--r--sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/NetconfnodeStateServiceRpcApiImpl.java126
-rw-r--r--sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/RpcApigetStateCallback.java27
11 files changed, 1687 insertions, 0 deletions
diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/GenericTransactionUtils.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/GenericTransactionUtils.java
new file mode 100644
index 000000000..93f230a23
--- /dev/null
+++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/GenericTransactionUtils.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. 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.ccsdk.features.sdnr.wt.netconfnodestateservice.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FluentFuture;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.onap.ccsdk.features.sdnr.wt.common.util.StackTrace;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.TransactionUtils;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.ReadTransaction;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class GenericTransactionUtils implements TransactionUtils {
+ static final Logger LOG = LoggerFactory.getLogger(GenericTransactionUtils.class);
+
+ /**
+ * Deliver the data back or null. Warning
+ *
+ * @param <T> SubType of the DataObject to be handled
+ * @param dataBroker for accessing data
+ * @param dataStoreType to address datastore
+ * @param iid id to access data
+ * @return null or object
+ */
+ @Override
+ @Nullable
+ public <T extends DataObject> T readData(DataBroker dataBroker, LogicalDatastoreType dataStoreType,
+ InstanceIdentifier<T> iid) {
+
+ AtomicBoolean noErrorIndication = new AtomicBoolean();
+ AtomicReference<String> statusText = new AtomicReference<>();
+
+ @Nullable T obj = readDataOptionalWithStatus(dataBroker, dataStoreType, iid, noErrorIndication, statusText);
+
+ if (!noErrorIndication.get()) {
+ LOG.warn("Read transaction for identifier " + iid + " failed with status " + statusText.get());
+ }
+
+ return obj;
+ }
+
+ /**
+ * Deliver the data back or null
+ *
+ * @param <T> SubType of the DataObject to be handled
+ * @param dataBroker for accessing data
+ * @param dataStoreType to address datastore
+ * @param iid id to access data
+ * @param noErrorIndication (Output) true if data could be read and are available and is not null
+ * @param statusIndicator (Output) String with status indications during the read.
+ * @return null or object
+ */
+ @Override
+ @SuppressWarnings("null")
+ public @Nullable <T extends DataObject> T readDataOptionalWithStatus(DataBroker dataBroker,
+ LogicalDatastoreType dataStoreType, InstanceIdentifier<T> iid, AtomicBoolean noErrorIndication,
+ AtomicReference<String> statusIndicator) {
+
+ @Nullable T data = null;
+ noErrorIndication.set(false);
+
+ statusIndicator.set("Preconditions");
+ Preconditions.checkNotNull(dataBroker);
+
+ int retry = 0;
+ int retryDelayMilliseconds = 2000;
+ int maxRetries = 5; // 0 no Retry
+
+ do {
+ if (retry > 0) {
+ try {
+ LOG.debug("Sleep {}ms", retryDelayMilliseconds);
+ Thread.sleep(retryDelayMilliseconds);
+ } catch (InterruptedException e) {
+ LOG.debug("Sleep interrupted", e);
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ LOG.debug("Sending message with retry {} ", retry);
+ statusIndicator.set("Create Read Transaction");
+
+ try (ReadTransaction readTransaction = dataBroker.newReadOnlyTransaction();) {
+ @NonNull FluentFuture<Optional<T>> od = readTransaction.read(dataStoreType, iid);
+ statusIndicator.set("Read done");
+ if (od != null) {
+ statusIndicator.set("Unwrap checkFuture done");
+ Optional<T> optionalData = od.get();
+ if (optionalData != null) {
+ statusIndicator.set("Unwrap optional done");
+ data = optionalData.orElse(null);
+ statusIndicator.set("Read transaction done");
+ noErrorIndication.set(true);
+ }
+ }
+
+ readTransaction.close();
+ } catch (CancellationException | ExecutionException | InterruptedException | NoSuchElementException e) {
+ statusIndicator.set(StackTrace.toString(e));
+ if (e instanceof InterruptedException) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ } while (noErrorIndication.get() == false && retry++ < maxRetries);
+
+ return data;
+ }
+
+
+}
diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfAccessorImpl.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfAccessorImpl.java
new file mode 100644
index 000000000..654b9d7d9
--- /dev/null
+++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfAccessorImpl.java
@@ -0,0 +1,164 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. 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.ccsdk.features.sdnr.wt.netconfnodestateservice.impl;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import org.eclipse.jdt.annotation.NonNull;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.Capabilities;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfAccessor;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.TransactionUtils;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.MountPoint;
+import org.opendaylight.mdsal.binding.api.NotificationService;
+import org.opendaylight.mdsal.binding.api.RpcConsumerRegistry;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionInput;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionOutput;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.NotificationsService;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.StreamNameType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetconfAccessorImpl implements NetconfAccessor {
+
+ private static final Logger log = LoggerFactory.getLogger(NetconfAccessorImpl.class);
+
+ private final NodeId nodeId;
+ private final DataBroker dataBroker;
+ private final TransactionUtils transactionUtils;
+ private final MountPoint mountpoint;
+ private final NetconfNode netconfNode;
+ private final Capabilities capabilities;
+
+ /**
+ * Contains all data to access and manage netconf device
+ * @param nodeId of managed netconf node
+ * @param netconfNode information
+ * @param dataBroker to access node
+ * @param mountpoint of netconfNode
+ * @param transactionUtils with read an write functions
+ */
+ public NetconfAccessorImpl(NodeId nodeId, NetconfNode netconfNode, DataBroker dataBroker, MountPoint mountpoint,
+ TransactionUtils transactionUtils) {
+ super();
+ this.nodeId = nodeId;
+ this.netconfNode = netconfNode;
+ this.dataBroker = dataBroker;
+ this.mountpoint = mountpoint;
+ this.transactionUtils = transactionUtils;
+
+ ConnectionStatus csts = netconfNode != null ? netconfNode.getConnectionStatus() : null;
+ this.capabilities = Capabilities.getAvailableCapabilities(csts != null ? netconfNode : null);
+ }
+
+ /**
+ * @param nodeId with uuid of managed netconf node
+ * @param dataBroker to access node
+ */
+ public NetconfAccessorImpl(String nodeId, NetconfNode netconfNode, DataBroker dataBroker, MountPoint mountpoint,
+ TransactionUtils transactionUtils) {
+ this(new NodeId(nodeId), netconfNode, dataBroker, mountpoint, transactionUtils);
+ }
+
+ @Override
+ public NodeId getNodeId() {
+ return nodeId;
+ }
+
+ @Override
+ public DataBroker getDataBroker() {
+ return dataBroker;
+ }
+ @Override
+ public MountPoint getMountpoint() {
+ return mountpoint;
+ }
+ @Override
+ public TransactionUtils getTransactionUtils() {
+ return transactionUtils;
+ }
+ @Override
+ public NetconfNode getNetconfNode() {
+ return netconfNode;
+ }
+ @Override
+ public Capabilities getCapabilites() {
+ return capabilities;
+ }
+
+ @Override
+ public @NonNull <T extends NotificationListener> ListenerRegistration<NotificationListener> doRegisterNotificationListener(@NonNull T listener) {
+ log.info("Begin register listener for Mountpoint {}", mountpoint.getIdentifier().toString());
+ final Optional<NotificationService> optionalNotificationService = mountpoint
+ .getService(NotificationService.class);
+ final NotificationService notificationService = optionalNotificationService.get();
+ final ListenerRegistration<NotificationListener> ranListenerRegistration = notificationService
+ .registerNotificationListener(listener);
+ log.info("End registration listener for Mountpoint {} Listener: {} Result: {}",
+ mountpoint.getIdentifier().toString(), optionalNotificationService, ranListenerRegistration);
+ return ranListenerRegistration;
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<CreateSubscriptionOutput>> registerNotificationsStream(String streamName) {
+
+ String failMessage = "";
+ final Optional<RpcConsumerRegistry> optionalRpcConsumerService =
+ mountpoint.getService(RpcConsumerRegistry.class);
+ if (optionalRpcConsumerService.isPresent()) {
+ final RpcConsumerRegistry rpcConsumerRegitry = optionalRpcConsumerService.get();
+ @Nonnull
+ final NotificationsService rpcService = rpcConsumerRegitry.getRpcService(NotificationsService.class);
+
+ final CreateSubscriptionInputBuilder createSubscriptionInputBuilder = new CreateSubscriptionInputBuilder();
+ createSubscriptionInputBuilder.setStream(new StreamNameType(streamName));
+ log.info("Event listener triggering notification stream {} for node {}", streamName, nodeId);
+ try {
+ CreateSubscriptionInput createSubscriptionInput = createSubscriptionInputBuilder.build();
+ if (createSubscriptionInput == null) {
+ failMessage = "createSubscriptionInput is null for mountpoint " + nodeId;
+ } else {
+ return rpcService.createSubscription(createSubscriptionInput);
+ }
+ } catch (NullPointerException e) {
+ failMessage = "createSubscription failed";
+ }
+ } else {
+ failMessage = "No RpcConsumerRegistry avaialble.";
+ }
+ log.warn(failMessage);
+ RpcResultBuilder<CreateSubscriptionOutput> result = RpcResultBuilder.failed();
+ result.withError(ErrorType.APPLICATION, failMessage);
+ SettableFuture<RpcResult<CreateSubscriptionOutput>> res = SettableFuture.create();
+ res.set(result.build());
+ return res;
+ }
+
+
+}
diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfNodeStateServiceImpl.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfNodeStateServiceImpl.java
new file mode 100644
index 000000000..041ab9a23
--- /dev/null
+++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfNodeStateServiceImpl.java
@@ -0,0 +1,625 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. 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.ccsdk.features.sdnr.wt.netconfnodestateservice.impl;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import javax.annotation.Nullable;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.IEntityDataProvider;
+import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.StatusChangedHandler.StatusKey;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfAccessor;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeConnectListener;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeStateListener;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeStateService;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.TransactionUtils;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.VesNotificationListener;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlAkka.AkkaConfig;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlAkka.ClusterConfig;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlGeo.GeoConfig;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.rpc.NetconfnodeStateServiceRpcApiImpl;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.rpc.RpcApigetStateCallback;
+import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
+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.MountPoint;
+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.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatus;
+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.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutputBuilder;
+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;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+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.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetconfNodeStateServiceImpl implements NetconfNodeStateService, RpcApigetStateCallback, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NetconfNodeStateServiceImpl.class);
+ private static final String APPLICATION_NAME = "NetconfNodeStateService";
+ @SuppressWarnings("unused")
+ private static final String CONFIGURATIONFILE = "etc/netconfnode-status-service.properties";
+
+
+ @SuppressWarnings("null")
+ private static final @NonNull InstanceIdentifier<Topology> NETCONF_TOPO_IID =
+ InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
+ new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName())));
+
+ @SuppressWarnings("null")
+ private static final @NonNull InstanceIdentifier<Node> NETCONF_NODE_TOPO_IID =
+ InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName())))
+ .child(Node.class);
+
+ private static final DataTreeIdentifier<Node> NETCONF_NODE_TOPO_TREE_ID =
+ DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, NETCONF_NODE_TOPO_IID);
+
+ // Name of ODL controller NETCONF instance
+ private static final NodeId CONTROLLER = new NodeId("controller-config");
+ private static final TransactionUtils TRANSACTIONUTILS = new GenericTransactionUtils();
+
+ // -- OSGi services, provided
+ private DataBroker dataBroker;
+ private MountPointService mountPointService;
+ private RpcProviderService rpcProviderRegistry;
+ private IEntityDataProvider iEntityDataProvider;
+ @SuppressWarnings("unused")
+ private NotificationPublishService notificationPublishService;
+ @SuppressWarnings("unused")
+ private ClusterSingletonServiceProvider clusterSingletonServiceProvider;
+
+ // -- Parameter
+ private ListenerRegistration<L1> listenerL1;
+ private ListenerRegistration<L2> listenerL2;
+ @SuppressWarnings("unused")
+ private ClusterSingletonServiceRegistration cssRegistration;
+
+ private NetconfnodeStateServiceRpcApiImpl rpcApiService;
+
+ /** Indication if init() function called and fully executed **/
+ private Boolean initializationSuccessful;
+
+ /** List of all registered listeners **/
+ private final List<NetconfNodeConnectListener> netconfNodeConnectListenerList;
+
+ /** List of all registered listeners **/
+ private final List<NetconfNodeStateListener> netconfNodeStateListenerList;
+
+ /** List of all registered listeners **/
+ private final List<VesNotificationListener> vesNotificationListenerList;
+
+ /** Indicates if running in cluster configuration **/
+ private boolean isCluster;
+
+ /** Indicates the name of the cluster **/
+ private String clusterName;
+
+ /** Blueprint **/
+ public NetconfNodeStateServiceImpl() {
+ LOG.info("Creating provider for {}", APPLICATION_NAME);
+
+ this.dataBroker = null;
+ this.mountPointService = null;
+ this.rpcProviderRegistry = null;
+ this.notificationPublishService = null;
+ this.clusterSingletonServiceProvider = null;
+
+ this.listenerL1 = null;
+ this.listenerL2 = null;
+ this.initializationSuccessful= false;
+ this.netconfNodeConnectListenerList = new CopyOnWriteArrayList<>();
+ this.netconfNodeStateListenerList = new CopyOnWriteArrayList<>();
+ this.vesNotificationListenerList = new CopyOnWriteArrayList<>();
+ }
+
+ public void setDataBroker(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ public void setRpcProviderRegistry(RpcProviderService rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ public void setNotificationPublishService(NotificationPublishService notificationPublishService) {
+ this.notificationPublishService = notificationPublishService;
+ }
+
+ public void setMountPointService(MountPointService mountPointService) {
+ this.mountPointService = mountPointService;
+ }
+ public void setClusterSingletonService(ClusterSingletonServiceProvider clusterSingletonService) {
+ this.clusterSingletonServiceProvider = clusterSingletonService;
+ }
+ public void setEntityDataProvider(IEntityDataProvider iEntityDataProvider) {
+ this.iEntityDataProvider = iEntityDataProvider;
+ }
+
+ /** Blueprint initialization **/
+ public void init() {
+
+ LOG.info("Session Initiated start {}", APPLICATION_NAME);
+
+ // Start RPC Service
+ this.rpcApiService = new NetconfnodeStateServiceRpcApiImpl(rpcProviderRegistry, vesNotificationListenerList);
+ // Get configuration
+ // ConfigurationFileRepresentation config = new ConfigurationFileRepresentation(CONFIGURATIONFILE);
+ // Akka setup
+ AkkaConfig akkaConfig = getAkkaConfig();
+ this.isCluster = akkaConfig == null ? false : akkaConfig.isCluster();
+ this.clusterName = akkaConfig == null ? "" : akkaConfig.getClusterConfig().getClusterSeedNodeName("abc");
+
+ // Provide status information
+ ClusterConfig cc = akkaConfig==null?null:akkaConfig.getClusterConfig();
+ this.iEntityDataProvider.setStatus(StatusKey.CLUSTER_SIZE,cc==null?"1":String.format("%d",cc.getClusterSize()));
+
+ // RPC Service for specific services
+ this.rpcApiService.setStatusCallback(this);
+
+ LOG.debug("start NetconfSubscriptionManager Service");
+ //this.netconfChangeListener = new NetconfChangeListener(this, dataBroker);
+ //this.netconfChangeListener.register();
+ //DataTreeIdentifier<Node> treeId = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, NETCONF_NODE_TOPO_IID);
+
+ listenerL1 = dataBroker.registerDataTreeChangeListener(NETCONF_NODE_TOPO_TREE_ID, new L1());
+ listenerL2 = dataBroker.registerDataTreeChangeListener(NETCONF_NODE_TOPO_TREE_ID, new L2());
+
+ this.initializationSuccessful = true;
+
+ LOG.info("Session Initiated end. Initialization done {}", initializationSuccessful);
+
+ }
+ /** Blueprint destroy-method method */
+ public void destroy() {
+ close();
+ }
+
+ /**
+ * Getter
+ * @return NetconfnodeStateServiceRpcApiImpl
+ */
+ public NetconfnodeStateServiceRpcApiImpl getNetconfnodeStateServiceRpcApiImpl() {
+ return rpcApiService;
+ }
+
+ @Override
+ public GetStatusOutputBuilder getStatus(GetStatusInput input) {
+ return new GetStatusOutputBuilder();
+ }
+
+ @Override
+ public <L extends NetconfNodeConnectListener> @NonNull ListenerRegistration<L> registerNetconfNodeConnectListener(
+ final @NonNull L netconfNodeConnectListener) {
+ LOG.info("Register connect listener {}",netconfNodeConnectListener.getClass().getName());
+ netconfNodeConnectListenerList.add(netconfNodeConnectListener);
+
+ return new ListenerRegistration<L>() {
+ @Override
+ public @NonNull L getInstance() {
+ return netconfNodeConnectListener;
+ }
+
+ @Override
+ public void close() {
+ LOG.info("Remove connect listener {}",netconfNodeConnectListener);
+ netconfNodeConnectListenerList.remove(netconfNodeConnectListener);
+ }
+ };
+ }
+
+ @Override
+ public <L extends NetconfNodeStateListener> @NonNull ListenerRegistration<L> registerNetconfNodeStateListener(
+ @NonNull L netconfNodeStateListener) {
+ LOG.info("Register state listener {}",netconfNodeStateListener.getClass().getName());
+ netconfNodeStateListenerList.add(netconfNodeStateListener);
+
+ return new ListenerRegistration<L>() {
+ @Override
+ public @NonNull L getInstance() {
+ return netconfNodeStateListener;
+ }
+
+ @Override
+ public void close() {
+ LOG.info("Remove state listener {}",netconfNodeStateListener);
+ netconfNodeStateListenerList.remove(netconfNodeStateListener);
+ }
+ };
+ }
+
+ @Override
+ public <L extends VesNotificationListener> @NonNull ListenerRegistration<L> registerVesNotifications(
+ @NonNull L vesNotificationListener) {
+ LOG.info("Register Ves notification listener {}",vesNotificationListener.getClass().getName());
+ vesNotificationListenerList.add(vesNotificationListener);
+
+ return new ListenerRegistration<L>() {
+ @Override
+ public @NonNull L getInstance() {
+ return vesNotificationListener;
+ }
+
+ @Override
+ public void close() {
+ LOG.info("Remove Ves notification listener {}",vesNotificationListener);
+ vesNotificationListenerList.remove(vesNotificationListener);
+ }
+ };
+ }
+
+ @Override
+ public void close() {
+ LOG.info("Closing start ...");
+ try {
+ close(rpcApiService, listenerL1, listenerL2);
+ } catch (Exception e) {
+ LOG.debug("Closing", e);
+ }
+ LOG.info("Closing done");
+ }
+
+ /**
+ * Used to close all Services, that should support AutoCloseable Pattern
+ *
+ * @param toClose
+ * @throws Exception
+ */
+ private void close(AutoCloseable... toCloseList) throws Exception {
+ for (AutoCloseable element : toCloseList) {
+ if (element != null) {
+ element.close();
+ }
+ }
+ }
+
+ /**
+ * Indication if init() of this bundle successfully done.
+ * @return true if init() was successful. False if not done or not successful.
+ */
+ public boolean isInitializationSuccessful() {
+ return this.initializationSuccessful;
+ }
+
+ /*-------------------------------------------------------------------------------------------
+ * Functions for interface DeviceManagerService
+ */
+
+ /**
+ * For each mounted device a mountpoint is created and this listener is called.
+ * Mountpoint was created or existing. Managed device is now fully connected to node/mountpoint.
+ * @param nNodeId id of the mountpoint
+ * @param netconfNode mountpoint contents
+ */
+ private void enterConnectedState(NodeId nNodeId, NetconfNode netconfNode) {
+
+ String mountPointNodeName = nNodeId.getValue();
+ LOG.info("Access connected state for mountpoint {}", mountPointNodeName);
+
+ boolean preConditionMissing = false;
+ if (mountPointService == null) {
+ preConditionMissing = true;
+ LOG.warn("No mountservice available.");
+ }
+ if (!initializationSuccessful) {
+ preConditionMissing = true;
+ LOG.warn("Devicemanager initialization still pending.");
+ }
+ if (preConditionMissing) {
+ return;
+ }
+
+ boolean isNetconfNodeMaster = isNetconfNodeMaster(netconfNode);
+ LOG.info("isNetconfNodeMaster indication {} for mountpoint {}", isNetconfNodeMaster, mountPointNodeName);
+ if (isNetconfNodeMaster) {
+
+ InstanceIdentifier<Node> instanceIdentifier = NETCONF_TOPO_IID.child(Node.class,
+ new NodeKey(new NodeId(mountPointNodeName)));
+
+ Optional<MountPoint> optionalMountPoint = null;
+ int timeout = 10000;
+ while (!(optionalMountPoint = mountPointService.getMountPoint(instanceIdentifier)).isPresent()
+ && timeout > 0) {
+ LOG.info("Event listener waiting for mount point for Netconf device :: Name : {}", mountPointNodeName);
+ sleepMs(1000);
+ timeout -= 1000;
+ }
+
+ if (!optionalMountPoint.isPresent()) {
+ LOG.warn("Event listener timeout while waiting for mount point for Netconf device :: Name : {} ",
+ mountPointNodeName);
+ } else {
+ // Mountpoint is present for sure
+ MountPoint mountPoint = optionalMountPoint.get();
+ // BindingDOMDataBrokerAdapter.BUILDER_FACTORY;
+ LOG.info("Mountpoint with id: {}", mountPoint.getIdentifier());
+
+ Optional<DataBroker> optionalNetconfNodeDatabroker = mountPoint.getService(DataBroker.class);
+
+ if (!optionalNetconfNodeDatabroker.isPresent()) {
+ LOG.info("Slave mountpoint {} without databroker", mountPointNodeName);
+ } else {
+ LOG.info("Master mountpoint {}", mountPointNodeName);
+ DataBroker netconfNodeDataBroker = optionalNetconfNodeDatabroker.get();
+ NetconfAccessor acessor = new NetconfAccessorImpl(nNodeId, netconfNode, netconfNodeDataBroker,
+ mountPoint, TRANSACTIONUTILS);
+ /*
+ * --> Call Listers for onConnect() Indication
+ for (all)
+ */
+ netconfNodeConnectListenerList.forEach(item -> {
+ try {
+ item.onEnterConnected(acessor);
+ } catch (Exception e) {
+ LOG.info("Exception during onEnterConnected listener call", e);
+ }
+ });
+
+ LOG.info("Connect indication forwarded for {}", mountPointNodeName);
+ }
+ }
+ }
+ }
+
+ /**
+ * Leave the connected status to a non connected or removed status for master mountpoint
+ * @param action that occurred
+ * @param nNodeId id of the mountpoint
+ * @param netconfNode mountpoint contents or not available on remove
+ */
+ private void leaveConnectedState(NodeId nNodeId, Optional<NetconfNode> optionalNetconfNode) {
+ String mountPointNodeName = nNodeId.getValue();
+ LOG.info("netconfNode id {}", mountPointNodeName);
+
+ InstanceIdentifier<Node> instanceIdentifier = NETCONF_TOPO_IID.child(Node.class,
+ new NodeKey(new NodeId(mountPointNodeName)));
+ Optional<MountPoint> optionalMountPoint = mountPointService.getMountPoint(instanceIdentifier);
+ if (optionalMountPoint.isPresent()) {
+ Optional<DataBroker> optionalNetconfNodeDatabroker = optionalMountPoint.get().getService(DataBroker.class);
+ if (optionalNetconfNodeDatabroker.isPresent()) {
+ LOG.info("Master mountpoint {}", mountPointNodeName);
+ netconfNodeConnectListenerList.forEach(item -> {
+ try {
+ if (item != null) {
+ item.onLeaveConnected(nNodeId, optionalNetconfNode);
+ } else {
+ LOG.warn("Unexpeced null item during onleave");
+ }
+ } catch (Exception e) {
+ LOG.info("Exception during onLeaveConnected listener call", e);
+ }
+ });
+ }
+ }
+ }
+
+ // ---- onDataTreeChangedHandler
+
+ private void onDataTreeChangedHandler(@NonNull Collection<DataTreeModification<Node>> changes) {
+ for (final DataTreeModification<Node> change : changes) {
+
+ final DataObjectModification<Node> root = change.getRootNode();
+ //if (LOG.isTraceEnabled()) {
+ LOG.info /*trace*/("Handle this modificationType:{} path:{} root:{}", root.getModificationType(),
+ change.getRootPath(), root);
+ //}
+
+ // Catch potential nullpointer exceptions ..
+ try {
+ ModificationType modificationTyp = root.getModificationType();
+ Node node = modificationTyp == ModificationType.DELETE ? root.getDataBefore()
+ : root.getDataAfter();
+ NodeId nodeId = node != null ? node.getNodeId() : null;
+ if (nodeId != null) {
+ if (nodeId.equals(CONTROLLER)) {
+ // Do not forward any controller related events to devicemanager
+ LOG.debug("Stop processing for [{}]", nodeId);
+ } else {
+ if (modificationTyp != null) {
+ switch (modificationTyp) {
+ case SUBTREE_MODIFIED: // Create or modify sub level node
+ case WRITE: // Create or modify top level node
+ // Treat an overwrite as an update
+ // leaveconnected state.before = connected; state.after != connected
+ // enterConnected state.after == connected
+ // => Here create or update by checking root.getDataBefore() != null
+
+ boolean connectedBefore, connectedAfter;
+ NetconfNode nNodeAfter = getNetconfNode(root.getDataAfter());
+ connectedAfter = isConnected(nNodeAfter);
+ if (root.getDataBefore() != null) {
+ // It is an update
+ NetconfNode nodeBefore = getNetconfNode(root.getDataBefore());
+ connectedBefore = isConnected(nodeBefore);
+ } else {
+ // It is a create
+ connectedBefore = false;
+ }
+
+ LOG.info(
+ "L1 NETCONF Node change with id:{} ConnectedBefore:{} connectedAfter {}:cluster status:{} akkaIsCluster:{}",
+ nodeId, connectedBefore, connectedAfter,
+ getClusteredConnectionStatus(nNodeAfter), isCluster);
+
+ if (!connectedBefore && connectedAfter) {
+ netconfNodeStateListenerList.forEach(item -> {
+ try {
+ item.onCreated(nodeId, nNodeAfter);
+ } catch (Exception e) {
+ LOG.info("Exception during onCreated listener call", e);
+ }
+ });
+ enterConnectedState(nodeId, nNodeAfter);
+ } else {
+ LOG.debug("State change {} {}", connectedBefore, connectedAfter);
+ if (connectedBefore && !connectedAfter) {
+ leaveConnectedState(nodeId, Optional.of(nNodeAfter));
+ }
+ netconfNodeStateListenerList.forEach(item -> {
+ try {
+ item.onStateChange(nodeId, nNodeAfter);
+ } catch (Exception e) {
+ LOG.info("Exception during onStateChange listener call", e);
+ }
+ });
+ }
+ // doProcessing(update ? Action.UPDATE : Action.CREATE, nodeId, root);
+ break;
+ case DELETE:
+ // Node removed
+ // leaveconnected state.before = connected;
+ leaveConnectedState(nodeId, Optional.empty());
+ netconfNodeStateListenerList.forEach(item -> {
+ try {
+ item.onRemoved(nodeId);
+ } catch (Exception e) {
+ LOG.info("Exception during onRemoved listener call", e);
+ }
+ });
+ // doProcessing(Action.REMOVE, nodeId, root);
+ break;
+ }
+ }
+ }
+ }
+ } catch (NullPointerException e) {
+ LOG.info("Data not available at ", e);
+ }
+ } //for
+ }
+
+ // ---- subclasses for listeners
+
+ /**
+ * Clustered listener function to select the right node from
+ * DataObjectModification. Called at all nodes.
+ */
+ private class L1 implements ClusteredDataTreeChangeListener<Node> {
+ @Override
+ public void onDataTreeChanged(@NonNull Collection<DataTreeModification<Node>> changes) {
+ LOG.info("L1 TreeChange enter changes:{}", changes.size());
+ onDataTreeChangedHandler(changes);
+ LOG.info("L1 TreeChange leave");
+ }
+ }
+
+ /**
+ * Data change, called at leader/master
+ */
+ private class L2 implements DataTreeChangeListener<Node> {
+
+ @Override
+ public void onDataTreeChanged(@NonNull Collection<DataTreeModification<Node>> changes) {
+ LOG.info("L2 TreeChange enter changes:{}", changes.size());
+ // Do nothing
+ LOG.info("L2 TreeChange leave");
+ }
+ }
+
+ /* --- private helpers --- */
+ private static @Nullable NetconfNode getNetconfNode(Node node) {
+ return node != null ? node.augmentation(NetconfNode.class) : null;
+ }
+
+ private static boolean isConnected(NetconfNode nNode) {
+ return nNode != null ? ConnectionStatus.Connected.equals(nNode.getConnectionStatus()) : false;
+ }
+
+ private static @Nullable ClusteredConnectionStatus getClusteredConnectionStatus(NetconfNode node) {
+ return node != null ? node.getClusteredConnectionStatus() : null;
+ }
+
+ /* -- LOG related functions -- */
+
+ /** Analyze configuration **/
+ private static @Nullable AkkaConfig getAkkaConfig() {
+ AkkaConfig akkaConfig;
+ try {
+ akkaConfig = AkkaConfig.load();
+ LOG.debug("akka.conf loaded: " + akkaConfig.toString());
+ } catch (Exception e1) {
+ akkaConfig = null;
+ LOG.warn("problem loading akka.conf: " + e1.getMessage());
+ }
+ if (akkaConfig != null && akkaConfig.isCluster()) {
+ LOG.info("cluster mode detected");
+ if (GeoConfig.fileExists()) {
+ try {
+ LOG.debug("try to load geoconfig");
+ GeoConfig.load();
+ } catch (Exception err) {
+ LOG.warn("problem loading geoconfig: " + err.getMessage());
+ }
+ } else {
+ LOG.debug("no geoconfig file found");
+ }
+ } else {
+ LOG.info("single node mode detected");
+ }
+ return akkaConfig;
+ }
+
+ private boolean isNetconfNodeMaster(NetconfNode nNode) {
+ if (this.isCluster) {
+ LOG.debug("check if me is responsible for node");
+ ClusteredConnectionStatus ccs = nNode.getClusteredConnectionStatus();
+ @SuppressWarnings("null")
+ @NonNull String masterNodeName = ccs == null || ccs.getNetconfMasterNode() == null ? "null" : ccs.getNetconfMasterNode();
+ LOG.debug("sdnMasterNode=" + masterNodeName + " and sdnMyNode=" + this.clusterName);
+ if (!masterNodeName.equals(this.clusterName)) {
+ LOG.debug("netconf change but me is not master for this node");
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ private void sleepMs(int milliseconds) {
+ try {
+ Thread.sleep(milliseconds);
+ } catch (InterruptedException e) {
+ LOG.debug("Interrupted sleep");
+ // Restore interrupted state...
+ Thread.currentThread().interrupt();
+ }
+ }
+
+
+}
diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/AkkaConfig.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/AkkaConfig.java
new file mode 100644
index 000000000..d0ea0eb69
--- /dev/null
+++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/AkkaConfig.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. 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.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlAkka;
+
+import java.io.File;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
+
+public class AkkaConfig {
+
+ @SuppressWarnings("unused")
+ private static final Logger LOG = LoggerFactory.getLogger(AkkaConfig.class);
+
+ private static final String DEFAULT_FILENAME = "configuration/initial/akka.conf";
+ private final String filename;
+ private ClusterConfig cluserConfig;
+
+ public ClusterConfig getClusterConfig() {
+ return this.cluserConfig;
+ }
+
+ private AkkaConfig(String filename) {
+ this.filename = filename;
+ }
+
+ public AkkaConfig() {
+ this(null);
+ }
+
+ @Override
+ public String toString() {
+ return "AkkaConfig [filename=" + filename + ", cluserConfig=" + cluserConfig + "]";
+ }
+
+ private void loadFromFile() throws Exception {
+ Config cfg = ConfigFactory.parseFile(new File(this.filename));
+ this.cluserConfig = new ClusterConfig(cfg.getConfig("odl-cluster-data").getConfig("akka").getConfig("cluster"));
+ }
+
+ public boolean isCluster() {
+ return this.cluserConfig != null ? this.cluserConfig.isCluster() : false;
+ }
+
+ public boolean isClusterAndFirstNode() {
+ return isSingleNode() || isCluster() && getClusterConfig().getRoleMemberIndex() == 1;
+ }
+
+ public static AkkaConfig load() throws Exception {
+ return load(DEFAULT_FILENAME);
+ }
+
+ public static AkkaConfig load(String filename) throws Exception {
+ AkkaConfig cfg = new AkkaConfig(filename);
+ cfg.loadFromFile();
+ return cfg;
+ }
+
+ public boolean isSingleNode() {
+ return !this.isCluster();
+ }
+ public static AkkaConfig parse(String content) throws Exception {
+ Config cfg = ConfigFactory.parseString(content);
+ AkkaConfig c = new AkkaConfig();
+ c.cluserConfig=new ClusterConfig(cfg.getConfig("odl-cluster-data").getConfig("akka").getConfig("cluster"));
+ return c;
+ }
+}
diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterConfig.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterConfig.java
new file mode 100644
index 000000000..7f8d6cc78
--- /dev/null
+++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterConfig.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. 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.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlAkka;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlGeo.ClusterRoleInfo;
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlGeo.ClusterRoleInfoCollection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.typesafe.config.Config;
+
+public class ClusterConfig {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ClusterConfig.class);
+
+ private final List<ClusterNodeInfo> seedNodes;
+ private final ClusterRoleInfoCollection roles;
+ private ClusterNodeInfo ismeInfo;
+
+ public static ClusterConfig defaultSingleNodeConfig()
+ {
+ ClusterConfig cfg=new ClusterConfig();
+ cfg.ismeInfo=ClusterNodeInfo.defaultSingleNodeInfo();
+ cfg.seedNodes.add(cfg.ismeInfo);
+ cfg.roles.add(ClusterRoleInfo.defaultSingleNodeRole());
+ return cfg;
+ }
+ public ClusterConfig()
+ {
+ this.seedNodes = new ArrayList<>();
+ this.roles = new ClusterRoleInfoCollection();
+
+ }
+ public ClusterConfig(Config o) throws Exception {
+ {
+ this.seedNodes = new ArrayList<>();
+ this.roles = new ClusterRoleInfoCollection();
+ List<String> a = o.getStringList("seed-nodes");
+ for (int i = 0; i < a.size(); i++) {
+ ClusterNodeInfo info = new ClusterNodeInfo(a.get(i));
+ this.seedNodes.add(info);
+ }
+ a = o.getStringList("roles");
+ for (int i = 0; i < a.size(); i++) {
+ ClusterRoleInfo s = new ClusterRoleInfo(a.get(i));
+ this.roles.add(s);
+ }
+ int idx = this.roles.get(0).getIndex() - 1;
+ if (idx >= 0 && idx < this.seedNodes.size()) {
+ this.ismeInfo = this.seedNodes.get(idx);
+ } else {
+ this.ismeInfo = null;
+ }
+ }
+
+ }
+
+ public boolean isCluster() {
+ return this.seedNodes != null ? this.seedNodes.size() > 1 : false;
+ }
+
+ public boolean isMe(ClusterNodeInfo i) {
+ return this.ismeInfo != null ? this.ismeInfo.equals(i) : false;
+ }
+
+ public List<ClusterNodeInfo> getSeedNodes() {
+ return this.seedNodes;
+ }
+
+ public String getHostName(String defaultValue) {
+ if (getRoleMemberIndex() > 0 && getRoleMemberIndex() <= seedNodes.size()) {
+ return this.seedNodes.get(getRoleMemberIndex()-1).getRemoteAddress();
+ } else {
+ LOG.warn("Seednode not available for roleMemberIndex {}. Using default {}",getRoleMember(), defaultValue);
+ return defaultValue;
+ }
+ }
+
+ public String getDBClusterName(String defaultValue) {
+ String r = null;
+ if (this.seedNodes != null && this.seedNodes.size() > 0) {
+ r = String.format("cluster-%s.%d", this.seedNodes.get(0).getRemoteAddress(), this.seedNodes.get(0).getPort());
+ }
+ if (r == null || r.isEmpty()) {
+ r = defaultValue;
+ }
+ return r;
+ }
+ public String getClusterSeedNodeName() {
+ return this.getClusterSeedNodeName("");
+ }
+ public String getClusterSeedNodeName(String defaultValue) {
+ int idx=this.getRoleMemberIndex()-1;
+ String r=null;
+ if(this.seedNodes!=null && idx>=0 && this.seedNodes.size()>0 && this.seedNodes.size()>idx)
+ {
+ r=this.seedNodes.get(idx).getSeedNodeName();
+ }
+ if (r == null || r.isEmpty()) {
+ r = defaultValue;
+ }
+ return r;
+ }
+ public int getRoleMemberIndex() {
+
+ ClusterRoleInfo role=this.roles.get("member");
+ return role!=null?role.getIndex():0;
+ }
+ public ClusterRoleInfo getRoleMember() {
+ return this.roles.get("member");
+ }
+
+ @Override
+ public String toString() {
+ return "ClusterConfig [seedNodes=" + seedNodes + ", roles=" + roles + ", ismeInfo=" + ismeInfo + "]";
+ }
+
+ public int getClusterSize() {
+ return this.seedNodes == null ? 0 : this.seedNodes.size();
+ }
+
+
+}
diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterNodeInfo.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterNodeInfo.java
new file mode 100644
index 000000000..ef161ad12
--- /dev/null
+++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterNodeInfo.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. 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.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlAkka;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ClusterNodeInfo {
+ private final String protocol;
+ private final String clusterName;
+ private final String remoteAdr;
+ private final int port;
+ private final String seedNodeName;
+
+ public static ClusterNodeInfo defaultSingleNodeInfo() {
+ return new ClusterNodeInfo("akka.tcp","opendaylight-cluster-data","127.0.0.1",2550);
+ }
+
+ public ClusterNodeInfo(String s) throws Exception {
+ final String regex = "([a-z.]*):\\/\\/([a-zA-Z0-9-]*)@([a-zA-Z0-9.-]*):([0-9]*)";
+ final Pattern pattern = Pattern.compile(regex);
+ final Matcher matcher = pattern.matcher(s);
+ if (!matcher.find()) {
+ throw new Exception("invalid seedNode format");
+ }
+ this.seedNodeName = matcher.group();
+ this.protocol = matcher.group(1);
+ this.clusterName = matcher.group(2);
+ this.remoteAdr = matcher.group(3);
+ this.port = Integer.parseInt(matcher.group(4));
+ }
+
+ public ClusterNodeInfo(String protocol, String clustername, String remoteadr, int port) {
+ this.protocol=protocol;
+ this.clusterName=clustername;
+ this.remoteAdr=remoteadr;
+ this.port=port;
+ this.seedNodeName=this.protocol+"://"+this.clusterName+"@"+this.remoteAdr+":"+this.port;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public String getClusterName() {
+ return clusterName;
+ }
+
+ public String getRemoteAddress() {
+ return remoteAdr;
+ }
+ public String getSeedNodeName() {
+ return seedNodeName;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ @Override
+ public String toString() {
+ return "ClusterNodeInfo [protocol=" + protocol + ", clusterName=" + clusterName + ", remoteAdr=" + remoteAdr
+ + ", port=" + port + ", seedNodeName=" + seedNodeName + "]";
+ }
+
+}
diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfo.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfo.java
new file mode 100644
index 000000000..994ef548b
--- /dev/null
+++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfo.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. 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.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlGeo;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ClusterRoleInfo {
+ private final String Role;
+ private final int Index;
+
+ public ClusterRoleInfo(String s) throws Exception {
+ final String regex = "([a-zA-Z]*)-([0-9]*)";
+ final Pattern pattern = Pattern.compile(regex);
+ final Matcher matcher = pattern.matcher(s);
+ if (!matcher.find()) {
+ throw new Exception("unexpected role format:"+s);
+ }
+ this.Role = matcher.group(1);
+ this.Index = Integer.parseInt(matcher.group(2));
+ }
+
+ private ClusterRoleInfo(String role, int idx) {
+ this.Role=role;
+ this.Index=idx;
+ }
+
+ public static ClusterRoleInfo defaultSingleNodeRole() {
+ return new ClusterRoleInfo("member",1);
+ }
+
+ public String getRole() {
+ return Role;
+ }
+ public int getIndex() {
+ return Index;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Index;
+ result = prime * result + (Role == null ? 0 : Role.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ClusterRoleInfo other = (ClusterRoleInfo) obj;
+ if (Index != other.Index) {
+ return false;
+ }
+ if (Role == null) {
+ if (other.Role != null) {
+ return false;
+ }
+ } else if (!Role.equals(other.Role)) {
+ return false;
+ }
+ return true;
+ }
+ @Override
+ public String toString() {
+ return "ClusterRoleInfo [Role=" + Role + ", Index=" + Index + "]";
+ }
+}
diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfoCollection.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfoCollection.java
new file mode 100644
index 000000000..478ed8394
--- /dev/null
+++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfoCollection.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. 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.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlGeo;
+
+import java.util.ArrayList;
+
+public class ClusterRoleInfoCollection extends ArrayList<ClusterRoleInfo> {
+ private static final long serialVersionUID = 1L;
+
+ public ClusterRoleInfo get(String role) {
+ for (ClusterRoleInfo info : this) {
+ if (info.getRole().equals(role)) {
+ return info;
+ }
+ }
+ return null;
+ }
+
+ public boolean contains(ClusterRoleInfo info) {
+ if (info == null) {
+ return false;
+ }
+ for (ClusterRoleInfo i : this) {
+ if (i.equals(info)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/GeoConfig.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/GeoConfig.java
new file mode 100644
index 000000000..c25f3264b
--- /dev/null
+++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/GeoConfig.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. 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.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlGeo;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
+
+public class GeoConfig {
+
+ private static final String DEFAULT_FILENAME = "configuration/initial/geo.conf";
+ private static final String LUMINA_ROOTNODENAME = "lumina-geo-cluster";
+ private final String filename;
+ private final String rootNodename;
+ private ClusterRoleInfoCollection primaryRoles;
+ private ClusterRoleInfoCollection secondayRoles;
+ private RolesTable rolesTable;
+
+ private GeoConfig() {
+ this(null);
+ }
+
+ private GeoConfig(String filename) {
+ this(filename, LUMINA_ROOTNODENAME);
+ }
+
+ private GeoConfig(String filename, String rootNodeName) {
+ this.filename = filename;
+ this.rootNodename = rootNodeName;
+ }
+
+ public static boolean fileExists() {
+ File f = new File(DEFAULT_FILENAME);
+ return f.exists();
+ }
+
+ public static GeoConfig load() throws Exception {
+ return load(DEFAULT_FILENAME);
+ }
+
+ public static GeoConfig load(String filename) throws Exception {
+ GeoConfig cfg = new GeoConfig(filename);
+ cfg._load();
+ return cfg;
+ }
+
+ private void _load() throws Exception {
+ this._load(ConfigFactory.parseFile(new File(this.filename)));
+ }
+
+ private void _load(Config cfg) throws Exception {
+ this.primaryRoles = new ClusterRoleInfoCollection();
+ List<String> a = cfg.getConfig(this.rootNodename).getStringList("primary_roles");
+
+ for (int i = 0; i < a.size(); i++) {
+ ClusterRoleInfo s = new ClusterRoleInfo(a.get(i));
+ this.primaryRoles.add(s);
+ }
+ this.secondayRoles = new ClusterRoleInfoCollection();
+ a = cfg.getConfig(this.rootNodename).getStringList("secondary_roles");
+ for (int i = 0; i < a.size(); i++) {
+ ClusterRoleInfo s = new ClusterRoleInfo(a.get(i));
+ this.secondayRoles.add(s);
+ }
+ this.checkDuplicateRoleEntries();
+ this.rolesTable = new RolesTable(cfg.getConfig(this.rootNodename).getConfigList("ip_roles_table"));
+ }
+
+ private void checkDuplicateRoleEntries() throws Exception {
+ ClusterRoleInfoCollection duplicateEntries = new ClusterRoleInfoCollection();
+ for (ClusterRoleInfo primaryRole : this.primaryRoles) {
+ if (this.secondayRoles.contains(primaryRole)) {
+ duplicateEntries.add(primaryRole);
+ }
+ }
+ if (duplicateEntries.size() > 0) {
+ throw new Exception("duplicate entries found: " + duplicateEntries.toString());
+ }
+
+ }
+
+ public static GeoConfig parse(String content) throws Exception {
+ GeoConfig cfg = new GeoConfig();
+ cfg._load(ConfigFactory.parseString(content));
+ return cfg;
+ }
+
+ public ClusterRoleInfoCollection getPrimaryRoles() {
+ return this.primaryRoles;
+ }
+
+ public ClusterRoleInfoCollection getSecondaryRoles() {
+ return this.secondayRoles;
+ }
+
+ public boolean isPrimary(ClusterRoleInfo roleMember) {
+ return !this.isSecondary(roleMember);
+ }
+
+ private boolean isSecondary(ClusterRoleInfo roleMember) {
+ if (roleMember == null) {
+ return false;
+ }
+ for (ClusterRoleInfo info : this.secondayRoles) {
+ if (info.equals(roleMember)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "GeoConfig [filename=" + filename + ", rootNodename=" + rootNodename + ", primaryRoles=" + primaryRoles
+ + ", secondayRoles=" + secondayRoles + ", rolesTable=" + rolesTable + "]";
+ }
+
+ public static class RolesTableEntry {
+ private final ClusterRoleInfo role;
+ private final String ip;
+
+ public RolesTableEntry(Config c) throws Exception {
+ this.role = new ClusterRoleInfo(c.getString("role"));
+ this.ip = c.getString("ip");
+ }
+
+ @Override
+ public String toString() {
+ return "RolesTableEntry [role=" + role + ", ip=" + ip + "]";
+ }
+ }
+ public static class RolesTable extends ArrayList<RolesTableEntry> {
+ private static final long serialVersionUID = -9146218864237487506L;
+
+ public RolesTable(List<? extends Config> configList) throws Exception {
+ for (Config c : configList) {
+ this.add(new RolesTableEntry(c));
+ }
+ }
+
+ }
+
+
+}
diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/NetconfnodeStateServiceRpcApiImpl.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/NetconfnodeStateServiceRpcApiImpl.java
new file mode 100644
index 000000000..9215887ff
--- /dev/null
+++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/NetconfnodeStateServiceRpcApiImpl.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. 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.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.rpc;
+
+import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.VesNotificationListener;
+import org.opendaylight.mdsal.binding.api.RpcProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.AttributeChangeNotificationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.FaultNotificationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.NetconfnodeStateService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushAttributeChangeNotificationInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushAttributeChangeNotificationOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushFaultNotificationInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushFaultNotificationOutput;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
+
+public class NetconfnodeStateServiceRpcApiImpl implements NetconfnodeStateService, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NetconfnodeStateServiceRpcApiImpl.class);
+
+ private final ObjectRegistration<NetconfnodeStateServiceRpcApiImpl> rpcReg;
+ private RpcApigetStateCallback getStatusCallback;
+ private final List<VesNotificationListener> vesNotificationListenerList;
+
+ public NetconfnodeStateServiceRpcApiImpl(final RpcProviderService rpcProviderRegistry,
+ List<VesNotificationListener> vesNotificationListenerList) {
+
+ this.vesNotificationListenerList = vesNotificationListenerList;
+
+ // Register ourselves as the REST API RPC implementation
+ LOG.info("Register RPC Service " + NetconfnodeStateService.class.getSimpleName());
+ rpcReg = rpcProviderRegistry.registerRpcImplementation(NetconfnodeStateService.class, this);
+ this.getStatusCallback = null;
+ }
+
+ public NetconfnodeStateServiceRpcApiImpl setStatusCallback(RpcApigetStateCallback getStatusCallback) {
+ this.getStatusCallback = getStatusCallback;
+ return this;
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("Close RPC Service");
+ if (rpcReg != null) {
+ rpcReg.close();
+ }
+ }
+
+ /*-------------------------------
+ * Interfaces for getting information
+ */
+ @Override
+ public ListenableFuture<RpcResult<GetStatusOutput>> getStatus(GetStatusInput input) {
+
+ LOG.info("RPC Request: getStatus input: {}", input);
+ RpcResultBuilder<GetStatusOutput> result;
+
+ try {
+ GetStatusOutputBuilder outputBuilder = new GetStatusOutputBuilder();
+ getStatusCallback.getStatus(input);
+ result = RpcResultBuilder.success(outputBuilder);
+ } catch (Exception e) {
+ result = RpcResultBuilder.failed();
+ result.withError(ErrorType.APPLICATION, "Exception", e);
+ }
+ return result.buildFuture();
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<PushFaultNotificationOutput>> pushFaultNotification(
+ PushFaultNotificationInput input) {
+
+ RpcResultBuilder<PushFaultNotificationOutput> result;
+ try {
+ FaultNotificationBuilder faultNotificationBuilder = new FaultNotificationBuilder();
+ faultNotificationBuilder.fieldsFrom(input);
+ vesNotificationListenerList.forEach(item -> item.onNotification(faultNotificationBuilder.build()));
+ result = RpcResultBuilder.success();
+ } catch (Exception e) {
+ result = RpcResultBuilder.failed();
+ result.withError(ErrorType.APPLICATION, "Exception", e);
+ }
+ return result.buildFuture();
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<PushAttributeChangeNotificationOutput>> pushAttributeChangeNotification(
+ PushAttributeChangeNotificationInput input) {
+ RpcResultBuilder<PushAttributeChangeNotificationOutput> result;
+ try {
+ AttributeChangeNotificationBuilder attributeChangeNotificationBuilder = new AttributeChangeNotificationBuilder();
+ attributeChangeNotificationBuilder.fieldsFrom(input);
+ vesNotificationListenerList.forEach(item -> item.onNotification(attributeChangeNotificationBuilder.build()));
+ result = RpcResultBuilder.success();
+ } catch (Exception e) {
+ result = RpcResultBuilder.failed();
+ result.withError(ErrorType.APPLICATION, "Exception", e);
+ }
+ return result.buildFuture();
+ }
+}
diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/RpcApigetStateCallback.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/RpcApigetStateCallback.java
new file mode 100644
index 000000000..1434cf41a
--- /dev/null
+++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/RpcApigetStateCallback.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. 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.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.rpc;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutputBuilder;
+
+public interface RpcApigetStateCallback {
+
+ GetStatusOutputBuilder getStatus(GetStatusInput input);
+}