BMF RESTful API总结

导读

  • 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 the help firewall command, or refer to the firewall 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的请求是由prefixXPATH组成。原文如下:

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()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容