Rename remote_nodes module to node_control
- Move remote_nodes.py to node_control.py; update commands __init__ - Rename design doc and test file; refresh README references Made-with: Cursor
This commit is contained in:
parent
1f3803c75a
commit
e5b5010aaa
12
README.md
12
README.md
|
|
@ -4,7 +4,7 @@ Tools and libraries for managing and testing Umber Fi‑Wi networks.
|
|||
|
||||
This repository ships one Python distribution (**`fiwicontrol`** for `pip`) whose import root is **`orchestrator`**:
|
||||
|
||||
1. **`orchestrator.commands`** — run commands on remote rigs via OpenSSH or **`ush`**, with asyncio streaming, timeouts, repeats (`Command`), and a small registry (`CommandManager`). Implementation: `src/orchestrator/commands/remote_nodes.py`.
|
||||
1. **`orchestrator.commands`** — run commands on remote rigs via OpenSSH or **`ush`**, with asyncio streaming, timeouts, repeats (`Command`), and a small registry (`CommandManager`). Implementation: `src/orchestrator/commands/node_control.py`.
|
||||
2. **`orchestrator.power`** — reserved for power switching, monitoring, and discovery (Acroname, Monsoon, …). Must depend on **`commands`** only, not the reverse.
|
||||
|
||||
**Layout**
|
||||
|
|
@ -15,12 +15,12 @@ FiWiControl/
|
|||
├── README.md
|
||||
├── pyproject.toml
|
||||
├── docs/
|
||||
│ └── remote-nodes-asyncio-design.md
|
||||
│ └── node-control-asyncio-design.md
|
||||
├── src/
|
||||
│ └── orchestrator/
|
||||
│ ├── commands/
|
||||
│ │ ├── __init__.py
|
||||
│ │ └── remote_nodes.py
|
||||
│ │ └── node_control.py
|
||||
│ └── power/
|
||||
│ └── __init__.py
|
||||
└── tests/
|
||||
|
|
@ -29,7 +29,7 @@ FiWiControl/
|
|||
## Requirements
|
||||
|
||||
- Python **3.11+**
|
||||
- For **`sshtype="ssh"`**: **passwordless** SSH to **`root@<host>`** (non-interactive `ssh`; see `docs/remote-nodes-asyncio-design.md`).
|
||||
- For **`sshtype="ssh"`**: **passwordless** SSH to **`root@<host>`** (non-interactive `ssh`; see `docs/node-control-asyncio-design.md`).
|
||||
|
||||
## Install (editable)
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ from orchestrator.commands import ssh_node, Command, CommandManager
|
|||
|
||||
## Tests
|
||||
|
||||
Commands, example **`pytest`** output, and **`unittest`** entry points for **`remote_nodes`**: **`docs/remote-nodes-asyncio-design.md`** → section **“Running tests”** (top-level `##` heading near the top of the file).
|
||||
Commands, example **`pytest`** output, and **`unittest`** entry points for **`node_control`**: **`docs/node-control-asyncio-design.md`** → section **“Running tests”** (top-level `##` heading near the top of the file).
|
||||
|
||||
Layout / import smoke (no network):
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ Remote integration (needs **`FIWI_REMOTE_IP`** and key auth):
|
|||
|
||||
```bash
|
||||
cd ~/Code/FiWiControl
|
||||
FIWI_REMOTE_IP=192.168.1.39 pytest -q tests/test_remote_nodes.py
|
||||
FIWI_REMOTE_IP=192.168.1.39 pytest -q tests/test_node_control.py
|
||||
```
|
||||
|
||||
## Remote (Gitea)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
**Status:** Current
|
||||
|
||||
**Package:** **`orchestrator.commands`** (FiWiControl repository).
|
||||
**Implementation file:** **`src/orchestrator/commands/remote_nodes.py`**.
|
||||
**Implementation file:** **`src/orchestrator/commands/node_control.py`**.
|
||||
The main entry type is still named **`ssh_node`** (historical name: SSH/`ush`-oriented rig connection).
|
||||
|
||||
**Scope:** Asyncio-based SSH/`ush` rig control: **`ssh_node`**, **`ssh_session`**, **`Command`**, **`CommandManager`**, concurrent execution via **`asyncio`**, line-oriented streaming, and logging.
|
||||
|
|
@ -15,7 +15,7 @@ The main entry type is still named **`ssh_node`** (historical name: SSH/`ush`-or
|
|||
|
||||
## Running tests
|
||||
|
||||
Integration tests for **`remote_nodes.py`** live in **`tests/test_remote_nodes.py`**. They open real **`ssh`** sessions to **`root@$FIWI_REMOTE_IP`** (default **`192.168.1.39`**). **Passwordless SSH must work** for that host.
|
||||
Integration tests for **`node_control.py`** live in **`tests/test_node_control.py`**. They open real **`ssh`** sessions to **`root@$FIWI_REMOTE_IP`** (default **`192.168.1.39`**). **Passwordless SSH must work** for that host.
|
||||
|
||||
**From a terminal** (repository root — e.g. **`~/Code/FiWiControl`**):
|
||||
|
||||
|
|
@ -26,24 +26,24 @@ cd ~/Code/FiWiControl
|
|||
export FIWI_REMOTE_IP=192.168.1.39
|
||||
|
||||
# Verbose pytest (recommended)
|
||||
python -m pytest tests/test_remote_nodes.py -v
|
||||
python -m pytest tests/test_node_control.py -v
|
||||
|
||||
# Quiet summary only
|
||||
python -m pytest tests/test_remote_nodes.py -q
|
||||
python -m pytest tests/test_node_control.py -q
|
||||
```
|
||||
|
||||
**Without pytest**, the file is also a **`unittest`** script:
|
||||
|
||||
```bash
|
||||
cd ~/Code/FiWiControl
|
||||
python tests/test_remote_nodes.py --remote-ip 192.168.1.39
|
||||
python tests/test_node_control.py --remote-ip 192.168.1.39
|
||||
# More asyncio logging:
|
||||
python tests/test_remote_nodes.py --remote-ip 192.168.1.39 --debug
|
||||
python tests/test_node_control.py --remote-ip 192.168.1.39 --debug
|
||||
```
|
||||
|
||||
**`pytest`** picks up **`pythonpath = ["src"]`** from **`pyproject.toml`**, so you do **not** need **`PYTHONPATH=src`** when you run from the repo root as above. After **`pip install -e .`**, imports resolve the same way.
|
||||
|
||||
**Example successful output** (line order and timings vary; captured with **`python -m pytest tests/test_remote_nodes.py -v`** on Linux):
|
||||
**Example successful output** (line order and timings vary; captured with **`python -m pytest tests/test_node_control.py -v`** on Linux):
|
||||
|
||||
```text
|
||||
============================= test session starts ==============================
|
||||
|
|
@ -54,12 +54,12 @@ configfile: pyproject.toml
|
|||
plugins: anyio-4.8.0
|
||||
collecting ... collected 6 items
|
||||
|
||||
tests/test_remote_nodes.py::TestRemoteSingleRunCommands::test_dmesg_tail PASSED [ 16%]
|
||||
tests/test_remote_nodes.py::TestRemoteSingleRunCommands::test_ls_home_directory PASSED [ 33%]
|
||||
tests/test_remote_nodes.py::TestRemoteRepeatingCommands::test_command_manager_add_and_self_clean PASSED [ 50%]
|
||||
tests/test_remote_nodes.py::TestRemoteRepeatingCommands::test_repeat_01_uname_r_every_1s_10_times PASSED [ 66%]
|
||||
tests/test_remote_nodes.py::TestRemoteRepeatingCommands::test_repeat_02_pwd_and_ls_every_1s_5_times PASSED [ 83%]
|
||||
tests/test_remote_nodes.py::TestRemoteRepeatingCommands::test_repeat_03_forever_can_be_stopped PASSED [100%]
|
||||
tests/test_node_control.py::TestRemoteSingleRunCommands::test_dmesg_tail PASSED [ 16%]
|
||||
tests/test_node_control.py::TestRemoteSingleRunCommands::test_ls_home_directory PASSED [ 33%]
|
||||
tests/test_node_control.py::TestRemoteRepeatingCommands::test_command_manager_add_and_self_clean PASSED [ 50%]
|
||||
tests/test_node_control.py::TestRemoteRepeatingCommands::test_repeat_01_uname_r_every_1s_10_times PASSED [ 66%]
|
||||
tests/test_node_control.py::TestRemoteRepeatingCommands::test_repeat_02_pwd_and_ls_every_1s_5_times PASSED [ 83%]
|
||||
tests/test_node_control.py::TestRemoteRepeatingCommands::test_repeat_03_forever_can_be_stopped PASSED [100%]
|
||||
|
||||
============================== 6 passed in 16.47s ==============================
|
||||
```
|
||||
|
|
@ -77,7 +77,7 @@ python -m pytest tests/test_package_layout.py -q
|
|||
|
||||
## How to use (examples)
|
||||
|
||||
Implementation lives in **`src/orchestrator/commands/remote_nodes.py`**. All remote I/O is **async** — call from a coroutine under **`asyncio.run()`** or your application event loop.
|
||||
Implementation lives in **`src/orchestrator/commands/node_control.py`**. All remote I/O is **async** — call from a coroutine under **`asyncio.run()`** or your application event loop.
|
||||
|
||||
### Prerequisites (remote targets)
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ from orchestrator.commands import Command, CommandManager, ssh_node
|
|||
Equivalent submodule import (same symbols):
|
||||
|
||||
```python
|
||||
from orchestrator.commands.remote_nodes import Command, CommandManager, ssh_node
|
||||
from orchestrator.commands.node_control import Command, CommandManager, ssh_node
|
||||
```
|
||||
|
||||
Install the package (editable: **`pip install -e .`** from the **FiWiControl** repo root; distribution name **`fiwicontrol`**). For **`pytest`** without installing, **`pythonpath = ["src"]`** is set in **`pyproject.toml`**.
|
||||
|
|
@ -611,6 +611,6 @@ This section lists **behaviors to verify** in automated tests (unit, functional,
|
|||
|
||||
---
|
||||
|
||||
Implemented coverage reference: `tests/test_remote_nodes.py`
|
||||
Implemented coverage reference: `tests/test_node_control.py`
|
||||
|
||||
*End of design document.*
|
||||
|
|
@ -4,7 +4,7 @@ Command execution over SSH / ``ush``: sessions, scheduling, timeouts.
|
|||
Must not import from ``orchestrator.power``.
|
||||
"""
|
||||
|
||||
from orchestrator.commands.remote_nodes import (
|
||||
from orchestrator.commands.node_control import (
|
||||
Command,
|
||||
CommandManager,
|
||||
sleep_async,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Licensed under the Apache License, Version 2.0; see LICENSE.
|
||||
#
|
||||
# Remote command helpers (SSH / ush) for test rig control.
|
||||
# Node command helpers (SSH / ush) for test rig control.
|
||||
# Package: orchestrator.commands (FiWiControl). Public imports: from orchestrator.commands import ssh_node, ...
|
||||
#
|
||||
# Async-first implementation for ssh_node.
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
# - Repeating: cmd = Command(node, cmd="...", interval=1.0, count=10); await cmd.start(); await cmd.task
|
||||
# - Many: CommandManager().add_command(...) / stop_all() / list_active()
|
||||
#
|
||||
# Remote targets (sshtype "ssh"): passwordless SSH is required — see docs/remote-nodes-asyncio-design.md (## Running tests).
|
||||
# SSH targets (sshtype "ssh"): passwordless SSH is required — see docs/node-control-asyncio-design.md (## Running tests).
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
|
@ -5,7 +5,7 @@ import os
|
|||
import sys
|
||||
import unittest
|
||||
|
||||
from orchestrator.commands.remote_nodes import Command, CommandManager, ssh_node
|
||||
from orchestrator.commands.node_control import Command, CommandManager, ssh_node
|
||||
|
||||
|
||||
class _RemoteNodeMixin:
|
||||
|
|
@ -84,7 +84,7 @@ class TestRemoteRepeatingCommands(_RemoteNodeMixin, unittest.IsolatedAsyncioTest
|
|||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Integration tests for orchestrator.commands.remote_nodes (passwordless SSH required)."
|
||||
description="Integration tests for orchestrator.commands.node_control (passwordless SSH required)."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--remote-ip",
|
||||
|
|
@ -100,5 +100,5 @@ if __name__ == "__main__":
|
|||
else:
|
||||
logging.basicConfig(level=logging.WARNING, format="%(message)s")
|
||||
logging.getLogger("asyncio").setLevel(logging.WARNING)
|
||||
logging.getLogger("orchestrator.commands.remote_nodes").setLevel(logging.INFO)
|
||||
logging.getLogger("orchestrator.commands.node_control").setLevel(logging.INFO)
|
||||
unittest.main(argv=[sys.argv[0], *remaining])
|
||||
Loading…
Reference in New Issue