Network Analytics Engine 是 Python環境 並且透過 REST API去做資料收集分析行動的功能。
因此,想要入門NAE, 建議就有「Python基礎」與「REST API」等相關知識,這部分可以看網路上很多文章與影片,就能準備基本的背景知識。

根據官方文件,上圖可以表示NAE所有部分。如果要造出屬於自己環境的腳本,就需要學習每個環節。這邊會簡單帶過,用一篇文章的幅度就能學會如何創造自己的腳本。
NAE改變過去Switch的管理方式,過去Switch透過Syslog或是SNMP,Switch都是被動的,會出現中央集中的log server或是snmp server去管理。
NAE透過仔細的API,腳本,行動,我們可以做到更靈活的狀態探知,並且使Switch變得主動。時間序資料庫也能保存紀錄並方便做成圖表。讓CX Switch可以不只是會因為重啟而消失的Current Data。
NAE可以使用外部REST API去觸發其他的工作流Webhook或是服務平臺的API服務,這能與現今發展趨勢吻合,也意味著你可以讓CX Switch在某些事件發生時,以telegram bot或是email等去通知。
本文,將會以「若介面1/1/1變成Down時,使用Telegram傳送訊息告知。」為目標。
瞭解NAE組成
https://arubanetworking.hpe.com/techdocs/AOS-CX/10.13/HTML/nae/Content/Chp_Scrpt/par-scr.htm
NAE是個由:Header、Import statements、Manifest、Parameter definitions、Agent class constructor組成。
如果有寫過Python,Header與Import statements就不用多提。NAE能import的python庫,詳細能用什麼可以點連結。
Manifest:說明此Script相關資訊以及適用版本型號
Parameter definitions: 可以讓使用者調整的參數,若未調整,在此定義初始值。使用者可以在NAE-Agent啟動指定Script時,帶入參數「名稱:值(base64)」。
Agent class constructor:監控(Moniter)、規則(Rule)、條件(Condition)、行動(Action)。
NAE-Lite是個更簡易的NAE部署,透過CLI,設定Agent class constructor四要件,就可以造出。不過本文目標所用的功能更高遠,就不提此功能。
Switch型號與NAE Script與Agent數限制

隨著型號越高,NAE能使用的數量上限也會增加,詳情可以參考上表。
NAE 各部分說明
https://arubanetworking.hpe.com/techdocs/AOS-CX/10.13/HTML/nae/Content/Chp_Scrpt/scr-exa.htm
「若介面1/1/1變成Down時,使用Telegram傳送訊息告知。」這目標。
NAE Agent四要件就是:
監控(Moniter):透過REST API去取得特定介面1/1/1的link_status。
規則(Rule):方便閱讀的條件說明「interface 1/1/1 down」。
條件(Condition):一個判斷式,這邊為link_status是否等於down。
行動(Action):傳入參數event,並執行類別函式,函式功能則是用Requests去使用Telegram Bot Notify。
Manifest隨意打打。ParameterDefinitions甚至可以不用。Import statements只需要導入requests。
監控(Moniter)
Monitor為一個類別,裡面需要指令REST API URL,後面則看需求。
# 類別
Monitor(url, <params>)
# 部分程式碼
url = "/rest/v10.13/system/interfaces/1%2F1%2F1?attributes=link_state"
self.specific_interface_status = Monitor(url, 'specific_interface status')
如果url內有特殊字符,後面參數就能替換特殊字符。要把特殊字符換上有很多方法,這邊以直接指定1/1/1,不做替換。
如何取得特定資訊的REST API URL?
透過Web UI連入CX Switch,右上方齒輪icon,點開後可以看到API,點擊進入就能進入CX Switch REST API的測試頁面。
測試頁面功能請務必先執行Login功能!!
這樣測試頁面才會帶有Token,其他REST API功能才能正常使用!


調用目的API之前,記得先使用Login去登入。

然後找到目標API,interface/1/1/1,執行,就能順利得到回傳(code:200)。

到此,已經找出取的特定介面1/1/1的Requests URL。
https://172.26.1.104/rest/v10.13/system/interfaces/1%2F1%2F1?attributes=link_state
去掉IP等前綴,只保留相對路徑 =>
/rest/v10.13/system/interfaces/1%2F1%2F1?attributes=link_state

規則(Rule)
說明此規則與條件,如果事件被觸發,可以在NAE上Alert看到Rule的說明。
self.r1 = Rule('Status - up -> down')

條件(Condition)
依附在Rule下,Condition為一個判斷式,第一個參數為True就會出發。這邊為link_status是否等於down。判斷式的參數可以為Moniter物件。
self.specific_interface_status = Monitor(url, 'specific_interface status')
#
self.r1.condition('{} == "down"', [self.specific_interface_status])
行動(Action)
當Rule的Condition被滿足(True),就會觸發一個行動,觸發時會帶入Event,因此記得函式要保留此參數。
self.r1.action(self.action_interface_status_anomaly)
# called function
def action_interface_status_anomaly(self, event):
self.telegram_notify("interface 1/1/1 down")
self.set_alert_level(AlertLevel.CRITICAL)
self.logger.info(f"================ {self.params['specific_interface']} down ================")
telegram_notify 參考
telegram_notify要能順利通知,要有bot_token與char_id,bot_token可以參考之前將HomeAssistant的LineNotify改為Telegram Bot – JN的電腦網路日常去取得。
def telegram_notify(self, message):
import requests
url = f'https://api.telegram.org/bot{self.telegram_api_key}/sendMessage'
payload = {
'chat_id': self.telegram_chat_id,
'text': message
}
requests.post(url, data=payload, timeout=10)
完整NAE Script
筆者在過程中參考很多ASE的範本,也消化官方文件,最後寫成一份可用的。
# jnnetlab.com
# JN
Manifest = {
'Name': 'interface_monitor_and_notify_telegram',
'Description': 'Monitor specific interface. if it shutdowns, notify manager by telegram',
'Version': '1.0',
'Author': 'JN'
}
ParameterDefinitions = {
'specific_interface': {
'Name': 'specific_interface',
'Description': 'specific_interface',
'Type': 'string',
'Required': True,
'Default': '1/1/1'
},
'telegram_api_key': {
'Name': 'telegram_api_key',
'Description': 'telegram_api_key',
'Type': 'string',
'Required': True,
'Default': ''
},
'telegram_chat_id': {
'Name': 'telegram_chat_id',
'Description': 'telegram_chat_id',
'Type': 'string',
'Required': True,
'Default': ''
},
}
class Agent(NAE):
def __init__(self):
url = "/rest/v10.13/system/interfaces/1%2F1%2F1?attributes=link_state"
self.specific_interface_status = Monitor(url, 'specific_interface status')
self.r1 = Rule('Status - up -> down')
self.r1.condition('{} == "down"', [self.specific_interface_status])
self.r1.action(self.action_interface_status_anomaly)
self.r1.clear_condition('{} == "up"', [self.specific_interface_status])
self.r1.clear_action(self.return_to_normal)
self.telegram_api_key = self.params['telegram_api_key']
self.telegram_chat_id = self.params['telegram_chat_id']
def action_interface_status_anomaly(self, event):
self.telegram_notify("interface 1/1/1 down")
self.set_alert_level(AlertLevel.CRITICAL)
self.logger.info(f"================ {self.params['specific_interface']} down ================")
def return_to_normal(self, event):
self.remove_alert_level()
self.logger.info(f"================ {self.params['specific_interface']} up ================")
def telegram_notify(self, message):
import requests
url = f'https://api.telegram.org/bot{self.telegram_api_key}/sendMessage'
payload = {
'chat_id': self.telegram_chat_id,
'text': message
}
requests.post(url, data=payload, timeout=10)
成果
故意將1/1/1的設備重啟,觸發interface 1/1/1 down。

Telegram收到通知

Plaintext轉換base64
線上有很多工具。要用CLI導入python,就需要先把文本以base64編碼,這時就能使用以上工具網站。如果要帶入參數,就需要把參數值也轉成base64。
如果有個參數為interface,值想要帶入1/1/1,這時需要先把1/1/1以base64編碼,參數與值中間使用「:」,值以base64編碼輸入。
interface:1/1/1
=>
interface:MS8xLzE=
CLI部署NAE Script與NAE Agent
# python的部分要用base64編碼
nae-script jn1234 false IyBqbm5ldGxhYi5jb20KIyBKTgoKTWFuaWZlc3QgPSB7CiAgICAnTmFtZSc6ICdpbnRlcmZhY2VfbW9uaXRvcl9hbmRfbm90aWZ5X3RlbGVncmFtJywKICAgICdEZXNjcmlwdGlvbic6ICdNb25pdG9yIHNwZWNpZmljIGludGVyZmFjZS4gaWYgaXQgc2h1dGRvd25zLCBub3RpZnkgbWFuYWdlciBieSB0ZWxlZ3JhbScsCiAgICAnVmVyc2lvbic6ICcyLjAnLAogICAgJ0F1dGhvcic6ICdKTicKfQoKUGFyYW1ldGVyRGVmaW5pdGlvbnMgPSB7CiAgICAnc3BlY2lmaWNfaW50ZXJmYWNlJzogewogICAgICAgICdOYW1lJzogJ3NwZWNpZmljX2ludGVyZmFjZScsCiAgICAgICAgJ0Rlc2NyaXB0aW9uJzogJ3NwZWNpZmljX2ludGVyZmFjZScsCiAgICAgICAgJ1R5cGUnOiAnc3RyaW5nJywKICAgICAgICAnUmVxdWlyZWQnOiBUcnVlLAogICAgICAgICdEZWZhdWx0JzogJzEvMS8xJwogICAgfSwKICAgICd0ZWxlZ3JhbV9hcGlfa2V5JzogewogICAgICAgICdOYW1lJzogJ3RlbGVncmFtX2FwaV9rZXknLAogICAgICAgICdEZXNjcmlwdGlvbic6ICd0ZWxlZ3JhbV9hcGlfa2V5JywKICAgICAgICAnVHlwZSc6ICdzdHJpbmcnLAogICAgICAgICdSZXF1aXJlZCc6IFRydWUsCiAgICAgICAgJ0RlZmF1bHQnOiAnJwogICAgfSwgICAgCiAgICAndGVsZWdyYW1fY2hhdF9pZCc6IHsKICAgICAgICAnTmFtZSc6ICd0ZWxlZ3JhbV9jaGF0X2lkJywKICAgICAgICAnRGVzY3JpcHRpb24nOiAndGVsZWdyYW1fY2hhdF9pZCcsCiAgICAgICAgJ1R5cGUnOiAnc3RyaW5nJywKICAgICAgICAnUmVxdWlyZWQnOiBUcnVlLAogICAgICAgICdEZWZhdWx0JzogJycKICAgIH0sICAgICAgCiAgICB9CgpjbGFzcyBBZ2VudChOQUUpOgogICAgZGVmIF9faW5pdF9fKHNlbGYpOgogICAgICAgIHVybCA9ICIvcmVzdC92MTAuMTMvc3lzdGVtL2ludGVyZmFjZXMvMSUyRjElMkYxP2F0dHJpYnV0ZXM9bGlua19zdGF0ZSIKICAgICAgICBzZWxmLnNwZWNpZmljX2ludGVyZmFjZV9zdGF0dXMgPSBNb25pdG9yKHVybCwgJ3NwZWNpZmljX2ludGVyZmFjZSBzdGF0dXMnKQogICAgICAgIHNlbGYucjEgPSBSdWxlKCdTdGF0dXMgLSB1cCAtPiBkb3duJykKICAgICAgICBzZWxmLnIxLmNvbmRpdGlvbigne30gPT0gImRvd24iJywgIFtzZWxmLnNwZWNpZmljX2ludGVyZmFjZV9zdGF0dXNdKQogICAgICAgIHNlbGYucjEuYWN0aW9uKHNlbGYuYWN0aW9uX2ludGVyZmFjZV9zdGF0dXNfYW5vbWFseSkKICAgICAgICBzZWxmLnIxLmNsZWFyX2NvbmRpdGlvbigne30gPT0gInVwIicsIFtzZWxmLnNwZWNpZmljX2ludGVyZmFjZV9zdGF0dXNdKQogICAgICAgIHNlbGYucjEuY2xlYXJfYWN0aW9uKHNlbGYucmV0dXJuX3RvX25vcm1hbCkKICAgICAgICBzZWxmLnRlbGVncmFtX2FwaV9rZXkgPSBzZWxmLnBhcmFtc1sndGVsZWdyYW1fYXBpX2tleSddCiAgICAgICAgc2VsZi50ZWxlZ3JhbV9jaGF0X2lkID0gc2VsZi5wYXJhbXNbJ3RlbGVncmFtX2NoYXRfaWQnXQoKICAgIGRlZiBhY3Rpb25faW50ZXJmYWNlX3N0YXR1c19hbm9tYWx5KHNlbGYsIGV2ZW50KToKICAgICAgICBzZWxmLnRlbGVncmFtX25vdGlmeSgiaW50ZXJmYWNlIDEvMS8xIGRvd24iKQogICAgICAgIHNlbGYuc2V0X2FsZXJ0X2xldmVsKEFsZXJ0TGV2ZWwuQ1JJVElDQUwpCiAgICAgICAgc2VsZi5sb2dnZXIuaW5mbyhmIj09PT09PT09PT09PT09PT0ge3NlbGYucGFyYW1zWydzcGVjaWZpY19pbnRlcmZhY2UnXX0gZG93biA9PT09PT09PT09PT09PT09IikKCiAgICBkZWYgcmV0dXJuX3RvX25vcm1hbChzZWxmLCBldmVudCk6CiAgICAgICAgc2VsZi5yZW1vdmVfYWxlcnRfbGV2ZWwoKQogICAgICAgIHNlbGYubG9nZ2VyLmluZm8oZiI9PT09PT09PT09PT09PT09IHtzZWxmLnBhcmFtc1snc3BlY2lmaWNfaW50ZXJmYWNlJ119IHVwID09PT09PT09PT09PT09PT0iKQoKICAgIGRlZiB0ZWxlZ3JhbV9ub3RpZnkoc2VsZiwgbWVzc2FnZSk6CiAgICAgICAgaW1wb3J0IHJlcXVlc3RzCiAgICAgICAgdXJsID0gZidodHRwczovL2FwaS50ZWxlZ3JhbS5vcmcvYm90e3NlbGYudGVsZWdyYW1fYXBpX2tleX0vc2VuZE1lc3NhZ2UnCiAgICAgICAgcGF5bG9hZCA9IHsKICAgICAgICAgICAgJ2NoYXRfaWQnOiBzZWxmLnRlbGVncmFtX2NoYXRfaWQsCiAgICAgICAgICAgICd0ZXh0JzogbWVzc2FnZQogICAgICAgIH0gICAgIAogICAgICAgIHJlcXVlc3RzLnBvc3QodXJsLCBkYXRhPXBheWxvYWQsIHRpbWVvdXQ9MTAp
#屬性值對,值的部分要用base64編碼
nae-agent jn1234 jn1234 false specific_interface:MS8xLzE= telegram_api_key:<your telegram_api_key encoded base64> telegram_chat_id:<your telegram_chat_id encoded base64>
[…] Aruba CX Switch Network Analytics Engine (NAE) 入門 – JN的電腦網路日常 […]