このページの目次
Perl クライアント・アプリケーションでの Junos XML プロトコル・サーバー応答の解析とフォーマット
Junos XML プロトコル Perl クライアント アプリケーションでは、リクエスト送信の最後のステップとして、Junos XML プロトコル サーバーからの応答にエラーがないことを確認します。その後、応答をファイル、画面、またはその両方に書き込むことができます。応答が操作クエリに対するものである場合、アプリケーションは通常 XSLT を使用して、出力を HTML や書式設定された ASCII テキストなどのより読みやすい形式に変換します。応答が設定データで構成されている場合、アプリケーションはその応答をXML(Junos XMLプロトコルサーバーからデフォルトで生成されるJunos XMLタグ要素)として保存するか、フォーマットされたASCIIテキストに変換することができます。
次のセクションでは、解析と書式設定のオプションについて説明します。
操作応答の解析と書式設定
Junos XMLプロトコルのPerlディストリビューションには、Junos OSを搭載したデバイスでさまざまな機能を実行するサンプルPerlスクリプトがいくつか含まれています。 以下の diagnose_bgp.pl および get_chassis_inventory.pl サンプル・スクリプトのコード・サンプルでは、XSLT を使用して、Junos XML プロトコル・サーバーからの操作応答を読みやすい形式に変換しています。機能サブセクションの詳細な説明は、完全なコード サンプルの後に続きます。
# Get the name of the output file
my $outputfile = $opt{o} || "";
# Retrieve the XSLT file
my $xslfile = $opt{x} || "xsl/text.xsl";
if ($xslfile && ! -f $xslfile) {
die "ERROR: XSLT file $xslfile does not exist";
#Get the xmlfile
my $xmlfile = "$deviceinfo{hostname}.xml";
$res->printToFile($xmlfile);
my $nm = $res->translateXSLtoRelease('xmlns:lc', $xslfile, "$xslfile.tmp");
if ($nm) {
print "Transforming $xmlfile with $xslfile...\n" if $outputfile;
my $command = "xsltproc $nm $deviceinfo{hostname}.xml";
$command .= "> $outputfile" if $outputfile;
system($command);
print "Done\n" if $outputfile;
print "See $outputfile\n" if $outputfile;
}
else {
print STDERR "ERROR: Invalid XSL file $xslfile\n";
}
上記のコード サンプルの最初の行は、スクリプトがコマンド ラインからオプションを読み取って -o 、XSLT 変換の結果を書き込むファイルの名前を取得する方法を示しています。
my $outputfile = $opt{o} || "";
スクリプトは、XSLT ファイルを使用して出力を変換します。 -x スクリプトの呼び出し時にコマンド ライン オプションが含まれている場合、スクリプトはオプションで指定された XSLT ファイルを使用します。それ以外の場合は、コードで指定された既定の XSLT ファイルを使用します。ファイルが存在しない場合、スクリプトは終了します。次の例は、 diagnose_bgp.pl スクリプトからのものです。
my $xslfile = $opt{x} || "xsl/text.xsl";
if ($xslfile && ! -f $xslfile) {
die "ERROR: XSLT file $xslfile does not exist";
XSLT ファイルの例については、Junos XML プロトコル Perl ディストリビューションの以下のディレクトリを参照してください。
examples/diagnose_bpg/xsl ディレクトリには、diagnose_bpg.pl スクリプト用の XSLT ファイルが含まれています。dhtml.xsl は動的 HTML を生成し、html.xsl は HTML を生成し、text.xsl は ASCII テキストを生成します。
example/get_chassis_inventory/xsl ディレクトリには、get_chassis_inventory.pl スクリプト用の XSLT ファイルが含まれています。chassis_inventory_csv.xsl はカンマ区切り値のリストを生成し、chassis_inventory_html.xsl は HTML を生成し、chassis_inventory_xml.xsl は XML を生成します。
実際の解析操作は、変数$xmlfileを.xml形式のdevice-nameファイル名に設定し、printToFile関数を呼び出してJunos XMLプロトコルサーバーのレスポンスをファイルに書き込みます(printToFile関数はモジュールでXML::DOM::Parser定義されています)。
my $xmlfile = "$deviceinfo{hostname}.xml";
$res->printToFile($xmlfile);
次の行は、 translateXSLtoRelease 関数 (モジュールで Junos::Response 定義) を呼び出して、XSLT ファイル内の名前空間定義の 1 つを変更します。XSLT 1.0 仕様では、すべての XSLT ファイルが、変換されるデータで使用される既定の名前空間ごとに特定の値を定義する必要があるため、これが必要です。 xmlns Junos XML動作応答タグ要素の属性には、Junos OSバージョンを表すコードが含まれています(Junos OSリリース20.4の初期バージョンの20.4R1など)。異なるバージョンのJunos OSを実行しているデバイスからの動作応答タグ要素にも同じXSLTファイルを適用できるため、XSLTファイルですべてのバージョンに一致する名前空間値を事前に定義 xmlns することはできません。この translateXSLtoRelease 関数は、変数によって $xslfile 識別される XSLT ファイル内の名前空間定義を、Junos XML プロトコルサーバーの応答の値と一致するように変更します。結果の XSLT ファイルを変数に割り当てます $nm 。
my $nm = $res->translateXSLtoRelease('xmlns:lc', $xslfile, "$xslfile.tmp");
関数が成功したことを確認しtranslateXSLtoReleaseた後、は を呼び出しformat_by_xslt、コマンド文字列を作成して変数に$command代入します。コマンド文字列の最初の部分は、コマンドを呼び出し、xsltprocXSLT および構成データ ファイル (と $deviceinfo{hostname}.xmlに格納されている$nm) の名前を指定します。
if ($nm) {
print "Transforming $xmlfile with $xslfile...\n" if $outputfile;
my $command = "xsltproc $nm $deviceinfo{hostname}.xml";
変数が定義され $outputfile ている場合 (XSLT 変換の結果を格納するファイルが存在する場合)、スクリプトは変数に $command 文字列を追加して、コマンドの xsltproc 結果をファイルに書き込みます。(ファイルが存在しない場合、スクリプトは結果を標準出力 [stdout] に書き込みます)。次に system 、スクリプトは関数を呼び出してコマンド文字列を実行し、ステータス メッセージを stdout に出力します。
$command .= "> $outputfile" if $outputfile;
system($command);
print "Done\n" if $outputfile;
print "See $outputfile\n" if $outputfile;
}
関数が失敗した場合 translateXSLtoRelease (式が if ($nm) "false" と評価された場合)、スクリプトはエラーを出力します。
else {
print STDERR "ERROR: Invalid XSL file $xslfile\n";
}
設定データの解析と出力
examples\RDB ディレクトリの get_config.pl スクリプトは、サブルーチンを使用して outconfig 、Junos XML プロトコル サーバーから取得した設定データを、Junos XML タグ要素または書式設定された ASCII テキストとしてファイルに書き込みます。
サブルーチンは outconfig 4 つのパラメーターを取ります。出力ファイルを保存するディレクトリ、デバイスのホスト名、Junos XMLプロトコルサーバーから返されるXML DOMツリー(設定データ)の3つに値が定義されている必要があります。4 番目のパラメータは、設定をフォーマット済みの ASCII テキストとして出力するかどうかを示し、要求された出力が Junos XML タグ要素の場合は NULL 値になります。次のコード サンプルでは、スクリプトは 4 つのパラメーターの値を取得し、サブルーチンに outconfig 渡します。各行の詳細な説明は、完全なコード サンプルの後に続きます。
my(%opt,$login,$password);
getopts('l:p:dm:hit', \%opt) || output_usage();
output_usage() if $opt{h};
my $basepath = shift || output_usage;
my $hostname = shift || output_usage;
my $config = getconfig( $hostname, $jnx, $opt{t} );
outconfig( $basepath, $hostname, $config, $opt{t} );
上記のサンプル コードの最初の行で、 get_config.pl スクリプトは次のステートメントを使用して 、サブルーチンの outconfig 4 つのパラメーターの値を取得します。
ユーザーがコマンドラインでオプションを指定する
-tと、サブルーチンはgetoptsそれをハッシュに%opt記録します。キーが$opt{t}付けられた値は、4 番目のパラメーターとしてサブルーチンに渡されますoutconfig。(コマンドラインからオプションを読み込む方法の詳細については、 Junos XML プロトコル Perl クライアントアプリケーションで対話的にパラメータを収集するを参照してください)。getopts('l:p:dm:hit', \%opt) || output_usage();次の行は、ハイフンで始まるオプションではないコマンドラインの最初の要素を読み取ります。変数に
$basepath値を割り当て、サブルーチンからのoutconfig出力を含むファイルを格納するディレクトリの名前を定義します。変数値は、最初のパラメーターとしてサブルーチンに渡されますoutconfig。my $basepath = shift || output_usage;
次の行は、コマンド ラインの次の要素を読み取ります。変数に
$hostname値を割り当て、ルーティング、スイッチング、またはセキュリティデバイスのホスト名を定義します。変数値は、2 番目のパラメーターとしてサブルーチンに渡されますoutconfig。my $hostname = shift || output_usage;
次の行は、サブルーチンを呼び出して、
getconfig指定されたデバイス上のJunos XMLプロトコルサーバーから設定データを取得し、結果のXML DOMツリーを変数に割り当てます$config。変数値は、3 番目のパラメーターとしてサブルーチンに渡されますoutconfig。my $config = getconfig( $hostname, $jnx, $opt{t} );
次のコード サンプルでは、サブルーチンを呼び出して定義します outconfig 。サブルーチン内の各機能サブセクションの詳細な説明は、完全なコード サンプルの後に続きます。
outconfig( $basepath, $hostname, $config, $opt{t} );
sub outconfig( $$$$ ) {
my $leader = shift;
my $hostname = shift;
my $config = shift;
my $text_mode = shift;
my $trailer = "xmlconfig";
my $filename = $leader . "/" . $hostname . "." . $trailer;
print "# storing configuration for $hostname as $filename\n";
my $config_node;
my $top_tag = "configuration";
$top_tag .= "-text" if $text_mode;
if ($config->getTagName() eq $top_tag) {
$config_node = $config;
} else {
print "# unknown response component ", $config->getTagName(), "\n";
}
if ( $config_node && $config_node ne "" ) {
if ( open OUTPUTFILE, ">$filename" ) {
if (!$text_mode) {
print OUTPUTFILE "<?xml version=\"1.0\"?>\n";
print OUTPUTFILE $config_node->toString(), "\n";
} else {
my $buf = $config_node->getFirstChild()->toString();
$buf =~ s/($char_class)/$escapes{$1}/ge;
print OUTPUTFILE "$buf\n";
}
close OUTPUTFILE;
}
else {
print "ERROR: could not open output file $filename\n";
}
}
else {
print "ERROR: empty configuration data for $hostname\n";
}
}
サブルーチンの最初の outconfig 行は、サブルーチンが呼び出されたときに渡された 4 つのパラメーターを読み取り、それぞれをローカル変数に代入します。
outconfig( $basepath, $hostname, $config, $opt{t} );
sub outconfig( $$$$ ) {
my $leader = shift;
my $hostname = shift;
my $config = shift;
my $text_mode = shift;
サブルーチンは、サブルーチンの出力を書き込むファイルの名前を作成し、その名前を変数に割り当てます$filename。ファイル名は、最初の 2 つのパラメーター (ディレクトリ名とホスト名) と$trailer変数で構成され、/.xmlconfig という形式directory-namehostnameの名前になります。
my $trailer = "xmlconfig";
my $filename = $leader . "/" . $hostname . "." . $trailer;
print "# storing configuration for $hostname as $filename\n";
サブルーチンは、XML DOM ツリーの最初のタグがファイル内の構成データのタイプを正しく示していることを確認します。ユーザーがコマンドラインに オプションを含めた -t 場合、最初のタグは、ファイルにフォーマットされたASCII設定ステートメントが含まれているためです。それ以外の場合は、最初のタグ <configuration-text> がファイルにJunos XMLタグ要素が含まれているためです <configuration> 。サブルーチンは、 $top_tag 変数の値 $text_mode (サブルーチンの 4 番目のパラメーターとして渡された から値 opt{t}を取る) に応じて、変数を適切な値に設定します。サブルーチンは、 getTagName (モジュールで XML::DOM::Element 定義された) 関数を呼び出して、入力ファイル内の最初のタグの名前を取得し、その名前を変数の値 $top_tag と比較します。比較が成功すると、XML DOM ツリーが変数に割り当てられます $config_node 。それ以外の場合、サブルーチンは、XML DOM ツリーが有効な構成データではないため、エラーメッセージを出力します。
my $config_node;
my $top_tag = "configuration";
$top_tag .= "-text" if $text_mode;
if ($config->getTagName( ) eq $top_tag) {
$config_node = $config;
} else {
print "# unknown response component ", $config->getTagName( ), "\n";
}
次に、サブルーチンはいくつかのネスト if されたステートメントを使用します。最初の if ステートメントは、XML DOM ツリーが存在し、データが含まれていることを確認します。
if ( $config_node && $config_node ne "" ) {
... actions if XML DOM tree contains data ...
}
else {
print "ERROR: empty configuration data for $hostname\n";
}
XML DOM ツリーにデータが含まれている場合、サブルーチンは出力ファイルを書き込み用に開くことができるかどうかを検証します。
if ( open OUTPUTFILE, ">$filename" ) {
... actions if output file is writable ...
}
else {
print "ERROR: could not open output file $filename\n";
}
出力ファイルを書き込み用に開くことができる場合、スクリプトはそこに構成データを書き込みます。ユーザーがJunos XMLタグ要素を要求した場合(コマンドラインにオプションを含め-tなかったため、変数に値がありません)、スクリプトは出力ファイルの最初の行として文字列を書き込み、toString次に関数(モジュールでXML::DOM定義)を呼び出して、XML DOMツリーの各Junos XMLタグ要素を出力<?xml version=1.0?>ファイルの1行に$text_mode書き込みます。
if (!$text_mode) {
print OUTPUTFILE "<?xml version=\"1.0\"?>\n";
print OUTPUTFILE $config_node->toString( ), "\n";
ユーザーがフォーマットされたASCIIテキストを要求した場合、スクリプト getFirstChild は および toString 関数(モジュールで XML::DOM 定義)を呼び出して、各タグの内容を出力ファイルの独自の行に書き込みます。このスクリプトは、許可されていない文字 (ハッシュで %escapes 定義されている) を定義済みのエンティティ参照に置き換え、出力を出力ファイルに書き込み、出力ファイルを閉じます。(許可されない文字のセットを含むハッシュを定義する %escapes 方法については、 Junos XML プロトコル Perl クライアントアプリケーションでの許可されていない文字の変換を参照してください)。
} else {
my $buf = $config_node->getFirstChild( )->toString( );
$buf =~ s/($char_class)/$escapes{$1}/ge;
print OUTPUTFILE "$buf\n";
}
close OUTPUTFILE;