专栏首页SDNLABOpenDaylight Carbon二次开发实用指南

OpenDaylight Carbon二次开发实用指南

通过本文你将知道:

  1. Maven Archetype的基本原理以及如何使用Maven Archetype生成适用于不同版本的ODL子项目。
  2. 本文将着重讲解cli命令开发,以及Carbon Release中新引入的Blueprint的一些基本知识。OpenDaylight Carbon Release中模块运行的大致流程以及对于api和impl的开发可以参考ODL碳版本模块开发及流程梳理还有ODL controller官方开发指南(它对DataStore的描述相当不错)。
  3. 如何将编写好的应用添加到一个正在运行的OpenDaylight控制器中。

Maven Archetype的原理与其在OpenDaylight中的应用

Archetype[1]是一个Maven项目模板的工具。它提供了一种快速生成一致的Maven项目的方法。事实上OpenDaylight的Archetype存储在controller项目中。大家可以从github或者git.opendaylight.org中访问controller项目,并找到Archetype对应的位置。在作者编写本篇教程时,使用下述URI下载的Archetype源码(建议使用git clone下载该源码,方便后面使用git checkout切换源码版本)。

1

https://github.com/opendaylight/controller/tree/master/opendaylight/archetypes

让我们看看Archetype的源文件,它与普通的文件并无很大区别,但它包含${package}、${classPrefix}等一些可被替换的参数。这些参数可以在用户利用Archetype生成自己的项目,使用mvn archetype:generate命令时被指定。

https://github.com/opendaylight/controller/blob/release/carbon-sr1/opendaylight/archetypes/opendaylight-startup/src/main/resources/archetype-resources/impl/src/main/java/__packageInPathFormat__/impl/__classPrefix__Provider.java #set( $symbol_pound = '#' )#set( $symbol_dollar = '$' )#set( $symbol_escape = '\' )/* * Copyright © ${copyrightYear} ${copyright} and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */package ${package}.impl;import org.opendaylight.controller.md.sal.binding.api.DataBroker;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class ${classPrefix}Provider { private static final Logger LOG = LoggerFactory.getLogger(${classPrefix}Provider.class); private final DataBroker dataBroker; public ${classPrefix}Provider(final DataBroker dataBroker) { this.dataBroker = dataBroker; } /** * Method called when the blueprint container is created. */ public void init() { LOG.info("${classPrefix}Provider Session Initiated"); } /** * Method called when the blueprint container is destroyed. */ public void close() { LOG.info("${classPrefix}Provider Closed"); }}

对于开发过之前版本的OpenDaylight用户而言,这些函数应该很眼熟,只不过原来的onSessionInitiated()变成init()。Carbon Release中使用Blueprint作为依赖注入Dependency Injection框架,关于Blueprint的细节详见第二章。

:Maven仓库[2]分为本地仓库远端仓库。之前的很多教程是直接从OpenDaylight Maven远端仓库(往往是一个通过一个URI指定)上拉取Archetype的artifact(Maven仓库里的货物可以被称为artifact或者project)然后生成自己的项目架构。但这个URI可能在作者撰写教程的时候存在,当OpenDaylight有了新的小版本更新后这个URI就失效了。因此本教程将说明如何利用OpenDaylight Archetype源码以及Maven本地仓库,生成任意版本的OpenDaylight子项目

既然有仓库,那么里面一定有货物(project或者叫做artifact),而且有不止一件货物。为了区分货物,每件货物都需要有自己的ID。而这个ID由groupId、artifactId、version构成。

<groupId>org.opendaylight.controller</groupId><artifactId>opendaylight-startup-archetype</artifactId><version>1.3.1-Carbon</version>

这些属性在命令mvn archetype:generate中用来指定即将要生成的项目是依赖于哪个Archetype的artifact。

为了使用Archectype,需要先将Archetype安装(maven install)到本地Maven仓库(在Ubuntu或者macOS下默认的本地Maven仓库路径为~/.m2)。具体操作如下:

1. 将Archetype的源码编译安装到本地仓库(在本地仓库生成了一个该Archetype对应的artifact),以下命令运行在控制台(Terminal)。

# 下载controller项目git clone https://github.com/opendaylight/controller.git# 进入controller目录cd controller# 切换到carbon-sr1版本git checkout release/carbon-sr1# 进入Archetype/opendaylight-startup目录cd opendaylight/archetypes/opendaylight-startup/# 将Archetype安装到本地仓库mvn clean install

:其他版本格式均为”release/大版本号-小版本号”或者”release/大版本号”,大版本号为某一个元素全拼,小版本号为sr1、sr2等等。

2. 使用mvn archetype:generate命令,从本地仓库中获取安装过的Archetype的artifact,生成自己所需的子项目。以下命令运行在控制台(Terminal)。其中带有Darchetype的行代表即将生成的项目依赖于哪些已经存在仓库的Archetype的artifact,该信息可以在上文执行mvn clean install的目录下的pom.xml文件中得到。DgroupId和DartifactId是即将生成的项目的groupId和artifactId。关于groupId、artifactId和version的命名规范请见[3]。version可以不填写,默认的version为0.1.0-SNAPSHOT。

mvn archetype:generate -B \ -DarchetypeGroupId=org.opendaylight.controller \ -DarchetypeArtifactId=opendaylight-startup-archetype \ -DarchetypeVersion=1.3.1-Carbon \ -DgroupId=snlab \ -DartifactId=helloworld \ -DclassPrefix=HelloWorld \ -Dcopyright=snlab \ -DcopyrightYear=2017

注:\前面的空格不要漏掉!

3. 观察与编译依照OpenDaylight Carbon SR1 startup模板生成的项目helloworld

# 进入helloworld目录cd helloworld# 查看该目录下的内容,对于该目录下的内容详见第二章ll# 编译helloword,并将相应artifact安装到本地Maven仓库mvn clean install

因此,你应该了解Maven Archtype生成的原理以及如何生成任意OpenDaylight版本的子项目。

Opendaylight Carbon release cli开发以及Blueprint基础知识介绍

OpenDaylight Carbon release的利用Archetype作为模板生成后的项目结构如下:

api/artifacts/cli/features/impl/it/karaf/src/

cli目录是Carbon版本里新出现的目录,它用于方便快捷地开发Karaf cli命令。它包含api、commands和impl三个子目录。api中主要是定义Karaf命令方法签名和Javadoc。在impl中,我们可以利用Java Annotation快速的定义了命令的格式,快速获得命令解析功能,以及实现相应命令对应的输出。具体而言,cli子模块的目录结构如下:

├── pom.xml└── src └── main ├── java │ └── snlab │ └── cli │ ├── api │ │ └── HelloworldCliCommands.java │ ├── commands │ │ └── HelloworldCliTestCommand.java │ └── impl │ └── HelloworldCliCommandsImpl.java └── resources └── org └── opendaylight └── blueprint └── cli-blueprint.xml

逐个查看各个java文件。 HelloworldCliCommands.java中定义了一个我们想要实现的接口方法。

1

Object testCommand(Object testArgument);

HelloworldCliTestCommand.java中定义了这个命令的格式,以及对应输出应该如何处理。例如本示例中定义了一个command,它以”test-command”开头,并且接受-tA的参数(在Karaf控制台中使用这个command的例子opendaylight-user@root> test-command -tA 123)。参考文献[6]中给出了更加详细的介绍。

// HelloworldCliTestCommand.java/** * This is an example class. The class name can be renamed to match the command implementation that it will invoke. * Specify command details by updating the fields in the Command annotation below. */@Command(name = "test-command", scope = "add the scope of the command, usually project name", description = "add a description for the command")public class HelloworldCliTestCommand extends AbstractAction { private static final Logger LOG = LoggerFactory.getLogger(HelloworldCliTestCommand.class); protected final HelloworldCliCommands service; public HelloworldCliTestCommand(final HelloworldCliCommands service) { this.service = service; } /** * Add the arguments required by the command. * Any number of arguments can be added using the Option annotation * The below argument is just an example and should be changed as per your requirements */ @Option(name = "-tA", aliases = { "--testArgument" }, description = "test command argument", required = true, multiValued = false) private Object testArgument; @Override protected Object doExecute() throws Exception { /** * Invoke commannd implementation here using the service instance. * Implement how you want the output of the command to be displayed. * Below is just an example. */ final String testMessage = (String) service.testCommand(testArgument); return testMessage; }}

HelloworldCliCommandsImpl继承了HelloworldCliCommands,并实现了testCommand方法。

// HelloworldCliCommandsImpl.javapublic class HelloworldCliCommandsImpl implements HelloworldCliCommands { private static final Logger LOG = LoggerFactory.getLogger(HelloworldCliCommandsImpl.class); private final DataBroker dataBroker; public HelloworldCliCommandsImpl(final DataBroker db) { this.dataBroker = db; LOG.info("HelloworldCliCommandImpl initialized"); } @Override public Object testCommand(Object testArgument) { return "This is a test implementation of test-command"; }}

上面列出了代码实现的部分,下面将介绍这个模块是如何被加载的。这与helloworld/impl/是一样的,使用Blueprint做Denpendency Injection。

Blueprint是一个为OSGi容器设计的Dependency Injection系统[4, 5]。Karaf包含了Apache Aries Blueprint的实现以及它的基本特色。

当一个bundle包含一个或者多少Blueprint XML文件时,会被认为是Blueprint bundles。这些Blueprint XML位于OSGI-INF/blueprint/目录下。Blueprint使用一个extender bundle来监视其他bundle的状态。一旦extender决定一个bundle是Blueprint bundle,它就为这个bundle创建一个Blueprint Container。

Bluepinrt Container负责以下的事情:

  • 解析Blueprint XML文件
  • 初始化组件
  • 将组件连接在一起
  • 注册services
  • 查找service reference

Blueprint的配置文件会被用来创建命令并将其注册到OSGi注册表中,这使得命令可以用于Karaf的控制台。cli模块的Blueprint xml文件位于cli/src/main/resources/下。reference标签让我们的子模块获取到了ODL本身最重要的模块DataBroker,通过它我们能够读写ODL中的DataStore。id为cliCommandsImpl的标签bean,告诉系统cliCommandsImpl这个模块需要从ODL中获取dataBroker。service标签告诉系统cliCommandsImpl这个bean是一个OSGi service。command-bundle标签是cli中相对最重要的,它把Karaf控制台输入的命令,前端处理类HelloworldCliTestCommands,以及对应的后端处理的类cliCommandsImpl联系到一起。

<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.controller.md.sal.binding.api.DataBroker" odl:type="default" /> <bean id="cliCommandsImpl" class="snlab.cli.impl.HelloworldCliCommandsImpl"> <argument ref="dataBroker" /> </bean> <service ref="cliCommandsImpl" odl:type="default" interface="snlab.cli.api.HelloworldCliCommands" /> <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0"> <command name="test-command"> <action class="snlab.cli.commands.HelloworldCliTestCommand"> <argument ref="cliCommandsImpl"/> </action> </command> </command-bundle></blueprint>

OpenDaylight Karaf目录结构以及向运行中的Karaf载入外部Kar包

OpenDaylight Karaf的目录包含以下几个部分,具体每个部分的配置选项的含义,可以直接进入对应文件夹,查看对应文件的注释部分:

/bin:包含了开始、停止、登陆等脚本。/etc:配置文件/data:工作目录 /data/cache: OSGi框架bundle的缓存 /data/generated-bundles: 部署者使用的临时文件 /data/log: log文件/deploy:热部署目录/lib:包含类/system:OSGi bundles仓库

1. 下载OpenDaylight控制器,本例中为Carbon SR1。

1

https://www.opendaylight.org/technical-community/getting-started-for-developers/downloads-and-documentation

2. 解压后,进入./distribution-karaf-0.6.1-Carbon/etc目录,在文件org.ops4j.pax.url.mvn.cfg文件,添加一行:

org.ops4j.pax.url.mvn.defaultRepositories=\ file:${karaf.home}/${karaf.default.repository}@id=system.repository@snapshots,\ file:${karaf.data}/kar@id=kar.repository@multi@snapshots

3. 启动karaf,并在karaf中执行以下命令,将位于helloworld/features/target下的kar包安装到正在运行的OpenDaylight控制器上。

# 安装自己的编译生成的kar包到控制器。kar包的位置位于helloworld/features/target下opendaylight-user@root&gt; kar:install file:/Users/shawn/Develop/alto-sdnlab/helloworld/features/target/helloworld-features-0.1.0-SNAPSHOT.kar # 可以看到我们的项目helloworld已经被加入到正在运行的ODL Carbon SR1控制器上opendaylight-user@root&gt; feature:list | grep helloodl-helloworld-api | 0.1.0-SNAPSHOT | x | odl-helloworld-0.1.0-SNAPSHOT | OpenDaylight :: helloworld :: api odl-helloworld | 0.1.0-SNAPSHOT | x | odl-helloworld-0.1.0-SNAPSHOT | OpenDaylight :: helloworld odl-helloworld-rest | 0.1.0-SNAPSHOT | x | odl-helloworld-0.1.0-SNAPSHOT | OpenDaylight :: helloworld :: REST odl-helloworld-ui | 0.1.0-SNAPSHOT | x | odl-helloworld-0.1.0-SNAPSHOT | OpenDaylight :: helloworld :: UI odl-helloworld-cli | 0.1.0-SNAPSHOT | x | odl-helloworld-0.1.0-SNAPSHOT | OpenDaylight :: helloworld :: CLI # 查看我们的项目helloworld中打印的log信息opendaylight-user@root&gt;log:display | grep hello......2017-09-22 20:21:29,543 | INFO | l for user karaf | helloworldCliCommandsImpl | 297 - snlab.helloworld-cli - 0.1.0.SNAPSHOT | helloworldCliCommandImpl initialized......

写在最后

我相信乐于分享能够使得大家共同进步!想要了解更多最前沿SDN技术相关的内容(相关论文、相关软件)可以访问我们实验室全体成员共同收集的awesome-sdn列表:https://github.com/snlab-freedom/awesome-sdn 。欢迎各位乐于分享的小伙伴帮助我们共同完善这份列表!

参考文献

[1] https://maven.apache.org/guides/mini/guide-creating-archetypes.html

[2] https://maven.apache.org/guides/introduction/introduction-to-repositories.html

[3] https://maven.apache.org/guides/mini/guide-naming-conventions.html

[4] https://wiki.opendaylight.org/view/Using_Blueprint

[5] http://aries.apache.org/modules/blueprint.html

[6] https://karaf.apache.org/manual/latest-2.x/developers-guide/extending-console.html

本文分享自微信公众号 - SDNLAB(SDNLAB),作者:帅帅的

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-09-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【培训】Barefoot Academy – P4实战特训营(第二期)

    P4凭借着网络可编程能力从上到下的渗透,打破了硬件设备对数据转发平面的限制,让数据包的解析和转发流程也能通过编程控制,使其网络更加简单、快速和可编程,全面向用户...

    SDNLAB
  • 【培训报名倒计时10天】Barefoot Academy – P4实战特训营(第二期)

    P4凭借着网络可编程能力从上到下的渗透,打破了硬件设备对数据转发平面的限制,让数据包的解析和转发流程也能通过编程控制,使其网络更加简单、快速和可编程,全面向用户...

    SDNLAB
  • P4编程理论与实践——理论篇

    由于对SDN充满着兴趣,在学习了一段时间OpenFlow之后,一次偶然的机会接触到了P4。P4可以实现很多新的Idea,但是无奈于国内的实践资料太少了(有些资料...

    SDNLAB
  • WordPress的Robots协议怎么写?附最新Robots.txt文件下载

    最近我发现搜索引擎收录了很多“夏末浅笑博客”的重复页面,当然了这跟我前一段时间,将站点根目录下的Robots.txt文件删除掉有直接的关系,Robots.txt...

    夏末浅笑
  • Cobalt Strike 上线微信提醒

    [Server酱]英文名[ServerChan],是一款"程序员"和"服务器"之间的通信软件.

    洛米唯熊
  • RocketMQ一次延迟消息故障排查【实战笔记】

    RocketMQ社区版本支持18个延迟级别,每个级别在设定的时间都被会消费者准确消费到。为此也专门测试过消费的间隔是不是准确,测试结果显示很准确。然而,如此准确...

    瓜农老梁
  • Sketchflow for Windows Phone 7

    这篇文章小试Sketchflow for Windows Phone 7 简要的介绍了Sketchflow for Windows Phone 7,这里是我主要...

    张善友
  • Windows 8.1 应用再出发 - 几种常用控件

    本篇为大家简单介绍Windows 商店应用中控件的用法,为方便讲解,我们在文本控件和按钮控件这两类中分别挑选有代表性的控件进行详细说明。 1. 文本控件 (1)...

    Shao Meng
  • 关于java连接mysql数据库的几个问题的解决方法。

    今天就为了连接下数据库获取信息来提供给ListView使用,搞了足足5小时。 出现的问题有:       第一个是,DriverManager.getConne...

    林冠宏-指尖下的幽灵
  • “智慧方案”改变生活 腾讯T派移动互联网创新创业大赛赛题方向解析

    2015年度腾讯T派移动互联网创新创业大赛已于近期拉开序幕,除了吸引了各高校在校生的关注,其三大命题方向也引发了大家的思考,其中“智慧方案”更是极具现实意义,让...

    腾讯高校合作

扫码关注云+社区

领取腾讯云代金券