summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@gmail.com>2014-10-01 16:24:47 +0000
committerRichard Maw <richard.maw@gmail.com>2014-10-01 16:24:47 +0000
commit01060c72158893863162acec85f576c442fc49ff (patch)
tree577ba011a02f11f8b8343647b9af6b5cc4a793b4
parentce2de6bd60db874f26502350a75de10faa1bf220 (diff)
downloadmorph-01060c72158893863162acec85f576c442fc49ff.tar.gz
distbuild: allow daemons to bind to ephemeral ports
You can bind to an ephemeral port by passing 0 as the port number. To work out which port you actually got, you need to call getsockname(). To facilitate being able to spawn multiple copies of the daemons for testing environments, you can pass a -file option, which will make the daemon write which port it actually bound to. If this path is a fifo, reading from it in the spawner process will allow synchronisation of only spawning services that require that port to be ready after it is.
-rw-r--r--distbuild/sockserv.py7
-rw-r--r--morphlib/plugins/distbuild_plugin.py24
2 files changed, 28 insertions, 3 deletions
diff --git a/distbuild/sockserv.py b/distbuild/sockserv.py
index a5215e79..68991a93 100644
--- a/distbuild/sockserv.py
+++ b/distbuild/sockserv.py
@@ -26,15 +26,20 @@ class ListenServer(StateMachine):
'''Listen for new connections on a port, send events for them.'''
- def __init__(self, addr, port, machine, extra_args=None):
+ def __init__(self, addr, port, machine, extra_args=None, port_file=''):
StateMachine.__init__(self, 'listening')
self._addr = addr
self._port = port
self._machine = machine
self._extra_args = extra_args or []
+ self._port_file = port_file
def setup(self):
src = ListeningSocketEventSource(self._addr, self._port)
+ if self._port_file:
+ host, port = src.sock.getsockname()
+ with open(self._port_file, 'w') as f:
+ f.write(port)
self.mainloop.add_event_source(src)
spec = [
diff --git a/morphlib/plugins/distbuild_plugin.py b/morphlib/plugins/distbuild_plugin.py
index 50ab7eeb..7e8188dd 100644
--- a/morphlib/plugins/distbuild_plugin.py
+++ b/morphlib/plugins/distbuild_plugin.py
@@ -121,6 +121,11 @@ class WorkerDaemon(cliapp.Plugin):
'listen for connections on PORT',
default=3434,
group=group_distbuild)
+ self.app.settings.string(
+ ['worker-daemon-port-file'],
+ 'write port used by worker-daemon to FILE',
+ default='',
+ group=group_distbuild)
self.app.add_subcommand(
'worker-daemon',
self.worker_daemon,
@@ -136,7 +141,9 @@ class WorkerDaemon(cliapp.Plugin):
address = self.app.settings['worker-daemon-address']
port = self.app.settings['worker-daemon-port']
- router = distbuild.ListenServer(address, port, distbuild.JsonRouter)
+ port_file = self.app.settings['worker-daemon-port-file']
+ router = distbuild.ListenServer(address, port, distbuild.JsonRouter,
+ port_file=port_file)
loop = distbuild.MainLoop()
loop.add_state_machine(router)
loop.run()
@@ -156,6 +163,11 @@ class ControllerDaemon(cliapp.Plugin):
'listen for initiator connections on PORT',
default=7878,
group=group_distbuild)
+ self.app.settings.string(
+ ['controller-initiator-port-file'],
+ 'write the port to listen for initiator connections to FILE',
+ default='',
+ group=group_distbuild)
self.app.settings.string(
['controller-helper-address'],
@@ -167,6 +179,11 @@ class ControllerDaemon(cliapp.Plugin):
'listen for helper connections on PORT',
default=5656,
group=group_distbuild)
+ self.app.settings.string(
+ ['controller-helper-port-file'],
+ 'write the port to listen for helper connections to FILE',
+ default='',
+ group=group_distbuild)
self.app.settings.string_list(
['worker'],
@@ -218,8 +235,10 @@ class ControllerDaemon(cliapp.Plugin):
listener_specs = [
# address, port, class to initiate on connection, class init args
('controller-helper-address', 'controller-helper-port',
+ 'controller-helper-port-file',
distbuild.HelperRouter, []),
('controller-initiator-address', 'controller-initiator-port',
+ 'controller-initiator-port-file',
distbuild.InitiatorConnection,
[artifact_cache_server, morph_instance]),
]
@@ -229,9 +248,10 @@ class ControllerDaemon(cliapp.Plugin):
queuer = distbuild.WorkerBuildQueuer()
loop.add_state_machine(queuer)
- for addr, port, sm, extra_args in listener_specs:
+ for addr, port, port_file, sm, extra_args in listener_specs:
addr = self.app.settings[addr]
port = self.app.settings[port]
+ port_file = self.app.settings[port_file]
listener = distbuild.ListenServer(
addr, port, sm, extra_args=extra_args)
loop.add_state_machine(listener)