| OLD | NEW | 
|---|
| 1 # Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ | 1 # Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ | 
| 2 # | 2 # | 
| 3 # Permission is hereby granted, free of charge, to any person obtaining a | 3 # Permission is hereby granted, free of charge, to any person obtaining a | 
| 4 # copy of this software and associated documentation files (the | 4 # copy of this software and associated documentation files (the | 
| 5 # "Software"), to deal in the Software without restriction, including | 5 # "Software"), to deal in the Software without restriction, including | 
| 6 # without limitation the rights to use, copy, modify, merge, publish, dis- | 6 # without limitation the rights to use, copy, modify, merge, publish, dis- | 
| 7 # tribute, sublicense, and/or sell copies of the Software, and to permit | 7 # tribute, sublicense, and/or sell copies of the Software, and to permit | 
| 8 # persons to whom the Software is furnished to do so, subject to the fol- | 8 # persons to whom the Software is furnished to do so, subject to the fol- | 
| 9 # lowing conditions: | 9 # lowing conditions: | 
| 10 # | 10 # | 
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 65                 print "%s has an entry in ~/.ssh/known_hosts and it doesn't matc
     h" % self.server.hostname | 65                 print "%s has an entry in ~/.ssh/known_hosts and it doesn't matc
     h" % self.server.hostname | 
| 66                 print 'Edit that file to remove the entry and then hit return to
      try again' | 66                 print 'Edit that file to remove the entry and then hit return to
      try again' | 
| 67                 raw_input('Hit Enter when ready') | 67                 raw_input('Hit Enter when ready') | 
| 68                 retry += 1 | 68                 retry += 1 | 
| 69             except EOFError: | 69             except EOFError: | 
| 70                 print 'Unexpected Error from SSH Connection, retry in 5 seconds' | 70                 print 'Unexpected Error from SSH Connection, retry in 5 seconds' | 
| 71                 time.sleep(5) | 71                 time.sleep(5) | 
| 72                 retry += 1 | 72                 retry += 1 | 
| 73         print 'Could not establish SSH connection' | 73         print 'Could not establish SSH connection' | 
| 74 | 74 | 
| 75     def get_file(self, src, dst): |  | 
| 76         sftp_client = self._ssh_client.open_sftp() |  | 
| 77         sftp_client.get(src, dst) |  | 
| 78 |  | 
| 79     def put_file(self, src, dst): |  | 
| 80         sftp_client = self._ssh_client.open_sftp() |  | 
| 81         sftp_client.put(src, dst) |  | 
| 82 |  | 
| 83     def listdir(self, path): |  | 
| 84         sftp_client = self._ssh_client.open_sftp() |  | 
| 85         return sftp_client.listdir(path) |  | 
| 86 |  | 
| 87     def open_sftp(self): | 75     def open_sftp(self): | 
| 88         return self._ssh_client.open_sftp() | 76         return self._ssh_client.open_sftp() | 
| 89 | 77 | 
|  | 78     def get_file(self, src, dst): | 
|  | 79         sftp_client = self.open_sftp() | 
|  | 80         sftp_client.get(src, dst) | 
|  | 81 | 
|  | 82     def put_file(self, src, dst): | 
|  | 83         sftp_client = self.open_sftp() | 
|  | 84         sftp_client.put(src, dst) | 
|  | 85 | 
|  | 86     def open(self, filename, mode='r', bufsize=-1): | 
|  | 87         """ | 
|  | 88         Open a file on the remote system and return a file-like object. | 
|  | 89         """ | 
|  | 90         sftp_client = self.open_sftp() | 
|  | 91         return sftp_client.open(filename, mode, bufsize) | 
|  | 92 | 
|  | 93     def listdir(self, path): | 
|  | 94         sftp_client = self.open_sftp() | 
|  | 95         return sftp_client.listdir(path) | 
|  | 96 | 
| 90     def isdir(self, path): | 97     def isdir(self, path): | 
| 91         status = self.run('[ -d %s ] || echo "FALSE"' % path) | 98         status = self.run('[ -d %s ] || echo "FALSE"' % path) | 
| 92         if status[1].startswith('FALSE'): | 99         if status[1].startswith('FALSE'): | 
| 93             return 0 | 100             return 0 | 
| 94         return 1 | 101         return 1 | 
| 95 | 102 | 
| 96     def exists(self, path): | 103     def exists(self, path): | 
| 97         status = self.run('[ -a %s ] || echo "FALSE"' % path) | 104         status = self.run('[ -a %s ] || echo "FALSE"' % path) | 
| 98         if status[1].startswith('FALSE'): | 105         if status[1].startswith('FALSE'): | 
| 99             return 0 | 106             return 0 | 
| 100         return 1 | 107         return 1 | 
| 101 | 108 | 
| 102     def shell(self): | 109     def shell(self): | 
|  | 110         """ | 
|  | 111         Start an interactive shell session on the remote host. | 
|  | 112         """ | 
| 103         channel = self._ssh_client.invoke_shell() | 113         channel = self._ssh_client.invoke_shell() | 
| 104         interactive_shell(channel) | 114         interactive_shell(channel) | 
| 105 | 115 | 
| 106     def run(self, command): | 116     def run(self, command): | 
| 107         boto.log.info('running:%s on %s' % (command, self.server.instance_id)) | 117         """ | 
| 108         log_fp = StringIO.StringIO() | 118         Execute a command on the remote host.  Return a tuple containing | 
|  | 119         an integer status and a two strings, the first containing stdout | 
|  | 120         and the second containing stderr from the command. | 
|  | 121         """ | 
|  | 122         boto.log.debug('running:%s on %s' % (command, self.server.instance_id)) | 
| 109         status = 0 | 123         status = 0 | 
| 110         try: | 124         try: | 
| 111             t = self._ssh_client.exec_command(command) | 125             t = self._ssh_client.exec_command(command) | 
| 112         except paramiko.SSHException: | 126         except paramiko.SSHException: | 
| 113             status = 1 | 127             status = 1 | 
| 114         log_fp.write(t[1].read()) | 128         std_out = t[1].read() | 
| 115         log_fp.write(t[2].read()) | 129         std_err = t[2].read() | 
| 116         t[0].close() | 130         t[0].close() | 
| 117         t[1].close() | 131         t[1].close() | 
| 118         t[2].close() | 132         t[2].close() | 
| 119         boto.log.info('output: %s' % log_fp.getvalue()) | 133         boto.log.debug('stdout: %s' % std_out) | 
| 120         return (status, log_fp.getvalue()) | 134         boto.log.debug('stderr: %s' % std_err) | 
|  | 135         return (status, std_out, std_err) | 
|  | 136 | 
|  | 137     def run_pty(self, command): | 
|  | 138         """ | 
|  | 139         Execute a command on the remote host with a pseudo-terminal. | 
|  | 140         Returns a string containing the output of the command. | 
|  | 141         """ | 
|  | 142         boto.log.debug('running:%s on %s' % (command, self.server.instance_id)) | 
|  | 143         channel = self._ssh_client.get_transport().open_session() | 
|  | 144         channel.get_pty() | 
|  | 145         channel.exec_command(command) | 
|  | 146         return channel.recv(1024) | 
| 121 | 147 | 
| 122     def close(self): | 148     def close(self): | 
| 123         transport = self._ssh_client.get_transport() | 149         transport = self._ssh_client.get_transport() | 
| 124         transport.close() | 150         transport.close() | 
| 125         self.server.reset_cmdshell() | 151         self.server.reset_cmdshell() | 
| 126 | 152 | 
| 127 class LocalClient(object): | 153 class LocalClient(object): | 
| 128 | 154 | 
| 129     def __init__(self, server, host_key_file=None, uname='root'): | 155     def __init__(self, server, host_key_file=None, uname='root'): | 
| 130         self.server = server | 156         self.server = server | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
| 159             t = process.communicate() | 185             t = process.communicate() | 
| 160             log_fp.write(t[0]) | 186             log_fp.write(t[0]) | 
| 161             log_fp.write(t[1]) | 187             log_fp.write(t[1]) | 
| 162         boto.log.info(log_fp.getvalue()) | 188         boto.log.info(log_fp.getvalue()) | 
| 163         boto.log.info('output: %s' % log_fp.getvalue()) | 189         boto.log.info('output: %s' % log_fp.getvalue()) | 
| 164         return (process.returncode, log_fp.getvalue()) | 190         return (process.returncode, log_fp.getvalue()) | 
| 165 | 191 | 
| 166     def close(self): | 192     def close(self): | 
| 167         pass | 193         pass | 
| 168 | 194 | 
|  | 195 class FakeServer(object): | 
|  | 196     """ | 
|  | 197     A little class to fake out SSHClient (which is expecting a | 
|  | 198     :class`boto.manage.server.Server` instance.  This allows us | 
|  | 199     to | 
|  | 200     """ | 
|  | 201     def __init__(self, instance, ssh_key_file): | 
|  | 202         self.instance = instance | 
|  | 203         self.ssh_key_file = ssh_key_file | 
|  | 204         self.hostname = instance.dns_name | 
|  | 205         self.instance_id = self.instance.id | 
|  | 206 | 
| 169 def start(server): | 207 def start(server): | 
| 170     instance_id = boto.config.get('Instance', 'instance-id', None) | 208     instance_id = boto.config.get('Instance', 'instance-id', None) | 
| 171     if instance_id == server.instance_id: | 209     if instance_id == server.instance_id: | 
| 172         return LocalClient(server) | 210         return LocalClient(server) | 
| 173     else: | 211     else: | 
| 174         return SSHClient(server) | 212         return SSHClient(server) | 
|  | 213 | 
|  | 214 def sshclient_from_instance(instance, ssh_key_file, | 
|  | 215                             host_key_file='~/.ssh/known_hosts', | 
|  | 216                             user_name='root', ssh_pwd=None): | 
|  | 217     """ | 
|  | 218     Create and return an SSHClient object given an | 
|  | 219     instance object. | 
|  | 220 | 
|  | 221     :type instance: :class`boto.ec2.instance.Instance` object | 
|  | 222     :param instance: The instance object. | 
|  | 223 | 
|  | 224     :type ssh_key_file: str | 
|  | 225     :param ssh_key_file: A path to the private key file used | 
|  | 226                          to log into instance. | 
|  | 227 | 
|  | 228     :type host_key_file: str | 
|  | 229     :param host_key_file: A path to the known_hosts file used | 
|  | 230                           by the SSH client. | 
|  | 231                           Defaults to ~/.ssh/known_hosts | 
|  | 232     :type user_name: str | 
|  | 233     :param user_name: The username to use when logging into | 
|  | 234                       the instance.  Defaults to root. | 
|  | 235 | 
|  | 236     :type ssh_pwd: str | 
|  | 237     :param ssh_pwd: The passphrase, if any, associated with | 
|  | 238                     private key. | 
|  | 239     """ | 
|  | 240     s = FakeServer(instance, ssh_key_file) | 
|  | 241     return SSHClient(s, host_key_file, user_name, ssh_pwd) | 
| OLD | NEW | 
|---|