diff options
Diffstat (limited to 'sdnr/wt/netconfnode-state-service/provider/src')
25 files changed, 2560 insertions, 0 deletions
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..0af35e569 --- /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,586 @@ +/******************************************************************************* + * ============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.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.VesNotificationListener; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlAkka.AkkaConfig; +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"; + + + private static final InstanceIdentifier<Topology> NETCONF_TOPO_IID = + InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, + new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))); + + private static final 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"); + + // -- OSGi services, provided + private DataBroker dataBroker; + private MountPointService mountPointService; + private RpcProviderService rpcProviderRegistry; + @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; + } + + /** 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"); + + // 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("Starting Event listener on Netconf 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; + } + + if (isNetconfNodeMaster(netconfNode)) { + + 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(); + + /* + * --> Call Listers for onConnect() Indication + for (all) + */ + netconfNodeConnectListenerList.forEach(item -> { + try { + item.onEnterConnected(nNodeId, netconfNode, netconfNodeDataBroker); + } 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 + * @param action that occurred + * @param nNodeId id of the mountpoint + * @param nNode mountpoint contents + */ + private void leaveConnectedState(NodeId nNodeId) { + LOG.info("netconfNode id {}", nNodeId); + netconfNodeConnectListenerList.forEach(item -> { + try { + if (item != null) { + item.onLeaveConnected(nNodeId); + } else { + LOG.warn("Unexpeced null item during onleave"); + } + } catch (Exception e) { + LOG.info("Exception during onLeaveConnected listener call", e); + } + }); + } + + // ---- subclasses for listeners + + /** + * Clustered listener function to select the right node from + * DataObjectModification + */ + private class L1 implements ClusteredDataTreeChangeListener<Node> { + @Override + public void onDataTreeChanged(@NonNull Collection<DataTreeModification<Node>> changes) { + LOG.info("L1 TreeChange, changes:{}", changes.size()); + + for (final DataTreeModification<Node> change : changes) { + + final DataObjectModification<Node> root = change.getRootNode(); + if (LOG.isTraceEnabled()) { + LOG.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); + } + 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); + 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); + } + } + } + } + + 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; + } + /** + * Normal listener function to select the right node from DataObjectModification + */ + private class L2 implements DataTreeChangeListener<Node> { + + @Override + public void onDataTreeChanged(@NonNull Collection<DataTreeModification<Node>> changes) { + LOG.info("L2 TreeChange, changes:{}", changes.size()); + } + } + + /* -- 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..bdde30828 --- /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,137 @@ +/******************************************************************************* + * ============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 + "]"; + } + + +} 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); +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml b/sdnr/wt/netconfnode-state-service/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml new file mode 100644 index 000000000..46930ac9e --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +============LICENSE_START======================================================= +ONAP : ccsdk feature sdnr wt netconfnode-service-provider + ================================================================================ +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========================================================= + --> + +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0" odl:use-default-for-reference-types="true"> + + <reference id="dataBroker" interface="org.opendaylight.mdsal.binding.api.DataBroker" + odl:type="default" /> + + <reference id="notificationPublishService" + interface="org.opendaylight.mdsal.binding.api.NotificationPublishService" + odl:type="default" /> + + <reference id="mountPointService" + interface="org.opendaylight.mdsal.binding.api.MountPointService" + odl:type="default" /> + + <reference id="rpcProviderRegistry" + interface="org.opendaylight.mdsal.binding.api.RpcProviderService" + odl:type="default" /> + + <reference id="clusterSingletonService" + interface="org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider"/> + + <bean id="netconfNodeStateService" class="org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.NetconfNodeStateServiceImpl" init-method="init" destroy-method="destroy" scope="singleton"> + <property name="dataBroker" ref="dataBroker"/> + <property name="rpcProviderRegistry" ref="rpcProviderRegistry" /> + <property name="notificationPublishService" ref="notificationPublishService" /> + <property name="mountPointService" ref="mountPointService" /> + <property name="clusterSingletonService" ref="clusterSingletonService" /> + </bean> + + <service id="registerNetconfNodeStateService" + interface="org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeStateService" + ref="netconfNodeStateService" /> + +</blueprint> diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/resources/version.properties b/sdnr/wt/netconfnode-state-service/provider/src/main/resources/version.properties new file mode 100644 index 000000000..80373399e --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/resources/version.properties @@ -0,0 +1,3 @@ +# Proberties filled in by maven during build process +version = ${project.version} +build = ${buildtime} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestAkkaConfig.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestAkkaConfig.java new file mode 100644 index 000000000..dd317c781 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestAkkaConfig.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * ============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.test; + +import static org.junit.Assert.fail; + +import java.io.File; +import org.junit.Test; +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.odlAkka.ClusterNodeInfo; + +public class TestAkkaConfig { + + private static String getAkkaConfigSingleNodeText() { + return "\n" + "odl-cluster-data {\n" + " akka {\n" + " remote {\n" + " artery {\n" + + " enabled = off\n" + " canonical.hostname = \"127.0.0.1\"\n" + + " canonical.port = 2550\n" + " }\n" + " netty.tcp {\n" + + " hostname = \"127.0.0.1\"\n" + " port = 2550\n" + " }\n" + + " # when under load we might trip a false positive on the failure detector\n" + + " # transport-failure-detector {\n" + " # heartbeat-interval = 4 s\n" + + " # acceptable-heartbeat-pause = 16s\n" + " # }\n" + " }\n" + "\n" + " cluster {\n" + + " # Remove \".tcp\" when using artery.\n" + + " seed-nodes = [\"akka.tcp://opendaylight-cluster-data@127.0.0.1:2550\"]\n" + "\n" + + " roles = [\n" + " \"member-1\"\n" + " ]\n" + "\n" + " }\n" + "\n" + + " persistence {\n" + + " # By default the snapshots/journal directories live in KARAF_HOME. You can choose to put it somewhere else by\n" + + " # modifying the following two properties. The directory location specified may be a relative or absolute path. \n" + + " # The relative path is always relative to KARAF_HOME.\n" + "\n" + + " # snapshot-store.local.dir = \"target/snapshots\"\n" + + " # journal.leveldb.dir = \"target/journal\"\n" + "\n" + " journal {\n" + + " leveldb {\n" + " # Set native = off to use a Java-only implementation of leveldb.\n" + + " # Note that the Java-only version is not currently considered by Akka to be production quality.\n" + + "\n" + " # native = off\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; + } + + private static String getAkkaConfigClusterNodeText() { + return "\n" + "odl-cluster-data {\n" + "\n" + " akka {\n" + " loglevel = \"\"\n" + " remote {\n" + + " netty.tcp {\n" + " hostname = \"zltcmtn23arbc01.2f0377.mtn23a.tci.att.com\"\n" + + " port = 2550\n" + " }\n" + " }\n" + " actor {\n" + " debug{\n" + + " autoreceive = on\n" + " lifecycle = on\n" + " unhandled = on\n" + + " fsm = on\n" + " event-stream = on\n" + " }\n" + " }\n" + " cluster {\n" + + " seed-nodes = [\"akka.tcp://opendaylight-cluster-data@zltcmtn23arbc01.2f0377.mtn23a.tci.att.com:2550\", \"akka.tcp://opendaylight-cluster-data@zltcmtn23arbc02.2f0377.mtn23a.tci.att.com:2550\", \"akka.tcp://opendaylight-cluster-data@zltcmtn23arbc03.2f0377.mtn23a.tci.att.com:2550\", \"akka.tcp://opendaylight-cluster-data@zltcmtn23brbc01.f84e7a.mtn23b.tci.att.com:2550\", \"akka.tcp://opendaylight-cluster-data@zltcmtn23brbc02.f84e7a.mtn23b.tci.att.com:2550\", \"akka.tcp://opendaylight-cluster-data@zltcmtn23brbc03.f84e7a.mtn23b.tci.att.com:2550\"]\n" + + " seed-node-timeout = 15s\n" + " roles = [\"member-1\"]\n" + "\n" + " }\n" + + " persistence {\n" + " journal-plugin-fallback {\n" + " circuit-breaker {\n" + + " max-failures = 10\n" + " call-timeout = 60s\n" + + " reset-timeout = 30s\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}\n" + "\n" + + "odl-cluster-rpc {\n" + "\n" + " akka {\n" + " loglevel = \"\"\n" + " remote {\n" + + " netty.tcp {\n" + " hostname = \"zltcmtn23arbc01.2f0377.mtn23a.tci.att.com\"\n" + + " port = 2551\n" + " }\n" + " }\n" + " actor {\n" + " debug{\n" + + " autoreceive = on\n" + " lifecycle = on\n" + " unhandled = on\n" + + " fsm = on\n" + " event-stream = on\n" + " }\n" + " }\n" + " cluster {\n" + + " seed-nodes = [\"akka.tcp://odl-cluster-rpc@zltcmtn23arbc01.2f0377.mtn23a.tci.att.com:2551\", \"akka.tcp://odl-cluster-rpc@zltcmtn23arbc02.2f0377.mtn23a.tci.att.com:2551\", \"akka.tcp://odl-cluster-rpc@zltcmtn23arbc03.2f0377.mtn23a.tci.att.com:2551\", \"akka.tcp://odl-cluster-rpc@zltcmtn23brbc01.f84e7a.mtn23b.tci.att.com:2551\", \"akka.tcp://odl-cluster-rpc@zltcmtn23brbc02.f84e7a.mtn23b.tci.att.com:2551\", \"akka.tcp://odl-cluster-rpc@zltcmtn23brbc03.f84e7a.mtn23b.tci.att.com:2551\"]\n" + + " seed-node-timeout = 15s\n" + " }\n" + " persistence {\n" + + " journal-plugin-fallback {\n" + " circuit-breaker {\n" + " max-failures = 10\n" + + " call-timeout = 60s\n" + " reset-timeout = 30s\n" + " }\n" + " }\n" + + " }\n" + " }\n" + "}\n" + "\n" + ""; + } + + @Test + public void test1() { + AkkaConfig cfg; + try { + System.out.println("testing clusternode config1"); + System.out.println("==========================="); + cfg = AkkaConfig.parse(getAkkaConfigClusterNodeText()); + System.out.println("succeeded: "); + System.out.println(cfg.toString()); + System.out.println(String.format("found %d cluster nodes", cfg.getClusterConfig().getSeedNodes().size())); + for (ClusterNodeInfo n : cfg.getClusterConfig().getSeedNodes()) { + System.out.println(n.toString()); + } + } catch (Exception e) { + String failMessage = "failed: " + e.getMessage(); + System.out.println(failMessage); + fail(failMessage); + } + } + + @Test + public void test2() { + AkkaConfig cfg; + try { + System.out.println("testing singlenode config1"); + System.out.println("==========================="); + cfg = AkkaConfig.parse(getAkkaConfigSingleNodeText()); + System.out.println("succeeded: "); + System.out.println(cfg.toString()); + } catch (Exception e) { + String failMessage = "failed: " + e.getMessage(); + System.out.println(failMessage); + fail(failMessage); + } + } + + @Test + public void test3() { + AkkaConfig cfg; + + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("captured-akka.conf").getFile()); + System.out.println(file.getAbsolutePath()); + + try { + System.out.println("testing clusternode config1"); + System.out.println("==========================="); + cfg = AkkaConfig.load(file.getAbsolutePath()); + System.out.println("succeeded: "+cfg.hashCode()); + System.out.println(cfg.toString()); + System.out.println(String.format("found %d cluster nodes", cfg.getClusterConfig().getSeedNodes().size())); + for (ClusterNodeInfo n : cfg.getClusterConfig().getSeedNodes()) { + System.out.println(n.toString()); + } + } catch (Exception e) { + String failMessage = "failed: " + e.getMessage(); + System.out.println(failMessage); + fail(failMessage); + } + } + + @Test + public void test4() { + ClusterConfig cc = ClusterConfig.defaultSingleNodeConfig(); + cc.getClusterSeedNodeName(); + cc.getRoleMemberIndex(); + cc.isCluster(); + cc.isMe(null); + } +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestGeoConfig.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestGeoConfig.java new file mode 100644 index 000000000..915c88d50 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestGeoConfig.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * ============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.test; + +import static org.junit.Assert.*; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlGeo.GeoConfig; + +public class TestGeoConfig { + + @Test + public void test() { + GeoConfig config; + try { + System.out.println("testing clusternode geo config1"); + System.out.println("==========================="); + config = GeoConfig.parse(getClusterGeoConfigContent()); + System.out.println("succeeded: "); + System.out.println(config.toString()); + System.out.println("primary roles:"); + System.out.println(config.getPrimaryRoles().toString()); + System.out.println("secondary roles:"); + System.out.println(config.getSecondaryRoles().toString()); + + } catch (Exception e) { + fail("failed: " + e.getMessage()); + } + } + + + + private static String getClusterGeoConfigContent() { + return "\n" + "lumina-geo-cluster {\n" + " primary_roles = [\n" + + " \"member-1\",\"member-2\",\"member-3\"\n" + " ]\n" + " secondary_roles = [\n" + + " \"member-4\",\"member-5\",\"member-6\"\n" + " ]\n" + " ip_roles_table = [\n" + "\n" + + " {\n" + "role=\"member-1\"\n" + "ip=\"zltcmtn23arbc01.2f0377.mtn23a.tci.att.com\"\n" + "},\n" + + "{\n" + "role=\"member-2\"\n" + "ip=\"zltcmtn23arbc02.2f0377.mtn23a.tci.att.com\"\n" + "},\n" + "{\n" + + "role=\"member-3\"\n" + "ip=\"zltcmtn23arbc03.2f0377.mtn23a.tci.att.com\"\n" + "},\n" + "{\n" + + "role=\"member-4\"\n" + "ip=\"zltcmtn23brbc01.f84e7a.mtn23b.tci.att.com\"\n" + "},\n" + "{\n" + + "role=\"member-5\"\n" + "ip=\"zltcmtn23brbc02.f84e7a.mtn23b.tci.att.com\"\n" + "},\n" + "{\n" + + "role=\"member-6\"\n" + "ip=\"zltcmtn23brbc03.f84e7a.mtn23b.tci.att.com\"\n" + "}\n" + " \n" + + " ]\n" + "}\n" + "\n" + "\n" + "\n" + "\n" + ""; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestNetconfNodeStateService.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestNetconfNodeStateService.java new file mode 100644 index 000000000..ff659ca3d --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestNetconfNodeStateService.java @@ -0,0 +1,316 @@ +/******************************************************************************* + * ============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.test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.common.util.concurrent.ListenableFuture; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.times; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.ExecutionException; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +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.VesNotificationListener; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.NetconfNodeStateServiceImpl; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.rpc.NetconfnodeStateServiceRpcApiImpl; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.ClusterSingletonServiceProviderMock; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.DataBrokerNetconfMock; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.MountPointMock; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.MountPointServiceMock; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.NotificationPublishServiceMock; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.RpcProviderRegistryMock; +import org.opendaylight.mdsal.binding.api.DataObjectModification; +import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType; +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.singleton.common.api.ClusterSingletonServiceProvider; +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.NetconfNodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.AttributeChangeNotification; +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.FaultNotification; +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.GetStatusInputBuilder; +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.PushAttributeChangeNotificationInputBuilder; +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.PushFaultNotificationInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushFaultNotificationOutput; +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.network.topology.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class TestNetconfNodeStateService { + + private static Path KARAF_ETC = Paths.get("etc"); + private static NetconfNodeStateServiceImpl netconfStateService; + private static MountPointMock mountPoint; + private static DataBrokerNetconfMock dataBrokerNetconf; + + private static final Logger LOG = LoggerFactory.getLogger(TestNetconfNodeStateService.class); + + @BeforeClass + public static void before() throws InterruptedException, IOException { + + System.out.println("Logger: " + LOG.getClass().getName() + " " + LOG.getName()); + // Call System property to get the classpath value + Path etc = KARAF_ETC; + delete(etc); + + System.out.println("Create empty:" + etc.toString()); + Files.createDirectories(etc); + + // Create mocks + dataBrokerNetconf = new DataBrokerNetconfMock(); + dataBrokerNetconf.newReadWriteTransaction(); + mountPoint = new MountPointMock(); + ClusterSingletonServiceProvider clusterSingletonService = new ClusterSingletonServiceProviderMock(); + MountPointService mountPointService = new MountPointServiceMock(mountPoint); + NotificationPublishService notificationPublishService = new NotificationPublishServiceMock(); + RpcProviderService rpcProviderRegistry = new RpcProviderRegistryMock(); + + // start using blueprint interface + netconfStateService = new NetconfNodeStateServiceImpl(); + + netconfStateService.setDataBroker(dataBrokerNetconf); + netconfStateService.setMountPointService(mountPointService); + netconfStateService.setNotificationPublishService(notificationPublishService); + netconfStateService.setRpcProviderRegistry(rpcProviderRegistry); + netconfStateService.setClusterSingletonService(clusterSingletonService); + netconfStateService.init(); + System.out.println("Initialization done"); + } + + @AfterClass + public static void after() throws InterruptedException, IOException { + System.out.println("Start shutdown"); + // close using blueprint interface + netconfStateService.close(); + delete(KARAF_ETC); + + } + + @Test + public void test1() { + + System.out.println("Test1: Verify init state"); + assertTrue("Devicemanager not initialized", netconfStateService.isInitializationSuccessful()); + } + + + @Test + public void test2() { + + System.out.println("Test2: Register state listener"); + + NetconfNodeStateListener nSL = mock(NetconfNodeStateListener.class); + ListenerRegistration<NetconfNodeStateListener> res = + netconfStateService.registerNetconfNodeStateListener(nSL); + assertNotNull("Result should be null", res); + res.getInstance(); + res.close(); + } + + @Test + public void test3() { + + System.out.println("Test3: Register connect listener"); + + NetconfNodeConnectListener nCL = mock(NetconfNodeConnectListener.class); + ListenerRegistration<NetconfNodeConnectListener> res = + netconfStateService.registerNetconfNodeConnectListener(nCL); + assertNotNull("Result should be null", res); + res.getInstance(); + res.close(); + } + + @Test + public void test4() { + System.out.println("Test4: Get status listener"); + GetStatusInputBuilder inputBuilder = new GetStatusInputBuilder(); + GetStatusOutputBuilder res = netconfStateService.getStatus(inputBuilder.build()); + assertNotNull("Result should be null", res); + } + + @SuppressWarnings("unchecked") + @Test + public void test5OnConnect() { + System.out.println("Test5: On Connect"); + NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder(); + netconfNodeBuilder.setConnectionStatus(ConnectionStatus.Connected); + NetconfNode rootNodeNetconf = netconfNodeBuilder.build(); + + NodeId nodeId = new NodeId("Test"); + NodeBuilder nodeBuilder = new NodeBuilder(); + nodeBuilder.addAugmentation(NetconfNode.class, rootNodeNetconf); + nodeBuilder.setNodeId(nodeId); + Node rootNode = nodeBuilder.build(); + + DataObjectModification<Node> dom = mock(DataObjectModification.class); + when(dom.getDataAfter()).thenReturn(rootNode); + when(dom.getModificationType()).thenReturn(ModificationType.WRITE); + + DataTreeModification<Node> ntn = mock(DataTreeModification.class); + when(ntn.getRootNode()).thenReturn(dom); + + NetconfNodeConnectListener nCL = mock(NetconfNodeConnectListener.class); + netconfStateService.registerNetconfNodeConnectListener(nCL); + mountPoint.setDatabrokerAbsent(false); + + Collection<DataTreeModification<Node>> changes = Arrays.asList(ntn); + dataBrokerNetconf.sendClusteredChanges(changes); + dataBrokerNetconf.sendChanges(changes); + + //verify that it was called one time + verify(nCL,times(1)).onEnterConnected(nodeId, rootNodeNetconf, mountPoint.getDataBroker()); + + } + + @SuppressWarnings("unchecked") + @Test + public void test6Update() { + System.out.println("Test6: OnChange"); + NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder(); + netconfNodeBuilder.setConnectionStatus(ConnectionStatus.Connected); + NetconfNode rootNodeNetconf = netconfNodeBuilder.build(); + + NodeBuilder nodeBuilder = new NodeBuilder(); + nodeBuilder.addAugmentation(NetconfNode.class, rootNodeNetconf); + nodeBuilder.setNodeId(new NodeId("Test")); + Node rootNodeAfter = nodeBuilder.build(); + + DataObjectModification<Node> dom = mock(DataObjectModification.class); + when(dom.getDataBefore()).thenReturn(rootNodeAfter); + when(dom.getDataAfter()).thenReturn(rootNodeAfter); + when(dom.getModificationType()).thenReturn(ModificationType.WRITE); + + DataTreeModification<Node> ntn = mock(DataTreeModification.class); + when(ntn.getRootNode()).thenReturn(dom); + + Collection<DataTreeModification<Node>> changes = Arrays.asList(ntn); + dataBrokerNetconf.sendClusteredChanges(changes); + dataBrokerNetconf.sendChanges(changes); + } + + @Test + public void test7ApiStatus() throws InterruptedException, ExecutionException { + + NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl(); + + GetStatusInputBuilder statusInput = new GetStatusInputBuilder(); + ListenableFuture<RpcResult<GetStatusOutput>> statusOutput = api.getStatus(statusInput.build()); + RpcResult<GetStatusOutput> res = statusOutput.get(); + GetStatusOutput output = res.getResult(); + System.out.println("Output "+output); + } + + + @Test + public void test8ApiPushFault() throws InterruptedException, ExecutionException { + + NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl(); + + VesNotificationListener vNL = mock(VesNotificationListener.class); + ListenerRegistration<VesNotificationListener> registration = netconfStateService.registerVesNotifications(vNL); + + FaultNotificationBuilder faultBuilder = new FaultNotificationBuilder(); + faultBuilder.setProblem("problem1"); + FaultNotification fault = faultBuilder.build(); + PushFaultNotificationInputBuilder statusInput = new PushFaultNotificationInputBuilder(); + statusInput.fieldsFrom(fault); + ListenableFuture<RpcResult<PushFaultNotificationOutput>> rpcOutput = api.pushFaultNotification(statusInput.build()); + RpcResult<PushFaultNotificationOutput> res = rpcOutput.get(); + PushFaultNotificationOutput output = res.getResult(); + + //verify that it was called one time + verify(vNL,times(1)).onNotification(fault); + + registration.close(); + System.out.println("Output "+output); + } + + @Test + public void test9ApiPushNotifiction() throws InterruptedException, ExecutionException { + + NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl(); + + VesNotificationListener vNL = mock(VesNotificationListener.class); + ListenerRegistration<VesNotificationListener> registration = netconfStateService.registerVesNotifications(vNL); + + AttributeChangeNotificationBuilder changeBuilder = new AttributeChangeNotificationBuilder(); + changeBuilder.setAttributeName("attribute1"); + AttributeChangeNotification change = changeBuilder.build(); + PushAttributeChangeNotificationInputBuilder statusInput = new PushAttributeChangeNotificationInputBuilder(); + statusInput.fieldsFrom(change); + ListenableFuture<RpcResult<PushAttributeChangeNotificationOutput>> rpcOutput = api.pushAttributeChangeNotification(statusInput.build()); + RpcResult<PushAttributeChangeNotificationOutput> res = rpcOutput.get(); + PushAttributeChangeNotificationOutput output = res.getResult(); + + //verify that it was called one time + verify(vNL,times(1)).onNotification(change); + + registration.close(); + System.out.println("Output "+output); + } + + + // ------- private section + + private static void delete(Path etc) throws IOException { + if (Files.exists(etc)) { + System.out.println("Found and remove:" + etc.toString()); + delete(etc.toFile()); + } + } + + private static void delete(File f) throws IOException { + if (f.isDirectory()) { + for (File c : f.listFiles()) { + delete(c); + } + } + if (!f.delete()) { + throw new FileNotFoundException("Failed to delete file: " + f); + } + } + + + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/ClusterSingletonServiceProviderMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/ClusterSingletonServiceProviderMock.java new file mode 100644 index 000000000..86340c052 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/ClusterSingletonServiceProviderMock.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * ============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.test.mock; + +import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService; +import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; +import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration; + +public class ClusterSingletonServiceProviderMock implements ClusterSingletonServiceProvider { + + @Override + public void close() throws Exception { + + } + + @Override + public ClusterSingletonServiceRegistration registerClusterSingletonService(ClusterSingletonService service) { + return null; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerMountpointMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerMountpointMock.java new file mode 100644 index 000000000..48401c881 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerMountpointMock.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * ============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.test.mock; + +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.binding.api.BindingService; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.DataTreeChangeListener; +import org.opendaylight.mdsal.binding.api.DataTreeIdentifier; +import org.opendaylight.mdsal.binding.api.ReadTransaction; +import org.opendaylight.mdsal.binding.api.ReadWriteTransaction; +import org.opendaylight.mdsal.binding.api.TransactionChain; +import org.opendaylight.mdsal.binding.api.TransactionChainListener; +import org.opendaylight.mdsal.binding.api.WriteTransaction; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; + +public class DataBrokerMountpointMock implements DataBroker, BindingService { + + ReadTransaction readTransaction; + + public void setReadOnlyTransaction(ReadTransaction readTransaction) { + this.readTransaction = readTransaction; + } + + @Override + public @NonNull ReadTransaction newReadOnlyTransaction() { + return null; + } + + @Override + public @NonNull ReadWriteTransaction newReadWriteTransaction() { + return null; + } + + @Override + public @NonNull WriteTransaction newWriteOnlyTransaction() { + return null; + } + + @Override + public <T extends DataObject, L extends DataTreeChangeListener<T>> @NonNull ListenerRegistration<L> registerDataTreeChangeListener( + @NonNull DataTreeIdentifier<T> treeId, @NonNull L listener) { + return null; + } + + @Override + public @NonNull TransactionChain createTransactionChain(@NonNull TransactionChainListener listener) { + return null; + } + + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerNetconfMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerNetconfMock.java new file mode 100644 index 000000000..90ab8608c --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerNetconfMock.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * ============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.test.mock; + +import java.util.Collection; +import org.eclipse.jdt.annotation.NonNull; +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.DataTreeIdentifier; +import org.opendaylight.mdsal.binding.api.DataTreeModification; +import org.opendaylight.mdsal.binding.api.ReadTransaction; +import org.opendaylight.mdsal.binding.api.TransactionChain; +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; + +public class DataBrokerNetconfMock implements DataBroker { + + private @NonNull DataTreeChangeListener<Node> listener; + private @NonNull ClusteredDataTreeChangeListener<Node> listenerClustered; + + @Override + public @NonNull ReadTransaction newReadOnlyTransaction() { + return null; + } + + @Override + public org.opendaylight.mdsal.binding.api.@NonNull ReadWriteTransaction newReadWriteTransaction() { + return null; + } + + @Override + public org.opendaylight.mdsal.binding.api.@NonNull WriteTransaction newWriteOnlyTransaction() { + return null; + } + + + @Override + public @NonNull TransactionChain createTransactionChain( + org.opendaylight.mdsal.binding.api.@NonNull TransactionChainListener listener) { + return null; + } + + @SuppressWarnings("unchecked") + @Override + public <T extends DataObject, L extends DataTreeChangeListener<T>> @NonNull ListenerRegistration<L> registerDataTreeChangeListener( + @NonNull DataTreeIdentifier<T> treeId, @NonNull L pListener) { + System.out.println("Register "+pListener.getClass().getName()); + if (pListener instanceof ClusteredDataTreeChangeListener) { + System.out.println("Clustered listener"); + this.listenerClustered = (ClusteredDataTreeChangeListener<Node>) pListener; + } else if (pListener instanceof DataTreeChangeListener) { + System.out.println("Listener"); + this.listener = (DataTreeChangeListener<Node>) pListener; + } + return new ListenerRegistration<L>() { + + @Override + public @NonNull L getInstance() { + return pListener; + } + + @Override + public void close() { + } + + }; + } + + public void sendChanges(Collection<DataTreeModification<Node>> changes) { + this.listener.onDataTreeChanged(changes); + } + + public void sendClusteredChanges(Collection<DataTreeModification<Node>> changes) { + this.listenerClustered.onDataTreeChanged(changes); + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointMock.java new file mode 100644 index 000000000..e5bff451d --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointMock.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * ONAP : ccsdk feature sdnr wt sdnr-wt-devicemanager-provider + * ================================================================================ + * 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.test.mock; + +import java.util.Optional; +import org.opendaylight.mdsal.binding.api.BindingService; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.MountPoint; +import org.opendaylight.mdsal.binding.api.NotificationService; +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.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.yangtools.yang.binding.InstanceIdentifier; + +/** + * @author herbert + * + */ +public class MountPointMock implements MountPoint { + + private boolean databrokerAbsent = true; + private final DataBrokerMountpointMock dataBroker = new DataBrokerMountpointMock(); + private final RpcConsumerRegistryMock rpcConsumerRegistry = new RpcConsumerRegistryMock(); + private NotificationService setReadTransaction; + + private static final InstanceIdentifier<Topology> NETCONF_TOPO_IID = + InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, + new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))); + + @Override + public InstanceIdentifier<?> getIdentifier() { + return NETCONF_TOPO_IID; + } + + @SuppressWarnings("unchecked") + @Override + public <T extends BindingService> Optional<T> getService(Class<T> service) { + + System.out.println("Requested mountpoint service: "+service.getSimpleName()+" databrokerAbsent state: "+databrokerAbsent); + + Optional<? extends BindingService> res; + if (service.isInstance(dataBroker)) { + System.out.println("Delivering databroker"); + res = databrokerAbsent ? Optional.empty() : Optional.of(dataBroker); + } else if (service.isInstance(rpcConsumerRegistry)) { + System.out.println("Delivering RpcConsumerRegistryMock"); + res = Optional.of(rpcConsumerRegistry); + } else if (service.isInstance(setReadTransaction)) { + System.out.println("Delivering notificationService"); + res = Optional.of(setReadTransaction); + } else { + System.out.println("Delivering no service"); + res = Optional.empty(); + } + return (Optional<T>) res; + } + + public void setDatabrokerAbsent( boolean state) { + this.databrokerAbsent = state; + } + + public DataBroker getDataBroker() { + return dataBroker; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointServiceMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointServiceMock.java new file mode 100644 index 000000000..127019633 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointServiceMock.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * ============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.test.mock; + +import java.util.Optional; +import org.opendaylight.mdsal.binding.api.MountPoint; +import org.opendaylight.mdsal.binding.api.MountPointService; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * @author herbert + * + */ +public class MountPointServiceMock implements MountPointService { + + private final MountPointMock mountpoint; + + public MountPointServiceMock(MountPointMock mountpoint) { + this.mountpoint = mountpoint; + } + + @Override + public Optional<MountPoint> getMountPoint(InstanceIdentifier<?> mountPoint) { + + Optional<MountPoint> optional = Optional.of(mountpoint); + return optional; + } + + @Override + public <T extends MountPointListener> ListenerRegistration<T> registerListener(InstanceIdentifier<?> path, + T listener) { + return null; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/NotificationPublishServiceMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/NotificationPublishServiceMock.java new file mode 100644 index 000000000..0564c56a3 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/NotificationPublishServiceMock.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.test.mock; + +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.TimeUnit; +import org.opendaylight.mdsal.binding.api.NotificationPublishService; +import org.opendaylight.yangtools.yang.binding.Notification; + +public class NotificationPublishServiceMock implements NotificationPublishService { + + @Override + public ListenableFuture<?> offerNotification(Notification notification) { + return null; + } + + @Override + public ListenableFuture<?> offerNotification(Notification notification, int timeout, TimeUnit unit) + throws InterruptedException { + return null; + } + + @Override + public void putNotification(Notification notification) throws InterruptedException { + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcConsumerRegistryMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcConsumerRegistryMock.java new file mode 100644 index 000000000..7e48ff2e5 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcConsumerRegistryMock.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * ONAP : ccsdk feature sdnr wt sdnr-wt-devicemanager-provider + * ================================================================================ + * 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.test.mock; + +import org.opendaylight.mdsal.binding.api.RpcConsumerRegistry; +import org.opendaylight.yangtools.yang.binding.RpcService; + +public class RpcConsumerRegistryMock implements RpcConsumerRegistry { + + @Override + public <T extends RpcService> T getRpcService(Class<T> serviceInterface) { + return null; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcProviderRegistryMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcProviderRegistryMock.java new file mode 100644 index 000000000..fbcb21db9 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcProviderRegistryMock.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * ============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.test.mock; + +import java.util.Set; +import org.opendaylight.mdsal.binding.api.RpcProviderService; +import org.opendaylight.yangtools.concepts.ObjectRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.RpcService; + +public class RpcProviderRegistryMock implements RpcProviderService { + + @Override + public <S extends RpcService, T extends S> ObjectRegistration<T> registerRpcImplementation(Class<S> type, + T implementation) { + return null; + } + + @Override + public <S extends RpcService, T extends S> ObjectRegistration<T> registerRpcImplementation(Class<S> type, + T implementation, Set<InstanceIdentifier<?>> paths) { + return null; + } + + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/resources/captured-akka.conf b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/captured-akka.conf new file mode 100644 index 000000000..8489f0905 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/captured-akka.conf @@ -0,0 +1,72 @@ + +odl-cluster-data { + + akka { + loglevel = "" + remote { + netty.tcp { + hostname = "zltcdyh1arbc02.2f0377.dyh1a.tci.att.com" + port = 2550 + } + } + actor { + debug{ + autoreceive = on + lifecycle = on + unhandled = on + fsm = on + event-stream = on + } + } + cluster { + seed-nodes = ["akka.tcp://opendaylight-cluster-data@zltcdyh1arbc01.2f0377.dyh1a.tci.att.com:2550", "akka.tcp://opendaylight-cluster-data@zltcdyh1arbc02.2f0377.dyh1a.tci.att.com:2550", "akka.tcp://opendaylight-cluster-data@zltcdyh1arbc03.2f0377.dyh1a.tci.att.com:2550", "akka.tcp://opendaylight-cluster-data@zltcdyh1brbc01.f84e7a.dyh1b.tci.att.com:2550", "akka.tcp://opendaylight-cluster-data@zltcdyh1brbc02.f84e7a.dyh1b.tci.att.com:2550", "akka.tcp://opendaylight-cluster-data@zltcdyh1brbc03.f84e7a.dyh1b.tci.att.com:2550"] + seed-node-timeout = 15s + roles = ["member-2"] + + } + persistence { + journal-plugin-fallback { + circuit-breaker { + max-failures = 10 + call-timeout = 60s + reset-timeout = 30s + } + } + } + } +} + +odl-cluster-rpc { + + akka { + loglevel = "" + remote { + netty.tcp { + hostname = "zltcdyh1arbc02.2f0377.dyh1a.tci.att.com" + port = 2551 + } + } + actor { + debug{ + autoreceive = on + lifecycle = on + unhandled = on + fsm = on + event-stream = on + } + } + cluster { + seed-nodes = ["akka.tcp://odl-cluster-rpc@zltcdyh1arbc01.2f0377.dyh1a.tci.att.com:2551", "akka.tcp://odl-cluster-rpc@zltcdyh1arbc02.2f0377.dyh1a.tci.att.com:2551", "akka.tcp://odl-cluster-rpc@zltcdyh1arbc03.2f0377.dyh1a.tci.att.com:2551", "akka.tcp://odl-cluster-rpc@zltcdyh1brbc01.f84e7a.dyh1b.tci.att.com:2551", "akka.tcp://odl-cluster-rpc@zltcdyh1brbc02.f84e7a.dyh1b.tci.att.com:2551", "akka.tcp://odl-cluster-rpc@zltcdyh1brbc03.f84e7a.dyh1b.tci.att.com:2551"] + seed-node-timeout = 15s + } + persistence { + journal-plugin-fallback { + circuit-breaker { + max-failures = 10 + call-timeout = 60s + reset-timeout = 30s + } + } + } + } +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/resources/simplelogger.properties b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/simplelogger.properties new file mode 100644 index 000000000..2eb3eb7b3 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/simplelogger.properties @@ -0,0 +1,38 @@ +# SLF4J's SimpleLogger configuration file +# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err. + +# Default logging detail level for all instances of SimpleLogger. +# Must be one of ("trace", "debug", "info", "warn", or "error"). +# If not specified, defaults to "info". +org.slf4j.simpleLogger.defaultLogLevel=info + +# Logging detail level for a SimpleLogger instance named "xxx.yyy.zzz". +# Must be one of ("trace", "debug", "info", "warn", or "error"). +# If not specified, the default logging detail level is used. +# org.slf4j.simpleLogger.log.xxx.yyy=debug +org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager=info +org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager.archiveservice=info +org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager.base.internalTypes.Resources=info +org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager.base.netconf.container=info + +# Set to true if you want the current date and time to be included in output messages. +# Default is false, and will output the number of milliseconds elapsed since startup. +#org.slf4j.simpleLogger.showDateTime=false + +# The date and time format to be used in the output messages. +# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat. +# If the format is not specified or is invalid, the default format is used. +# The default format is yyyy-MM-dd HH:mm:ss:SSS Z. +#org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z + +# Set to true if you want to output the current thread name. +# Defaults to true. +#org.slf4j.simpleLogger.showThreadName=true + +# Set to true if you want the Logger instance name to be included in output messages. +# Defaults to true. +#org.slf4j.simpleLogger.showLogName=true + +# Set to true if you want the last component of the name to be included in output messages. +# Defaults to false. +#org.slf4j.simpleLogger.showShortLogName=false diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/resources/test.properties b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/test.properties new file mode 100644 index 000000000..de49c5893 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/test.properties @@ -0,0 +1,55 @@ +[dcae] +dcaeUserCredentials=admin:admin +dcaeUrl=off +dcaeHeartbeatPeriodSeconds=120 +dcaeTestCollector=no + +[aots] +userPassword=passwd +soapurladd=off +soapaddtimeout=10 +soapinqtimeout=20 +userName=user +inqtemplate=inqreq.tmpl.xml +assignedto=userid +addtemplate=addreq.tmpl.xml +severitypassthrough=critical,major,minor,warning +systemuser=user +prt-offset=1200 +soapurlinq=off +#smtpHost= +#smtpPort= +#smtpUsername= +#smtpPassword= +#smtpSender= +#smtpReceivers= + +[es] +esCluster=sendateodl5 +#time limit to keep increasing data in database [in seconds] +#60*60*24*30 (30days) +esArchiveLimit=2592000 +#folder where removed data will be stored +esArchiveFolder=./backup +#interval to archive database [in seconds] +#60*60*24 (1day) +esArchiveInterval=86400 + +[aai] +#keep comment +aaiHeaders=["X-TransactionId: 9999"] +aaiUrl=http://localhost:81 +aaiUserCredentials=AAI:AAI +aaiDeleteOnMountpointRemove=false +aaiTrustAllCerts=false +aaiApiVersion=aai/v13 +aaiPropertiesFile=aaiclient.properties +aaiApplicationId=SDNR +aaiPcks12ClientCertFile=/opt/logs/externals/data/stores/keystore.client.p12 +aaiPcks12ClientCertPassphrase=adminadmin +aaiClientConnectionTimeout=30000 + +[pm] +pmCluster=sendateodl5 +pmEnabled=true + |