在OpenDayLight控制器上开发Bundle
odl远端仓库把startup project删除了。这个教程已经不再适用了。
基于OpendayLight官网上的这篇文档翻译修改而来:Developing Apps on the OpenDaylight controller
本文档适用于boron版本。其他版本不一定适用。
综述
本文档旨在指导如何在ODL控制器上开发应用。本文档包含以下内容:
1. 创建一个简单的示例程序Hello World
;
2. 启动ODL控制器;
3. 在Hello World
测试简单的Remote Procedure Call(RPC)
。
基础环境
本文档需要以下基础开发环境:
- Maven 3.1.1 或更新的版本
- JDK 7/8
- 合适的Maven settings.xml
。可以通过一下途径获得默认的OpenDaylight settings.xml
cp -n ~/.m2/settings.xml{,.orig} ; \wget -q -O - https://raw.githubusercontent.com/opendaylight/odlparent/stable/boron/settings.xml > ~/.m2/settings.xml
在除Linux和Mac OS X以外的环境中,你需要修改上诉命令中maven的本地仓库地址~/.m2/repository
构建一个Example模块
按以下步骤构建:
1. 从Maven远端仓库中拉取一个初始工程。(第一次拉取的时候需要一定的时间)
“`
mvn archetype:generate -DarchetypeGroupId=org.opendaylight.controller -DarchetypeArtifactId=opendaylight-startup-archetype \
-DarchetypeRepository=https://nexus.opendaylight.org/content/repositories/public/ \
-DarchetypeCatalog=https://nexus.opendaylight.org/content/repositories/public/archetype-catalog.xml
```
在国内,由于墙的缘故,你可能需要设置代理才能较快的下载工程。设置代理的参数如下:
```
-DsocksProxyHost=YourProxyHost -DsocksProxyPort=YourProxyPort
```
此外你还可以使用多线程编译,跳过生成文档,跳过测试来加快速度:
```
-T 1C -D maven.javadoc.skip=true -DskipTests
```
2. 使用如下值来初始化工程:
Define value for property 'groupId': : org.opendaylight.example
Define value for property 'artifactId': : example
Define value for property 'version': 1.0-SNAPSHOT: : 1.0.0-SNAPSHOT
Define value for property 'package': org.opendaylight.example: :
Define value for property 'classPrefix': : ${artifactId.substring(0,1).toUpperCase()}${artifactId.substring(1)}
Define value for property 'copyright': : Copyright (c) 2015 Yoyodyne, Inc.
其中,version
,package
,classPrefix
都会默认填写,直接回车就行。
3. 完成步骤1,2后,可以看到一个example
文件夹。可以看到如下目录结构。
```
${artifactId}/
example/
cd example/
api/
artifacts/
features/
impl/
karaf/
pom.xml
```
4. 构建示例工程。
注意,这个可能需要耗费一定的时间,你可以使用1中提到的maven参数来提升编译速度。
mvn clean install
5. 启动ODL控制器。
cd karaf/target/assembly/bin
ls
./karaf
6. 等待直至启动完毕出现以下命令行。可能需要等一段时间,这个时间和你电脑配置有关。
opendaylight-user@root>
7. 查看日志,确认example
模块被正常加载。
log:display | grep Example
8. 关闭ODL控制器。
shutdown -f
定义一个简单的`Hello World
RPC
从maven远端仓库拉取初始工程。
mvn archetype:generate -DarchetypeGroupId=org.opendaylight.controller -DarchetypeArtifactId=opendaylight-startup-archetype \ -DarchetypeRepository=http://nexus.opendaylight.org/content/repositories/opendaylight.release/ \ -DarchetypeCatalog=http://nexus.opendaylight.org/content/repositories/opendaylight.release/archetype-catalog.xml
这里需要注意,原文中使用的是
snapshot
,而使用snapshot
会出现无法编译通过的问题。本文中使用release
版本且目前的maven远端仓库release
版本是boron
。使用如下值来初始化工程:
Define value for property 'groupId': : org.opendaylight.hello Define value for property 'artifactId': : hello Define value for property 'version': 1.0-SNAPSHOT: : 1.0.0-SNAPSHOT Define value for property 'package': org.opendaylight.hello: : Define value for property 'classPrefix': : ${artifactId.substring(0,1).toUpperCase()}${artifactId.substring(1)} Define value for property 'copyright': : Copyright (c) 2015 Yoyodyne, Inc.
其中,
version
,package
,classPrefix
都会默认填写,直接回车就行。查看
hello
工程。cd hello/ ls -1 api artifacts features impl karaf pom.xml
构建
Hello
工程。mvn clean install
同样,可以利用之前提到的参数来提升编译构建速度。
启动ODL控制器。
cd karaf/target/assembly/bin ls ./karaf
- 等待直至启动完毕出现以下命令行。可能需要等一段时间,这个时间和你电脑配置有关。
opendaylight-user@root>
- 查看日志,确认
Hello
模块被正常加载。
log:display | grep Hello
关闭ODL控制器。
shutdown -f
返回到
Hello
目录:cd ../../../../
- 可以通过查看
Hello
模块的实现来了解7中的日志从何而来,模块实现源文件路径如下:
impl/src/main/java/org/opendaylight/hello/impl/HelloProvider.java
- 可以使用
HelloProvider.onSessionInitiate
方法来添加自己的实现。
@Override
public void onSessionInitiated(ProviderContext session) {
LOG.info("HelloProvider Session Initiated");
}
添加一个简单的HelloWorld
RPC API
修改YANG文件。
vi api/src/main/yang/hello.yang
修改为如下文件,通过修改该文件来定义
hello-world
RPC:module hello { yang-version 1; namespace "urn:opendaylight:params:xml:ns:yang:hello"; prefix "hello"; revision "2015-01-05" { description "Initial revision of hello model"; } rpc hello-world { input { leaf name { type string; } } output { leaf greating { type string; } } } }
- 返回到
hello/api
目录并构建你的API:
cd ../../../
mvn clean install
实现HelloWorld
RPC API
- 定义
HelloService
,该服务会被HelloWorld
API调用。
cd ../impl/src/main/java/org/opendaylight/hello/impl/
创建
HelloWorldImpl.java
文件,添加如下代码:/* * Copyright © 2016 Cisco Systems 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 org.opendaylight.hello.impl; import java.util.concurrent.Future; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloService; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldOutputBuilder; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; public class HelloWorldImpl implements HelloService { @Override public Future<RpcResult<HelloWorldOutput>> helloWorld(HelloWorldInput input) { HelloWorldOutputBuilder helloBuilder = new HelloWorldOutputBuilder(); helloBuilder.setGreating("Hello " + input.getName()); return RpcResultBuilder.success(helloBuilder.build()).buildFuture(); } }
修改
HelloProvider.java
.注册在hello.yang
中创建的RPC. 你可以自己添加自己想要的实现,或者直接按如下编写:/* * Copyright © 2016 Cisco Systems 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 org.opendaylight.hello.impl; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HelloProvider { private static final Logger LOG = LoggerFactory.getLogger(HelloProvider.class); private final DataBroker dataBroker; private final RpcProviderRegistry rpcProviderRegistry; private RpcRegistration<HelloService> serviceRegistration; public HelloProvider(final DataBroker dataBroker, RpcProviderRegistry rpcProviderRegistry) { this.dataBroker = dataBroker; this.rpcProviderRegistry = rpcProviderRegistry; } /** * Method called when the blueprint container is created. */ public void init() { serviceRegistration = rpcProviderRegistry.addRpcImplementation(HelloService.class, new HelloWorldImpl()); LOG.info("HelloProvider Session Initiated"); } /** * Method called when the blueprint container is destroyed. */ public void close() { serviceRegistration.close(); LOG.info("HelloProvider Closed"); } }
这边需要注意:文件开头的版权声明不能去掉,否则无法通过Maven构建。此外,官网上的源文件有问题。本文档的源文件至少通过了本地编译。
此外,需要在BluePrint中注册你的RPC API.修改如下:
cd hello/impl/src/main/resources/org/opendaylight/blueprint vi impl-blueprint.xml
修改为如下。
<?xml version="1.0" encoding="UTF-8"?> <!-- vi: set et smarttab sw=4 tabstop=4: --> <!-- Copyright © 2016 Cisco Systems 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 --> <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" /> <reference id="rpcRegistry" interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry" /> <bean id="provider" class="org.opendaylight.hello.impl.HelloProvider" init-method="init" destroy-method="close"> <argument ref="dataBroker" /> <argument ref="rpcRegistry" /> </bean> </blueprint>
这个文档中添加了
rpcRegistry
。需要注意
通过REST来测试hello-world
RPC
有很多方式可以测试RPC, 比如以下两种。
通过HTTP使用ODL控制器自带的API Explorer
使用浏览器的REST 客户端
通过HTTP使用ODL控制器自带的API Explorer
使用浏览器进入 apidoc UI
<http://localhost:8181/apidoc/explorer/index.html>
。TIP: localhost是你ODL控制器的IP地址或者Hostname。
选择
hello(2015-01-05)
选择
POST /operations/hello:hello-world
在框内填写如下值
{"hello:input": { "name":"Your Name"}}
点击按钮.
输入 username 和 password, 默认是
admin/admin
.返回的Response body应该为:
{ "output": { "greating": "Hello Your Name" } }
使用浏览器的REST 客户端
可以使用火狐浏览器的 RESTClient或者Chrome的Restlet Client
。
POST: http://192.168.1.43:8181/restconf/operations/hello:hello-world
Header:
application/json
Body:
{"input": {
"name": "Andrew"
}
}
Troubleshooting
If you get a response code 501 while attempting to POST
/operations/hello:hello-world, check the file: HelloProvider.java and
make sure the helloService member is being set. By not invoking
“session.addRpcImplementation()” the REST API will be unable to map
/operations/hello:hello-world url to HelloWorldImpl.
这个应该碰不到了。所以就不翻译了。