summaryrefslogtreecommitdiffstats
path: root/release-notes/src/main/asciidoc/devel_guide/devel_plugin_tutorial.adoc
diff options
context:
space:
mode:
Diffstat (limited to 'release-notes/src/main/asciidoc/devel_guide/devel_plugin_tutorial.adoc')
-rw-r--r--release-notes/src/main/asciidoc/devel_guide/devel_plugin_tutorial.adoc364
1 files changed, 364 insertions, 0 deletions
diff --git a/release-notes/src/main/asciidoc/devel_guide/devel_plugin_tutorial.adoc b/release-notes/src/main/asciidoc/devel_guide/devel_plugin_tutorial.adoc
new file mode 100644
index 000000000..496ec55d1
--- /dev/null
+++ b/release-notes/src/main/asciidoc/devel_guide/devel_plugin_tutorial.adoc
@@ -0,0 +1,364 @@
+= Developing generic plugins
+
+link:release_notes.html[< Home]
+
+Since Honeycomb is a generic agent. Any plugin (translation code) can be injected into the framework, creating a custom agent providing RESTCONF/NETCONF northbound interfaces out-of-box.
+
+== Developing plugin code
+
+Honeycomb provides a maven archetype to generate a plugin skeleton. To use that archetype, run maven:
+
+ mvn -X archetype:generate -DarchetypeGroupId=io.fd.honeycomb.tools -DarchetypeArtifactId=honeycomb-plugin-archetype -DarchetypeVersion={project-version}
+
+Fill in the parameters e.g.
+
+ groupId: io.fd.honeycomb.tutorial
+ artifactId: sample-plugin
+ version: {project-version}
+ package: io.fd.honeycomb.tutorial
+
+And following structure should be created:
+
+[source]
+----
+sample-plugin/
+├── pom.xml
+├── sample-plugin-api
+│ ├── pom.xml
+│ └── src
+│ └── main
+│ ├── java
+│ └── yang
+│ └── sample-plugin.yang
+└── sample-plugin-impl
+ ├── pom.xml
+ ├── Readme.adoc
+ └── src
+ ├── main
+ │ └── java
+ │ └── io
+ │ └── fd
+ │ └── honeycomb
+ │ └── tutorial
+ │ ├── CrudService.java
+ │ ├── ElementCrudService.java
+ │ ├── init
+ │ │ └── ConfigDataInitializer.java
+ │ ├── ModuleConfiguration.java
+ │ ├── Module.java
+ │ ├── read
+ │ │ ├── ElementStateCustomizer.java
+ │ │ └── ModuleStateReaderFactory.java
+ │ └── write
+ │ ├── ElementCustomizer.java
+ │ └── ModuleWriterFactory.java
+ └── test
+ └── java
+----
+
+There are 2 modules:
+
+* sample-plugin-api - Contains YANG models and generates Java APIs from the models.
+* sample-plugin-impl - Contains: Readers, Writers, Initializers, Notification producers (not yet), Configuration and Wiring.
+
+There is plenty of comments within the code, so its is advised to import the code into an IDE and take a look around.
+
+*The archetype generates a plugin that is fully working right from the start*. Since it contains all the components necessary, works on a sample yang model and provides some sample values.
+
+== Building the code
+
+To build the code, just execute maven:
+
+ mvn clean install
+
+And that's it. This is a working Honeycomb plugin.
+
+== Adding notifications
+
+No notification producer is generated by the archetype, but it is pretty straightforward to add one.
+
+First, the notification has to be defined in YANG (sample-plugin-api/src/main/yang/sample-plugin.yang) e.g.
+
+[source,yang]
+----
+notification sample-notification {
+ leaf content {
+ type string;
+ }
+}
+----
+
+Now rebuild the plugin to generate new APIs for our notification.
+
+Next part is implementing the Notification producer. First thing to do is to add a dependency on notification-api, since it's not included by default. Update sample-plugin-impl's pom file with:
+
+[source,xml]
+----
+<dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>notification-api</artifactId>
+ <version>${honeycomb.infra.version}</version>
+</dependency>
+----
+
+Now, the producer code can be added:
+
+[source,java]
+----
+package io.fd.honeycomb.tutorial.notif;
+
+import io.fd.honeycomb.notification.ManagedNotificationProducer;
+import io.fd.honeycomb.notification.NotificationCollector;
+import java.util.Collection;
+import java.util.Collections;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.sample.plugin.rev160918.SampleNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.sample.plugin.rev160918.SampleNotificationBuilder;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Notification producer for sample plugin
+ */
+public class SampleNotificationProducer implements ManagedNotificationProducer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SampleNotificationProducer.class);
+
+ private Thread thread;
+
+ @Override
+ public void start(@Nonnull final NotificationCollector collector) {
+ LOG.info("Starting notification stream for interfaces");
+
+ // Simulating notification producer
+ thread = new Thread(() -> {
+ while(true) {
+ if (Thread.currentThread().isInterrupted()) {
+ return;
+ }
+
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ break;
+ }
+
+ final SampleNotification notification = new SampleNotificationBuilder()
+ .setContent("Hello world " + System.currentTimeMillis())
+ .build();
+ LOG.info("Emitting notification: {}", notification);
+ collector.onNotification(notification);
+ }
+ }, "NotificationProducer");
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ @Override
+ public void stop() {
+ if(thread != null) {
+ thread.interrupt();
+ }
+ }
+
+ @Nonnull
+ @Override
+ public Collection<Class<? extends Notification>> getNotificationTypes() {
+ // Producing only this single type of notification
+ return Collections.singleton(SampleNotification.class);
+ }
+
+ @Override
+ public void close() throws Exception {
+ stop();
+ }
+}
+----
+
+This is placed sample-plugin/sample-plugin-impl/src/main/java/io/fd/honeycomb/tutorial/notif/SampleNotificationProducer.java.
+
+NOTE: This is a sample producer, that creates a thread to periodically emit a sample notification
+
+Now it needs to be exposed from the plugin. The configure method in Module class needs to be updated with:
+
+[source,java]
+----
+ Multibinder.newSetBinder(binder(), ManagedNotificationProducer.class).addBinding().to(SampleNotificationProducer.class);
+----
+
+Plugin needs to be rebuilt, but that's it for notification producers.
+
+== Creating custom distribution
+
+The plugin is now ready to have a Honeycomb distribution for it. This section will provides information on how to create a custom Honeycomb distribution.
+
+A new maven module needs to be created. So in sample-plugin folder:
+
+ mkdir sample-distribution
+ cd sample-distribution
+ mkdir -p src/main/java/io/fd/honeycomb/tutorial
+
+Then create the pom:
+
+[source,xml]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>io.fd.honeycomb.common</groupId>
+ <artifactId>minimal-distribution-parent</artifactId>
+ <version>{project-version}</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>io.fd.honeycomb.tutorial</groupId>
+ <artifactId>sample-distribution</artifactId>
+ <version>{project-version}</version>
+
+ <properties>
+ <exec.parameters>-Xms128m -Xmx128m</exec.parameters>
+ <main.class>io.fd.honeycomb.tutorial.Main</main.class>
+ <interfaces.mapping.version>{project-version}</interfaces.mapping.version>
+ <honeycomb.min.distro.version>{project-version}</honeycomb.min.distro.version>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.gmaven</groupId>
+ <artifactId>groovy-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <!-- Dependency on sample plugin -->
+ <dependency>
+ <groupId>io.fd.honeycomb.tutorial</groupId>
+ <artifactId>sample-plugin-impl</artifactId>
+ <version>${interfaces.mapping.version}</version>
+ </dependency>
+ <!-- Dependency on distribution base -->
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>minimal-distribution</artifactId>
+ <version>${honeycomb.min.distro.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
+----
+
+Now, Main class has to be added in folder src/main/java/io/fd/honeycomb/tutorial:
+
+[source,java]
+----
+package io.fd.honeycomb.tutorial;
+
+import com.google.common.collect.Lists;
+import com.google.inject.Module;
+import java.util.List;
+
+public class Main {
+
+ public static void main(String[] args) {
+ final List<Module> sampleModules = Lists.newArrayList(io.fd.honeycomb.infra.distro.Main.BASE_MODULES);
+
+ sampleModules.add(new io.fd.honeycomb.tutorial.Module());
+
+ io.fd.honeycomb.infra.distro.Main.init(sampleModules);
+ }
+}
+----
+
+Last thing to do is to update sample-plugin/pom.xml with:
+[source,xml]
+----
+ <module>sample-distribution</module>
+----
+
+Another rebuild and the distribution should be created in sample-distribution/target.
+
+=== Adding existing plugins to the mix
+
+In previous section, a custom Honeycomb distribution was created. This section will show how to add existing plugins to the new distribution.
+
+So in order to add another existing sample (sample interface plugin from Honeycomb) into the distribution, update the sample-plugin/sample-distribution/pom.xml with:
+
+[source,xml]
+----
+<dependency>
+ <groupId>io.fd.honeycomb.samples.interfaces</groupId>
+ <artifactId>interfaces-mapping</artifactId>
+ <version>${interfaces.mapping.version}</version>
+</dependency>
+----
+
+Now in main, add this line:
+
+[source,java]
+----
+ sampleModules.add(new SampleInterfaceModule());
+----
+
+That's it, just rebuild.
+
+== Verifying distribution
+The distribution with this sample plugin and sample interface plugin is now available and can be tested.
+
+Distribution can now be found in sample-plugin/sample-distribution/target as:
+
+zip archive
+tar.gz archive
+folder
+The distribution can be started by:
+
+ sudo ./sample-distribution/target/sample-distribution-{project-version}-hc/sample-distribution-{project-version}/honeycomb
+Note: honeycomb-start script is the background alternative
+
+Honeycomb will display following message in the log:
+
+ 2016-09-02 13:20:30.424 CEST [main] INFO io.fd.honeycomb.infra.distro.Main - Honeycomb started successfully!
+
+and that means Honeycomb was started successfully.
+
+=== Testing over RESTCONF
+Reading sample-plugin operational data:
+
+ curl -u admin:admin http://localhost:8181/restconf/operational/sample-plugin:sample-plugin-state
+
+Writing sample-plugin operational data:
+
+ Not possible from YANG spec. Operational data is only for read.
+
+Writing sample-plugin config data:
+
+ curl -H 'Content-Type: application/json' -H 'Accept: application/json' -u admin:admin -X PUT -d '{"sample-plugin":{"element":[{"id":10,"description":"This is a example of loaded data"}]}}' http://localhost:8181/restconf/config/sample-plugin:sample-plugin
+
+Reading sample-plugin config data:
+
+ curl -u admin:admin http://localhost:8181/restconf/config/sample-plugin:sample-plugin
+
+=== Testing over NETCONF
+Netconf testing guide including Notifications, can be found in link:user_running_honeycomb.html[User guide]
+
+== Full working example
+Full working example on github: https://github.com/marosmars/honeycomb-samples
+