Brocade BNA API

Brocade Network Advisor (BNA) has a REST API for accessing Fibre Channel-related data. The documentation includes a sample Python script showing how to connect to the API to retrieve Fabric info. The script given only works with Python 3.x. It’s also a pain to copy out of the documentation as you end up with a few extra characters in there. Here’s a version that will work with Python 2.7. I’ve also made a few other modifications - in this one, you can set the BNA IP, Username & Password at the top of the script.  I’ve also made it PEP8-compliant.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/env python

import httplib
import json
import sys

BNAServer = "10.200.5.181"
BNAUsername = "Administrator"
BNAPassword = "password"

# Create HTTPConnection object and connect to the server.
connection = httplib.HTTPConnection(BNAServer)

###########################
# Log in to Network Advisor
###########################

# Send login request
connection.request(
    'POST',
    '/rest/login',
    headers={
        "WSUsername": BNAUsername,
        "WSPassword": BNAPassword,
        "Accept": "application/vnd.brocade.networkadvisor+json;version=v1"}
    )

print()
print("Sending login request to Network Advisor...")

# Get the response
response = connection.getresponse()
# Display the response status print()
print ("Status= ", response.status)
# If successful (status = 200), display the returned session token
if response.status == 200:
    WStoken = response.getheader('WStoken')
    print()
    print("Login successful!")
    print("WStoken: ", WStoken)
else:
    print()
    print (response.status, response.reason)

connection.close()

###########################
# Retrieve fabrics
###########################

# Send GET request
connection.connect()
connection.request(
    'GET',
    '/rest/resourcegroups/All/fcfabrics',
    headers={
        "WStoken": WStoken,
        "Accept": "application/vnd.brocade.networkadvisor+json;version=v1"}
    )

print()
print("--------------------------------------------------------------------")
print("Getting list of all fabrics...")

# Get the response
response = connection.getresponse()

# Display the response status
print()
print ("Status= ", response.status)

# If successful (status = 200), display the returned list in JSON format
if response.status == 200:
    print()
    print("List of fabrics:")
    json_response_bytes = response.read()
    json_response_string = json_response_bytes.decode('utf-8')
    list_of_fabrics_dict = json.loads(json_response_string)
    print(json.dumps(list_of_fabrics_dict, indent=4))
    print("Number of FC fabrics: ", len(list_of_fabrics_dict["fcFabrics"]))
else:
    print()
    print (response.status, response.reason)
    sys.exit()

connection.close()

##############################
# Retrieve details of a fabric
##############################

# Get the key of the first fabric in the list
fabric_key = list_of_fabrics_dict["fcFabrics"][0]["key"]

# Send GET requrest
connection.connect()
connection.request(
    'GET',
    '/rest/resourcegroups/All/fcfabrics/'+fabric_key,
    headers={
        "WStoken": WStoken,
        "Accept": "application/vnd.brocade.networkadvisor+json;version=v1"}
    )

print()
print("--------------------------------------------------------------------")
print("Get fabric "+fabric_key+" details...")

# Get the response
response = connection.getresponse()

# Display the response status
print()
print ("Status= ", response.status)

# If successful (status = 200), display the returned list in JSON format
if response.status == 200:
    print()
    print("Fabric details:")
    json_response_bytes = response.read()
    json_response_string = json_response_bytes.decode('utf-8')
    fabric_details_dict = json.loads(json_response_string)
    print(json.dumps(fabric_details_dict, indent=4))
else:
    print()
    print (response.status, response.reason)
    sys.exit()

connection.close()

######################################################
# Retrieve list of switches in the context of a fabric
######################################################

# Send GET requrest
connection.connect()
connection.request(
    'GET',
    '/rest/resourcegroups/All/fcfabrics/'+fabric_key+'/fcswitches',
    headers={
        "WStoken": WStoken,
        "Accept": "application/vnd.brocade.networkadvisor+json;version=v1"}
    )

print()
print("--------------------------------------------------------------------")
print("Get the list of switches under fabric "+fabric_key+" ...")

# Get the response
response = connection.getresponse()

# Display the response status
print()
print ("Status= ", response.status)

# If successful (status = 200), display the returned list in JSON format
if response.status == 200:
    print()
    print("List of switches:")
    json_response_bytes = response.read()
    json_response_string = json_response_bytes.decode('utf-8')
    list_of_fabric_switches_dict = json.loads(json_response_string)
    print(json.dumps(list_of_fabric_switches_dict, indent=4))
else:
    print()
    print (response.status, response.reason)
    sys.exit()

connection.close()

Save that, edit the server IP & username/password, then run it. You should get output that looks something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
bna-api lhill$ ./na_client.py
()
Sending login request to Network Advisor...
('Status= ', 200)
()
Login successful!
('WStoken: ', '3CSkxp2i4HPtAiQFOLY/ha6mF7w=')
()
--------------------------------------------------------------------
Getting list of all fabrics...
()
('Status= ', 200)
()
List of fabrics:
{
    "fcFabrics": [
        {
            "fabricName": "",
            "name": "Fabric B",
            "seedSwitchWwn": "10:00:00:05:33:A3:DF:90",
            "description": null,
            "principalSwitchWwn": "10:00:00:05:33:A3:DF:90",
            "virtualFabricId": 128,
            "contact": null,
            "location": null,
            "key": "10:00:00:05:33:A3:DF:90",
            "seedSwitchIpAddress": "10.200.10.100",
            "adEnvironment": false,
            "secure": false
        },
        {
            "fabricName": "",
            "name": "Fabric A",
            "seedSwitchWwn": "10:00:00:05:1E:92:D8:00",
            "description": null,
            "principalSwitchWwn": "10:00:00:05:33:8A:7C:6A",
            "virtualFabricId": -1,
            "contact": null,
            "location": null,
            "key": "10:00:00:05:33:8A:7C:6A",
            "seedSwitchIpAddress": "10.200.7.110",
            "adEnvironment": false,
            "secure": false
        }
    ],
    "totalResults": null,
    "startIndex": null,
    "itemsPerPage": null
}
('Number of FC fabrics: ', 2)
()
--------------------------------------------------------------------
Get fabric 10:00:00:05:33:A3:DF:90 details...
()
('Status= ', 200)
()
Fabric details:
{
    "fcFabrics": [
        {
            "fabricName": "",
            "name": "Fabric B",
            "seedSwitchWwn": "10:00:00:05:33:A3:DF:90",
            "description": null,
            "principalSwitchWwn": "10:00:00:05:33:A3:DF:90",
            "virtualFabricId": 128,
            "contact": null,
            "location": null,
            "key": "10:00:00:05:33:A3:DF:90",
            "seedSwitchIpAddress": "10.200.10.100",
            "adEnvironment": false,
            "secure": false
        }
    ],
    "totalResults": null,
    "startIndex": null,
    "itemsPerPage": null
}
()
--------------------------------------------------------------------
Get the list of switches under fabric 10:00:00:05:33:A3:DF:90 ...
()
('Status= ', 200)
()
List of switches:
{
    "totalResults": null,
    "startIndex": null,
    "fcSwitches": [
        {
            "baseSwitch": false,
            "domainId": 160,
            "adCapable": false,
            "name": "fcr_fd_160",
            "portBasedRoutingPresent": false,
            "defaultLogicalSwitch": false,
            "inOrderDeliveryCapable": false,
            "dynamicLoadSharingCapable": false,
            "state": "UNKNOWN",
            "statusReason": null,
            "autoSnmpEnabled": true,
            "virtualFabricId": -1,
            "operationalStatus": "HEALTHY",
            "role": "SUBORDINATE",
            "fmsMode": false,
            "key": "50:00:51:E9:2D:80:0E:0A",
            "fcsRole": "None",
            "lfEnabled": false,
            "wwn": "50:00:51:E9:2D:80:0E:0A",
            "type": 40,
            "persistentDidEnabled": false
        },
        {
            "baseSwitch": false,
            "domainId": 2,
            "adCapable": true,
            "name": "SW6510-B",
            "portBasedRoutingPresent": false,
            "defaultLogicalSwitch": true,
            "inOrderDeliveryCapable": false,
            "dynamicLoadSharingCapable": true,
            "state": "ONLINE",
            "statusReason": "Switch Status is HEALTHY. Contributors:",
            "autoSnmpEnabled": true,
            "virtualFabricId": 128,
            "operationalStatus": "HEALTHY",
            "role": "PRINCIPAL",
            "fmsMode": false,
            "key": "10:00:00:05:33:A3:DF:90",
            "fcsRole": "None",
            "lfEnabled": false,
            "wwn": "10:00:00:05:33:A3:DF:90",
            "type": 109,
            "persistentDidEnabled": false
        },
        {
            "baseSwitch": false,
            "domainId": 1,
            "adCapable": true,
            "name": "DCX2",
            "portBasedRoutingPresent": false,
            "defaultLogicalSwitch": true,
            "inOrderDeliveryCapable": false,
            "dynamicLoadSharingCapable": true,
            "state": "ONLINE",
            "statusReason": "Switch Status is HEALTHY. Contributors:",
            "autoSnmpEnabled": true,
            "virtualFabricId": -1,
            "operationalStatus": "HEALTHY",
            "role": "SUBORDINATE",
            "fmsMode": false,
            "key": "10:00:00:05:1E:75:4A:00",
            "fcsRole": "None",
            "lfEnabled": false,
            "wwn": "10:00:00:05:1E:75:4A:00",
            "type": 77,
            "persistentDidEnabled": false
        }
    ],
    "itemsPerPage": null
}

Hope this helps someone trying to get started with the API.