簡介
本文說明如何使用Python使用Cisco Catalyst Center上提供的不同API。
必要條件
需求
以下方面的基礎知識:
- Cisco Catalyst Center
- API
- Python
採用元件
- Cisco Catalyst中心2.3.5.x
- Python 3.x.x
本文中的資訊是根據特定實驗室環境內的裝置所建立。文中使用到的所有裝置皆從已清除(預設)的組態來啟動。如果您的網路運作中,請確保您瞭解任何指令可能造成的影響。
附註:思科技術援助中心(TAC)不為Python提供技術支援。如果您遇到Python問題,請聯絡Python支援部門尋求技術支援。
設定
概觀
Cisco Catalyst Center提供了許多API。要驗證可以使用哪些API,請在Catalyst Center上導航到Platform > Developer Toolkit > APIs。
Catalyst Center API頁
每個API都有其自己的用途,具體取決於需要在Catalyst Center上執行的資訊或操作。要使API正常工作,必須首先使用令牌向Catalyst Center正確驗證並獲得成功的API響應。令牌相應地標識REST呼叫方的許可權。
確定構成API的元件也很重要,這些元件如下所示:
- URL:提供對特定資源的訪問的端點。
- 方法:所有API都必須包含方法。它定義客戶端要對特定端點執行的操作/操作。範例:POST、GET、PUT、DELETE。
- 標題:以鍵值對格式提供有關請求的其他資訊。例如,授權報頭提供了一種使用憑證的身份驗證方法。
- 引數:使用API向端點提供特定指令的變數。引數可以是終端的URL的一部分。
- 負載:在API呼叫期間需要傳送到終結點的資料。
附註:有關Catalyst Center上可用的每個API的詳細資訊,請參閱API參考指南。
模組
使用的Python模組:
- 請求:此模組允許將HTTP/1.1請求傳送到特定URL。有關該模組的更多資訊,請參閱《請求模組指南》。
- base64:提供編碼和解碼功能。有關模組的詳細資訊,請參閱base64模組指南。
- json:此模塊允許從API響應獲取特定資料。有關此模組的更多資訊,請參閱json模組指南。
生成令牌
必須使用Authentication API來生成新令牌。
身份驗證API:
POST https:///dna/system/api/v1/auth/token
必須說明生成的令牌有效期為1小時。1小時後,必須使用上面提到的API生成新的令牌。
在新的Python檔案中,匯入模塊(請求、base64和json),然後建立四個變數:
import requests
import base64
import json
user = 'user' # User to login to Catalyst Center
password = 'password' # Password to login to Catalyst Center
token = '' # Variable to store the token string
authorizationBase64 = '' # Variable that stores Base64 encoded string of "username:password"
驗證API支援標頭中作為授權權杖的基本驗證。基本身份驗證是一種可用於對終端進行身份驗證的方法,提供用冒號(username:password)分隔的使用者名稱和密碼。 兩個值都採用base64編碼,終端將解碼登入憑證並檢查使用者是否可以訪問。
要為我們的使用者名稱和密碼建立包含Base64的字串,請使用base64模組。為此,使用b64encode函式。
byte_string = (f'{user}:{password}').encode("ascii")
authorizationBase64 = base64.b64encode(byte_string).decode()
從上面的代碼中,使用「encode("ascii")」函式建立了byte_string變量。這是因為base64.b64encode函式需要類似位元組的對象。另請注意,user和password變數用於保留字串格式'user:password'。最後,使用使用者和密碼建立了一個base64編碼的位元組字串。使用'decode()'方法,將該值轉換為str對象。
要驗證它,可以列印authorizationBase64變數的值:
print(authorizationBase64)
輸出示例:
am9yZ2QhbDI6Sm9yZ2VhbDXxXxXx
注意:base64不是加密演算法。不能用於安全目的。Authentication API還支援將AES金鑰加密作為頭中的授權令牌,從而提供更高的安全性。
現在已使用使用者和密碼建立一個base64編碼的字串,以向Catalyst Center進行身份驗證,現在應該使用模組請求繼續執行API身份驗證API調用。另外,名為request的函式允許獲取包含請求文本的響應對象。
方法的語法:
requests.request(“method”, “url”, **kwargs)
**kwargs表示傳入請求的任何引數,例如cookie、使用者代理、負載、報頭等。
驗證API指定方法為POST,URL為"/dna/system/api/v1/auth/token",且基本驗證需要在Header中指定。
建立這些變數是為了將其用於request()函數。
url = https:///api/system/v1/auth/token
headers = {
‘content-type’: “application/json”,
‘Authorization’: ‘Basic ’ + authorizationBase64
}
對於headers變數,指定了兩個內容。第一個是content-type,它指定傳送到終結點的資源的媒體型別(這有助於終結點準確分析和處理資料)。 第二個是Authorization,在本例中,變數authorizationBase64(儲存我們的base64包含字串)作為引數傳送到Catalyst Center進行身份驗證。
現在,繼續使用request()函式執行API呼叫。下一個代碼顯示函式的語法:
response = requests.request(“POST”, url, headers=headers)
建立了response變數以儲存所做的API呼叫的資料。
要列印獲得的響應,請在響應變數中使用print函數以及text()方法。text()方法使用從Catalyst Center接收的響應生成str對象。
print(response.text)
輸出示例:
{“Token”:“eyJhbGci0iJSUzI1NiIsInR5JK09s1zVmNjk0NjhkNTFhNDJ1ZWeLCU291cmNlIjoiaW50ZXJuYWwiLCW2vMPUbU0JNlqxOXNe1jMzY1LTQ5MWEtODljNC0yZmE2YjVhM2
!--- Output is supressed
附註:如果Catalyst Center使用自簽名證書,則API請求可能會失敗,並出現下一個錯誤:
requests.exceptions.SSLError: HTTPSConnectionPool(host='X.X.X.X', port=443): Max retries exceeded with url: /api/system/v1/auth/token (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1000)')))
要解決此問題,需要將verify引數作為False新增到請求函式中。這會忽略從終結點(Catalyst Center)驗證SSL證書。
response = requests.request(“POST”, url, headers=headers, verify=False)
從從API authentication呼叫收到的響應中,請注意,該結構類似於Python中的字典,但它是一個str對象。
要驗證對象的型別,請使用type()函數。
print(type(response.text))
返回下一個輸出:
在實際中,只需要從從API接收的響應中提取令牌值,而不是整個字串,因為要使用其它Catalyst Center API,必須僅將令牌作為引數傳遞。
由於從API呼叫收到的響應具有類似於Python中的詞典的結構,但對象型別為str,因此需要使用json模組將所述的對象轉換為詞典。這會從從API接收的整個字串中提取令牌值。
為此,函式json.loads()將字串轉換為字典,以便稍後只提取令牌值並將其直接分配到令牌變數。
token = json.loads(response.text) # Converting the response.text string value into a dictionary (It is creating a JSON object).
token = (token["Token"]) # Extracting just the token value by specifying the key as a parameter.
要驗證token變數是否僅將令牌作為其值,請繼續列印它。
print(token)
輸出示例:
eyJhbGci0iJSUzI1NiIsInR5JK09s1zVmNjk0NjhkNTFhNDJ1ZWeLCU291cmNlIjoiaW50ZXJuYWwiLCW2vMPUbU0JNlqxOXNe1jMzY1LTQ5MWEtODljNC0yZmE2YjVhM2
!--- Output is supressed
提示:由於每個生成的令牌預設在1小時內到期,因此可以建立包含生成令牌的代碼的Python方法,並且可以在每次令牌到期時呼叫該方法,而無需通過呼叫建立的方法來運行整個程式。
測試API
現在令牌已成功分配給token變數,因此可以使用可用的Catalyst Center API。
在這種情況下,將測試Cisco DNA Center Nodes Configuration Summary API。
Cisco DNA中心節點配置摘要
GET https:///dna/intent/api/v1/nodes-config
此API提供有關Catalyst Center當前配置的詳細資訊,如配置的NTP伺服器、節點名稱、集群內鏈路、LACP模式等。
Cisco DNA Center Nodes Configuration Summary API指定,在此案例中,使用的方法是GET,URL是"/dna/intent/api/v1/nodes-config",而且,由於已提取令牌字串並將其分配給token變數,因此這次令牌作為API呼叫標頭中的變數傳遞為'X-Auth-Token':後跟令牌。
這將驗證所執行的每個API呼叫向Catalyst中心發出的請求。記住每個令牌持續1小時。1小時後,必須生成新的令牌才能繼續對Catalyst Center進行API呼叫。
繼續建立變數以測試API:
nodeInfo_url = "https:///dna/intent/api/v1/nodes-config"
nodeInfo_headers = {
'X-Auth-Token': token
}
nodeInfoResponse = requests.request("GET", nodeInfo_url, headers=nodeInfo_headers)
建立nodeInfo_url變數以儲存我們的API的URL。nodeInfo_headers變量儲存我們的API的標頭。在此案例中,將「X-Auth-Token:」和token變數作為引數傳遞到Catalyst Center,以成功驗證請求。最後,nodeInfoResponse變數儲存API的響應。
要驗證收到的響應,可以使用print()函式。
輸出示例:
{"response": {"nodes": [{"name": "Catalyst Center", "id": "ea5dbec1-fbb6-4339-9242-7694eb1cXxXx", "network": [{"slave": ["enp9s0"], "lacp_supported": true, "intra_cluster_link": false, "interface": "enterprise", "inet6": {}, "inet": {"routes": [{"netmask": "255.255.0.0"
!--- Output is supressed
附註:如果Catalyst Center中使用的是自簽名證書,API請求可能會失敗,並出現下一個錯誤:
requests.exceptions.SSLError: HTTPSConnectionPool(host='X.X.X.X', port=443): Max retries exceeded with url: /api/system/v1/auth/token (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1000)')))
要解決此問題,需要將verify引數新增為False到請求中。這會抑制來自終端(Catalyst Center)的SSL證書驗證。
nodeInfoResponse = requests.request("GET", nodeInfo_url, headers=nodeInfo_headers, verify=False)
從API收到的響應可能難以讀取。使用json()模組可以將響應列印為更易讀的字串。首先,必須使用json.loads()函式後跟json.dumps()函式將API響應載入到JSON對象:
jsonFormat = (json.loads(nodeInfoResponse.text)) # Creating a JSON object from the string received from the API response.
print(json.dumps(jsonFormat, indent=1)) # Printing the response in a more readable string using the dumps() function.
json.dumps:此函式返回JSON對象作為JSON格式字串中的引數。
縮排:此引數定義JSON格式字串的縮排級別。
輸出示例:
{
"response": {
"nodes": [
{
"name": "X.X.X.X",
"id": "ea5dbec1-fbb6-4339-9242-7694eb1xXxX",
"network": [
{
"slave": [
"enp9s0"
],
"lacp_supported": true,
"intra_cluster_link": false,
!--- Output is supressed
包含標頭引數的API
有些API需要在報頭中傳送一些引數才能按預期工作。在這種情況下,將測試Get Client Excentration Details API。
GET https:///dna/intent/api/v1/client-enrichment-details
要驗證API需要哪些標頭引數才能按預期工作,請導航到Platform > Developer Toolkit > APIs > Get Client Encapsulation Details,然後點選API的名稱。將開啟一個新視窗,並在Parameters選項下顯示API工作所需的標頭引數。

在這種情況下,根據說明,對於entity_type引數,值可以是network_user_id或mac_address,而entity_value引數必須包含已定義的實體型別的值。
要繼續執行該操作,需要定義兩個新變數:entity_type和entity_value,以及它們的相應值:
entity_type = 'mac_address' #This value could be either 'network_user_id' or 'mac_address'.
entity_value = 'e4:5f:02:ff:xx:xx' #Depending of the 'entity_type' used, need to add the corresponding value for 'entity_value'. In this case, 'mac_address' value was chosen for 'entity_type' parameter so, a MAC Address was assigned to the 'entity_value' parameter.
還會建立新的變數來執行API呼叫。API呼叫的URL儲存在userExposition_url變數中。標頭儲存在userExpositionHeaders變數中。接收的響應儲存在userDerivationResponse變數中。
userEnrichment_url = "https:///dna/intent/api/v1/user-enrichment-details"
userEnrichmentHeaders = {
'X-Auth-Token': token,
'entity_type': entity_type,
'entity_value': entity_value,
}
userEnrichmentResponse = requests.request("GET", userEnrichment_url, headers=userEnrichmentHeaders)
您可以看到,從userExpositionHeaders中,entity_type和entity_value變數作為API呼叫的頭引數傳遞了,同時傳遞了token變數。
要驗證收到的響應,請使用print()函式。
print(userEnrichmentResponse.text)
輸出示例:
[ {
"userDetails" : {
"id" : "E4:5F:02:FF:xx:xx",
"connectionStatus" : "CONNECTED",
"tracked" : "No",
"hostType" : "WIRELESS",
"userId" : null,
"duid" : "",
"identifier" : "jonberrypi-1",
"hostName" : "jonberrypi-1",
"hostOs" : null,
"hostVersion" : null,
"subType" : "RaspberryPi-Device",
"firmwareVersion" : null,
"deviceVendor" : null,
"deviceForm" : null,
"salesCode" : null,
"countryCode" : null,
"lastUpdated" : 1721225220000,
"healthScore" : [ {
"healthType" : "OVERALL",
"reason" : "",
"score" : 10
}, {
"healthType" : "ONBOARDED",
"reason" : "",
"score" : 4
!--- Output is suppressed
包含查詢引數的API
查詢引數可用於篩選API返回的特定結果數。這些引數將新增到API的URL中。
Get Device List API呼叫已測試。
GET https://10.88.244.133/dna/intent/api/v1/network-device
Get Device List API返回Catalyst Center中新增的所有裝置的清單。如果請求特定裝置的詳細資訊,查詢引數有助於過濾特定資訊。
要驗證哪些查詢引數可用於API,請導航到Platform > Developer Toolkit > APIs > Get Device List,然後點選API的名稱。將開啟一個新視窗,並在Parameters選項下顯示可用於API的查詢引數。

在本示例中,使用managementIpAddress和serialNumber查詢引數(考慮不必要使用API呼叫的所有查詢引數)。 繼續為兩個查詢引數建立並分配相應的值。
managementIpAddress = '10.82.143.250'
serialNumber = 'FDO25160X9L'
如上所述,查詢引數將使用「?」新增到API的URL中,特別是其末尾 後跟查詢引數。
在要使用多個查詢引數的情況下,會在它們之間放置一個「&」號,以形成所謂的查詢字串。
下一個示例顯示如何將查詢引數新增到儲存API呼叫的URL的deviceListUrl變數中。
deviceListUrl = "https:///dna/intent/api/v1/network-device?managementIpAddresss=" + managementIpAddress + "&serialNumber=" + serialNumber
請注意,先前建立的變數已附加到URL字串。換句話說,URL的整個字串如下所示:
deviceListUrl = "https:///dna/intent/api/v1/network-device?managementIpAddresss=10.82.143.250&serialNumber=FDO25160X9L"
繼續API呼叫,將建立deviceListHeaders變數以儲存API標頭以及作為引數傳遞的token變數,而deviceListResponse變數儲存API響應。
deviceListHeaders = {
'X-Auth-Token': token,
}
deviceListResponse = requests.request("GET", deviceListUrl, headers=deviceListHeaders)
要驗證收到的響應,可以使用print()函式。
print(deviceListResponse.text)
輸出示例:
{"response":[{"family":"Switches and Hubs","description":"Cisco IOS Software [Cupertino], Catalyst L3 Switch Software (CAT9K_IOSXE), Version 17.9.4a, RELEASE SOFTWARE (fc3) Technical Support: http://www.cisco.com/techsupport Copyright (c) 1986-2023 by Cisco Systems, Inc. Compiled Fri 20-Oct-23 10:44 by mcpre","lastUpdateTime":1721205664979,"deviceSupportLevel":"Supported","softwareType":"IOS-XE","softwareVersion":"17.9.4a","serialNumber":"FDO25160X9L","inventoryStatusDetail":"
提示:若要以更易讀的方式列印響應,可以使用「測試API」部分中介紹的json.loads()和json.dumps()函式。