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的project文件夹结构。
第一步:定义yang文件及其pom.xml
在文件夹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定义yang的pom.xml,在xptest下定义pom.xml"; 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 函数。第二步:定义rpc的实现文件XpTestProvider及其Activator
该project定义为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实现插件入口类Activator,顺便实现命令行接口,能够自己定义命令行測试命令。> 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); }}
/** * 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"; } }xpprovider的pom.xml文件。
> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.opendaylight.controller.samples</groupId> <artifactId>sal-samples</artifactId> <version>1.2.0-SNAPSHOT</version> </parent> <artifactId>sample-xptest-provider</artifactId> <packaging>bundle</packaging> <dependencies> <dependency> <groupId>${project.groupId}</groupId> <artifactId>sample-xptest</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>equinoxSDK381</groupId> <artifactId>org.eclipse.osgi</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>config-api</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-api</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-config</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-common-util</artifactId> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.core</artifactId> </dependency> <!-- dependencies to use AbstractDataBrokerTest --> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-broker-impl</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-broker-impl</artifactId> <type>test-jar</type> <scope>test</scope> </dependency> <dependency> <artifactId>junit</artifactId> <groupId>junit</groupId> <scope>test</scope> </dependency> <!-- used to mock up classes --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-api</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller.model</groupId> <artifactId>model-flow-service</artifactId> </dependency> <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-common</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-broker-impl</artifactId> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <configuration> <instructions> <Bundle-Activator>org.opendaylight.controller.xptest.Activator</Bundle-Activator> </instructions> </configuration> </plugin> </plugins> </build> <scm> <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection> <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection> <tag>HEAD</tag> <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url> </scm> </project>
执行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
- Status Code: 200 OK
- Content-Type: application/xml
- Date: Wed, 08 Oct 2014 12:43:29 GMT
- Server: Apache-Coyote/1.1
- Transfer-Encoding: chunked
xml version="1.0" encoding="UTF-8" standalone="no"?> <output xmlns="http://startsky.com/ns/xptest"> <name>3</name> <orderno>112233</orderno> </output>
假设header中加accept:application/yang.data+json,将返回json数据。
按上面代码中意图能够构造失败測试用例。
希望本文对odl有兴趣的人,可以给予帮助。