~ubuntu-branches/ubuntu/trusty/heat/trusty-security

« back to all changes in this revision

Viewing changes to heat/openstack/common/eventlet_backdoor.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2013-09-08 21:51:19 UTC
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: package-import@ubuntu.com-20130908215119-7tcek6gn73275x5k
Tags: upstream-2013.2~b3
ImportĀ upstreamĀ versionĀ 2013.2~b3

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
from __future__ import print_function
20
20
 
 
21
import errno
21
22
import gc
 
23
import os
22
24
import pprint
 
25
import socket
23
26
import sys
24
27
import traceback
25
28
 
28
31
import greenlet
29
32
from oslo.config import cfg
30
33
 
 
34
from heat.openstack.common.gettextutils import _  # noqa
 
35
from heat.openstack.common import log as logging
 
36
 
 
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',
33
46
               default=None,
34
 
               help='port for eventlet backdoor to listen')
 
47
               help="Enable eventlet backdoor.  %s" % help_for_backdoor_port)
35
48
]
36
49
 
37
50
CONF = cfg.CONF
38
51
CONF.register_opts(eventlet_backdoor_opts)
 
52
LOG = logging.getLogger(__name__)
 
53
 
 
54
 
 
55
class EventletBackdoorConfigValueError(Exception):
 
56
    def __init__(self, port_range, help_msg, ex):
 
57
        msg = ('Invalid backdoor_port configuration %(range)s: %(ex)s. '
 
58
               '%(help)s' %
 
59
               {'range': port_range, 'ex': ex, 'help': help_msg})
 
60
        super(EventletBackdoorConfigValueError, self).__init__(msg)
 
61
        self.port_range = port_range
39
62
 
40
63
 
41
64
def _dont_use_this():
60
83
        print()
61
84
 
62
85
 
 
86
def _parse_port_range(port_range):
 
87
    if ':' not in port_range:
 
88
        start, end = port_range, port_range
 
89
    else:
 
90
        start, end = port_range.split(':', 1)
 
91
    try:
 
92
        start, end = int(start), int(end)
 
93
        if end < start:
 
94
            raise ValueError
 
95
        return start, end
 
96
    except ValueError as ex:
 
97
        raise EventletBackdoorConfigValueError(port_range, ex,
 
98
                                               help_for_backdoor_port)
 
99
 
 
100
 
 
101
def _listen(host, start_port, end_port, listen_func):
 
102
    try_port = start_port
 
103
    while True:
 
104
        try:
 
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):
 
109
                raise
 
110
            try_port += 1
 
111
 
 
112
 
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:
73
123
        return None
74
124
 
 
125
    start_port, end_port = _parse_port_range(str(CONF.backdoor_port))
 
126
 
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
84
136
 
85
 
    sock = eventlet.listen(('localhost', CONF.backdoor_port))
 
137
    sock = _listen('localhost', start_port, end_port, eventlet.listen)
 
138
 
 
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)
89
146
    return port