Simple SSH Connection

159 views
Skip to first unread message

Tom

unread,
Aug 6, 2012, 2:35:54 PM8/6/12
to trigge...@googlegroups.com
Hi

I've been tasked with automating the maintenance of ACLs on my clients ASR9000s so I was pretty happy to find trigger. I'm trying to connect to an ASR via SSH and I'm a little stuck. I can connect to the ASR from a linux shell prompt (ssh <user>@<ip_address>) without any trouble. The connection fails when I try to use trigger. Here's my code:
from trigger import tacacsrc
from trigger.netdevices import NetDevices
from twisted.python import log

log.startLogging(open('trig.log', 'w'), 'setStdout=False')

tcrc = tacacsrc.Tacacsrc()

nd = NetDevices()
print ('nd: ', nd)
dev = nd.find('10.252.17.122')
print ('dev: ', dev)
dev.connect()

This what my log looks like:
2012-08-06 14:04:42-0400 [-] Log opened.
2012-08-06 14:04:42-0400 [-] Using GPG method: False
2012-08-06 14:04:42-0400 [-] Got username: 'tpurcell'
2012-08-06 14:04:42-0400 [-] skipping '# Saved by trigger.tacacsrc at 2012-08-06 14:04:11 EDT'
2012-08-06 14:04:42-0400 [-] skipping ''
2012-08-06 14:04:42-0400 [-] using set_wakeup_fd
2012-08-06 14:04:42-0400 [-] ('nd: ', {'10.252.17.122': <NetDevice: 10.252.17.122>})
2012-08-06 14:04:42-0400 [-] ('dev: ', <NetDevice: 10.252.17.122>)
2012-08-06 14:04:42-0400 [-] Connecting to 10.252.17.122.  Use ^X to exit.
2012-08-06 14:04:42-0400 [-] File not found: '/home/tpurcell/.gorc'
2012-08-06 14:04:42-0400 [-] No config data, not sending init commands
2012-08-06 14:04:42-0400 [-] SSH connection test PASSED
2012-08-06 14:04:42-0400 [-] Could not connect to 10.252.17.122.

If I run without logging I get slightly different output:
('nd: ', {'10.252.17.122': <NetDevice: 10.252.17.122>})
('dev: ', <NetDevice: 10.252.17.122>)
Connecting to 10.252.17.122.  Use ^X to exit.
Fetching credentials from /home/tpurcell/.tacacsrc
Connection failed for the following reason:
ssh_exchange_identification: Connection closed by remote host
BYE

When I initially ran my code I was prompted for a Username and Password. I entered the values I use when I ssh in from the command prompt. Any thoughts?

Thanks
Tom

 

Jathan McCollum

unread,
Aug 6, 2012, 5:36:33 PM8/6/12
to trigge...@googlegroups.com
Hi Tom-

Welcome to the world of Trigger!  I'm glad you found it! Thanks for posting your issue. First things first, I have not officially tested the Cisco ASR, but since it falls under an IOS-like device, it should work fine but there are a few things I'd like to check.

A few questions:

+ How are you populating your NetDevices?

+ I'm curious about the contents of your device object for 10.252.17.122. Can you please show me the output of `dev.dump()` for that device?

+ Can you also provide a simple copy/paste of the output you get back from the device when connecting manually from the command-line?

Thanks!

jathan.

Tom

unread,
Aug 7, 2012, 10:28:29 AM8/7/12
to trigge...@googlegroups.com
Jathan

Thanks for the response. I really appreciate your help. Answers to your question are inline below.  


On Monday, August 6, 2012 5:36:33 PM UTC-4, Jathan McCollum wrote:
Hi Tom-

Welcome to the world of Trigger!  I'm glad you found it! Thanks for posting your issue. First things first, I have not officially tested the Cisco ASR, but since it falls under an IOS-like device, it should work fine but there are a few things I'd like to check.

A few questions:

+ How are you populating your NetDevices? 
From the following netdevices.xml file (Note: Its copied from the sample and I've change only a few of the values):
<?xml version="1.0" encoding="UTF-8"?>
<!-- Dummy version of netdevices.xml, with just one real entry copied
     from the real file (version of 2006-06-19 20:01 UTC). -->
<NetDevices>
    <device nodeName="ur03">
        <adminStatus>PRODUCTION</adminStatus>
        <assetID>90000041207</assetID>
        <authMethod>tacacs</authMethod>
        <barcode>001020020</barcode>
        <budgetCode>100124.06</budgetCode>
        <budgetName>DCNETS - IW</budgetName>
        <coordinate>16AH</coordinate>
        <deviceType>ROUTER</deviceType>
        <enablePW>mkL0v3!w4r</enablePW>
        <lastUpdate>2006-07-19 19:56:32.0</lastUpdate>
        <layer2>1</layer2>
        <layer3>1</layer3>
        <lifecycleStatus>INSTALLED</lifecycleStatus>
        <loginPW><an-actual-password-here></loginPW>
        <make>ASR9000 ROUTER</make>
        <manufacturer>Cisco</manufacturer>
        <model>ASR9006</model>
        <nodeName>10.252.17.122</nodeName>
        <onCallEmail>dcn...@aol.net</onCallEmail>
        <onCallID>17</onCallID>
        <onCallName>NETOPS DCNETS</onCallName>
        <OOBTerminalServerConnector>C</OOBTerminalServerConnector>
        <OOBTerminalServerFQDN>ts-cr3-w7-srv5.oob.aol.com</OOBTerminalServerFQDN>
        <OOBTerminalServerNodeName>ts-cr3-w7-srv5</OOBTerminalServerNodeName>
        <OOBTerminalServerPort>18</OOBTerminalServerPort>
        <OOBTerminalServerTCPPort>5018</OOBTerminalServerTCPPort>
        <operationStatus>MONITORED</operationStatus>
        <owner>NETWORK ENGINEERING</owner>
        <room>LAB</room>
        <serialNumber>12345</serialNumber>
        <site>UCS</site>
    </device>
</NetDevices>

+ I'm curious about the contents of your device object for 10.252.17.122. Can you please show me the output of `dev.dump()` for that device?
Here's my code. I made two small changes: the startLogging statement and added dev.dump() on the last line:
From trigger import tacacsrc
from trigger.netdevices import NetDevices
from twisted.python import log
import sys

log.startLogging(sys.stdout)

tcrc = tacacsrc.Tacacsrc()

nd = NetDevices()
print ('nd: ', nd)
dev = nd.find('10.252.17.122')
print ('dev: ', dev)
dev.connect()
dev.dump()
Here's the output:
(vtrigger)tpurcell@tpurcell-Latitude-E6500 ~/data/comcast-code/mytrigger $ python mytrigger.py
2012-08-07 10:23:57-0400 [-] Log opened.
2012-08-07 10:23:57-0400 [-] Using GPG method: False
2012-08-07 10:23:57-0400 [-] Got username: 'tpurcell'
2012-08-07 10:23:57-0400 [-] skipping '# Saved by trigger.tacacsrc at 2012-08-06 14:04:11 EDT'
2012-08-07 10:23:57-0400 [-] skipping ''
2012-08-07 10:23:57-0400 [-] ('nd: ', {'10.252.17.122': <NetDevice: 10.252.17.122>})
2012-08-07 10:23:57-0400 [-] ('dev: ', <NetDevice: 10.252.17.122>)
2012-08-07 10:23:57-0400 [-] Connecting to 10.252.17.122.  Use ^X to exit.
2012-08-07 10:23:57-0400 [-] File not found: '/home/tpurcell/.gorc'
2012-08-07 10:23:57-0400 [-] No config data, not sending init commands
2012-08-07 10:23:57-0400 [-] SSH connection test PASSED
2012-08-07 10:23:57-0400 [-] Could not connect to 10.252.17.122.
2012-08-07 10:23:57-0400 [-] 
2012-08-07 10:23:57-0400 [-] Hostname:          10.252.17.122
2012-08-07 10:23:57-0400 [-] Owning Org.:       NETWORK ENGINEERING
2012-08-07 10:23:57-0400 [-] Owning Team:       None
2012-08-07 10:23:57-0400 [-] OnCall Team:       NETOPS DCNETS
2012-08-07 10:23:57-0400 [-] 
2012-08-07 10:23:57-0400 [-] Vendor:            Cisco (Cisco)
2012-08-07 10:23:57-0400 [-] Make:              ASR9000 ROUTER
2012-08-07 10:23:57-0400 [-] Model:             ASR9006
2012-08-07 10:23:57-0400 [-] Type:              ROUTER
2012-08-07 10:23:57-0400 [-] Location:          UCS LAB 16AH
2012-08-07 10:23:57-0400 [-] 
2012-08-07 10:23:57-0400 [-] Project:           None
2012-08-07 10:23:57-0400 [-] Serial:            12345
2012-08-07 10:23:57-0400 [-] Asset Tag:         90000041207
2012-08-07 10:23:57-0400 [-] Budget Code:       100124.06 (DCNETS - IW)
2012-08-07 10:23:57-0400 [-] 
2012-08-07 10:23:57-0400 [-] Admin Status:      PRODUCTION
2012-08-07 10:23:57-0400 [-] Lifecycle Status:  INSTALLED
2012-08-07 10:23:57-0400 [-] Operation Status:  MONITORED
2012-08-07 10:23:57-0400 [-] Last Updated:      2006-07-19 19:56:32.0
2012-08-07 10:23:57-0400 [-]  

+ Can you also provide a simple copy/paste of the output you get back from the device when connecting manually from the command-line?
tpurcell@tpurcell-Latitude-E6500 ~ $ ssh aut...@10.252.17.122


This system is solely for the use of authorized Comcast employees and contractors. 

aut...@10.252.17.122's password: 
RP/0/RSP0/CPU0:ur03.hsi.cc38.ula#show clock
Tue Aug  7 21:31:33.671 UTC
21:31:33.697 UTC Tue Aug 07 2012
RP/0/RSP0/CPU0:ur03.hsi.cc38.ula#
 

Jathan McCollum

unread,
Aug 7, 2012, 11:00:32 AM8/7/12
to trigge...@googlegroups.com
On Tuesday, August 7, 2012 7:28:29 AM UTC-7, Tom wrote:
Jathan

Thanks for the response. I really appreciate your help. Answers to your question are inline below.  

You're welcome! 

The first thing that stands out is that in the log it's reporting that your cached username within your .tacacsrc is "tpurcell":

2012-08-07 10:23:57-0400 [-] Got username: 'tpurcell'

... But the account name you're using to log into the device manually is "autoacl". You'll need to make sure that the credentials you're caching are the same ones you'll be using to connect to the device.

The easiest way to fix this is to just delete the .tacacsrc from your home directory and connect again. If the file is missing you'll be prompted to create a new one.

I hope it's as simple as that! Please let me know.

Tom

unread,
Aug 7, 2012, 1:13:50 PM8/7/12
to trigge...@googlegroups.com
Jathan

I'm pretty sure I have .tacacsrc set up correctly.  In twister.py, TriggerClientFactory's __init__ method I added a print statement on line 537:
    def __init__(self, deferred, creds=None, init_commands=None):
        self.d = deferred
        self.tcrc = tacacsrc.Tacacsrc()
        if creds is None:
            log.msg('creds not defined, fetching...', debug=True)
            realm = settings.DEFAULT_REALM
            creds = self.tcrc.creds.get(realm, tacacsrc.get_device_password(realm))
        self.creds = creds
        print('TriggerClientFactory.__init__ self.creds: ', self.creds)
...
My output shows:
(vtrigger)tpurcell@tpurcell-Latitude-E6500 ~/data/comcast-code/mytrigger $ python mytrigger.py
('nd: ', {'10.252.17.122': <NetDevice: 10.252.17.122>})
('dev: ', <NetDevice: 10.252.17.122>)
Connecting to 10.252.17.122.  Use ^X to exit.
('TriggerClientFactory.__init__ self.creds: ', Credentials(username='autoacl', password='<actual-password-here>', realm=''))

Fetching credentials from /home/tpurcell/.tacacsrc

Connection failed for the following reason:

ssh_exchange_identification: Connection closed by remote host

BYE

Hostname:          10.252.17.122
Owning Org.:       NETWORK ENGINEERING
Owning Team:       None
OnCall Team:       NETOPS DCNETS

Vendor:            Cisco (Cisco)
Make:              ASR9000 ROUTER
Model:             ASR9006
Type:              ROUTER
Location:          UCS LAB 16AH

Project:           None
Serial:            12345
Asset Tag:         90000041207
Budget Code:       100124.06 (DCNETS - IW)

Admin Status:      PRODUCTION
Lifecycle Status:  INSTALLED
Operation Status:  MONITORED
Last Updated:      2006-07-19 19:56:32.0

Note that it shows credentials to be: Credentials(username='autoacl', password='<actual-password-here>', realm='')). A couple of notes:
  • It says "Fetching credentials from /home/tpurcell/.tacacsrc" after the credentials for autoacl are established. 
  • I don't have a "realm". This is straight user id and password access, no ldap, nothing fancy.
  • A side note, I get very different behavior if I attempt to turn on twister logging (log.startLogging to stdout or a file). Any hints on how to get more logging out of trigger?
And again thanks for the help.

Thanks
Tom 

Tom

unread,
Aug 7, 2012, 3:50:46 PM8/7/12
to trigge...@googlegroups.com
Jathan

Some additional information. I think it looks like the "startedConnecting" method calling falling through to the super class'(ClientFactory) version in twisted.internet.py. I changed that method as follows:
      def startedConnecting(self, connector):
        """Called when a connection has been started.

        You can call connector.stopConnecting() to stop the connection attempt.

        @param connector: a Connector object.
        """
        import pdb
        pdb.set_trace()

Resulting output:
(vtrigger)tpurcell@tpurcell-Latitude-E6500 ~/data/comcast-code/mytrigger $ python mytrigger.py
('nd: ', {'10.252.17.122': <NetDevice: 10.252.17.122>})
('dev: ', <NetDevice: 10.252.17.122>)
Connecting to 10.252.17.122.  Use ^X to exit.
('TriggerClientFactory.__init__ self.creds: ', Credentials(username='autoacl', password='c0mcast!', realm=''))
--Return--
> /home/tpurcell/data/comcast-code/mytrigger/vtrigger/local/lib/python2.7/site-packages/twisted/internet/protocol.py(124)startedConnecting()->None
-> pdb.set_trace()
(Pdb) w
  /home/tpurcell/data/comcast-code/mytrigger/mytrigger.py(24)<module>()
-> dev.connect(init_commands=['show clock', 'exit'])
  /home/tpurcell/data/comcast-code/mytrigger/vtrigger/local/lib/python2.7/site-packages/trigger/twister.py(231)connect()
-> init_commands=init_commands)
  /home/tpurcell/data/comcast-code/mytrigger/vtrigger/local/lib/python2.7/site-packages/trigger/twister.py(172)pty_connect()
-> reactor.connectTCP(device.nodeName, port, factory)
  /home/tpurcell/data/comcast-code/mytrigger/vtrigger/local/lib/python2.7/site-packages/twisted/internet/posixbase.py(471)connectTCP()
-> c.connect()
  /home/tpurcell/data/comcast-code/mytrigger/vtrigger/local/lib/python2.7/site-packages/twisted/internet/base.py(1027)connect()
-> self.factory.startedConnecting(self)
> /home/tpurcell/data/comcast-code/mytrigger/vtrigger/local/lib/python2.7/site-packages/twisted/internet/protocol.py(124)startedConnecting()->None
-> pdb.set_trace()

Tom

unread,
Aug 8, 2012, 10:18:09 AM8/8/12
to trigge...@googlegroups.com
Jathan

I realized I didn't type the correct module name below. Its  twisted.internet.protocol.py. Sorry for the confusion.

Thanks
Tom

Tom

unread,
Aug 8, 2012, 12:56:48 PM8/8/12
to trigge...@googlegroups.com
Jathan

I have a break through of sorts. I've been trying to walk through the code with pdb. I added a set_trace() to the startedConnecting() method in ClientFactory. If I run with it commented out I get the connection failure:

(vtrigger)tpurcell@tpurcell-Latitude-E6500 ~/data/comcast-code/mytrigger $ python mytrigger.py
('nd: ', {'10.252.17.122': <NetDevice: 10.252.17.122>})
('dev: ', <NetDevice: 10.252.17.122>)
Connecting to 10.252.17.122.  Use ^X to exit.
('TriggerClientFactory.__init__ self.creds: ', Credentials(username='autoacl', password='c0mcast!', realm=''))
Fetching credentials from /home/tpurcell/.tacacsrc
Connection failed for the following reason:
ssh_exchange_identification: Connection closed by remote host
BYE

If I run with not commented out I get a very different result:

(vtrigger)tpurcell@tpurcell-Latitude-E6500 ~/data/comcast-code/mytrigger $ python mytrigger.py
('nd: ', {'10.252.17.122': <NetDevice: 10.252.17.122>})
('dev: ', <NetDevice: 10.252.17.122>)
Connecting to 10.252.17.122.  Use ^X to exit.
('TriggerClientFactory.__init__ self.creds: ', Credentials(username='autoacl', password='c0mcast!', realm=''))
--Return--
> /home/tpurcell/data/comcast-code/mytrigger/vtrigger/local/lib/python2.7/site-packages/twisted/internet/protocol.py(128)startedConnecting()->None
-> pdb.set_trace()
(Pdb) c
Fetching credentials from /home/tpurcell/.tacacsrc
RP/0/RSP0/CPU0:ur03.hsi.cc38.ula#show configuration commit list
Thu Aug  9 00:43:21.296 UTC
SNo. Label/ID    User      Line                Client      Time Stamp
~~~~ ~~~~~~~~    ~~~~      ~~~~                ~~~~~~      ~~~~~~~~~~
1    1000000024  red       vty0:node0_RSP0_CP  CLI         Wed Jul 25 05:18:35 2012
2    1000000023  red       vty0:node0_RSP0_CP  CLI         Wed Jul 25 05:17:23 2012
3    1000000022  autoacl   vty0:node0_RSP0_CP  CLI         Thu Jul 19 21:45:15 2012
4    1000000021  red       vty1:node0_RSP0_CP  CLI         Thu Jul 19 05:51:42 2012
5    1000000020  red       vty1:node0_RSP0_CP  CLI         Thu Jul 19 05:48:34 2012
6    1000000019  red       vty1:node0_RSP0_CP  CLI         Thu Jul 19 05:45:15 2012
7    1000000018  red       vty0:node0_RSP0_CP  CLI         Thu Jul 19 04:37:52 2012
8    1000000017  red       vty0:node0_RSP0_CP  CLI         Thu Jul 19 04:36:00 2012
9    1000000016  red       vty0:node0_RSP0_CP  cfgmgr-ins  Thu Jul 19 03:05:42 2012
10   1000000015  red       vty0:node0_RSP0_CP  CLI         Thu Jul 19 00:10:45 2012
11   1000000014  red       con0_RSP0_CPU0      CLI         Tue Jul 17 05:15:31 2012
12   1000000013  red       con0_RSP0_CPU0      CLI         Tue Jul 17 05:11:02 2012
13   1000000012  red       con0_RSP0_CPU0      CLI         Tue Jul 17 05:10:11 2012
14   1000000011  red       con0_RSP0_CPU0      CLI         Tue Jul 17 05:06:37 2012
15   1000000010  red       con0_RSP0_CPU0      CLI         Tue Jul 17 05:03:39 2012
16   1000000009  red       con0_RSP0_CPU0      CLI         Tue Jul 17 02:23:27 2012
17   1000000008  red       con0_RSP0_CPU0      CLI         Tue Jul 17 01:45:15 2012
18   1000000007  red       con0_RSP0_CPU0      CLI         Tue Jul 17 01:43:59 2012
19   1000000006  red       con0_RSP0_CPU0      CLI         Tue Jul 17 01:39:05 2012
20   1000000005  red       con0_RSP0_CPU0      CLI         Tue Jul 17 01:20:17 2012
21   1000000004  red       con0_RSP0_CPU0      CLI         Fri Jun 29 05:05:44 2012
22   1000000003  red       con0_RSP0_CPU0      CLI         Fri Jun 29 05:00:07 2012
23   1000000002  root      con0_RSP0_CPU0      CLI         Fri May  4 00:43:06 2012
24   1000000001  root      con0_RSP0_CPU0      CLI         Thu May  3 16:28:45 2012
RP/0/RSP0/CPU0:ur03.hsi.cc38.ula#exit
Connection failed for the following reason:
BYE

Apparently the pause caused by the set_trace() is causing a "pause" long enough for the connection to complete. So I tried this:

    def startedConnecting(self, connector):
        """Called when a connection has been started.

        You can call connector.stopConnecting() to stop the connection attempt.

        @param connector: a Connector object.
        """
        import time
        time.sleep(1)

And that works as well (sleep(.9)) does not). My next question: is there a configuration I'm missing that can set the time to pause?

Thanks
Tom

Jathan McCollum

unread,
Aug 8, 2012, 6:09:51 PM8/8/12
to trigge...@googlegroups.com
Just to make sure I'm clear, on the successful login, did you execute the command "show configuration commit list" manually? What is the estimated amount of time the device is taking to present a "#" prompt after logging in manually? Is it significant? 

I'm just wondering if this is somehow a factor, and Twisted's default connection timeout is abnormally low, however, as far as I can tell it defaults to 30 seconds. There must be something wonky with the SSH channel negotiation that your device is not happy about.

I've never run into this before for SSH. For telnet we have a configuration directive TELNET_TIMEOUT which defaults to 60 seconds. There is an ability to specify a command_interval for when you're executing commands asynchronously (using the .execute() method) that was the result of a similar issue when connecting to and executing commands on some older Foundry hardware. But since I've never run into this exact issue you're experiencing for SSH on Cisco devices there is not a configuration setting to toggle a login pause.

The other thing that stands out to me is you're using the .connect() method which is intended for interactive logins and there is the "gong" script bundled with Trigger that does all of that for you by instantiating NetDevices for you and doing a lookup based on IP/hostname and then connecting you.

--
Jathan.
--

Tom

unread,
Aug 9, 2012, 10:16:45 AM8/9/12
to trigge...@googlegroups.com
Jathan 

Response inline. Thanks for the help.

On Wednesday, August 8, 2012 6:09:51 PM UTC-4, Jathan McCollum wrote:
Just to make sure I'm clear, on the successful login, did you execute the command "show configuration commit list" manually? What is the estimated amount of time the device is taking to present a "#" prompt after logging in manually? Is it significant? 
 
This is what I'm currently executing:
from trigger import tacacsrc
from trigger.netdevices import NetDevices
tcrc = tacacsrc.Tacacsrc()
nd = NetDevices()
dev = nd.find('10.252.17.122')
dev.connect(init_commands=['show configuration commit list', 'exit'])

As you can see I'm not attempting an interactive session. I'm passing in the commands on the call to connect. If I manually perform an old fashioned ssh logon(ssh aut...@10.252.17.122) from a linux terminal there is no significant delay in connecting. After entering a password there is no significant delay in getting # prompt.   
 
I'm just wondering if this is somehow a factor, and Twisted's default connection timeout is abnormally low, however, as far as I can tell it defaults to 30 seconds. There must be something wonky with the SSH channel negotiation that your device is not happy about.

I've never run into this before for SSH. For telnet we have a configuration directive TELNET_TIMEOUT which defaults to 60 seconds. There is an ability to specify a command_interval for when you're executing commands asynchronously (using the .execute() method) that was the result of a similar issue when connecting to and executing commands on some older Foundry hardware. But since I've never run into this exact issue you're experiencing for SSH on Cisco devices there is not a configuration setting to toggle a login pause.

The other thing that stands out to me is you're using the .connect() method which is intended for interactive logins and there is the "gong" script bundled with Trigger that does all of that for you by instantiating NetDevices for you and doing a lookup based on IP/hostname and then connecting you.
It is entirely possible I'm going about this the wrong way. Right now I'm just trying to connect and execute a command but eventually I need to maintain ACLs.
 
What will need to happen is a call will be made by another system to a component I'm responsible for developing. The other system will send the ACL. My component will be responsible for pushing the ACL to the network device and maintaining a change log. Initially the devices will be of the ASR9000 variety but it is not a homogeneous environment. Eventually we will need to communicate with other vendors products as well.     

So I'm hoping to use trigger as a library that will handle the transformation, connection and execution parts of what needs to happen but right now I'm just trying to understand what it has to offer.

Jathan McCollum

unread,
Aug 16, 2012, 8:15:27 PM8/16/12
to trigge...@googlegroups.com
Ok, I think I've gotten to the bottom of the problem.

I'll reply inline some more...

On Thu, Aug 9, 2012 at 7:16 AM, Tom <tpur...@chariotsolutions.com> wrote:
Jathan 

Response inline. Thanks for the help.

On Wednesday, August 8, 2012 6:09:51 PM UTC-4, Jathan McCollum wrote:
Just to make sure I'm clear, on the successful login, did you execute the command "show configuration commit list" manually? What is the estimated amount of time the device is taking to present a "#" prompt after logging in manually? Is it significant? 
 
This is what I'm currently executing:
from trigger import tacacsrc
from trigger.netdevices import NetDevices
tcrc = tacacsrc.Tacacsrc()
nd = NetDevices()
dev = nd.find('10.252.17.122')
dev.connect(init_commands=['show configuration commit list', 'exit'])

As you can see I'm not attempting an interactive session. I'm passing in the commands on the call to connect. If I manually perform an old fashioned ssh logon(ssh aut...@10.252.17.122) from a linux terminal there is no significant delay in connecting. After entering a password there is no significant delay in getting # prompt.   

We may be onto something with the login delay thing, but the `init_commands` argument was also not rigorously tested with commands that output more than a few lines of data. I'll need to research it more.

But, this is not really what you want to be using anyway, because I think you want to be capturing output. So... go below:

 
I'm just wondering if this is somehow a factor, and Twisted's default connection timeout is abnormally low, however, as far as I can tell it defaults to 30 seconds. There must be something wonky with the SSH channel negotiation that your device is not happy about.

I've never run into this before for SSH. For telnet we have a configuration directive TELNET_TIMEOUT which defaults to 60 seconds. There is an ability to specify a command_interval for when you're executing commands asynchronously (using the .execute() method) that was the result of a similar issue when connecting to and executing commands on some older Foundry hardware. But since I've never run into this exact issue you're experiencing for SSH on Cisco devices there is not a configuration setting to toggle a login pause.

The other thing that stands out to me is you're using the .connect() method which is intended for interactive logins and there is the "gong" script bundled with Trigger that does all of that for you by instantiating NetDevices for you and doing a lookup based on IP/hostname and then connecting you.
It is entirely possible I'm going about this the wrong way. Right now I'm just trying to connect and execute a command but eventually I need to maintain ACLs.
 
What will need to happen is a call will be made by another system to a component I'm responsible for developing. The other system will send the ACL. My component will be responsible for pushing the ACL to the network device and maintaining a change log. Initially the devices will be of the ASR9000 variety but it is not a homogeneous environment. Eventually we will need to communicate with other vendors products as well.     

So I'm hoping to use trigger as a library that will handle the transformation, connection and execution parts of what needs to happen but right now I'm just trying to understand what it has to offer.

This should be where Trigger excels for you, but to capture output and do event-based stuff, you'll need to write a custom Commando adapter, which simplifies the async execution of commands on devices and allows you to dynamically generate commands based on the device metadata, and then parse/handle the output conditionally.

Before I give you an example, there is a caveat: 

There is another bug I discovered that I'm in the process of fixing that related to executing commands over SSH. If you get more than 25 lines of data (which is the default height of the vty used by Trigger), the device will try to page the data and give you the '--more--' prompts. This causes the channel to block while it waits for input, and the program will just hang until it hits the command timeout.

The async SSH channel support for IOS-like (Cisco, Foundry, etc.) is new, so I'll have this worked out soon. Using telnet we already have the functionality to disable paging, it just needs to be migrated to the SSH channels as well.

In the meantime this can be worked around by sending "terminal length 0" as the first command to the device to disable paging. Then you may execute your other commands and get their results.

So... Having said that, here is a very simple example of what you're wanting to do would be like this:

from trigger.cmds import Commando
from twisted.python import log
log.startLogging(open('trig.log', 'w'), setStdout=False)

class ShowCommitList(Commando):
    vendors = ['cisco']
    commands = ['terminal length 0', 'show configuration commit list']

devnames= ['10.252.17.122']
scl = ShowCommitList(devices=devnames, verbose=True)
scl.run()

This very basic example will run the same commands on every device you specify to the constructor. After it completes, it populate a dictionary with the results found at `scl.results`. This dictionary will be keyed by the nodename of the device, and will contain a dictionary keyed by the commands with the output from each command as the value. 

So for example `print scl.results['10.252.17.122'].keys()` will return:

['show configuration commit list', 'terminal length 0']

Ya dig?

One more thing you can do to MAJORLY increase verbosity for SSH channels is to uncomment line 914 in trigger/twister.py. This will log every byte sent and received and give you a much clearer idea of the communication going on. I have it commented out by default because it's absurdly chatty.

Please let me know if this puts you down a better path for the time being. I'll be sure to follow-up once I have the SSH async bug fixed.

Jathan McCollum

unread,
Aug 23, 2012, 11:11:32 AM8/23/12
to trigge...@googlegroups.com
BTW, for the login delay problem you are having, I added a `login_delay` argument to the `connect()` method. These can be found in  the "passwords" branch (yes, the branch name is unrelated). I've also fixed the bug with `load_acl` where it was still hard-coded to `/home/tftp`.

Here is the commit for that:


Please give it a test if you have time and let me know how it works out for you.  Thanks!


On Monday, August 6, 2012 11:35:54 AM UTC-7, Tom wrote:

Jathan McCollum

unread,
Aug 23, 2012, 11:13:12 AM8/23/12
to trigge...@googlegroups.com
Sorry I meant the bug with `acl`, not `load_acl`.
Reply all
Reply to author
Forward
0 new messages