opendaylight作为sdn主要开源项目,采用osgi框架,已经得到很多厂商的支持。氦版本也发布在即。
下面介绍一下在odl中如何实现rpc. odl使用yang作为model模型定义文件,yang规范最先被用于netconf,后来restconf在http协议上实现restful,而采用yang定义模型。
实现分2步:1.采用yang定义模型,实现api jar包。2 实现rpc service的实现类,注册到session中。
2个java的工程目录结构。
在目录xptest\src\main\yang下定义xptest.yang
module xptest {
yang-version 1;
namespace
"http://startsky.com/ns/xptest";
prefix xps;
organization "xpstudio Netconf Central";
contact
"xinping ";
description
"YANG version of the xptest-MIB.";
revision "2014-10-3" {
description
"xptest module in progress.";
}
typedef DispString {
type string {
length "0 .. 255";
}
description
"YANG version of the SMIv2 DisplayString TEXTUAL-CONVENTION.";
reference
"RFC 2579, section 2.";
}
container xptester {
leaf name {
type string;
}
leaf age {
type uint32;
default 99;
}
leaf homeaddress {
type string;
}
} // container toaster
rpc make-order {
input {
leaf name {
type string;
}
leaf days {
type uint32;
default 1;
}
}
output {
leaf name {
type string;
}
leaf orderno {
type uint32;
}
}
} // make-order
rpc cancel-order {
input {
leaf orderno {
type uint32;
}
}
output {
leaf name {
type string;
}
leaf order-status {
type enumeration {
enum "success" {
value 1;
}
enum "fail" {
value 2;
}
}
}
}
} // cancel-order
} // module xptest
4.0.0
org.opendaylight.controller.samples
sal-samples
1.2.0-SNAPSHOT
sample-xptest
bundle
org.opendaylight.yangtools
yang-binding
org.opendaylight.yangtools
yang-common
org.opendaylight.yangtools
yang-maven-plugin
org.opendaylight.yangtools
maven-sal-api-gen-plugin
${yangtools.version}
jar
generate-sources
src/main/yang
org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
${salGeneratorPath}
true
scm:git:ssh://git.opendaylight.org:29418/controller.git
scm:git:ssh://git.opendaylight.org:29418/controller.git
HEAD
https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL
上面yang文件定义了两个rpc。
运行mvn install编译xptest.yang. 会产生一个rpc服务XptestService 接口。其中两个方法对应两个rpc 函数。该工程定义为xpprovider。
rpc实现类XpTestProvider
package org.opendaylight.controller.xptest.impl;
import java.io.File;
import java.util.concurrent.Future;
//import org.opendaylight.controller.xptest.Activator;
import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.CancelOrderInput;
import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.CancelOrderOutput;
import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.CancelOrderOutput.OrderStatus;
import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.CancelOrderOutputBuilder;
import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.MakeOrderInput;
import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.MakeOrderOutput;
import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.MakeOrderOutputBuilder;
import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.XptestService;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.util.concurrent.Futures;
public class XpTestProvider implements XptestService {
private final static Logger LOG = LoggerFactory.getLogger(XpTestProvider.class);
@Override
public Future> cancelOrder(
CancelOrderInput input) {
// TODO Auto-generated method stub
RpcResult ret=null;
if(input.getOrderno() >10)
{
ret=RpcResultBuilder.failed().withError( ErrorType.APPLICATION, "resource-denied",
"days > 10,failed!!" ).build();
}else {
CancelOrderOutputBuilder builder=new CancelOrderOutputBuilder();
builder.setName("name"+input.getOrderno());
builder.setOrderStatus(OrderStatus.Success);
ret=RpcResultBuilder.success(builder.build()).build();
}
return Futures.immediateFuture(ret);
}
@Override
public Future> makeOrder(MakeOrderInput input) {
// TODO Auto-generated method stub
RpcResult ret=null;
LOG.info( "user.dir "+System.getProperty("user.dir"));
File directory = new File("");//设定为当前文件夹
try{
LOG.info("std: "+directory.getCanonicalPath());//获取标准的路径
LOG.info("abs: "+directory.getAbsolutePath());//获取绝对路径
}catch(Exception e)
{
}
if(input.getDays()>10)
{
ret=RpcResultBuilder.failed().withError( ErrorType.APPLICATION, "resource-denied",
"days > 10,failed!!" ).build();
}else {
MakeOrderOutputBuilder builder=new MakeOrderOutputBuilder();
builder.setName(input.getName());
builder.setOrderno((long) 112233);
ret=RpcResultBuilder.success(builder.build()).build();
}
return Futures.immediateFuture(ret);
}
}
实现插件入口类Activator,顺便实现命令行接口,可以自定义命令行测试命令。
/**
* Copyright (c) 2014 Cisco Systems, 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.controller.xptest;
import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.xptest.impl.XpTestProvider;
import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.XptestService;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Forwarding Rules Manager Activator
*
* Activator {@link ForwardingRulesManager}.
* It registers all listeners (DataChangeEvent, ReconcilNotification)
* in the Session Initialization phase.
*
* @author Vaclav Demcak
* *
*/
public class Activator extends AbstractBindingAwareProvider
implements CommandProvider {
private final static Logger LOG = LoggerFactory.getLogger(Activator.class);
@Override
public void onSessionInitiated(ProviderContext session) {
LOG.info("FRMActivator initialization.");
try {
// final DataBroker dataBroker = session.getSALService(DataBroker.class);
// this.manager = new ForwardingRulesManagerImpl(dataBroker, session);
// this.manager.start();
XpTestProvider rpcins=new XpTestProvider();
session.addRpcImplementation(XptestService.class,rpcins);
LOG.info("FRMActivator initialization successfull.");
}
catch (Exception e) {
LOG.error("Unexpected error by FRM initialization!", e);
this.stopImpl(null);
}
}
@Override
protected void startImpl(BundleContext context) {
// TODO Auto-generated method stub
super.startImpl(context);
context.registerService(CommandProvider.class.getName(),
this, null);
}
@Override
protected void stopImpl(final BundleContext context) {
/* if (manager != null) {
try {
manager.close();
} catch (Exception e) {
LOG.error("Unexpected error by stopping FRMActivator", e);
}
manager = null;
}*/
LOG.info("FRMActivator stopped.");
}
public void _gettpsbyne(CommandInterpreter ci) {
ci.println("gettpsbyne:" + ci.nextArgument());
}
@Override
public String getHelp() {
return "\tgettpsbyne neid– say what you input\n";
}
}
4.0.0
org.opendaylight.controller.samples
sal-samples
1.2.0-SNAPSHOT
sample-xptest-provider
bundle
${project.groupId}
sample-xptest
${project.version}
equinoxSDK381
org.eclipse.osgi
org.opendaylight.controller
config-api
org.opendaylight.controller
sal-binding-api
org.opendaylight.controller
sal-binding-config
org.opendaylight.controller
sal-common-util
org.osgi
org.osgi.core
org.opendaylight.controller
sal-binding-broker-impl
test
org.opendaylight.controller
sal-binding-broker-impl
test-jar
test
junit
junit
test
org.mockito
mockito-all
test
org.opendaylight.controller
sal-binding-api
org.opendaylight.controller.model
model-flow-service
org.opendaylight.yangtools
yang-common
org.opendaylight.controller
sal-binding-broker-impl
provided
org.apache.felix
maven-bundle-plugin
org.opendaylight.controller.xptest.Activator
scm:git:ssh://git.opendaylight.org:29418/controller.git
scm:git:ssh://git.opendaylight.org:29418/controller.git
HEAD
https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL
运行mvn install 编译,之后把这两个jar包拷贝到odl的plugins目录下,最好运行odl准备。
运行run.bat,启动odl,在restclient中运行下面测试用例。可以做restclient的工具有chrome插件postman,firefox的restclient,网上还有个单独jar包restclient.
HTTP Method => POST
URL => http://localhost:8080/restconf/operations/xptest:make-order
Header => Content-Type: application/yang.data+json
Body =>
{
"input" :
{
"xptest:name" : "3","xptest:days":3
}
}
可以看到返回xml数据, response header
如果header中加accept:application/yang.data+json,将返回json数据。
按上面代码中意图可以构造失败测试用例。
希望本文对odl有兴趣的人,能够给予帮助。