18a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#
28a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen# Eric S. Raymond
38a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#
48a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen# Greatly modified by Nigel W. Moriarty
58a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen# April 2003
68a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#
78a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenfrom pexpect import *
88a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenimport os, sys
98a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenimport getpass
108a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenimport time
118a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
128a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenclass ssh_session:
138a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
148a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    "Session with extra state including the password to be used."
158a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
168a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def __init__(self, user, host, password=None, verbose=0):
178a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
188a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.user = user
198a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.host = host
208a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.verbose = verbose
218a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.password = password
228a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.keys = [
238a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            'authenticity',
248a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            'assword:',
258a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            '@@@@@@@@@@@@',
268a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            'Command not found.',
278a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            EOF,
288a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            ]
298a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
308a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.f = open('ssh.out','w')
318a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
328a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def __repr__(self):
338a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
348a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        outl = 'class :'+self.__class__.__name__
358a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        for attr in self.__dict__:
368a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            if attr == 'password':
378a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                outl += '\n\t'+attr+' : '+'*'*len(self.password)
388a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            else:
398a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                outl += '\n\t'+attr+' : '+str(getattr(self, attr))
408a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        return outl
418a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
428a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def __exec(self, command):
438a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
448a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        "Execute a command on the remote host.    Return the output."
458a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        child = spawn(command,
468a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                                    #timeout=10,
478a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                                    )
488a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        if self.verbose:
498a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            sys.stderr.write("-> " + command + "\n")
508a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        seen = child.expect(self.keys)
518a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.f.write(str(child.before) + str(child.after)+'\n')
528a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        if seen == 0:
538a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            child.sendline('yes')
548a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            seen = child.expect(self.keys)
558a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        if seen == 1:
568a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            if not self.password:
578a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                self.password = getpass.getpass('Remote password: ')
588a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            child.sendline(self.password)
598a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            child.readline()
608a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            time.sleep(5)
618a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            # Added to allow the background running of remote process
628a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            if not child.isalive():
638a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                seen = child.expect(self.keys)
648a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        if seen == 2:
658a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            lines = child.readlines()
668a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            self.f.write(lines)
678a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        if self.verbose:
688a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            sys.stderr.write("<- " + child.before + "|\n")
698a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        try:
708a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            self.f.write(str(child.before) + str(child.after)+'\n')
718a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        except:
728a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            pass
738a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.f.close()
748a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        return child.before
758a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
768a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def ssh(self, command):
778a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
788a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        return self.__exec("ssh -l %s %s \"%s\"" \
798a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                                             % (self.user,self.host,command))
808a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
818a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def scp(self, src, dst):
828a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
838a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        return self.__exec("scp %s %s@%s:%s" \
848a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                                             % (src, session.user, session.host, dst))
858a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
868a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def exists(self, file):
878a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
888a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        "Retrieve file permissions of specified remote file."
898a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        seen = self.ssh("/bin/ls -ld %s" % file)
908a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        if string.find(seen, "No such file") > -1:
918a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            return None # File doesn't exist
928a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        else:
938a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            return seen.split()[0] # Return permission field of listing.
948a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
95