chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:17:40 +08:00
commit f1825c8ceb
10096 changed files with 2364182 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
load("//bazel:python.bzl", "doctest")
doctest(
files = glob(["**/*.py"]),
tags = ["team:core"],
)
View File
File diff suppressed because it is too large Load Diff
+274
View File
@@ -0,0 +1,274 @@
"""Symmetric Run for Ray."""
import socket
import subprocess
import sys
import time
from typing import List
import click
import ray
from ray._common.network_utils import is_localhost
from ray._private.ray_constants import env_integer
from ray._raylet import GcsClient
from ray.exceptions import RpcError
import psutil
CLUSTER_WAIT_TIMEOUT = env_integer("RAY_SYMMETRIC_RUN_CLUSTER_WAIT_TIMEOUT", 30)
def check_ray_already_started() -> bool:
import ray._private.services as services
# Try auto-detecting the Ray instance.
running_gcs_addresses = services.find_gcs_addresses()
return len(running_gcs_addresses) > 0
def check_cluster_ready(nnodes, timeout=CLUSTER_WAIT_TIMEOUT):
"""Wait for all nodes to start.
Raises an exception if the nodes don't start in time.
"""
start_time = time.time()
current_nodes = 1
ray.init(ignore_reinit_error=True)
while time.time() - start_time < timeout:
time.sleep(5)
current_nodes = len(ray.nodes())
if current_nodes == nnodes:
return True
else:
click.echo(
f"Waiting for nodes to start... {current_nodes}/{nnodes} nodes started"
)
return False
def check_head_node_ready(address: str, timeout=CLUSTER_WAIT_TIMEOUT):
start_time = time.time()
gcs_client = GcsClient(address=address)
while time.time() - start_time < timeout:
try:
gcs_client.check_alive([], timeout=1)
click.echo("Ray cluster is ready!")
return True
except RpcError:
pass
time.sleep(5)
return False
def curate_and_validate_ray_start_args(run_and_start_args: List[str]) -> List[str]:
# Reparse the arguments to remove symmetric_run arguments.
ctx = symmetric_run.make_context("_", run_and_start_args, resilient_parsing=True)
cleaned_args = list(ctx.params["ray_args_and_entrypoint"])
for arg in cleaned_args:
if arg == "--head":
raise click.ClickException("Cannot use --head option in symmetric_run.")
if arg == "--node-ip-address":
raise click.ClickException(
"Cannot use --node-ip-address option in symmetric_run."
)
if arg == "--port":
raise click.ClickException("Cannot use --port option in symmetric_run.")
if arg == "--block":
raise click.ClickException("Cannot use --block option in symmetric_run.")
return cleaned_args
@click.command(
name="symmetric_run",
context_settings={"ignore_unknown_options": True, "allow_extra_args": True},
help="""Command to start Ray across all nodes and execute an entrypoint command.
USAGE:
ray symmetric-run --address ADDRESS
[--min-nodes NUM_NODES] [RAY_START_OPTIONS] -- [ENTRYPOINT_COMMAND]
DESCRIPTION:
This command (1) starts a Ray cluster across all nodes,
(2) runs a command on the head node, and (3) stops the Ray cluster.
The '--' separator is required to distinguish between Ray start arguments
and the entrypoint command. The --min-nodes option is optional and
can be used to wait for a specific number of nodes to start.
EXAMPLES:
# Start Ray with default settings and run a Python script
ray symmetric-run --address 127.0.0.1:6379 -- python my_script.py
# Start Ray with specific head node and run a command
ray symmetric-run --address 127.0.0.1:6379 --min-nodes 4 -- python train_model.py --epochs=100
# Start Ray and run a multi-word command
ray symmetric-run --address 127.0.0.1:6379 --min-nodes 4 --num-cpus=4 -- python -m my_module --config=prod
RAY START OPTIONS:
Most ray start command options are supported. Arguments that are not
supported are: --head, --node-ip-address, --port, --block.
SEPARATOR REQUIREMENT:
The '--' separator is mandatory and must appear between Ray start
arguments and the entrypoint command. This ensures clear separation
between the two sets of arguments.
""",
)
@click.option(
"--address", required=True, type=str, help="The address of the Ray cluster."
)
@click.option(
"--min-nodes",
type=int,
help="If provided, wait for this number of nodes to start.",
)
@click.argument("ray_args_and_entrypoint", nargs=-1, type=click.UNPROCESSED)
def symmetric_run(address, min_nodes, ray_args_and_entrypoint):
all_args = sys.argv[1:]
if all_args and all_args[0] == "symmetric-run":
all_args = all_args[1:]
try:
separator = all_args.index("--")
except ValueError:
raise click.ClickException(
"No separator '--' found in arguments. Please use '--' to "
"separate Ray start arguments and the entrypoint command."
)
run_and_start_args, entrypoint_on_head = (
all_args[:separator],
all_args[separator + 1 :],
)
ray_start_args = curate_and_validate_ray_start_args(run_and_start_args)
min_nodes = 1 if min_nodes is None else min_nodes
if not entrypoint_on_head:
raise click.ClickException("No entrypoint command provided.")
if check_ray_already_started():
raise click.ClickException("Ray is already started on this node.")
# 1. Parse address and check if we are on the head node.
gcs_host_port = ray._common.network_utils.parse_address(address)
if gcs_host_port is None:
raise click.ClickException(
f"Invalid address format: {address}, should be `host:port`"
)
gcs_host, gcs_port = gcs_host_port
try:
# AF_UNSPEC allows resolving both IPv4 and IPv6
addrinfo = socket.getaddrinfo(
gcs_host, gcs_port, socket.AF_UNSPEC, socket.SOCK_STREAM
)
resolved_gcs_host = addrinfo[0][4][0]
except socket.gaierror:
raise click.ClickException(f"Could not resolve hostname: {gcs_host}")
my_ips = []
for iface, addrs in psutil.net_if_addrs().items():
for addr in addrs:
# Look for AF_INET (IPv4) or AF_INET6 (IPv6)
if addr.family in [
socket.AddressFamily.AF_INET,
socket.AddressFamily.AF_INET6,
]:
my_ips.append(addr.address)
if min_nodes > 1:
# Ban localhost ips if we are not running on a single node
# to avoid starting N head nodes
my_ips = [ip for ip in my_ips if not is_localhost(ip)]
is_head = resolved_gcs_host in my_ips
result = None
# 2. Start Ray and run commands.
try:
if is_head:
# On the head node, start Ray, run the command, then stop Ray.
click.echo("On head node. Starting Ray cluster head...")
# Build the ray start command with all parameters
ray_start_cmd = [
"ray",
"start",
"--head",
f"--node-ip-address={resolved_gcs_host}",
f"--port={gcs_port}",
*ray_start_args,
]
# Start Ray head. This runs in the background and hides output.
subprocess.run(ray_start_cmd, check=True, capture_output=True)
click.echo("Head node started.")
click.echo("=======================")
if min_nodes > 1 and not check_cluster_ready(min_nodes):
raise click.ClickException(
"Timed out waiting for other nodes to start."
)
click.echo(
f"Running command on head node: {entrypoint_on_head}",
)
click.echo("=======================")
result = subprocess.run(entrypoint_on_head)
click.echo("=======================")
else:
# On a worker node, start Ray and connect to the head.
click.echo(f"On worker node. Connecting to Ray cluster at {address}...")
if not check_head_node_ready(address):
raise click.ClickException("Timed out waiting for head node to start.")
# Build the ray start command for worker nodes with all parameters
ray_start_cmd = [
"ray",
"start",
"--address",
address,
"--block",
*ray_start_args,
]
# This command will block until the Ray cluster is stopped.
subprocess.run(ray_start_cmd, check=True)
except subprocess.CalledProcessError as e:
click.echo(f"Failed to start Ray: {e}", err=True)
if e.stdout:
click.echo(f"stdout:\n{e.stdout.decode()}", err=True)
if e.stderr:
click.echo(f"stderr:\n{e.stderr.decode()}", err=True)
except KeyboardInterrupt:
# This can be triggered by ctrl-c on the user's side.
click.echo("Interrupted by user.", err=True)
finally:
# Stop Ray cluster.
subprocess.run(["ray", "stop"])
# Propagate the exit code of the user script.
if result is not None and result.returncode != 0:
click.echo(f"Command failed with return code {result.returncode}", err=True)
sys.exit(result.returncode)
if __name__ == "__main__":
symmetric_run()