在odl中如何实现rpc

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 <[email protected]>";

    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.1-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.util.concurrent.Future;

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 com.google.common.util.concurrent.Futures;

public class XpTestProvider implements XptestService {

  @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;
    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:[email protected]">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.1-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>

第三步:进行测试。

运行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数据,如何header中加accept:application/yang.data+json,将返回json数据。

按上面代码中意图可以构造失败测试用例。

希望本文对odl有兴趣的人,能够给予帮助。

时间: 2024-08-10 15:10:24

在odl中如何实现rpc的相关文章

java中常见的rpc框架介绍

姓名:邓勇  班级:软件151 RPC是远程过程调用的简称,广泛应用在大规模分布式应用中,作用是有助于系统的垂直拆分,使系统更易拓展.Java中的RPC框架比较多,各有特色,广泛使用的有RMI.Hessian.Dubbo等.RPC还有一个特点就是能够跨语言,本文只以JAVA语言里的RPC为例. 其他的框架结构也类似,区别在于对象的序列化方法,传输对象的通讯协议,以及注册中心的管理与failover设计(利用zookeeper).客户端和服务端可以运行在不同的JVM中,Client只需要引入接口,

Yarn中ResourceManager的RPC协议

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemNjXzAwMTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > ResourceTrackerProtocol:注冊.汇报节点的健康状况和Container的执行情况. AppMasterProtocol:向RM注冊.申请和释放资源. AppClientProtocol:向RM提交用户程序.

基于protobuf的RPC实现

可以对照使用google protobuf RPC实现echo service一文看,细节本文不再描述. google protobuf只负责消息的打包和解包,并不包含RPC的实现,但其包含了RPC的定义.假设有下面的RPC定义: service MyService { rpc Echo(EchoReqMsg) returns(EchoRespMsg) } 那么要实现这个RPC需要最少做哪些事?总结起来需要完成以下几步: 客户端 RPC客户端需要实现google::protobuf::RpcCh

Hadoop的RPC机制

一.RPC(Remote Procedure Call)简介 RPC 是远程过程调用(Remote Procedure Call),即远程调用其他虚拟机中运行的javaobject.RPC 是一种客户端/服务器模式,那么在使用时包括服务端代码和客户端代码,还有我们调用的远程过程对象.HDFS 的运行就是建立在此基础之上的.本章通过分析实现一个简单的RPC 程序来分析HDFS 的运行机理. 二.代码解析 1.服务端代码 代码如下: public class MyServer { public st

(转)RabbitMQ消息队列(七):适用于云计算集群的远程调用(RPC)

在云计算环境中,很多时候需要用它其他机器的计算资源,我们有可能会在接收到Message进行处理时,会把一部分计算任务分配到其他节点来完成.那么,RabbitMQ如何使用RPC呢?在本篇文章中,我们将会通过其它节点求来斐波纳契完成示例. 1. 客户端接口 Client interface 为了展示一个RPC服务是如何使用的,我们将创建一段很简单的客户端class. 它将会向外提供名字为call的函数,这个call会发送RPC请求并且阻塞知道收到RPC运算的结果.代码如下: [python] vie

RPC框架实现 - 框架篇

RPC(Remote Procedure Call,远程过程调用)框架是分布式服务的基石,实现RPC框架需要考虑方方面面.其对业务隐藏了底层通信过程(TCP/UDP.打包/解包.序列化/反序列化),使上层专注于功能实现:框架层面,提供各类可选架构(多进程/多线程/协程):应对设备故障(高负载/死机).网络故障(拥塞/网络分化),提供相应容灾措施. 关于服务端框架设计和实现,很多文章都有介绍,最常见的是epoll + prefork(进程池/线程池)实现方式,近几年业界又兴起了协程(corouti

hadoop rpc基础

第一部分: hadoop rpc基础 RPC,远程程序调用,分布式计算中C/S模型的一个应用实例. 同其他RPC框架一样,Hadoop分为四个部分: 序列化层:支持多种框架实现序列化与反序列化 函数调用层:利用java反射与动态代理实现 网络传输层:基于TCP/IP的Socket机制 服务的处理框架:基于Reactor模式的事件驱动IO模型 Hadoop RPC主要对外提供2种接口 public static ProtocolProxy getProxy/waitForProxy: 构造一个客户

远程过程调用(RPC)详解

原文同步至 http://waylau.com/remote-procedure-calls/ 本文介绍了什么是远程过程调用(RPC),RPC 有哪些常用的方法,RPC 经历了哪些发展阶段,以及比较了各种 RPC 技术的优劣. 什么是 RPC RPC 是远程过程调用(Remote Procedure Call)的缩写形式,Birrell 和 Nelson 在 1984 发表于 ACM Transactions on Computer Systems 的论文<Implementing remote

rpc(remote procedure call)

远程过程:java进程.即一个java进程调用另外一个java进程中对象的方法. 调用方称作客户端(client),被调用方称作服务端(server).rpc的通信在java中表现为客户端去调用服务端对象中的方法.RPC通信就是cs结构的通信.client端会知道服务端被调用对象的接口.RPC是hadoop分布式机制运行的基础. 代码示例: 接口:MyBizable public interface MyBizable extends VersionedProtocol{ public stat