Skip to content

Commit b7f0504

Browse files
author
xianglongfei_uniontech
committed
Fixed the issue:Supports specifying port ranges.
Signed-off-by: xianglongfei_uniontech <xianglongfei@uniontech.com>
1 parent 74b7379 commit b7f0504

File tree

3 files changed

+63
-9
lines changed

3 files changed

+63
-9
lines changed

avocado/core/status/server.py

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,45 @@
11
import asyncio
22
import os
3+
import socket
34

45
from avocado.core.settings import settings
6+
from avocado.core.output import LOG_JOB
7+
8+
9+
def resolve_listen_uri(uri):
10+
"""
11+
Normalize a status server URI that may contain a port range into
12+
a concrete "host:port" endpoint.
13+
"""
14+
if ":" not in uri:
15+
return uri
16+
host, port_spec = uri.rsplit(":", 1)
17+
if "-" not in port_spec:
18+
return uri
19+
20+
start_s, end_s = port_spec.split("-", 1)
21+
start = int(start_s)
22+
end = int(end_s)
23+
if start > end:
24+
raise ValueError(
25+
f"Invalid port range (start > end) in status server URI: {uri}"
26+
)
27+
28+
last_exc = None
29+
for port in range(start, end + 1):
30+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
31+
try:
32+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
33+
sock.bind((host, port))
34+
return f"{host}:{port}"
35+
except OSError as exc:
36+
last_exc = exc
37+
finally:
38+
sock.close()
39+
40+
raise OSError(
41+
f"Could not bind status server to any port in range {start}-{end} on {host}: {last_exc}"
42+
)
543

644

745
class StatusServer:
@@ -16,7 +54,7 @@ def __init__(self, uri, repo):
1654
messages
1755
:type repo: :class:`avocado.core.status.repo.StatusRepo`
1856
"""
19-
self._uri = uri
57+
self._uri = resolve_listen_uri(uri)
2058
self._repo = repo
2159
self._server_task = None
2260

@@ -27,15 +65,17 @@ def uri(self):
2765
async def create_server(self):
2866
limit = settings.as_dict().get("run.status_server_buffer_size")
2967
if ":" in self._uri:
30-
host, port = self._uri.split(":")
68+
host, port = self._uri.rsplit(":", 1)
3169
port = int(port)
3270
self._server_task = await asyncio.start_server(
3371
self.cb, host=host, port=port, limit=limit
3472
)
73+
LOG_JOB.info("Status server listening on %s", self._uri)
3574
else:
3675
self._server_task = await asyncio.start_unix_server(
3776
self.cb, path=self._uri, limit=limit
3877
)
78+
LOG_JOB.info("Status server listening on %s", self._uri)
3979

4080
async def serve_forever(self):
4181
if self._server_task is None:

avocado/plugins/runner_nrunner.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from avocado.core.plugin_interfaces import CLI, Init, SuiteRunner
3232
from avocado.core.settings import settings
3333
from avocado.core.status.repo import StatusRepo
34-
from avocado.core.status.server import StatusServer
34+
from avocado.core.status.server import StatusServer, resolve_listen_uri
3535
from avocado.core.task.runtime import RuntimeTaskGraph
3636
from avocado.core.task.statemachine import TaskStateMachine, Worker
3737

@@ -240,10 +240,19 @@ def _sync_status_server_urls(self, config):
240240
def _create_status_server(self, test_suite, job):
241241
self._sync_status_server_urls(test_suite.config)
242242
listen = self._determine_status_server(test_suite, "run.status_server_listen")
243+
try:
244+
resolved_listen = resolve_listen_uri(listen)
245+
except (ValueError, OSError) as exc:
246+
raise JobError(str(exc)) from exc
247+
if resolved_listen != listen:
248+
test_suite.config["run.status_server_listen"] = resolved_listen
249+
server_uri = test_suite.config.get("run.status_server_uri")
250+
if server_uri in (listen, DEFAULT_SERVER_URI):
251+
test_suite.config["run.status_server_uri"] = resolved_listen
243252
# pylint: disable=W0201
244253
self.status_repo = StatusRepo(job.unique_id)
245254
# pylint: disable=W0201
246-
self.status_server = StatusServer(listen, self.status_repo)
255+
self.status_server = StatusServer(resolved_listen, self.status_repo)
247256

248257
async def _update_status(self, job):
249258
message_handler = MessageHandler()

man/avocado.rst

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,15 +185,20 @@ Options for subcommand `run` (`avocado run --help`)::
185185
server.
186186
--status-server-listen HOST_PORT
187187
URI where status server will listen on. Usually a
188-
"HOST:PORT" string. This is only effective if
188+
"HOST:PORT" string, or a "HOST:START-END" port
189+
range (for example, "127.0.0.1:8888-9000") in which
190+
case an available port within the range will be
191+
chosen. This is only effective if
189192
"status_server_auto" is disabled. If
190193
"status_server_uri" is not set, the value from
191-
"status_server_listen " will be used.
194+
"status_server_listen" will be used.
192195
--status-server-uri HOST_PORT
193196
URI for connecting to the status server, usually a
194-
"HOST:PORT" string. Use this if your status server is
195-
in another host, or different port. This is only
196-
effective if "status_server_auto" is disabled. If
197+
"HOST:PORT" string, or a "HOST:START-END" port range
198+
where an available port within the range will be
199+
chosen. Use this if your status server is in another
200+
host, or different port. This is only effective if
201+
"status_server_auto" is disabled. If
197202
"status_server_listen" is not set, the value from
198203
"status_server_uri" will be used.
199204
--max-parallel-tasks NUMBER_OF_TASKS

0 commit comments

Comments
 (0)