From 5f1baedefebd2ee3c5003957a3441ca54ff3380e Mon Sep 17 00:00:00 2001
From: Maros Marsalek <mmarsale@cisco.com>
Date: Fri, 14 Oct 2016 14:09:02 +0200
Subject: Release notes

- migrated from wiki
- updated versions to current version

- notes are built with each regular build
- notes root is at: target/generated-docs/release_notes.html
- notes are inlined into site

Change-Id: I581898988f41f77f5eafb20e9e61e08f09908b98
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
---
 .../devel_guide/devel_plugin_tutorial.adoc         | 364 +++++++++++++++++++++
 1 file changed, 364 insertions(+)
 create mode 100644 release-notes/src/main/asciidoc/devel_guide/devel_plugin_tutorial.adoc

(limited to 'release-notes/src/main/asciidoc/devel_guide/devel_plugin_tutorial.adoc')

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
+
-- 
cgit 1.2.3-korg

