Merge "Support multiple API and mDNS listen address pairs"
This commit is contained in:
commit
20b5c13fca
@ -24,10 +24,17 @@ OPTS = [
|
||||
help='Number of agent worker processes to spawn'),
|
||||
cfg.IntOpt('threads', default=1000,
|
||||
help='Number of agent greenthreads to spawn'),
|
||||
cfg.IPOpt('host', default='0.0.0.0',
|
||||
help='The host for the Agent to bind to'),
|
||||
cfg.PortOpt('port', default=5358,
|
||||
help='The port for the Agent to bind to'),
|
||||
cfg.IPOpt('host',
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason="Replaced by 'listen' option",
|
||||
help='Agent Bind Host'),
|
||||
cfg.PortOpt('port',
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason="Replaced by 'listen' option",
|
||||
help='Agent Port Number'),
|
||||
cfg.ListOpt('listen',
|
||||
default=['0.0.0.0:5358'],
|
||||
help='Agent host:port pairs to listen on'),
|
||||
cfg.IntOpt('tcp-backlog', default=100,
|
||||
help='The Agent TCP Backlog'),
|
||||
cfg.FloatOpt('tcp-recv-timeout', default=0.5,
|
||||
|
@ -37,6 +37,7 @@ CONF = cfg.CONF
|
||||
|
||||
|
||||
class Service(service.DNSService, service.Service):
|
||||
_dns_default_port = 5358
|
||||
|
||||
def __init__(self, threads=None):
|
||||
super(Service, self).__init__(threads=threads)
|
||||
|
@ -28,10 +28,17 @@ cfg.CONF.register_opts([
|
||||
cfg.BoolOpt('enable-host-header', default=False,
|
||||
help='Enable host request headers'),
|
||||
cfg.StrOpt('api-base-uri', default='http://127.0.0.1:9001/'),
|
||||
cfg.IPOpt('api_host', default='0.0.0.0',
|
||||
help='API Host'),
|
||||
cfg.PortOpt('api_port', default=9001,
|
||||
cfg.IPOpt('api_host',
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason="Replaced by 'listen' option",
|
||||
help='API Bind Host'),
|
||||
cfg.PortOpt('api_port',
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason="Replaced by 'listen' option",
|
||||
help='API Port Number'),
|
||||
cfg.ListOpt('listen',
|
||||
default=['0.0.0.0:9001'],
|
||||
help='API host:port pairs to listen on'),
|
||||
cfg.StrOpt('api_paste_config', default='api-paste.ini',
|
||||
help='File name for the paste.deploy config for designate-api'),
|
||||
cfg.StrOpt('auth_strategy', default='keystone',
|
||||
|
@ -27,10 +27,17 @@ OPTS = [
|
||||
help='Number of mdns worker processes to spawn'),
|
||||
cfg.IntOpt('threads', default=1000,
|
||||
help='Number of mdns greenthreads to spawn'),
|
||||
cfg.IPOpt('host', default='0.0.0.0',
|
||||
cfg.IPOpt('host',
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason="Replaced by 'listen' option",
|
||||
help='mDNS Bind Host'),
|
||||
cfg.PortOpt('port', default=5354,
|
||||
cfg.PortOpt('port',
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason="Replaced by 'listen' option",
|
||||
help='mDNS Port Number'),
|
||||
cfg.ListOpt('listen',
|
||||
default=['0.0.0.0:5354'],
|
||||
help='mDNS host:port pairs to listen on'),
|
||||
cfg.IntOpt('tcp-backlog', default=100,
|
||||
help='mDNS TCP Backlog'),
|
||||
cfg.FloatOpt('tcp-recv-timeout', default=0.5,
|
||||
|
@ -29,6 +29,7 @@ CONF = cfg.CONF
|
||||
|
||||
|
||||
class Service(service.DNSService, service.RPCService, service.Service):
|
||||
_dns_default_port = 5354
|
||||
|
||||
@property
|
||||
def storage(self):
|
||||
|
@ -97,6 +97,43 @@ class Service(service.Service):
|
||||
|
||||
super(Service, self).stop()
|
||||
|
||||
def _get_listen_on_addresses(self, default_port):
|
||||
"""
|
||||
Helper Method to handle migration from singular host/port to
|
||||
multiple binds
|
||||
"""
|
||||
try:
|
||||
# The API service uses "api_host", and "api_port", others use
|
||||
# just host and port.
|
||||
host = self._service_config.api_host
|
||||
port = self._service_config.api_port
|
||||
|
||||
except cfg.NoSuchOptError:
|
||||
host = self._service_config.host
|
||||
port = self._service_config.port
|
||||
|
||||
if host or port:
|
||||
LOG.warning(_LW("host and port config options used, the 'listen' "
|
||||
"option has been ignored"))
|
||||
|
||||
host = host or "0.0.0.0"
|
||||
port = port or default_port
|
||||
|
||||
return [(host, port)]
|
||||
|
||||
else:
|
||||
def _split_host_port(l):
|
||||
try:
|
||||
host, port = l.split(':', 1)
|
||||
return host, int(port)
|
||||
except ValueError:
|
||||
LOG.exception(_LE('Invalid ip:port pair: %s'), l)
|
||||
raise
|
||||
|
||||
# Convert listen pair list to a set, to remove accidental
|
||||
# duplicates.
|
||||
return map(_split_host_port, set(self._service_config.listen))
|
||||
|
||||
|
||||
class RPCService(object):
|
||||
"""
|
||||
@ -180,6 +217,8 @@ class WSGIService(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(WSGIService, self).__init__(*args, **kwargs)
|
||||
|
||||
self._wsgi_socks = []
|
||||
|
||||
@abc.abstractproperty
|
||||
def _wsgi_application(self):
|
||||
pass
|
||||
@ -187,23 +226,28 @@ class WSGIService(object):
|
||||
def start(self):
|
||||
super(WSGIService, self).start()
|
||||
|
||||
self._wsgi_sock = utils.bind_tcp(
|
||||
self._service_config.api_host,
|
||||
self._service_config.api_port,
|
||||
CONF.backlog,
|
||||
CONF.tcp_keepidle)
|
||||
addresses = self._get_listen_on_addresses(9001)
|
||||
|
||||
for address in addresses:
|
||||
self._start(address[0], address[1])
|
||||
|
||||
def _start(self, host, port):
|
||||
wsgi_sock = utils.bind_tcp(
|
||||
host, port, CONF.backlog, CONF.tcp_keepidle)
|
||||
|
||||
if sslutils.is_enabled(CONF):
|
||||
self._wsgi_sock = sslutils.wrap(CONF, self._wsgi_sock)
|
||||
wsgi_sock = sslutils.wrap(CONF, wsgi_sock)
|
||||
|
||||
self.tg.add_thread(self._wsgi_handle)
|
||||
self._wsgi_socks.append(wsgi_sock)
|
||||
|
||||
def _wsgi_handle(self):
|
||||
self.tg.add_thread(self._wsgi_handle, wsgi_sock)
|
||||
|
||||
def _wsgi_handle(self, wsgi_sock):
|
||||
logger = logging.getLogger('eventlet.wsgi')
|
||||
# Adjust wsgi MAX_HEADER_LINE to accept large tokens.
|
||||
eventlet.wsgi.MAX_HEADER_LINE = self._service_config.max_header_line
|
||||
|
||||
eventlet.wsgi.server(self._wsgi_sock,
|
||||
eventlet.wsgi.server(wsgi_sock,
|
||||
self._wsgi_application,
|
||||
custom_pool=self.tg.pool,
|
||||
log=logger)
|
||||
@ -221,6 +265,9 @@ class DNSService(object):
|
||||
# reading/writing to the UDP socket at once. Disable this warning.
|
||||
eventlet.debug.hub_prevent_multiple_readers(False)
|
||||
|
||||
self._dns_socks_tcp = []
|
||||
self._dns_socks_udp = []
|
||||
|
||||
@abc.abstractproperty
|
||||
def _dns_application(self):
|
||||
pass
|
||||
@ -228,17 +275,23 @@ class DNSService(object):
|
||||
def start(self):
|
||||
super(DNSService, self).start()
|
||||
|
||||
self._dns_sock_tcp = utils.bind_tcp(
|
||||
self._service_config.host,
|
||||
self._service_config.port,
|
||||
self._service_config.tcp_backlog)
|
||||
addresses = self._get_listen_on_addresses(self._dns_default_port)
|
||||
|
||||
self._dns_sock_udp = utils.bind_udp(
|
||||
self._service_config.host,
|
||||
self._service_config.port)
|
||||
for address in addresses:
|
||||
self._start(address[0], address[1])
|
||||
|
||||
self.tg.add_thread(self._dns_handle_tcp)
|
||||
self.tg.add_thread(self._dns_handle_udp)
|
||||
def _start(self, host, port):
|
||||
sock_tcp = utils.bind_tcp(
|
||||
host, port, self._service_config.tcp_backlog)
|
||||
|
||||
sock_udp = utils.bind_udp(
|
||||
host, port)
|
||||
|
||||
self._dns_socks_tcp.append(sock_tcp)
|
||||
self._dns_socks_udp.append(sock_udp)
|
||||
|
||||
self.tg.add_thread(self._dns_handle_tcp, sock_tcp)
|
||||
self.tg.add_thread(self._dns_handle_udp, sock_udp)
|
||||
|
||||
def wait(self):
|
||||
super(DNSService, self).wait()
|
||||
@ -248,18 +301,18 @@ class DNSService(object):
|
||||
# _handle_udp are stopped too.
|
||||
super(DNSService, self).stop()
|
||||
|
||||
if hasattr(self, '_dns_sock_tcp'):
|
||||
self._dns_sock_tcp.close()
|
||||
for sock_tcp in self._dns_socks_tcp:
|
||||
sock_tcp.close()
|
||||
|
||||
if hasattr(self, '_dns_sock_udp'):
|
||||
self._dns_sock_udp.close()
|
||||
for sock_udp in self._dns_socks_udp:
|
||||
sock_udp.close()
|
||||
|
||||
def _dns_handle_tcp(self):
|
||||
def _dns_handle_tcp(self, sock_tcp):
|
||||
LOG.info(_LI("_handle_tcp thread started"))
|
||||
|
||||
while True:
|
||||
try:
|
||||
client, addr = self._dns_sock_tcp.accept()
|
||||
client, addr = sock_tcp.accept()
|
||||
|
||||
if self._service_config.tcp_recv_timeout:
|
||||
client.settimeout(self._service_config.tcp_recv_timeout)
|
||||
@ -312,20 +365,21 @@ class DNSService(object):
|
||||
self.tg.add_thread(self._dns_handle, addr, payload,
|
||||
client=client)
|
||||
|
||||
def _dns_handle_udp(self):
|
||||
def _dns_handle_udp(self, sock_udp):
|
||||
LOG.info(_LI("_handle_udp thread started"))
|
||||
|
||||
while True:
|
||||
try:
|
||||
# TODO(kiall): Determine the appropriate default value for
|
||||
# UDP recvfrom.
|
||||
payload, addr = self._dns_sock_udp.recvfrom(8192)
|
||||
payload, addr = sock_udp.recvfrom(8192)
|
||||
|
||||
LOG.debug("Handling UDP Request from: %(host)s:%(port)d" %
|
||||
{'host': addr[0], 'port': addr[1]})
|
||||
|
||||
# Dispatch a thread to handle the query
|
||||
self.tg.add_thread(self._dns_handle, addr, payload)
|
||||
self.tg.add_thread(self._dns_handle, addr, payload,
|
||||
sock_udp=sock_udp)
|
||||
|
||||
except socket.error as e:
|
||||
errname = errno.errorcode[e.args[0]]
|
||||
@ -338,7 +392,7 @@ class DNSService(object):
|
||||
"from: %(host)s:%(port)d") %
|
||||
{'host': addr[0], 'port': addr[1]})
|
||||
|
||||
def _dns_handle(self, addr, payload, client=None):
|
||||
def _dns_handle(self, addr, payload, client=None, sock_udp=None):
|
||||
"""
|
||||
Handle a DNS Query
|
||||
|
||||
@ -360,7 +414,7 @@ class DNSService(object):
|
||||
client.sendall(tcp_response)
|
||||
else:
|
||||
# Handle UDP Responses
|
||||
self._dns_sock_udp.sendto(response, addr)
|
||||
sock_udp.sendto(response, addr)
|
||||
|
||||
except Exception:
|
||||
LOG.exception(_LE("Unhandled exception while processing request "
|
||||
|
@ -60,6 +60,8 @@ class MdnsServiceTest(MdnsTestCase):
|
||||
expected_response = (b"271289050001000000000000076578616d706c6503636f6"
|
||||
b"d0000010001")
|
||||
|
||||
self.service._dns_handle(self.addr, binascii.a2b_hex(payload))
|
||||
sock_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
self.service._dns_handle(self.addr, binascii.a2b_hex(payload),
|
||||
sock_udp=sock_udp)
|
||||
sendto_mock.assert_called_once_with(
|
||||
binascii.a2b_hex(expected_response), self.addr)
|
||||
|
@ -82,15 +82,13 @@ function configure_designate {
|
||||
iniset $DESIGNATE_CONF service:api enabled_extensions_v1 $DESIGNATE_ENABLED_EXTENSIONS_V1
|
||||
iniset $DESIGNATE_CONF service:api enabled_extensions_v2 $DESIGNATE_ENABLED_EXTENSIONS_V2
|
||||
iniset $DESIGNATE_CONF service:api enabled_extensions_admin $DESIGNATE_ENABLED_EXTENSIONS_ADMIN
|
||||
iniset $DESIGNATE_CONF service:api api_host $DESIGNATE_SERVICE_HOST
|
||||
iniset $DESIGNATE_CONF service:api api_base_uri $DESIGNATE_SERVICE_PROTOCOL://$DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT/
|
||||
iniset $DESIGNATE_CONF service:api enable_api_v1 $DESIGNATE_ENABLE_API_V1
|
||||
iniset $DESIGNATE_CONF service:api enable_api_v2 $DESIGNATE_ENABLE_API_V2
|
||||
iniset $DESIGNATE_CONF service:api enable_api_admin $DESIGNATE_ENABLE_API_ADMIN
|
||||
|
||||
# mDNS Configuration
|
||||
iniset $DESIGNATE_CONF service:mdns host $DESIGNATE_SERVICE_HOST
|
||||
iniset $DESIGNATE_CONF service:mdns port $DESIGNATE_SERVICE_PORT_MDNS
|
||||
iniset $DESIGNATE_CONF service:mdns listen ${DESIGNATE_SERVICE_HOST}:${DESIGNATE_SERVICE_PORT_MDNS}
|
||||
|
||||
# Set up Notifications/Ceilometer Integration
|
||||
iniset $DESIGNATE_CONF DEFAULT notification_driver "$DESIGNATE_NOTIFICATION_DRIVER"
|
||||
@ -114,9 +112,9 @@ function configure_designate {
|
||||
# TLS Proxy Configuration
|
||||
if is_service_enabled tls-proxy; then
|
||||
# Set the service port for a proxy to take the original
|
||||
iniset $DESIGNATE_CONF service:api api_port $DESIGNATE_SERVICE_PORT_INT
|
||||
iniset $DESIGNATE_CONF service:api listen ${DESIGNATE_SERVICE_HOST}:${DESIGNATE_SERVICE_PORT_INT}
|
||||
else
|
||||
iniset $DESIGNATE_CONF service:api api_port $DESIGNATE_SERVICE_PORT
|
||||
iniset $DESIGNATE_CONF service:api listen ${DESIGNATE_SERVICE_HOST}:${DESIGNATE_SERVICE_PORT}
|
||||
fi
|
||||
|
||||
# Setup the Keystone Integration
|
||||
|
@ -100,11 +100,8 @@ debug = False
|
||||
# The base uri used in responses
|
||||
#api_base_uri = 'http://127.0.0.1:9001/'
|
||||
|
||||
# Address to bind the API server
|
||||
#api_host = 0.0.0.0
|
||||
|
||||
# Port the bind the API server to
|
||||
#api_port = 9001
|
||||
# API bind host+port pairs, comma separated
|
||||
#listen = 0.0.0.0:9001
|
||||
|
||||
# Maximum line size of message headers to be accepted. max_header_line may
|
||||
# need to be increased when using large tokens (typically those generated by
|
||||
@ -238,11 +235,8 @@ debug = False
|
||||
# Number of mdns greenthreads to spawn
|
||||
#threads = 1000
|
||||
|
||||
# mDNS Bind Host
|
||||
#host = 0.0.0.0
|
||||
|
||||
# mDNS Port Number
|
||||
#port = 5354
|
||||
# mDNS bind host+port pairs, comma separated
|
||||
#listen = 0.0.0.0:5354
|
||||
|
||||
# mDNS TCP Backlog
|
||||
#tcp_backlog = 100
|
||||
@ -264,8 +258,7 @@ debug = False
|
||||
#-----------------------
|
||||
[service:agent]
|
||||
#workers = None
|
||||
#host = 0.0.0.0
|
||||
#port = 5358
|
||||
#listen = 0.0.0.0:5358
|
||||
#tcp_backlog = 100
|
||||
#allow_notify = 127.0.0.1
|
||||
#masters = 127.0.0.1:5354
|
||||
|
@ -0,0 +1,15 @@
|
||||
---
|
||||
features:
|
||||
- designate-mdns, designate-agent and designate-api can now bind to multiple
|
||||
host:port pairs via the new "listen" configuration arguments for eacg
|
||||
service.
|
||||
deprecations:
|
||||
- designate-api's api_host and api_port configuration options have been
|
||||
deprecated, please use the new combined "listen" argument in place of
|
||||
these.
|
||||
- designate-mdns's host and port configuration options have been
|
||||
deprecated, please use the new combined "listen" argument in place of
|
||||
these.
|
||||
- designate-agents's host and port configuration options have been
|
||||
deprecated, please use the new combined "listen" argument in place of
|
||||
these.
|
Loading…
Reference in New Issue
Block a user