Conversation
Implements DCCS-6410 -- automated passwordless SSH setup across cluster nodes as a prerequisite for multi-node RCCL and training tests. - cvs/lib/ssh_keys_lib.py: config validation, hostname collection, wildcard derivation, ~/.ssh/config block rendering, remote command builders, and orchestration drivers (key upload, authorized_keys injection, connectivity verification). Supports NFS-shared ssh dirs via ssh_dir_nfs_shared -- uploads via the head node only when the remote dir is a shared mount, skipping redundant per-node transfers. - cvs/lib/unittests/test_ssh_keys_lib.py: 56 mocked unit tests, no live cluster dependency - cvs/tests/cluster_key_distribution/ssh_keys_distribution.py: pytest suite with 6 ordered tests covering dir setup, key distribution, authorized_keys injection (cluster + optional controlling station), ssh config installation, and end-to-end passwordless SSH verification - cvs/input/config_file/cluster_key_distribution/ssh_key_distribute_config.json: sample config with <changeme> placeholders Live-tested against a 4-node cluster. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
pytest 8+ requires filterwarnings categories to be Warning subclasses; BrokenPipeError is an OSError, so parsing this entry raises UsageError and aborts every test run under pytest>=8 (reproduced with pytest 9.1.1). filterwarnings only matches warnings.warn() calls anyway, so this entry never suppressed a raised BrokenPipeError. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ode on NFS-shared dirs When ssh_dir_nfs_shared is true, remote_ssh_dir is the same physical directory on every node. authorize_cluster_pubkey, authorize_controlling_station, and install_ssh_config still ran their mutating commands on all nodes concurrently, racing multiple hosts against the same underlying file. install_ssh_config's sed -i (temp-file + rename) hit this in practice -- reproduced live as "base64: write error: Stale file handle" on one node of a 4-node NFS-shared cluster. All three now dispatch through orch.exec_on_head instead of orch.exec when ssh_dir_nfs_shared is set, matching the head-only pattern already used for the SFTP key uploads. Live-tested against the 4-node cluster: 6/6 tests pass, no stale handle errors. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
speriaswamy-amd
left a comment
There was a problem hiding this comment.
Looks good overall, requires couple of changes though:
| for (src, dst), output in zip( | ||
| pairs, [out.get(node, "") for node in nodes if node != nodes[0] or len(nodes) < 2] | ||
| ): | ||
| results[(src, dst)] = "error" not in str(output).lower() and output is not None |
There was a problem hiding this comment.
Blocking: we use "error" not in str(raw).lower() for judging failures, we should be using exit nodes. probe with detailed=True (or ssh ... true && echo CVS_SSH_OK) and require exit code 0
| raw = node_outputs[i] if i < len(node_outputs) else "" | ||
| results[(src, dst)] = raw is not None and "error" not in str(raw).lower() | ||
|
|
||
| else: |
There was a problem hiding this comment.
Blocking: This block generated n - 1 commands and executes on 1 node. But exec_cmd_list requires len(cmd_list) to match the host count, this would raise errors multinode job. Better option would be to use orch.exec(cmd, hosts=[src], detailed=True) as Pssh handle is deprecated
| f"ssh -F {ssh_config_path} -o BatchMode=yes -o ConnectTimeout={timeout} {dst} true" for dst in peers | ||
| ] | ||
| # Run all probes from src via a temporary single-host handle | ||
| from cvs.lib.parallel_ssh_lib import Pssh |
There was a problem hiding this comment.
This is deprecated, should be using the new from cvs.lib.parallel.phandle import ParallelHandle
| return result | ||
|
|
||
|
|
||
| def _upload_local_file(orch, local_path, remote_path): |
There was a problem hiding this comment.
This method doesn't seem to be used anywhere?
| exec_target = orch.exec_on_head if nfs_shared else orch.exec | ||
| out = exec_target(cmd, timeout=30, detailed=True) | ||
|
|
||
| results = {node: True for node in orch.all.reachable_hosts} |
There was a problem hiding this comment.
We turn one result into per node status dict, i.e even if First node fails other nodes stay True, here's a walk through from claude on 3+ nodes: ```
alk through a 3-node cluster, head = n1, NFS write fails on head (exit_code=1):
Start: {n1: True, n2: True, n3: True} — every node assumed success.
out is only {n1: {exit_code: 1}}.
The loop updates only n1 to False.
Return: {n1: False, n2: True, n3: True}.
We should follow `upload_cluster_keys` pattern and mark every node as failed
Motivation
Multi-node RCCL and training test suites require password-less SSH between all cluster nodes as a prerequisite, but CVS has no automated way to set this up — users currently do it by hand per cluster. This adds a
cluster_key_distributiontest suite that distributes a shared cluster keypair, authorizes it (plus optionally the controlling station's own key) inauthorized_keys, writes a managed~/.ssh/configHost block, and verifies password-less connectivity — all driven by a single JSON config.Technical Details
cvs/lib/ssh_keys_lib.py: config validation/normalization, SFTP key upload, authorized_keys injection (append-only, idempotent — never truncates the file), ~/.ssh/config managed-block rendering, and ring/full-mesh connectivity verification.cvs/tests/cluster_key_distribution/ssh_keys_distribution.py: pytest suite, 6 ordered tests (dir setup → key distribution → cluster pubkey authorization → controlling-station pubkey authorization → ssh config install → passwordless SSH verification).cvs/input/config_file/cluster_key_distribution/ssh_key_distribute_config.json: sample config.ssh_dir_nfs_sharedconfig flag: when the remote ~/.ssh dir is the same NFS-mounted directory on every node, all mutating steps (key upload, authorized_keys writes, ~/.ssh/config write) route through the head node only via orch.exec_on_head/orch.head, instead of running redundantly — and racily — on every node against the same underlying file. Without this, concurrent sed -i (temp-file + rename) from multiple nodes against one NFS-shared file reproduced as base64: write error: Stale file handle on a live cluster.exceptions anyway, only warnings.warn() calls.
Test Plan
cluster_key_distributionsuite, both withssh_dir_nfs_sharedtrue and false.Test Result
install_ssh_configon the node that previously hit the stale-NFS-handle race — confirmed fixed with no errors in the run log.Submission Checklist