<br><font size=2 face="sans-serif">Raul,</font>
<br>
<br><font size=2 face="sans-serif">This is simply some work-in-progress
code, but is basically what you are looking for even written for PythonCard.
This takes a list of three commands and runs them in the order given using
deferreds to wait for the previous to complete before executing the next.</font>
<br>
<br><font size=2 face="sans-serif">This took me about forever to get it
this far. If you make and significant improvements, please share.</font>
<br>
<br><font size=2 face="sans-serif">One remaining mystery is how to switch
users once logged in. For example, I need to run some things as root.</font>
<br>
<br><font size=2 face="sans-serif">Paul</font>
<br>
<br><font size=2 face="sans-serif">============================================</font>
<br><font size=2 face="sans-serif">from twisted.conch import error</font>
<br><font size=2 face="sans-serif">from twisted.conch.ssh import transport,
connection, keys, userauth, channel, common</font>
<br><font size=2 face="sans-serif">from twisted.internet import defer,
protocol, reactor</font>
<br><font size=2 face="sans-serif">import sys, getpass, os, string</font>
<br>
<br><font size=2 face="sans-serif">from PythonCard import model, twistedModel</font>
<br>
<br>
<br><font size=2 face="sans-serif">class ClientCommandTransport(transport.SSHClientTransport):</font>
<br><font size=2 face="sans-serif"> def __init__(self, username,
password, cmds, caller):</font>
<br><font size=2 face="sans-serif"> self.username
= username</font>
<br><font size=2 face="sans-serif"> self.password
= password</font>
<br><font size=2 face="sans-serif"> self.cmds
= cmds</font>
<br><font size=2 face="sans-serif"> self.caller
= caller</font>
<br><font size=2 face="sans-serif"> </font>
<br><font size=2 face="sans-serif"> def verifyHostKey(self,
pubKey, fingerprint):</font>
<br><font size=2 face="sans-serif"> # in a real
app, you should verify that the fingerprint matches</font>
<br><font size=2 face="sans-serif"> # the one
you expected to get from this server</font>
<br><font size=2 face="sans-serif"> return defer.succeed(True)</font>
<br>
<br><font size=2 face="sans-serif"> def connectionSecure(self):</font>
<br><font size=2 face="sans-serif"> self.requestService(PasswordAuth(self.username,
self.password, ClientConnection(self.cmds, self.caller)))</font>
<br>
<br><font size=2 face="sans-serif">class PasswordAuth(userauth.SSHUserAuthClient):</font>
<br><font size=2 face="sans-serif"> def __init__(self, user,
password, connection):</font>
<br><font size=2 face="sans-serif"> userauth.SSHUserAuthClient.__init__(self,
user, connection)</font>
<br><font size=2 face="sans-serif"> self.password
= password</font>
<br><font size=2 face="sans-serif"> </font>
<br><font size=2 face="sans-serif"> def getPassword(self,
prompt=None):</font>
<br><font size=2 face="sans-serif"> return defer.succeed(self.password)</font>
<br>
<br><font size=2 face="sans-serif">class ClientConnection(connection.SSHConnection):</font>
<br><font size=2 face="sans-serif"> def __init__(self, cmds,
caller, *args, **kwargs):</font>
<br><font size=2 face="sans-serif"> connection.SSHConnection.__init__(self)</font>
<br><font size=2 face="sans-serif"> self.cmds
= cmds</font>
<br><font size=2 face="sans-serif"> self.caller
= caller</font>
<br>
<br><font size=2 face="sans-serif"> #======================</font>
<br><font size=2 face="sans-serif"> def serviceStarted(self):</font>
<br><font size=2 face="sans-serif"> self.d =
defer.Deferred()</font>
<br><font size=2 face="sans-serif"> self.d.addCallback(self._cbFirst)</font>
<br><font size=2 face="sans-serif"> self.d.addErrback(self._ebFirst)</font>
<br><font size=2 face="sans-serif"> self.openChannel(CommandChannel(self.cmds[0],
lastcmd=0, conn=self))</font>
<br>
<br><font size=2 face="sans-serif"> def _cbFirst(self, result):</font>
<br><font size=2 face="sans-serif"> print 'CALLBACK
Result 1:', result</font>
<br><font size=2 face="sans-serif"> self.caller.responses.append(result.rstrip())</font>
<br><font size=2 face="sans-serif"> self.d =
defer.Deferred()</font>
<br><font size=2 face="sans-serif"> self.d.addCallback(self._cbSecond)</font>
<br><font size=2 face="sans-serif"> self.d.addErrback(self._ebSecond)</font>
<br><font size=2 face="sans-serif"> self.openChannel(CommandChannel(self.cmds[1],
lastcmd=0, conn=self))</font>
<br>
<br><font size=2 face="sans-serif"> def _ebFirst(self, f):</font>
<br><font size=2 face="sans-serif"> self.caller.responses.append(None)</font>
<br><font size=2 face="sans-serif"> print "Error
1"</font>
<br><font size=2 face="sans-serif"> self.d =
defer.Deferred()</font>
<br><font size=2 face="sans-serif"> self.d.addCallback(self._cbSecond)</font>
<br><font size=2 face="sans-serif"> self.d.addErrback(self._ebSecond)</font>
<br><font size=2 face="sans-serif"> self.openChannel(CommandChannel(self.cmds[1],
lastcmd=0, conn=self))</font>
<br><font size=2 face="sans-serif"> #log.err()</font>
<br>
<br><font size=2 face="sans-serif"> def _cbSecond(self, result):</font>
<br><font size=2 face="sans-serif"> print 'CALLBACK
Result 2:', result</font>
<br><font size=2 face="sans-serif"> self.caller.responses.append(result.rstrip())</font>
<br><font size=2 face="sans-serif"> self.d =
defer.Deferred()</font>
<br><font size=2 face="sans-serif"> self.d.addCallback(self._cbThird)</font>
<br><font size=2 face="sans-serif"> self.d.addErrback(self._ebThird)</font>
<br><font size=2 face="sans-serif"> self.openChannel(CommandChannel(self.cmds[2],
lastcmd=1, conn=self))</font>
<br>
<br><font size=2 face="sans-serif"> def _ebSecond(self, f):</font>
<br><font size=2 face="sans-serif"> self.caller.responses.append(None)</font>
<br><font size=2 face="sans-serif"> self.d =
defer.Deferred()</font>
<br><font size=2 face="sans-serif"> self.d.addCallback(self._cbThird)</font>
<br><font size=2 face="sans-serif"> self.d.addErrback(self._ebThird)</font>
<br><font size=2 face="sans-serif"> self.openChannel(CommandChannel(self.cmds[2],
lastcmd=1, conn=self))</font>
<br><font size=2 face="sans-serif"> #log.err()</font>
<br>
<br><font size=2 face="sans-serif"> def _cbThird(self, result):</font>
<br><font size=2 face="sans-serif"> self.caller.responses.append(result.rstrip())</font>
<br><font size=2 face="sans-serif"> print 'CALLBACK
Result 3:', result</font>
<br><font size=2 face="sans-serif"> #reactor.stop()</font>
<br>
<br><font size=2 face="sans-serif"> def _ebThird(self, f):</font>
<br><font size=2 face="sans-serif"> self.caller.responses.append(None)</font>
<br><font size=2 face="sans-serif"> log.err()</font>
<br><font size=2 face="sans-serif"> #reactor.stop()</font>
<br><font size=2 face="sans-serif"> #======================</font>
<br>
<br><font size=2 face="sans-serif">class CommandChannel(channel.SSHChannel):</font>
<br><font size=2 face="sans-serif"> name = 'session'</font>
<br><font size=2 face="sans-serif"> </font>
<br><font size=2 face="sans-serif"> def __init__(self, command,
lastcmd, *args, **kwargs):</font>
<br><font size=2 face="sans-serif"> channel.SSHChannel.__init__(self,
*args, **kwargs)</font>
<br><font size=2 face="sans-serif"> self.command
= command</font>
<br><font size=2 face="sans-serif"> self.lastcmd
= lastcmd</font>
<br><font size=2 face="sans-serif"> self.data
= ""</font>
<br>
<br><font size=2 face="sans-serif"> def channelOpen(self,
data):</font>
<br><font size=2 face="sans-serif"> self.conn.sendRequest(self,
'exec', common.NS(self.command), wantReply=True).addCallback(self._gotResponse)</font>
<br>
<br><font size=2 face="sans-serif"> def _gotResponse(self,
_):</font>
<br><font size=2 face="sans-serif"> #print "RESPONSE"</font>
<br><font size=2 face="sans-serif"> self.conn.sendEOF(self)</font>
<br>
<br><font size=2 face="sans-serif"> def dataReceived(self,
data):</font>
<br><font size=2 face="sans-serif"> #print "Data
Received:", data</font>
<br><font size=2 face="sans-serif"> self.data
+= data</font>
<br>
<br><font size=2 face="sans-serif"> def closed(self):</font>
<br><font size=2 face="sans-serif"> self.conn.d.callback(self.data)</font>
<br><font size=2 face="sans-serif"> self.loseConnection()</font>
<br><font size=2 face="sans-serif"> ##
if self.lastcmd:</font>
<br><font size=2 face="sans-serif"> ##
print "closing reactor."</font>
<br><font size=2 face="sans-serif"> ##
reactor.stop()</font>
<br>
<br><font size=2 face="sans-serif">class ClientCommandFactory(protocol.ClientFactory):</font>
<br><font size=2 face="sans-serif"> def __init__(self, username,
password, cmds, caller):</font>
<br><font size=2 face="sans-serif"> self.username
= username</font>
<br><font size=2 face="sans-serif"> self.password
= password</font>
<br><font size=2 face="sans-serif"> self.cmds
= cmds</font>
<br><font size=2 face="sans-serif"> self.caller
= caller</font>
<br>
<br><font size=2 face="sans-serif"> def buildProtocol(self,
addr):</font>
<br><font size=2 face="sans-serif"> protocol
= ClientCommandTransport(self.username, self.password, self.cmds, self.caller)</font>
<br><font size=2 face="sans-serif"> return protocol</font>
<br>
<br><font size=2 face="sans-serif"> </font>
<br><font size=2 face="sans-serif">class SSH():</font>
<br><font size=2 face="sans-serif"> """ Contains
a SSH connection, runs commands, and stores results. """</font>
<br><font size=2 face="sans-serif"> def __init__(self, host,
username, password, cmds):</font>
<br><font size=2 face="sans-serif"> self.host
= host</font>
<br><font size=2 face="sans-serif"> self.username
= username</font>
<br><font size=2 face="sans-serif"> self.password
= password</font>
<br><font size=2 face="sans-serif"> self.cmds
= cmds</font>
<br><font size=2 face="sans-serif"> self.responses
= []</font>
<br><font size=2 face="sans-serif"> self.run_commands()</font>
<br>
<br><font size=2 face="sans-serif"> def run_commands(self):</font>
<br><font size=2 face="sans-serif"> factory
= ClientCommandFactory(self.username, self.password, self.cmds, self)</font>
<br><font size=2 face="sans-serif"> reactor.connectTCP(self.host,
22, factory)</font>
<br><font size=2 face="sans-serif"> #reactor.registerWxApp(app)</font>
<br><font size=2 face="sans-serif"> #reactor.run()</font>
<br>
<br>
<br>
<br><font size=2 face="sans-serif">#from PythonCard import model</font>
<br>
<br><font size=2 face="sans-serif">class Dashboard(model.Background):</font>
<br>
<br><font size=2 face="sans-serif"> def on_initialize(self,
event):</font>
<br><font size=2 face="sans-serif"> self.responses
= []</font>
<br><font size=2 face="sans-serif"> </font>
<br><font size=2 face="sans-serif"> def on_btSend_mouseClick(self,
event):</font>
<br><font size=2 face="sans-serif"> print "Hello
World!"</font>
<br><font size=2 face="sans-serif"> self.run_commands("myhost",
"myusername", "mypassword", ["id", "pwd",
"ls -l"])</font>
<br><font size=2 face="sans-serif"> #for i,
response in enumerate(self.ssh.responses):</font>
<br><font size=2 face="sans-serif"> #
print i, response</font>
<br><font size=2 face="sans-serif"> #
print "=" * 25</font>
<br>
<br><font size=2 face="sans-serif"> def on_btCheck_mouseClick(self,
event):</font>
<br><font size=2 face="sans-serif"> """
Check it out! """</font>
<br><font size=2 face="sans-serif"> for i, response
in enumerate(self.responses):</font>
<br><font size=2 face="sans-serif">
print i, response</font>
<br><font size=2 face="sans-serif">
print "=" * 25</font>
<br><font size=2 face="sans-serif"> print "Done."</font>
<br><font size=2 face="sans-serif"> </font>
<br><font size=2 face="sans-serif"> """ Contains
a SSH connection, runs commands, and stores results. """</font>
<br><font size=2 face="sans-serif"> #def __init__(self, host,
username, password, cmds):</font>
<br>
<br><font size=2 face="sans-serif"> def run_commands(self,
host, username, password, cmds):</font>
<br><font size=2 face="sans-serif"> self.host
= host</font>
<br><font size=2 face="sans-serif"> self.username
= username</font>
<br><font size=2 face="sans-serif"> self.password
= password</font>
<br><font size=2 face="sans-serif"> self.cmds
= cmds</font>
<br><font size=2 face="sans-serif"> self.responses
= []</font>
<br><font size=2 face="sans-serif"> </font>
<br>
<br><font size=2 face="sans-serif"> self.factory
= ClientCommandFactory(self.username, self.password, self.cmds, self)</font>
<br><font size=2 face="sans-serif"> reactor.connectTCP(self.host,
22, self.factory)</font>
<br><font size=2 face="sans-serif"> #reactor.run()</font>
<br><font size=2 face="sans-serif"> for i, response
in enumerate(self.responses):</font>
<br><font size=2 face="sans-serif">
print i, response</font>
<br><font size=2 face="sans-serif">
print "=" * 25</font>
<br>
<br><font size=2 face="sans-serif">#print "\nDone."</font>
<br>
<br><font size=2 face="sans-serif">if __name__ == '__main__':</font>
<br><font size=2 face="sans-serif"> app = twistedModel.TwistedApplication(Dashboard)</font>
<br><font size=2 face="sans-serif"> app.MainLoop()</font>
<br><font size=2 face="sans-serif"><br>
</font>
<br><font size=2 face="sans-serif">Here's the PythonCard resource file:</font>
<br>
<br><font size=2 face="sans-serif">{'application':{'type':'Application',</font>
<br><font size=2 face="sans-serif"> 'name':'Minimal',</font>
<br><font size=2 face="sans-serif"> 'backgrounds': [</font>
<br><font size=2 face="sans-serif"> {'type':'Background',</font>
<br><font size=2 face="sans-serif"> 'name':'bgMin',</font>
<br><font size=2 face="sans-serif"> 'title':'Minimal
PythonCard Application',</font>
<br><font size=2 face="sans-serif"> 'size':(382,
271),</font>
<br>
<br><font size=2 face="sans-serif"> 'menubar':
{'type':'MenuBar',</font>
<br><font size=2 face="sans-serif"> 'menus':
[</font>
<br><font size=2 face="sans-serif">
{'type':'Menu',</font>
<br><font size=2 face="sans-serif">
'name':'menuFile',</font>
<br><font size=2 face="sans-serif">
'label':'&File',</font>
<br><font size=2 face="sans-serif">
'items': [</font>
<br><font size=2 face="sans-serif">
{'type':'MenuItem',</font>
<br><font size=2 face="sans-serif">
'name':'menuFileExit',</font>
<br><font size=2 face="sans-serif">
'label':'E&xit\tAlt+X',</font>
<br><font size=2 face="sans-serif">
'command':'exit',</font>
<br><font size=2 face="sans-serif">
},</font>
<br><font size=2 face="sans-serif">
]</font>
<br><font size=2 face="sans-serif">
},</font>
<br><font size=2 face="sans-serif"> ]</font>
<br><font size=2 face="sans-serif"> },</font>
<br><font size=2 face="sans-serif"> 'components':
[</font>
<br>
<br><font size=2 face="sans-serif">{'type':'Button', </font>
<br><font size=2 face="sans-serif"> 'name':'btCheck', </font>
<br><font size=2 face="sans-serif"> 'position':(210, 186),
</font>
<br><font size=2 face="sans-serif"> 'label':u'Check', </font>
<br><font size=2 face="sans-serif"> },</font>
<br>
<br><font size=2 face="sans-serif">{'type':'Button', </font>
<br><font size=2 face="sans-serif"> 'name':'btSend', </font>
<br><font size=2 face="sans-serif"> 'position':(102, 185),
</font>
<br><font size=2 face="sans-serif"> 'label':u'Send', </font>
<br><font size=2 face="sans-serif"> },</font>
<br>
<br><font size=2 face="sans-serif">{'type':'CodeEditor', </font>
<br><font size=2 face="sans-serif"> 'name':'ceReponse', </font>
<br><font size=2 face="sans-serif"> 'position':(6, 33), </font>
<br><font size=2 face="sans-serif"> 'size':(360, 141), </font>
<br><font size=2 face="sans-serif"> 'backgroundColor':(255,
255, 255, 255), </font>
<br><font size=2 face="sans-serif"> },</font>
<br>
<br><font size=2 face="sans-serif">{'type':'TextField', </font>
<br><font size=2 face="sans-serif"> 'name':'field1', </font>
<br><font size=2 face="sans-serif"> 'position':(5, 5), </font>
<br><font size=2 face="sans-serif"> 'size':(150, -1), </font>
<br><font size=2 face="sans-serif"> 'text':u'Hello PythonCard',
</font>
<br><font size=2 face="sans-serif"> },</font>
<br>
<br><font size=2 face="sans-serif">] # end components</font>
<br><font size=2 face="sans-serif">} # end background</font>
<br><font size=2 face="sans-serif">] # end backgrounds</font>
<br><font size=2 face="sans-serif">} }</font>
<br>
<br>
<br><tt><font size=2>twisted-python-bounces@twistedmatrix.com wrote on
10/07/2007 01:04:56 PM:<br>
<br>
> Hi list, this is my first post :p<br>
> <br>
> I'm new to Twisted/Conch and I was wondering how can I modify the
<br>
> sshsimpleclient.py in order to run several commands, on a user <br>
> request mode, without the need to authenticate just before every <br>
> command, just like a normal interactive ssh session. This is for a
<br>
> GUI front end I'm writing (PythonCard) that will execute some <br>
> benchmarks on a remote server. <br>
> <br>
> Thanks in advance...<br>
> <br>
> Raul_______________________________________________<br>
> Twisted-Python mailing list<br>
> Twisted-Python@twistedmatrix.com<br>
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python<br>
</font></tt>