This took a bit of hacking of the RANCID code to deal with - nothing terribly complicated, I basically run one remote show context
up front and use the output from this to build the command list for the rest of the script.
Here are a few code snippets to show what I did (sorry about the funky formatting, I'm new to this site and don't know all the tricks yet):
\##### Main
\# Get the list of contexts from the FW. fwsmlogin handles multi-context ASAs.
open(INPUT,"fwsmlogin -t $timeo -c \"changeto system;show context\" $host </dev/null |") || die "fwsmlogin failed for $host: $!\n";
$ContextFlag = 0;
$ModeFlag = 0;
while (<INPUT>) {
tr/\015//d;
print STDERR ("Processing line: $_") if ($DEBUG);
if ( /^Context Name/ ) {
$ContextFlag = 1;
if ( / Mode / ) {$ModeFlag = 1}
}
if ( /Connection.*closed/ ) {
print STDERR ("\nDEBUG: Connection closed\n\n") if ($DEBUG);
$clean_run=1;
last;
}
if ( /^Error:/ ) {
print STDOUT ("$host fwsmlogin error: $_");
print STDERR ("$host fwsmlogin error: $_") if ($DEBUG);
$clean_run=0;
last;
}
if ( /^Total active Security Contexts: (\d+)/ ) {
$ContextCount = $1;
last;
}
if ( $ContextFlag ) {
if ( $ModeFlag && /^.(\S+)\s+\S+\s+\S+\s+\S+\s+\S+$/ ||
!$ModeFlag && /^.(\S+)\s+\S+\s+\S+\s+\S+$/ ) {
print STDERR ("$host matched context $1\n") if ($DEBUG);
push @ContextList, $1;
next;
}
}
}
close INPUT;
print STDERR ("\nDEBUG: Preprocessing found $ContextCount contexts: @ContextList\n\n") if ($DEBUG);
if (scalar @ContextList ne $ContextCount) {
print STDERR ("\nERROR: Context count mismatch, count = $ContextCount, List = @ContextList\n\n");
exit 1;
}
%commands=(
'changeto context' => "ChangeContext",
'changeto system' => "IgnoreOutput",
'dir all-filesystems' => "DirAll",
'show context' => "ShowFWContext",
'show failover' => "ShowFailover",
'show mode' => "ShowMode",
'show resource acl-partition' => "ShowResourceACL",
'show resource allocation' => "ShowResourceAlloc",
'show resource partition' => "ShowResourcePart",
'show resource rule' => "ShowResourceRule",
'show resource usage' => "ShowResourceUsage",
'show run' => "ShowRun",
'show version' => "ShowVersion"
);
.
.
.
\## Add the commands to pull the config for each context
foreach my $context (@ContextList) {
$commands{"changeto context $context"} = "ChangeContext";
push @commands, "changeto context $context", "show failover", "show run";
}
$cisco_cmds=join(";",@commands);
$cmds_regexp=join("|",@commands);
I think this is all you really need to handle multiple contexts - if you're reasonably familiar with Perl it shouldn't be too hard to see how this works.
As an aside, I've also moved most of the subroutines into separate libraries, so when working on custom versions I can include the needed ones with appropriate "use lib" and "use" statements - for example customized scripts for CatOS devices will have this:
use lib '/home/rancid/lib';
use RANCIDsubs;
use CatOSsubs;
while for IOS devices we replace "use CatOSsubs" with "use IOSsubs"; for our ACE30 and ACE4710 devices with "use ACEsubs"; for Force10 switches with "use F10subs", etc. This makes it a lot easier to write custom RANCID scripts for whatever purpose you need.
As for fwsmlogin, over the years I've created many customized versions of clogin for various other device types; fwsmlogin is one of these. It's not very different from clogin - I mostly added comments and deleted unneeded code (for example "proc label", which is unnecessary since we don't use Xterm). The only important change is right at the end of this script, as the command needed on the firewalls to disable paging is different from that needed in IOS/CatOS.
To create your own fwsmlogin, edit a copy of clogin, find the "elseif { $do_script }" line near the end of of the file, and change the section that follows to look like this:
:
:
} elseif { $do_script } {
send "term pager 0\r"
sleep 0.2
expect -re $prompt {}
source $sfile
close
} else {
:
:
Your formatting may look different, but it shouldn't be too hard to figure this out.
It appears that you have autoenable
switched on in your config, which indicates that the username you're using (admin
) already has "enable" privilege. If you have the opposite autoenable * 0
, RANCID will issue an enable
command, with the password you've defined.
I believe the reason it behaves differently when you run it by hand on sw-dc-tor-1.cbr.net.wit
is that this hostname ends in '.wit' and so doesn't match the *.net
you have in your .cloginrc
which triggers the autoenable
.
See http://www.shrubbery.net/rancid/man/cloginrc.5.html
Best Answer
This has been fixed in upstream and is no longer relevant. I am closing it.