Ruby & Telnet & Cisco

Discussion in 'Ruby' started by Pablo Zorzoli, Mar 30, 2007.

  1. Pablo Zorzoli, Mar 30, 2007
    #1
    1. Advertising

  2. On Sat, Mar 31, 2007 at 12:48:22AM +0900, Pablo Zorzoli wrote:
    > Is there any approach similar to perl's Net:Telnet:Cisco [1] in ruby?
    > Has anyone nice experiences in this mix?


    Not that I'm aware of. But if you discover something please let me know -
    I'm going to have to do this myself in the next few weeks too.

    I was planning just to use plain Net::Telnet, which I think is good enough
    for what I need. I was also planning to try to make a wrapper for Net::SSH
    to make it provide an IO object that can be passed into Net::Telnet.

    Regards,

    Brian.
     
    Brian Candler, Mar 31, 2007
    #2
    1. Advertising

  3. Pablo Zorzoli

    Robert Dober Guest

    On 3/31/07, Brian Candler <> wrote:
    > On Sat, Mar 31, 2007 at 12:48:22AM +0900, Pablo Zorzoli wrote:
    > > Is there any approach similar to perl's Net:Telnet:Cisco [1] in ruby?
    > > Has anyone nice experiences in this mix?

    >
    > Not that I'm aware of. But if you discover something please let me know -
    > I'm going to have to do this myself in the next few weeks too.
    >
    > I was planning just to use plain Net::Telnet, which I think is good enough
    > for what I need.

    Please kindly let me know about this, I was trying to do this with
    Catalyst 29xx series Switches and a 2600 router, no luck so far, I
    guess the prompt, timeout selection is quite tricky :(

    Cheers
    Robert
    >I was also planning to try to make a wrapper for Net::SSH
    > to make it provide an IO object that can be passed into Net::Telnet.
    >
    > Regards,
    >
    > Brian.
    >
    >



    --
    You see things; and you say Why?
    But I dream things that never were; and I say Why not?
    -- George Bernard Shaw
     
    Robert Dober, Mar 31, 2007
    #3
  4. On Sat, Mar 31, 2007 at 10:40:15PM +0900, Robert Dober wrote:
    > >Not that I'm aware of. But if you discover something please let me know -
    > >I'm going to have to do this myself in the next few weeks too.
    > >
    > >I was planning just to use plain Net::Telnet, which I think is good enough
    > >for what I need.

    > Please kindly let me know about this, I was trying to do this with
    > Catalyst 29xx series Switches and a 2600 router, no luck so far, I
    > guess the prompt, timeout selection is quite tricky :(


    The best documentation is the source, /usr/lib/ruby/1.8/net/telnet.rb

    Make sure you call your code with a debug block, e.g. (untested)

    n = Net::Telnet(...)
    blk = proc { |str| $stderr << str }
    n.login("user", "password", &blk)
    n.cmd("show users", &blk)

    By adding &blk to all of the Net::Telnet methods, you'll get debugging
    output to the screen and you can see how far it's getting.

    IIRC, the default regexp for a prompt looks for '# ' and '> ' (i.e. with a
    trailing space). Typical Cisco prompt is 'router>' without the trailing
    space. So easy enough to fix: just pass in a suitable prompt regexp.

    Brian.
     
    Brian Candler, Apr 1, 2007
    #4
  5. Pablo Zorzoli

    Robert Dober Guest

    On 4/1/07, Brian Candler <> wrote:
    > On Sat, Mar 31, 2007 at 10:40:15PM +0900, Robert Dober wrote:
    > > >Not that I'm aware of. But if you discover something please let me know -
    > > >I'm going to have to do this myself in the next few weeks too.
    > > >
    > > >I was planning just to use plain Net::Telnet, which I think is good enough
    > > >for what I need.

    > > Please kindly let me know about this, I was trying to do this with
    > > Catalyst 29xx series Switches and a 2600 router, no luck so far, I
    > > guess the prompt, timeout selection is quite tricky :(

    >
    > The best documentation is the source, /usr/lib/ruby/1.8/net/telnet.rb
    >
    > Make sure you call your code with a debug block, e.g. (untested)
    >
    > n = Net::Telnet(...)
    > blk = proc { |str| $stderr << str }
    > n.login("user", "password", &blk)
    > n.cmd("show users", &blk)
    >
    > By adding &blk to all of the Net::Telnet methods, you'll get debugging
    > output to the screen and you can see how far it's getting.
    >
    > IIRC, the default regexp for a prompt looks for '# ' and '> ' (i.e. with a
    > trailing space). Typical Cisco prompt is 'router>' without the trailing
    > space. So easy enough to fix: just pass in a suitable prompt regexp.
    >
    > Brian.
    >

    Brian that is sound advice, but actually the problem is more or less
    the subtle details about the Cisco interface(1), like getting rid of
    the '---More---' or nonstandard login without user.

    I think that's why there are some modules around in other languages. I
    think it is a good possibility to share some findings and I might have
    a look at the Perl module some of these days.

    Cheers Robert
    >

    (1) used net/telnet for some remote control of old Unix systems
    without ssh quite often, the code is really easy to factorize, maybe
    it is too for Cisco, but given the complexity of the Cisco OS I doubt
    it :(, So the problem is not within Ruby but within Cisco.

    --
    You see things; and you say Why?
    But I dream things that never were; and I say Why not?
    -- George Bernard Shaw
     
    Robert Dober, Apr 1, 2007
    #5
  6. Pablo Zorzoli

    Martin Boese Guest

    --Boundary-00=_LN3DGl+5PS/LhCP
    Content-Type: Multipart/Mixed;
    boundary="Boundary-00=_LN3DGl+5PS/LhCP"

    --Boundary-00=_LN3DGl+5PS/LhCP
    Content-Type: text/plain;
    charset="iso-8859-1"
    Content-Transfer-Encoding: 7bit
    Content-Disposition: inline

    I don't know perl's cisco library, but this (see attached) is what I wrote to
    send commands to cisco routers and switches or fetch some values.

    To get it's running config for example I do this:

    ------------------------------------
    require 'ciscotelnet'

    c = CiscoTelnet.new("Host" => '10.253.1.8',
    "Password" => "users-password",
    "Enable" => "enable-password",
    "User" => "martin")

    c.open
    c.login
    c.enable
    c.cmd "terminal length 0"
    puts c.cmd("show run", 20)
    ------------------------------------

    Martin





    On Saturday 31 March 2007 13:40:15 Robert Dober wrote:
    > On 3/31/07, Brian Candler <> wrote:
    > > On Sat, Mar 31, 2007 at 12:48:22AM +0900, Pablo Zorzoli wrote:
    > > > Is there any approach similar to perl's Net:Telnet:Cisco [1] in ruby?
    > > > Has anyone nice experiences in this mix?

    > >
    > > Not that I'm aware of. But if you discover something please let me know -
    > > I'm going to have to do this myself in the next few weeks too.
    > >
    > > I was planning just to use plain Net::Telnet, which I think is good
    > > enough for what I need.

    >
    > Please kindly let me know about this, I was trying to do this with
    > Catalyst 29xx series Switches and a 2600 router, no luck so far, I
    > guess the prompt, timeout selection is quite tricky :(
    >
    > Cheers
    > Robert
    >
    > >I was also planning to try to make a wrapper for Net::SSH
    > > to make it provide an IO object that can be passed into Net::Telnet.
    > >
    > > Regards,
    > >
    > > Brian.




    --Boundary-00=_LN3DGl+5PS/LhCP
    Content-Type: application/x-ruby;
    name="ciscotelnet.rb"
    Content-Transfer-Encoding: 7bit
    Content-Disposition: attachment;
    filename="ciscotelnet.rb"

    require 'net/telnet'


    class CiscoTelnet
    require 'net/telnet'

    def initialize options
    @host = options["Host"] || "localhost"
    @user = options["User"] || "martin"
    @password = options["Password"] || "nopass"
    @enable = options["Enable"] || "nopass"
    @debug = options["Debug"] || false
    @prompt = nil
    end

    def debug_out(msg)
    $stdout.puts ">> " + msg if @debug
    end

    def debug_in(msg)
    $stdout.puts "<< " + msg if @debug
    end


    def open
    @socket = Net::Telnet.new("Host" => @host)
    end

    def close
    @socket.close
    end

    # returns last line received
    def expect(str)
    ret = @socket.waitfor("String" => str, "Timeout" => 10) { |rv| debug_in(rv) }
    return ret.split('\n').last.strip
    end

    # overwrite to match dynamic prompt
    def cmd(command, timeout=10)
    debug_out command
    return @socket.cmd("String" => command, "Match" => Regexp.new(Regexp.escape(@prompt)), "Timeout" => timeout) { |c| debug_in(c) }
    end

    def print(s)
    @socket.print(s) { |c| debug_out c }
    end

    def puts(s)
    @socket.puts(s) { |c| debug_out c }
    end

    def login
    expect "Username"
    puts @user
    expect "Password"
    puts @password
    @prompt = expect '>'
    $stdout.puts "prompt is " + @prompt if @debug
    end

    def enable
    puts "enable"
    expect "Password"
    puts @enable
    @prompt = expect '#'
    $stdout.puts "new prompt is " + @prompt if @debug
    end


    end



    --Boundary-00=_LN3DGl+5PS/LhCP--
    --Boundary-00=_LN3DGl+5PS/LhCP--
     
    Martin Boese, Apr 1, 2007
    #6
  7. Pablo Zorzoli wrote:
    > Ruby friends,
    >
    > Is there any approach similar to perl's Net:Telnet:Cisco [1] in ruby?
    > Has anyone nice experiences in this mix?
    >
    > I usually interact with my routers/switches with perl but I would like
    > to switch to ruby ;-)
    >
    > Regards,
    >
    > Pablo
    >
    > [1] http://search.cpan.org/~joshua/Net-Telnet-Cisco-1.10/Cisco.pm


    I don't know what perl's Net:Telnet:Cisco does, but I wrote this script
    that allows me to run commands on our Cisco fiber switches without
    having to login.

    I'm not sure this is what your looking for but I hope it helps out.
    I can provide the 'hec_getopts' module if you're intrested.

    Hector


    require 'pty'
    require 'expect'
    require 'hec_getopts'

    # Global variables
    $expect_verbose = true # Writes all characters read from the I/O
    stram to STDOUT.

    class MyExpect
    def initialize(switch='cisco1')
    @switch = switch
    STDOUT.sync = true
    STDERR.sync = true
    @passwd =
    File.new("/root/.system/.fraces/#{@switch}_dm").gets.chomp
    @uid =
    File.new("/root/.system/.fraces/#{@switch}_dm_user").gets.chomp
    end

    # This is where RubyExpect takes over
    def showInfo(cmd)
    PTY.spawn("ssh #{@uid}@#{@switch}") do |r_f, w_f, pid| # Spaw a
    process and create filehandles to it's input/output
    w_f.sync = true
    r_f.expect(/^password:/io) { w_f.puts @passwd }
    r_f.expect(/(switch\d+|1301)#\s+/io) { w_f.puts "terminal length
    0\n" } # Make terminal length infinite!!!

    case cmd
    when /^rc$/
    r_f.expect(/(switch\d+|1301)#\s+/io) { w_f.puts "show
    running-config\n" }
    when /^sc$/
    r_f.expect(/(switch\d+|1301)#\s+/io) { w_f.puts "show
    startup-config\n" }
    when /^az$/
    r_f.expect(/(switch\d+|1301)#\s+/io) { w_f.puts "show zoneset
    active\n" }
    when /^zs$/
    r_f.expect(/(switch\d+|1301)#\s+/io) { w_f.puts "show
    zoneset\n" }
    when /^fl$/
    r_f.expect(/(switch\d+|1301)#\s+/io) { w_f.puts "show flogi
    database\n" }
    when /^pi$/
    r_f.expect(/(switch\d+|1301)#\s+/io) { w_f.puts "show port
    internal info\n" }
    when /^td$/
    r_f.expect(/(switch\d+|1301)#\s+/io) { w_f.puts "show tech
    detail\n" }
    else
    r_f.expect(/(switch\d+|1301)#\s+/io) { w_f.puts "#{cmd}\n" }
    end
    r_f.expect(/(switch\d+|1301)#\s+/io) { w_f.puts "exit\n" }
    puts
    end
    end
    end

    class Help
    def showHelp(help)
    help_string = <<-EOHelp

    #{$PROG_NAME} lists configuration information for the Cisco directors.
    Syntax: #{$PROG_NAME} [-s[cisco1|cisco2|tcisco1|tcisco2]] <command>


    -Options-

    -s cisco_switch_name
    Selects a Cisco switch to pull information from(Cisco1, Cisco2,
    tcisco1, tcisco2).
    If no switch number is specified on the command-line, Cisco1 is the
    default.


    [ Commands: ]
    rc - Shows running-config
    az - Shows active zone
    zs - Shows zoneset
    fl - Shows flogi database
    pc <slot> <port> - Shows port config for <slot> and <port>
    td - Show tech detail


    [ Examples: ]
    #{$PROG_NAME} rc
    Displays currently running configuration for Cisco1

    #{$PROG_NAME} -scisco2 az
    Displays currently active zone for Cisco2
    EOHelp

    (help == '?' or help == 'h') and puts(help_string)
    help and exit(0)
    end
    end

    $PROG_NAME = File.basename($0).freeze

    # ? = help, h = help, s = switch_name
    cmdln = GetOpts.new('?hs:')
    Help.new.showHelp(cmdln.orHas?('?', 'h'))
    cmdln.has?('s') ? exp = MyExpect.new(cmdln.has?('s')) : exp =
    MyExpect.new()
    #cmdln.argv[0] ? exp.showInfo(cmdln.argv[0], cmdln.argv[1],
    cmdln.argv[2]) : Help.new.showHelp('?')
    cmdln.argv[0] ? exp.showInfo("#{cmdln.argv.join(' ')}") :
    Help.new.showHelp('?')

    --
    Posted via http://www.ruby-forum.com/.
     
    Hector Quiroz, Apr 1, 2007
    #7
  8. On Sun, Apr 01, 2007 at 04:58:22PM +0900, Robert Dober wrote:
    > Brian that is sound advice, but actually the problem is more or less
    > the subtle details about the Cisco interface(1), like getting rid of
    > the '---More---' or nonstandard login without user.


    If all the devices are under your control, it's probably reasonable to
    standardise on "login local" so that you get prompted for both username and
    password (since this can then be extended to RADIUS/TACACS without changing
    the interaction)

    As for the ---More--- prompt, simply send "term length 0" as the first
    command after logging in and that problem goes away :)

    Regards,

    Brian.
     
    Brian Candler, Apr 2, 2007
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. h4fun

    Cisco and telnet

    h4fun, Oct 18, 2007, in forum: Java
    Replies:
    1
    Views:
    477
    Esmond Pitt
    Oct 19, 2007
  2. Carcarius
    Replies:
    0
    Views:
    331
    Carcarius
    Dec 6, 2007
  3. jackster the jackle

    Net:Telnet to Cisco Router

    jackster the jackle, Dec 14, 2007, in forum: Ruby
    Replies:
    5
    Views:
    322
    jackster the jackle
    Dec 17, 2007
  4. Bhaskar Kurapati

    Net::Telnet::Cisco->enable always return 1

    Bhaskar Kurapati, Sep 10, 2003, in forum: Perl Misc
    Replies:
    0
    Views:
    111
    Bhaskar Kurapati
    Sep 10, 2003
  5. Prashant Varghese

    Net-Telnet-Cisco module

    Prashant Varghese, Sep 26, 2003, in forum: Perl Misc
    Replies:
    9
    Views:
    218
    Prashant Varghese
    Sep 30, 2003
Loading...

Share This Page