2016年3月17日木曜日

contrail_sandeshlibs.pyの使いかた

vRouter-agentのintrospectで、virutal-networkを見る場合、 http://<compute-node>:8085/Snh_VnListReq?name= でXMLを確認できます。
ただ、生のintrospectデータはXMLのため、ブラウザでは見えないタグなどがついていてpythonでは扱いにくいです。
contrail_sandeshlibs.py はintrospectのXMLデータをpythonのdict/list形式に変換するプログラムです。
contrail_sandeshlibs.pyはxmlの'@type'のTypeが'sandesh', 'struct', 'i64', 'i32', 'i16', 'u64', 'u32', 'u16', 'double', 'string', 'bool'の場合、Pythonの辞書キーをセットします。
もし、タイプがlistの場合、共通の辞書キーの中にリストを格納します。
contrail_sandeshlibs.py はsandeshのテーブル名から多数のdef定義してあります。
例えば、def get_vn_list(self, name='') はVnListRespから命名されています。
それぞれのdefはコメントを参照してください。

注意: 幾つかのdefは大量のデータを返します。特にifmap系のデータは大量です。事故を防ぐため、幾つかのifmapのdefはフラグを立てないと全てのデータを取ることはできません。全てを取得したい場合、ifmap_dump=Trueを引数にセットしてください。

** vrouter introspect のドキュメントはこちら
** bumtreedisp.pytor_tsn_compare.pyはこのライブラリを使っています。

使い方

1) librariesのインストール
sys
copy
xmltodict
urllib2
** contrail_sandeshlibs.py は以下のライブラリを使っています。xmltodictは標準ライブラリではないですが、Contrailが使っているライブラリです

2) contrail_sandeshlibs のインポート
3) ホスト名とポートのセット. デフォルト値 hostname=127.0.0.1 port=8085
   ポート番号はデーモン毎に異なります。こちらを参照してください。 RolesDaemaonPorts.
4) オブジェクトの作成
5) インスタンスの実行。引数をつけることが可能です。

### Sample code
from contrail_sandeshlibs import *

hostname='172.27.113.207'
port='8085'

a = GetContrailSandesh(hostname=hostname,port=port)
py_dict = a.get_vn_list(name='default-domain:test-project1:VRRPvn1')
return py_dict
### Example:Result
{u'VnListResp': {u'vn_list': {u'vxlan_id': u'7833', u'bridging': u'true', u'name': u'default-domain:test-project1:VRRPvn1', u'admin_state': u'true', u'mirror_acl_uuid': '', u'acl_uuid': '', u'config_vxlan_id': u'0', u'enable_rpf': u'true', u'ipv4_forwarding': u'true', u'flood_unknown_unicast': u'false', u'vrf_name': u'default-domain:test-project1:VRRPvn1:VRRPvn1', u'layer2_forwarding': u'true', u'ipam_host_routes': {u'ipam_name': u'default-domain:default-project:default-network-ipam', u'host_routes': ''}, u'mirror_cfg_acl_uuid': '', u'ipam_data': {u'dns_server': u'10.0.0.2', u'dhcp_enable': u'true', u'ipam_name': u'default-domain:default-project:default-network-ipam', u'ip_prefix': u'10.0.0.0', u'prefix_len': u'24', u'gateway': u'10.0.0.1'}, u'vn_id': u'7833', u'uuid': u'bf34d68a-1eb7-4722-ac78-d7d6104de250'}}}
### Example:Raw XML これは元データです。これが上のようなdictに変換されます
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="/universal_parse.xsl"?>
<__VnListResp_list type="slist">
  <VnListResp type="sandesh">
    <vn_list type="list" identifier="1">
      <list type="struct" size="1">
        <VnSandeshData>
          <name type="string" identifier="1">default-domain:test-project1:VRRPvn1</name>
          <uuid type="string" identifier="2">bf34d68a-1eb7-4722-ac78-d7d6104de250</uuid>
          <acl_uuid type="string" identifier="3" link="AclReq"/>
          <mirror_acl_uuid type="string" identifier="4" link="AclReq"/>
          <mirror_cfg_acl_uuid type="string" identifier="5" link="AclReq"/>
          <vrf_name type="string" identifier="6" link="VrfListReq">default-domain:test-project1:VRRPvn1:VRRPvn1</vrf_name>
          <ipam_data type="list" identifier="7">
            <list type="struct" size="1">
              <VnIpamData>
                <ip_prefix type="string" identifier="1">10.0.0.0</ip_prefix>
                <prefix_len type="i32" identifier="2">24</prefix_len>
                <gateway type="string" identifier="3">10.0.0.1</gateway>
                <ipam_name type="string" identifier="4">default-domain:default-project:default-network-ipam</ipam_name>
                <dhcp_enable type="string" identifier="5">true</dhcp_enable>
                <dns_server type="string" identifier="6">10.0.0.2</dns_server>
              </VnIpamData>
            </list>
          </ipam_data>
          <ipam_host_routes type="list" identifier="8">
            <list type="struct" size="1">
              <VnIpamHostRoutes>
                <ipam_name type="string" identifier="1">default-domain:default-project:default-network-ipam</ipam_name>
                <host_routes type="list" identifier="2">
                  <list type="string" size="0"/>
                </host_routes>
              </VnIpamHostRoutes>
            </list>
          </ipam_host_routes>
          <layer2_forwarding type="bool" identifier="9">true</layer2_forwarding>
          <ipv4_forwarding type="bool" identifier="10">true</ipv4_forwarding>
          <admin_state type="bool" identifier="11">true</admin_state>
          <vxlan_id type="i32" identifier="12">7833</vxlan_id>
          <config_vxlan_id type="i32" identifier="13">0</config_vxlan_id>
          <vn_id type="i32" identifier="14">7833</vn_id>
          <enable_rpf type="bool" identifier="15">true</enable_rpf>
          <bridging type="bool" identifier="16">true</bridging>
          <flood_unknown_unicast type="bool" identifier="17">false</flood_unknown_unicast>
        </VnSandeshData>
      </list>
    </vn_list>
    <more type="bool" identifier="0">true</more>
  </VnListResp>
  <Pagination type="sandesh">
    <req type="struct" identifier="1">
      <PageReqData>
        <prev_page type="string" identifier="1" link="PageReq"/>
        <next_page type="string" identifier="2" link="PageReq"/>
        <first_page type="string" identifier="3" link="PageReq">begin:0,end:99,table:db.vn.0,name:default-domain:test-project1:VRRPvn1</first_page>
        <all type="string" identifier="4" link="PageReq">begin:-1,end:-1,table:db.vn.0,name:default-domain:test-project1:VRRPvn1</all>
        <table_size type="u32" identifier="5">2</table_size>
        <entries type="string" identifier="6">0-0/1</entries>
      </PageReqData>
    </req>
    <more type="bool" identifier="0">false</more>
  </Pagination>
</__VnListResp_list>

2016年2月23日火曜日

Contrail R2.2X 系より前でnfsを使ってNova live migrationする場合の注意

Contrail R2.2X系より前で、Contrail付属のOpenstackを使用している場合、nova live-migration時の設定は以下に注意。
これをしないと以下のように怒られる。
ERROR (BadRequest): contrail-07 is not on shared storage: Live migration can not be used without shared storage. (HTTP 400) (Request-ID: req-6e3cf590-13a9-4dd0-8406-af54d1a0f17e)

**必須項目
NFSのマウントポイントは /var/lib/nova/instances/global を設定

/etc/nova/nova.conf は以下の設定が必要
state_path=/var/lib/nova
live_migration_flag = VIR_MIGRATE_UNDEFINE_SOURCE, VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_LIVE
storage_scope=global

参考)
root@contrail-08:~# mount | grep nfs
172.27.113.201:/lib/nfs/nova on /var/lib/nova/instances/global type nfs (rw,clientaddr=192.168.22.1,addr=172.27.113.201)
/etc/nova/nova.conf
[DEFAULT]
dhcpbridge_flagfile=/etc/nova/nova.conf
dhcpbridge=/usr/bin/nova-dhcpbridge
logdir=/var/log/nova
state_path=/var/lib/nova
lock_path=/var/lib/nova/tmp
force_dhcp_release=True
libvirt_use_virtio_for_bridges=True
verbose=True
ec2_private_dns_show_ip=False
api_paste_config=/etc/nova/api-paste.ini
enabled_apis=ec2,osapi_compute,metadata
neutron_admin_auth_url = http://10.84.50.8:5000/v2.0/
auth_strategy = keystone
libvirt_nonblocking = True
libvirt_inject_partition = -1
rabbit_host = 10.84.50.100
glance_host = 10.84.50.8
neutron_admin_tenant_name = service
neutron_admin_username = neutron
neutron_admin_password = juniper123
neutron_url = http://10.84.50.100:9696/
neutron_url_timeout = 300
network_api_class = nova.network.neutronv2.api.API
compute_driver = libvirt.LibvirtDriver
novncproxy_base_url = http://172.27.113.201:6080/vnc_auto.html
vncserver_enabled = true
vncserver_listen = 0.0.0.0
vncserver_proxyclient_address = 192.168.22.1
security_group_api = neutron
heal_instance_info_cache_interval = 0
image_cache_manager_interval = 0
libvirt_cpu_mode = none
libvirt_vif_driver = nova_contrail_vif.contrailvif.VRouterVIFDriver
firewall_driver = nova.virt.firewall.NoopFirewallDriver
glance_port = 9292
glance_num_retries = 10
rabbit_port = 5673
rabbit_retry_interval = 1
rabbit_retry_backoff = 2
rabbit_max_retries = 0
rabbit_ha_queues = True
rpc_cast_timeout = 30
rpc_conn_pool_size = 40
rpc_response_timeout = 60
rpc_thread_pool_size = 70
report_interval = 15
novncproxy_port = 6080
vnc_port = 5900
vnc_port_total = 100
resume_guests_state_on_host_boot = True
service_down_time = 300
periodic_fuzzy_delay = 30
disable_process_locking = True
live_migration_flag = VIR_MIGRATE_UNDEFINE_SOURCE, VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_LIVE
storage_scope=global

[keystone_authtoken]
admin_tenant_name = service
admin_user = nova
admin_password = juniper123
auth_host = 10.84.50.8
auth_protocol = http
auth_port = 5000
signing_dir = /tmp/keystone-signing-nova

2016年2月8日月曜日

Contrail TSNとToR SwitchのOVSDB-Serverのデータをチェックするプログラム

bumtreedisp.pyというContrailのBUM Treeを出力するプログラムを作りました。
今回はtor_tsn_compare.pyという、Contrail TSNとToR SwitchのOVSDB-Serverのデータをチェックするプログラムを作ったので公開。

両方のプログラムに共通する点は、contrail_sandeshlibsというプログラムをimportしているところです。
contrail_sandeshlibsはvRouter-agentやControl-nodeなどのIntrospect情報(xml)をブラウザ上で見える部分をdictのキーにして出力するLibraryです。contrail_sandeshlibsについては別途Blogを書きますのでしばらくお待ちください。

ContrailはOVSDBでToR-Switch(Hardware VTEP)にデータを送って、物理ポート、VLAN設定、Remote VTEPの設定などを行います。
下図はOVSDBを使った場合のデータの流れです。
  1. ToR SwitchはHAProxy(TSNを冗長化する場合)にOVSDB over TLSのセッションを張る
  2. HA ProxyはいずれかのTSNにOVSDB over TLSのセッションを張る
  3. ToR AgentはBUM用のff:ff:ff:ff:ff:ff(any-dst)やUnicastのRemote VTEPの情報、VLANやVNIの情報をToR Switchに送信
  4. ToR Agentは自分が接続しているToR SwitchのVTEP情報やMACアドレス情報をControl nodeに送信
  5. Control-nodeは他のToR-AgentやvRouter-agent(TSNやCompute-node)に送信
(データモデルなどはGitのWikiJuniper.netを見てください。)

つまり、ToR Switchは色々なコンフィグをTSN(ToR-agent)から受信します。
このとき、障害などでTSNとToR-Switchの情報が一致しない場合があり、通信ができないなどの事象が発生する場合があります。
OVSDBのHardwareVTEPには複数のSchemaが定義されています(詳細はこちら)。これらをTSN側のデータと同期しているか確認すれば、どのデータが欠けているのかなどがわかります。

例えば、 ToR Switchが受信しているUcast_Macs_Remoteは以下のように表示されます(ovsdb-clientを使用)。
Ucast_Macs_Remote table
MAC                 _uuid                                ipaddr locator                              logical_switch                      
------------------- ------------------------------------ ------ ------------------------------------ ------------------------------------
"02:8f:d5:8e:e6:56" 26a7d358-4c43-4831-a495-a4373042776e ""     331baf5f-6b34-4a7d-8df2-fb2aa2e6eff8 bced0b50-fbaf-4757-bb4c-0ef9532e8eaa
"02:e4:d7:4c:50:cc" a7768131-4d58-4fd0-af67-ced3836011af ""     a113bfee-4156-45ea-8371-f58dc2f1eab5 bced0b50-fbaf-4757-bb4c-0ef9532e8eaa
"22:22:22:00:00:01" 4b514bb4-e28c-49e8-bf27-bfeba71c638b ""     df1e1788-e7a7-449e-be04-4143209b776b 6b1e1249-8d02-4bbf-aac6-da9d9906dd5e
"22:22:22:00:00:01" 8c86ef9a-3a98-4adf-bdb4-cdf087018e59 ""     df1e1788-e7a7-449e-be04-4143209b776b 9a892745-09a4-434a-8bc6-b261668e8019
"22:22:22:00:00:01" b0761188-a077-4869-a6ff-78f0217951cc ""     df1e1788-e7a7-449e-be04-4143209b776b ca899f3d-d5df-44f8-9126-90125f0f52e4
"22:22:22:00:00:01" d88c82db-d8a2-40b5-a59c-8610c7e75320 ""     df1e1788-e7a7-449e-be04-4143209b776b e691aaae-e42f-4b3c-93a6-128b5421de58
"22:22:22:00:00:01" dea6b7d0-69e7-4da3-ab3e-f84e92efc9ed ""     df1e1788-e7a7-449e-be04-4143209b776b 8957219c-ed1a-4a8a-829f-4a4ccd3ef41b
"22:22:22:00:00:01" f1f35b78-aa31-47db-90ae-fb85dee61359 ""     df1e1788-e7a7-449e-be04-4143209b776b 6079900f-5e6a-45d7-b11f-adaab6442663
"22:22:22:00:00:02" 7c70dc8c-7cd7-492a-805a-b5e7519af880 ""     df1e1788-e7a7-449e-be04-4143209b776b 1c6e1fd8-89f0-4752-baec-2859f409b215
"22:22:22:00:00:02" 8b8c086b-b6d0-4519-a620-0da110fc60ff ""     df1e1788-e7a7-449e-be04-4143209b776b 895c18c3-3578-44e9-a0e3-939289b5a473
"22:22:22:00:00:02" 8d5cbf5a-1095-49ed-be28-0c8035762174 ""     df1e1788-e7a7-449e-be04-4143209b776b cdf05c2a-7f0f-4922-a1d8-95d2d38e219f
"22:22:22:00:00:02" 9027f67f-e216-4a6b-9843-a3a40688d261 ""     df1e1788-e7a7-449e-be04-4143209b776b 61f1d0a8-3889-46be-9ca0-ff45794346d5
"22:22:22:00:00:02" 9856a1e9-075e-420f-aa2f-0c45e3bb1b86 ""     df1e1788-e7a7-449e-be04-4143209b776b 827da3e0-b340-4beb-8b8b-77d8a94c1409
"22:22:22:00:00:02" a25fbec4-24a6-454c-81c5-ac6b7e677682 ""     df1e1788-e7a7-449e-be04-4143209b776b c90463d7-42e7-403f-a1ac-acb743d28f12

ここで面倒なのが、locatorのカラムです。このlocatorはRemote VTEPをさしているのですが、実際のIPアドレスを知るには別のテーブルPhysical_Locator参照しなければなりません。
Physical_Locator table
_uuid                                dst_ip         encapsulation_type
------------------------------------ -------------- ------------------
ea87b2ee-150e-4b60-8374-9792b0cc1172 "10.84.50.4"   "vxlan_over_ipv4" 
353eb19e-6a82-4d5a-9505-e0845b820e86 "10.84.51.72"  "vxlan_over_ipv4" 
df1e1788-e7a7-449e-be04-4143209b776b "10.84.51.73"  "vxlan_over_ipv4" 
331baf5f-6b34-4a7d-8df2-fb2aa2e6eff8 "192.168.21.1" "vxlan_over_ipv4" 
a113bfee-4156-45ea-8371-f58dc2f1eab5 "192.168.22.1" "vxlan_over_ipv4" 

これらを合わせるとやっとMACアドレスがどのRemoteVTEPにいるのかわかります。
さらに、この情報はTSNのOvsdbUnicastMacRemote というテーブルの一部を参照します。
※ TSNのOVSDBの情報は TSN_IPaddress:Port/ovsdb.xml で参照できます。

このテーブルを得るには仮想ネットワークのUUIDが必要です。
MACアドレスがどの仮想ネットワークに所属しているかはUcast_Macs_Remoteのlogical-switchカラムのUUIDからLogical_Switchテーブルを参照し、仮想ネットワークのUUIDを確認する必要があります。Contrailの場合、"Contrail-" + UUIDです。
Logical_Switch table
_uuid                                description name                                            tunnel_key
------------------------------------ ----------- ----------------------------------------------- ----------
827da3e0-b340-4beb-8b8b-77d8a94c1409 ""          "Contrail-0c286caa-915e-48e5-a386-50b324c22a70" 2152      
31f1c529-3c00-4066-a589-34ce67fd5e55 ""          "Contrail-220539f5-cee1-44f3-8c79-1a2ad56dc04d" 1809      
e691aaae-e42f-4b3c-93a6-128b5421de58 ""          "Contrail-25fb215b-4819-463f-be6a-0aa13c6ca984" 2041      
1c6e1fd8-89f0-4752-baec-2859f409b215 ""          "Contrail-37b9045c-6411-4fdc-8ec0-62accb6856a3" 2162      
61f1d0a8-3889-46be-9ca0-ff45794346d5 ""          "Contrail-39fb95bc-a339-4d3e-877e-34ba35c1c8a0" 1843      
13f4993a-5eda-46ae-81ff-f9aa6886b74f ""          "Contrail-5818adc2-1a15-4e90-a361-1ff0494f0227" 2359      
cdf05c2a-7f0f-4922-a1d8-95d2d38e219f ""          "Contrail-6cfdaa57-8dea-4c95-885e-3d5b87dd832c" 2008      
895c18c3-3578-44e9-a0e3-939289b5a473 ""          "Contrail-76ac5c31-dda6-4fae-870f-92d48f042c95" 2028      
bced0b50-fbaf-4757-bb4c-0ef9532e8eaa ""          "Contrail-7bab18ee-5eac-46df-9fe6-ccaa4a5dd445" 2336      
9a892745-09a4-434a-8bc6-b261668e8019 ""          "Contrail-8384126e-2ec8-4ab2-8e31-45ba1e87548a" 1878      
6079900f-5e6a-45d7-b11f-adaab6442663 ""          "Contrail-8961314e-afc6-471f-83dc-e32153440897" 2009      
ca899f3d-d5df-44f8-9126-90125f0f52e4 ""          "Contrail-912590b7-cdce-41ae-bc43-b8efff5504c2" 2055      
c90463d7-42e7-403f-a1ac-acb743d28f12 ""          "Contrail-955c489a-9712-4ee0-95ed-03021356bde6" 2046      
8957219c-ed1a-4a8a-829f-4a4ccd3ef41b ""          "Contrail-b573a1b8-e322-4896-85f9-33d7b428411e" 2153      
6b1e1249-8d02-4bbf-aac6-da9d9906dd5e ""          "Contrail-e9291384-666f-4c6a-bc23-54a396b6813f" 1815      

これらのテーブルを一つずつ確認するのは大変なので、python tor_tsn_compare.pyをつくりました。
https://github.com/nakadaisuke/contrail_utils/tree/master/getnhutils から以下の3ファイルをダウンロードしてください。基本的にContrailで使っているPhythonパッケージを使用しています。
contrail_sandeshlibs.py
ovsdb_schema_reader.py
tor_tsn_compare.py

使用ライブラリ
sys
xmltodict
urllib2
socket
json
argarse
copy

使用方法
tor_tsn_compare.py -t 'TSNのIPアドレス' -o 'ToR-SwitchのIPアドレス' -v 'verbose'

例えば以下のようにコマンドを打ちます。冗長化をしていてTSNが複数ある場合は ","でつないでください。
python tor_tsn_compare.py -t '172.27.113.205:9011','172.27.113.206:9011' -o 172.27.113.51:9999
-v Trueしない場合、Syncしているテーブルは"Sync all data"と表示されます。Syncしていないテーブルはテーブルが表示されます。
python tor_tsn_compare.py -t '172.27.113.205:9011','172.27.113.206:9011' -o 172.27.113.51:9999
-------- Mcast_Macs_Remote Table --------
Sync all data
-------- Ucast_Macs_local Table --------
Sync all data
-------- Mcast_Macs_Local Table --------
Sync all data
-------- Physical_Switch Table --------
Sync all data
-------- Logical_Switch Table --------
Sync all data
-------- Ucast_Macs_Remote Table --------
Sync all data
-------- Physical_Port Table --------
Sync all data

-v Trueした場合、全ての結果が表示されます。(データが多いので一部割愛)
python tor_tsn_compare.py -t '172.27.113.205:9011','172.27.113.206:9011' -o 172.27.113.51:9999 -v True
-------- Mcast_Macs_Remote Table --------
[[u'In sync(4)', u'ff:ff:ff:ff:ff:ff', u'0c286caa-915e-48e5-a386-50b324c22a70', u'10.84.50.4']]
[[u'In sync(4)', u'ff:ff:ff:ff:ff:ff', u'220539f5-cee1-44f3-8c79-1a2ad56dc04d', u'10.84.50.4']]
[[u'In sync(4)', u'ff:ff:ff:ff:ff:ff', u'25fb215b-4819-463f-be6a-0aa13c6ca984', u'10.84.50.4']]
[[u'In sync(4)', u'ff:ff:ff:ff:ff:ff', u'37b9045c-6411-4fdc-8ec0-62accb6856a3', u'10.84.50.4']]
-------- Ucast_Macs_local Table --------
[[u'In sync(4)', u'22:22:22:00:00:01', u'0c286caa-915e-48e5-a386-50b324c22a70', u'10.84.51.72']]
[[u'In sync(4)', u'22:22:22:00:00:01', u'37b9045c-6411-4fdc-8ec0-62accb6856a3', u'10.84.51.72']]
[[u'In sync(4)', u'22:22:22:00:00:02', u'b573a1b8-e322-4896-85f9-33d7b428411e', u'10.84.51.72']]
[[u'In sync(4)', u'22:22:22:00:00:02', u'e9291384-666f-4c6a-bc23-54a396b6813f', u'10.84.51.72']]
-------- Mcast_Macs_Local Table --------
[[u'In sync(4)', u'ff:ff:ff:ff:ff:ff', u'0c286caa-915e-48e5-a386-50b324c22a70', u'10.84.51.72']]
[[u'In sync(4)', u'ff:ff:ff:ff:ff:ff', u'220539f5-cee1-44f3-8c79-1a2ad56dc04d', u'10.84.51.72']]
[[u'In sync(4)', u'ff:ff:ff:ff:ff:ff', u'25fb215b-4819-463f-be6a-0aa13c6ca984', u'10.84.51.72']]
[[u'In sync(4)', u'ff:ff:ff:ff:ff:ff', u'37b9045c-6411-4fdc-8ec0-62accb6856a3', u'10.84.51.72']]
[[u'In sync(4)', u'ff:ff:ff:ff:ff:ff', u'39fb95bc-a339-4d3e-877e-34ba35c1c8a0', u'10.84.51.72']]
[[u'In sync(4)', u'ff:ff:ff:ff:ff:ff', u'b573a1b8-e322-4896-85f9-33d7b428411e', u'10.84.51.72']]
[[u'In sync(4)', u'ff:ff:ff:ff:ff:ff', u'e9291384-666f-4c6a-bc23-54a396b6813f', u'10.84.51.72']]
-------- Physical_Switch Table --------
[[u'In sync(4)', u'shinjuku', u'10.84.51.72']]
-------- Logical_Switch Table --------
[[u'In sync(4)', u'0c286caa-915e-48e5-a386-50b324c22a70', u'2152']]
[[u'In sync(4)', u'220539f5-cee1-44f3-8c79-1a2ad56dc04d', u'1809']]
[[u'In sync(4)', u'912590b7-cdce-41ae-bc43-b8efff5504c2', u'2055']]
[[u'In sync(4)', u'b573a1b8-e322-4896-85f9-33d7b428411e', u'2153']]
[[u'In sync(4)', u'e9291384-666f-4c6a-bc23-54a396b6813f', u'1815']]
-------- Ucast_Macs_Remote Table --------
[[u'In sync(4)', u'02:8f:d5:8e:e6:56', u'7bab18ee-5eac-46df-9fe6-ccaa4a5dd445', u'192.168.21.1']]
[[u'In sync(4)', u'02:e4:d7:4c:50:cc', u'7bab18ee-5eac-46df-9fe6-ccaa4a5dd445', u'192.168.22.1']]
[[u'In sync(4)', u'22:22:22:00:00:01', u'8384126e-2ec8-4ab2-8e31-45ba1e87548a', u'10.84.51.73']]
[[u'In sync(4)', u'22:22:22:00:00:01', u'8961314e-afc6-471f-83dc-e32153440897', u'10.84.51.73']]
[[u'In sync(4)', u'22:22:22:00:00:01', u'912590b7-cdce-41ae-bc43-b8efff5504c2', u'10.84.51.73']]
-------- Physical_Port Table --------
[[u'In sync(4)', [[u'4001', u'25fb215b-4819-463f-be6a-0aa13c6ca984']], u'ge-0/0/10']]
[[u'In sync(4)', [[u'4001', u'955c489a-9712-4ee0-95ed-03021356bde6']], u'ge-0/0/11']]
[[u'In sync(4)', [[u'4001', u'912590b7-cdce-41ae-bc43-b8efff5504c2']], u'ge-0/0/12']]
[[u'In sync(4)', [[u'4001', u'0c286caa-915e-48e5-a386-50b324c22a70']], u'ge-0/0/13']]
[[u'In sync(4)', [[u'10', u'5818adc2-1a15-4e90-a361-1ff0494f0227'], [u'100', u'5818adc2-1a15-4e90-a361-1ff0494f0227'], [u'1000', u'220539f5-cee1-44f3-8c79-1a2ad56dc04d']], u'ge-0/0/19']]
[[u'In sync(4)', [[u'0', u'7bab18ee-5eac-46df-9fe6-ccaa4a5dd445']], u'ge-0/0/20']]
[[u'In sync(4)', [], u'ge-0/0/23']]
[[u'In sync(4)', [], u'ge-0/0/24']]
[[u'In sync(4)', [], u'ge-0/0/25']]

出力方式とかご意見あればgitへのコメントやメールをいただければなと。

2015年12月15日火曜日

Contrailのmulticast treeを表示するプログラム

ContrailはBUMトラフィックを処理するときに、特定のノードが大量のコピーをして付加が増えないようにツリーを作ります。
このとき、1つのvrouterは最大4台のvRouterへトラフィックをコピーします。
実際のツリーを確認するには、コマンドラインかIntrospectで確認できるのですが、複数のvRouterにアクセスしなければ確認できないので面倒です。
例えばコマンドラインの場合、以下の手順で確認できます。
1)VNIからNextHop IDを確認
root@contrail-05:~# vxlan --get 2008
VXLAN Table

 VNID    NextHop
----------------
   2008    183

2) NextHopからVRF IDを確認
root@contrail-05:~# nh --get 183
Id:183        Type:Vrf_Translate  Fmly: AF_INET  Flags:Valid, Vxlan, Unicast Flood,   Rid:0  Ref_cnt:2 Vrf:2005
              Vrf:2005

3) VRF IDからMACリストを確認
root@contrail-05:~# rt --dump 2005 --family bridge
Kernel L2 Bridge table 0/2005

Flags: L=Label Valid, Df=DHCP flood

Index     DestMac                          Flags       Label/VNID      Nexthop
170652     0:44:44:0:0:12                                       -          1
249441     a0:36:9f:74:88:d8                  Df                -          3
315393     0:0:5e:0:1:0                       Df                -          3
404400     0:22:22:0:0:12                                       -          1
540752     ff:ff:ff:ff:ff:ff                 LDf             2008        203
656836     2:d2:2f:ef:ae:93                  LDf               27        792
797245     2:b:eb:af:7:f5                    LDf               24        397

4) ff:ff:ff:ff:ff:ff のNextHopを確認し、Sub NHを確認していく。
root@contrail-05:~# nh --get 203
Id:203        Type:Composite  Fmly:AF_BRIDGE  Flags:Valid, Multicast, L2,   Rid:0  Ref_cnt:4 Vrf:2005
              Sub NH(label): 209(0) 204(0) 200(0)

今回作ったプログラムはVNIとvRouterのアドレスを入れれば自動的にBUMを複製するリストを出します。 
プログラムはこちら
必要なライブラリは argparse, sys, xmldict, urllib2です。

使い方はpython bumtreedisp.py -t <vRouterアドレス> -v <VNI>です。
以下のように出力します。
root@console:~# python bumtreedisp.py -t 172.27.113.207 -v 2008
### Host 172.27.113.207 VNI 2008 BUM Tree ###
---- TAP interfaces ----
TAP:tapd22fefae-93  MAC:02:d2:2f:ef:ae:93
---- Tunnel interfaces ----
SIP:192.168.21.1    DIP:10.84.50.5      Encap:MPLSoUDP
SIP:192.168.21.1    DIP:192.168.22.1    Encap:MPLSoUDP※まだ作り途中のため、エラーハンドリングなどが入っていません。
※今後もアップデート予定です。
※2015/12/16出力を調整
※2016/2/8 importしているライブラリをContrailが使用しているxmltodictに変更。合わせてコードを少しきれいにした。 ※2016/3/30 一応αをとった

2015年10月7日水曜日

OpenContrailのSimple Gatewayの作り方 (改訂版)

以前このポストでSimple Gatewayの作り方を書きましたが、2.20で再度試したところバグが直っていて作成方法が少し変わったので再度ポストします。

下図のようにFloatingIPやインターネットに出て行くIPアドレスとして203.0.113.0/24を割り当てます。
この仮想ネットワークはSimpleゲートウェイを作成する前に作成しておきます。
vhost0とRouterの間は適宜接続できるように設定してださい。Compute NodeのDefault GatewayはRouterのアドレスになります。
テスト環境などでグローバルIPアドレスをFloatingIPに割り当てられない場合は、RouterでNATできるように事前に設定してください。
この例では作成されるテナント(プロジェクト)はadminで仮想ネットワーク名はpublicと設定します。


このネットワークに対してSimple gatewayを作成します。


Simple GatewayはコンピュートノードのvRouterをゲートウェイとして利用し、コンピュートノードをゲートウェイとするため、コンピュートノードコマンドを実行します。
まず、以下のディレクトリをexport
export PYTHONPATH=/usr/lib/python2.7/dist-packages/contrail_vrouter_api/gen_py/instance_service/
export PYTHONPATH=/usr/lib/python2.7/dist-packages/nova_contrail_vif/gen_py/instance_service/

次に、provision_vgw_interface.pyでゲートウェイを作成する
python /opt/contrail/utils/provision_vgw_interface.py --oper create --interface vgw1 --subnets 203.0.113.0/24 --route 0.0.0.0/0 --vrf default-domain:admin:public:public

--vrfの引数がdefault-domain:admin:public:publicと仮想ネットワーク名が重なっていますが、これは設定するルーティングインスタンス名です。


この設定をすると、コンピュートノードはvhost経由で外部ネットワークと通信を行います。
インターネットのゲートウェイルータやゲートウェイサーバには仮想ネットワークに通信できるようにルーティングの追加を忘れないようにしてください。

ここまで設定すると、vRouterに VGW1と --routeで設定したルーティング情報が追加されます。
後は仮想マシンにpublicからIPアドレスを割り当てるか、publicからFloating IPを作成し、仮想マシンに割り当てれば外部ネットワークに接続できます。

2015年7月3日金曜日

REST/API ヘルパーを作ってみた

Pythonの勉強がてらREST/APIのヘルパーを作成してみました。
もともとContrailのREST/APIを叩くのに作りましたが、考えてみればOpenStack系のREST/APIでも使えると思ったので公開します。
コードはこちらです。
※まだ入力値のバリデーションとかありません。今後追加していく予定です。

動作:
ユーザー/パスワードをKeystoneに認証し、トークンを受け取った後別のサーバに接続します。

使い方:
Contrail-json.py -k <Keyston IP> -c <Contrail-API> を実行すると、Contrail-APIに接続し、ルートの情報をゲットします。
ゲットしたJSONはデフォルトで見やすくインデントして表示します。

オプション:
-k : Keystone のIPアドレスを入力
-c : Contrail-APIのアドレスを入力
-u : ユーザー名を入力
-p : パスワードを入力
-t : テナント名を入力
-o :get, delete, post, put のいずれかを入力。デフォルトget
-b : JSONメッセージなど、post / putするデータを入力。 ' ' でくくると良い
-d :URIのディレクトリ部を入力。 /v2/network など
-T :ゲットしたJSONメッセージの整形の可否を入力。True/False。デフォルトTrue
-P :認証後に接続するサーバのポート番号を入力。デフォルト8082

例)Keystone と Contrailのアドレスを入れて、仮想ネットワーク一覧を取得
./Contrail_json.py -k 172.27.113.85 -c 172.27.113.85 -u admin -p contrail123 -d virtual-networks
出力結果
{
    "virtual-networks": [
        {
            "fq_name": [
                "default-domain", 
                "default-project", 
                "ip-fabric"
            ], 
            "href": "http://172.27.113.85:8082/virtual-network/263cea75-de70-483b-a05a-76975c8a5387", 
            "uuid": "263cea75-de70-483b-a05a-76975c8a5387"
        }, 
        {
            "fq_name": [
                "default-domain", 
                "demo", 
                "testVN1"
            ], 
            "href": "http://172.27.113.85:8082/virtual-network/289ee5a1-f529-45fd-aa43-180520769227", 
            "uuid": "289ee5a1-f529-45fd-aa43-180520769227"
        }
    ]
}

例)仮想ネットワークを作成
./Contrail_json.py -k 172.27.113.85 -c 172.27.113.85 -u admin -p contrail123 -d virtual-networks -o post -b '{"virtual-network": {"
display_name": "testVN1","flood_unknown_unicast": true,"fq_name": ["default-domain","demo","testVN"],"is_shared": false,"network_ipam_refs": [{"attr": {"ipam_subnets": 
[{"addr_from_start": true,"allocation_pools": [],"default_gateway": "20.0.0.1","dhcp_option_list": {"dhcp_option": []},"dns_server_address": "20.0.0.2","enable_dhcp": t
rue,"host_routes": {"route": []},"subnet": {"ip_prefix": "20.0.0.0","ip_prefix_len": 24}}]},"to": ["default-domain","default-project","default-network-ipam"]}],"parent_
type": "project","parent_uuid": "8e19297b-5c3c-4b48-85f2-76229e27b1a1","route_target_list": {"route_target": ["target:64512:39999"]},"router_external": false,"routing_i
nstances": [{"to": ["default-domain","demo","testVN1","testVN1"]}],"uuid": "32100000-0000-0000-0000-000000000001","virtual_network_properties": {"allow_transit": false,
"forwarding_mode": "l2_l3"}}}'
出力結果
{
    "virtual-network": {
        "fq_name": [
            "default-domain", 
            "demo", 
            "testVN"
        ], 
        "href": "http://172.27.113.85:8082/virtual-network/32100000-0000-0000-0000-000000000001", 
        "name": "testVN", 
        "parent_href": "http://172.27.113.85:8082/project/8e19297b-5c3c-4b48-85f2-76229e27b1a1", 
        "parent_uuid": "8e19297b-5c3c-4b48-85f2-76229e27b1a1", 
        "uuid": "32100000-0000-0000-0000-000000000001"
    }
}

例)仮想ネットワークを削除
./Contrail_json.py -k 172.27.113.85 -c 172.27.113.85 -u admin -p contrail123 -d virtual-networks -o delete
出力結果
delete "virtual-network/32100000-0000-0000-0000-000000000001" succesfully

2015年5月7日木曜日

ContrailのUUIDからfq-nameをゲットする方法と、fq-nameからUUIDをゲットする方法

UUIDからFQNAMEをゲットするには "id-to-fqname"にUUIDを{"uuid": "実際のUUID"}のようにポストします。 例えばUUIDが"10012000-1400-0000-0000-000000000009"の場合、以下のようになります。
curl -H "X-AUTH-TOKEN:$TOKEN" http://172.27.113.85:8082/id-to-fqname -H "Content-Type: application/json; charset=UTF-8" -d '{"uuid": "10012000-1400-0000-0000-000000000009"}'  -X POST

FQNAMが返ってきます。
{"type": "virtual_network", "fq_name": ["default-domain", "demo", "90VN_4_9"]}

逆にFQNAMEからUUIDをゲットしたい場合は""fqname-to-id"にFQNAMEを{"type": "アトリビュート", "fq_name": ["default-domain", "テナント名", "名前"]}のようにポストします。 FQNAMEはアトリビュートによって違います。 さっきの逆をして見ます。以下をポストすると
curl -H "X-AUTH-TOKEN:$TOKEN" http://172.27.113.85:8082/fqname-to-id -H "Content-Type: application/json; charset=UTF-8" -d '{"type": "virtual_network", "fq_name": ["default-domain", "demo", "90VN_4_9"]}'  -X POST 

UUIDが返ってきます。
{"uuid": "10012000-1400-0000-0000-000000000009"}