入門介紹看此
Aruba CX Switch Network Analytics Engine (NAE) 入門 – JN的電腦網路日常
上回帶領瞭解與如何造出自己的NAE,本回會繼續深入,完成一項難以置信工程創舉,定期開關特定介面PoE,這個介面接著Aruba AP,因此能讓Aruba AP透過CX Switch NAE功能定時重啟!
本篇在Aruba AP接至特定介面並透過PoE供電為主,我們已知是什麼介面,所以針對該介面進行操作即可。
規劃
基礎:
每十分鐘觸發一次 > 檢查PoE Status() > 開啟 > 觸發指令關閉
每十分鐘觸發一次 > 檢查PoE Status > 關閉 > 觸發指令開啟
進階:
設定每週每月特定時間,計算下次觸發時間
每一分鐘觸發一次 > 檢查當前時間是否超過觸發時間 > 是 > 觸發指令關閉,並設定下次恢復為啟用
每一分鐘觸發一次 > 檢查下次恢復為啟用 > 是 > 觸發指令開啟,並設定下次恢復為關閉,計算與設定下次觸發時間。
本文只介紹基礎的設置。
回顧NAE Agent四個要件
「定期開關1/1/1介面PoE。」這目標。
定期為10min,若poe_status為disable,則enable。若poe_status為enable,則disable。
接著會繼續延伸,在每週四特定時間先Disable,再Enable,促使AP重啟。(選週四是因為筆者是在週四撰寫本文。
NAE Agent四要件就是:
監控(Moniter):透過REST API去取得特定介面1/1/1的poe_status。
規則(Rule):方便閱讀的條件說明「interface 1/1/1 poe_status」。
條件(Condition):一個判斷式,這邊定期10分鐘(every 600 seconds),。
行動(Action):傳入參數event,並執行類別函式,此函式則是依據狀態去下對應指令。
搭配上次的成果,如果有成功,我每20分鐘就能收到Telegram的通知,因為link_status down。
探索PoE_Status
一樣藉助CX Switch的WebUI,並使用其中的API。

記得先Login

找到能看到介面PoE狀態的API

介面「config」中有「admin_disable」。

只需要紀錄config.admin_disable,URL要改為以下
/rest/v10.13/system/interfaces/1%2F1%2F1/poe_interface?attributes=config.admin_disable
# .後面能接屬性,這樣能確切指出是config.admin_disable的值
知道目標狀態的URL在哪,本文不使用Monitor監控,而是會透過REST API取得狀態。
※筆者對於REST API最有信心,查不太各類別內建支援什麼method的相關說明文件,只好看官方NAE Scripts,嘗試self.get_rest_request_json(HTTP_ADDRESS + uri, retry=3)中,但無進展。
Action寫法
https://arubanetworking.hpe.com/techdocs/AOS-CX/10.13/HTML/nae/Content/Chp_Scrpt/act-cli-act.htm

#關閉1/1/1的PoE狀態
config
interface 1/1/1
no power-over-ethernet
exit
exit
#轉換成Python
ActionCLI("config\ninterface 1/1/1\nno power-over-ethernet\nexit\nexit")
# 打開poe版本
ActionCLI("config\ninterface 1/1/1\npower-over-ethernet\nexit\nexit")
# 轉換成Python 第二種寫法
ActionCLI(
f'config\n'
f'interface {self.params["specific_poe_interface"]}\n'
f'no power-over-ethernet\n'
f'exit\n'
f'exit'
)
Time Series Data Record
NAE是時間序列,使用every時,會去對齊交換器的時間,而不是從開始時間去計算。
例如:我使用every 10 minute,就會在00:00、00:10、00:20、00:30、00:40、00:50準時執行,而不是從agent開始時間點計算。
要比擬的話,linux系統的Crontab類似。
透過Rest API取得CX Switch Status
由於CX Switch支援外部Requests,本文是使用本身URL與API,技術上仍可以延伸至取得其他台CX Switch狀態與控制。
上次例子使用telegram API,這次是使用CX Switch API。
CX Switch API使用流程在先前也有提過,先login,再執行你的安排,最後logout。本文範例流程是登入,取得PoE Status,最後登出,然後回傳PoE Status。
ParameterDefinitions = {
'API_URL': {
'Name': 'POE_STATUS_URL',
'Description': 'POE_STATUS_URL',
'Type': 'string',
'Required': True,
'Default': 'https://172.26.1.104/rest/v10.13/'
},
'API_ACCOUNT': {
'Name': 'API_ACCOUNT',
'Description': 'API_ACCOUNT',
'Type': 'string',
'Required': True,
'Default': ''
},
'API_PASSWORD': {
'Name': 'API_PASSWORD',
'Description': 'API_PASSWORD',
'Type': 'string',
'Required': True,
'Default': ''
}
}
......
def getPoEStatus(self):
BASE_URL = self.params["API_URL"].value
USERNAME = self.params["API_ACCOUNT"].value
PASSWORD = self.params["API_PASSWORD"].value
session = requests.Session()
login_url = BASE_URL + 'login?'
resp = session.post(
login_url,
params={'username': USERNAME, 'password': PASSWORD},
verify=False,
timeout=5
)
resp.raise_for_status()
poe_url = BASE_URL + 'system/interfaces/' + self.int_encoded + '/poe_interface?attributes=config'
resp = session.get(poe_url, verify=False, timeout=5)
resp.raise_for_status()
payload = resp.json()
poe_status = True
admin_disable = payload.get('config', {}).get('admin_disable', False)
if admin_disable:
poe_status = False
self.logger.info("admin_disable = True ")
else:
self.logger.info("admin_disable = False ")
logout_url = BASE_URL + 'logout'
resp = session.post(logout_url, verify=False, timeout=5)
return poe_status
成果
本範例Monitor不是必要的,沒有Monitor也能正常運行。
透過Rule與Condition定期執行,定期透過REST API取得狀態,然後決定CX Switch要使用什麼指令。
# jnnetlab.com
# JN
from urllib.parse import quote
import requests
Manifest = {
'Name': 'jnpoe2',
'Description': 'interface_poe_disable_and_enable',
'Version': '1',
'Author': 'JN'
}
ParameterDefinitions = {
'poe_int': {
'Name': 'poe_int',
'Description': 'poe_int',
'Type': 'string',
'Required': True,
'Default': '1/1/1'
},
'API_URL': {
'Name': 'POE_STATUS_URL',
'Description': 'POE_STATUS_URL',
'Type': 'string',
'Required': True,
'Default': 'https://172.26.1.104/rest/v10.13/'
},
'API_ACCOUNT': {
'Name': 'API_ACCOUNT',
'Description': 'API_ACCOUNT',
'Type': 'string',
'Required': True,
'Default': ''
},
'API_PASSWORD': {
'Name': 'API_PASSWORD',
'Description': 'API_PASSWORD',
'Type': 'string',
'Required': True,
'Default': ''
}
}
class Agent(NAE):
def __init__(self):
self.int_encoded = quote(self.params["poe_int"].value, safe="")
self.r = Rule('Periodic Check')
self.r.condition("every 120 seconds")
self.r.action(self.timed_action)
def timed_action(self, event):
ActionSyslog("every 120 seconds")
if self.getPoEStatus():
ActionCLI(
f'config\n'
f'interface {self.params["poe_int"]}\n'
f'no power-over-ethernet\n'
f'exit\n'
f'exit'
)
self.set_alert_level(AlertLevel.CRITICAL)
else:
ActionCLI(
f'config\n'
f'interface {self.params["poe_int"]}\n'
f'power-over-ethernet\n'
f'exit\nexit'
)
self.remove_alert_level()
def getPoEStatus(self):
BASE_URL = self.params["API_URL"].value
USERNAME = self.params["API_ACCOUNT"].value
PASSWORD = self.params["API_PASSWORD"].value
session = requests.Session()
login_url = BASE_URL + 'login?'
resp = session.post(
login_url,
params={'username': USERNAME, 'password': PASSWORD},
verify=False,
timeout=5
)
resp.raise_for_status()
poe_url = BASE_URL + 'system/interfaces/' + self.int_encoded + '/poe_interface?attributes=config'
resp = session.get(poe_url, verify=False, timeout=5)
resp.raise_for_status()
payload = resp.json()
poe_status = True
admin_disable = payload.get('config', {}).get('admin_disable', False)
if admin_disable:
poe_status = False
self.logger.info("admin_disable = True ")
else:
self.logger.info("admin_disable = False ")
logout_url = BASE_URL + 'logout'
resp = session.post(logout_url, verify=False, timeout=5)
return poe_status
搭配我上一回的NAE,可以看出週期性的UP與DOWN,也間接證明腳本正常運作。
※為了讓成果可以快速呈現,我調短週期。

每次通電時,都會先短暫UP然後DOWN,再次UP才會穩定。
