Juniper Slax Script 介绍 Stylesheet Language Alternative syntaX(SLAX 脚本:Juniper): 主要用于Junos 环境,功能类似 Extensible Stylesheet Language Transformations (XSLT) 语言,语法类似 C 和 PERL XSLT 是扩展样式表转换语言,可以把 XSL 文件链接到 XML 里面,例如: <!-- mataihang.xsl 可以是一个样式表,针对标签进行处理 --> <!-- mataihang.xsl 可以认为是XML的一个样式表 --> <?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet type="text/xsl" href="mataihang.xsl"?> <math> <m>mataihang</m> </math> SLAX 手册: http://juniper./libslax/slax-manual.html https://www./documentation/en_US/junos/topics/concept/junos-script-automation-slax-overview.html http://www.w3school.com.cn/xsl/ (XSL 教程) https://try./ (测试环境) / https://try./course/1/section/3/ JunOS 相关的方法定义 https://github.com/Juniper/libslax/wiki/Building 运行环境 SLAX 的工作流程:SLAX 脚本生成 -> XSLT 脚本(可选) -> 通过Junos mgd 渲染 XML Doc -> 生成最后的XML,目的是为了生成 XML 第一个Hello world 程序: # 输入的文件 SLAX version 1.0; ns junos = "http://xml./junos/*/junos"; ns xnm = "http://xml./xnm/1.1/xnm"; ns jcs = "http://xml./junos/commit-scripts/1.0"; match / { /* 直接输出 */ expr "mataihang"; } # 输出的内容 <?xml version="1.0"?> mataihang {} 代码块定义方式: match / 是匹配整个文档的根,和XSTL一样,match 上面有三个参数 version:版本 ns:等于 xmlns import:导入xsl 文件,例如 import "mataihang.xsl"; /* 注释写法 */ version 1.0; /* 定义变量 */ ns junos = "http://xml./junos/*/junos"; ns xnm = "http://xml./xnm/1.1/xnm"; ns jcs = "http://xml./junos/commit-scripts/1.0"; /* 匹配根目录 */ match / { <math> { /* 直接显示输出 */ <output> "mataihang1"; <output m1="m1" m2="m2"> "mataihang2"; } } <!-- 最终输出结果 --> <?xml version="1.0"?> <math xmlns:junos="http://xml./junos/*/junos" xmlns:xnm="http://xml./xnm/1.1/xnm" xmlns:jcs="http://xml./junos/commit-scripts/1.0"> <output> mataihang1 </output> <output m1="m1" m2="m2"> mataihang2 </output> </math> 如何定义变量及相关: 变量包含5种类型:(var 是常量,mvar 是变量) 字符串:var $mataihang = "m" 数字:var $mataihang = "100" 或者 var $mataihang = 100 布尔(true / false):var $mataihang = ( 15 == 15); 结果数片段:var $mataihang = { <m1> { <m2> "m3"; } } 节点集合:var $mataihang1 = jcs:invoke("get-interface-information"); 结果数片段转换成节点集合方式 var $mataihang := var $mataihang1 /* 输入文件 */ version 1.0; var $mataihang = { <m1> { <m2> "m3"; } } var $mataihang1 = "我可以定义在外面,全局变量"; match / { <math> { var $mataihang2 = "我可以定义在里面,局部变量"; <output mataihang1=$mataihang1> $mataihang; <output> $mataihang1; <output> $mataihang2; } } <!-- 最终输出结果 --> <?xml version="1.0"?> <math> <output mataihang1="mataihang1"> m3 </output> <output> 我可以定义在外面,全局变量 </output> <output> 我可以定义在里面,局部变量 </output> </math> 运算符及操作符: # and 操作:$mataihang > 500000 && $mataihang < 100000 # or 操作:$mataihang != 1500 || $mataihang > 2000 # node 并操作:var $mataihang = $mataihang1 | $mataihang2 # 比较操作符:<、>、<=、>=、!=、==、 if else 的写法: if( $mataihang == "m1" ) { <output> "m1"; } else if( $mataihang == "m2" ) { <output> "m2"; } else { <output> "m3"; } /* 输入文件 */ version 1.0; match / { <math> { <output> 1 + 1; <output> 1 - 1; <output> 5 * 10; <output> 10 div 2; <output> 10 mod 3; /* 条件语句 */ var $mataihang = 1500; if ($mataihang == 1500) { <output> "mataihang is 1500"; } if ($mataihang != 1400) { <output> "mataihang is not equal to 1400"; } <output> ( $mataihang * 2 ) + 150; /* 字符串拼接,需要加_ */ <output> "mataihang value is " _$mataihang; } } <!-- 最终输出结果 --> <?xml version="1.0"?> <math> <output>2</output> <output>0</output> <output>50</output> <output>5</output> <output>1</output> <output>mataihang is 1500</output> <output>mataihang is not equal to 1400</output> <output>3150</output> <output>mataihang value is 1500</output> </math> 字符串转换:(字符串之间+法用_) /* 输入文件 */ version 1.0; match / { <math> { var $mataihang1 = "-500"; var $mataihang2 = "100"; <output> $mataihang1 + $mataihang2; <output> $mataihang1 + "" + $mataihang2; <output> $mataihang1 _$mataihang2; } } <!-- 最终输出结果 --> <?xml version="1.0"?> <math> <output>-400</output> <output>NaN</output> <output>-500100</output> </math> ../import/junos.xsl 默认参数: 提供了6个设备的默认参数: $product: Junos device 名字 $user: Junos device 被分配的用户 $hostname: Junos device 主机名 $script: 当然执行脚本名 $localtime: 本地时间 Tue Jan 20 14:07:33 2009 $localtime-iso: 格式化的本地时间 2009-01-20 14:07:33 PST 还提供了一个全局变量 $junos-context;,需要引入../import/junos.xsl /* 输入文件 */ version 1.0; ns junos = "http://xml./junos/*/junos"; ns xnm = "http://xml./xnm/1.1/xnm"; ns jcs = "http://xml./junos/commit-scripts/1.0"; import "../import/junos.xsl"; match / { <math> { <output> $junos-context; } } <!-- 最终输出结果 --> <?xml version="1.0" standalone="yes"?> <math xmlns:junos="http://xml./junos/*/junos" xmlns:xnm="http://xml./xnm/1.1/xnm" xmlns:jcs="http://xml./junos/commit-scripts/1.0"> <output> try-slax-host-1juiseThu Aug 30 03:15:41 2000-08-30 03:15:41 UTCoplocalhostslaxmodejuise-D/home/ubuntu/juise_rpc_scripts-Pnetconf--userslaxmode--targetlocalhosttemp.slax </output> </math> 定义和使用模板: /* 输入文件 */ version 1.0; import "../import/junos.xsl"; template math-template($mataihang) { /* 内部参数定义方式,用var 也行,param 只能定义在 template 和 function 里面 */ param $mataihang_inner = 100; <output> "mataihang:" _$mataihang; <output> $mataihang_inner; } template math_temp($param1, $param2 = 0){ <output> $param1 _$param2; } template mp(){ param $param1 = "mataihang_param"; /* 下面方法等效 */ call math_temp($param1, $param2 = 100); call math_temp{ with $param1; with $param2 = 100; }; } match / { <math> { call mp; call math-template($mataihang = "mataihang"); } } <!-- 最终输出结果 --> <?xml version="1.0" standalone="yes"?> <math> <output>mataihang:mataihang</output> <output>100</output> </math> 定义和使用函数: /* 输入文件 */ version 1.0; ns junos = "http://xml./junos/*/junos"; ns xnm = "http://xml./xnm/1.1/xnm"; ns jcs = "http://xml./junos/commit-scripts/1.0"; match / { <math> { var $mataihang = { call mataihang-template(); } <output> $mataihang; /* 使用命名空间内的方法:jcs:printf() */ <output> jcs:printf("%10s", "mataihang"); } } template mataihang-template { expr substring( "mataihang", 1, 4 ); } <!-- 最终输出结果 --> <?xml version="1.0"?> <math xmlns:junos="http://xml./junos/*/junos" xmlns:xnm="http://xml./xnm/1.1/xnm" xmlns:jcs="http://xml./junos/commit-scripts/1.0"> <output>mata</output> <output> mataihang</output> </math> /* 定义一个函数 */ version 1.1; ns mataihang = "http://www./math"; function mataihang:size ($math1, $math2, $math3 = 1) { /* 等于 return */ result <size> { expr $math1 * $math2 * $math3; } } match / { <out> { /* copy-of 直接复制结果集到文档树 */ copy-of mataihang:size(100,200); } } <!-- 最终输出结果 --> <?xml version="1.0"?> <out xmlns:mataihang="http://www./math"> <size>20000</size> </out> 递归的调用的例子: version 1.0; var $count = 1; match / { call update-count($mataihang = $count); } template update-count($mataihang) { expr $count _ ", " _ $mataihang _"\n"; if ($mataihang != 4) { call update-count($mataihang = $mataihang + 1); } } <!-- 最终输出结果 --> <?xml version="1.0"?> 1, 1 1, 2 1, 3 1, 4 循环调用的例子: version 1.0; var $list := { <list> { <grocery> { <name> "milk"; <type> "nonfat"; <brand> "any"; <size> "gallon"; } <grocery> { <name> "orange juice"; <type> "no pulp"; <brand> "any"; <size> "half gallon"; } <drugstore>{ <name> "aspirin"; <brand> "any"; <size> "50 tablets"; } } } match / { /* 可变变量 */ mvar $mylist; set $mylist = <item> { <name> "coffee"; <size> "1 lb"; } /* 可以添加条件:for $item ($list/list/grocery[type == "nonfat"]) */ /* 类似 for-each,for-each 会选取所有元素 */ for $item ($list/list/grocery) { /* append 添加list元素 */ append $mylist += <item> { <name> $item/name; <size> $item/size; } } /* copy-of 是添加节点 */ <grocery-short-list> { copy-of $mylist; } } <!-- 最终输出结果 --> <?xml version="1.0"?> <grocery-short-list> <item><name>coffee</name><size>1 lb</size></item> <item><name>milk</name><size>gallon</size></item> <item><name>orange juice</name><size>half gallon</size></item> </grocery-short-list> 命名空间的一些使用: bit - libslax - xml./bit curl - libslax - xml./curl exsl - exslt - http:///common crypto - exslt - http:///crypto math - exslt - http:///math set - exslt - http:///sets func - exslt - http:///functions str - exslt - http:///string date - exslt - http:///dates-and-times dyn - exslt - http:///dynamic saxon - libxslt - http:///saxon os - libslax - http://xml./os xutil - libslax - http://xml./xutil 例:两种写法 /* 写法一 */ version 1.1; match / { <top> { expr date:time(); } } <?xml version="1.0"?> <top>04:19:38</top> /* 写法二 */ version 1.1; ns date extension = "http:///dates-and-times"; match / { <top> date:time(); } <?xml version="1.0"?> <top>04:20:12</top> 两个event script 的例子: /* change-apn-settings.slax */ version 1.0; ns junos = "http://xml./junos/*/junos"; ns xnm = "http://xml./xnm/1.1/xnm"; ns jcs = "http://xml./junos/commit-scripts/1.0"; ns str = "http:///strings"; ns exsl extension = "http:///common"; import "../import/junos.xsl"; var $APN_NAME = "apn"; var $AUTH_METHOD = "PAP"; var $USER_ID = "matiahang"; var $PASSWORD = "mataihang"; var $SIM_CE = "Y"; var $STORE_S1_FILE = "/var/tmp/change-apn-settings.tmp"; var $STORE_S2_FILE = "/var/tmp/confirm-or-revert-apn-settings.tmp"; /* show wireless-wan adapter | display xml */ /* todo change cli command */ var $IMSI_CMD = <get-wireless-wan-adapter-information>; var $CREATE_PROFILE_CMD = "request modem wireless create-profile cl-0/1/0 slot 1 profile-id 2 access-point-name" _ $APN_NAME _ "authentication-method" _ $AUTH_METHOD _ "sip-user-id" _ $USER_ID _ "sip-password" _ $PASSWORD; match / { <event-script-results> { var $connection = jcs:open(); if ($SIM_CE == "Y") { <exsl:document href=$STORE_S1_FILE indent="yes" method="xml" omit-xml-declaration="yes"> { var $imsi_result = jcs:execute($connection, $IMSI_CMD); $imsi_result; } } var $create_profile_result = jcs:execute($connection, $CREATE_PROFILE_CMD); if ($create_profile_result == "ok"){ /* "set interfaces cl-0/1/0 cellular-options sim 1 select-profile profile-id 2" */ var $sim_conf = { <configuration> { <interfaces> { <cl-0\/1\/0> { <cellular-options> { <sim> 1; <select-profile> { <profile-id> 2; } } } } } } var $sim_conf_options := { <commit-options> { <synchronize>; <log> "set interfaces cl-0/1/0 cellular-options sim 1 select-profile profile-id 2"; } } var $sim_conf_results := { call jcs:load-configuration($action="merge", $commit-options=$sim_conf_options, $configuration = $sim_conf, $connection = $connection); } if ($sim_conf_results//xnm:error) { for-each ($sim_conf_results//xnm:error) { <output> "set sim conf error"; } } else { var $policy_conf = { <configuration> { <event-options> { <policy operation="delete"> "change-apn-setting-policy"; } } } var $policy_conf_options := { <commit-options> { <synchronize>; <log> "delete event policy: change-apn-setting-policy "; } } var $policy_conf_results := { call jcs:load-configuration($action="merge", $commit-options=$policy_conf_options, $configuration = $policy_conf, $connection = $connection); } if ($policy_conf_results//xnm:error) { for-each ($policy_conf_results//xnm:error) { <output> "delete event policy error"; } } } } var $close-connection = jcs:close( $connection ); } } /* confirm-or-revert-apn-settings.slax */ version 1.0; ns junos = "http://xml./junos/*/junos"; ns xnm = "http://xml./xnm/1.1/xnm"; ns jcs = "http://xml./junos/commit-scripts/1.0"; ns str = "http:///strings"; ns exsl extension = "http:///common"; import "../import/junos.xsl"; var $APN_NAME = "apn"; var $AUTH_METHOD = "PAP"; var $USER_ID = "matiahang"; var $PASSWORD = "mataihang"; var $SIM_CE = "Y"; var $STORE_S1_FILE = "/var/tmp/change-apn-settings.tmp"; var $STORE_S2_FILE = "/var/tmp/confirm-or-revert-apn-settings.tmp"; var $STORE_ERROR_FILE = "/var/tmp/confirm-or-revert-apn-settings_error.tmp"; /* show modem wireless network | display xml */ var $GET_SIM_ID_CMD = "<xxx>" var $NEW_PROFILE_CMD = "request modem wireless create-profile cl-0/1/0 slot 1 profile-id 2 access-point-name" _ $APN_NAME _ "authentication-method" _ $AUTH_METHOD _ "sip-user-id" _ $USER_ID _ "sip-password" _ $PASSWORD; var $OLD_PROFILE_CMD = "request modem wireless create-profile cl-0/1/0 slot 1 profile-id 1 access-point-name" _ $APN_NAME _ "authentication-method" _ $AUTH_METHOD _ "sip-user-id" _ $USER_ID _ "sip-password" _ $PASSWORD; template delete-policy($conn){ var $policy_conf = { <configuration> { <event-options> { <policy operation="delete"> "confirm-or-revert-apn-setting-policy"; } } } var $policy_conf_options := { <commit-options> { <synchronize>; <log> "delete event policy: confirm-or-revert-apn-setting-policy "; } } var $policy_conf_results := { call jcs:load-configuration($action="merge", $commit-options=$policy_conf_options, $configuration = $policy_conf, $connection = $conn); } if ($policy_conf_results//xnm:error) { for-each ($policy_conf_results//xnm:error) { <output> "delete event policy error"; } } } match / { <event-script-results> { if ($SIM_CE == "Y") { var $fileget_s1 = { <file-get> { <filename> $STORE_S1_FILE; <encoding> "ascii"; } } var $fileget_s2 = { <file-get> { <filename> $STORE_S2_FILE; <encoding> "ascii"; } } var $connection = jcs:open(); var $old_sim_id = jcs:execute( $connection , $fileget_s1 ); var $apn_flag = jcs:execute( $connection , $fileget_s2 ); var $result = jcs:execute($connection, $GET_SIM_ID_CMD); var $new_sim_id = $result//sim; if ($apn_flag){ /* show modem wireless network */ if($new_sim_id == $old_sim_id){ jcs:execute($connection, $OLD_PROFILE_CMD); call delete-policy($conn = $connection); } } else { if ($new_sim_id != $old_sim_id){ if ($result//ip == "successfully" && $result//gateway == "successfully"){ jcs:execute($connection, $NEW_PROFILE_CMD); call delete-policy($conn = $connection); } else { <exsl:document href=$STORE_ERROR_FILE indent="yes" method="xml" omit-xml-declaration="yes"> { "APN settings do not work with new SIM" } <exsl:document href=$STORE_S2_FILE indent="yes" method="xml" omit-xml-declaration="yes"> { "APN_FLAG" } } } } } else { var $result = jcs:execute($connection, $GET_SIM_ID_CMD); if ($result//ip == "successfully" && $result//gateway == "successfully"){ jcs:execute($connection, $NEW_PROFILE_CMD); call delete-policy($conn = $connection); } else { jcs:execute($connection, $OLD_PROFILE_CMD); call delete-policy($conn = $connection); <exsl:document href=$STORE_ERROR_FILE indent="yes" method="xml" omit-xml-declaration="yes"> { "APN settings do not work" } } } var $close-results = jcs:close( $connection ); } } 部署 libslax 运行环境,可以是JunOS的环境,或者unix环境 root@mataihang-virtual-machine:~# apt-get install make gcc bison libxml2-devel libxml2 home: http://www./index.html download information: http://www./downloads.html libxslt home: http:///XSLT/ download information: http:///XSLT/downloads.html libcurl (optional) home: http://curl./libcurl/ download information: http://curl./download.html libedit (optional) note: libreadline can also be used optionally home: http://www./editline/ 最好找一些Junos的环境,这样比较调用系统库的内容 JunOS 环境: andyma@andyma-mbp:~/git/csp-hapi-server/csp-template-service$ telnet 10.208.26.60 7025 Trying 10.208.26.60... Connected to 10.208.26.60. Escape character is '^]'. * * * * ttyS25 is being used by (pid=27814) !!! * 1 - Initiate a regular session 2 - Initiate a sniff session 3 - Send messages to another user 4 - Kill session(s) 5 - Quit # 创建一个slax 文件,放入/var/db/scripts/op 下面 root@c06-33% vi /var/db/scripts/op # 默认模式,需要进入cli 模式 root@c06-33% cli # 进入configure 模式 root@c06-33> configure Entering configuration mode [edit] # 进入分层 root@c06-33# edit system scripts op [edit system scripts op] # 提交刚才创建的脚本 root@c06-33# set file mataihang.slax # 确认配置 root@c06-33# commit and-quit # cli 模式下执行 root@c06-33> op mataihang.slax 2 0 50 5 1 mataihang is 1500 Junos 自动化脚本: 主要包含了6类脚本:commit scripts,operation (op) scripts,Event policies,Event scripts,SNMP scripts,macros 支持的语言:XSTL、SLAX、Python,脚本需要扔到指定类型目录,然后添加到系统脚本里面cli 模式下执行,或者event 触发一下 Commit Scripts:生成显示警告给用户、生成日志(syslog)给用户、改变配置规则、生成提交错误信息 operation Scripts:创建和执行操作、自定义输出、执行配置更改、监控设备状态 Event policies:忽略事件、执行Junos 事件和操作命令、修改配置、上传指定目的文件 Event scripts:网络故障诊断及处理、监控设备状态、作为policies 条件部分的一部分执行、响应问题改变的配置 SNMP scripts:[edit system scripts snmp file script-name] 下面管理SNMP Junos 一些命令:查询 rpc xml 命令 cli>show xxx| display xml rpc,不加rpc 是结果 root@c06-33> show interfaces |display xml rpc <rpc-reply xmlns:junos="http://xml./junos/12.1I0/junos"> <rpc> <get-interface-information> </get-interface-information> </rpc> <cli> <banner></banner> </cli> </rpc-reply> Event Scripts:(例子:change-apn-setting,Event Scripts) 执行模式:[edit event-options event-script file] // event script 模板 version 1.0; ns junos = "http://xml./junos/*/junos"; ns xnm = "http://xml./xnm/1.1/xnm"; ns jcs = "http://xml./junos/commit-scripts/1.0"; import "../import/junos.xsl"; match / { <event-script-results> { /* * Insert your code here */ } } 系统 eventd process 会接收事件策略,使用if-then-else结构,下面是查看策略命令列表 [edit] root@c06-33# set event-options policy policy-name events ? Possible completions: <event> [ Open a set of values acct_accounting_ferror acct_accounting_fopen_error acct_accounting_small_file_size acct_bad_record_format acct_cu_rtslib_error acct_fork_err acct_fork_limit_exceeded acct_gethostname_error acct_malloc_failure acct_thread_create_failure acct_undefined_counter_name acct_xfer_failed acct_xfer_popen_fail acct_xfer_timedout alarmd_config_access_error alarmd_config_close_error alarmd_config_parse_error alarmd_config_reconfig_error alarmd_connection_failure alarmd_decode_alarm_object_error alarmd_exists ---(more 1%)--- 创建一个脚本:/var/db/scripts/event/mataihang.slax root@c06-33% vi /var/db/scripts/event/mataihang.slax root@c06-33% cli root@c06-33> configure Entering configuration mode The configuration has been changed but not committed [edit] root@c06-33# edit event-options event-script [edit event-options event-script] root@c06-33# set file mataihang.slax [edit event-options event-script] # 删除错误配置 [edit event-options] root@c06-33# delete policy policy-name 定义一个策略,下面是模板,一句一句set出来 var $event-definition = { <event-options> { <generate-event> { <name> "MIB-DATA-DUMP"; <time-interval> "300"; } <policy> { <name> "MIB-DATA-DUMP"; <events> "MIB-DATA-DUMP"; <then> { <event-script> { <name> "mataihang.slax"; } } } } } # set event-options policy mataihang-policy events "MIB-DATA-DUMP" root@c06-33# set policy mataihang-policy events "MIB-DATA-DUMP" root@c06-33# set policy mataihang-policy then event-script mataihang.slax [edit event-options] root@c06-33# show policy mataihang-policy { events MIB-DATA-DUMP; then { event-script mataihang.slax; } } event-script { file mataihang.slax; } root@c06-33# commit # cli 模式下,reload 所有事件到内存 root@c06-33> request system scripts event-scripts reload Event scripts loaded |
|
来自: 新用户8581QGfy > 《待分类》