#!/usr/bin/perl # # File: reload_vmps # Author: Dael Maselli - LNF - INFN # Date: 06 April 2004 # Purpose: Perform `download vmps` on vmps Cisco servers, # and fork for parallel `reconfirm vmps` on Cisco switches # # Changed: 13 May 2004 # Changes: control-c or `kill` don't stop the script, it will instead list # switches the script are waiting for in the forked reconfirmation. # To stop the script you have now to press control-4 or `kill -QUIT`. # Use `Term::ReadKey` instead of `system 'stty -echo'` to disable # passwords echoing. # # Changed: 15 Sep 2004 # Changes: Added the switch '-r' from command line to run only the forked # reconfirmation request but not the `download vmps` on servers # # Requires: Term::ReadKey ( included by default since Perl 5.6.1 ) # # Changed: 28 Feb 2006 # Changes: Also fork for `download vmps` on servers # # Requires: Term::ReadKey ( included by default since Perl 5.6.1 ) # Net::Telnet # Net::Telnet::Cisco # to download them look at: http://NetTelnetCisco.SourceForge.net/ # or: http://www.cpan.org # use Net::Telnet::Cisco; use Term::ReadKey; use File::Copy; print "--- RELOAD VMPS\n"; $vmpsdef = "/HIDDEN_FOR_INFN_SECURITY"; $vmpsrun = "/HIDDEN_FOR_INFN_SECURITY"; unless ( copy( $vmpsdef, $vmpsrun ) ) { print "VMPS file copy failed\n"; exit 1; } ############################################################################ # path to the file containing the list of the switches and reconfirmation # command, separated by at least one blank. One switch per line. # # Example:-- # swcriorog vmps reconfirm # swcrio vmps reconfirm # swdafne reconfirm vmps # swfinudage vmps reconfirm # ---------- $switch_list_file = "/HIDDEN_FOR_INFN_SECURITY"; # list of vmps server where to execute `download vmps` @host_server = ( 'swcalc2', 'swac1', 'swae2a', 'swlat', 'swleale1' ); ############################################################################# sub print_success($$) { ( $host, $result ) = @_; printf ("%-18s %s\n", $host, $result); } sub print_unsuccess($$) { ( $host, $result ) = @_; warn sprintf ("%-18s !!! %s !!!\n", $host, $result); } sub child_exit { #kill('USR1', $dpid); exit; } $dpid = $$; ReadMode('noecho'); # don't echo print "Enter Login password: "; chomp ( $lpass = ); print "\n"; print "Enter Enable password: "; chomp ( $enapass = ); print "\n"; ReadMode(0); # back to normal $SIG{'QUIT'} = sub{ exit; }; $SIG{'INT'} = sub{ }; print "\n--- Use control-4 (QUIT) to exit.\n"; print "\n--- Download VMPS on servers... (press control-c to show waiting list)\n\n"; $todo = 0; foreach ( @host_server ) { last if $ARGV[0] && $ARGV[0] =~ /-r/; $host = $_; $chpid = fork(); if ( $dpid == $$ ) { $todo++; $cld_host{$chpid} = $host; } else { $SIG{'QUIT'} = sub{ exit; }; #print "child: i'm $$\n"; my $session = Net::Telnet::Cisco->new( Host => $host, Timeout => 60 ); #print "$host: Connected...\n"; $session->prompt('/(?m:^[\w.-]+\s?(?:\(config[^\)]*\))?\s?[\$#> ]\s?(?:\(enable\))?\s*$)/'); $session->errmode("return"); $session->login( Password => $lpass ); #print "$host: Logged in...\n"; if ($session->enable( $enapass ) ) { #print "$host: Enabled...\n"; $command = 'download vmps'; #print "$host: Running '$command'...\n"; $std_prompt = $session->prompt; # print "-- $std_prompt --\n"; $session->prompt('/Errors \d+/'); @output = $session->cmd( String => $command, Timeout => 60 ); $session->prompt($std_prompt); ( $result = $session->last_prompt ) =~ s/\r|\n//g; $outmess = ''; foreach ( @output ) { s/^\s*(.*)(\n|\r)*$/$1/; $outmess .= "$host".$_."\n"; } $outmess =~ s/\n$/$result/; if ( $result =~ /Errors (\d+)/ && $1 == 0 ) { print_success( $host, "Downloaded"); } else { print_unsuccess( $host, "ALERT: Error Parsing vmps.db file... exiting" ); kill ( 'QUIT', $dpid ); exit; } } else { warn "$host Can't enable: " . $session->errmsg; print "\n!!! Wrong PASS? !!!\n\n"; kill ( 'QUIT', $dpid ); exit; } $session->close; undef $session ; &child_exit(); } } $SIG{'INT'} = sub{ print "\n-------- Waiting for:\n"; printf ("%-18s %s\n", "-SWITCH-", "-PID-"); foreach ( keys %cld_host ) { printf ( "%-18s %s\n", $cld_host{$_}, $_ ) if $cld_host{$_}; } print "-------- Use control-4 (QUIT) to exit.\n\n"; }; while ( $todo ) { $enddpid = wait(); $cld_host{$enddpid} = ''; $todo--; #print "Wait: $todo\n"; } $SIG{'INT'} = sub{}; open ( CLTNS, "<$switch_list_file" ); %host_client = (); my $todo = 0; while ( ) { s/\r|\n//g; next if /^\s*#/; if ( /^\s*(\S+)(\s+(.+))?\s*$/ ) { $host_client{$1} = 'reconfirm vmps'; $host_client{$1} = $3 if $3; #print $1." - ".$host_client{$1}."\n"; $todo++; #print "$1\n"; } } close ( CLTNS ); print "\n\n--- Reconfirm... (press control-c to show waiting list)\n\n"; $SIG{'USR1'} = sub{ }; foreach my $host ( keys %host_client ) { #print "Trying to $host...\n"; #print "daddy: i'm $$\n"; $chpid = fork(); if ( $dpid == $$ ) { $cld_host{$chpid} = $host; } else { $SIG{'QUIT'} = sub{ exit; }; #print "child: i'm $$\n"; sleep; $log = ''; $host_command = $host_client{$host}; my $session = Net::Telnet::Cisco->new( Host => $host, Timeout => 60 ); if ( $host_command !~ / / ) { $session->send_wakeup('connect'); } $session->errmode( "return" ); $log .= "Connected to $host... - "; $session->prompt('/(?m:^[\w.-]+\s?(?:\(config[^\)]*\))?\s?[\$#> ]\s?(?:\(enable\))?\s*$)/'); $res = ''; $res = $session->login( Password => $lpass ); unless ( $res ) { print "!! $host: Error Logging in.: $res".$session->last_prompt."\n"; &child_exit; } $log .= " Logged in... - "; if ($session->enable( $enapass ) ) { # $session->ignore_warnings(1); $log .= "Enabled... - "; $command = $host_command; $log .= "Running '$command'... - "; if ( $session->cmd( String => $command, Timeout => 10 ) ) { #print "\n".$outmess."\n" if $outmess; #print $log."done.\n"; #print "$host -> Done.\n"; } else { print "!! $host: Error running '$command'\n"; } $command = 'show vmps'; $log .= "Running '$command'... - "; if ( $session->cmd( String => $command, Timeout => 10 ) ) { my $result = "Error running '$command'"; $to = 0; do { sleep (1); if ( $res = join ( '', $session->cmd( $command ) ) ) { unless ( $res =~ /(vmps action:(\W)*(.*)(\n|$))/i ) { print_unsuccess($host, "Error running '$command': $res"); &child_exit(); } $result = $3; } else { print_unsuccess($host, "Error running '$command'"); &child_exit; } } until ( $result !~ /progress/i && $to++ < 120 ) ; if ( $result !~ /success/i ) { print_unsuccess($host, $result); } else { print_success($host, $result); #print "$host: VMPS: $result\n"; } } else { print_unsuccess($host, "Error running '$command'"); } } else { print_unsuccess($host, "Can't enable: " . $session->errmsg); } $session->close; undef $session ; &child_exit; } } $SIG{'INT'} = sub{ print "\n-------- Waiting for:\n"; printf ("%-18s %s\n", "-SWITCH-", "-PID-"); foreach ( keys %cld_host ) { printf ( "%-18s %s\n", $cld_host{$_}, $_ ) if $cld_host{$_}; } print "-------- Use control-4 (QUIT) to exit.\n\n"; }; kill 'USR1', $_ foreach keys %cld_host ; while ( $todo ) { $enddpid = wait(); $cld_host{$enddpid} = ''; $todo--; #print "Wait: $todo\n"; }