目录
声明
摘要
概览
先决条件
构建示例模块
创建一个简单的hello-world RPC
添加一个简单的hello-world RPC API
实现hello-world RPC API
运行hello-world工程
通过REST测试hello-world RPC
故障排除
参考文献
声明
官网的文档一直在变化,可能翻译时的文档跟目前文档有出入,请以官网文档为准。
摘要
本文提供了OpenDaylight控制器应用开发所需要的信息。你既可以使用 model-driven SAL(MD-SAL)原型在控制器内部开发应用,也可以使用 RESTCONF开发外部应用与控制器进行通讯。
概览
这部分内容让你对OpenDaylight控制器应用开发进行入门。按如下步骤开发一个应用。
- 通过一个简单的编译过程为代码创建一个本地仓库。
- 启动一个odl控制器。
- 测试创建的hello-world RPC功能。
先决条件
- Maven 3.1.1或更新
- Java 7- 或 Java 8-compliant JDK
- 一个配置正确的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,本地仓库默认是在~/.m2/repository。其他系统的位置会有变化。
构建示例模块
按要求执行如下步骤
1.使用 Maven和一个叫做opendaylight-startup-archetype的原型创建一个模版工程。如果你第一次创建该工程,需要花费一些时间从远程仓库下载。
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
2.按如下修改属性,确保groupid和artifactid是小写
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.
3.classPrefix的默认值是:( a r t i f a c t I d . s u b s t r i n g ( 0 , 1 ) . t o U p p e r C a s e ( ) {artifactId.substring(0,1).toUpperCase()} artifactId.substring(0,1).toUpperCase(){artifactId.substring(1)}). 即通过把articleId的第一个字母大写,classPrefix用于创建Java类的前缀。
注意:在这个场景下,使用的classPrefix是Example。原型创建了一个顶层目录。
${artifactId}/
example/
cd example/
api/
artifacts/
features/
impl/
karaf/
pom.xml
4.编译example工程
注意:这个编译过程花费的时间多少,根据你的开发机配置情况。确保你是在项目的根目录example/下,然后执行如下命令。
mvn clean install
5.启动example工程
cd karaf/target/assembly/bin
ls
./karaf
6.等待karaf cli如下所示提示符的出现。在提示符出现之前,OpenDaylight加载所有组件需要花费1~2分钟时间
opendaylight-user@root>
7.验证example工程是否编译成功,查找日志是否包含ExampleProvider Session Initiated
log:display | grep Example
8.通过控制台执行如下命令关闭OpenDaylight
shutdown -f
定义一个简单的hello-world RPC
1.执行 maven archetype opendaylight-startup-archetype,创建hello工程.
mvn archetype:generate -DarchetypeGroupId=org.opendaylight.controller -DarchetypeArtifactId=opendaylight-startup-archetype -DarchetypeRepository=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/ -DarchetypeCatalog=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/archetype-catalog.xml
2.按如下修改属性值.
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) Yoyodyne, Inc.
3.查看hello工程.
cd hello/
ls -1
api
artifacts
features
impl
karaf
pom.xml
4.执行如下命令编译hello工程
mvn clean install
5.运行karaf验证工程是否正常
cd karaf/target/assembly/bin
./karaf
6.出现如下 karaf cli提示符
注意:记得等opendaylight组件完全加载完,可以查看java进程是否稳定来判断
opendaylight-user@root>
7.通过日志验证hello模块是否加载.
log:display | grep Hello
8.关闭 karaf.
shutdown -f
9.返回到顶级目录
cd ../../../../
10.查看入口,了解日志是从哪里来的。入口在impl工程目录中
impl/src/main/java/org/opendaylight/hello/impl/HelloProvider.java
11.在HelloProvider.onSessionInitiate中添加你想做的任何事情
@Override
public void onSessionInitiated(ProviderContext session) {
LOG.info("HelloProvider Session Initiated");
}
添加一个简单的hello-world RPC API
1.找到如下文件
编辑
api/src/main/yang/hello.yang
2.按如下编辑该文件.该例子中我们在YANG module中添加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;
}
}
}
}
3.返回到hello/api目录,然后运行如下命令编译api.
cd ../../../
mvn clean install
实现hello-world RPC API
1.实现一个HelloService,通过hello-world API调用该服务.
cd ../impl/src/main/java/org/opendaylight/hello/impl/
2.创建一个文件HelloWorldImpl.java,添加如下代码.
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();
}
}
3.在当前目录中找到HelloProvider.java文件. 在该文件中注册你在hello.yang中定义的RPC。你可以按如下编辑该文件或者用下面的代码替换该文件。
/*
* Copyright(c) Yoyodyne, Inc. 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.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
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 implements BindingAwareProvider, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(HelloProvider.class);
private RpcRegistration<HelloService> helloService;
@Override
public void onSessionInitiated(ProviderContext session) {
LOG.info("HelloProvider Session Initiated");
helloService = session.addRpcImplementation(HelloService.class, new HelloWorldImpl());
}
@Override
public void close() throws Exception {
LOG.info("HelloProvider Closed");
if (helloService != null) {
helloService.close();
}
}
}
4.可选, 你可以马上编译注册新RPC功能的java类。这样做可以检查你编写的HelloProvider.java和HelloWorldImpl.java是否正确。
cd ../../../../../../../
mvn clean install
5.返回到顶级部目录
cd ../
6.再次编译整个hello工程, 这次将把你所做的修订编译进整个工程。
mvn clean install
运行hello-world工程
1.运行karaf
cd ../karaf/target/assembly/bin
./karaf
2.等待工程加载完成. 然后查看hello模块的日志
log:display | grep Hello
通过REST测试hello-world RPC
有很多方法可以测试你的RPC.如下是一些例子
- 通过http使用API Explorer
- 使用一个浏览器REST客户端
通过http使用API Explorer
1.用浏览器打开apidoc UI http://localhost:8181/apidoc/explorer/index.html , 默认密码admin/admin。
注意: 上面提及的URL,把localhost改成你开发机的网络地址。
2.选择
hello(2015-01-05)
3.选择
POST /operations/hello:hello-world
4.填入要求的值
{"hello:input": { "name":"Your Name"}}
5.点击按钮
6.你可以看见响应内容
{
"output": {
"greating": "Hello Your Name"
}
}
使用一个浏览器REST客户端
例如,在Firefox插件 RESTClient (https://github.com/chao/RESTClient) 使用如下信息
POST:
http://192.168.1.43:8181/restconf/operations/hello:hello-world
Header:
application/json
Body:
{
"input": {
"name": "Andrew"
}
}
故障排除
如果你尝试用POST请求/operations/hello:hello-world返回501错误,检查下该文件HelloProvider.java,确保helloService被注入。如果没有调用“session.addRpcImplementation()”,REST API将无法映射/operations/hello:hello-world url到HelloWorldImpl。
(欢迎关注鲁班曰)