40
42
ParamikoNotPresent,
42
from bzrlib.osutils import pathjoin, fancy_rename
44
from bzrlib.osutils import pathjoin, fancy_rename, getcwd
43
45
from bzrlib.trace import mutter, warning, error
44
46
from bzrlib.transport import (
45
47
register_urlparse_netloc_protocol,
103
# don't use prefetch unless paramiko version >= 1.5.2 (there were bugs earlier)
104
_default_do_prefetch = False
105
if getattr(paramiko, '__version_info__', (0, 0, 0)) >= (1, 5, 5):
106
_default_do_prefetch = True
105
_paramiko_version = getattr(paramiko, '__version_info__', (0, 0, 0))
106
# don't use prefetch unless paramiko version >= 1.5.5 (there were bugs earlier)
107
_default_do_prefetch = (_paramiko_version >= (1, 5, 5))
109
# Paramiko 1.5 tries to open a socket.AF_UNIX in order to connect
110
# to ssh-agent. That attribute doesn't exist on win32 (it does in cygwin)
111
# so we get an AttributeError exception. So we will not try to
112
# connect to an agent if we are on win32 and using Paramiko older than 1.6
113
_use_ssh_agent = (sys.platform != 'win32' or _paramiko_version >= (1, 6, 0))
109
116
_ssh_vendor = None
373
381
basepath.append(p)
375
383
path = '/'.join(basepath)
384
# mutter('relpath => remotepath %s => %s', relpath, path)
378
387
def relpath(self, abspath):
497
506
def mkdir(self, relpath, mode=None):
498
507
"""Create a directory at the given path."""
508
path = self._remote_path(relpath)
500
path = self._remote_path(relpath)
501
510
# In the paramiko documentation, it says that passing a mode flag
502
511
# will filtered against the server umask.
503
512
# StubSFTPServer does not do this, which would be nice, because it is
702
711
vendor = _get_ssh_vendor()
703
712
if vendor == 'loopback':
704
713
sock = socket.socket()
705
sock.connect((self._host, self._port))
715
sock.connect((self._host, self._port))
716
except socket.error, e:
717
raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
718
% (self._host, self._port, e))
706
719
self._sftp = SFTPClient(LoopbackSFTP(sock))
707
720
elif vendor != 'none':
708
721
sock = SFTPSubprocess(self._host, vendor, self._port,
723
736
t.set_log_channel('bzr.paramiko')
725
738
except paramiko.SSHException, e:
726
raise ConnectionError('Unable to reach SSH host %s:%d' %
727
(self._host, self._port), e)
739
raise ConnectionError('Unable to reach SSH host %s:%s: %s'
740
% (self._host, self._port, e))
729
742
server_key = t.get_remote_server_key()
730
743
server_key_hex = paramiko.util.hexify(server_key.get_fingerprint())
767
780
# Also, it would mess up the self.relpath() functionality
768
781
username = self._username or getpass.getuser()
770
# Paramiko tries to open a socket.AF_UNIX in order to connect
771
# to ssh-agent. That attribute doesn't exist on win32 (it does in cygwin)
772
# so we get an AttributeError exception. For now, just don't try to
773
# connect to an agent if we are on win32
774
if sys.platform != 'win32':
775
784
agent = paramiko.Agent()
776
785
for key in agent.get_keys():
777
786
mutter('Trying SSH agent key %s' % paramiko.util.hexify(key.get_fingerprint()))
883
893
nvuQES5C9BMHjF39LZiGH1iLQy7FgdHyoP+eodI7
884
894
-----END RSA PRIVATE KEY-----
888
class SingleListener(threading.Thread):
898
class SocketListener(threading.Thread):
890
900
def __init__(self, callback):
891
901
threading.Thread.__init__(self)
895
905
self._socket.bind(('localhost', 0))
896
906
self._socket.listen(1)
897
907
self.port = self._socket.getsockname()[1]
898
self.stop_event = threading.Event()
901
s, _ = self._socket.accept()
902
# now close the listen socket
905
self._callback(s, self.stop_event)
907
pass #Ignore socket errors
909
# probably a failed test
910
warning('Exception from within unit test server thread: %r' % x)
908
self._stop_event = threading.Event()
913
self.stop_event.set()
911
# called from outside this thread
912
self._stop_event.set()
914
913
# use a timeout here, because if the test fails, the server thread may
915
914
# never notice the stop_event.
920
readable, writable_unused, exception_unused = \
921
select.select([self._socket], [], [], 0.1)
922
if self._stop_event.isSet():
924
if len(readable) == 0:
927
s, addr_unused = self._socket.accept()
928
# because the loopback socket is inline, and transports are
929
# never explicitly closed, best to launch a new thread.
930
threading.Thread(target=self._callback, args=(s,)).start()
931
except socket.error, x:
932
sys.excepthook(*sys.exc_info())
933
warning('Socket error during accept() within unit test server'
936
# probably a failed test; unit test thread will log the
938
sys.excepthook(*sys.exc_info())
939
warning('Exception from within unit test server thread: %r' %
919
943
class SFTPServer(Server):
937
961
"""StubServer uses this to log when a new server is created."""
938
962
self.logs.append(message)
940
def _run_server(self, s, stop_event):
964
def _run_server(self, s):
941
965
ssh_server = paramiko.Transport(s)
942
key_file = os.path.join(self._homedir, 'test_rsa.key')
943
file(key_file, 'w').write(STUB_SERVER_KEY)
966
key_file = pathjoin(self._homedir, 'test_rsa.key')
967
f = open(key_file, 'w')
968
f.write(STUB_SERVER_KEY)
944
970
host_key = paramiko.RSAKey.from_private_key_file(key_file)
945
971
ssh_server.add_server_key(host_key)
946
972
server = StubServer(self)
950
976
event = threading.Event()
951
977
ssh_server.start_server(event, server)
953
stop_event.wait(30.0)
956
981
global _ssh_vendor
957
982
self._original_vendor = _ssh_vendor
958
983
_ssh_vendor = self._vendor
959
self._homedir = os.getcwd()
984
if sys.platform == 'win32':
985
# Win32 needs to use the UNICODE api
986
self._homedir = getcwd()
988
# But Linux SFTP servers should just deal in bytestreams
989
self._homedir = os.getcwd()
960
990
if self._server_homedir is None:
961
991
self._server_homedir = self._homedir
963
# FIXME WINDOWS: _root should be _server_homedir[0]:/
964
self._listener = SingleListener(self._run_server)
993
if sys.platform == 'win32':
995
self._listener = SocketListener(self._run_server)
965
996
self._listener.setDaemon(True)
966
997
self._listener.start()
971
1002
self._listener.stop()
972
1003
_ssh_vendor = self._original_vendor
1005
def get_bogus_url(self):
1006
"""See bzrlib.transport.Server.get_bogus_url."""
1007
# this is chosen to try to prevent trouble with proxies, wierd dns,
1009
return 'sftp://127.0.0.1:1/'
975
1013
class SFTPFullAbsoluteServer(SFTPServer):
976
1014
"""A test server for sftp transports, using absolute urls and ssh."""
987
1025
super(SFTPServerWithoutSSH, self).__init__()
988
1026
self._vendor = 'loopback'
990
def _run_server(self, sock, stop_event):
1028
def _run_server(self, sock):
991
1029
class FakeChannel(object):
992
1030
def get_transport(self):
1003
1041
server = paramiko.SFTPServer(FakeChannel(), 'sftp', StubServer(self), StubSFTPServer,
1004
1042
root=self._root, home=self._server_homedir)
1005
server.start_subsystem('sftp', None, sock)
1044
server.start_subsystem('sftp', None, sock)
1045
except socket.error, e:
1046
if (len(e.args) > 0) and (e.args[0] == errno.EPIPE):
1047
# it's okay for the client to disconnect abruptly
1048
# (bug in paramiko 1.6: it should absorb this exception)
1052
except Exception, e:
1053
import sys; sys.stderr.write('\nEXCEPTION %r\n\n' % e.__class__)
1006
1054
server.finish_subsystem()
1012
1060
def get_url(self):
1013
1061
"""See bzrlib.transport.Server.get_url."""
1014
return self._get_sftp_url(urlutils.escape(self._homedir[1:]))
1062
if sys.platform == 'win32':
1063
return self._get_sftp_url(urlutils.escape(self._homedir))
1065
return self._get_sftp_url(urlutils.escape(self._homedir[1:]))
1017
1068
class SFTPHomeDirServer(SFTPServerWithoutSSH):