X-Git-Url: http://git.rot13.org/?p=dell-switch;a=blobdiff_plain;f=dell-switch.pl;h=82debdaedb3074ce69bf4d348cc57e321b2edb5e;hp=081a19724b04013c2b8cdfa61f0218ef30381ff9;hb=HEAD;hpb=cdd290ae716924064ec25af855729e2eacf083c8 diff --git a/dell-switch.pl b/dell-switch.pl index 081a197..485d29c 100755 --- a/dell-switch.pl +++ b/dell-switch.pl @@ -3,65 +3,161 @@ use warnings; use strict; use autodie; +# example usage as pipe: +# ./ips | sed 's/^/ping /' | NO_LOG=1 ./dell-switch.pl sw-dpc + use Net::OpenSSH; use Data::Dump qw(dump); -use List::Util qw(first); -use Time::HiRes; +use Time::HiRes qw(sleep); our $login; our $passwd; +our $debug = $ENV{DEBUG} || 0; +use lib '.'; require 'config.pl'; #$Net::OpenSSH::debug = ~0; -my $ip = shift @ARGV || '10.20.0.2'; +my $ip = shift @ARGV || die "usage: $0 IP command[ command ...]\n"; +$ip = $1 if `host $ip` =~ m/has address (\S+)/; my @commands = @ARGV; -@commands = unless @commands; +if ( ! @commands && ! -t STDIN && -p STDIN ) { # we are being piped into + while(<>) { + push @commands, $_; + } +} else { + @commands = unless @commands; +} -my $ssh = Net::OpenSSH->new('auto@'.$ip); +warn "\n## ssh $ip\n"; +my $ssh = Net::OpenSSH->new($ip, user => $login, passwd => $passwd, + ssh_cmd => '/usr/bin/ssh1', # apt-get install openssh-client-ssh1 + master_opts => [ + -o => "StrictHostKeyChecking=no", + -F => '/home/dpavlin/dell-switch/ssh1-config' + ], + default_ssh_opts => [ + -o => "StrictHostKeyChecking=no", + -F => '/home/dpavlin/dell-switch/ssh1-config' + ], +); my ($pty ,$pid) = $ssh->open2pty(); - -open my $log, '>', '/tmp/dell.log'; +if ( ! $pty ) { + warn "ERROR: can't connect to $ip, skipping"; + exit 0; +} my $buff; -while(1) { +sub send_pty { + my $string = shift; + sleep 0.05; # we really need to wait for slow PowerConnect 5324 + foreach (split //, $string) { + print STDERR "[$_]" if $debug; + syswrite $pty, $_; + #$pty->flush; + sleep 0.01; + + sysread $pty, my $echo, 1; + print STDERR $echo; + $buff .= $echo; + } +} + +mkdir 'log' unless -d 'log'; + +chdir 'log'; + +sub save_log { + my ($ip, $hostname, $command, $buff) = @_; + + return unless $command; + return if $ENV{NO_LOG}; + + my $file = "${ip}_${hostname}_${command}.log"; + open my $log, '>', $file; + $buff =~ s/\r//gs; # strip CR, leave LF only + print $log $buff; + if ( -e '.git' ) { + system 'git', 'add', $file; + system 'git', 'commit', '-m', "$ip $hostname", $file; + } +} + +my $command; +my @commands_while = ( @commands ); + +while() { my $data; my $read = sysread($pty, $data, 1); print STDERR $data; $buff .= $data; if ( $buff =~ m/User Name:/ ) { - print $pty "$login\n"; + send_pty "$login\n"; $buff = ''; } elsif ( $buff =~ m/Password:/ ) { - print $pty "$passwd\n"; + send_pty "$passwd\n"; $buff = ''; - } elsif ( $buff =~ m/#$/ ) { + } elsif ( $buff =~ m/[\n\r\b]([\w\-\(\)\/]+)#\s*$/ ) { + # config interface needs / in prompt + my $hostname = $1; if ( $buff ) { - print $log $buff; + save_log $ip, $hostname, $command, $buff; $buff = ''; } - if ( my $command = shift @commands ) { - $command .= "\n" unless $command =~ m/\n$/; - warn ">> $command\n"; - print $pty "$command"; + if ( $command = shift @commands_while ) { + $command =~ s/[\n\r]+$//; + send_pty "$command\n"; $buff = ''; } else { - print $pty "exit\n"; + send_pty "exit\n"; close($pty); last; } } elsif ( $buff =~ m/% Unrecognized command/ ) { exit 1; - } elsif ( $buff =~ s{More: , Quit: q, One line: }{} ) { - print $pty " "; - } elsif ( $buff =~ s{\e\[0m\r\s+\r}{} ) { + } elsif ( $buff =~ m/% Invalid input detected at .* marker/ ) { + + # try to rewrite command differences + + if ( $command =~ m/show lldp neighbors/ ) { + unshift @commands_while, 'show lldp remote-device all'; + undef $command; # don't save this command + $buff = ''; + } + + warn "# commands_while = ",dump( \@commands_while ); + + } elsif ( $buff =~ s{More: , Quit: q.*One line: \s*}{} ) { + send_pty " "; + } elsif ( $buff =~ s{\Q--More-- or (q)uit\E}{} ) { + send_pty " "; + } elsif ( $buff =~ s{\r\s{18}\r}{} ) { + # strip spaces delete after more prompt + } elsif ( $buff =~ s{\e\[0m\s*\r\s+\r}{} ) { + # nop + } elsif ( $buff =~ m/^[\r\n]+[\w\-]+>$/ ) { + send_pty "enable\n"; + } elsif ( $buff =~ m{\QOverwrite file [startup-config] ?[Yes/press any key for no]....\E} ) { + send_pty "y"; + $buff = ''; + } elsif ( $buff =~ s{Management access will be blocked for the duration of the transfer.*Are you sure you want to start\? \(y/n\) }{}s ) { + send_pty 'y'; + } elsif ( $buff =~ s{\QThis command will reset the whole system and disconnect your current session.\E}{}s ) { # reload + warn "\nRELOAD detected\n"; + sleep 0.5; + send_pty 'y'; + } elsif ( $buff =~ m{MikroTik RouterOS} ) { + warn "\nERROR: don't know how to talk to MicroTik - ABORTING"; + exit 0; } } __DATA__ +show system show arp show vlan show running-config -show bridge address-table +show bridge address +show interfaces status