ONOS-6078 Netconf active component and integration with store
Change-Id: Ia80f0123f58a8e872de6ef7bf90bdde24f99d00c
diff --git a/apps/config/src/main/java/org/onosproject/config/DynamicConfigService.java b/apps/config/src/main/java/org/onosproject/config/DynamicConfigService.java
index aaa3812..060c286 100755
--- a/apps/config/src/main/java/org/onosproject/config/DynamicConfigService.java
+++ b/apps/config/src/main/java/org/onosproject/config/DynamicConfigService.java
@@ -146,25 +146,6 @@
void deleteNodeRecursive(ResourceId path);
/**
- * Adds a listener to be notified when a leaf or subtree rooted at the
- * specified path is modified.
- *
- * @param path data structure with absolute path to the node being listened to
- * @param listener listener to be notified
- * @throws FailedException if the listener could not be added
- */
- void addConfigListener(ResourceId path, DynamicConfigListener listener);
-
- /**
- * Removes a previously added listener.
- *
- * @param path data structure with absolute path to the node being listened to
- * @param listener listener to unregister
- * @throws FailedException if the listener could not be removed
- */
- void removeConfigListener(ResourceId path, DynamicConfigListener listener);
-
- /**
* Registers an RPC handler.
*
* @param handler RPC handler
diff --git a/apps/config/src/main/java/org/onosproject/config/DynamicConfigStore.java b/apps/config/src/main/java/org/onosproject/config/DynamicConfigStore.java
index 25ddf55..9ea34f2 100644
--- a/apps/config/src/main/java/org/onosproject/config/DynamicConfigStore.java
+++ b/apps/config/src/main/java/org/onosproject/config/DynamicConfigStore.java
@@ -20,7 +20,6 @@
import org.onosproject.yang.model.ResourceId;
import org.onosproject.store.Store;
-import java.util.Collection;
import java.util.concurrent.CompletableFuture;
/**
@@ -137,32 +136,4 @@
* {@code FailedException} if the delete request failed
*/
CompletableFuture<Boolean> deleteNodeRecursive(ResourceId path);
-
- /**
- * Adds a listener to be notified when a leaf or subtree rooted at the
- * specified path is modified.
- *
- * @param path data structure with absolute path to the node being listened to
- * @param listener listener to be notified
- * @throws FailedException if the listener could not be added
- */
- void addConfigListener(ResourceId path, DynamicConfigListener listener);
-
- /**
- * Removes a previously added listener.
- *
- * @param path data structure with absolute path to the node being listened to
- * @param listener listener to unregister
- * @throws FailedException if the listener could not be removed
- */
- void removeConfigListener(ResourceId path, DynamicConfigListener listener);
-
- /**
- * Returns a collection of previously added listeners.
- *
- * @param path data structure with absolute path to the node being listened to
- * @return a collection of previously added listeners
- */
- Collection<? extends DynamicConfigListener> getConfigListener(ResourceId path);
- //DynamicConfigListener getConfigListener(ResourceId path);
}
\ No newline at end of file
diff --git a/apps/config/src/main/java/org/onosproject/config/impl/DistributedDynamicConfigStore.java b/apps/config/src/main/java/org/onosproject/config/impl/DistributedDynamicConfigStore.java
index 1c63258..094d04c 100644
--- a/apps/config/src/main/java/org/onosproject/config/impl/DistributedDynamicConfigStore.java
+++ b/apps/config/src/main/java/org/onosproject/config/impl/DistributedDynamicConfigStore.java
@@ -24,19 +24,15 @@
import org.apache.felix.scr.annotations.Service;
import org.onlab.util.KryoNamespace;
import org.onosproject.config.DynamicConfigEvent;
-import org.onosproject.config.DynamicConfigListener;
import org.onosproject.config.DynamicConfigStore;
import org.onosproject.config.DynamicConfigStoreDelegate;
import org.onosproject.config.ResourceIdParser;
import org.onosproject.config.FailedException;
import org.onosproject.config.Filter;
-//import org.onosproject.config.cfgreceiver.CfgReceiver;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.AsyncDocumentTree;
import org.onosproject.store.service.ConsistentMap;
-import org.onosproject.store.service.ConsistentMapException;
-import org.onosproject.store.service.ConsistentMultimap;
import org.onosproject.store.service.DocumentPath;
import org.onosproject.store.service.DocumentTreeEvent;
import org.onosproject.store.service.DocumentTreeListener;
@@ -58,7 +54,7 @@
import org.onosproject.yang.model.SchemaId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Collection;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -82,7 +78,6 @@
protected StorageService storageService;
private AsyncDocumentTree<DataNode.Type> keystore;
private ConsistentMap<String, LeafNode> objectStore;
- private ConsistentMultimap<String, DynamicConfigListener> lstnrStore;
private final DocumentTreeListener<DataNode.Type> klistener = new InternalDocTreeListener();
private final MapEventListener<String, LeafNode> olistener = new InternalMapListener();
@@ -90,7 +85,6 @@
public void activateStore() {
KryoNamespace.Builder kryoBuilder = new KryoNamespace.Builder()
.register(KryoNamespaces.BASIC)
- //.register(String.class)
.register(java.lang.Class.class)
.register(DataNode.Type.class)
.register(LeafNode.class)
@@ -98,8 +92,10 @@
.register(ResourceId.class)
.register(NodeKey.class)
.register(SchemaId.class)
+ .register(LeafListKey.class)
+ .register(ListKey.class)
+ .register(KeyLeaf.class)
.register(java.util.LinkedHashMap.class);
- //.register(CfgReceiver.InternalDynamicConfigListener.class);
keystore = storageService.<DataNode.Type>documentTreeBuilder()
.withSerializer(Serializer.using(kryoBuilder.build()))
.withName("config-key-store")
@@ -110,11 +106,6 @@
.withName("config-object-store")
.withRelaxedReadConsistency()
.build();
- lstnrStore = storageService.<String, DynamicConfigListener>consistentMultimapBuilder()
- .withSerializer(Serializer.using(kryoBuilder.build()))
- .withName("config-listener-registry")
- .withRelaxedReadConsistency()
- .build();
keystore.addListener(klistener);
objectStore.addListener(olistener);
log.info("DyanmicConfig Store Active");
@@ -137,6 +128,13 @@
public CompletableFuture<Boolean>
addRecursive(ResourceId complete, DataNode node) {
CompletableFuture<Boolean> eventFuture = CompletableFuture.completedFuture(true);
+ //Workaround
+ List<NodeKey> nodeKeyList = complete.nodeKeys();
+ NodeKey f = nodeKeyList.get(0);
+ if (f.schemaId().name().compareTo("/") == 0) {
+ nodeKeyList.remove(0);
+ }
+ //Workaround end
ResourceId path = ResourceIdParser.getParent(complete);
String spath = ResourceIdParser.parseResId(path);
if (spath == null) {
@@ -219,6 +217,13 @@
@Override
public CompletableFuture<DataNode> readNode(ResourceId path, Filter filter) {
CompletableFuture<DataNode> eventFuture = CompletableFuture.completedFuture(null);
+ //Workaround
+ List<NodeKey> nodeKeyList = path.nodeKeys();
+ NodeKey f = nodeKeyList.get(0);
+ if (f.schemaId().name().compareTo("/") == 0) {
+ nodeKeyList.remove(0);
+ }
+ //Workaround end
String spath = ResourceIdParser.parseResId(path);
DocumentPath dpath = DocumentPath.from(spath);
DataNode.Type type = null;
@@ -341,6 +346,13 @@
@Override
public CompletableFuture<Boolean> deleteNodeRecursive(ResourceId path) {
+ //Workaround
+ List<NodeKey> nodeKeyList = path.nodeKeys();
+ NodeKey f = nodeKeyList.get(0);
+ if (f.schemaId().name().compareTo("/") == 0) {
+ nodeKeyList.remove(0);
+ }
+ //Workaround end
String spath = ResourceIdParser.parseResId(path);
DocumentPath dpath = DocumentPath.from(spath);
DataNode.Type type = null;
@@ -357,45 +369,6 @@
}
}
- @Override
- public void addConfigListener(ResourceId path, DynamicConfigListener listener) {
- String lpath = ResourceIdParser.parseResId(path);
- try {
- lstnrStore.put(lpath, listener);
- } catch (ConsistentMapException e) {
- throw new FailedException(e.getCause().getMessage());
- }
- }
-
- @Override
- public void removeConfigListener(ResourceId path, DynamicConfigListener listener) {
- String lpath = ResourceIdParser.parseResId(path);
- try {
- lstnrStore.remove(lpath, listener);
- } catch (ConsistentMapException e) {
- throw new FailedException(e.getCause().getMessage());
- }
- }
-
- @Override
- public Collection<? extends DynamicConfigListener> getConfigListener(ResourceId path) {
- String lpath = ResourceIdParser.parseResId(path);
- try {
- Versioned<Collection<? extends DynamicConfigListener>> ls = lstnrStore.get(lpath);
- if (ls != null) {
- return ls.value();
- } else {
- log.info("STORE: no Listeners!!");
- return null;
- }
- } catch (ConsistentMapException e) {
- //throw new FailedException(e.getCause().getMessage());
- throw new FailedException("getConfigListener failed");
- } catch (NullPointerException e) {
- throw new FailedException(e.getCause().getMessage());
- }
- }
-
public class InternalDocTreeListener implements DocumentTreeListener<DataNode.Type> {
@Override
public void event(DocumentTreeEvent<DataNode.Type> event) {
diff --git a/apps/config/src/main/java/org/onosproject/config/impl/DynamicConfigManager.java b/apps/config/src/main/java/org/onosproject/config/impl/DynamicConfigManager.java
index c79d42a..938734d 100644
--- a/apps/config/src/main/java/org/onosproject/config/impl/DynamicConfigManager.java
+++ b/apps/config/src/main/java/org/onosproject/config/impl/DynamicConfigManager.java
@@ -37,11 +37,8 @@
import org.onosproject.yang.model.DataNode;
import org.onosproject.yang.model.ResourceId;
import org.onosproject.event.AbstractListenerManager;
-import org.onosproject.event.EventDeliveryService;
import org.slf4j.Logger;
-import java.util.Collection;
-
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -57,19 +54,19 @@
private final Logger log = getLogger(getClass());
private final DynamicConfigStoreDelegate storeDelegate = new InternalStoreDelegate();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected EventDeliveryService eventDispatcher;
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DynamicConfigStore store;
@Activate
public void activate() {
store.setDelegate(storeDelegate);
+ eventDispatcher.addSink(DynamicConfigEvent.class, listenerRegistry);
log.info("DynamicConfigService Started");
}
@Deactivate
public void deactivate() {
store.unsetDelegate(storeDelegate);
+ eventDispatcher.removeSink(DynamicConfigEvent.class);
log.info("DynamicConfigService Stopped");
}
@@ -106,16 +103,10 @@
public void replaceNode(ResourceId path, DataNode node) {
throw new FailedException("Not yet implemented");
}
+
public Integer getNumberOfChildren(ResourceId path, Filter filter) {
throw new FailedException("Not yet implemented");
}
- public void addConfigListener(ResourceId path, DynamicConfigListener listener) {
- store.addConfigListener(path, listener);
- }
-
- public void removeConfigListener(ResourceId path, DynamicConfigListener listener) {
- store.removeConfigListener(path, listener);
- }
public void registerHandler(RpcHandler handler, RpcCommand command) {
throw new FailedException("Not yet implemented");
@@ -138,15 +129,7 @@
*/
private class InternalStoreDelegate implements DynamicConfigStoreDelegate {
public void notify(DynamicConfigEvent event) {
- ResourceId path = event.subject();
- Collection<? extends DynamicConfigListener> lstnrs = store.getConfigListener(path);
- if (lstnrs != null) {
- for (DynamicConfigListener l : lstnrs) {
- l.event(event);
- }
- } else {
- log.info("InternalStoreDelegate: no Listeners");
- }
+ post(event);
}
}
}
\ No newline at end of file
diff --git a/apps/netconf/BUCK b/apps/netconf/BUCK
index c619118..f4cc35c 100644
--- a/apps/netconf/BUCK
+++ b/apps/netconf/BUCK
@@ -1,5 +1,6 @@
BUNDLES = [
'//apps/netconf/client:onos-apps-netconf-client',
+ '//apps/netconf/storeadapter:onos-apps-netconf-storeadapter',
]
onos_app (
diff --git a/apps/netconf/storeadapter/BUCK b/apps/netconf/storeadapter/BUCK
new file mode 100644
index 0000000..b58c1d8
--- /dev/null
+++ b/apps/netconf/storeadapter/BUCK
@@ -0,0 +1,26 @@
+COMPILE_DEPS = [
+ '//lib:CORE_DEPS',
+ '//lib:onos-yang-model',
+ '//lib:onos-yang-runtime',
+ '//apps/config:onos-apps-config',
+]
+
+osgi_jar_with_tests (
+ deps = COMPILE_DEPS,
+)
+
+BUNDLES = [
+ '//apps/netconf/client:onos-apps-netconf-client',
+ '//apps/netconf/storeadapter:onos-apps-netconf-storeadapter',
+]
+
+onos_app (
+ app_name = 'org.onosproject.netconf',
+ title = 'NETCONF Application Module',
+ category = 'Utility',
+ url = 'http://onosproject.org',
+ description = """This application provides an interface for monitoring and modifying datastores
+ of NETCONF devices using Yang data. It uses the YangRuntime to serialize outbound
+ messages from Yang into NETCONF and deserialize received messages.""",
+ included_bundles = BUNDLES,
+)
diff --git a/apps/netconf/storeadapter/src/main/java/org/onosproject/netconf/storeadapter/NetConfListener.java b/apps/netconf/storeadapter/src/main/java/org/onosproject/netconf/storeadapter/NetConfListener.java
new file mode 100644
index 0000000..a268c35
--- /dev/null
+++ b/apps/netconf/storeadapter/src/main/java/org/onosproject/netconf/storeadapter/NetConfListener.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.
+ */
+
+package org.onosproject.netconf.storeadapter;
+
+import com.google.common.annotations.Beta;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.config.DynamicConfigEvent;
+import org.onosproject.config.DynamicConfigListener;
+import org.onosproject.config.DynamicConfigService;
+import org.onosproject.config.Filter;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.ResourceId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Beta
+@Component(immediate = true)
+public class NetConfListener implements DynamicConfigListener {
+
+ private static final Logger log = LoggerFactory.getLogger(NetConfListener.class);
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DynamicConfigService cfgServcie;
+ public static final String DEVNMSPACE = "namespace1";
+
+ private ResourceId resId = new ResourceId.Builder()
+ .addBranchPointSchema("device", DEVNMSPACE )
+ .build();
+ @Activate
+ protected void activate() {
+ cfgServcie.addListener(this);
+ log.info("NetConfListener Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ cfgServcie.removeListener(this);
+ log.info("NetConfListener Stopped");
+ }
+
+ public boolean isRelevant(DynamicConfigEvent event) {
+ if (event.subject().equals(resId)) {
+ log.info("isRelevant {} = {}", resId, event.subject());
+ return true;
+ } else {
+ log.info("isRelevant {} != {}", resId, event.subject());
+ return false;
+ }
+ }
+
+ public void event(DynamicConfigEvent event) {
+ if (!isRelevant(event)) {
+ log.info("event is not relevanyt!!!! {} != {}", resId, event.subject());
+ return;
+ }
+ switch (event.type()) {
+ case NODE_ADDED:
+ log.info("NetConfListener: RXD NODE_ADDED event");
+ Filter filt = new Filter();
+ DataNode node = cfgServcie.readNode(event.subject(), filt);
+ //call netconf passive
+ break;
+ case NODE_UPDATED:
+ log.info("NetConfListener: RXD NODE_UPDATED event");
+ break;
+ case NODE_REPLACED:
+ log.info("NetConfListener: RXD NODE_REPLACED event");
+ break;
+ case NODE_DELETED:
+ log.info("NetConfListener: RXD NODE_DELETED event");
+ break;
+ case UNKNOWN_OPRN:
+ default:
+ log.warn("NetConfListener: unknown event: {}", event.type());
+ break;
+ }
+ }
+}
\ No newline at end of file