/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2005, 2006, 2008-2011 Robey Pointer <robey@lag.net>, Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
16
17
"""
18
A stub SFTP server for loopback SFTP testing.
19
Adapted from the one in paramiko's unit tests.
20
"""
21
22
import os
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
23
import paramiko
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
24
import socket
6621.25.1 by Martin
Adapt to SocketServer module name change
25
try:
26
    import socketserver
27
except ImportError:
28
    import SocketServer as socketserver
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
29
import sys
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
30
import time
1666.1.6 by Robert Collins
Make knit the default format.
31
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
32
from .. import (
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
33
    osutils,
34
    trace,
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
35
    urlutils,
36
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
37
from ..transport import (
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
38
    ssh,
39
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
40
from . import test_server
5017.3.34 by Vincent Ladeuil
-s bt.per_branch passing
41
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
42
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
43
class StubServer(paramiko.ServerInterface):
1666.1.6 by Robert Collins
Make knit the default format.
44
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
45
    def __init__(self, test_case_server):
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
46
        paramiko.ServerInterface.__init__(self)
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
47
        self.log = test_case_server.log
1185.49.10 by John Arbash Meinel
Use a weakref dictionary to enable re-use of a connection (for sftp).
48
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
49
    def check_auth_password(self, username, password):
50
        # all are allowed
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
51
        self.log('sftpserver - authorizing: %s' % (username,))
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
52
        return paramiko.AUTH_SUCCESSFUL
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
53
54
    def check_channel_request(self, kind, chanid):
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
55
        self.log('sftpserver - channel request: %s, %s' % (kind, chanid))
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
56
        return paramiko.OPEN_SUCCEEDED
57
58
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
59
class StubSFTPHandle(paramiko.SFTPHandle):
60
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
61
    def stat(self):
62
        try:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
63
            return paramiko.SFTPAttributes.from_stat(
64
                os.fstat(self.readfile.fileno()))
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
65
        except OSError as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
66
            return paramiko.SFTPServer.convert_errno(e.errno)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
67
68
    def chattr(self, attr):
69
        # python doesn't have equivalents to fchown or fchmod, so we have to
70
        # use the stored filename
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
71
        trace.mutter('Changing permissions on %s to %s', self.filename, attr)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
72
        try:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
73
            paramiko.SFTPServer.set_file_attr(self.filename, attr)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
74
        except OSError as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
75
            return paramiko.SFTPServer.convert_errno(e.errno)
76
77
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
78
class StubSFTPServer(paramiko.SFTPServerInterface):
1666.1.6 by Robert Collins
Make knit the default format.
79
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
80
    def __init__(self, server, root, home=None):
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
81
        paramiko.SFTPServerInterface.__init__(self, server)
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
82
        # All paths are actually relative to 'root'.
83
        # this is like implementing chroot().
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
84
        self.root = root
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
85
        if home is None:
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
86
            self.home = ''
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
87
        else:
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
88
            if not home.startswith(self.root):
89
                raise AssertionError(
90
                    "home must be a subdirectory of root (%s vs %s)"
91
                    % (home, root))
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
92
            self.home = home[len(self.root):]
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
93
        if self.home.startswith('/'):
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
94
            self.home = self.home[1:]
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
95
        server.log('sftpserver - new connection')
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
96
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
97
    def _realpath(self, path):
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
98
        # paths returned from self.canonicalize() always start with
99
        # a path separator. So if 'root' is just '/', this would cause
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
100
        # a double slash at the beginning '//home/dir'.
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
101
        if self.root == '/':
102
            return self.canonicalize(path)
103
        return self.root + self.canonicalize(path)
104
105
    if sys.platform == 'win32':
106
        def canonicalize(self, path):
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
107
            # Win32 sftp paths end up looking like
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
108
            #     sftp://host@foo/h:/foo/bar
109
            # which means absolute paths look like:
110
            #     /h:/foo/bar
111
            # and relative paths stay the same:
112
            #     foo/bar
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
113
            # win32 needs to use the Unicode APIs. so we require the
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
114
            # paths to be utf8 (Linux just uses bytestreams)
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
115
            thispath = path.decode('utf8')
116
            if path.startswith('/'):
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
117
                # Abspath H:/foo/bar
118
                return os.path.normpath(thispath[1:])
119
            else:
120
                return os.path.normpath(os.path.join(self.home, thispath))
121
    else:
122
        def canonicalize(self, path):
123
            if os.path.isabs(path):
6015.39.2 by Florian Vichot
Fixed an infinite loop when creating a repo at the root of the filesystem,
124
                return osutils.normpath(path)
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
125
            else:
6015.39.2 by Florian Vichot
Fixed an infinite loop when creating a repo at the root of the filesystem,
126
                return osutils.normpath('/' + os.path.join(self.home, path))
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
127
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
128
    def chattr(self, path, attr):
129
        try:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
130
            paramiko.SFTPServer.set_file_attr(path, attr)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
131
        except OSError as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
132
            return paramiko.SFTPServer.convert_errno(e.errno)
133
        return paramiko.SFTP_OK
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
134
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
135
    def list_folder(self, path):
136
        path = self._realpath(path)
137
        try:
7143.15.2 by Jelmer Vernooij
Run autopep8.
138
            out = []
1685.1.72 by Wouter van Heyst
StubSFTPServer should use bytestreams rather than unicode
139
            # TODO: win32 incorrectly lists paths with non-ascii if path is not
5278.1.2 by Martin Pool
Don't say 'Linux' except when specifically talking about the kernel
140
            # unicode. However on unix the server should only deal with
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
141
            # bytestreams and posix.listdir does the right thing
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
142
            if sys.platform == 'win32':
143
                flist = [f.encode('utf8') for f in os.listdir(path)]
144
            else:
145
                flist = os.listdir(path)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
146
            for fname in flist:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
147
                attr = paramiko.SFTPAttributes.from_stat(
148
                    os.stat(osutils.pathjoin(path, fname)))
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
149
                attr.filename = fname
150
                out.append(attr)
151
            return out
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
152
        except OSError as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
153
            return paramiko.SFTPServer.convert_errno(e.errno)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
154
155
    def stat(self, path):
156
        path = self._realpath(path)
157
        try:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
158
            return paramiko.SFTPAttributes.from_stat(os.stat(path))
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
159
        except OSError as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
160
            return paramiko.SFTPServer.convert_errno(e.errno)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
161
162
    def lstat(self, path):
163
        path = self._realpath(path)
164
        try:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
165
            return paramiko.SFTPAttributes.from_stat(os.lstat(path))
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
166
        except OSError as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
167
            return paramiko.SFTPServer.convert_errno(e.errno)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
168
169
    def open(self, path, flags, attr):
170
        path = self._realpath(path)
171
        try:
1963.2.4 by Robey Pointer
remove usage of hasattr
172
            flags |= getattr(os, 'O_BINARY', 0)
1540.1.9 by John Arbash Meinel
Cleanup getattr() code, since getattr(None, '', None) still works
173
            if getattr(attr, 'st_mode', None):
1185.58.10 by John Arbash Meinel
[patch] Robey Pointer to fix sftp server using umask for files (failing tests for directories)
174
                fd = os.open(path, flags, attr.st_mode)
175
            else:
1988.1.1 by John Arbash Meinel
Restore mode bit tests for sftp, and track down bugs
176
                # os.open() defaults to 0777 which is
177
                # an odd default mode for files
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
178
                fd = os.open(path, flags, 0o666)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
179
        except OSError as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
180
            return paramiko.SFTPServer.convert_errno(e.errno)
1685.1.72 by Wouter van Heyst
StubSFTPServer should use bytestreams rather than unicode
181
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
182
        if (flags & os.O_CREAT) and (attr is not None):
1185.58.10 by John Arbash Meinel
[patch] Robey Pointer to fix sftp server using umask for files (failing tests for directories)
183
            attr._flags &= ~attr.FLAG_PERMISSIONS
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
184
            paramiko.SFTPServer.set_file_attr(path, attr)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
185
        if flags & os.O_WRONLY:
1185.31.51 by John Arbash Meinel
Setting binary flags for sftp.
186
            fstr = 'wb'
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
187
        elif flags & os.O_RDWR:
1185.31.51 by John Arbash Meinel
Setting binary flags for sftp.
188
            fstr = 'rb+'
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
189
        else:
190
            # O_RDONLY (== 0)
1185.31.51 by John Arbash Meinel
Setting binary flags for sftp.
191
            fstr = 'rb'
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
192
        try:
193
            f = os.fdopen(fd, fstr)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
194
        except (IOError, OSError) as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
195
            return paramiko.SFTPServer.convert_errno(e.errno)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
196
        fobj = StubSFTPHandle()
197
        fobj.filename = path
198
        fobj.readfile = f
199
        fobj.writefile = f
200
        return fobj
201
202
    def remove(self, path):
203
        path = self._realpath(path)
204
        try:
205
            os.remove(path)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
206
        except OSError as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
207
            return paramiko.SFTPServer.convert_errno(e.errno)
208
        return paramiko.SFTP_OK
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
209
210
    def rename(self, oldpath, newpath):
211
        oldpath = self._realpath(oldpath)
212
        newpath = self._realpath(newpath)
213
        try:
214
            os.rename(oldpath, newpath)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
215
        except OSError as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
216
            return paramiko.SFTPServer.convert_errno(e.errno)
217
        return paramiko.SFTP_OK
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
218
7058.2.1 by Jelmer Vernooij
Support symlink creation for SFTP.
219
    def symlink(self, target_path, path):
220
        path = self._realpath(path)
221
        try:
222
            os.symlink(target_path, path)
223
        except OSError as e:
224
            return paramiko.SFTPServer.convert_errno(e.errno)
225
        return paramiko.SFTP_OK
226
7119.2.2 by Jelmer Vernooij
Test readlink.
227
    def readlink(self, path):
228
        path = self._realpath(path)
229
        try:
230
            target_path = os.readlink(path)
231
        except OSError as e:
232
            return paramiko.SFTPServer.convert_errno(e.errno)
233
        return target_path
234
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
235
    def mkdir(self, path, attr):
236
        path = self._realpath(path)
237
        try:
1540.1.5 by John Arbash Meinel
Bugfix to allow using paramiko > 1.5.2
238
            # Using getattr() in case st_mode is None or 0
239
            # both evaluate to False
1540.1.9 by John Arbash Meinel
Cleanup getattr() code, since getattr(None, '', None) still works
240
            if getattr(attr, 'st_mode', None):
1185.58.11 by John Arbash Meinel
Made the StubSFTPServer use umask even for mkdir()
241
                os.mkdir(path, attr.st_mode)
242
            else:
243
                os.mkdir(path)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
244
            if attr is not None:
1185.58.11 by John Arbash Meinel
Made the StubSFTPServer use umask even for mkdir()
245
                attr._flags &= ~attr.FLAG_PERMISSIONS
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
246
                paramiko.SFTPServer.set_file_attr(path, attr)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
247
        except OSError as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
248
            return paramiko.SFTPServer.convert_errno(e.errno)
249
        return paramiko.SFTP_OK
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
250
251
    def rmdir(self, path):
252
        path = self._realpath(path)
253
        try:
254
            os.rmdir(path)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
255
        except OSError as e:
4797.11.1 by Vincent Ladeuil
Fix test.stub_sftp imports.
256
            return paramiko.SFTPServer.convert_errno(e.errno)
257
        return paramiko.SFTP_OK
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
258
7119.2.2 by Jelmer Vernooij
Test readlink.
259
    # removed: chattr
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
260
    # (nothing in bzr's sftp transport uses those)
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
261
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
262
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
263
# ------------- server test implementation --------------
264
7290.42.6 by Jelmer Vernooij
Fix compatibility with newer versions of paramiko, which break on noise before keys in pem files.
265
STUB_SERVER_KEY = """\
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
266
-----BEGIN RSA PRIVATE KEY-----
267
MIICWgIBAAKBgQDTj1bqB4WmayWNPB+8jVSYpZYk80Ujvj680pOTh2bORBjbIAyz
268
oWGW+GUjzKxTiiPvVmxFgx5wdsFvF03v34lEVVhMpouqPAYQ15N37K/ir5XY+9m/
269
d8ufMCkjeXsQkKqFbAlQcnWMCRnOoPHS3I4vi6hmnDDeeYTSRvfLbW0fhwIBIwKB
270
gBIiOqZYaoqbeD9OS9z2K9KR2atlTxGxOJPXiP4ESqP3NVScWNwyZ3NXHpyrJLa0
271
EbVtzsQhLn6rF+TzXnOlcipFvjsem3iYzCpuChfGQ6SovTcOjHV9z+hnpXvQ/fon
272
soVRZY65wKnF7IAoUwTmJS9opqgrN6kRgCd3DASAMd1bAkEA96SBVWFt/fJBNJ9H
273
tYnBKZGw0VeHOYmVYbvMSstssn8un+pQpUm9vlG/bp7Oxd/m+b9KWEh2xPfv6zqU
274
avNwHwJBANqzGZa/EpzF4J8pGti7oIAPUIDGMtfIcmqNXVMckrmzQ2vTfqtkEZsA
275
4rE1IERRyiJQx6EJsz21wJmGV9WJQ5kCQQDwkS0uXqVdFzgHO6S++tjmjYcxwr3g
276
H0CoFYSgbddOT6miqRskOQF3DZVkJT3kyuBgU2zKygz52ukQZMqxCb1fAkASvuTv
277
qfpH87Qq5kQhNKdbbwbmd2NxlNabazPijWuphGTdW0VfJdWfklyS2Kr+iqrs/5wV
278
HhathJt636Eg7oIjAkA8ht3MQ+XSl9yIJIS8gVpbPxSw5OMfw0PjVE7tBdQruiSc
279
nvuQES5C9BMHjF39LZiGH1iLQy7FgdHyoP+eodI7
280
-----END RSA PRIVATE KEY-----
281
"""
282
283
284
class SocketDelay(object):
285
    """A socket decorator to make TCP appear slower.
286
287
    This changes recv, send, and sendall to add a fixed latency to each python
288
    call if a new roundtrip is detected. That is, when a recv is called and the
289
    flag new_roundtrip is set, latency is charged. Every send and send_all
290
    sets this flag.
291
292
    In addition every send, sendall and recv sleeps a bit per character send to
293
    simulate bandwidth.
294
295
    Not all methods are implemented, this is deliberate as this class is not a
296
    replacement for the builtin sockets layer. fileno is not implemented to
297
    prevent the proxy being bypassed.
298
    """
299
300
    simulated_time = 0
301
    _proxied_arguments = dict.fromkeys([
302
        "close", "getpeername", "getsockname", "getsockopt", "gettimeout",
303
        "setblocking", "setsockopt", "settimeout", "shutdown"])
304
305
    def __init__(self, sock, latency, bandwidth=1.0,
306
                 really_sleep=True):
307
        """
308
        :param bandwith: simulated bandwith (MegaBit)
309
        :param really_sleep: If set to false, the SocketDelay will just
310
        increase a counter, instead of calling time.sleep. This is useful for
311
        unittesting the SocketDelay.
312
        """
313
        self.sock = sock
314
        self.latency = latency
315
        self.really_sleep = really_sleep
316
        self.time_per_byte = 1 / (bandwidth / 8.0 * 1024 * 1024)
317
        self.new_roundtrip = False
318
319
    def sleep(self, s):
320
        if self.really_sleep:
321
            time.sleep(s)
322
        else:
323
            SocketDelay.simulated_time += s
324
325
    def __getattr__(self, attr):
326
        if attr in SocketDelay._proxied_arguments:
327
            return getattr(self.sock, attr)
328
        raise AttributeError("'SocketDelay' object has no attribute %r" %
329
                             attr)
330
331
    def dup(self):
332
        return SocketDelay(self.sock.dup(), self.latency, self.time_per_byte,
333
                           self._sleep)
334
335
    def recv(self, *args):
336
        data = self.sock.recv(*args)
337
        if data and self.new_roundtrip:
338
            self.new_roundtrip = False
339
            self.sleep(self.latency)
340
        self.sleep(len(data) * self.time_per_byte)
341
        return data
342
343
    def sendall(self, data, flags=0):
344
        if not self.new_roundtrip:
345
            self.new_roundtrip = True
346
            self.sleep(self.latency)
347
        self.sleep(len(data) * self.time_per_byte)
348
        return self.sock.sendall(data, flags)
349
350
    def send(self, data, flags=0):
351
        if not self.new_roundtrip:
352
            self.new_roundtrip = True
353
            self.sleep(self.latency)
354
        bytes_sent = self.sock.send(data, flags)
355
        self.sleep(bytes_sent * self.time_per_byte)
356
        return bytes_sent
357
358
6621.25.1 by Martin
Adapt to SocketServer module name change
359
class TestingSFTPConnectionHandler(socketserver.BaseRequestHandler):
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
360
361
    def setup(self):
362
        self.wrap_for_latency()
363
        tcs = self.server.test_case_server
5397.2.10 by John Arbash Meinel
refactor a little bit, so it is clearer what is going on.
364
        ptrans = paramiko.Transport(self.request)
365
        self.paramiko_transport = ptrans
5397.2.3 by John Arbash Meinel
Do it a different way by overriding the logging chosen
366
        # Set it to a channel under 'bzr' so that we get debug info
6658.4.1 by Martin
Correct sftp logging name hack in tests
367
        ptrans.set_log_channel('brz.paramiko.transport')
5397.2.10 by John Arbash Meinel
refactor a little bit, so it is clearer what is going on.
368
        ptrans.add_server_key(tcs.get_host_key())
369
        ptrans.set_subsystem_handler('sftp', paramiko.SFTPServer,
370
                                     StubSFTPServer, root=tcs._root,
371
                                     home=tcs._server_homedir)
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
372
        server = tcs._server_interface(tcs)
5397.2.1 by John Arbash Meinel
Instead of time.sleep() wait for paramiko to actually finish.
373
        # This blocks until the key exchange has been done
5397.2.10 by John Arbash Meinel
refactor a little bit, so it is clearer what is going on.
374
        ptrans.start_server(None, server)
375
376
    def finish(self):
377
        # Wait for the conversation to finish, when the paramiko.Transport
378
        # thread finishes
379
        # TODO: Consider timing out after XX seconds rather than hanging.
380
        #       Also we could check paramiko_transport.active and possibly
381
        #       paramiko_transport.getException().
382
        self.paramiko_transport.join()
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
383
384
    def wrap_for_latency(self):
385
        tcs = self.server.test_case_server
386
        if tcs.add_latency:
387
            # Give the socket (which the request really is) a latency adding
388
            # decorator.
389
            self.request = SocketDelay(self.request, tcs.add_latency)
390
391
392
class TestingSFTPWithoutSSHConnectionHandler(TestingSFTPConnectionHandler):
393
394
    def setup(self):
395
        self.wrap_for_latency()
396
        # Re-import these as locals, so that they're still accessible during
397
        # interpreter shutdown (when all module globals get set to None, leading
398
        # to confusing errors like "'NoneType' object has no attribute 'error'".
7143.15.2 by Jelmer Vernooij
Run autopep8.
399
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
400
        class FakeChannel(object):
401
            def get_transport(self):
402
                return self
7143.15.2 by Jelmer Vernooij
Run autopep8.
403
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
404
            def get_log_channel(self):
6658.4.1 by Martin
Correct sftp logging name hack in tests
405
                return 'brz.paramiko'
7143.15.2 by Jelmer Vernooij
Run autopep8.
406
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
407
            def get_name(self):
408
                return '1'
7143.15.2 by Jelmer Vernooij
Run autopep8.
409
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
410
            def get_hexdump(self):
411
                return False
7143.15.2 by Jelmer Vernooij
Run autopep8.
412
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
413
            def close(self):
414
                pass
415
416
        tcs = self.server.test_case_server
5397.2.11 by John Arbash Meinel
Add a .finish method to the sftp version as well.
417
        sftp_server = paramiko.SFTPServer(
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
418
            FakeChannel(), 'sftp', StubServer(tcs), StubSFTPServer,
419
            root=tcs._root, home=tcs._server_homedir)
5397.2.11 by John Arbash Meinel
Add a .finish method to the sftp version as well.
420
        self.sftp_server = sftp_server
7143.15.2 by Jelmer Vernooij
Run autopep8.
421
        sys_stderr = sys.stderr  # Used in error reporting during shutdown
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
422
        try:
5397.2.11 by John Arbash Meinel
Add a .finish method to the sftp version as well.
423
            sftp_server.start_subsystem(
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
424
                'sftp', None, ssh.SocketAsChannelAdapter(self.request))
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
425
        except socket.error as e:
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
426
            if (len(e.args) > 0) and (e.args[0] == errno.EPIPE):
427
                # it's okay for the client to disconnect abruptly
428
                # (bug in paramiko 1.6: it should absorb this exception)
429
                pass
430
            else:
431
                raise
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
432
        except Exception as e:
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
433
            # This typically seems to happen during interpreter shutdown, so
434
            # most of the useful ways to report this error won't work.
435
            # Writing the exception type, and then the text of the exception,
436
            # seems to be the best we can do.
437
            # FIXME: All interpreter shutdown errors should have been related
438
            # to daemon threads, cleanup needed -- vila 20100623
5397.2.11 by John Arbash Meinel
Add a .finish method to the sftp version as well.
439
            sys_stderr.write('\nEXCEPTION %r: ' % (e.__class__,))
440
            sys_stderr.write('%s\n\n' % (e,))
441
442
    def finish(self):
443
        self.sftp_server.finish_subsystem()
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
444
445
446
class TestingSFTPServer(test_server.TestingThreadingTCPServer):
447
448
    def __init__(self, server_address, request_handler_class, test_case_server):
449
        test_server.TestingThreadingTCPServer.__init__(
450
            self, server_address, request_handler_class)
451
        self.test_case_server = test_case_server
452
453
454
class SFTPServer(test_server.TestingTCPServerInAThread):
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
455
    """Common code for SFTP server facilities."""
456
457
    def __init__(self, server_interface=StubServer):
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
458
        self.host = '127.0.0.1'
459
        self.port = 0
460
        super(SFTPServer, self).__init__((self.host, self.port),
461
                                         TestingSFTPServer,
462
                                         TestingSFTPConnectionHandler)
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
463
        self._original_vendor = None
464
        self._vendor = ssh.ParamikoVendor()
465
        self._server_interface = server_interface
5247.4.24 by Vincent Ladeuil
Create the ssh host key only once for a given sftp test server.
466
        self._host_key = None
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
467
        self.logs = []
468
        self.add_latency = 0
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
469
        self._homedir = None
470
        self._server_homedir = None
471
        self._root = None
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
472
473
    def _get_sftp_url(self, path):
474
        """Calculate an sftp url to this server for path."""
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
475
        return "sftp://foo:bar@%s:%s/%s" % (self.host, self.port, path)
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
476
477
    def log(self, message):
478
        """StubServer uses this to log when a new server is created."""
479
        self.logs.append(message)
480
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
481
    def create_server(self):
482
        server = self.server_class((self.host, self.port),
483
                                   self.request_handler_class,
484
                                   self)
485
        return server
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
486
5247.4.24 by Vincent Ladeuil
Create the ssh host key only once for a given sftp test server.
487
    def get_host_key(self):
488
        if self._host_key is None:
489
            key_file = osutils.pathjoin(self._homedir, 'test_rsa.key')
490
            f = open(key_file, 'w')
491
            try:
492
                f.write(STUB_SERVER_KEY)
493
            finally:
494
                f.close()
495
            self._host_key = paramiko.RSAKey.from_private_key_file(key_file)
496
        return self._host_key
497
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
498
    def start_server(self, backing_server=None):
499
        # XXX: TODO: make sftpserver back onto backing_server rather than local
500
        # disk.
7143.15.2 by Jelmer Vernooij
Run autopep8.
501
        if not (backing_server is None
502
                or isinstance(backing_server, test_server.LocalURLServer)):
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
503
            raise AssertionError(
5055.1.2 by Vincent Ladeuil
Add a FIXME about using osutils.getcwd()
504
                'backing_server should not be %r, because this can only serve '
505
                'the local current working directory.' % (backing_server,))
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
506
        self._original_vendor = ssh._ssh_vendor_manager._cached_ssh_vendor
507
        ssh._ssh_vendor_manager._cached_ssh_vendor = self._vendor
6619.3.26 by Martin
Fix fallout from 2to3 getcwdu transformation and other test uses
508
        self._homedir = osutils.getcwd()
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
509
        if sys.platform == 'win32':
5229.1.9 by Vincent Ladeuil
Fix sftp homedir path handling on windows.
510
            # Normalize the path or it will be wrongly escaped
5229.1.7 by Vincent Ladeuil
Fix sftp paths for windows.
511
            self._homedir = osutils.normpath(self._homedir)
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
512
        else:
6855.2.6 by Jelmer Vernooij
Fix recent regressions.
513
            self._homedir = self._homedir
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
514
        if self._server_homedir is None:
515
            self._server_homedir = self._homedir
516
        self._root = '/'
517
        if sys.platform == 'win32':
518
            self._root = ''
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
519
        super(SFTPServer, self).start_server()
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
520
521
    def stop_server(self):
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
522
        try:
523
            super(SFTPServer, self).stop_server()
524
        finally:
525
            ssh._ssh_vendor_manager._cached_ssh_vendor = self._original_vendor
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
526
527
    def get_bogus_url(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
528
        """See breezy.transport.Server.get_bogus_url."""
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
529
        # this is chosen to try to prevent trouble with proxies, weird dns, etc
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
530
        # we bind a random socket, so that we get a guaranteed unused port
531
        # we just never listen on that port
532
        s = socket.socket()
533
        s.bind(('localhost', 0))
534
        return 'sftp://%s:%s/' % s.getsockname()
535
536
537
class SFTPFullAbsoluteServer(SFTPServer):
538
    """A test server for sftp transports, using absolute urls and ssh."""
539
540
    def get_url(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
541
        """See breezy.transport.Server.get_url."""
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
542
        homedir = self._homedir
543
        if sys.platform != 'win32':
544
            # Remove the initial '/' on all platforms but win32
545
            homedir = homedir[1:]
546
        return self._get_sftp_url(urlutils.escape(homedir))
547
548
549
class SFTPServerWithoutSSH(SFTPServer):
550
    """An SFTP server that uses a simple TCP socket pair rather than SSH."""
551
552
    def __init__(self):
553
        super(SFTPServerWithoutSSH, self).__init__()
554
        self._vendor = ssh.LoopbackVendor()
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
555
        self.request_handler_class = TestingSFTPWithoutSSHConnectionHandler
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
556
5247.4.24 by Vincent Ladeuil
Create the ssh host key only once for a given sftp test server.
557
    def get_host_key():
558
        return None
559
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
560
561
class SFTPAbsoluteServer(SFTPServerWithoutSSH):
562
    """A test server for sftp transports, using absolute urls."""
563
564
    def get_url(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
565
        """See breezy.transport.Server.get_url."""
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
566
        homedir = self._homedir
567
        if sys.platform != 'win32':
568
            # Remove the initial '/' on all platforms but win32
569
            homedir = homedir[1:]
570
        return self._get_sftp_url(urlutils.escape(homedir))
571
572
573
class SFTPHomeDirServer(SFTPServerWithoutSSH):
574
    """A test server for sftp transports, using homedir relative urls."""
575
576
    def get_url(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
577
        """See breezy.transport.Server.get_url."""
5268.7.20 by Jelmer Vernooij
Fix URL for transport tests.
578
        return self._get_sftp_url("%7E/")
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
579
580
581
class SFTPSiblingAbsoluteServer(SFTPAbsoluteServer):
582
    """A test server for sftp transports where only absolute paths will work.
583
584
    It does this by serving from a deeply-nested directory that doesn't exist.
585
    """
586
5247.4.18 by Vincent Ladeuil
Replace SocketListener by TestingTCPServerInAThread and fallouts,
587
    def create_server(self):
588
        # FIXME: Can't we do that in a cleaner way ? -- vila 20100623
589
        server = super(SFTPSiblingAbsoluteServer, self).create_server()
590
        server._server_homedir = '/dev/noone/runs/tests/here'
591
        return server