Skip to content

Commit 0ce06be

Browse files
committed
Add support for specifying a bind port hint in the machine spec
1 parent f9cee85 commit 0ce06be

File tree

4 files changed

+39
-16
lines changed

4 files changed

+39
-16
lines changed

docs/src/_changelog.md

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ This documents notable changes in DistributedNext.jl. The format is based on
2222
incompatibilities from both libraries being used simultaneously ([#10]).
2323
- [`other_workers()`](@ref) and [`other_procs()`](@ref) were implemented and
2424
exported ([#18]).
25+
- The `SSHManager` now supports specifying a bind port hint in the machine
26+
specification ([#19], see the [`addprocs()`](@ref) docs).
2527

2628
### Changed
2729
- [`remotecall_eval`](@ref) is now exported ([#23]).

src/cluster.jl

+15-7
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ end
214214
mutable struct LocalProcess
215215
id::Int
216216
bind_addr::String
217+
bind_port_hint::Int
217218
bind_port::Int
218219
cookie::String
219220
LocalProcess() = new(1)
@@ -257,8 +258,7 @@ function start_worker(out::IO, cookie::AbstractString=readline(stdin); close_std
257258
init_worker(cookie)
258259
interface = IPv4(LPROC.bind_addr)
259260
if LPROC.bind_port == 0
260-
port_hint = 9000 + (getpid() % 1000)
261-
(port, sock) = listenany(interface, port_hint)
261+
(port, sock) = listenany(interface, LPROC.bind_port_hint)
262262
LPROC.bind_port = Int(port)
263263
else
264264
sock = listen(interface, LPROC.bind_port)
@@ -1318,17 +1318,24 @@ end
13181318
# initialize the local proc network address / port
13191319
function init_bind_addr()
13201320
opts = JLOptions()
1321+
bind_port_hint = 9000 + (getpid() % 1000)
1322+
bind_port = 0
1323+
13211324
if opts.bindto != C_NULL
13221325
bind_to = split(unsafe_string(opts.bindto), ":")
13231326
bind_addr = string(parse(IPAddr, bind_to[1]))
13241327
if length(bind_to) > 1
1325-
bind_port = parse(Int,bind_to[2])
1326-
else
1327-
bind_port = 0
1328+
port_str = bind_to[2]
1329+
if startswith(port_str, '[')
1330+
if !endswith(port_str, ']')
1331+
error("Malformed bind port string, please see the addprocs documentation for the formatting rules: $(port_str)")
1332+
end
1333+
bind_port_hint = parse(Int, port_str[2:end - 1])
1334+
else
1335+
bind_port = parse(Int, port_str)
1336+
end
13281337
end
13291338
else
1330-
bind_port = 0
1331-
13321339
interfaces = _get_interfaces(IPv4)
13331340
if isempty(interfaces)
13341341
# Include IPv6 interfaces if there are no IPv4 ones
@@ -1355,6 +1362,7 @@ function init_bind_addr()
13551362
global LPROC
13561363
LPROC.bind_addr = bind_addr
13571364
LPROC.bind_port = bind_port
1365+
LPROC.bind_port_hint = bind_port_hint
13581366
end
13591367

13601368
using Random: randstring

src/managers.jl

+16-9
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,30 @@ arguments (see below). In particular, the `exename` keyword can be used to speci
5656
the path to the `julia` binary on the remote machine(s).
5757
5858
`machines` is a vector of "machine specifications" which are given as strings of
59-
the form `[user@]host[:port] [bind_addr[:port]]`. `user` defaults to current user and `port`
60-
to the standard SSH port. If `[bind_addr[:port]]` is specified, other workers will connect
61-
to this worker at the specified `bind_addr` and `port`.
59+
the form `[user@]host[:ssh_port] [bind_addr[:bind_port]]`. `user` defaults to
60+
current user and `ssh_port` to the standard SSH port. If
61+
`[bind_addr[:bind_port]]` is specified, other workers will connect to this
62+
worker at the specified `bind_addr` and `bind_port`. `bind_port` can be a
63+
specific port like in `addr:9000`, but it can also specify a port hint by
64+
enclosing it in brackets like `addr:[9000]`.
6265
6366
It is possible to launch multiple processes on a remote host by using a tuple in the
6467
`machines` vector or the form `(machine_spec, count)`, where `count` is the number of
6568
workers to be launched on the specified host. Passing `:auto` as the worker count will
66-
launch as many workers as the number of CPU threads on the remote host.
69+
launch as many workers as the number of CPU threads on the remote host. If the
70+
`bind_port` is specified then the first worker will bind to `bind_port` and all
71+
other workers on the host will use `bind_port` as a port hint.
6772
6873
**Examples**:
6974
```julia
7075
addprocs([
71-
"remote1", # one worker on 'remote1' logging in with the current username
72-
"user@remote2", # one worker on 'remote2' logging in with the 'user' username
73-
"user@remote3:2222", # specifying SSH port to '2222' for 'remote3'
74-
("user@remote4", 4), # launch 4 workers on 'remote4'
75-
("user@remote5", :auto), # launch as many workers as CPU threads on 'remote5'
76+
"remote1", # one worker on 'remote1' logging in with the current username
77+
"user@remote2", # one worker on 'remote2' logging in with the 'user' username
78+
"user@remote3:2222", # specifying SSH port to '2222' for 'remote3'
79+
"user@remote4 10.1.1.1:8000" # specify the address for the worker to bind to on 'remote4'
80+
"user@remote5 10.1.1.1:[8000]" # same as above, but with a port hint instead of a specific port
81+
("user@remote4", 4), # launch 4 workers on 'remote4'
82+
("user@remote5", :auto), # launch as many workers as CPU threads on 'remote5'
7683
])
7784
```
7885

test/sshmanager.jl

+6
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ end
6161
@test length(new_pids) == 5
6262
test_n_remove_pids(new_pids)
6363

64+
print("\nssh addprocs with a port hint\n")
65+
new_pids = addprocs_with_testenv(["localhost 127.0.0.1:[8000]"]; sshflags=sshflags)
66+
worker = DistributedNext.worker_from_id(only(new_pids))
67+
@test 8000 >= worker.config.port < 9000
68+
test_n_remove_pids(new_pids)
69+
6470
print("\nssh addprocs with tunnel\n")
6571
new_pids = addprocs_with_testenv([("localhost", num_workers)]; tunnel=true, sshflags=sshflags)
6672
@test length(new_pids) == num_workers

0 commit comments

Comments
 (0)