在odl中如何实现rpc

来源:互联网 发布:在线客服源码下载 编辑:程序博客网 时间:2024/06/05 03:40

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的工程目录结构。


第一步:定义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 <xpzh@sohu.com>";    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

定义yang的pom.xml,在xptest下定义pom.xml

<?xml version="1.0" encoding="UTF-8"?><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</artifactId>  <packaging>bundle</packaging>  <dependencies>    <dependency>      <groupId>org.opendaylight.yangtools</groupId>      <artifactId>yang-binding</artifactId>    </dependency>    <dependency>      <groupId>org.opendaylight.yangtools</groupId>      <artifactId>yang-common</artifactId>    </dependency>  </dependencies>  <build>    <plugins>      <plugin>        <groupId>org.opendaylight.yangtools</groupId>        <artifactId>yang-maven-plugin</artifactId>        <dependencies>          <dependency>            <groupId>org.opendaylight.yangtools</groupId>            <artifactId>maven-sal-api-gen-plugin</artifactId>            <version>${yangtools.version}</version>            <type>jar</type>          </dependency>        </dependencies>        <executions>          <execution>            <goals>              <goal>generate-sources</goal>            </goals>            <configuration>              <yangFilesRootDir>src/main/yang</yangFilesRootDir>              <codeGenerators>                <generator>                  <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>                  <outputBaseDir>${salGeneratorPath}</outputBaseDir>                </generator>              </codeGenerators>              <inspectDependencies>true</inspectDependencies>            </configuration>          </execution>        </executions>      </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>

上面yang文件定义了两个rpc。

运行mvn install编译xptest.yang. 会产生一个rpc服务XptestService 接口。其中两个方法对应两个rpc 函数。

第二步:定义rpc的实现文件XpTestProvider及其Activator

该工程定义为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<RpcResult<CancelOrderOutput>> cancelOrder(      CancelOrderInput input) {    // TODO Auto-generated method stub    RpcResult<CancelOrderOutput> ret=null;    if(input.getOrderno() >10)    {      ret=RpcResultBuilder.<CancelOrderOutput>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.<CancelOrderOutput>success(builder.build()).build();    }    return Futures.immediateFuture(ret);  }  @Override  public Future<RpcResult<MakeOrderOutput>> makeOrder(MakeOrderInput input) {    // TODO Auto-generated method stub    RpcResult<MakeOrderOutput> 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.<MakeOrderOutput>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.<MakeOrderOutput>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 <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a> * * */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文件。

<?xml version="1.0" encoding="UTF-8"?><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

  1. Status Code: 200 OK
  2. Content-Type: application/xml
  3. Date: Wed, 08 Oct 2014 12:43:29 GMT
  4. Server: Apache-Coyote/1.1
  5. Transfer-Encoding: chunked
response body

<?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有兴趣的人,能够给予帮助。

0 0
原创粉丝点击