示例:为脚本内的连接指定会话协议
以下示例演示如何在创建与远程设备的连接时在 Junos 自动化脚本中指定会话协议。具体来说,示例 操作脚本 会与运行 Junos OS 的远程设备建立 NETCONF 会话,检索和打印 NETCONF 服务器功能,然后在该设备上更新并提交配置。
要求
运行 Junos OS 11.4 或更高版本的路由、交换或安全设备。
客户端应用程序可以登录到 NETCONF 服务器所在的设备。
NETCONF 服务器所在设备上启用了 通过 SSH 的 NETCONF 服务。
概述和脚本
扩展 jcs:open()
功能包括以下选项:在运行 Junos OS 的设备上与 Junos XML 协议服务器创建会话,或者在启用了通过 SSH 提供 NETCONF 服务的设备上与 NETCONF 服务器创建会话。在以下示例中,该脚本会创建连接并与运行 Junos OS 的远程设备建立 NETCONF 会话。如果成功建立了连接和会话,则脚本会更新远程设备上的配置,以便将 ftp
语句添加到 [edit system services]
层次结构级别。该脚本还会检索和打印会话协议以及 NETCONF 服务器的功能。
脚本会采用一个参数, remote-host
即远程设备的 IP 地址或主机名。该 arguments
变量在脚本的全局级别进行声明,以便在用户需要 上下文相关帮助时,参数名称和说明在命令行界面 (CLI) 中可见。
该变量 netconf
是一个节点集,用于为远程设备指定会话协议和连接参数。元素的值 <method>
设置为“netconf”,以通过 SSHv2 连接与 NETCONF 服务器建立会话。该 <username>
元素用于指定连接的用户名。如果未指定用户名,并且是连接所需的用户名,则脚本将使用执行脚本的用户的本地名称。在此示例中,未指定密码和端口。如果身份验证需要密码,则远程设备应在脚本执行期间提示输入密码。该脚本使用默认的 NETCONF 端口 830 建立会话。
如果连接和建立 NETCONF 会话成功,则脚本将执行远程过程调用 (RPC)。RPC 包含标记元素 <lock>
、 <edit-config>
、 <commit>
和 <unlock>
,这些是 NETCONF 操作,用于锁定、编辑、提交和解锁 候选配置。该脚本将每个任务的 RPC 存储在一个单独的变量中。每个 RPC 的结果也会单独存储,并解析错误。只有在上一步成功的情况下,脚本才会执行每个后续步骤。例如,如果脚本无法锁定配置,则不会执行 RPC 来编辑、提交或解锁配置。
该变量 rpc-edit-config
包含标记元素 <edit-config>
,这是修改配置的 NETCONF 操作。子元素 <config>
包括与设备上的候选配置合并的配置的修改部分。如果遇到错误,则脚本会调用语句 copy-of
,将结果树分片变量复制到结果树,以便在脚本执行期间将错误消息打印到 CLI。
SLAX 语法
version 1.0; ns junos = "http://xml.juniper.net/junos/*/junos"; ns xnm = "http://xml.juniper.net/xnm/1.1/xnm"; ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0"; ns ext = "http://xmlsoft.org/XSLT/namespace"; var $arguments = { <argument> { <name> "remote-host"; <description> "device hostname or IP address to which to connect"; } } param $remote-host; match / { <op-script-results> { var $netconf := { <method> "netconf"; <username> "bsmith"; } var $rpc-lock-config = { <lock> { <target> { <candidate>; } } } var $rpc-unlock-config = { <unlock> { <target> { <candidate>; } } } var $rpc-commit = { <commit>; } var $rpc-edit-config = { <edit-config> { <target> { <candidate>; } <default-operation> "merge"; <config> { <configuration> { <system> { <services> { <ftp>; } } } } } } if ($remote-host = '') { <xnm:error> { <message> "missing mandatory argument 'remote-host'"; } } else { var $connection = jcs:open($remote-host, $netconf); if ($connection) { /* request protocol and capabilities */ var $protocol = jcs:get-protocol($connection); var $capabilities = jcs:get-hello($connection); <output> "\nSession protocol: " _ $protocol _ "\n"; copy-of $capabilities; /* execute rpcs to lock, edit, commit, and unlock config */ var $lock-reply = jcs:execute($connection, $rpc-lock-config); if ($lock-reply/..//rpc-error) { copy-of $lock-reply; } else { var $edit-config-reply = jcs:execute($connection, $rpc-edit-config); if ($edit-config-reply/..//rpc-error) { <output>"Configuration error: "_ $edit-config-reply/..//error-message/. _ "\nConfiguration not committed.\n" ; copy-of $edit-config-reply; } else { var $commit-reply = jcs:execute($connection, $rpc-commit); if ($commit-reply/..//rpc-error) { <output>"Commit error or warning: " _ $commit-reply/..//error-message/.; copy-of $commit-reply; } } var $unlock-reply = jcs:execute($connection, $rpc-unlock-config); } expr jcs:close($connection); } else { <output>"\nNo connection - exiting script"; } } } }
XSLT 语法
<?xml version="1.0" standalone="yes"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:junos="http://xml.juniper.net/junos/*/junos" xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm" xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0" xmlns:ext="http://xmlsoft.org/XSLT/namespace" version="1.0"> <xsl:variable name="arguments"> <argument> <name>remote-host</name> <description>device hostname or IP address to which to connect</description> </argument> </xsl:variable> <xsl:param name="remote-host"/> <xsl:template match="/"> <op-script-results> <xsl:variable name="netconf-temp-1"> <method>netconf</method> <username>bsmith</username> </xsl:variable> <xsl:variable xmlns:ext="http://xmlsoft.org/XSLT/namespace" name="netconf" select="ext:node-set($netconf-temp-1)"/> <xsl:variable name="rpc-lock-config"> <lock> <target> <candidate/> </target> </lock> </xsl:variable> <xsl:variable name="rpc-unlock-config"> <unlock> <target> <candidate/> </target> </unlock> </xsl:variable> <xsl:variable name="rpc-commit"> <commit/> </xsl:variable> <xsl:variable name="rpc-edit-config"> <edit-config> <target> <candidate/> </target> <default-operation>merge</default-operation> <config> <configuration> <system> <services> <ftp/> </services> </system> </configuration> </config> </edit-config> </xsl:variable> <xsl:choose> <xsl:when test="$remote-host = ''"> <xnm:error> <message>missing mandatory argument 'remote-host'</message> </xnm:error> </xsl:when> <xsl:otherwise> <xsl:variable name="connection" select="jcs:open($remote-host, $netconf)"/> <xsl:choose> <xsl:when test="$connection"> <!-- request protocol and capabilities --> <xsl:variable name="protocol" select="jcs:get-protocol($connection)"/> <xsl:variable name="capabilities" select="jcs:get-hello($connection)"/> <output> <xsl:value-of select="concat(' Session protocol: ', $protocol, ' ')"/> </output> <xsl:copy-of select="$capabilities"/> <!-- execute rpcs --> <xsl:variable name="lock-reply" select="jcs:execute($connection, $rpc-lock-config)"/> <xsl:choose> <xsl:when test="$lock-reply/..//rpc-error"> <xsl:copy-of select="$lock-reply"/> </xsl:when> <xsl:otherwise> <xsl:variable name="edit-config-reply" select="jcs:execute($connection, $rpc-edit-config)"/> <xsl:choose> <xsl:when test="$edit-config-reply/..//rpc-error"> <output> <xsl:value-of select="concat('Configuration error: ', $edit-config-reply/..//error-message/., ' Configuration not committed. ')"/> </output> <xsl:copy-of select="$edit-config-reply"/> </xsl:when> <xsl:otherwise> <xsl:variable name="commit-reply" select="jcs:execute($connection, $rpc-commit)"/> <xsl:if test="$commit-reply/..//rpc-error"> <output> <xsl:value-of select="concat('Commit error or warning: ', $commit-reply/..//error-message/.)"/> </output> <xsl:copy-of select="$commit-reply"/> </xsl:if> </xsl:otherwise> </xsl:choose> <xsl:variable name="unlock-reply" select="jcs:execute($connection, $rpc-unlock-config)"/> </xsl:otherwise> </xsl:choose> <xsl:value-of select="jcs:close($connection)"/> </xsl:when> <xsl:otherwise> <output>No connection - exiting script</output> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </op-script-results> </xsl:template> </xsl:stylesheet>
配置
程序
逐步过程
要下载、启用和测试脚本:
将 XSLT 或 SLAX 脚本复制到文本文件中,根据需要将文件命名 为 netconf-session.xsl 或 netconf-session.slax ,并将其复制到设备上的 /var/db/script/op/ 目录中。
在配置模式下,在层次结构级别包括语句
[edit system scripts op]
,并根据需要将 netconf-session.xsl 或 netconf-session.slax 包含在file
内。[edit system scripts op] bsmith@local-host# set file netconf-session.(slax | xsl)
commit and-quit
发出命令。[edit] bsmith@local-host# commit and-quit
通过发出
op netconf-session
操作模式命令在本地设备上执行 op 脚本,并包括任何必要的参数。在此示例中,用户 bsmith 正在连接到远程设备(五星)。远程设备具有双路由引擎,因此操作
commit
会返回一个警告,即commit synchronize
应使用命令向两个路由引擎提交新的候选配置。bsmith@local-host> op netconf-session remote-host fivestar bsmith@fivestar's password: Session protocol: netconf Commit error or warning: graceful-switchover is enabled, commit synchronize should be used
验证
确认设备工作正常。
验证操作脚本执行
目的
验证脚本是否按预期运行。
行动
查看 CLI 和操作脚本日志文件中的脚本输出。特别注意在执行过程中发生的任何错误。默认的 op 脚本日志文件为 /var/log/op-script.log。如果日志文件很长,请通过将选项追加 | last number-of-lines
到命令并指定要打印到 CLI 的行数来 show log
限制显示。元素内的 <op-script-results>
输出与脚本执行相关。
bsmith@local-host> show log op-script.log | last 100 ...output omitted for brevity... <op-script-results xmlns:junos="http://xml.juniper.net/junos/*/junos" xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm" xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0" xmlns:ext="http://xmlsoft.org/XSLT/namespace"> <output> Session protocol: netconf </output> <hello> <capabilities> <capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability> <capability>urn:ietf:params:xml:ns:netconf:capability:candidate:1.0 </capability> <capability>urn:ietf:params:xml:ns:netconf:capability:confirmed-commit:1.0 </capability> <capability>urn:ietf:params:xml:ns:netconf:capability:validate:1.0</capability> <capability> urn:ietf:params:xml:ns:netconf:capability:url:1.0?protocol=http,ftp,file </capability> <capability>http://xml.juniper.net/netconf/junos/1.0</capability> <capability>http://xml.juniper.net/dmi/system/1.0</capability> </capabilities> <session-id>29087</session-id> </hello> <output>Commit error or warning: graceful-switchover is enabled, commit synchronize should be used </output> <rpc-error> <error-severity>warning</error-severity> <error-message> graceful-switchover is enabled, commit synchronize should be used </error-message> </rpc-error> <ok/> </op-script-results>
在执行操作脚本时包含 | display xml
选项,您还可以在运行 Junos OS 的设备上获取更具描述性的脚本输出。
bsmith@local-host> op netconf-session remote-host fivestar | display xml <rpc-reply xmlns:junos="http://xml.juniper.net/junos/11.4D0/junos"> <output> Session protocol: netconf </output> <hello> <capabilities> <capability> urn:ietf:params:xml:ns:netconf:base:1.0 </capability> <capability> urn:ietf:params:xml:ns:netconf:capability:candidate:1.0 </capability> <capability> urn:ietf:params:xml:ns:netconf:capability:confirmed-commit:1.0 </capability> <capability> urn:ietf:params:xml:ns:netconf:capability:validate:1.0 </capability> <capability> urn:ietf:params:xml:ns:netconf:capability:url:1.0?protocol=http,ftp,file </capability> <capability> http://xml.juniper.net/netconf/junos/1.0 </capability> <capability> http://xml.juniper.net/dmi/system/1.0 </capability> </capabilities> <session-id> 29087 </session-id> </hello> <output> Commit error or warning: graceful-switchover is enabled, commit synchronize should be used </output> <rpc-error> <error-severity> warning </error-severity> <error-message> graceful-switchover is enabled, commit synchronize should be used </error-message> </rpc-error> <ok/> </op-script-results> <cli> <banner></banner> </cli> </rpc-reply>
意义
此示例将在运行 Junos OS 的远程设备上创建一个 NETCONF 会话。NETCONF 服务器的功能包括标准 NETCONF 操作和瞻博网络的专有扩展,这些扩展在和http://xml.juniper.net/dmi/system/1.0
中http://xml.juniper.net/netconf/junos/1.0
定义。操作的 commit
RPC 结果包括一个警告,但提交操作仍然成功。
验证配置更改
目的
查看远程设备上的配置更改和提交日志,验证提交是否成功。
行动
在远程设备上,执行 show configuration system services
操作模式命令以查看 [edit system services]
配置的层级。如果脚本成功,则配置将包含语句 ftp
。
bsmith@fivestar> show configuration system services ftp; netconf { ssh; }
此外,您还可以查看提交日志。在远程设备上,执行 show system commit
操作模式命令以查看提交日志。在此示例中,日志确认在给定日期和时间在 NETCONF 会话中提交候选配置。
bsmith@fivestar> show system commit 0 2011-07-11 12:04:01 PDT by bsmith via netconf 1 2011-07-08 15:16:33 PDT by root via cli
故障 排除
连接错误的故障排除
问题
该脚本将生成以下错误消息:
hello packet:1:(0) Document is empty hello packet:1:(0) Start tag expected, '<' not found error: netconf: could not read hello error: did not receive hello packet from server error: Error in creating the session with "fivestar" server No connection - exiting script
连接错误的潜在原因包括:
要连接的设备或接口已关闭或不可用。
远程设备的 IP 地址或 DNS 名称的脚本参数不正确。
建立连接之前,超过了连接超时值。
远程设备的用户身份验证无效或输入不正确。
您尝试建立 NETCONF 会话,NETCONF on SSH 未在 NETCONF 服务器所在的设备上启用,或者其他端口上未启用 NETCONF。
解决 方案
确保远程设备已启动并运行,并且用户能够访问该设备。还要验证在执行脚本时,是否为远程设备的 IP 地址或 DNS 名称提供了正确的参数。
对于 NETCONF 会话,请确保在 NETCONF 服务器所在的设备上通过 SSH 启用了 NETCONF。由于示例程序没有为 NETCONF 会话指定特定的端口号,因此会话在默认的 NETCONF-over-SSH 端口 830 上建立。要验证在运行 Junos OS 的设备的默认端口上是否启用了基于 SSH 的 NETCONF,请在远程设备上输入以下操作模式命令:
bsmith@fivestar> show configuration system services netconf { ssh; }
netconf
如果远程设备上没有配置层次结构,在配置模式下发出以下语句,以在默认端口上通过 SSH 启用 NETCONF:
[edit] bsmith@fivestar# set system services netconf ssh bsmith@fivestar# commit
netconf
如果配置层次结构指定了默认端口以外的端口,请将端口号包含在您传递到函数的 jcs:open()
XML 节点集中。例如,为端口 12345 上的 SSH 上的 NETCONF 配置了以下设备:
bsmith@fivestar> show configuration system services netconf { ssh { port 12345; } }
要对备用端口创建 NETCONF 会话,请将新端口号包含在 XML 节点集中。
var $netconf := { <method> "netconf"; <username> "bsmith"; <port> "12345"; } var $connection = jcs:open($remote-host, $netconf); ...
对配置锁定错误进行故障排除
问题
该脚本会生成以下其中一条错误消息:
configuration database locked by: root terminal p0 (pid 24113) on since 2011-07-11 11:48:06 PDT, idle 00:07:59
Users currently editing the configuration: root terminal p1 (pid 24279) on since 2011-07-11 12:28:30 PDT {master}[edit]
configuration database modified
解决 方案
另一个用户当前已锁定候选配置,或者已修改候选配置,但尚未提交此配置。等待锁释放,然后执行程序。
对配置语法错误进行故障排除
问题
以下错误消息会打印到 CLI:
Configuration error: syntax error Configuration not committed.
检查结果树,了解更多信息。在这种情况下,结果树将显示以下错误消息:
<rpc-error> <error-severity> error </error-severity> <error-info> <bad-element> ftp2 </bad-element> </error-info> <error-message> syntax error </error-message> </rpc-error>
解决 方案
<bad-element>
标记元素表示配置语句无效。更正配置层次结构并运行脚本。在此示例错误中,用户输入了标记<ftp2>
,而不是<ftp>
。由于这不是配置中可接受的元素,NETCONF 服务器会返回错误。