OPS
適用階段 |
OPS API |
---|---|
訂閱階段 |
|
執行階段 |
|
訂閱階段和執行階段 |
|
參數 |
參數說明 |
取值 |
---|---|---|
tag |
用於標識條件。 |
字符串形式,不區分大小寫,長度范圍是1~12,由字母、數字和下划線組成,以字母開頭。tag不能為""、None、and、or以及andnot,不能包含\0。 |
pattern |
指定匹配命令的正則表達式。 |
字符串形式,取值范圍是1~128個字符,不能包含\0。 |
enter |
指定匹配正則表達式的時間。 |
布爾型,取值如下:
缺省值是False。 |
sync |
指定命令行觸發執行動作后,是否等待腳本執行結束。 |
布爾型,取值如下:
缺省值是True。 |
async_skip |
在sync取值為False時,指定是否跳過原有命令執行。 |
布爾型,取值如下:
缺省值是False。 |
sync_wait |
在sync取值為True時,指定命令行同步等待腳本執行的時間。 |
整數形式,取值范圍是1~2147483647,單位是秒。缺省值是30秒。 |
參數 |
參數說明 |
取值 |
---|---|---|
tag |
用於標識條件。 |
字符串形式,不區分大小寫,長度范圍是1~12,由字母、數字和下划線組成,以字母開頭。tag不能為""、None、and、or以及andnot,不能包含\0。 |
network |
指定路由前綴。 |
點分十進制形式。 |
maskLen |
指定掩碼長度。 |
整數形式,取值范圍是0~32。 |
minLen |
指定掩碼長度匹配范圍的下限。 |
整數形式,必須大於等於maskLen的值。缺省值是None,表示掩碼長度匹配范圍的下限是0。 |
maxLen |
指定掩碼長度匹配范圍的上限。 |
整數形式,必須大於等於minLen的值。缺省值是None,表示掩碼長度匹配范圍的上限是0。 |
neLen |
指定不匹配的掩碼長度。 |
整數形式,必須大於等於minLen的值,小於等於maxLen的值。缺省值是None,表示不匹配的掩碼長度是0。 |
optype |
指定路由事件變更類型。 |
枚舉類型,取值如下:
缺省值是all。 |
protocol |
指定路由協議屬性。 |
字符串形式,缺省值為all,表示所有路由協議。
|
OPS 腳本模板
1 # -*- coding: utf-8 -*- # 聲明使用utf-8編碼格式,可以在Python腳本中添加中文注釋。 2 3 # 固定語句,導入ops模塊。導入ops模塊后,才能在腳本中使用設備支持的OPS API。詳見OPS API列表。 4 import ops 5 # 固定語句,導入sys模塊。sys模塊負責程序與設備內置Python解釋器的交互,提供了一系列的函數和變量。 6 # 導入sys模塊后,可以使用這些函數和變量。函數和變量的相關信息,請參考官方Python文檔。 7 import sys 8 # 固定語句,導入os模塊。os模塊負責程序與操作系統的交互,提供了訪問操作系統底層的接口。 9 # 導入os模塊后,可以使用這些接口。接口的相關信息,請參考官方Python文檔。 10 import os 11 12 # 固定語句,定義訂閱處理函數ops_condition。該函數在配置腳本助手的時候調用,用於訂閱事件,由設備內置的框架腳本_frame.py調度執行。 13 # 函數ops_condition的輸入參數是_frame.py中創建的ops對象,用戶可以在該對象下進行數據訪問。 14 def ops_condition(ops): 15 # 當前是訂閱階段,需要使用適用於訂閱階段的OPS API,詳見設備支持的OPS API中的表6-1。以下以定時器事件訂閱為例。 16 # 使用ops.timer.cron接口訂閱一個定時器,以t1標識。其含義為在每周一06:00觸發執行階段指定的動作。可以根據實際需求修改該定時器。 17 # 當輸入的參數值為字符串時,需要在字符串兩端使用雙引號。 18 # status和err_str為用戶定義的腳本變量,分別表示ops.timer.cron接口的第一個返回值和第二個返回值。 19 # 通常在調試階段,可以通過print語句將返回值打印出來,便於查看調試信息和定位問題。 20 # 對於OPS API,用戶可以根據實際需求決定是否需要返回值。如需要返回值,則必須根據各OPS API接口原型指定返回值的個數。 21 # 返回值的含義因OPS API而異。詳細描述請參見各OPS API。 22 # 對於ops.timer.cron接口,第一個返回值是數字時,0表示該API執行成功,1表示該API執行失敗。 23 # 第二個返回值僅當第一個返回值為1時返回,為字符串形式,描述執行失敗的原因。 24 status, err_str = ops.timer.cron("t1", "0 6 * * 1") 25 # 指定函數的返回值。函數的返回值可以作為處理結果,也可以通過result函數明確返回處理結果(詳見返回事件執行結果)。 26 # 函數的返回值作為函數的輸出,可以賦值給其他變量,作為其他函數的輸入。 27 # 這里指定函數ops_condition的返回值為0,表示返回值為0時,ops_condition函數執行成功。 28 return 0 29 30 # 固定語句,定義執行處理函數ops_execute。該函數在腳本事件執行的時候調用,用於執行動作,由設備內置的框架腳本_frame.py調度執行。 31 # 函數ops_execute的輸入參數是_frame.py中創建的ops對象,用戶可以在該對象下進行數據訪問。 32 def ops_execute(ops): 33 # 當前是執行階段,需要使用適用於執行階段的OPS API,詳見設備支持的OPS API中的表6-1。 34 # 以下以打開命令行通道、執行命令行命令和關閉命令行通道為例。 35 # 打開命令行通道。只有打開命令行通道之后,才能執行命令行。執行完命令行之后,需要關閉命令行通道。 36 # handle和err_desp為用戶定義的腳本變量,分別表示ops.cli.open接口的第一個返回值和第二個返回值。 37 # 通常在調試階段,可以通過print語句將返回值打印出來,便於查看調試信息和定位問題。 38 # 執行命令行命令和關閉命令行通道接口使用打開命令行通道接口的第一個返回值作為輸入參數。因此使用打開命令行通道接口時,必須指定返回值。 39 handle, err_desp = ops.cli.open() 40 # 執行命令display interface gigabitethernet 1/0/1。 41 # 返回值result為None時,表示命令行未能發送給CLI或者命令行執行超時,其他值為顯示輸出,即CLI中執行的命令行。 42 # 返回值n11為Next:0表示后續沒有輸出了,Next:1表示后續還有輸出。返回值n12僅在返回值result為None時顯示,表示命令行執行失敗的原因。 43 result1, n11, n12 = ops.cli.execute(handle, "display interface gigabitethernet 1/0/1") 44 # 執行命令display current-configuration interface gigabitethernet 1/0/1。 45 result2, n21, n22 = ops.cli.execute(handle, "display current-configuration interface gigabitethernet 1/0/1") 46 # 命令行執行結束,關閉命令行通道。 47 result = ops.cli.close(handle) 48 # 將display interface gigabitethernet 1/0/1命令的顯示結果記錄到日志中,可以在日志文件中查看相應信息。 49 log1, descri_str1 = ops.syslog(result1, "informational", "syslog") 50 # 將display current-configuration interface gigabitethernet 1/0/1命令的顯示結果記錄到日志中,可以在日志文件中查看相應信息。 51 log2, descri_str2 = ops.syslog(result2, "informational", "syslog") 52 # 指定函數的返回值。函數的返回值可以作為處理結果,也可以通過result函數明確返回處理結果(詳見返回事件執行結果)。 53 # 函數的返回值作為函數的輸出,可以賦值給其他變量,作為其他函數的輸入。 54 # 這里指定函數ops_execute的返回值為0,表示返回值為0時,ops_execute函數執行成功。 55 return 0
1 # -*- coding: utf-8 -*- 2 import ops # 導入ops模塊 3 import sys # 導入sys模塊 4 import os # 導入os模塊 5 import re # 導入re模塊,正則表達式 6 # 訂閱處理函數 7 def ops_condition (ops): 8 # 檢測有新增鄰居事件,這里僅訂閱鄰居是交換機和路由器類型的事件,如果需要訂閱其他類型的事件,請按照下面格式補充 9 value1, err_str1 = ops.lldp.subscribe("add1", ops.lldp.LLDP_NEIGHBOR_EVENT_ADD, "INTERFACE_ALL", ops.lldp.LLDP_NEIGHBOR_TYPE_SWITCH) 10 value11, err_str11 = ops.lldp.subscribe("add2", ops.lldp.LLDP_NEIGHBOR_EVENT_ADD, "INTERFACE_ALL", ops.lldp.LLDP_NEIGHBOR_TYPE_ROUTER) 11 12 # 檢測有刪除鄰居事件 13 value2, err_str2 = ops.lldp.subscribe("delete1", ops.lldp.LLDP_NEIGHBOR_EVENT_DEL, "INTERFACE_ALL", ops.lldp.LLDP_NEIGHBOR_TYPE_SWITCH) 14 value22, err_str21 = ops.lldp.subscribe("delete2", ops.lldp.LLDP_NEIGHBOR_EVENT_DEL, "INTERFACE_ALL", ops.lldp.LLDP_NEIGHBOR_TYPE_ROUTER) 15 16 # 組合事件,新增鄰居或刪除鄰居,最多支持8個事件組合 17 value10, err_str10 = ops.correlate("add1 or add2 or delete1 or delete2") 18 return 0 19 20 # 工作處理函數 21 def ops_execute (ops): 22 # 獲取系統環境變量_lldp_event,表示事件觸發類型 23 key, value = ops.environment.get("_lldp_event") 24 inter, value = ops.environment.get("_lldp_interface") 25 26 if key == "OPR_TYPE_ADD": 27 28 # 打開命令行通道 29 handle, err_desp = ops.cli.open() 30 neighbor, n11, n21 = ops.cli.execute(handle,"display lldp neighbor interface " + inter) 31 32 resultsys = re.search(r'System[\s]+name[\s:]*\S*', neighbor).group() 33 sysname = re.split(':', resultsys) 34 35 resultport = re.search(r'Port\s+ID\s{2,}:*\S*', neighbor).group() 36 port = re.split(':', resultport) 37 38 # 進入系統視圖 39 result, n11, n21 = ops.cli.execute(handle,"system-view") 40 41 # 進入接口視圖 42 result, n11, n21 = ops.cli.execute(handle,"interface " + inter) 43 44 # 設置接口描述信息 45 result, n11, n21 = ops.cli.execute(handle,"description " + "To-" + sysname[1] + "-" + port[1]) 46 47 48 # 關閉命令行通道 49 result = ops.cli.close(handle) 50 51 52 elif key == "OPR_TYPE_DEL": 53 handle, err_desp = ops.cli.open() 54 55 # 進入系統視圖 56 result, n11, n21 = ops.cli.execute(handle,"system-view") 57 58 # 進入接口視圖 59 result, n11, n21 = ops.cli.execute(handle,"interface " + inter) 60 61 # 設置接口描述信息 62 result, n11, n21 = ops.cli.execute(handle,"undo description") 63 64 # 關閉命令行通道 65 result = ops.cli.close(handle) 66 67 else: 68 return 1 69 return 0
#下載lldp.py文件 tftp 10.0.64.74 get ops/lldp.py #ops 安裝 lldp.py ops install file lldp.py #查看是否被安裝 <test>dir $_user/ Directory of flash:/$_user/ Idx Attr Size(Byte) Date Time FileName 0 drw- - Oct 15 2021 15:54:30 __pycache__ 1 -rw- 2,603 Oct 14 2021 15:29:20 lldp.py 2 drw- - May 27 2020 11:35:19 huawei_pys 3 -rw- 612 Oct 14 2021 16:43:13 dangerouscli.py 4 -rw- 912 Oct 15 2021 11:47:06 ospfroute.py 5 -rw- 2,145 Oct 15 2021 15:54:20 20211015.py 6 -rw- 471 Oct 14 2021 15:25:17 portshutdown.py #ops注冊 [test]ops [test-ops] script-assistant python lldp.py #設備開啟lldp [test]lldp enable #查看接口是否自動配置描述信息 [test]dis cu int MEth 0/0/1 # interface MEth0/0/1 description To-CN-ZhZ01-SW-B-eth-0-10 ip address 10.0.3.105 255.255.255.0 # #禁用LLDP [test]undo lldp enable #查看接口描述信息是否被刪除 Info: Global LLDP is disabled successfully. [test]dis cu int me [test]dis cu int MEth 0/0/1 # interface MEth0/0/1 ip address 10.0.3.105 255.255.255.0
import ops def ops_condition (ops): value1, descri_str1 = ops.cli.subscribe("cli1", "reboot", enter=False, sync=False,async_skip=True, sync_wait=60) value2, descri_str2 = ops.cli.subscribe("cli2", "stp disable", enter=False, sync=False,async_skip=True, sync_wait=60) value3, descri_str3 = ops.cli.subscribe("cli3", "stp enable", enter=False, sync=False,async_skip=True, sync_wait=60) value10, err_str10 = ops.correlate("cli1 or cli2 or cli3") return 0 def ops_execute (ops): value, descri_str = ops.terminal.write("Dangerous order, please contact the administrator to execute", vty="all")
驗證
#加載ops略 #執行關閉與開啟stp和reboot命令 [test]stp enable [test] Dangerous order, please contact the administrator to execute [test]undo stp enable [test] Dangerous order, please contact the administrator to execute [test]q <test>reboot <test> Dangerous order, please contact the administrator to execute
import ops,sys def ops_condition (ops): #result1_value, result2_description = ops.route.subscribe(tag, network, maskLen, minLen=None, maxLen=None, neLen=None, optype=all, protocol=all) #network可以自定義環境變量,在ops視圖下使用environment ospf_routes 10.2.1.0設定值 #獲取自定義環境變量值 slotid, errstr = ops.environment.get("ospf_routes") value,descri_str=ops.route.subscribe("route1", slotid, 24, minLen=None, maxLen=None, neLen=None, optype="all", protocol="ospf") return 0 def ops_execute (ops): key,values = ops.environment.get("_routing_type") if key == "Delete": handle, err_desp = ops.cli.open() cli, n11, n21 = ops.cli.execute(handle,"sys") cli, n11, n21 = ops.cli.execute(handle,"interface vlan 1588") cli1, n12, n22 = ops.cli.execute(handle,"shutdown") result = ops.cli.close(handle)
測試
#定義環境變量 [test-ops] environment ospf_routes 122.114.1.0 #加載ops腳本略 #查看ospf路由 [test]dis ospf routing 122.114.1.0 OSPF Process 1 with Router ID 192.168.35.60 Destination : 122.114.1.0/24 AdverRouter : 5.5.5.5 Area : 0.0.0.0 Cost : 2 Type : Stub NextHop : 10.35.0.133 Interface : Vlanif1588 Priority : Low Age : 22h42m42s [test] #刪除接口ospf后查看vlanif接口是否自動down interface Vlanif1588 ip address 10.35.0.134 255.255.255.252 ospf enable 1 area 0.0.0.0 # return [test-Vlanif1588]undo ospf enable ar 0 [test-Vlanif1588]dis this # interface Vlanif1588 shutdown ip address 10.35.0.134 255.255.255.252 # return [test-Vlanif1588]
import ops,sys,os,re def ops_condition (ops): value, descri_str = ops.cli.subscribe("cli1", "start", enter=True, sync=False,async_skip=True, sync_wait=60) value1, descri_str1 = ops.cli.subscribe("cli2", "rollback", enter=True, sync=False,async_skip=True, sync_wait=60) value2, descri_str2 = ops.cli.subscribe("cli3", "end", enter=True, sync=False,async_skip=True, sync_wait=60) value10, err_str10 = ops.correlate("cli1 or cli2 or cli3") return 0 def ops_execute (ops): key,value = ops.environment.get('_cli_command') if key =="start": #value, descri_str = ops.terminal.write(key, vty="all") handle, err_desp = ops.cli.open() ops.cli.execute(handle,"system-view") ops.cli.execute(handle,"ospf") ops.cli.execute(handle,"ar 0") ops.cli.execute(handle,"vlan 1587") ops.cli.execute(handle,"interface vlan 1587") ops.cli.execute(handle,"ip address 10.35.0.33 30") ops.cli.execute(handle,"ospf enable area 0") ops.cli.execute(handle,"interface XGigabitEthernet 0/0/5") ops.cli.execute(handle,"port link-type trunk") ops.cli.execute(handle,"undo port trunk allow-pass vlan 1") ops.cli.execute(handle,"port trunk allow-pass vlan 1587") ops.cli.execute(handle,"quit") result = ops.cli.close(handle) elif key =="rollback": handle, err_desp = ops.cli.open() ops.cli.execute(handle,"system-view") ops.cli.execute(handle,"undo interface vlan 1587") ops.cli.execute(handle,"undo vlan 1587") ops.cli.execute(handle,"interface XGigabitEthernet 0/0/5") ops.cli.execute(handle,"undo port trunk allow-pass vlan 1587") ops.cli.execute(handle,"undo port link-type") ops.cli.execute(handle,"quit") result = ops.cli.close(handle) elif key =='end': handle, err_desp = ops.cli.open() ops.cli.execute(handle,"system-view") ops.cli.execute(handle,"ops") ops.cli.execute(handle,"undo script-assistant python 20211015.py") ops.cli.execute(handle,"quit") ops.cli.execute(handle,"quit") ops.cli.execute(handle,"ops uninstall file 20211015.py") ops.cli.execute(handle,"delete 20211015.py") ops.cli.execute(handle,"y") result = ops.cli.close(handle)
測試
[test]dis vlan 1587 Error: The VLAN does not exist. [test]start [test]dis vlan 1587 -------------------------------------------------------------------------------- U: Up; D: Down; TG: Tagged; UT: Untagged; MP: Vlan-mapping; ST: Vlan-stacking; #: ProtocolTransparent-vlan; *: Management-vlan; -------------------------------------------------------------------------------- VID Type Ports -------------------------------------------------------------------------------- 1587 common TG:XGE0/0/5(D) VID Status Property MAC-LRN Statistics Description -------------------------------------------------------------------------------- 1587 enable default enable disable VLAN 1587 [test]dis cu int vlan 1587 # interface Vlanif1587 ip address 10.35.0.33 255.255.255.252 ospf enable 1 area 0.0.0.0 # return [test]rollback [test]dis vlan 1587 Error: The VLAN does not exist. [test]end [test]dis ops assistant current ------------------------------------------------------------------ Assistant State Condition ------------------------------------------------------------------ lldp.py ready multi dangerouscli.py ready multi ospfroute.py ready URM ------------------------------------------------------------------
華為ops核心思想
調用OPS API配置偵聽事件,編寫事件所觸發的執行腳本,命令行能實現的功能都可以寫入腳本,也可以讀取系統變量來動態執行命令