导读
- BMF RESTful API 文档勘误
- interface role 的增删查
- lag 的增删查
- service node 的增删查
- policy 的增删查
- Python版本的REST client
BMF RESTful API 文档勘误
在《BMF-6.0.0-REST-API-Guide-2017.03.07》文档的Chapter 1 page16给出了介绍,如何用curl或者Python实现REST请求。因为文档有错误,所以只纠正这些错误的地方。
注《BMF-6.0.1-REST-API-Guide-2017.04.19》文档已经修正了这些错误
1. BMF Controller需要开启REST端口
文档上是这么写的:
Note: By default, port 8082 is not enabled on the controller firewall. To enable this port, enter the
firewall allow port 8082
command from the BMF controller config mode. For details about limiting access to specific source or destination addresses, enter thehelp firewall
command, or refer to thefirewall
command section in the ...
这里面有两个错误:
- 8082端口就不是REST端口,而是8443
- 根本没有
firewall
这个命令
解决办法:
在BMF Controller进行如下操作
BMF6> enable
BMF6# config
BMF6(config)# controller
BMF6(config-controller)# access-control
BMF6(config-controller-access)# access-list api
BMF6(config-controller-access-list)# <ACL ID,自己指定> permit from <IP>
2. REST auth URL有错误
开启了REST端口,还需要修改auth URL。
文档里面的是:http://${CONTROLLER_IP}:8082/auth/login
实际应该是:https://${CONTROLLER_IP}:8443/api/v1/auth/login
把上面两个问题解决后再看文档可知,在发送REST请求之前,先要登陆拿到sesson_cookie,然后再发送请求。这个过程可以通过curl
来完成(具体见文档),也可以用Python来完成。我很懒,懒得每次都敲一长串的curl
命令。所以基于Sample code做了一些修改,用来做REST client。源码见最后。
interface role 的增删查
这里主要列一下创建、查看以及修改interface role设计到的REST URL
创建 interface role
- uri
PUT https://${CONTROLLER_IP}:8443/api/v1/data/controller/core/switch-config/interface
- json
[
{
"analytics" : true,
"bigtap-name" : "Filter",
"breakout" : false,
"name" : "ethernet1",
"optics-always-enabled" : false,
"role" : "filter",
"shutdown" : false
},
{
"analytics" : true,
"bigtap-name" : "Delivery",
"breakout" : false,
"name" : "ethernet2",
"optics-always-enabled" : false,
"role" : "delivery",
"shutdown" : false
},
{
"analytics" : true,
"bigtap-name" : "Service-ingress",
"breakout" : false,
"name" : "ethernet3",
"optics-always-enabled" : false,
"role" : "service",
"shutdown" : false
},
{
"analytics" : true,
"bigtap-name" : "Service-egress",
"breakout" : false,
"name" : "ethernet4",
"optics-always-enabled" : false,
"role" : "service",
"shutdown" : false
}
]
注 json的列表长度、每个元素的
"name"
和"bigtap-name"
都可以根据自己需要定义
- response
None
删除 interface role
- uri
DELETE https://${CONTROLLER_IP}:8443/api/v1/data/controller/core/switch-config/interface%5Bname%3D%22${INTERFACE_NAME}%22%5D
这个uri有必要多说一下,文档的Chapter 1 Page 14 BigDB REST API YANG Extensions小节提到,BMF使用REST API完成查询操作时使用了YANG模型,,REST API的请求是由prefix
和XPATH
组成。原文如下:
Note BigDB REST API uses YANG schema language to define resources, which are naturally mapped into an XML structure. BigDB REST API uses XPATH as a query language to query and manipulate resources. XPATH location path and predicates are encoded within URIs of REST API call. In other words, each rest URI contains an XPATH that selects a set of data nodes within the resources tree defined by the YANG schema. For sample XPATH queries, see the sample queries in the REST API section.
再来看上面的uri,它在创建interface role的uri后面拼接了[key=value]部分。我们知道,URL中是不允许出现类似空格、等号、双引号等字符的,因此这个uri需要经过转码。编码之后便成了这个样子:%5Bname%3D%22${INTERFACE_NAME}%22%5D
(其中,双引号必不可少)。
- responese
None
查询 interface role
- uri
# 查询所有的interface role
GET https://${CONTROLLER_IP}:8443/api/v1/data/controller/core/switch-config/interface
# 根据interface name查询
GET https://${CONTROLLER_IP}:8443/api/v1/data/controller/core/switch-config/interface%5Bname%3D%22${INTERFACE_NAME}%22%5D
- response
创建 interface role PUT的json
lag 的增删查
创建 lag interface
- uri
PUT https://${CONTROLLER_IP}:8443/api/v1/data/controller/core/switch-config/lag-interface%5Bname%3D%22${LAG_NAME}%22%5D
- json
{
"hash-type" : "autoconfig",
"member" : [ {
"name" : "ethernet23"
}, {
"name" : "ethernet24"
} ],
"name" : "LAG-1"
}
- response
None
删除 lag interface
- uri
DELETE https://${CONTROLLER_IP}:8443/api/v1/data/controller/core/switch-config/lag-interface%5Bname%3D%22${LAG_NAME}%22%5D
- response
None
查看 lag interface
- uri
# 查看所有的lag interface
GET https://${CONTROLLER_IP}:8443/api/v1/data/controller/core/switch-config/lag-interface
# 根据lag interface name查询
https://${CONTROLLER_IP}:8443/api/v1/data/controller/core/switch-config/lag-interface%5Bname%3D%22${LAG_NAME}%22%5D
- response
创建 lag interface PUT的json
service node 的增删查
创建 service node
- uri
POST https://${CONTROLLER_IP}:8443/api/v1/data/controller/applications/bigtap/service
- json
[
{
"max-from-service-bandwidth-bps" : 1000000000,
"max-to-service-bandwidth-bps" : 1000000000,
"name" : "WAF",
"post-group" : [ {
"bigtap-name" : "Service-egress"
} ],
"pre-group" : [ {
"bigtap-name" : "Service-ingress"
} ],
"total-from-service-bps" : 0,
"total-to-service-bps" : 0
},
{
"max-from-service-bandwidth-bps" : 1000000000,
"max-to-service-bandwidth-bps" : 1000000000,
"name" : "NF",
"post-group" : [ {
"bigtap-name" : "Service-egress"
} ],
"pre-group" : [ {
"bigtap-name" : "Service-ingress"
} ],
"total-from-service-bps" : 0,
"total-to-service-bps" : 0
}
]
json的列表长度、每个元素的
"name"
、"post-group"
和"pre-group"
根据自己需要定义
- response
None
删除 service node
- uri
DELETE https://${CONTROLLER_IP}:8443/api/v1/data/controller/applications/bigtap/service%5Bname%3D%22${SERVICE_NAME}%22%5D
- response
None
查看 service node
- uri
# 查看所有的service node
GET https://${CONTROLLER_IP}:8443/api/v1/data/controller/applications/bigtap/service
# 根据service node name查询
GET https://${CONTROLLER_IP}:8443/api/v1/data/controller/applications/bigtap/service%5Bname%3D%22${SERVICE_NAME}%22%5D
- response
创建 service node PUT的json
policy 的增删查
创建 policy
- uri
POST https://${CONTROLLER_IP}:8443/api/v1/data/controller/applications/bigtap/policy
- json
[
{
"action" : "forward",
"delivery-group" : [ {
"bigtap-name" : "Delivery"
} ],
"delivery-mode" : "custom",
"duration" : 0,
"expired-delivery-count" : false,
"expired-time" : false,
"filter-group" : [ {
"bigtap-name" : "Filter"
} ],
"filter-mode" : "custom",
"inactive" : false,
"name" : "SSH",
"policy-description" : "SSH policy",
"priority" : 100,
"rule" : [ {
"dst-ip" : "172.16.1.1",
"dst-ip-mask" : "255.255.255.0",
"dst-tp-port-max" : 23,
"dst-tp-port-min" : 22,
"ether-type" : 2048,
"ip-fragment" : true,
"ip-proto" : 6,
"sequence" : 1,
"src-ip" : "172.16.0.1",
"src-ip-mask" : "255.255.255.0",
"src-tp-port-max" : 50025,
"src-tp-port-min" : 50022,
"tcp-flags" : 63,
"tcp-flags-mask" : 63
} ],
"service" : [ {
"name" : "WAF",
"optional" : false,
"sequence" : 1
} ],
"start-time" : "2017-06-02T14:26:00+08:00"
}
]
json的列表长度、每个元素的
"name"
、"rule"
、"service"
等字段都可根据自己需要定义(有一些不必要的字段可以省略,如"start-time"
、"policy-description"
等)
- response
None
删除 policy
- uri
DELETE https://${CONTROLLER_IP}:8443/api/v1/data/controller/applications/bigtap/policy%5Bname%3D%22${POLICY_NAME}%22%5D
- response
None
查看 policy
- uri
# 查看全部policy
GET https://${CONTROLLER_IP}:8443/api/v1/data/controller/applications/bigtap/policy
# 根据policy name查询
GET https://${CONTROLLER_IP}:8443/api/v1/data/controller/applications/bigtap/policy%5Bname%3D%22${POLICY_NAME}%22%5D
- response
创建 policy PUT的json
Python版本的REST client
import sys
import urllib2
import json
import ssl
# 根据不同环境自行修改,但PORT是固定的
BIGTAP_CONTROLLER =
PORT = "8443"
USER =
PASSWORD =
def rest_request(url, obj=None, verb="GET", session=None):
headers = {"Content-type": "application/json"}
if session:
headers["Cookie"] = "session_cookie=%s" % session
request = urllib2.Request(url, obj, headers)
request.get_method = lambda: verb
# skip certificate check
context = ssl._create_unverified_context()
response = urllib2.urlopen(request, context=context)
return response.read()
def get_session_cookie():
url_login = "https://%s:%s/api/v1/auth/login" % (BIGTAP_CONTROLLER, PORT)
data = {"password": str(PASSWORD), "user": str(USER)}
output = rest_request(str(url_login), obj=json.dumps(data), verb="POST")
auth_obj = json.loads(output)
# print "Login complete %s" % auth_obj["session_cookie"]
return auth_obj["session_cookie"]
def delete_session(session_cookie=None):
url_delete_session = "https://%s:%s/api/v1/data/controller/core/aaa/session" % (BIGTAP_CONTROLLER, PORT)
rest_response = rest_request(url_delete_session, verb="DELETE", session=session_cookie)
print rest_response
def make_rest_call(rest_uri_path, session_cookie, method, data=None):
# check whether rest_uri_path need quote (DELETE verb)
pos = rest_uri_path.find('[')
if pos != -1:
rest_uri_path = rest_uri_path[:pos] + urllib2.quote(rest_uri_path[pos:])
url = "https://%s:%s/api/v1/data/controller/%s" % (BIGTAP_CONTROLLER, PORT, rest_uri_path)
print "=" * 50
print "Requesting URI:\n%s %s" % (method, url)
if not data:
rest_response = rest_request(url, verb=method, session=session_cookie)
else:
rest_response = rest_request(url, verb=method, obj=json.dumps(data), session=session_cookie)
print "=" * 50
print "Response:\n%s" % rest_response
def usage():
print """
python rest_client.py <rest_uri> <method> [json_file]
<rest_uri> RESTful API request url
<method> POST|GET|PUT|DELETE
NOTICE: If method=POST|PUT, you have to specify json data file
<json_file> json data file path
For example: python rest_client.py 'applications/bigtap/policy' GET
python rest_client.py 'applications/bigtap/policy' POST ssh_policy.json
python rest_client.py 'applications/bigtap/policy[name="SSH"]' DELETE
"""
def main():
if len(sys.argv) >= 3:
rest_uri_path = sys.argv[1]
method = sys.argv[2]
session_cookie = get_session_cookie()
if method == "POST" or method == "PUT":
if len(sys.argv) != 4:
print "ERROR usage! You have specify %s json data" % method
usage()
sys.exit(1)
json_data = json.loads(open(sys.argv[3],"r").read())
make_rest_call(rest_uri_path, session_cookie, method, json_data)
else:
make_rest_call(rest_uri_path, session_cookie, method)
delete_session(session_cookie)
else:
usage()
if __name__ == "__main__":
main()