折腾了一段时间的 ONOS

近期需要在 onos 上做点东西,做一下简单记录.

运行环境安装

安装 docker

我笔记本用的发行版是 manjaro, 本来打算直接包管理器装,但是版本问题彻底把我折腾毛了。AUR 里的 onos 是 2.0.0,这个安装和运行没有啥问题;mininet 问题比较大:装 mininet 的 2.2.x 版本能运行但是不管用什么控制器,虚拟的 host 之间互相 ping 不通;装 2.3.x 版本倒是用 mininet 自己的控制器没问题了,但 onos 连接不上,看日志应该是 oepnflow 的版本没匹配上,没找到怎么解决。最后决定全放到 docker 里面用了(其实只要 mininet 放到 docker 里就可以了)。

虽然网上现在都在说 podman 才是未来,但是毕竟还是太新了,用的时候出现了问题。一个容器关了再开就错误了,感觉不太稳定,还是用的 docker

安装 mininet

# pull 镜像
docker pull iwaseyusuke/mininet

# 创建并运行容器
docker run -it --name mn --privileged -e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -v /lib/modules:/lib/modules iwaseyusuke/mininet

# 进入容器
docker exec -it mn /bin/bash

# 在宿主机执行便于运行容器中的 X window 应用(对 mininet 来说主要是 xterm)
xhost +si:localuser:root

# 开启和关闭容器
docker start mn
docker stop mn

docker pull 的时候网络不好很难受,最后用的阿里云的源,免费的不过要登录阿里云申请(虽然在我这里也并不是很快

安装 onos

安装 release 版

只是使用可以安装官方发行的版本或者用 docker 镜像

# pull 镜像
docker pull onosproject/onos:1.15.0

# 创建并运行容器
docker run -t -d --name onos onosproject/onos:1.15.0

# ssh 进入 onos CLI, 默认密码 karaf
ssh -p 8101 [email protected]

# 通过浏览器访问 onos 的 web UI:http://172.17.0.2:8181/onos/ui/index.html

# 开启和关闭容器
docker start onos
docker stop onos

安装好后要使用还需要激活基本的功能

# 在 onos CLI 执行

# 启用openflow
app activate org.onosproject.openflow
# 启用转发功能
app activate org.onosproject.fwd

从源码编译安装

如果要对源码进行修改需要从源码编译安装

# clone 源码
git clone https://gerrit.onosproject.org/onos
# 切换分支
git checkout -b onos-1.15 origin/onos-1.15

# 编译,编译前需要的依赖:bazel git zip curl unzip python python3 bzip2
# 其他需要的依赖都交给 bazel 当场下载,下载内容+编译生成的 cache 共 2.6 G
bazel build onos

# 编译时可以用代理,如果后来编译 gui 时 npm 卡住建议修改相应的 BUILD 文件,用各种方式科学上网
# 给 bazel 用代理 build 的方式
export HTTP_PROXY=http://<proxy address>:<proxy port>
bazel build onos --action_env=HTTP_PROXY=$HTTP_PROXY

# 运行
bazel run onos-local [-- clean debug]
# clean 会清空之前的使用痕迹就像重新安装一样
# debug 是 java 的什么远程调控

编译成功后会将 release 打包在 bazel-bin/onos.tar.gz,里面内容跟从官网下载的 release 版本一样

测试

# 进入 mn 容器
docker exec -it mn /bin/bash

# 创建一个简单拓扑,onos 作为控制器,并测试联通性
mn --topo tree,2 --controller remote,ip=172.17.0.2 --test pingall

之后再打开 onos 的 Web UI 就可以直观地看到创建出的虚拟网络的拓扑

我使用的版本

  • onos 1.15.0
  • mininet 2.2.2
  • docker 19.03.5-ce

为了让环境和服务器上一致,onos 和 mininet 用的都不是最新版本

开发环境

现在能够运行了,接下来是如何基于 ONOS 开发,我这里主要是用 Java 编写 onos 应用。

环境配置

源码里带了一些开发工具,可以用项目自带的脚本加到环境变量里

# 以下内容加到.bashrc 之类的 profile 里
export ONOS_ROOT=~/onos
source $ONOS_ROOT/tools/dev/bash_profile

脚本有一些问题,会输出很多错误,比如输出在环境变量里找不到这个项目之前用现在已经不用了的 buck,可以无视

利用 Java API 编写应用

可以利用 onos 提供的 Java API 为 onos 编写应用,一般用 maven 作为默认的构建工具(onos 源码现在用的是 bazel,但文档和他的 samples 还是说用 maven 构建,也有一些教程说可以直接在源码的 apps 里面新建项目用 bazel 构建,但我个人更熟悉 maven)。

可以用之前提供的开发工具里的 onos-create-app 脚本来新建项目,也可以 git clone 下来已有的 sample 项目做修改

官方文档:

设置版本

onos-create-app 本质上是从 maven 仓库下载官方的项目模板,不同版本的 onos 可能会不兼容,最好在环境变量里设置版本,如

export ONOS_POM_VERSION=1.15.0

不设置的话会默认下载最新版本的模板。

创建项目

onos-create-app -h 输出帮助可以看到模板应用主要有以下几类:

  • app 基础模板
  • ui 为 web GUI 创建一个 view
  • uitab 为 web GUI 创建一个 表格 view
  • uitopo 为默认的拓扑view 添加功能
  • rest 创建一个提供 REST API 北向接口的模板
  • cli 创建一个 onos 命令行应用的模板
  • 其他的我还没接触

首先用 onos-create-app app [groupId] [artifactId] 创建基础的项目模板

接下来可以 onos-create-app ui/rest/... [groupId] [artifactId] 对基础项目进行 overlay,模板会自动生成一些类,这些类都是可以共存的,一个应用可以同时有 REST API 和自己定义的 GUI view, 互相不干扰

基本思路

基本的思路是把要实现的功能实现在一个 Service 类中,然后在 REST 和 CLI 这种类里面调用,将功能暴露出来

首先定义一个接口比如 MyOnosService, 接下来写一个类实现接口,定义时加上特定的注解

public interface MyOnosService {
    // method
    public void xxx();
}

@Component(immediate = true)
@Service
public class XXXImpl implements MyOnosService {

    // 在一个 service 中通过这种形式可以获取到其他 service 来使用
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    LinkService linkService;

    @Override
    public void xxx() {

    }
}

// 在 REST 和 CLI 对应的类里面就可以这样使用自己定义的 service
MyOnosService myService = get(MyOnosService.class);
myService.xxx();

常用方法

ONOS 提供了很多基础的 Service

  • CoreService 跟核心系统相关的基础功能,比如注册 AppId
  • LinkService 跟链路相关的功能
  • HostService 跟主机相关的功能
  • PortStatisticsService 提供端口信息,比如获取交换机的端口速率
  • PathService 跟转发路径相关的功能
  • IntentService 意图功能,我的理解就是在流表上又抽象出来一层

等等,还有很多,我暂时也没写多少东西,用到了再补充吧…

ONOS提供的 API DOC

TODO

感觉还不是很熟悉,如果接下来还要写相关的东西,加一些常用的代码段之类的