DX NetOps

 View Only
  • 1.  Config Capture of Cisco Switch Via SSH(Perl Script) in Spectrum(NCM)

    Posted Jul 31, 2014 03:47 AM

    Hi

     

    We want to take configuration backup of Cisco( CAT37XXSTACK) switch in Spectrum via SSH not telnet. I have created a new device family and customized the perl script as below , but I am getting an error of use of unintialized value in concatenation  . Has anyone able to achieve it via ssh ? SSH is enabled on the device .

     

     

     

    #!/opt/SPECTRUM/bin/perl -w

     

      # This script will capture the running configuration of a

      # Cisco OS device through an SSH session and print it to STDOUT.

      #

      # Error Codes:

      #   0   = Success

      #   255 = Usage error

      #   254 = Invalid timeout value

      #   252 = Login error

      #   249 = Exec prompt not found error

      #   244 = Error retrieving configuration

      #   245 = Insufficient privileges

      #   253 = Unexpected output

      #

     

      use strict;

      use warnings;

      use Net::SSH::Expect;

     

     

     

      ### Main ###

      if( $#ARGV != 4 && $#ARGV != 5 )

      {

              print "Usage: capture_running.pl <device IP> <user> <pass> <enable_pass>

      <login_timeout_in_seconds> <capture_timeout_in_seconds>\n";

              print STDERR "Usage:  capture_running.pl <deviceIP> <user> <pass>

      <enable_pass> <login_timeout_in_seconds> <capture_timeout_in_seconds>\n";

              exit 255;

      }

      elsif( $ARGV[4] < 1 || $ARGV[4] > 600 )

      {

              print "$ARGV[4] is the login timeout and must be an int between 1 and 600  seconds\n";

              print STDERR "$ARGV[4] is the login timeout and must be an int between 1 and  600 seconds\n";

              exit 254;

      }

      elsif( $#ARGV == 5 && ( $ARGV[5] < 1 || $ARGV[5] > 600 ) )

      {

              print "$ARGV[5] is the capture timeout and must be an int between 1 and 600  seconds\n";

              print STDERR "$ARGV[5] is the capture timeout and must be an int between 1  and 600 seconds\n";

              exit 254;

      }

      else

      {

              my $capture_timeout = $ARGV[4];

              if( $ARGV[5] )

              {

                 $capture_timeout = $ARGV[5];

              }

     

              my $errorCode = 1;

              my @data;

              my $errorString = "\nHost $ARGV[0]:  \n";

     

              ($errorCode, @data) = GetConfig( $ARGV[0], $ARGV[1], $ARGV[2], $ARGV[3],

                                               $ARGV[4], $capture_timeout );

     

              if( $errorCode == 0 )

              {

                  # Success.  The running configuration

                  # content is in the data variable

     

                  foreach ( @data ) { print "$_\n" }; # print the configuration to STDOUT

                  exit 0;

              }

              else

              {

                  print STDERR $errorString;

     

                  if( $errorCode == 245 )

                  {

                      print STDERR join " ", @data, "\nEnsure that the device user has

      sufficient privileges to disable paging and view the config\n";

                  }

                  else

                  {

                      print STDERR join " ", @data, "\n";

                  }

     

                  exit $errorCode;

              }

      }

     

      exit 0;

     

      sub GetConfig

      {

              my $deviceIP=shift;

              my $user=shift;

              my $pass=shift;

              my $epass=shift;

              my $login_timeout=shift;

              my $capture_timeout=shift;

              my @config;

              my $msg;

     

              my $ssh = Net::SSH::Expect->new ( host => $deviceIP,

                                                user => $user,

                                                password=> $pass,

                                                raw_pty => 1,

                                                no_terminal => 0,

                                                timeout => $login_timeout

                                              );

     

              my $login_output;

              eval { $login_output = $ssh->login(); };

      

              if( $@ )

              {

                  $msg = "Login has failed. Output: $login_output";

                  return( 252, $msg );

              }

     

              # login output should contain the right prompt characters

              if( $login_output !~ /\>\s*\z/ )

              {

                  $msg = "Login has failed. Didn't see device prompt as expected.";

                  $ssh->close();

                  return( 252, $msg );

              }

     

              if( $login_output !~ /\>\s*\z/ )  # Replace '#' is the prompt character here

              {

      #            we don't have the '#' prompt, means we still can't exec commands

                   $msg = "Exec prompt not found.";

                   $ssh->close();

                   return( 249, $msg );

              }

      

        my $elogin = $ssh->exec("en");

      

        my $elogin2 = $ssh->exec($epass);

      

     

        if( $elogin2 !~ /\#\s*\z/ )  # Replace '#' is the prompt character here

        {

                 $msg = "Exec prompt not found.";

                   $ssh->close();

                   return( 249, $msg );

        }

     

              # disable paging

              # different commands for different devices, if they don't

              # work then we will get messages about problems later

              # specifically the "No prompt after 'sh run'" error

              # errmsg doesn't get set when these error and if we use print

              # and getlines to read for errors it causes problems with print "sh run"

              # later.

      # $ssh->exec( "term pager 0" );

              my $paging = $ssh->exec( "term pager 0" );

              if ( $paging =~  /\s?%\s/ )

              {

                  $msg = "Unable to set terminal size to 0 - Insufficient privileges";

                  $ssh->close();

                      return( 245, $msg);

              }

     

              $ssh->send( "sh run" );

              $ssh->timeout( $capture_timeout );

              $ssh->peek(0);

     

              while( my $line = $ssh->read_line() )

              {

                  # get configuration content

     

                  if( $line !~

                      /sh run|Building configuration|Current configuration|^\s*$/ )

                  {

                      push @config, $line;

                  }

              }

     

              if( @config <= 0 )

              {

                  $msg = "No data retrieved, the capture timeout may be too low.";

                  $ssh->close();

                  return( 244, $msg );

              }

     

              if( scalar grep { $_ =~ /^%/ } @config )

              {

                  # Ensure show running actually returned the config and not an error

                  # message containing '%'

                  return( 245, @config );

              }

     

              return( 0, @config ); # everything was okay, return the captured data

      }



  • 2.  Re: Config Capture of Cisco Switch Via SSH(Perl Script) in Spectrum(NCM)

    Posted Jul 31, 2014 08:42 AM

    Does it tell you which line the error occurs on? Usually this happens because you're using 'use strict;use warnings'. But those are good to have because they prevent you from making mistakes that could cause bigger problems.



  • 3.  Re: Config Capture of Cisco Switch Via SSH(Perl Script) in Spectrum(NCM)

    Posted Jul 31, 2014 10:07 AM

    SSH_Login.JPGThanks for the reply Stuart  , i have attached the screenshot , it throws error on line 112.



  • 4.  Re: Config Capture of Cisco Switch Via SSH(Perl Script) in Spectrum(NCM)

    Posted Jul 31, 2014 12:20 PM

    Ok, here's where it's breaking down:

    On line 50, the code executes the GetConfig subroutine, which tries to logon to the device and get the data. The subroutine returns two values: $errorCode (a scalar/number) and @data (an array).

    The GetConfig subroutine then attempts to connect to the device: eval { $login_output = $ssh->login(); }; The results of this are stored in the temporary array $@.

    Then the GetConfig subroutine checks to see if login fails by checking the length of the $@ array. If the array has something in it, a message is constructed by concatenating "Login has failed. Output: " with the variable $login_output.

    Then the message ($msg) is returned along with the error code 252. However, your script doesn't get this far because the variable $login_output hasn't been set to anything.

    The returned error code and message are stored in the $errorcode scalar and @data array.

    Since $errorcode is not 0, the code prints the value of $errorstring (in this case '\nHost 10.106.64.30:  \n') then joins all the elements of the @data array (separated with spaces) and prints that out to the screen.

     

    So the problem is likely with this line:

    eval { $login_output = $ssh->login(); };

     

    You should be able to run this from your command line like this to see it all happening:

    capture_running.pl <device IP> <user> <pass> <enable_pass> <login_timeout_in_seconds> <capture_timeout_in_seconds>

     

    I hope this helps. I'm not an expert on the Net::SSH:Expect module, so I can't really help there.

     

    You might find this discussion related: Re: capture start-upconfig from Cisco devices to Spectrum.



  • 5.  Re: Config Capture of Cisco Switch Via SSH(Perl Script) in Spectrum(NCM)

    Posted Aug 21, 2014 06:32 AM

    Hello, I am having same kind of problem.

     

        I have checked and it seems that the problem is that you can´t connect from SpectroSERVER to the device you are trying.

     

        Check if you have SSH access from SS to device. (On linux it is: "ssh -l username IP_ADDRESS")

     

        Once you solve it should work.

     

    Regards, Juan