2013年12月24日火曜日

Network Namespace を使って OpenVNet を動かしてみる

先日 Wakame Advent Calendar の記事として コマンドラインからだけで OpenVNet の機能を推測してみる という記事を書きましたが、その後実際に動かしていませんでした。

最初は、Ubuntu で OpenVNet を動かして、いんちきで OpenStack と接続してみようと思ったのですが、Ubuntu では 12.04 でも 13.04 でも 13.10 でも VNA が起動できなかったので、もう少し軽く動かしてみます。 Ubuntu 13.10 では wakame-edge のコンパイルも失敗しました (trema-edge では修正されています)。

今回は Network Namespace を使って OpenVNet の動作を確認してみようと思います。動作確認するのは以下の3つです。

  • 仮想ネットワークを作成
  • IPアドレスが重複する仮想ネットワークでの動作
  • 仮想ネットワーク間のルーティング

Network Namespace は 1 つの Linux ホストの中に仮想的なネットワーク環境を複数作れる機能です。これを使うと、ネットワークの実験を VM などリソースをたくさん消費する手段を使わずにできるので便利です。仮想ネットワークを複数作ってみる方法については、OpenVNet Installation Guideには、VM 環境を使って OpenVNet を動かしてみる方法が紹介されていますが、Network Namespace を使うとお手軽に実験できるので、今回はその方法を紹介します。

今回の動作確認の中でいくつかスクリプトを作りました。OpenVNet test tools with network namespace においてありますので、適当に参考にしてください。

CentOS6 で Network Namespace を使う準備

Network Namespace は最近新しめの Linux Kernel を採用している Ubuntu などではそのままで利用できますが、OpenVNet の推奨環境となっている CentOS6 では残念ながら、まだそのままでは動きません。

設定方法を CentOS6 で Linux Network Namespace を使うにまとめましたので、こちらを参照して、必要な iproute パッケージ (ip コマンド) を入れておいて下さい。

OpenVNet のインストール

OpenVNet Installation Guideにしたがって、インストールを行います。

"Let's try 1Box OpenVNet" の前までを実施します。

注意点としては、OpenVNet のサービスを開始する前に redis も開始しておく必要があります。

# chkconfig redis on
# service redis start

CentOS6.4 が推奨となっていますが、今回は CentOS6.5 を使いましたが問題なく動作しました。

仮想ネットワークの作成

準備ができたので、2つの VM が接続された仮想ネットワーク net1 を作成してみます。

  • 仮想ネットワーク net1 : 172.16.1.0/24
    • インタフェース1 (VM1 相当) : 172.16.1.1 (@netns ns1)
    • インタフェース1 (VM2 相当) : 172.16.1.2 (@netns ns2)

手順を順番に見ていきます。 Installation Guide に説明がある 1 ホストで VM を使って動かす例についている設定スクリプト db.sh を参考に整理してみました。

まず、最初に OpenFlow として動作する Open vSwitch bridge を OpenVNet に登録します。Open vSwitch bridge は br0 です。今回は 1 ホストなので、最初に一回 datapath を登録します。

https://github.com/amotoki/openvnet-test-tools/blob/master/vnet-register-datapath.sh#L17
# uuid は dp- で始める必要あり
# dpid は 0x を先頭に付けること (OVS の出力とは違うので注意)
./vnctl datapath add ¥
    --uuid dp-br0 ¥
    --display-name=br0 ¥
    --dc-segment-id=seg1 ¥
    --dpid=0x000002fdee8e0a44 ¥
    --ipv4-address=$HOST_IP192.168.122.207 ¥
    --node-id=192.168.122.207
openvnet にネットワークを作成します。
https://github.com/amotoki/openvnet-test-tools/blob/master/vnet-register-net1.sh#L20
# ネットワークの作成
# 仮想ネットワークなので network-mode は virtual を指定する
# uuid は nw- で始める必要あり
./vnctl network add ¥
  --uuid nw-net1 --display-name=net1 --ipv4-network 172.16.1.0 --ipv4-prefix=24 ¥
  --domain-name=dom1 --network-mode=virtual

# datapath に作成したネットワークを関連付ける
# broadcast-mac-address は MAC2MAC でブロードキャストパケットを転送する際に使用されるはず
./vnctl datapath networks add dp-$BRNAME nw-net1 --broadcast-mac-address=08:00:27:10:03:01

# ネットワークに接続されるインタフェースを登録する
# uuid は単なる ID ではなく、OVS に追加するポートの名前と一致している必要があるみたい。また、if- で始める必要あり。
# IPv4 address と MAC はそのインタフェースの値を指定する。VM の場合は VM の中の NIC、network namespace の場合は
# namespace 内の NIC の値になる。OVS に add-port する network device の値ではない点に注意。
./vnctl interface add --uuid=if-veth1 --ipv4-address=$IP1 --network-uuid=nw-net1 --mac-address=$MAC1
./vnctl interface add --uuid=if-veth2 --ipv4-address=$IP2 --network-uuid=nw-net1 --mac-address=$MAC2
上記で OpenVNet 側の設定は終わりです。

次に、実際のデバイスを作成します。
./ovs-create.sh
./if-create-net1.sh
ovs-create.sh は OVS bridge を作成し、datapath ID 設定、OpenFlow 設定などを行っています。今回は OpenVNet の設定を行った後でないと、うまく動かなかったので、このタイミングで行っています。

/var/log/wakame-vnet/vna.log を見ると、OVS から接続や、スイッチポートが追加されていることが分かります。

ping を実行してみましょう。
network namespace ns1 の 172.16.1.1 側から ns2 の 172.16.1.2 に ping を送ります。
# ip netns
ns2
ns1
# ip netns exec ns1 ip -o addr
207: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN \    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
207: lo    inet 127.0.0.1/8 scope host lo
207: lo    inet6 ::1/128 scope host \       valid_lft forever preferred_lft forever
208: ns-veth1:  mtu 1500 qdisc pfifo_fast state UP qlen 1000\    link/ether 52:54:00:0d:84:01 brd ff:ff:ff:ff:ff:ff
208: ns-veth1    inet 172.16.1.1/24 brd 172.16.1.255 scope global ns-veth1
208: ns-veth1    inet6 fe80::5054:ff:fe0d:8401/64 scope link \       valid_lft forever preferred_lft forever
# ip netns exec ns1 ping -c 5 172.16.1.2
PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data.
64 bytes from 172.16.1.2: icmp_seq=1 ttl=64 time=0.466 ms
64 bytes from 172.16.1.2: icmp_seq=2 ttl=64 time=0.134 ms
64 bytes from 172.16.1.2: icmp_seq=3 ttl=64 time=0.058 ms
64 bytes from 172.16.1.2: icmp_seq=4 ttl=64 time=0.066 ms
64 bytes from 172.16.1.2: icmp_seq=5 ttl=64 time=0.063 ms

--- 172.16.1.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4000ms
rtt min/avg/max/mdev = 0.058/0.157/0.466/0.157 ms
# ip netns exec ns1 arp -na
? (172.16.1.2) at 52:54:00:0d:84:02 [ether] on ns-veth1
ns2 の 172.16.1.2 側で tcpdump を仕掛けておくとパケットが見えます。
# ip netns exec ns2 tcpdump -i ns-veth2
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ns-veth2, link-type EN10MB (Ethernet), capture size 65535 bytes
01:16:35.234573 ARP, Request who-has 172.16.1.2 tell 172.16.1.1, length 28
01:16:35.234610 ARP, Reply 172.16.1.2 is-at 52:54:00:0d:84:02 (oui Unknown), length 28
01:16:35.234709 IP 172.16.1.1 > 172.16.1.2: ICMP echo request, id 12927, seq 1, length 64
01:16:35.234758 IP 172.16.1.2 > 172.16.1.1: ICMP echo reply, id 12927, seq 1, length 64
01:16:36.234855 IP 172.16.1.1 > 172.16.1.2: ICMP echo request, id 12927, seq 2, length 64
01:16:36.234917 IP 172.16.1.2 > 172.16.1.1: ICMP echo reply, id 12927, seq 2, length 64
01:16:37.234633 IP 172.16.1.1 > 172.16.1.2: ICMP echo request, id 12927, seq 3, length 64
01:16:37.234651 IP 172.16.1.2 > 172.16.1.1: ICMP echo reply, id 12927, seq 3, length 64
01:16:38.234501 IP 172.16.1.1 > 172.16.1.2: ICMP echo request, id 12927, seq 4, length 64
01:16:38.234522 IP 172.16.1.2 > 172.16.1.1: ICMP echo reply, id 12927, seq 4, length 64
01:16:39.234528 IP 172.16.1.1 > 172.16.1.2: ICMP echo request, id 12927, seq 5, length 64
01:16:39.234550 IP 172.16.1.2 > 172.16.1.1: ICMP echo reply, id 12927, seq 5, length 64
01:16:40.234515 ARP, Request who-has 172.16.1.1 tell 172.16.1.2, length 28
01:16:40.234793 ARP, Reply 172.16.1.1 is-at 52:54:00:0d:84:01 (oui Unknown), length 28
^C
14 packets captured
14 packets received by filter
0 packets dropped by kernel

IPアドレスが重複する仮想ネットワークでの動作


仮想ネットワークといえば、IP アドレス重複に対応できるか!です。もちろん試してみましょう。
先ほどの net1 に追加で、同じ IP アドレスを持つ net3 を作成します。
  • 仮想ネットワーク net1 : 172.16.1.0/24
    • インタフェース : 172.16.1.1 (@netns ns1)
    • インタフェース : 172.16.1.2 (@netns ns2)
  • 仮想ネットワーク net3 : 172.16.1.0/24
    • インタフェース : 172.16.1.1 (@netns ns5)
    • インタフェース : 172.16.1.2 (@netns ns6)
OpenVNet にネットワークとインタフェースを登録して、その後実際のデバイスを作成します。net1 のときと全く同じなので、説明は省略します。
./vnet-register-net3.sh
./if-create-net3.sh
ns1 の 172.16.1.1 と ns5 の 172.16.1.1 からそれぞれ 172.16.1.2 に ping を送ってみます。ns1 から送った時は同じ net1 側の ns2 の 172.16.1.2で、ns5 から送った時は net3 側の ns6 の 172.16.1.2 にパケットが届いていることが確認できます。片方の結果だけ載せておきます。
(net3 側の 172.16.1.1 から ping)
# ip netns exec ns5 ping -c 3 172.16.1.2
PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data.
64 bytes from 172.16.1.2: icmp_seq=1 ttl=64 time=1.68 ms
64 bytes from 172.16.1.2: icmp_seq=2 ttl=64 time=0.058 ms
64 bytes from 172.16.1.2: icmp_seq=3 ttl=64 time=0.048 ms

--- 172.16.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.048/0.596/1.683/0.768 ms

(net1 側の 172.16.1.2)
# ip netns exec ns2 tcpdump -i ns-veth2
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ns-veth2, link-type EN10MB (Ethernet), capture size 65535 bytes
^C
0 packets captured
0 packets received by filter
0 packets dropped by kernel

(net3 側の 172.16.1.2)
# ip netns exec ns5 tcpdump -i ns-veth5
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ns-veth5, link-type EN10MB (Ethernet), capture size 65535 bytes
01:34:38.493450 ARP, Request who-has 172.16.1.2 tell 172.16.1.1, length 28
01:34:38.493998 ARP, Reply 172.16.1.2 is-at 52:54:00:0d:84:06 (oui Unknown), length 28
01:34:38.494005 IP 172.16.1.1 > 172.16.1.2: ICMP echo request, id 57983, seq 1, length 64
01:34:38.494093 IP 172.16.1.2 > 172.16.1.1: ICMP echo reply, id 57983, seq 1, length 64
01:34:39.493507 IP 172.16.1.1 > 172.16.1.2: ICMP echo request, id 57983, seq 2, length 64
01:34:39.493546 IP 172.16.1.2 > 172.16.1.1: ICMP echo reply, id 57983, seq 2, length 64
01:34:40.493471 IP 172.16.1.1 > 172.16.1.2: ICMP echo request, id 57983, seq 3, length 64
01:34:40.493503 IP 172.16.1.2 > 172.16.1.1: ICMP echo reply, id 57983, seq 3, length 64
01:34:43.493577 ARP, Request who-has 172.16.1.1 tell 172.16.1.2, length 28
01:34:43.493588 ARP, Reply 172.16.1.1 is-at 52:54:00:0d:84:05 (oui Unknown), length 28
^C
10 packets captured
10 packets received by filter
0 packets dropped by kernel
IP アドレス帳服がある場合でも、期待通り仮想ネットワークが機能しています。

仮想ネットワーク間のルーティング

最後に、仮想ネットワーク間でのルーティングをさせてみたいと思います。先日、コマンドラインからだけで OpenVNet の機能を推測してみる記事を書いた時にはいまいちよく分からなかったのですが、サンプルスクリプトの db.sh などと睨めったことしつつなんとなく分かって来ましたので、試してみました。

IP アドレスの違う論理ネットワークを2つ用意し、それらを論理ルータで接続する構成です。論理ルータは 172.16.1.254 と 172.16.2.254 という2つのインタフェースを持ちます。
  • 仮想ネットワーク net1 : 172.16.1.0/24
    • インタフェース : 172.16.1.1 (@netns ns1)
    • インタフェース : 172.16.1.2 (@netns ns2)
    • ルータインタフェース : 172.16.1.254
  • 仮想ネットワーク net2 : 172.16.2.0/24
    • インタフェース : 172.16.2.3 (@netns ns3)
    • インタフェース : 172.16.2.4 (@netns ns4)
    • ルータインタフェース : 172.16.2.254
まず、net2 を作成しておきます。手順はこれまでと全く同じです。net2 で ping などを行って、導通を確認しておきましょう。
./vnet-register-net2.sh
./if-create-net2.sh
OpenVNet 側にルータを作成していきます。次のような手順になります。
  1. ルータインタフェースの作成
  2. ルータインタフェースに対して network_service を関連付け (なくても動く)
  3. route_link の作成
  4. route_link の datapath への関連付け (なくても動く)
  5. route 情報の登録
最初の2つがルータのインタフェースに関する操作、後ろの3つがルータの宣言のようなものです。
ざっくり言うと、route_link が論理ルータに対応します。 route は論理ルータの経路情報です。名前が分かりにくいですね。

サンプルスクリプト db.sh に書かれている手順を参考にしていますが、network_service の作成、route_link の datapath への関連付けの2つはなくても動きました。どういうことでしょう?

実際のコマンドベースで説明します。一部のコマンドは CLI では提供されていないので、curl を直接叩いています。
https://github.com/amotoki/openvnet-test-tools/blob/master/vnet-register-router.sh#L29
# net1 の論理ルータに対応するインタフェースを作成
# OpenVNet が機能を提供するので mode=simulated を指定する
# vnctl CLI では mode が指定できないので、curl を使う
curl -s -X POST --data-urlencode uuid=if-vnet1gw ¥
  --data-urlencode network_uuid=nw-net1 ¥
  --data-urlencode mac_address=52:54:00:74:00:00 ¥
  --data-urlencode ipv4_address=172.16.1.254 ¥
  --data-urlencode mode=simulated ¥
  http://localhost:9090/api/interfaces

# ルータインタフェースの終端を OpenVNet が行うことの宣言のようです。
# ★ 1 ホストでのテストでは、なくても動きました。
./vnctl network_service add --uuid=ns-vnet1gw --interface-uuid=if-vnet1gw --display-name=router

# net2 の論理ルータに対応するインタフェースを作成
# OpenVNet が機能を提供するので mode=simulated を指定する
# vnctl CLI では mode が指定できないので、curl を使う
curl -s -X POST --data-urlencode uuid=if-vnet2gw ¥
  --data-urlencode network_uuid=nw-net2 ¥
  --data-urlencode mac_address=52:54:00:74:22:22 ¥
  --data-urlencode ipv4_address=172.16.2.254 ¥
  --data-urlencode mode=simulated ¥
  http://localhost:9090/api/interfaces

# ルータインタフェースの終端を OpenVNet が行うことの宣言のようです。
# ★ 1 ホストでのテストでは、なくても動きました。
./vnctl network_service add --uuid=ns-vnet2gw --interface-uuid=if-vnet2gw --display-name=router

# 論理ルータの作成
# OpenVNet では route_link という概念として表現される
# MAC address が何に利用されるのかは不明
./vnctl route_link add --uuid=rl-vnetlink1 --mac-address=52:54:00:60:11:11

# 作成した route_link を datapath に登録する
# ★ 1 ホストでのテストでは、なくても動きました。
curl -s -X POST --data-urlencode route_link_uuid=rl-vnetlink1 \
  --data-urlencode mac_address=08:00:27:20:01:01 \
  http://localhost:9090/api/datapaths/dp-br0/route_links/rl-vnetlink1

# 論理ルータでの経路情報を登録する
curl -s -X POST --data-urlencode uuid=r-vnet1 ¥
  --data-urlencode interface_uuid=if-vnet1gw ¥
  --data-urlencode route_link_uuid=rl-vnetlink1 ¥
  --data-urlencode ipv4_network=172.16.1.0 ¥
  http://localhost:9090/api/routes
curl -s -X POST --data-urlencode uuid=r-vnet2 ¥
  --data-urlencode interface_uuid=if-vnet2gw ¥
  --data-urlencode route_link_uuid=rl-vnetlink1 ¥
  --data-urlencode ipv4_network=172.16.2.0 ¥
  http://localhost:9090/api/routes
上記を実行して、OpenVNet に登録します。ルータ機能は OpenVNet が提供するので、実際のデバイスの設定は必要ありません。
./vnet-register-router.sh
net1 と net2 の間で ping を行ってみます。 net1 の 172.16.1.1 (@ns1) から net2 の 172.16.2.3 (@ns3) に ping を実行しています。ちゃんと ping が通りました。成功です。

# ip netns exec ns1 ping 172.16.2.3
PING 172.16.2.3 (172.16.2.3) 56(84) bytes of data.
64 bytes from 172.16.2.3: icmp_seq=1 ttl=64 time=20.0 ms
64 bytes from 172.16.2.3: icmp_seq=2 ttl=64 time=0.060 ms
64 bytes from 172.16.2.3: icmp_seq=3 ttl=64 time=0.056 ms
^C
--- 172.16.2.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2550ms
rtt min/avg/max/mdev = 0.056/6.711/20.018/9.409 ms
/var/log/wakame-vnet/vna.log を見ると、vna が ARP に応答している記録もあります。

I, [2013-12-24T02:41:50.725318 #2463]  INFO -- : 0x000002fdee8e0a44 interfaces/simulated: simulated arp reply (arp_tpa:172.16.1.254)
I, [2013-12-24T02:41:50.735063 #2463]  INFO -- : 0x000002fdee8e0a44 interfaces/simulated: simulated arp reply (arp_tpa:172.16.2.254)
ちなみに、ルータインタフェースへの ping は通りませんでした。

# ip netns exec ns1 ping 172.16.1.254
PING 172.16.1.254 (172.16.1.254) 56(84) bytes of data.
^C
--- 172.16.1.254 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 4590ms

まとめ

今回は OpenVNet の基本的な使い方を Network Namespace を使って実験してみました。仮想ネットワークの作成、重複 IP アドレスの扱い、仮想ルータを使った通信をどうやって行うのかは分かりました。外部の物理ネットワークとの通信方法は時間があれば調査してみようと思います。

テスト中には、コマンドの投入順序の違いなどで動かず、やり直してみたら動いた、といった点もありました。全体的に、OpenVNet に情報 (datapath や interface) を登録してから、OVS から VNA への接続やインタフェースの OVS への追加を行う必要があるみたいです。今後そのあたりは改善されていくと思います。また、一部の機能は CLI からは制御できないようです。そのうち対応されるのではないかと思います。

OpenVNet API を見ながら仮想ネットワークのAPIについて考えたこと

Wakame Advent CalendarをきっかけにOpenVNetのAPIを見て思ったことを書いてみたいと思います。OpenFlow Controller の Northband API や OpenStack Neutron API なども見ているので、どうなっているとうれしいのか考えてみたい。

API はまだまだ発展途上にあると思われるので、何かの参考になればと思います。

  • datapath にネットワークを登録するのはなぜ?
  • API で datapath の登録は必要なのか?
  • Interface の論物マッピングの指定方法
  • 論理モデルや名称は既存の概念に近い方がよいのでは?
  • OpenVNet 内部で使用する MAC アドレスの指定はない方がよい
  • UUID が UUID ではない

datapath にネットワークを登録するのはなぜ?

ネットワークは論理的なものであり、どのノードに広がって存在するかはそのときの インタフェースの登録状況で決まるのが自然だろう。 一方、datapath は特定のノードに存在する OpenFlow スイッチ (OVS) に対応するものなので、 datapath にネットワークを登録するということは、ネットワークが新しいノードの広がる場合には ネットワークを datapath に登録しないといけないということにもなるし、 逆に datapath にネットワークを登録していないと、ネットワークがそのノードには 広がることができないということになる。

datapath とネットワークの関連付けは OpenVNet の中で面倒をみるようになっていると API を使う側から見るとうれしい。 datapath にネットワークを登録するのは実装上の都合のように思える。

同じことが route_link についても言えると思う。

API で datapath の登録は必要なのか?

OVS が VNA に接続してくるので、OpenVNet はどの OVS が配下にいるのか分かるので、 datapath を API 経由で登録しておく必要はないように思える。

上で書いたように、現在はネットワークを datapath に登録するというステップがあるので、 登録対象となる datapath を API で登録する手順になっているように思えた。 それだけの理由であれば、datapath を API 経由で登録する必要はないと思われる。

datapath を API で登録することに意味がないか、他に考えてみると、 自分の配下にある OVS を明示的に管理しておき、意図しない OVS が接続されてしまうことを避けるという 可能性がある。OpenVNet の場合は、現在のところ OpenFlow Controller と OVS が同じホスト上で動作することが前提になっているので、この目的は必要性が少なそうに見える。

やはりいらないのだろうか? もちろん datapath 一覧を取得する方はインベントリーの意味があると思う。

Interface の論物マッピングの指定方法

リソース Interface は、論理ネットワークにおける論理インタフェースを表しているが、 同時に論理インタフェースと物理情報の対応付けも必要である。 現在の Interface 作成時のパラメータにも、これらの両方が含まれているが、 物理情報の指定はもっと明示的なパラメータにした方がよいと思われる。

現在、物理インタフェースとの対応付けに使われる情報は、以下の2つである。

  • uuid
  • owner-datapath-id

UUID は必ず "if-****" という形式である必要があり、この情報が OVS に登録する物理ポートとの対応付けにも使用されている。UUID という名前からは物理インタフェースとの対応付けに使用されるとは、到底想像できないので、明らかに別パラメータを用意した方がいいと思う。

datapath-id の方は省略可能なパラメータになっているが、これは物理インタフェース名がシステム全体で一意であれば datapath-id がなくても一意に識別できるからだと推測している。

OpenFlow ネットワークで、スイッチポートを識別する情報としては、

  • (datapath_id, switch port name)
  • (datapath_id, switch port number)
  • (datapath_id, MAC address)

などが考えられる。

安全に OpenFlow ネットワークでスイッチポートを識別するには、最初の2つのいずれかを利用できる必要がある。 この方法は、OpenFlow Controller では一般的に使用されている。例えば、 Trema ベースで作られている Virtual Network PlatformAPI のポート作成 (POST /networks/<net_id>/ports) では、 datapath_id と インタフェース名 (name) または スイッチポート番号 (number) のいずれかを指定する。Trema Sliceable Switch の API では datapath_id と port (ポート番号) の組み合わせで指定する。他の OpenFlow Controller でもこの方法が一般的に使用されている。

ポート番号を指定する方法とインタフェース名を指定する方法を比べると、インタフェースを指定する方法の方がサーバー管理者から見ると敷居が低いと思う。いくつか理由があると思う。一つは、VM を起動する際に、インタフェース名は libvirt の設定ファイルなどでも登場するため、サーバー管理者にも比較的馴染みがあるパラメータだという点。もうひとつは、ポート番号は OpenFlow スイッチにインタフェースを接続してみないと分からず、インタフェース名の方が変化が少ないため、管理しやすいということである。

(datapath_id, MAC address) の方法は、VM 管理などサーバー側の管理者から見るとわかりやすい指定方法である。OpenFlow スイッチでのポート番号を知る必要がないので、API を利用するにあたっての敷居が低くなる。一方、スイッチポートから受信したパケットの MAC アドレスを信用して処理を行うため、MAC アドレスの信頼性をどうやって確保するかが課題となる。そのため、あまり積極的には使われていない印象を受ける。

比較すると、(datapath_id, インタフェース名) を指定する方法が自然に見える。

論理モデルや名称は既存の概念に近い方がよいのでは?

最初に API を見た時、route_link っていったい何だろう?と思いました。サンプルスクリプトを見てみると、実は論理ルータと1:1に対応しているみたいと気付くと、あとは簡単でした。

このとき思ったのが、最初から router という名前だったら分かりやすかったのではないか?ということでした。

仮想ネットワークを作成する際も、論理構造としては、L2、L3 などのこれまで広まっている IP ネットワークの考え方やモデルが基本になってくると思います。ネットワーク仮想化は、論理構造と物理構造を分離して使い勝手を向上するのがひとつの価値ですが、その際に論理構造の定義は既存の概念を踏襲できると、とっつきやすいと思います。一方で、論理構造を物理構造にどのようにマッピングするかは、それぞれのネットワーク仮想化プラットフォームの腕の見せどころなのだと思います。

OpenVNet 内部で使用する MAC アドレスの指定はない方がよい

OpenVNet の API では、ネットワークの MAC2MAC で使用するブロードキャストアドレスや、 route_link の MAC アドレスなど、OpenVNet の内部で使用する MAC アドレスを指定する必要がある。 これらは API を利用する人から見ると、どの MAC アドレスが割り当て済みなのか管理する必要があり、指定することが難しい。あらかじめ OpenVNet が使用してよい MAC アドレス空間をプールとして登録しておき、自動で払い出すようにすべきだと思う。場合によっては Wakame や OpenVNet で OUI を取得してもいいかもしれない。

同様のことは、OpenVNet が機能を提供するルータや DHCP などの mode-simulated のインタフェースについても言える。これらの MAC アドレスも自動で払いだしてくれるとうれしい。

UUID が UUID ではない

これは些細なこと。API でリソース識別子として UUID というフィールドがあるが(以下の引用はネットワークの例)、 正確には UUID ではなく、単なる ID である。

また、OpenVNet の UUID フィールドはリソース種別に応じたプレフィックスが必要である (ネットワークの場合は nw-)。この意味でも、純粋な UUID ではない。

UUID は RFC 4122 http://www.ietf.org/rfc/rfc4122.txt でそのフォーマットや ユニーク性を担保して値を生成する方法が規定されている。 UUID とするのであれば、きちんと RFC で定められた UUID を生成するのがよいと思う。

# ./vnctl.sh network show
{"id"=>1,
 "uuid"=>"nw-net1",
 "display_name"=>"net1",
 "ipv4_network"=>"172.16.1.0",
 "ipv4_prefix"=>24,
 "domain_name"=>"dom1",
 "network_mode"=>"virtual",
 "editable"=>nil,
 "created_at"=>"2013-12-23T17:24:53Z",
 "updated_at"=>"2013-12-23T17:24:53Z",
 ""=>nil}

まとめ

OpenVNet API へのコメントが中心ですが、仮想ネットワークの API について考えたことを書き連ねてみました。 API を比較すると設計思想などが見えてくるので、比べてみるのはおもしろいです。

OpenVNet の話をすると、API はいろいろと改善の余地がありそうです。まだ生まれたてなので、機能が大きくなる前に API がどうあるべきかの観点からの見直しを行うのも一つの選択肢かなとも思いました。

2013年12月23日月曜日

CentOS6 で Linux Network Namespace を使う

Network Namespace は 1 つの Linux ホストの中に仮想的なネットワーク環境を複数作れる機能です。これを使うと、ネットワークの実験を VM などリソースをたくさん消費する手段を使わずにできるので便利です。

Network Namespace は最近新しめの Linux Kernel を採用している Ubuntu などではそのままで利用できますが、RHEL6/CentOS6 ではまだ標準では利用できません。 RedHat が中心となって開発している OpenStack ディストリビューション RDO のパッケージを使うことで、簡単に CentOS6 環境でも Network Namespace が利用できるので、紹介します。

RDO が RHEL6/CentOS6 向けに Network Namespace に対応したパッケージを用意しているのは、OpenStack Neutron では Reference Implementation は Network Namespace の機能が利用されており、RHEL6/CentOS6 環境で OpenStack を動かせるようにするためです。

Network Namespace (netns) を動かすためには、netns に対応した Linux Kernel と netns に対応した iproute パッケージ (ip コマンド) が必要です。
CentOS6.5 とそれ以前では、カーネルの対応状況が異なりますので、分けて説明します。

CentOS 6.5 (以降)

CentOS 6.5 で提供されるカーネル自身は netns に対応していますが、標準で提供されている iproute は netns に対応していません (ip netns というサブコマンドがありません)。

RDO の yum レポジトリから iproute パッケージをインストールします。
  • RDO の yum レポジトリを追加してからインストールする方法
  • RDO で提供される iproute RPM パッケージを直接指定する
の2つの方法があります。今現在は後者の方が楽だと思いますが、パッケージバージョンの変更には前者の方が強いでしょう。
RDO の yum レポジトリを追加してからインストールする方法
rdo-release.rpm をインストールすると、RDO 関連の yum repository 定義が /etc/yum.repos.d 以下に登録されます。その後、yum install で iproute を指定してインストールします。
# yum install http://rdo.fedorapeople.org/rdo-release.rpm
# yum install iproute
インストール後に期待通りのバージョンがインストールされているか確認します。あわせて、netns がきちんと動作するか確認しておきます。
# rpm -qa | grep iproute
iproute-2.6.32-130.el6ost.netns.2.x86_64
# ip netns
# ip netns add testns1
# ip netns
testns1
# ip netns delete testns1
RDO で提供される iproute RPM パッケージを直接指定する
# yum install http://repos.fedorapeople.org/repos/openstack/openstack-havana/epel-6/iproute-2.6.32-130.el6ost.netns.2.x86_64.rpm
パッケージは以下の URL にありますので、もしパッケージのバージョン番号が変わっていた場合はチェックしてみてください。古いものがなくなることはあまりありませんが。
http://repos.fedorapeople.org/repos/openstack/openstack-havana/epel-6/

CentOS 6.4 以前

CentOS 6.4 以前では、カーネルも network namespace に対応していません。そのため、カーネルと iproute パッケージの両方を新しくする必要があります。
http://repos.fedorapeople.org/repos/openstack/openstack-havana/epel-6/ にパッケージがありますので、kernel と iproute を探してインストールします。
  • kernel-2.6.32-358.123.2.openstack.el6.x86_64.rpm, kernel-firmware-2.6.32-358.123.2.openstack.el6.noarch.rpm
  • iproute-2.6.32-130.el6ost.netns.2.x86_64.rpm
個別にインストールするよりは、上記の CentOS6.5 の説明の「RDO の yum レポジトリを追加してからインストールする方法」にあるように yum repository を追加しておいた方が楽だと思います。

では、Network Namespace を使って、お手軽にネットワーク実験をお楽しみください。

2013年12月17日火曜日

コマンドラインからだけで OpenVNet の機能を推測してみる

Wakame Advent Calendar http://atnd.org/events/45749 を機会に wakame-vdc から分離された? OpenVNet を触ってみようと思います。機能を知るには API を見るのが一番なので、まずは動かす前に API を見てみます。 API は https://github.com/axsh/openvnet/wiki/WebAPI-Reference にあるということですが、最新版ではないかも?という噂を聞いたので、今回は CLI の vnctl のコマンドラインから機能を推測してみることにします(きちんと更新されているようでしたらごめんなさい)。実際に動かしてみるのは明日以降にします。

CLI のインストール


Advent Calendar 2日目のエンジニアじゃないけど仮想ネットワークOSSのOpenVNetをサクっとインストールしとく。 #wakameug を参考にインストールしてみます。

用意した環境はインストールガイドと微妙に違いますが、CentOS 6.5 に入れました。
# vi /etc/yum.repos.d/openvnet.repo
[openvnet]
name=OpenVNet
baseurl=http://dlc.openvnet.axsh.jp/packages/rhel/6/vnet/current/
enabled=1
gpgcheck=0
# vi /etc/yum.repos.d/openvnet-third-party.repo
[openvnet-third-party]
name=OpenVNet Third Party
baseurl=http://dlc.openvnet.axsh.jp/packages/rhel/6/third_party/current/
enabled=1
gpgcheck=0
# rpm -Uvh http://dlc.wakame.axsh.jp.s3-website-us-east-1.amazonaws.com/epel-release
# yum install -y wakame-vnet

今日は実際のデーモンは起動しないので、CLI が使える環境を設定だけ。

# export PATH=/opt/axsh/wakame-vnet/ruby/bin:/opt/axsh/wakame-vnet/vnctl/bin:$PATH
# which vnctl
/opt/axsh/wakame-vnet/vnctl/bin/vnctl
# which ruby
/opt/axsh/wakame-vnet/ruby/bin/ruby
# ruby --version
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-linux]
# vnctl
/opt/axsh/wakame-vnet/vnctl/bin/vnctl:8:in `<main>': undefined method `setup' for Bundler:Module (NoMethodError)

vnctl と ruby が入っている場所に PATH を通してみたのですが、vnctl がうまく動きません。 Ruby の bundler の設定が必要なようです。 Ruby の bundler 初心者の僕にはよく分かりません。検索してみると、 bundler は Gemfile.lock というファイルが場所で bundle exec でファイルを実行するといいみたいです。 /etc/init/vnctl.conf でもそうなっているので、チャレンジしてみます。

# cd /opt/axsh/wakame-vnet/vnctl/
# which bundle
/opt/axsh/wakame-vnet/ruby/bin/bundle
# bundle exec ./bin/vnctl
Could not find fuguta-1.0.2 in any of the sources
Run `bundle install` to install missing gems.

まだダメです。言われたとおりに bundle install を実行してみます。

# bundle install
Fetching gem metadata from http://rubygems.org/.......
Fetching gem metadata from http://rubygems.org/..
Installing fuguta (1.0.2)
Installing multi_json (1.8.0)
Installing multi_xml (0.5.5)
Installing httparty (0.11.0)
Installing thor (0.18.1)
Using bundler (1.3.5)
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.
Post-install message from httparty:
When you HTTParty, you must party hard!
# vnctl
Commands:
  vnctl datapath         # Operations for datapaths.
  vnctl help [COMMAND]   # Describe available commands or one specific command
  vnctl interface        # Operations for interfaces.
  vnctl ip_address       # Operations for ip addresses.
  vnctl ip_lease         # Operations for ip leases.
  vnctl mac_lease        # Operations for mac leases.
  vnctl network          # Operations for networks.
  vnctl network_service  # Operations for network services.
  vnctl route            # Operations for routes.
  vnctl route_link       # Operations for route links.
  vnctl security_group   # Operations for security groups.
# vnctl
/opt/axsh/wakame-vnet/vnctl/bin/vnctl:8:in `<main>': undefined method `setup' for Bundler:Module (NoMethodError)

今度はきちんと動きました。ただし、/opt/axsh/wakeme-vnet/vnctl 以下で vnctl を実行する必要があるようです。何はともあれ vnctl が動いたので、やっと今日の目的に進めます。

RPM だけでだめなのはそういうものなのでしょうか? 誰か教えてください。

CLI の使い方を探る

さて CLI のコマンドとオプションを探ってみます。 今日のポリシーとしてコードは読みません。

vnctl help [COMMAND] というヘルプを実行したのですが、情報量 0 です。
面倒なので、help をつけないで実行してみると、サブコマンドが出てきました (^^
この先もかなり探検が必要なようです。

# vnctl help datapath
Usage:
  vnctl datapath

Operations for datapaths.
# vnctl datapath
Commands:
  vnctl datapath add [OPTIONS] --display-name=DISPLAY_NAME --dpid=DPID --node-id=NODE_ID  # Creates a new datapath.
  vnctl datapath del UUID(S)                                                              # Deletes one or more datapath(s) separated by a space.
  vnctl datapath help [COMMAND]                                                           # Describe subcommands or one specific subcommand
  vnctl datapath modify UUID [OPTIONS]                                                    # Modify a datapath.
  vnctl datapath networks OPTIONS                                                         # subcommand to manage networks in this datapath.
  vnctl datapath route_links OPTIONS                                                      # subcommand to manage route_links in this datapath.
  vnctl datapath show [UUID(S)]                                                           # Shows all or a specific set of datapath(s).

この次は、サブコマンドのオプションも知りたいところです。いろいろなところに help–help を入れてみたところ、サブコマンド名の直前に help をつけると、詳しいオプションが出ることが分かりました。上に表示されているヘルプをちゃんと見ると書いてありました。ゴメンナサイ、あまり直観的ではないですね。

# vnctl datapath add
No value provided for required options '--display-name', '--node-id', '--dpid'
# vnctl datapath add help
No value provided for required options '--display-name', '--node-id', '--dpid'
# vnctl datapath help add
Usage:
  vnctl add [OPTIONS] --display-name=DISPLAY_NAME --dpid=DPID --node-id=NODE_ID

Options:
  [--uuid=UUID]                    # Unique UUID for the datapath.
  --display-name=DISPLAY_NAME      # Human readable display name.
  [--is-connected]                 # Flag that detemines if the datapath is connected or not.
  [--dc-segment-id=DC_SEGMENT_ID]  # The datapath's dc segment id.
  --node-id=NODE_ID                # The node id for the datapath.
  [--ipv4-address=IPV4_ADDRESS]    # Ipv4 address for the datapath.
  --dpid=DPID                      # Hexadecimal id for the datapath.

Creates a new datapath.

API 体系を分析してみる

vnctl datapath help add のようなリソース作成コマンドのヘルプを順に実行して、リソース間を探ってみました。
矢印は、リソース作成時に指定するパラメータの関係を指しています。矢印の行先が指定されている方のパラメータです。



これを元に機能を推測してみます。

datapath
最初に作成するリソースのようです。 datapath ID と Node ID を指定することから、VM が起動するホストの OVS を表しているみたいです。
network
論理ネットワークを指すリソースのようです。論理 L2 とそのうえで動作する IPv4 サブネットがひとまとめで管理されています。
network を datapath に関連付けする際に broadcast MAC address を指定するところが特徴的に見えます。
network-mode というパラメータがあり、physical/virtual という指定ができるので、物理ネットワークの定義と仮想ネットワークの定義の両方に使用するのでしょうか。
IP address
network で使用する IP アドレスを登録するように見えます。
interface
interface は VM などが接続される endpoint に対応していると推測しました。
どうやって OVS の各ポートを識別するのかが気になります。
MAC アドレスが必須パラメータで、属性として network ID や datapath ID を指定できることから、OVS のポートに対応していて、MAC アドレスベースでネットワークを判定しているのかなと感じました。
IP lease
interface に IP Address を割り当てたり、現在の割り当て状況を管理するのに使っているようです。
なぜ network ID が IP Lease のパラメータにあるのかわかりませんでした。 interface はネットワークとは独立に存在できて、 IP Lease を変更すると、別のネットワークにもつなぎ直せるのかな?
network service
interface に接続された VM などがどんな L4 ポート番号を使用しているかを指定することで、その interface に接続されたネットワークサービスを表現しているようです。
route_link と route
経路情報があることからルーター機能に関するものであることは分かりますが、具体的にどのように使うかまでは分かりませんでした。

まとめ

おおざっぱに機能を推測してみました。ソースも読んでいませんし、実際にも動かしていないので、完全にはずしているかもしれません。

OpenStack Neutron や Amazon VPC のモデルとはだいぶ違いますね。 もう少し詳しく見てどういう思想で設計されているのかを知りたいと思います。

リソースモデルや CLI だけだとなかなか具体的なイメージが湧きませんね。 仮想ネットワーク作成例とコマンドラインシーケンスがあると分かりやすいなあと思いました。

明日も記事を書く予定ですが、実際に動かしてみようと思います。 VM を起動するのは面倒なので、network namespace を使って論理ネットワークの動作を見てみたいと思います。

Neutron VPNaaS を使ってみる ~ 意味もないけど、とりあえず back-to-back で IPsec VPN

OpenStack Neutron に Havana リリースで VPNaaS が追加されました。今回のリリースでは IPsec による L3 VPN のみが実装されています。Icehouse では SSL-VPN や BGP/MPLS による VPN なども計画されています。devstack を使って VPNaaS を動かして、どんなことが行われているのか見てみたいと思います。

VPNaaS だけでなく LBaaS/FWaaS を含めた Network Service の考え方は OpenStack Neutron の紹介資料 (Havana 版) の後ろの方で説明しているので、こちらもご参照ください。

構成

2か所のサイトを IPsec VPN で接続する例を考えます。


ここでは、一つの OpenStack で 2つのネットワークをそれぞれ別のサイトとみなして、VPNaaS を使って back-to-back で VPN を作成して接続します。上の図の site1, site2 はそれぞれ net1, net2 が対応します。router1, router2 にそれぞれ相手のネットワークに向けた経路情報を明示的に設定しない限り、net1 と net2 間は通信できないので、VPN 接続の確認として使うことができます。


devstack の実行

devstack の stable/havana branch を取得して、localrc を作成して、stack.sh を実行します。 Ubuntu 12.04.3 LTS を使っています。
git clone https://github.com/openstack-dev/devstack.git
cd devstack
git checkout stable/havana
wget -O localrc https://gist.github.com/amotoki/6520741/raw/6856653c57b67441c99aba057f310801da4d03ae/localrc-havana-allinone
./stack.sh
今回使った localrc は https://gist.github.com/amotoki/6520741 にありますので、参考にしてください。
Ceilometer, Heat, Swift も有効にしていますが、無効にしても構いません。
余談ですが、Ubuntu 12.04 では mongodb のバージョンが古いので、Ceilometer を動かすには 2.4.6 などの新しいバージョンの mongodb をインストールする必要があります。 Havana の Ubuntu Cloud Archives から mongodb をインストールするのが一番簡単だと思います。

VPNaaS 用の Neutron の設定

devstack では、設定ファイルの作成は devstack の実行中に行われますが、何が行われているのかを見ておきます。

まず /etc/neutron/neutron.conf です。 VPNaaS を有効にするには service_pliugins に VPN プラグイン neutron.services.vpn.plugin.VPNDriverPlugin を指定します。この例では、他に L3, LBaaS, FWaaS の reference implementation が有効になっています。大きな流れとしては OpenStack Neutron の紹介資料 (Havana 版) の資料 (p.19) で紹介しているように、Neutron では機能単位のプラグイン (Service Plugin) を用意する方向です。VPNaaS もこの方向で実装されています。
service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin,neutron.services.loadbalancer.plugin.LoadBalancerPlugin,neutron.services.vpn.plugin.VPNDriverPlugin,neutron.services.firewall.fwaas_plugin.FirewallPlugin
extension list を確認すると、vpnaas が有効になっていることが分かります。
$ neutron ext-list
+-----------------------+-----------------------------------------------+
| alias                 | name                                          |
+-----------------------+-----------------------------------------------+
| service-type          | Neutron Service Type Management               |
| fwaas                 | Firewall service                              |
| security-group        | security-group                                |
| l3_agent_scheduler    | L3 Agent Scheduler                            |
| lbaas_agent_scheduler | Loadbalancer Agent Scheduler                  |
| ext-gw-mode           | Neutron L3 Configurable external gateway mode |
| binding               | Port Binding                                  |
| quotas                | Quota management support                      |
| agent                 | agent                                         |
| router                | Neutron L3 Router                             |
| dhcp_agent_scheduler  | DHCP Agent Scheduler                          |
| external-net          | Neutron external network                      |
| multi-provider        | Multi Provider Network                        |
| allowed-address-pairs | Allowed Address Pairs                         |
| vpnaas                | VPN service                                   |
| extra_dhcp_opt        | Neutron Extra DHCP opts                       |
| provider              | Provider Network                              |
| lbaas                 | LoadBalancing service                         |
| extraroute            | Neutron Extra Route                           |
+-----------------------+-----------------------------------------------+
IPsec の実装は Openswan https://www.openswan.org/ を使用しています。
devstack 実行後には openswan パッケージがインストールされています。現状は openswan ベースの IPsec VPN だけが Neutron に入っている唯一の VPNaaS の実装です。
)$ COLS=80 dpkg -l openswan
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                Version             Description
+++-===================-===================-======================================================
ii  openswan            1:2.6.37-1          Internet Key Exchange daemon
VPN に対応した L3 agent である neutron-vpn-agent が openswan を呼び出して VPN 接続を行います。 VPNaaS を使う場合には l3-agent の代わりに vpn-agent を使用します。 vpn-agent は l3-agent に VPN 用の機能が追加されたもので、通常の l3-agent としてもふるまいます。
実行されているサービスプロセスを確認すると vpn-agent が起動していることが分かります。 FWaaS も同時に有効にしているので、fwaas.ini も引数に指定されています。現状は VPNaaS に関連する設定項目はありません。
$ ps auxw | grep vpn-agent
1000      7786  0.0  0.0   9388   932 pts/90   S+   21:28   0:00 grep --color=auto vpn-agent
1000     17627  0.2  0.9 112980 39164 pts/14   S+   20:58   0:05 /usr/bin/python /usr/local/bin/neutron-vpn-agent --config-file /etc/neutron/neutron.conf --config-file=/etc/neutron/l3_agent.ini --config-file /etc/neutron/fwaas_driver.ini

ネットワークの準備

site1 側のネットワーク、ルーターは devstack の実行時にデフォルトで作成されているので、2つ目のサイトに相当するネットワーク、ルーターを作成します。ここではコマンドラインで作成していますが、ダッシュボードから作成した方が楽だと思います。(user_name: demo, tenant_name: demo で操作します)。さらに、それぞれのネットワークに接続した VM も起動しておきます。
$ neutron net-create net2
$ neutron subnet-create --name subnet2 net2 10.3.3.0/24
$ neutron router-create router2
$ neutron router-interface-add router2 subnet2
$ neutron router-gateway-set router2 ext_net
$ nova boot --key-name mykey --image tty-quantum --flavor m1.tiny --nic net-id= vm1
$ nova boot --key-name mykey --image tty-quantum --flavor m1.tiny --nic net-id= vm2
この状態ではこのようになります。


自分の例では以下のようなアドレスになりました。
  • Site1
    • VM1 : 10.0.0.3
    • router1 (net1側) : 10.0.0.1
  • Site1
    • VM2 : 10.3.3.2
    • router2 (net2側) : 10.3.3.1

この段階で異なるネットワーク間で ping が通らないことを確認しておきます。
  • VM1 -> router1(net1側) : OK
  • VM1 -> router2(net2側) : NG
  • VM1 -> VM2 : NG
  • VM2 -> router2(net2側) : OK
  • VM2 -> router1(net1側) : NG
  • VM2 -> VM1 : NG
セキュリティグループで ICMP と SSH を開けた上で確認します。
neutron security-group-rule-create --protocol tcp --port-range-min 22 --port-range-max 22 --remote-ip-prefix 0.0.0.0/0 default
neutron security-group-rule-create --protocol icmp --remote-ip-prefix 0.0.0.0/0 default

VPN の作成


VPN の作成は、それぞれのサイトで行います。

最初に、VPN service はルーターとサブネットを指定して作成します。VPN service は、VPN 接続を受け付けるサイト側で、VPN 接続をどのルーターで終端し、どのサブネットに関連付けるかを指定するものです。また、IPsec 接続の各種ポリシーはあらかじめ用意した IPsec Policy, IKE Policy で作成しておきます。この段階では VPN service の status は Pending Create で問題ありません。

Site1 側
neutron vpn-ipsecpolicy-create ipsec-policy1
neutron vpn-ikepolicy-create ike-policy1
neutron vpn-service-create --name vpn1 router1 private-subnet
Site2 側
neutron vpn-ipsecpolicy-create ipsec-policy2
neutron vpn-ikepolicy-create ike-policy2
neutron vpn-service-create --name vpn2 router2 subnet2

次に、IPsec 接続を VPN service を指定して作成します。

IPsec 接続を作成するには、接続相手側の VPN ルータの外側の IP アドレスが必要です。以下のコマンドを実行することで、それぞれのルーターの外側の IP アドレスが以下のように分かります。
  • router1: 172.24.4.226
  • router2: 172.24.4.227
現在の Neutron API ではルーターの外側の IP アドレスは管理者権限でしか入手することができません。そのため、通常のユーザーが OpenStack どうしを VPNaaS で接続することはできません。これでは不便なので、ルーターの外部の IP アドレス情報を入手できるようにすることが検討されています。
$ OS_USERNAME=admin OS_TENANT_NAME=admin neutron router-port-list router1 --device_owner network:router_gateway -c fixed_ips
+-------------------------------------------------------------------------------------+
| fixed_ips                                                                           |
+-------------------------------------------------------------------------------------+
| {"subnet_id": "711a97f6-b6c0-425c-b17b-618904324f95", "ip_address": "172.24.4.226"} |
+-------------------------------------------------------------------------------------+
$ OS_USERNAME=admin OS_TENANT_NAME=admin neutron router-port-list router2 --device_owner network:router_gateway -c fixed_ips
+-------------------------------------------------------------------------------------+
| fixed_ips                                                                           |
+-------------------------------------------------------------------------------------+
| {"subnet_id": "711a97f6-b6c0-425c-b17b-618904324f95", "ip_address": "172.24.4.227"} |
+-------------------------------------------------------------------------------------+

この情報をもとに IPsec 接続を作成します。

まず Site1 側を作成します。 peer-address には接続相手の VPN ルーターの外側の IP アドレス (ここでは router2 の外側のアドレス) 172.24.4.227 を、peer-cidr は接続相手のサブネットアドレス 10.3.3.0/24 を指定します。 peer-id の指定内容は VPN ルーターの構成により変わりますが、vpn-agent ベースのルーターの場合は peer-address と同じアドレスを指定します。
$ neutron ipsec-site-connection-create --vpnservice-id vpn1 \
    --ikepolicy-id ike-policy1 --ipsecpolicy-id ipsec-policy1 \
    --peer-address 172.24.4.227 --peer-id 172.24.4.227 \
    --peer-cidr 10.3.3.0/24 --psk secret1 --name conn1
$ neutron ipsec-site-connection-list -c name -c peer_address -c peer_cidrs -c status
+-------+--------------+---------------+--------+
| name  | peer_address | peer_cidrs    | status |
+-------+--------------+---------------+--------+
| conn1 | 172.24.4.227 | "10.3.3.0/24" | DOWN   |
+-------+--------------+---------------+--------+
この段階では Site1 側の IPsec 接続 conn1 のステータスは、まだ相手と接続されていないので、DOWN となります。

次に、Site2 側の IPsec 接続を作成します。
$ neutron ipsec-site-connection-create --vpnservice-id vpn2 \
    --ikepolicy-id ike-policy2 --ipsecpolicy-id ipsec-policy2 \
    --peer-address 172.24.4.226 --peer-id 172.24.4.226 \
    --peer-cidr 10.0.0.0/24 --psk secret1 --name conn2
$ neutron ipsec-site-connection-list -c name -c peer_address -c peer_cidrs -c status
+-------+--------------+---------------+--------+
| name  | peer_address | peer_cidrs    | status |
+-------+--------------+---------------+--------+
| conn1 | 172.24.4.227 | "10.3.3.0/24" | ACTIVE |
| conn2 | 172.24.4.226 | "10.0.0.0/24" | ACTIVE |
+-------+--------------+---------------+--------+
相手と正常に接続されていれば、両方のサイトの IPsec 接続でステータスが ACTIVE になります。

導通も確認してみましょう。VM1 にログインして、VM2 に対して ping を実行します。
# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr FA:16:3E:8A:39:FE
          inet addr:10.0.0.3  Bcast:10.0.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1185 errors:0 dropped:0 overruns:0 frame:0
          TX packets:821 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:126234 (123.2 KiB)  TX bytes:144124 (140.7 KiB)

# ping -c 5 10.3.3.2
PING 10.3.3.2 (10.3.3.2): 56 data bytes
64 bytes from 10.3.3.2: seq=0 ttl=62 time=6.093 ms
64 bytes from 10.3.3.2: seq=1 ttl=62 time=1.803 ms
64 bytes from 10.3.3.2: seq=2 ttl=62 time=1.886 ms
64 bytes from 10.3.3.2: seq=3 ttl=62 time=1.771 ms
64 bytes from 10.3.3.2: seq=4 ttl=62 time=1.399 ms

--- 10.3.3.2 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 1.399/2.590/6.093 ms

デバッグ情報

上では手順と動作確認を見てきましたが、デバッグ情報がどこにあるかを紹介しておきます。

  • neutron-vpn-agent のログ : /opt/stack/logs/screen-q-vpn.log (devstack の場合)
  • neutron-vpn-agent が作成する openswan の情報 : /opt/stack/data/neutron/ipsec/<router-id>
    • <router-id> は VPN service が関連付けられたルーターの ID
    • 通常のインストールであれば /var/lib/neutron などになります。
  • network namespace 内の ipsec 設定の情報
    • ip netns qrouter-ROUTER_ID ip -s xfrm state
    • ip netns qrouter-ROUTER_ID ip -s xfrm policy
    $ sudo netns exec qrouter-b78b3faf-e8d1-45dd-b185-02f65415b389 ip -s xfrm state
    src 172.24.4.227 dst 172.24.4.226
            proto esp spi 0x910992d8(2433323736) reqid 16385(0x00004001) mode tunnel
            replay-window 32 seq 0x00000000 flag af-unspec (0x00100000)
            auth-trunc hmac(sha1) 0x34f52f8ecdc75a4c3a4940e578b3f8a6a50e8147 (160 bits) 96
            enc cbc(aes) 0xc6091efe44c2a152ac5c77d6e6672f05 (128 bits)
            lifetime config:
              limit: soft (INF)(bytes), hard (INF)(bytes)
              limit: soft (INF)(packets), hard (INF)(packets)
              expire add: soft 0(sec), hard 0(sec)
              expire use: soft 0(sec), hard 0(sec)
            lifetime current:
              1512(bytes), 18(packets)
              add 2013-12-16 01:40:17 use 2013-12-16 01:46:21
            stats:
              replay-window 0 replay 0 failed 0
    src 172.24.4.226 dst 172.24.4.227
            proto esp spi 0xadd229c7(2916231623) reqid 16385(0x00004001) mode tunnel
            replay-window 32 seq 0x00000000 flag af-unspec (0x00100000)
            auth-trunc hmac(sha1) 0x8a0f54cd12bd528be9b7f7feeb6a901276d7264a (160 bits) 96
            enc cbc(aes) 0x4f7ffa695054c7408dae2f99ceb0c241 (128 bits)
            lifetime config:
              limit: soft (INF)(bytes), hard (INF)(bytes)
              limit: soft (INF)(packets), hard (INF)(packets)
              expire add: soft 0(sec), hard 0(sec)
              expire use: soft 0(sec), hard 0(sec)
            lifetime current:
              1512(bytes), 18(packets)
              add 2013-12-16 01:40:17 use 2013-12-16 01:46:21
            stats:
              replay-window 0 replay 0 failed 0
    

後始末

現時点では unstack.sh を行っても openswan のプロセスが削除されません。このプロセスを停止しないと、対応する network namespace を削除できません。 openswan が作成するプロセス pluto の PID が /opt/stack/data/neutron/ipsec/*/var/run/pluto.pid にあるので、この情報をもとに関連プロセスを削除します。
$ sudo kill `cat /opt/stack/data/neutron/ipsec/*/var/run/pluto.pid$`
$ for ns in `ip netns | grep -E '(qrouter|qdhcp)-'`; do sudo ip netns delete $ns; done

2013年12月14日土曜日

OpenStack Neutron の紹介資料 (Havana 版)

OpenStack Neutron の概要紹介の資料をアップデートしました。 1年前の OSC で話した「Quantum の紹介」の資料をベースに Havana の Neutron の状況にあわせて更新しました。 ML2 Plugin の説明、LBaaS/FWaaS/VPNaaS などの Advanced Network Service の考え方に関する情報を追加しています。みなさんの理解の参考になればと思います。

こちらの記事でも公開しているのですが、分かりやすいように別記事にしておきます。

OpenStack 開発体制とコントリビューションのお誘い @ Okinawa Open Days (と Neutron Havana 紹介資料)

12/12-13 に開催された Okinawa Open Days に参加して来ました。前日の OpenStack BOF と OpenStack セッションで話をして来ました。12日は OpenStack セッションで、13日は SDN セッションでした。久しぶりに SDN 関係者ともたくさん話をできて楽しかったです。

OpenStack セッションで「OpenStack開発体制とコントリビューションのお誘い」と題して話しました。OpenStack の開発体制や品質維持が行われているか、機能追加・バグ修正の流れ、OpenStack へのコントリビューションの進め方について説明しました。 OpenStack の開発体制を理解する上でも参考になると思いますので、Advent Calendar でも紹介したいと思います。

OpenStack BOF の中で学生さんから OpenStack を触っておいた方がいいですか?という質問をもらいました。技術がどんどん出て来る現在、OpenStack などのクラウドOSはある意味でいろいろな技術の集合体であり、OpenStack に触れることで、コンピュータ、ネットワークのいろいろな技術について体系的、統合的に学べるではないかと話しました。それをきっかけに興味を持った部分を深く突っ込んでいってもらいたいと思いました。


OpenStack BOF では、Neutron のコンセプトがどのような考え方で作られているのかを、ざっくばらんに話しました。
それに向けて Neutron の概要資料を作りました。 1年前の OSC で話した「Quantum の紹介」の資料を Havana で状況にあわせて更新したものです。
ML2 Plugin の説明、LBaaS/FWaaS/VPNaaS などの Advanced Network Service の考え方に関する情報を追加しています。

2013年12月11日水曜日

OpenStack と Trema Sliceable Switch とつないでみる

日本 OpenStack ユーザー会 Advent Calendar の 11日目ということで、Neutron と Trema Sliceable Switch を組み合わせて動かしてみようと思います。Okinawa OpenDays の BOF でプレゼンしながらデバッグしています。

devstack を使って動かしていますが、Ubuntu 12.04 でパッケージを使った Havana with Neutron のインストールガイドも https://github.com/amotoki/openstack-havana-install-guideで作っています。今は NEC OpenFlow Plugin のみですが、ML2 Plugin も準備中です。

Trema は OpenFlow Controller Framework で C と Ruby で OpenFlow Controller を書くことができます。みなさん知っていますね。 Sliceable Switch のアプリケーションで、 OpenFlow Controller として動作します。

Neutron のプラグインは NEC OpenFlow Plugin を使います。Sliceable Switch には REST API があり、この API を Plugin から呼び出して、OpenFlow ネットワーク上に複数の論理ネットワークを作成します。

今回は以下のような 3ノードの構成を使用しました。使用したマシンは Ubuntu 12.04 の KVM の VM です。メモリは 2GB です。 NIC は 1つです。 OVS 間のデータプレーンは GRE トンネルで接続しました。
  • Controller Node (nova, neutron のすべてのサービスを動かします)
  • Compute Node
  • OpenFlow Controller


最初に Sliceable Switch をセットアップします。 RVM 環境を利用して Ruby 2.0.0 の環境で動かします。 Trema は Ubuntu 12.04 の ruby 1.8.7 でも動作しますが、 ruby 1.8.7 はすでにサポートが終わっていること、依存モジュールが今後動かないなどのトラブルが出てくる可能性もあります。

Trema のインストール

依存パッケージのインストール以外は root 権限は不要です。
sudo aptitude install gcc make ruby rubygems ruby-dev libpcap-dev libsqlite3-dev libglib2.0-dev sqlite3 libdbi-perl libdbd-sqlite3-perl apache2 libjson-perl
# rvm インストール
\curl -sSL https://get.rvm.io | bash -s stable
# rvm 環境の反映 (ログインし直すか、source .bash_profile と PATH の追加)
PATH=$PATH:$HOME/.rvm/bin
source .bash_profile
# ruby 2.0.0 インストール
rvm install 2.0.0
# trema インストール
gem install trema
bundle install

Sliceable Switch のインストール

インストールは方法は trema apps の sliceable switch の README.md に使い方が書かれています。https://github.com/amotoki/openstack-havana-install-guide/wiki/TremaSliceableSwitch にも詳しく書いておきました。

sliceable switch の実行

最後の起動方法だけが rvm 環境なので少し違います。もっといい方法を調べたいと思います。
sudo bash --login
LOGGING_LEVEL=info TREMA_TMP=$HOME/trema/work/trema trema run -d -c ~/trema/work/sliceable_switch/etc/sliceable.conf
sliceable switch の設定ファイルを引数に指定して trema を実行します。
デバッグレベルを変更する場合は TREMA_LOG_LEVEL で debug などを指定します。
TREMA_TMP 以下に一時ファイル、ログなどが生成されます。

きちんと起動していることを確認しておきます。
$ ps auxw | grep trema
root   24938 0.0 0.0 15024 1844 ?    Ss  17:50  0:00 /home/ubuntu/.rvm/gems/ruby-2.0.0-p353/gems/trema-0.4.6/objects/switch_manager/switch_manager --daemonize --port=6653 -- port_status::topology packet_in::filter state_notify::topology vendor::sliceable_switch
root   24940 0.0 0.0 15216 2044 ?    Ss  17:50  0:00 /home/ubuntu/.rvm/gems/ruby-2.0.0-p353/gems/trema-0.4.6/objects/packetin_filter/packetin_filter --daemonize --name=filter lldp::topology_discovery packet_in::sliceable_switch
root   24942 0.0 0.0 15284 2364 ?    Ss  17:50  0:00 /home/ubuntu/trema/apps/./topology/topology --name topology -d
root   24944 0.0 0.0 15608 2664 ?    Ss  17:50  0:00 /home/ubuntu/trema/apps/./topology/topology_discovery --name topology_discovery -d
root   24946 0.0 0.0 16752 3576 ?    Ss  17:50  0:00 /home/ubuntu/trema/apps/./flow_manager/flow_manager --name flow_manager -d
root   24948 0.0 0.2 21588 8652 ?    Ss  17:50  0:00 /home/ubuntu/trema/apps/./sliceable_switch/sliceable_switch --name sliceable_switch -d -s /home/ubuntu/trema/work/sliceable_switch/db/slice.db -a /home/ubuntu/trema/work/sliceable_switch/db/filter.db
ubuntu  25048 0.0 0.0  8108  896 pts/0  R+  17:53  0:00 grep --color=auto trema
6653/tcp と 8888/tcp が LISTEN されています。 6653 は OpenFlow の controller channel (secure channel) です。 8888 は Sliceable Switch の仮想ネットワークを操作するための REST API です。
$ netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address      Foreign Address     State
tcp    0   0 0.0.0.0:80       0.0.0.0:*        LISTEN
tcp    0   0 0.0.0.0:22       0.0.0.0:*        LISTEN
tcp    0   0 0.0.0.0:8888      0.0.0.0:*        LISTEN
tcp    0   0 0.0.0.0:6653      0.0.0.0:*        LISTEN
tcp6    0   0 :::22          :::*          LISTEN
OpenFlow Controller の準備は終わりです。

OpenStack Controller ノード


devstack を使ってインストールします。
パッケージを使った手順はhttps://github.com/amotoki/openstack-havana-install-guide/wiki/ControllerNodeに書いていますので、参考にして下さい。

localrc はこんな感じです。

KEYSTONE_TOKEN_FORMAT=UUID
PRIVATE_NETWORK_NAME=net1
PUBLIC_NETWORK_NAME=ext_net

disable_service n-net
enable_service neutron q-svc q-agt
enable_service q-dhcp
enable_service q-l3
enable_service q-meta

Q_USE_DEBUG_COMMAND=True
Q_PLUGIN=nec
GRE_LOCAL_IP=10.56.45.216:10.56.45.226
OFC_DRIVER=trema
OFC_API_HOST=10.56.45.218
OFC_API_PORT=8888
OFC_OFP_HOST=10.56.45.218
OFC_OFP_PORT=6653

LOGDIR=$DEST/logs
SCREEN_LOGDIR=$LOGDIR
LOGFILE=$LOGDIR/devstack.log
ADMIN_PASSWORD=pass
MYSQL_PASSWORD=stackdb
RABBIT_PASSWORD=stackqueue
SERVICE_PASSWORD=$ADMIN_PASSWORD
SERVICE_TOKEN=xyzpdqlazydog

Neutron を有効にして、プラグインは NEC OpenFlow Plugin を指定しています。OpenFlow Controller の情報を指定して実行します。ノード間は GRE トンネルで接続するので、GRE で接続するノードリストを指定しています。

./stack.sh を実行して待ちましょう。

OpenStack Compute Node ノード


こちらも同様に devstack を使ってインストールします。
パッケージを使った手順は XXXXXX に書いていますので、参考にして下さい。

localrc はこんな感じです。こちらはいたってシンプルです。
USE_NEUTRON=True

CC_HOST=10.56.45.216
MYSQL_HOST=${CC_HOST}
SERVICE_HOST=${CC_HOST}
RABBIT_HOST=${CC_HOST}
Q_HOST=${CC_HOST}

HOST_IP=$(get_host_ip)

ENABLED_SERVICES=n-cpu,rabbit

enable_service n-novnc
VNCSERVER_PROXYCLIENT_ADDRESS=$HOST_IP
VNCSERVER_LISTEN=$HOST_IP

enable_service q-agt

Q_PLUGIN=nec
GRE_REMOTE_IPS=10.56.45.216:10.56.45.226
OFC_OFP_HOST=${CC_HOST}

LOGDIR=$DEST/logs
SCREEN_LOGDIR=$LOGDIR
LOGFILE=$LOGDIR/devstack.log
LOG_COLOR=False

ADMIN_PASSWORD=pass
MYSQL_PASSWORD=stackdb
RABBIT_PASSWORD=stackqueue
SERVICE_PASSWORD=$ADMIN_PASSWORD
SERVICE_TOKEN=xyzpdqlazydog
こちらもしばらく待ちます。

初期状態の確認


一通り動かし終わったので、状態を見てみましょう。

まずは Neutron 側の情報から。
$ cd devstack
$ . openrc
$ neutron net-list
+--------------------------------------+---------+--------------------------------------------------+
| id                                   | name    | subnets                                          |
+--------------------------------------+---------+--------------------------------------------------+
| f567b464-2968-4d78-a884-875259bc9fc0 | net1    | 042d74c4-434a-4f52-884d-61c10539d2de 10.0.0.0/24 |
| ff946453-aa0e-492c-af8a-f0c53be78448 | ext_net | 73c5c8ca-8c94-4921-88a4-af77ef000fb8             |
+--------------------------------------+---------+--------------------------------------------------+
$ neutron net-show net1
+-----------------+--------------------------------------+
| Field           | Value                                |
+-----------------+--------------------------------------+
| admin_state_up  | True                                 |
| id              | f567b464-2968-4d78-a884-875259bc9fc0 |
| name            | net1                                 |
| router:external | False                                |
| shared          | False                                |
| status          | ACTIVE                               |
| subnets         | 042d74c4-434a-4f52-884d-61c10539d2de |
| tenant_id       | c980a2144ebc4a2dbeb0562218b96fb9     |
+-----------------+--------------------------------------+
$ neutron port-list -c id -c device_owner -c fixed_ips
+--------------------------------------+--------------------------+---------------------------------------------------------------------------------+
| id                                   | device_owner             | fixed_ips                                                                       |
+--------------------------------------+--------------------------+---------------------------------------------------------------------------------+
| 26755062-0bb2-41ff-a85c-95c927d2f5d1 | network:dhcp             | {"subnet_id": "042d74c4-434a-4f52-884d-61c10539d2de", "ip_address": "10.0.0.3"} |
| c8993f73-f737-4cd5-9736-4194cb6624db | compute:probe            | {"subnet_id": "042d74c4-434a-4f52-884d-61c10539d2de", "ip_address": "10.0.0.2"} |
| f48d65b7-85e0-4389-b271-144bde7b8b58 | network:router_interface | {"subnet_id": "042d74c4-434a-4f52-884d-61c10539d2de", "ip_address": "10.0.0.1"} |
+--------------------------------------+--------------------------+---------------------------------------------------------------------------------+
次に OpenFlow Controller 側の情報です。
$ netstat -nt
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address      Foreign Address     State
tcp    0   0 10.56.45.218:6653    10.56.45.226:55373   ESTABLISHED
tcp    0   0 10.56.45.218:6653    10.56.45.216:46843   ESTABLISHED
tcp    0   0 10.56.45.218:22      10.56.45.227:52031   ESTABLISHED
6653/tcp は OpenFlow の control channel です。 6653/tcp の接続が二つあります。
Controller ノードと Compute ノードの OVS br-int が OpenFlow Switch として動作していて、接続に来ていることがわかります。

br-int の設定方法は Install Guide の "Setup datapath bridge" https://github.com/amotoki/openstack-havana-install-guide/wiki/ComputeNodeNeutronNecPlugin を見てください。
set-controller というコマンドを実行すると、OpenFlow Switch として動作します。
ovs-vsctl --no-wait set-controller br-int tcp:10.56.45.210:6653
trema のログを見てみましょう。
trema では switch_manager が接続をうけて、個別の switch daemon を起動します。
switch.0xXXXXXXXXXXXXX.log があることから OVS から接続に来ていることが分かります。
% ls -1l trema/log/
total 12
-rw-r--r-- 1 root root  0 Dec 11 19:18 filter.log
-rw-r--r-- 1 root root  0 Dec 11 19:18 flow_manager.log
-rw-r--r-- 1 root root 6121 Dec 11 19:24 sliceable_switch.log
-rw-rw-rw- 1 root root  0 Dec 11 19:21 switch.0x10056045216.log
-rw-rw-rw- 1 root root  0 Dec 11 19:24 switch.0x10056045226.log
-rw-r--r-- 1 root root  0 Dec 11 19:18 switch_manager.log
-rw-r--r-- 1 root root  0 Dec 11 19:18 topology_discovery.log
-rw-r--r-- 1 root root  82 Dec 11 19:24 topology.log
sliceable_switch.log を見てみます。
以下は dpid = 0x10056045216 の OVS から接続があったことが分かります。
Wed Dec 11 19:21:12 2013 [info] Adding a port: dpid = 0x10056045216, port = 65534 ( "br-int" )
Wed Dec 11 19:22:04 2013 [info] Adding a port: dpid = 0x10056045216, port = 1 ( "tapc8993f73-f7" )
Wed Dec 11 19:22:09 2013 [info] Adding a port: dpid = 0x10056045216, port = 2 ( "tap26755062-0b" )
Wed Dec 11 19:22:17 2013 [info] Adding a port: dpid = 0x10056045216, port = 3 ( "tapf48d65b7-85" )
devstack の中で Neutron Plugin が仮想ネットワークの REST API が呼ばれて、スライス定義が登録されています。
Wed Dec 11 19:18:22 2013 [info] Loading slice definitions.
Wed Dec 11 19:18:22 2013 [info] Adding a port-slice binding ( type = 0x1, datapath_id = 0x10056045216, port = 0x1, vid = 0xffff, slice_number = 0x1, id = 3a084cc4-c090-456f-ac79-7acc9aa20c08, dynamic = 0, updated_at = 1386757102 ).
Wed Dec 11 19:18:22 2013 [info] Adding a port-slice binding ( type = 0x1, datapath_id = 0x10056045216, port = 0x2, vid = 0xffff, slice_number = 0x1, id = def41b36-0d8b-4651-b0dc-b6ede86877a3, dynamic = 0, updated_at = 1386757102 ).
Wed Dec 11 19:18:22 2013 [info] Adding a port-slice binding ( type = 0x1, datapath_id = 0x10056045216, port = 0x3, vid = 0xffff, slice_number = 0x1, id = 59392aa3-8779-403e-92b3-bdc8805630b9, dynamic = 0, updated_at = 1386757102 ).
Wed Dec 11 19:18:22 2013 [info] Adding a port-slice binding ( type = 0x1, datapath_id = 0x10056045216, port = 0x1, vid = 0xffff, slice_number = 0x3, id = 6dfd6bf6-ce17-409a-85f3-6b12f0059570, dynamic = 0, updated_at = 1386757102 ).
Sliceable Switch 側での仮想ネットワーク情報の確認もしてみます。期待通り。
% SLICE_DB_FILE=/home/ubuntu/trema/work/sliceable_switch/db/slice.db ./slice list
               ID               Description
f567b464-2968-4d78-a884-875259bc9fc0  ID=f567b464-2968-4d78-a884-875259bc9fc0 Name=net1 at Neutron.
ff946453-aa0e-492c-af8a-f0c53be78448  ID=ff946453-aa0e-492c-af8a-f0c53be78448 Name=ext_net at Neutron.

% SLICE_DB_FILE=/home/ubuntu/trema/work/sliceable_switch/db/slice.db ./slice show f567b464-2968-4d78-a884-875259bc9fc0
[Description]
ID=f567b464-2968-4d78-a884-875259bc9fc0 Name=net1 at Neutron.

[Port-based bindings]
           ID         Datapath ID    Port       VID
f48d65b7-85e0-4389-b271-144bde7b8b58      0x10056045216      3      65535
26755062-0bb2-41ff-a85c-95c927d2f5d1      0x10056045216      2      65535
c8993f73-f737-4cd5-9736-4194cb6624db      0x10056045216      1      65535

[MAC-based bindings]
No bindings found.

[MAC-based bindings on ports]
No bindings found.

Open vSwitch を見てみます。
$ sudo ovs-vsctl show
ce91e39a-ec92-4a6f-9fbe-d0c8f742c7a3
  Bridge br-ex
    Port "tap9632e3f8-53"
      Interface "tap9632e3f8-53"
    Port br-ex
      Interface br-ex
        type: internal
    Port "tap75223dc9-8f"
      Interface "tap75223dc9-8f"
  Bridge br-int
    Controller "tcp:10.56.45.218:6653"
      is_connected: true
    fail_mode: secure
    Port "tapf48d65b7-85"
      Interface "tapf48d65b7-85"
    Port br-int
      Interface br-int
        type: internal
    Port "tap26755062-0b"
      Interface "tap26755062-0b"
    Port "tapc8993f73-f7"
      Interface "tapc8993f73-f7"
  ovs_version: "1.10.2"
connected: true になっていて、接続されています。
br-int には Neutron のポートに対応するインタフェースがあることが分かります。

Compute Node の方も同じように試してみてください。
devstack を Controller Node で先に実行しているので、こちらには何もありません。

VM を起動してみる


ここで VM を起動してみましょう。
$ nova boot --image tty-quantum --flavor m1.tiny vm1
$ OS_USERNAME=admin OS_TENANT_NAME=admin nova hypervisor-servers ostack
+--------------------------------------+-------------------+---------------+---------------------+
| ID                                   | Name              | Hypervisor ID | Hypervisor Hostname |
+--------------------------------------+-------------------+---------------+---------------------+
| 9170da74-be92-4df4-8f6a-3963de13eede | instance-00000003 | 1             | ostack05            |
| a0d1f35a-0200-4145-9c17-470710f31dd0 | instance-00000004 | 2             | ostack06            |
+--------------------------------------+-------------------+---------------+---------------------+
$ OS_USERNAME=admin OS_TENANT_NAME=admin nova hypervisor-list
+----+---------------------+
| ID | Hypervisor hostname |
+----+---------------------+
| 1  | ostack05            |
| 2  | ostack06            |
+----+---------------------+
今回は Compute ノード側で起動しました。

console.log を見て、アドレスが割り当てられているか確認しましょう。

Horizon のコンソールからログインして ping が通れば成功です。

時間もせまってきたようなので、そろそろ終わりにしようと思います。
一応うまく行ったみたいです。
飲みながらやっていると、全然進みませんね。