From f31e292087e56b5171dcdfc83bbd81462236977d Mon Sep 17 00:00:00 2001 From: Maros Marsalek 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 --- .../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] +---- + + io.fd.honeycomb + notification-api + ${honeycomb.infra.version} + +---- + +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> 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] +---- + + + + + io.fd.honeycomb.common + minimal-distribution-parent + {project-version} + + + 4.0.0 + io.fd.honeycomb.tutorial + sample-distribution + {project-version} + + + -Xms128m -Xmx128m + io.fd.honeycomb.tutorial.Main + {project-version} + {project-version} + + + + + + maven-compiler-plugin + + + org.codehaus.gmaven + groovy-maven-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-dependency-plugin + + + maven-assembly-plugin + + + + + + + + io.fd.honeycomb.tutorial + sample-plugin-impl + ${interfaces.mapping.version} + + + + io.fd.honeycomb + minimal-distribution + ${honeycomb.min.distro.version} + + + + +---- + +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 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] +---- + sample-distribution +---- + +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] +---- + + io.fd.honeycomb.samples.interfaces + interfaces-mapping + ${interfaces.mapping.version} + +---- + +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