29
32
from oslo.config import cfg
34
from heat.openstack.common.gettextutils import _ # noqa
35
from heat.openstack.common import log as logging
37
help_for_backdoor_port = (
38
"Acceptable values are 0, <port>, and <start>:<end>, where 0 results "
39
"in listening on a random tcp port number; <port> results in listening "
40
"on the specified port number (and not enabling backdoor if that port "
41
"is in use); and <start>:<end> results in listening on the smallest "
42
"unused port number within the specified range of port numbers. The "
43
"chosen port is displayed in the service's log file.")
31
44
eventlet_backdoor_opts = [
32
cfg.IntOpt('backdoor_port',
45
cfg.StrOpt('backdoor_port',
34
help='port for eventlet backdoor to listen')
47
help="Enable eventlet backdoor. %s" % help_for_backdoor_port)
38
51
CONF.register_opts(eventlet_backdoor_opts)
52
LOG = logging.getLogger(__name__)
55
class EventletBackdoorConfigValueError(Exception):
56
def __init__(self, port_range, help_msg, ex):
57
msg = ('Invalid backdoor_port configuration %(range)s: %(ex)s. '
59
{'range': port_range, 'ex': ex, 'help': help_msg})
60
super(EventletBackdoorConfigValueError, self).__init__(msg)
61
self.port_range = port_range
41
64
def _dont_use_this():
86
def _parse_port_range(port_range):
87
if ':' not in port_range:
88
start, end = port_range, port_range
90
start, end = port_range.split(':', 1)
92
start, end = int(start), int(end)
96
except ValueError as ex:
97
raise EventletBackdoorConfigValueError(port_range, ex,
98
help_for_backdoor_port)
101
def _listen(host, start_port, end_port, listen_func):
102
try_port = start_port
105
return listen_func((host, try_port))
106
except socket.error as exc:
107
if (exc.errno != errno.EADDRINUSE or
108
try_port >= end_port):
63
113
def initialize_if_enabled():
64
114
backdoor_locals = {
65
115
'exit': _dont_use_this, # So we don't exit the entire process
72
122
if CONF.backdoor_port is None:
125
start_port, end_port = _parse_port_range(str(CONF.backdoor_port))
75
127
# NOTE(johannes): The standard sys.displayhook will print the value of
76
128
# the last expression and set it to __builtin__._, which overwrites
77
129
# the __builtin__._ that gettext sets. Let's switch to using pprint
82
134
pprint.pprint(val)
83
135
sys.displayhook = displayhook
85
sock = eventlet.listen(('localhost', CONF.backdoor_port))
137
sock = _listen('localhost', start_port, end_port, eventlet.listen)
139
# In the case of backdoor port being zero, a port number is assigned by
140
# listen(). In any case, pull the port number out here.
86
141
port = sock.getsockname()[1]
142
LOG.info(_('Eventlet backdoor listening on %(port)s for process %(pid)d') %
143
{'port': port, 'pid': os.getpid()})
87
144
eventlet.spawn_n(eventlet.backdoor.backdoor_server, sock,
88
145
locals=backdoor_locals)