客户端可以通过ovsdb定义的协议访问openvswitch的数据库,协议在http://tools.ietf.org/html/draft-pfaff-ovsdb-proto-02,看来要成为ietf的标准了?怎么查询这些数据其实有一个样例,但是比较简单,我这里略作扩展,说明如何查询ovs的网桥、所连controller和流信息。
- 准备工作
- echo发送存活信息
- 获得所有数据库名
- 获得数据库的所有表结构
- 获得所有网桥
- 获得所有网桥
- 获得所有openflow信息
因为ovs需要认证(公钥)才能访问其数据,我们为了简化直接在ovs所在节点上运行以下命令:
ovs-appctl -t ovsdb-server ovsdb-server/add-remote ptcp:6632
然后可以直接通过tcp的方式访问ovsdb了
客户端可以使用tcp方式与服务器保持长连接,所以可能定时需要发送echo信息与服务器确认存活。可编写以下脚本:
import socket
import json
OVSDB_IP = '127.0.0.1'
OVSDB_PORT = 6632
BUFSIZE = 409600
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((OVSDB_IP, OVSDB_PORT))
query = {"method":"echo", "params":[], "id": 0}
s.send(json.dumps(query))
response = s.recv(BUFSIZE)
print response
执行结果为:
{“id”:0,”result”:[],”error”:null}
这是最简单的获取信息方式了,我们接下来要看看OVSDB中到底有些什么数据
脚本中其他不变,最后三行换为以下内容,以后步骤也是类似:
query = {"method":"list_dbs", "params":[], "id": 0}
s.send(json.dumps(query))
response = s.recv(BUFSIZE)
print response
执行后结果为
{“id”:0,”result”:[“Open_vSwitch”],”error”:null}
可见现在OVSDB中只有一个数据库Open_vSwitch。接下来我们查询这个数据库有哪些表
同样,代码为
query = {"method":"get_schema", "params":["Open_vSwitch"], "id": 0}
s.send(json.dumps(query))
response = s.recv(BUFSIZE)
print response
因为表结构字段较多,所以我们将结果格式化,执行./ovs.py |python -m json.tool
返回的结果将是所有数据库的内容
{ "error": null, "id": 0, "result": { "cksum": "2180939265 17455", "name": "Open_vSwitch", "tables": { "Bridge": { "columns": { "controller": { "type": { "key": { "refTable": "Controller", "type": "uuid" }, "max": "unlimited", "min": 0 } }, "datapath_id": { "ephemeral": true, "type": { "key": "string", "min": 0 } }, "datapath_type": { "type": "string" }, "external_ids": { "type": { "key": "string", "max": "unlimited", "min": 0, "value": "string" } }, "fail_mode": { .......................................
后面还有很多内容,在这里就不显示了。数据库除了Bridge,还有Controller、Flow Table、Interface、Manager、Mirror、Netflow、Open vswitch、Port、QoS、Queue、SSL、sFlow。看来OVS默认的流Flow表应该是openflow,其他还支持netflow和sflow。
我们查看一下网桥信息
query = {"method":"transact", "params":["Open_vSwitch", {"op":"select", "table": "Bridge", "where":[]}], "id": 0}
s.send(json.dumps(query))
response = s.recv(BUFSIZE)
print response
执行./ovs.py |python -m json.tool
返回的结果将是所有数据库的内容
{ "error": null, "id": 0, "result": [ { "rows": [ { "_uuid": [ "uuid", "fd924881-6a15-4a1b-a803-aa49efa38179" ], "_version": [ "uuid", "5306417b-381e-49dd-9ac2-0d95c450919c" ], "controller": [ "set", [] ], "datapath_id": "0000e0db551f99b4", "datapath_type": "", "external_ids": [ "map", [] ], "fail_mode": [ "set", [] ], "flood_vlans": [ "set", [] ], "flow_tables": [ "map", [] ], "mirrors": [ "set", [] ], "name": "br-ex", "netflow": [ "set", [] ], "other_config": [ "map", [] ], "ports": [ "set", [ [ "uuid", "28b44f02-7ecd-4135-9836-f1059ac1ec10" ], [ "uuid", "596e6d23-ec51-4b56-bddc-5aa0805fe16c" ], [ "uuid", "82cd970c-ac39-46e6-8aa7-b03529cc8916" ], [ "uuid", "be77f10f-1a52-4be2-8b9e-c97b26c9acee" ], [ "uuid", "f8ae4f3c-9d77-4f7e-8707-ee2e36c70e08" ] ] ], "protocols": [ "set", [] ], "sflow": [ "set", [] ], "status": [ "map", [] ], "stp_enable": false }, { "_uuid": [ "uuid", "e29eac0c-a9ae-4108-a277-21388a24a2f1" ], "_version": [ "uuid", "65e1bd22-6178-4b01-827f-8d64b0840e72" ], "controller": [ "uuid", "15846c69-f014-4a5a-bc8d-3cb67cc3cb03" ], "datapath_id": "00000eac9ee20841", "datapath_type": "", "external_ids": [ "map", [] ], "fail_mode": [ "set", [] ], "flood_vlans": [ "set", [] ], "flow_tables": [ "map", [] ], "mirrors": [ "set", [] ], "name": "br-tun", "netflow": [ "set",[] ], "other_config": [ "map", [] ], "ports": [ "set", [ [ "uuid", "aff50719-bd85-4b72-9283-656844b663aa" ], [ "uuid", "bcd6e8f9-713f-4177-b730-caed455df9b7" ], [ "uuid", "d8e93efc-7ebd-4d89-b7d2-b9b4b60c993a" ] ] ], "protocols": [ "set", [] ], "sflow": [ "set", [] ], "status": [ "map", [] ], "stp_enable": false }, .......................................
篇幅关系,这里展现了两个网桥br-ex和br-tun,其中port字段可以查询网桥上连接的端口,如果controller字段存在,说明该网桥受控制器控制。那我们再看一下其所连控制器的信息。
我们查看一下网桥信息
query = {"method":"transact", "params":["Open_vSwitch", {"op":"select", "table": "Controller", "where":[]}], "id": 0}
s.send(json.dumps(query))
response = s.recv(BUFSIZE)
print response
执行./ovs.py |python -m json.tool
返回的结果
{ "error": null, "id": 0, "result": [ { "rows": [ { "_uuid": [ "uuid", "15846c69-f014-4a5a-bc8d-3cb67cc3cb03" ], "_version": [ "uuid", "3a6bf4ed-035b-4e57-beb3-8bd08997826e" ], "connection_mode": [ "set", [] ], "controller_burst_limit": [ "set", [] ], .... "role": "master", "status": [ "map", [ [ "last_error", "Connection refused" ], [ "sec_since_connect", "423018" ], [ "sec_since_disconnect", "423089" ], [ "state", "ACTIVE" ] ] ], "target": "tcp:30.0.0.1" }, { "_uuid": [ "uuid", "77fab68b-c693-4c9e-aea7-ba847809376d" ], "_version": [ "uuid", "5e1f25ec-ae35-43fe-9cf4-835ef5980056" ], "connection_mode": [ "set", [] ], ..... "role": "master", "status": [ "map", [ [ "last_error", "Connection refused" ], [ "sec_since_connect", "423018" ], [ "sec_since_disconnect", "423089" ], [ "state", "ACTIVE" ] ] ], "target": "tcp:30.0.0.1" } ] } ] } 这里列出了两个controller项,但目标地址都是30.0.0.1,说明都是同一个controller,但是这两项的uuid不同,如15846c69-f014-4a5a-bc8d-3cb67cc3cb03是br-tun设置的controller,而77fab68b-c693-4c9e-aea7-ba847809376d是br-in设置的controller。
代码为
query = {"method":"transact", "params":["Open_vSwitch", {"op":"select", "table": "Flow_Table", "where":[]}], "id": 0}
s.send(json.dumps(query))
response = s.recv(BUFSIZE)
print response
执行./ovs.py |python -m json.tool
返回的结果result为空,而且静态动态流都为空,开始很疑惑,后来了解ovsdb主要是存放静态信息,所以流信息是没有保留的。获取流应该从vswitchd中获取,具体怎么做看下一篇吧:-)
ovsdb和vswitchd的关系如该图所示,还有一些ovs的命令。
最后说明一下,用REST访问ovsdb可以使用程序化的方法获得ovs的信息,为下一步工作打下基础