~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/ssh.py

  • Committer: John Arbash Meinel
  • Date: 2006-12-01 19:41:16 UTC
  • mfrom: (2158 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2159.
  • Revision ID: john@arbash-meinel.com-20061201194116-nvn5qhfxux5284jc
[merge] bzr.dev 2158

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
from bzrlib.config import config_dir, ensure_config_dir_exists
28
28
from bzrlib.errors import (ConnectionError,
29
29
                           ParamikoNotPresent,
 
30
                           SocketConnectionError,
30
31
                           TransportError,
31
32
                           UnknownSSH,
32
33
                           )
38
39
try:
39
40
    import paramiko
40
41
except ImportError, e:
41
 
    raise ParamikoNotPresent(e)
 
42
    # If we have an ssh subprocess, we don't strictly need paramiko for all ssh
 
43
    # access
 
44
    paramiko = None
42
45
else:
43
46
    from paramiko.sftp_client import SFTPClient
44
47
 
106
109
    return _ssh_vendor
107
110
 
108
111
 
109
 
 
110
112
def _ignore_sigint():
111
113
    # TODO: This should possibly ignore SIGHUP as well, but bzr currently
112
114
    # doesn't handle it itself.
161
163
        """
162
164
        raise NotImplementedError(self.connect_ssh)
163
165
        
 
166
    def _raise_connection_error(self, host, port=None, orig_error=None,
 
167
                                msg='Unable to connect to SSH host'):
 
168
        """Raise a SocketConnectionError with properly formatted host.
 
169
 
 
170
        This just unifies all the locations that try to raise ConnectionError,
 
171
        so that they format things properly.
 
172
        """
 
173
        raise SocketConnectionError(host=host, port=port, msg=msg,
 
174
                                    orig_error=orig_error)
 
175
 
164
176
 
165
177
class LoopbackVendor(SSHVendor):
166
178
    """SSH "vendor" that connects over a plain TCP socket, not SSH."""
170
182
        try:
171
183
            sock.connect((host, port))
172
184
        except socket.error, e:
173
 
            raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
174
 
                                  % (host, port, e))
 
185
            self._raise_connection_error(host, port=port, orig_error=e)
175
186
        return SFTPClient(LoopbackSFTP(sock))
176
187
 
177
188
register_ssh_vendor('loopback', LoopbackVendor())
201
212
            t.set_log_channel('bzr.paramiko')
202
213
            t.start_client()
203
214
        except (paramiko.SSHException, socket.error), e:
204
 
            raise ConnectionError('Unable to reach SSH host %s:%s: %s' 
205
 
                                  % (host, port, e))
 
215
            self._raise_connection_error(host, port=port, orig_error=e)
206
216
            
207
217
        server_key = t.get_remote_server_key()
208
218
        server_key_hex = paramiko.util.hexify(server_key.get_fingerprint())
215
225
            our_server_key_hex = paramiko.util.hexify(our_server_key.get_fingerprint())
216
226
        else:
217
227
            warning('Adding %s host key for %s: %s' % (keytype, host, server_key_hex))
218
 
            if host not in BZR_HOSTKEYS:
219
 
                BZR_HOSTKEYS[host] = {}
220
 
            BZR_HOSTKEYS[host][keytype] = server_key
 
228
            add = getattr(BZR_HOSTKEYS, 'add', None)
 
229
            if add is not None: # paramiko >= 1.X.X
 
230
                BZR_HOSTKEYS.add(host, keytype, server_key)
 
231
            else:
 
232
                BZR_HOSTKEYS.setdefault(host, {})[keytype] = server_key
221
233
            our_server_key = server_key
222
234
            our_server_key_hex = paramiko.util.hexify(our_server_key.get_fingerprint())
223
235
            save_host_keys()
236
248
        try:
237
249
            return t.open_sftp_client()
238
250
        except paramiko.SSHException, e:
239
 
            raise ConnectionError('Unable to start sftp client %s:%d' %
240
 
                                  (host, port), e)
 
251
            self._raise_connection_error(host, port=port, orig_error=e,
 
252
                                         msg='Unable to start sftp client')
241
253
 
242
254
    def connect_ssh(self, username, password, host, port, command):
243
255
        t = self._connect(username, password, host, port)
247
259
            channel.exec_command(cmdline)
248
260
            return _ParamikoSSHConnection(channel)
249
261
        except paramiko.SSHException, e:
250
 
            raise ConnectionError('Unable to invoke remote bzr %s:%d' %
251
 
                                  (host, port), e)
 
262
            self._raise_connection_error(host, port=port, orig_error=e,
 
263
                                         msg='Unable to invoke remote bzr')
252
264
 
253
 
register_ssh_vendor('paramiko', ParamikoVendor())
 
265
if paramiko is not None:
 
266
    register_ssh_vendor('paramiko', ParamikoVendor())
254
267
 
255
268
 
256
269
class SubprocessVendor(SSHVendor):
270
283
            sock = self._connect(argv)
271
284
            return SFTPClient(sock)
272
285
        except (EOFError, paramiko.SSHException), e:
273
 
            raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
274
 
                                  % (host, port, e))
 
286
            self._raise_connection_error(host, port=port, orig_error=e)
275
287
        except (OSError, IOError), e:
276
288
            # If the machine is fast enough, ssh can actually exit
277
289
            # before we try and send it the sftp request, which
278
290
            # raises a Broken Pipe
279
291
            if e.errno not in (errno.EPIPE,):
280
292
                raise
281
 
            raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
282
 
                                  % (host, port, e))
 
293
            self._raise_connection_error(host, port=port, orig_error=e)
283
294
 
284
295
    def connect_ssh(self, username, password, host, port, command):
285
296
        try:
287
298
                                                  command=command)
288
299
            return self._connect(argv)
289
300
        except (EOFError), e:
290
 
            raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
291
 
                                  % (host, port, e))
 
301
            self._raise_connection_error(host, port=port, orig_error=e)
292
302
        except (OSError, IOError), e:
293
303
            # If the machine is fast enough, ssh can actually exit
294
304
            # before we try and send it the sftp request, which
295
305
            # raises a Broken Pipe
296
306
            if e.errno not in (errno.EPIPE,):
297
307
                raise
298
 
            raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
299
 
                                  % (host, port, e))
 
308
            self._raise_connection_error(host, port=port, orig_error=e)
300
309
 
301
310
    def _get_vendor_specific_argv(self, username, host, port, subsystem=None,
302
311
                                  command=None):