예: 스크립트 내에서 연결에 대한 세션 프로토콜 지정
다음 예제는 원격 디바이스와의 연결을 생성할 때 Junos 자동화 스크립트 내에서 세션 프로토콜을 지정하는 방법을 보여줍니다. 특히, 예제 op 스크립트는 Junos OS를 실행하는 원격 디바이스와 NETCONF 세션을 설정하고, NETCONF 서버 기능을 검색 및 인쇄한 다음, 해당 디바이스에서 구성을 업데이트 및 커밋합니다.
요구 사항
Junos OS 릴리스 11.4 이상을 실행하는 라우팅, 스위칭 또는 보안 디바이스.
클라이언트 애플리케이션은 NETCONF 서버가 상주하는 디바이스에 로그인할 수 있습니다.
SSH를 통한 NETCONF 서비스는 NETCONF 서버가 상주하는 디바이스에서 활성화됩니다.
개요 및 스크립트
확장 기능에는 jcs:open()
Junos OS를 실행하는 디바이스의 Junos XML 프로토콜 서버 또는 SSH를 통한 NETCONF 서비스가 활성화된 디바이스의 NETCONF 서버로 세션을 생성하는 옵션이 포함됩니다. 다음 예제에서 스크립트는 Junos OS를 실행하는 원격 디바이스와 연결을 생성하고 NETCONF 세션을 설정합니다. 연결 및 세션이 성공적으로 설정되면 스크립트는 원격 디바이스의 구성을 업데이트하여 문을 [edit system services]
계층 수준에 추가합니다ftp
. 또한 스크립트는 NETCONF 서버의 세션 프로토콜과 기능을 검색하고 인쇄합니다.
스크립트는 원격 디바이스의 IP 주소 또는 호스트 이름인 인수 remote-host
1개를 사용합니다. arguments
변수는 스크립트의 전역 레벨에서 선언되므로 사용자가 상황에 맞는 도움말을 필요로 할 때 명령줄 인터페이스(CLI)에서 인수 이름과 설명을 볼 수 있습니다.
변수는 netconf
원격 디바이스에 대한 세션 프로토콜 및 연결 매개 변수를 지정하는 노드 집합입니다. 요소의 값은 <method>
SSHv2 연결을 통해 NETCONF 서버와의 세션을 설정하기 위해 "netconf"로 설정됩니다. 요소는 <username>
연결의 사용자 이름을 지정합니다. 사용자 이름을 지정하지 않고 연결에 필요한 경우 스크립트는 스크립트를 실행하는 사용자의 로컬 이름을 사용합니다. 이 예에서는 암호와 포트가 지정되지 않습니다. 인증에 암호가 필요한 경우 원격 디바이스는 스크립트 실행 중에 암호를 묻는 메시지를 표시해야 합니다. 스크립트는 기본 NETCONF 포트 830을 사용하여 세션을 설정합니다.
NETCONF 세션의 연결 및 설정이 성공하면 스크립트는 원격 프로시저 호출(RPC)을 실행합니다. RPC에는 후보 구성을 잠그고, 편집하고, 커밋하고, 잠금 해제하는 NETCONF 작업인 태그 요소 <lock>
, <edit-config>
, <commit>
, 가 <unlock>
포함되어 있습니다. 스크립트는 각 작업에 대한 RPC를 별도의 변수에 저장합니다. 각 RPC에 대한 결과도 별도로 저장되고 오류에 대해 구문 분석됩니다. 스크립트는 이전 단계가 성공한 경우에만 각 후속 단계를 실행합니다. 예를 들어, 스크립트가 구성을 잠글 수 없는 경우 구성을 편집, 커밋 또는 잠금 해제하기 위해 RPC를 실행하지 않습니다.
변수 rpc-edit-config
에는 구성을 수정하기 위한 NETCONF 작업인 태그 요소가 <edit-config>
포함되어 있습니다. 하위 요소 <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>
구성
절차
단계별 절차
스크립트를 다운로드, 사용 및 테스트하려면:To download, enable, and test the script:
XSLT 또는 SLAX 스크립트를 텍스트 파일에 복사하고, 파일 이름을 netconf-session.xsl 또는 netconf-session.slax 로 적절하게 지정한 다음, 디바이스의 /var/db/scripts/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는 원격 디바이스 fivestar에 연결 중입니다. 원격 디바이스에는 이중 라우팅 엔진이 있으므로
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
확인
장치가 제대로 작동하는지 확인하십시오.
Op 스크립트 실행 확인
목적
스크립트가 예상대로 작동하는지 확인합니다.
작업
CLI 및 op 스크립트 로그 파일에서 스크립트 출력을 검토합니다. 실행 중에 발생한 오류를 특히 기록해 둡니다. 기본 op 스크립트 로그 파일은 /var/log/op-script.log입니다. 로그 파일이 상당히 긴 경우, 명령에 옵션을 show log
추가하여 | last number-of-lines
표시를 제한하고 CLI에 인쇄할 줄 수를 지정합니다. 요소 내의 <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>
또한 op 스크립트를 실행할 때 옵션을 포함하여 | 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 서버의 기능에는 및 에 http://xml.juniper.net/netconf/junos/1.0
http://xml.juniper.net/dmi/system/1.0
정의된 표준 NETCONF 운영과 주니퍼 네트웍스 독점 확장이 모두 포함됩니다. 작업에 대한 commit
RPC 결과에는 하나의 경고가 포함되지만 커밋 작업은 여전히 성공적입니다.
구성 변경 사항 확인
목적
원격 디바이스의 구성 변경 및 커밋 로그를 확인하여 커밋이 성공했는지 확인합니다.
작업
원격 디바이스에서 작동 모드 명령을 실행하여 show configuration system services
구성의 계층 수준을 확인합니다 [edit system services]
. 스크립트가 성공하면 구성에 문이 포함됩니다 ftp
.
bsmith@fivestar> show configuration system services ftp; netconf { ssh; }
또한 커밋 로그를 검토할 수 있습니다. 원격 디바이스에서 운영 모드 명령을 실행하여 show system commit
커밋 로그를 확인합니다. 이 예에서 로그는 bsmith가 주어진 날짜와 시간에 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 서버가 상주하는 디바이스에서 SSH를 통한 NETCONF가 활성화되지 않았거나 다른 포트에서 활성화되었습니다.
솔루션
원격 디바이스가 가동되어 실행 중이고 사용자가 디바이스에 액세스할 수 있는지 확인합니다. 또한 스크립트를 실행할 때 원격 디바이스의 IP 주소 또는 DNS 이름에 대해 올바른 인수를 제공했는지 확인합니다.
NETCONF 세션의 경우, NETCONF 서버가 상주하는 디바이스에서 SSH를 통해 NETCONF를 활성화했는지 확인합니다. 예제 프로그램이 NETCONF 세션에 대한 특정 포트 번호를 지정하지 않기 때문에 세션은 기본 NETCONF-over-SSH 포트 830에 설정됩니다. Junos OS를 실행하는 디바이스의 기본 포트에서 NETCONF over SSH가 활성화되어 있는지 확인하려면 원격 디바이스에서 다음 운영 모드 명령을 입력합니다.
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>
tag 요소는 구성 문이 유효하지 않음을 나타냅니다. 구성 계층을 수정하고 스크립트를 실행합니다. 이 예제 오류에서 사용자는 <ftp2>
<ftp>
. 이는 구성에서 허용되는 요소가 아니므로 NETCONF 서버는 오류를 반환합니다.