0

私は現在、ジュニパー、シスコのルーターとやり取りするpexpect python モジュールを使用して実装しています。子アプリケーションを生成し、「show version」などのコマンドを実行して、出力をログに記録します。

このプロセスを実行するためのより良い方法を探しています。スイッチ側で何かが変更された場合 (OS アップグレード後のプロンプトのスペースまたはコロン)、プログラムが機能しなくなるためです。ジュニパーにはそのような操作を実行するための API があると思いますが、シスコにはないと思います。これを HP などの他のスイッチにも拡張する必要があります。

これにアプローチできる一般化された方法はありますか?

pexpect よりも標準的なアプローチが存在する場合は、必要に応じて、デバイスごとに異なるコードを書くことも気にしません。

ありがとう

4

2 に答える 2

2

理想的な世界では、NETCONF がソリューションになります。これは基本的に、(一連の) ワイヤ プロトコルと、ネットワーク デバイスに対する get/set/exec 要求用の XML エンコーディングです。

見る:

JunOS の最新バージョンは、古い独自のインターフェイスに加えて、これをサポートしています。

http://www.juniper.net/support/products/junoscript/

一部のシスコのハードウェアとソフトウェアの組み合わせでサポートされています。たとえば、NETCONF は 6500 sup720/sup2T の 12.2(33)SXI および 12.2SY/15.0SY トレインに存在します。NX-OS (Cisco Nexus) のすべてのバージョンが NETCONF をサポートしていると思います。

HPはわかりません。Extreme XOS がそれ以降のバージョンで、Extreme 独自の XML API に加えて NETCONF をサポートしていることは知っています。

ただし、NETCONF にはいくつかの問題があります。

  1. プロトコルは標準化されていますが、サポートされているデータ モデルは標準化されていません。したがって、さまざまなデバイスからの非常に異なる XML になります。デバイス固有のコードは引き続き必要です。しかし、少なくともスクリーンスクレイピングや悪用を期待する必要はなく、はるかに信頼性の高いエラー検出が得られます

  2. 一部のデバイス (Cisco IOS など) は、実際には内部が XML ではありません。XML は一連のルール ベースのパーサー (スクリーン スクレーパー) を使用して生成されますが、私のテストでは、これらは不完全であるかバグがあることがよくあります。たとえば、Cisco の主張に反して、「show run | format」は「XML をネイティブに生成」しません。Cisco の回線ベースの構成を XML に変換し、使用する多くの構成構造 (BGP ルーター構成のアドレス ファミリ サブスタンザなど) を壊します。最終的に、データに XML を使用せず、ラインベースの Cisco コマンド/構成に固執することになりました。これは引き続き解析する必要がありますが、少なくとも NETCONF コマンド フレーミングとエラー コードの恩恵を受けます。

  3. SSH 経由で NETCONF を実行できますが、多くのデバイスは依然として SSH キーベースのログイン (Cisco IOS) を実行しないため、ハードコードされたパスワードをいじる必要があります。

于 2011-10-19T17:24:19.070 に答える
2

これを行うには、一部のバージョンのexpectを使用することが受け入れられている方法です。ほとんどのベンダーから、ほとんどのネットワーキング デバイスとの端末対話を行うための成熟した OSS スクリプトがすでに存在します。同じ問題が存在しますが、ベンダーがプロンプトを変更すると、より多くの眼球がそれを見て、物事を更新しています.

RANCIDをチェックしてください。

以下は、RANCID に基づいて ASA で ACL ヒット数を収集するために私が作成したスクリプトの簡単な例です。

#!/usr/bin/perl

use strict;
use Getopt::Std;

my $usage = "Usage: gethitcnt.pl -c configfile -o outputdir\n\n";
my %opts;

getopts('hc:o:', \%opts);

my $login = sprintf "~%s\/bin\/clogin.in", $ENV{'HOME'};
my $loginrc = sprintf "~%s\/.cloginrc", $ENV{'HOME'};
my $cmdfile = sprintf "~%s\/cmd", $ENV('HOME');
my $date = getdate;
my ($config,$outdir);

unless (-e $login) {
 die "Cannot find $login\n\n";
}

unless (-e $loginrc) {
 die "Cannot find $loginrc\n\n";
}

if ($opts{h} or !$opts{c}) {
 die $usage;
}

if ($opts{o}) {
 $outdir = $opts{o};
} else {
 $outdir = $ENV{'PWD'};
}

if (-e $opts{c}) {
 $config = getconfig($opts{c});
} else {
 die "Cannot open config file $opts{c}\n\n";
}

foreach my $firewall (keys %$config) {
 foreach my $acl (@{$config->{$firewall}}) {
  open (CMD,>$cmdfile);
  print CMD "show access-list $acl\n";
  print CMD "clear access-list $acl counters\n";
  close (CMD);
  my $command = ($login,"-x",$cmdfile,$firewall)
  open (TMP,"$command |");
  my $outfile = sprintf "%s\/%s-%s-%s.txt", $outdir, $firewall, $acl, $date;
  open (OUTFILE,>$outfile);
  foreach my $line (<TMP>) {
   if ($line =~ /\s*(access-list.*\(hitcnt=\d+\))/) {
    print OUTFILE "$1\n";
   }
  }
  system ("rm",$cmdfile);
 }
}

sub getconfig {
 my $configfile = shift;
 open(CONFIG,$configfile);
 my $out;
 foreach (<CONFIG>) {
  chomp;
  my @$elements = split(/,/);
  my $host = shift(@$elements);
  $out->{$host} = $elements;
 }
 close(CONFIG);
 return($out);
}

sub getdate {
 my @time = localtime;
 my @abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
 my $month = $abbr[$time[4]];
 my $out = sprintf "%s-%d", $month, $time[3];
 return($out);
}
于 2011-09-30T14:15:05.663 に答える