Merge "Avoid eventlet_backdoor listing on same port"

This commit is contained in:
Zuul 2019-01-17 13:52:22 +00:00 committed by Gerrit Code Review
commit 3c645a77ec
2 changed files with 25 additions and 4 deletions

View File

@ -21,13 +21,13 @@ import gc
import logging import logging
import os import os
import pprint import pprint
import socket
import sys import sys
import traceback import traceback
import eventlet.backdoor import eventlet.backdoor
import greenlet import greenlet
from eventlet.green import socket
from oslo_service._i18n import _ from oslo_service._i18n import _
from oslo_service import _options from oslo_service import _options
@ -121,11 +121,24 @@ def _parse_port_range(port_range):
port_range, ex, _options.help_for_backdoor_port) port_range, ex, _options.help_for_backdoor_port)
def _listen(host, start_port, end_port, listen_func): def _listen_func(host, port):
# eventlet is setting SO_REUSEPORT by default from v0.20.
# But we can configure it by passing reuse_port argument
# from v0.22
try:
return eventlet.listen((host, port), reuse_port=False)
except TypeError:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen(50)
return sock
def _listen(host, start_port, end_port):
try_port = start_port try_port = start_port
while True: while True:
try: try:
return listen_func((host, try_port)) return _listen_func(host, try_port)
except socket.error as exc: except socket.error as exc:
if (exc.errno != errno.EADDRINUSE or if (exc.errno != errno.EADDRINUSE or
try_port >= end_port): try_port >= end_port):
@ -169,7 +182,7 @@ def _initialize_if_enabled(conf):
if conf.backdoor_socket is None: if conf.backdoor_socket is None:
start_port, end_port = _parse_port_range(str(conf.backdoor_port)) start_port, end_port = _parse_port_range(str(conf.backdoor_port))
sock = _listen('localhost', start_port, end_port, eventlet.listen) sock = _listen('localhost', start_port, end_port)
# In the case of backdoor port being zero, a port number is assigned by # In the case of backdoor port being zero, a port number is assigned by
# listen(). In any case, pull the port number out here. # listen(). In any case, pull the port number out here.
where_running = sock.getsockname()[1] where_running = sock.getsockname()[1]

View File

@ -105,6 +105,14 @@ class BackdoorPortTest(base.ServiceBaseTestCase):
self.assertRaises(socket.error, self.assertRaises(socket.error,
eventlet_backdoor.initialize_if_enabled, self.conf) eventlet_backdoor.initialize_if_enabled, self.conf)
@mock.patch.object(eventlet, 'spawn')
def test_backdoor_port_range_inuse(self, spawn_mock):
self.config(backdoor_port='8800:8801')
port = eventlet_backdoor.initialize_if_enabled(self.conf)
self.assertEqual(8800, port)
port = eventlet_backdoor.initialize_if_enabled(self.conf)
self.assertEqual(8801, port)
@mock.patch.object(eventlet, 'spawn') @mock.patch.object(eventlet, 'spawn')
@mock.patch.object(eventlet, 'listen') @mock.patch.object(eventlet, 'listen')
def test_backdoor_port_range(self, listen_mock, spawn_mock): def test_backdoor_port_range(self, listen_mock, spawn_mock):