CentOS7でOpenVNetを動作させよう

この記事は、[Wakame-vdc / OpenVNet Advent Calendar 2014](http://www.adventar.org/calendars/577)の19日目です。

OpenVNetの[Install Guide](https://github.com/axsh/openvnet/blob/master/docs/InstallGuide.md)を見る限り、OpenVNetが動作保証されているOSは下記のようにかなり限定されています。

|OS|Kernel|
|:--|:--|
|RHEL 6.4|Kernel 2.6.32-358.6.2.el6.x86_64|

RHEL6系（CentOS6系）は2020年11月30日までメンテナンスされるとしても、最新OSで動作するに越したことはありません。そこでCentOS7にOpenVNetをインストールしてみました。

## Vagrant Box

下記手順を一つずつ実施するには、かなり手間と時間がかかります。そこで[chef/centos-7.0](https://atlas.hashicorp.com/chef/boxes/centos-7.0)のbox上にOpenVNetをインストール（下記手順の1.〜7.まで実施）した、[openvnet-centos7](https://atlas.hashicorp.com/nmatsui/boxes/openvnet-centos7) boxをVagrant Cloudで公開しました。

`$ vagrant init nmatsui/openvnet-centos7`で試してみてください。

> もしvagrant cloudからうまくboxを取得できない場合は、[ココ](https://s3-ap-northeast-1.amazonaws.com/nmatsui-vagrant-box/openvnet-centos7.box)から直接boxをダウンロードして`vagrant box add nmatsui/openvnet-centos7 openvnet-centos7.box`としてください。

## 検証した環境

### HOST

|OS|Kernel|
|:--|:--|
|CentOS Linux release 7.0.1406|Kernel 3.10.0-123.9.3.el7.x86_64 |

### GUEST

|OS|Kernel|
|:--|:--|
|CentOS Linux release 7.0.1406|Kernel 3.10.0-123.13.1.el7.x86_64|

## 1. OpenVNetとepelリポジトリ登録

OpenVNetとepelのリポジトリを登録します。
[Install Guide](https://github.com/axsh/openvnet/blob/master/docs/InstallGuide.md)ではaxshが準備したepelを用いることになっていますが、CentOSのextrasリポジトリのepelをそのまま利用します。

```text
[vagrant@centos7 ~]$ sudo su -
[root@centos7 ~]# curl -o /etc/yum.repos.d/openvnet.repo -R https://raw.githubusercontent.com/axsh/openvnet/master/deployment/yum_repositories/stable/openvnet.repo
[root@centos7 ~]# curl -o /etc/yum.repos.d/openvnet-third-party.repo -R https://raw.githubusercontent.com/axsh/openvnet/master/deployment/yum_repositories/stable/openvnet-third-party.repo
[root@centos7 ~]# yum install epel-release -y
[root@centos7 ~]# yum update -y
```

## 2. Open vSwitchのインストール

CentOS6の手順と同様にこの段階で`yum install openvnet`を実行すると、依存関係にあるopenvswitch-1.10.0をインストールしようとします。しかしKernel 3.10系はopenvswitch 1.10には対応していないため、Dependency ResolutionでErrorとなります。
[Q: What Linux kernel versions does each Open vSwitch release work with?](https://github.com/openvswitch/ovs/blob/master/FAQ.md)

そのためKernel 3.10に対応したOpen vSwitchを事前にインストールします。

### RDOからOpen vSwitchインストール

簡単なのは、RDOリポジトリからOpen vSwitchをインストールする手順です。

```text
[root@centos7 ~]# yum install https://rdo.fedorapeople.org/rdo-release.rpm -y
[root@centos7 ~]# yum install openvswitch -y
[root@centos7 ~]# systemctl start openvswitch
[root@centos7 ~]# ovs-vsctl show
7cc3a436-f943-4bb9-be1f-17294b4ca194
    ovs_version: "2.1.3"
```

### ソースコードからOpen vSwitchインストール

RDOはOpenStack用の巨大なパッケージなため、その導入を避けてOpen vSwitchのソースコードをrpm-buildしてピンポイントにlocalinstallしても良いでしょう。

```text
[root@centos7 ~]# yum install gcc make automake rpm-build redhat-rpm-config python-devel openssl-devel kernel-devel kernel-debug-devel -y
[root@centos7 ~]# adduser ovswitch
[root@centos7 ~]# su - ovswitch
[ovswitch@centos7 ~]$ mkdir -p ~/rpmbuild/SOURCES
[ovswitch@centos7 ~]$ cd ~/rpmbuild/SOURCES/
[ovswitch@centos7 SOURCES]$ wget http://openvswitch.org/releases/openvswitch-2.3.0.tar.gz
[ovswitch@centos7 SOURCES]$ tar xfz openvswitch-2.3.0.tar.gz 
[ovswitch@centos7 SOURCES]$ cd openvswitch-2.3.0
[ovswitch@centos7 openvswitch-2.3.0]$ sed -i.org -e 's/openvswitch-kmod, //g' rhel/openvswitch.spec
[ovswitch@centos7 openvswitch-2.3.0]$ rpmbuild -bb --without check rhel/openvswitch.spec
[ovswitch@centos7 openvswitch-2.3.0]$ exit
[root@centos7 ~]# yum install /home/ovswitch/rpmbuild/RPMS/x86_64/openvswitch-2.3.0-1.x86_64.rpm -y
[root@centos7 ~]# systemctl start openvswitch
[root@centos7 ~]# ovs-vsctl show
39139eae-0747-4a26-8bf0-66747b2c522e
    ovs_version: "2.3.0"
```

## 3. MySQL 5.5系のインストール

この段階で`yum install openvnet`を実行すると、今度はmysql-serverの依存関係が解決できないと言われて止まります。
CentOS7からは標準リポジトリでmysqlが提供されなくなりましたので、RPMを取得してMySQLをインストールします。

**※注意**
**最新版のMySQL 5.6をインストールしてはいけません！**
**MySQL 5.6からはsql_modeのデフォルト値がSTRICT_TRANS_TABLEに変更されており、OpenVNetのいくつかのSQLがエラーを起こします**

```text
[root@centos7 ~]# wget http://dev.mysql.com/get/Downloads/MySQL-5.5/MySQL-shared-compat-5.5.41-1.el7.x86_64.rpm
[root@centos7 ~]# wget http://dev.mysql.com/get/Downloads/MySQL-5.5/MySQL-devel-5.5.41-1.el7.x86_64.rpm
[root@centos7 ~]# wget http://dev.mysql.com/get/Downloads/MySQL-5.5/MySQL-client-5.5.41-1.el7.x86_64.rpm
[root@centos7 ~]# wget http://dev.mysql.com/get/Downloads/MySQL-5.5/MySQL-server-5.5.41-1.el7.x86_64.rpm
[root@centos7 ~]# wget http://dev.mysql.com/get/Downloads/MySQL-5.5/MySQL-shared-5.5.41-1.el7.x86_64.rpm
[root@centos7 ~]# yum localinstall MySQL-shared-5.5.41-1.el7.x86_64.rpm -y
[root@centos7 ~]# yum localinstall MySQL-shared-compat-5.5.41-1.el7.x86_64.rpm -y
[root@centos7 ~]# yum localinstall MySQL-devel-5.5.41-1.el7.x86_64.rpm -y
[root@centos7 ~]# yum localinstall MySQL-server-5.5.41-1.el7.x86_64.rpm -y
[root@centos7 ~]# yum localinstall MySQL-client-5.5.41-1.el7.x86_64.rpm -y
[root@centos7 ~]# systemctl start mysql
[root@centos7 ~]# mysqladmin -uroot version
mysqladmin  Ver 8.42 Distrib 5.5.41, for Linux on x86_64
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Server version      5.5.41
Protocol version    10
Connection      Localhost via UNIX socket
UNIX socket     /var/lib/mysql/mysql.sock
Uptime:         31 sec

Threads: 1  Questions: 2  Slow queries: 0  Opens: 33  Flush tables: 1  Open tables: 26  Queries per second avg: 0.064
```

## 4. OpenVNetのインストール

Open vSwitchとMySQLを事前にインストールしておけば、OpenVNetのインストールが成功します。

```text
[root@centos7 ~]# yum install openvnet -y
...
Complete!
[root@centos7 ~]# yum info openvnet
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.jaist.ac.jp
 * epel: ftp.jaist.ac.jp
 * extras: ftp.jaist.ac.jp
 * updates: ftp.jaist.ac.jp
Installed Packages
Name        : openvnet
Arch        : noarch
Version     : 20141028112732gitc45f717.fpm0
Release     : 1
Size        : 0.0  
Repo        : installed
From repo   : openvnet
Summary     : Virtual network agent for OpenVNet
URL         : https://github.com/axsh/openvnet/                                                                                                                                 
License     : unknown                                                                                                                                                           
Description : Virtual network agent for OpenVNet
```

## 5. ruby 2.1.1のインストール

OpenVNetのパッケージに内包されるrubyはCentOS6系用ですので、rubyをソースコードからビルドしてインストールします。

### ruby自身のインストール

公式から2.1.1のソースコードを取得し、ビルドします。

**※注意**
**最新版のruby 2.1.5をインストールしてはいけません！**
**OpenVNetのWebAPIが依存するsinatra/namespaceは、内部でbackportsという過去のrubyのfeatureを最新のrubyで利用可能にするgemを利用していますが、このbackportsが最新版のruby 2.1.5ではエラーを起こしてしまうようです**

```text
[root@centos7 ~]# yum install gcc make automake sqlite-devel openssl-devel git -y
[root@centos7 ~]# wget http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.1.tar.gz
[root@centos7 ~]# tar xfz ruby-2.1.1.tar.gz 
[root@centos7 ~]# cd ruby-2.1.1
[root@centos7 ruby-2.1.1]# ./configure
[root@centos7 ruby-2.1.1]# make
[root@centos7 ruby-2.1.1]# make install
[root@centos7 ruby-2.1.1]# ruby -v
ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-linux]
[root@centos7 ruby-2.1.1]# gem -v
2.2.2
```

### bundlerのインストール

次にbundlerをインストールします。

```text
[root@centos7 ruby-2.1.1]# gem install bundler
[root@centos7 ruby-2.1.1]# bundle -v
Bundler version 1.7.9
```

もしgemが遅い場合、`echo 'options single-request-reopen' >> /etc/resolv.conf`で名前解決の挙動を変更すると高速化するかもしれません。

### OpenVNetが依存するgemの再インストール

各種gemを再取得し、mysql2などC extentionを含んだgemをCentOS7用にビルドしなおします。この作業を怠ると、よくわからないエラーに悩まされることになります。

```text
[root@centos7 ruby-2.1.1]# cd /opt/axsh/openvnet/vnet/
[root@centos7 vnet]# rm -rf vendor/
[root@centos7 vnet]# bundle install
...
Your bundle is complete!
```

### OpenVNetのCLIの依存ライブラリの取得

OpenVNetのREST APIにcurlでコマンドを送信しても良いのですが、必要とするパラメータがわかりづらいため、helpが充実しているOpenVNetのCLI（vnctl）を使えるようにします。

```text
[root@centos7 vnet]# cd /opt/axsh/openvnet/vnctl/
[root@centos7 vnctl]# bundle install
...
Your bundle is complete!
```

`/opt/axsh/openvnet/vnctl`ディレクトリで`bin/vnctl help`と実行すれば、利用可能なコマンドが参照できます。

```text
[root@centos7 vnctl]# bin/vnctl help
Commands:
  vnctl datapaths          # Operations for datapaths.
  vnctl dns_services       # Operations for dns_services.
...
```

また`bin/vnctl datapaths help add`等と実行すれば、コマンドのオプションが参照できます。

```text
[root@centos7 vnctl]# bin/vnctl datapaths help add
Usage:
  vnctl datapaths add [OPTIONS] --display-name=DISPLAY_NAME --dpid=DPID --node-id=NODE_ID

Options:
  [--uuid=UUID]                # Unique UUID for the datapaths.
...
```



## 6. OpenVNetの起動スクリプトの作成

CentOS7からはUpStartが使えなくなり、サービスの起動管理はsystemdに一本化されました。そこでsystemd経由でOpenVNetの起動・停止を行えるようにします。

### 環境設定ファイルの変更

CentOS7用にrubyをインストールしましたので、OpenVNetに同梱されているrubyを使わないように環境設定ファイルを変更します。

```text
[root@centos7 vnet]# sed -i.org -e 's/^RUBY_PATH=/#RUBY_PATH=/g' /etc/default/openvnet
[root@centos7 vnet]# sed -i -e 's/^PATH=/#PATH=/g' /etc/default/openvnet
```

### サービス起動スクリプトの作成

Virtual NetwrokのManager（vnmgr）、API（webapi）、Agent（vna）の起動スクリプトを`/opt/axsh/openvnet/vnet/bin`へ作成し、実行権を与えます。

```text
[root@centos7 vnctl]# cd /opt/axsh/openvnet/vnet/
[root@centos7 vnet]# vi bin/vnet-vnmgr
[root@centos7 vnet]# vi bin/vnet-webapi
[root@centos7 vnet]# vi bin/vnet-vna
[root@centos7 vnet]# chmod +x bin/vnet-*
```

```bash:bin/vnet-vnmgr
#!/bin/bash

NAME=vnmgr

[ -f /etc/default/vnet-${NAME} ] && . /etc/default/vnet-${NAME}
export LOG_DIRECTORY

[ -d "${LOG_DIRECTORY}" ] || {
  mkdir ${LOG_DIRECTORY}
}

[ -d "${VNET_ROOT}" ] || {
  logger "no such directory: ${VNET_ROOT}"
  exit 1
}
cd ${VNET_ROOT}/vnet/

bundle exec ./bin/${NAME} \
    >> ${LOG_DIRECTORY}/${NAME}.log 2>&1 
```

```bash:bin/vnet-webapi
#!/bin/bash

NAME=webapi

[ -f /etc/default/vnet-${NAME} ] && . /etc/default/vnet-${NAME}
export LOG_DIRECTORY

[ -d "${LOG_DIRECTORY}" ] || {
  mkdir ${LOG_DIRECTORY}
}

[ -d "${VNET_ROOT}" ] || {
  logger "no such directory: ${VNET_ROOT}"
  exit 1
}
cd ${VNET_ROOT}/vnet/

bundle exec unicorn \
 -o ${BIND_ADDR:-0.0.0.0} \
 -p ${PORT:-9090} \
 ./rack/config-${NAME}.ru \
    >> ${LOG_DIRECTORY}/${NAME}.log 2>&1
```

```bash:bin/vnet-vna
#!/bin/bash

NAME=vna

[ -f /etc/default/vnet-${NAME} ] && . /etc/default/vnet-${NAME}
export LOG_DIRECTORY

[ -d "${LOG_DIRECTORY}" ] || {
  mkdir ${LOG_DIRECTORY}
}

[ -d "${VNET_ROOT}" ] || {
  logger "no such directory: ${VNET_ROOT}"
  exit 1
}
cd ${VNET_ROOT}/vnet/

bundle exec ./bin/${NAME} \
    >> ${LOG_DIRECTORY}/${NAME}.log 2>&1
```

### Unit作成

systemctlから起動するためにUnitを作成します。

```text
[root@centos7 vnet]# vi /etc/systemd/system/vnet-vnmgr.service
[root@centos7 vnet]# vi /etc/systemd/system/vnet-webapi.service
[root@centos7 vnet]# vi /etc/systemd/system/vnet-vna.service
```

```ini:/etc/systemd/system/vnet-vnmgr.service
[Unit]
Description=OpenVNet Manager Service
After=openvswitch.service redis.service mysql.service
Requires=openvswitch.service redis.service mysql.service

[Service]
Type=simple
ExecStart=/opt/axsh/openvnet/vnet/bin/vnet-vnmgr

[Install]
WantedBy=multi-user.target
```

```ini:/etc/systemd/system/vnet-webapi.service
[Unit]
Description=OpenVNet WebAPI Service
After=openvswitch.service redis.service mysql.service
Requires=openvswitch.service redis.service mysql.service

[Service]
Type=simple
ExecStart=/opt/axsh/openvnet/vnet/bin/vnet-webapi

[Install]
WantedBy=multi-user.target
```

```ini:/etc/systemd/system/vnet-vna.service
[Unit]
Description=OpenVNet Agent Service
After=openvswitch.service redis.service mysql.service
Requires=openvswitch.service redis.service mysql.service

[Service]
Type=simple
ExecStart=/opt/axsh/openvnet/vnet/bin/vnet-vna

[Install]
WantedBy=multi-user.target
```

## 7. OpenVNet用DB作成

MySQLにOpenVNetの初期DBを作成します。

```text
[root@centos7 vnet]# systemctl restart mysql
[root@centos7 vnet]# mysqladmin -uroot create vnet
[root@centos7 vnet]# bundle exec rake db:init
```

> [openvnet-centos7](https://atlas.hashicorp.com/nmatsui/boxes/openvnet-centos7)のVagrant boxでは、この7.までの手順が実施されています。

## 8. OpenVNetの起動状態確認

OpenVNetの各サービス（vnmgr、webapi、vna）を起動し、状態を確認します。
（Unitの依存関係定義に従い、Open vSwitchやRedis、MySQLは停止していても自動起動します）
**Active: active (running)** と表示されていれば、起動成功です。もし **Active: failed** と表示されている場合、これまでのインストール作業のどこかで失敗していることになります。

```text:vnet-vnmgr
[root@centos7 vnet]# systemctl start vnet-vnmgr
[root@centos7 vnet]# systemctl start vnet-webapi
[root@centos7 vnet]# systemctl start vnet-vna
[root@centos7 vnet]# systemctl status vnet-vnmgr
vnet-vnmgr.service - OpenVNet VNManager Service
   Loaded: loaded (/etc/systemd/system/vnet-vnmgr.service; disabled)
   Active: active (running) since Fri 2014-12-12 08:11:53 UTC; 4s ago
 Main PID: 4797 (vnet-vnmgr)
   CGroup: /system.slice/vnet-vnmgr.service
           ├─4797 /bin/sh /opt/axsh/openvnet/vnet/bin/vnet-vnmgr
           └─4798 ruby ./bin/vnmgr

Dec 12 08:11:53 localhost.localdomain systemd[1]: Starting OpenVNet VNManager...
Dec 12 08:11:53 localhost.localdomain systemd[1]: Started OpenVNet VNManager ...
Hint: Some lines were ellipsized, use -l to show in full.
```

```text:vnet-webapi
[root@centos7 vnet]# systemctl status vnet-webapi
vnet-webapi.service - OpenVNet WebAPI Service
   Loaded: loaded (/etc/systemd/system/vnet-webapi.service; disabled)
   Active: active (running) since Fri 2014-12-12 08:12:03 UTC; 4s ago
 Main PID: 4830 (vnet-webapi)
   CGroup: /system.slice/vnet-webapi.service
           ├─4830 /bin/bash /opt/axsh/openvnet/vnet/bin/vnet-webapi
           ├─4831 unicorn master -o 0.0.0.0 -p 9090 ./rack/config-webapi.ru
           └─4834 unicorn worker[0] -o 0.0.0.0 -p 9090 ./rack/config-webapi.r...

Dec 12 08:12:03 localhost.localdomain systemd[1]: Starting OpenVNet WebAPI Se...
Dec 12 08:12:03 localhost.localdomain systemd[1]: Started OpenVNet WebAPI Ser...
Hint: Some lines were ellipsized, use -l to show in full.
```

```text:vnet-vna
[root@centos7 vnet]# systemctl status vnet-vna
vnet-vna.service - OpenVNet Agent Service
   Loaded: loaded (/etc/systemd/system/vnet-vna.service; disabled)
   Active: active (running) since Fri 2014-12-12 08:12:13 UTC; 3s ago
 Main PID: 4856 (vnet-vna)
   CGroup: /system.slice/vnet-vna.service
           ├─4856 /bin/bash /opt/axsh/openvnet/vnet/bin/vnet-vna
           ├─4857 Controller
           └─4865 /opt/axsh/openvnet/vnet/vendor/bundle/ruby/2.1.0/bundler/ge...

Dec 12 08:12:13 localhost.localdomain systemd[1]: Started OpenVNet Agent Serv...
Hint: Some lines were ellipsized, use -l to show in full.
```
ついでにOpenVNetが出力するログにERRORが出力されていないことも確認します。

```text:/var/log/openvnet/vnmgr.log
[root@centos7 vnet]# tail /var/log/openvnet/vnmgr.log 
I, [2014-12-12T08:11:56.232326 #4798]  INFO -- : Rpc initalized.
I, [2014-12-12T08:11:56.963914 #4798]  INFO -- : vdc_vnet_plugin initialized...
```

```text:/var/log/openvnet/webapi.log
[root@centos7 vnet]# tail /var/log/openvnet/webapi.log 
I, [2014-12-12T08:12:04.986618 #4831]  INFO -- : listening on addr=0.0.0.0:9090 fd=9
I, [2014-12-12T08:12:04.986959 #4831]  INFO -- : worker=0 spawning...
I, [2014-12-12T08:12:04.988864 #4831]  INFO -- : master process ready
I, [2014-12-12T08:12:04.989695 #4834]  INFO -- : worker=0 spawned pid=4834
I, [2014-12-12T08:12:04.989993 #4834]  INFO -- : Refreshing Gem list
I, [2014-12-12T08:12:08.787527 #4834]  INFO -- : worker=0 ready
```

```text:/var/log/openvnet/vna.log 
[root@centos7 vnet]# tail /var/log/openvnet/vna.log 
I, [2014-12-12T08:12:16.044798 #4857]  INFO -- : trema: pid_directory:'/var/run/openvnet/pid'.
I, [2014-12-12T08:12:16.047938 #4857]  INFO -- : starting OpenFlow controller.
```

## 9. OpenVNetの動作確認

12/11のAdvent Calendarで書かれている[OpenVNetとDockerを組み合わせてみるデモ](http://qiita.com/qb0c80aE/items/8bdd22d104b06657fd89)を参考に、OpenVNet配下で２つの仮想ネットワークを動作させ、重複したIPアドレスを持つ「container1 ⇔ container3」「container2 ⇔ container4」が問題なく通信できることを確認しました。

```text
[root@centos7 vnet]# cd
[root@centos7 ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
[root@centos7 ~]# vi /etc/sysconfig/network-scripts/ifcfg-br0
[root@centos7 ~]# shutdown -r now
```

```text:/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
DEVICETYPE=ovs
TYPE=OVSPort
OVS_BRIDGE=br0
BOOTPROTO=none
ONBOOT=yes
HOTPLUG=no
```

```text:/etc/sysconfig/network-scripts/ifcfg-br0
DEVICE=br0
DEVICETYPE=ovs
TYPE=OVSBridge
ONBOOT=yes
BOOTPROTO=static
IPADDR=172.16.20.41
NETMASK=255.255.255.0
HOTPLUG=no
OVS_EXTRA="
 set bridge     ${DEVICE} protocols=OpenFlow10,OpenFlow12,OpenFlow13 --
 set bridge     ${DEVICE} other_config:disable-in-band=true --
 set bridge     ${DEVICE} other-config:datapath-id=00004e6d2b508f4c --
 set bridge     ${DEVICE} other-config:hwaddr=02:01:00:00:00:01 --
 set-fail-mode  ${DEVICE} standalone --
 set-controller ${DEVICE} tcp:127.0.0.1:6633
"
```

```text
[vagrant@centos7 ~]$ sudo su -
[root@centos7 ~]# systemctl start vnet-vnmgr
[root@centos7 ~]# systemctl start vnet-webapi
[root@centos7 ~]# systemctl start vnet-vna
[root@centos7 ~]# mkdir vnet-docker
[root@centos7 ~]# cd vnet-docker/
[root@centos7 vnet-docker]# yum install docker -y
[root@centos7 vnet-docker]# systemctl start docker
[root@centos7 vnet-docker]# vi Dockerfile
[root@centos7 vnet-docker]# vi sshd.sh
[root@centos7 vnet-docker]# vi docker-init.sh
[root@centos7 vnet-docker]# vi docker-stop.sh
[root@centos7 vnet-docker]# vi docker-vnet.sh
[root@centos7 vnet-docker]# chmod +x docker*sh
[root@centos7 vnet-docker]# docker build -t centos_sshd .
[root@centos7 vnet-docker]# ./docker-init.sh
[root@centos7 vnet-docker]# ./docker-vnet.sh
[root@centos7 vnet-docker]# docker ps
CONTAINER ID        IMAGE                COMMAND             CREATED             STATUS              PORTS               NAMES
7ad9a8e072b4        centos_sshd:latest   "/bin/bash"         15 seconds ago      Up 15 seconds                           romantic_goldstine     
7efc3d3f23c7        centos_sshd:latest   "/bin/bash"         16 seconds ago      Up 15 seconds                           distracted_wright      
3b3e2efd816d        centos_sshd:latest   "/bin/bash"         17 seconds ago      Up 16 seconds                           backstabbing_hypatia   
b4d6125fc11a        centos_sshd:latest   "/bin/bash"         17 seconds ago      Up 17 seconds                           lonely_brattain        
```

```text:container1⇔container3
[root@centos7 vnet-docker]# docker attach b4d6125fc11a
[root@container1 /]# ssh 10.102.0.11
[root@container3 ~]# ip addr show veth3-2
46: veth3-2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether f2:9e:ec:82:a3:a3 brd ff:ff:ff:ff:ff:ff
    inet 10.102.0.11/24 scope global veth3-2
       valid_lft forever preferred_lft forever
    inet6 fe80::f09e:ecff:fe82:a3a3/64 scope link 
       valid_lft forever preferred_lft forever
```

```text:container2⇔container4
[root@localhost ~]# docker attach 3b3e2efd816d
[root@container2 /]# ssh 10.102.0.11
[root@container4 ~]# ip addr show veth4-2
48: veth4-2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether b6:af:03:a7:6c:05 brd ff:ff:ff:ff:ff:ff
    inet 10.102.0.11/24 scope global veth4-2
       valid_lft forever preferred_lft forever
    inet6 fe80::b4af:3ff:fea7:6c05/64 scope link 
       valid_lft forever preferred_lft forever
```

```bash:Dockerfile
FROM centos:centos6
MAINTAINER nobuyuki.matsui <nobuyuki.matsui@gmail.com>
RUN yum -y update
RUN yum -y install openssh-server openssh-clients
RUN sed -ri 's/^#PermitEmptyPasswords no/PermitEmptyPasswords yes/' /etc/ssh/sshd_config
RUN sed -ri 's/^#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -ri 's/^UsePAM yes/UsePAM no/' /etc/ssh/sshd_config
RUN passwd -d root
ADD sshd.sh /etc/profile.d/
```

```bash:sshd.sh
#!/bin/sh
service sshd start
```

```bash:docker-init.sh
#!/bin/sh

BRIDGE=br0
DOCKER_PID=`ps -ef | grep docker | grep -v grep |  awk '{print $2}'`
DOCKER_IMAGE="centos_sshd"
IP_ADDRESSES=("10.102.0.10/24" "10.102.0.10/24" "10.102.0.11/24" "10.102.0.11/24")

rm -f ./netconfig.env
mkdir -p /var/run/netns/

for i in `seq 1 ${#IP_ADDRESSES[@]}`; do
  let address_index=$i-1
  CONTAINER_ID=`docker run --hostname="container${i}" --net="none" -i -t -d ${DOCKER_IMAGE} /bin/bash`
  BASH_PID=`docker inspect --format {{.State.Pid}} ${CONTAINER_ID}`

  ln -s /proc/${BASH_PID}/ns/net /var/run/netns/${BASH_PID}

  ip link add veth${i}-1 type veth peer name veth${i}-2
  ip link set veth${i}-1 up
  ip link set veth${i}-2 netns ${BASH_PID}
  ip netns exec ${BASH_PID} ip link set veth${i}-2 up
  ip netns exec ${BASH_PID} ip addr add ${IP_ADDRESSES[${address_index}]} dev veth${i}-2

  ovs-vsctl add-port ${BRIDGE} veth${i}-1

  hwaddr=`ip netns exec ${BASH_PID} ip link show veth${i}-2 | awk 'NR==2' | awk '{print $2}'`
  ipaddr=`echo "${IP_ADDRESSES[${address_index}]}" | awk -F/ '{print $1}'`
  netmask=`echo "${IP_ADDRESSES[${address_index}]}" | awk -F/ '{print $2}'`
  echo "veth${i}-2 ${IP_ADDRESSES[${address_index}]} ${hwaddr}"
  echo "export mac_veth${i}2=${hwaddr}" >> ./netconfig.env
  echo "export ip_veth${i}2=${ipaddr}" >> ./netconfig.env
  echo "export netmask_veth${i}2=${netmask}" >> ./netconfig.env
done
```

```bash:docker-stop.sh
#!/bin/sh

BRIDGE=br0

ovs-vsctl show | grep "Port \"veth" | awk '{print $2}' | sed -e 's/"//g' | while read port; do
  ovs-vsctl del-port ${BRIDGE} ${port}
done

docker ps | awk '{print $1}' | grep -v grep | grep -v CONTAINER | while read container_id; do
  docker kill ${container_id}
done

rm -rf /var/run/netns/*
```

```bash:docker-vnet.sh
#!/bin/sh

set -e
set -x

BASE="/opt/axsh/openvnet"
VNETPATH="${BASE}/vnet"
VNCTLPATH="${BASE}/vnctl"

mysqladmin -f -uroot drop vnet
mysqladmin -uroot create vnet
(cd ${VNETPATH}; bundle exec rake db:init)

. ./netconfig.env

cd ${VNCTLPATH}

# datapaths
bin/vnctl datapaths add \
  --uuid="dp-node1" \
  --display-name="node1" \
  --dpid="0x00004e6d2b508f4c" \
  --node-id="node1"

# networks
bin/vnctl networks add \
  --uuid="nw-vnet1" \
  --display-name="nw-vnet1" \
  --ipv4-network="10.100.0.0" \
  --ipv4-prefix="24" \
  --network-mode="virtual"

bin/vnctl networks add \
  --uuid="nw-vnet2" \
  --display-name="nw-vnet2" \
  --ipv4-network="10.100.0.0" \
  --ipv4-prefix="24" \
  --network-mode="virtual"

# interfaces
bin/vnctl interfaces add \
  --uuid="if-veth1" \
  --owner-datapath-uuid="dp-node1" \
  --network-uuid="nw-vnet1" \
  --mac-address="${mac_veth12}" \
  --ipv4-address="${ip_veth12}" \
  --port-name="veth1-1"

bin/vnctl interfaces add \
  --uuid="if-veth2" \
  --owner-datapath-uuid="dp-node1" \
  --network-uuid="nw-vnet2" \
  --mac-address="${mac_veth22}" \
  --ipv4-address="${ip_veth22}" \
  --port-name="veth2-1"

bin/vnctl interfaces add \
  --uuid="if-veth3" \
  --owner-datapath-uuid="dp-node1" \
  --network-uuid="nw-vnet1" \
  --mac-address="${mac_veth32}" \
  --ipv4-address="${ip_veth32}" \
  --port-name="veth3-1"

bin/vnctl interfaces add \
  --uuid="if-veth4" \
  --owner-datapath-uuid="dp-node1" \
  --network-uuid="nw-vnet2" \
  --mac-address="${mac_veth42}" \
  --ipv4-address="${ip_veth42}" \
  --port-name="veth4-1"

systemctl restart vnet-vna
```

## 最後に

何度も地雷を踏み抜き、やっとここまでたどり着きました。CentOS7でもOpenVNetは無事に動作するようです。これでOpenVNetの利用シーンが広がると良いですね。