summaryrefslogtreecommitdiffstats
path: root/openstack
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-06-28 13:42:45 +0000
committerGerrit Code Review <review@openstack.org>2013-06-28 13:42:45 +0000
commit76bf705b8093f0ed81587226a73688de133af390 (patch)
tree4480cb6cda63584b6db42c7a29f81a8062f0ec30 /openstack
parent7b7566bac8e2df14e17631980a7fbf2df68cf116 (diff)
parentc7c55b2f82e6a9d712f7951b937a2a2e46e2b2d5 (diff)
downloadoslo-76bf705b8093f0ed81587226a73688de133af390.tar.gz
oslo-76bf705b8093f0ed81587226a73688de133af390.tar.xz
oslo-76bf705b8093f0ed81587226a73688de133af390.zip
Merge "Improve usability when backdoor_port is nonzero"
Diffstat (limited to 'openstack')
-rw-r--r--openstack/common/eventlet_backdoor.py63
1 files changed, 60 insertions, 3 deletions
diff --git a/openstack/common/eventlet_backdoor.py b/openstack/common/eventlet_backdoor.py
index 57b89ae..f2102d6 100644
--- a/openstack/common/eventlet_backdoor.py
+++ b/openstack/common/eventlet_backdoor.py
@@ -18,8 +18,11 @@
from __future__ import print_function
+import errno
import gc
+import os
import pprint
+import socket
import sys
import traceback
@@ -28,14 +31,34 @@ import eventlet.backdoor
import greenlet
from oslo.config import cfg
+from openstack.common.gettextutils import _
+from openstack.common import log as logging
+
+help_for_backdoor_port = 'Acceptable ' + \
+ 'values are 0, <port> and <start>:<end>, where 0 results in ' + \
+ 'listening on a random tcp port number, <port> results in ' + \
+ 'listening on the specified port number and not enabling backdoor' + \
+ 'if it is in use and <start>:<end> results in listening on the ' + \
+ 'smallest unused port number within the specified range of port ' + \
+ 'numbers. The chosen port is displayed in the service\'s log file.'
eventlet_backdoor_opts = [
- cfg.IntOpt('backdoor_port',
+ cfg.StrOpt('backdoor_port',
default=None,
- help='port for eventlet backdoor to listen')
+ help='Enable eventlet backdoor. %s' % help_for_backdoor_port)
]
CONF = cfg.CONF
CONF.register_opts(eventlet_backdoor_opts)
+LOG = logging.getLogger(__name__)
+
+
+class EventletBackdoorConfigValueError(Exception):
+ def __init__(self, port_range, help_msg, ex):
+ msg = ('Invalid backdoor_port configuration %(range)s: %(ex)s. '
+ '%(help)s' %
+ {'range': port_range, 'ex': ex, 'help': help_msg})
+ super(EventletBackdoorConfigValueError, self).__init__(msg)
+ self.port_range = port_range
def _dont_use_this():
@@ -60,6 +83,33 @@ def _print_nativethreads():
print()
+def _parse_port_range(port_range):
+ if ':' not in port_range:
+ start, end = port_range, port_range
+ else:
+ start, end = port_range.split(':', 1)
+ try:
+ start, end = int(start), int(end)
+ if end < start:
+ raise ValueError
+ return start, end
+ except ValueError as ex:
+ raise EventletBackdoorConfigValueError(port_range, ex,
+ help_for_backdoor_port)
+
+
+def _listen(host, start_port, end_port, listen_func):
+ try_port = start_port
+ while True:
+ try:
+ return listen_func((host, try_port))
+ except socket.error as exc:
+ if (exc.errno != errno.EADDRINUSE or
+ try_port >= end_port):
+ raise
+ try_port += 1
+
+
def initialize_if_enabled():
backdoor_locals = {
'exit': _dont_use_this, # So we don't exit the entire process
@@ -72,6 +122,8 @@ def initialize_if_enabled():
if CONF.backdoor_port is None:
return None
+ start_port, end_port = _parse_port_range(str(CONF.backdoor_port))
+
# NOTE(johannes): The standard sys.displayhook will print the value of
# the last expression and set it to __builtin__._, which overwrites
# the __builtin__._ that gettext sets. Let's switch to using pprint
@@ -82,8 +134,13 @@ def initialize_if_enabled():
pprint.pprint(val)
sys.displayhook = displayhook
- sock = eventlet.listen(('localhost', CONF.backdoor_port))
+ sock = _listen('localhost', start_port, end_port, eventlet.listen)
+
+ # In the case of backdoor port being zero, a port number is assigned by
+ # listen(). In any case, pull the port number out here.
port = sock.getsockname()[1]
+ LOG.info(_('Eventlet backdoor listening on %(port)s for process %(pid)d') %
+ {'port': port, 'pid': os.getpid()})
eventlet.spawn_n(eventlet.backdoor.backdoor_server, sock,
locals=backdoor_locals)
return port