<div>I'm not necessary trying to bootstrap a router... that was just a string of config commands off the top of my head... the point is that they must be sequential, and must be done ins a single session to make sense... </div>

<div> </div>
<div>I thought about the output a file and SCP / TFTP transfer it, but that is a bit of a kludge/workaround... would like to avoid if possible.  it requires TFTP, yet another dependency, so I'd prefer to do it directly with SSH if possible.</div>

<div> </div>
<div> </div>
<div>The ultimate goal is to build a provisioning system for a DMVPN solution we have</div>
<div> </div>
<div> </div>
<div>We use DMVPN in combination with GETVPN (aka GDOI) over Internet links to provide branch and customer (extranet) connectivity.  The DMVPN solution for branch connectivity uses dynamic spoke-to-spoke tunneling, and GETVPN is used so that there is no lag in the dynamic tunnel setup, as there is then no IKE and IPSec negotiation between spoke routers when they build direct spok-to-spoke tunnels. We're also using Front-Door VRF on the routers, so the Internet interface is in an FVRF and the tunnel(s) are configured to use the FVRF for NHRP resolution (tunnel vrf <vrf-name>).  We have an ACL applied inbound and another ACL applied outbound.  </div>

<div> </div>
<div>In order for each spoke router to build dynamic tunnel to another spoke, ESP must be permitted inbound in the inbound ACL applied to the Internet interface.  Due to the dictates of our internal infosec people, the ACL, must explicitly permit EACH spoke router's public IP, rather than a nice, easy "permit esp any any "</div>

<div> </div>
<div> </div>
<div>the effect of this is that each time we add a new branch office router, we must update the ACL and deploy it to all the branch routers.  In addition, we must add IKE key entries (using PSK IKE keys on the GETVPN keyservers), and add routing neighbors to the headends routing (using eBGP for routing exchange through the tunnel).</div>

<div> </div>
<div>The net effect is that the addition of 1 router to the group triggers a few different small config changes to the keyservers, a few routing neighbor additions, and an ACL deployment to all existing branch routers.</div>

<div> </div>
<div> </div>
<div>My goal is to script this whole process:</div>
<div> </div>
<div> - create a DB-like structure that is persistent on disk of all the routers and their attributes (name, location, loopbak0 ip, tun1 ip , tun 2 ip, internet interface IPs, IKE keys, etc) - so far, using shelve for this, and using a class to represent the routers, serializing to disk using shelve... working OK at the moment</div>

<div> </div>
<div> - to add a new router</div>
<div>     - add a new object to the DB</div>
<div> </div>
<div> - to deploy the new router</div>
<div>     - from the DB structure, pull out the public IPs and generate the ACL.</div>
<div>     - ssh to GETVPN keyserver </div>
<div>          - add the IKE keys for the new router's public IPs, </div>
<div>          - issue commands to SCP or TFTP a new ACL which controls access to the key server to the keyserver's flash</div>
<div>          - checksum the ACL file on flash:</div>
<div>          - copy the ACL to running-config</div>
<div>          - wr mem </div>
<div>     - ssh to the DMVPN headends</div>
<div>           - add BGP neighbors for the new router's tunnel IPs (the tunnel IPs are the eBGP peering addresses)</div>
<div>           - wr mem</div>
<div>     - ssh to each router's Lo0 ip in the DB</div>
<div>           - issue commands to SCP or TFTP the new ACL to the router's flash:</div>
<div>           - checksum the ACL file on flash: </div>
<div>           - copy the ACL to running config</div>
<div>           - wr mem</div>
<div>     - (optional) archive a copy of each router's config before and after to a Subversion repository for disaster recovery and troubleshooting purposes</div>
<div>     - write a copy of the ACLs into a Subversion repository</div>
<div>     - write a copy of the shelve structure/DB structure elsewhere (ie: Subversion repository) </div>
<div>     - send a status report about what happened</div>
<div> </div>
<div> </div>
<div>The SSH aspect for multiple commands is currently tripping me up.  </div>
<div> </div>
<div>:-|</div>
<div> </div>
<div> </div>
<div>I've look at various sources, but all are somewhat convoluted.. .I'm new to using Twisted, so I am sure that is a part of my issue... also the examples I've seen are a bit trivial.  Planning on looking closely at the tkconch.py example script that comes with Twisted, as well as the code in ModiPy, which also uses Twisted... ModiPy itself doesn't seem to work.  </div>

<div> </div>
<div> </div>
<div>- </div>
<div><br> </div>
<div class="gmail_quote">On Tue, Mar 10, 2009 at 11:34 AM, Andreux Fort <span dir="ltr"><<a href="mailto:afort@choqolat.org">afort@choqolat.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">
<div class="im">On Tue, Mar 10, 2009 at 9:24 AM, Sam Crooks <<a href="mailto:sam.a.crooks@gmail.com">sam.a.crooks@gmail.com</a>> wrote:<br>> Does anyone have any suggestions for SSHv2 to multiple Cisco devices and<br>
> (this is the catch) running multiple commands?<br>><br>> I've tried with Paramiko using the SSHClient(), then connect()'ing and<br>> issuing exec_command(), and it seems that the router closes the channel<br>
> after the .exec_command('command here').  Subsequent write()'s on the stdin<br>> file object returned do not work, as shown on the examples I have seen:<br>> <a href="http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/#more-465" target="_blank">http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/#more-465</a><br>
<br></div>Yes.  The SSH session you're opening has a lifetime of one command.<br>If you want to do more than that, you have a couple of options:<br><br>1. Don't use exec_command().  Create the connection yourself, like<br>
SSHClient does, and then run in SSH1.5 mode (details escape me now in<br>this airport, but I've done this).<br><br>2. On Juniper, I can do "show foo; show this; show that", which works<br>just fine with exec_command().  Does that work on a Crisco?  (I'm<br>
guessing no, since that's a single command that the juniper splits).<br>
<div class="im"><br>><br>> I've tried various examples with twisted.conch.ssh and it seems Twisted is a<br>> bit more low-level than paramiko's SSHClient class.<br>><br><br></div>Yes; however, the SSHClient class wraps up a few other things that you<br>
could just do yourself, too.  The code isn't that ugly, although it<br>will raise EOFError on most operations (or socket.timeout in paramiko<br>1.7), and the docstrings in SSHClient's methods don't say that, so be<br>
aware.<br>
<div class="im"><br>><br>> I'm trying to  be able to issue a string of commands to routers which<br>> require a particular sequence;<br>><br>> configure terminal<br>> hostname blahrouter1<br>> ip domain-name x.i.z<br>
><br>> ip tftp source-interface lo0<br>> end<br>><br>><br>> copy tftp:/x.y.z.w/my/path/file.txt   flash:<br>><br><br></div>So you're trying to bootstrap a new router?<br>You could use the Cisco TFTP/BOOTP/DHCP method of bootstrapping.  I<br>
don't think many people really use this, but you may be in luck (i.e.,<br>it may work on your routers).<br><br>For ongoing mainteance:<br>Put the actual commands in a file, and then just send "copy source<br>dest" on the router?  This is how I do config pushes (it allows you to<br>
copy to a local file on the router first and perform an MD5 checksum,<br>too.  Which I'd recommend so your operators don't want to kill you<br>:-).<br><font color="#888888"><br>--<br>Andreux Fort (<a href="mailto:afort@choqolat.org">afort@choqolat.org</a>)<br>
</font></blockquote></div><br>