Check used port, fix #985.

This commit is contained in:
Norman Jäckel 2013-11-06 17:49:41 +01:00
parent 5040de8dcb
commit 17a2eb97cb
2 changed files with 34 additions and 14 deletions

View File

@ -23,6 +23,10 @@ class PortableDirNotWritable(Exception):
pass pass
class PortIsBlockedError(Exception):
pass
class DatabaseInSettingsError(Exception): class DatabaseInSettingsError(Exception):
pass pass
@ -273,22 +277,27 @@ def get_portable_paths(name):
def get_port(address, port): def get_port(address, port):
""" """
Returns the port for the server. If port 80 is given, checks if it is Checks if the port for the server is available and returns it the port. If
available. If not returns port 8000. it is port 80, try also port 8000.
The argument 'address' should be an IP address. The argument 'port' should The argument 'address' should be an IP address. The argument 'port' should
be an integer. be an integer.
""" """
if port == 80: s = socket.socket()
# test if we can use port 80 try:
s = socket.socket() s.bind((address, port))
try: s.listen(-1)
s.bind((address, port)) except socket.error:
s.listen(-1) error = True
except socket.error: else:
port = 8000 error = False
finally: finally:
s.close() s.close()
if error:
if port == 80:
port = get_port(address, 8000)
else:
raise PortIsBlockedError('Port %d is not available. Try another port using the --port option.' % port)
return port return port

View File

@ -20,6 +20,7 @@ from openslides.utils.main import (
get_port, get_port,
get_portable_paths, get_portable_paths,
get_user_data_path_values, get_user_data_path_values,
PortIsBlockedError,
setup_django_settings_module, setup_django_settings_module,
start_browser, start_browser,
UNIX_VERSION, UNIX_VERSION,
@ -71,11 +72,19 @@ class TestFunctions(TestCase):
def test_get_port(self): def test_get_port(self):
class MyException(Exception): class MyException(Exception):
pass pass
def block_some_ports(mock):
if not 8000 == mock_socket.socket().bind.call_args[0][0][1]:
raise MyException
# Test open port
self.assertEqual(get_port('localhost', 8234), 8234) self.assertEqual(get_port('localhost', 8234), 8234)
# Test blocked ports
with patch('openslides.utils.main.socket') as mock_socket: with patch('openslides.utils.main.socket') as mock_socket:
mock_socket.error = MyException mock_socket.error = MyException
mock_socket.socket().listen = MagicMock(side_effect=MyException) mock_socket.socket().listen = MagicMock(side_effect=block_some_ports)
self.assertEqual(get_port('localhost', 80), 8000) self.assertEqual(get_port('localhost', 80), 8000)
self.assertRaises(PortIsBlockedError, get_port, 'localhost', 81)
@patch('openslides.utils.main.threading.Thread') @patch('openslides.utils.main.threading.Thread')
@patch('openslides.utils.main.time') @patch('openslides.utils.main.time')
@ -121,9 +130,11 @@ class TestOtherFunctions(TestCase):
mock_syncdb.assert_called() mock_syncdb.assert_called()
mock_runserver.assert_called_with(None, mock_args) mock_runserver.assert_called_with(None, mock_args)
@patch('openslides.__main__.get_port')
@patch('openslides.__main__.run_tornado') @patch('openslides.__main__.run_tornado')
@patch('openslides.__main__.start_browser') @patch('openslides.__main__.start_browser')
def test_runserver(self, mock_start_browser, mock_run_tornado): def test_runserver(self, mock_start_browser, mock_run_tornado, mock_get_port):
mock_get_port.return_value = 8000
mock_args = MagicMock() mock_args = MagicMock()
runserver(settings=None, args=mock_args) runserver(settings=None, args=mock_args)
mock_run_tornado.assert_called() mock_run_tornado.assert_called()