mesk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mesk-0.1.0/PKG-INFO +205 -0
- mesk-0.1.0/README.md +170 -0
- mesk-0.1.0/pyproject.toml +125 -0
- mesk-0.1.0/setup.cfg +4 -0
- mesk-0.1.0/setup.py +3 -0
- mesk-0.1.0/src/mesk/__init__.py +10 -0
- mesk-0.1.0/src/mesk/__main__.py +80 -0
- mesk-0.1.0/src/mesk/__version__.py +1 -0
- mesk-0.1.0/src/mesk/py.typed +0 -0
- mesk-0.1.0/src/mesk/runner.py +224 -0
- mesk-0.1.0/src/mesk/vendor/__init__.py +0 -0
- mesk-0.1.0/src/mesk/vendor/boardctrl_phidget/README.md +244 -0
- mesk-0.1.0/src/mesk/vendor/boardctrl_phidget/__init__.py +0 -0
- mesk-0.1.0/src/mesk/vendor/boardctrl_phidget/monitor.py +232 -0
- mesk-0.1.0/src/mesk/vendor/boardctrl_phidget/phidget.py +224 -0
- mesk-0.1.0/src/mesk/vendor/boardctrl_phidget/phidget_control.sh +324 -0
- mesk-0.1.0/src/mesk/vendor/topo/Android.mk +27 -0
- mesk-0.1.0/src/mesk/vendor/topo/TCA9539.py +70 -0
- mesk-0.1.0/src/mesk/vendor/topo/__init__.py +0 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/_PCA953x.py +134 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/_TCA6408.py +122 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/__init__.py +0 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/_common.py +203 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/_nv_base_orin_target.py +37 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/_nv_base_thor_target.py +47 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/_nv_base_topo_target.py +249 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/_nv_thor_target.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/_nv_topo_target.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/concord.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/horizon-eb1.py +99 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/jane.py +44 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/orin-jetson.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/orin-slt.py +32 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/t239-slt.py +28 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/t268-slt.py +262 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/tango.py +75 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-andor-slt.py +253 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-cassian-slt.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-drive-agx.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-drive-agx2.py +105 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-drive-pm.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-hope.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-jetson-devkit.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-jetson-module.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-l4t-pm.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-slt.py +262 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/topo.py +21 -0
- mesk-0.1.0/src/mesk/vendor/topo/_targets/yukon.py +75 -0
- mesk-0.1.0/src/mesk/vendor/topo/bmc_interface.py +441 -0
- mesk-0.1.0/src/mesk/vendor/topo/board_control.py +74 -0
- mesk-0.1.0/src/mesk/vendor/topo/board_info.py +104 -0
- mesk-0.1.0/src/mesk/vendor/topo/boardctl +216 -0
- mesk-0.1.0/src/mesk/vendor/topo/debug_board.py +308 -0
- mesk-0.1.0/src/mesk/vendor/topo/e2379.py +130 -0
- mesk-0.1.0/src/mesk/vendor/topo/ftdi_i2c_lin.py +337 -0
- mesk-0.1.0/src/mesk/vendor/topo/ftdi_wrapper.py +103 -0
- mesk-0.1.0/src/mesk/vendor/topo/galen_power.py +40 -0
- mesk-0.1.0/src/mesk/vendor/topo/ina219.py +167 -0
- mesk-0.1.0/src/mesk/vendor/topo/ina226.py +197 -0
- mesk-0.1.0/src/mesk/vendor/topo/ina3221.py +135 -0
- mesk-0.1.0/src/mesk/vendor/topo/libnvtopo.so +0 -0
- mesk-0.1.0/src/mesk/vendor/topo/libnvtopo_wrapper.py +516 -0
- mesk-0.1.0/src/mesk/vendor/topo/lspm342.py +49 -0
- mesk-0.1.0/src/mesk/vendor/topo/measure +324 -0
- mesk-0.1.0/src/mesk/vendor/topo/measure_power +130 -0
- mesk-0.1.0/src/mesk/vendor/topo/metadata.py +158 -0
- mesk-0.1.0/src/mesk/vendor/topo/nvtopo.py +516 -0
- mesk-0.1.0/src/mesk/vendor/topo/pca954x.py +41 -0
- mesk-0.1.0/src/mesk/vendor/topo/pm342.py +122 -0
- mesk-0.1.0/src/mesk/vendor/topo/power.py +93 -0
- mesk-0.1.0/src/mesk/vendor/topo/requirements-bmc.txt +5 -0
- mesk-0.1.0/src/mesk/vendor/topo/supported_targets.py +16 -0
- mesk-0.1.0/src/mesk/vendor/topo/supported_targets_all.py +16 -0
- mesk-0.1.0/src/mesk/vendor/topo/tb500-ctl +792 -0
- mesk-0.1.0/src/mesk/vendor/topo/tckctrl +110 -0
- mesk-0.1.0/src/mesk/vendor/topo/th500-ctl +282 -0
- mesk-0.1.0/src/mesk/vendor/topo/utils.py +91 -0
- mesk-0.1.0/src/mesk/vendor/topo_yukon/README.txt +41 -0
- mesk-0.1.0/src/mesk/vendor/topo_yukon/__init__.py +6 -0
- mesk-0.1.0/src/mesk/vendor/topo_yukon/_targets/__init__.py +0 -0
- mesk-0.1.0/src/mesk/vendor/topo_yukon/_targets/_common.py +202 -0
- mesk-0.1.0/src/mesk/vendor/topo_yukon/_targets/_nv_base_topo_target.py +246 -0
- mesk-0.1.0/src/mesk/vendor/topo_yukon/_targets/yukon.py +75 -0
- mesk-0.1.0/src/mesk/vendor/topo_yukon/boardctl +216 -0
- mesk-0.1.0/src/mesk/vendor/topo_yukon/libnvtopo.dll +0 -0
- mesk-0.1.0/src/mesk/vendor/topo_yukon/libnvtopo.so +0 -0
- mesk-0.1.0/src/mesk/vendor/topo_yukon/libnvtopo_wrapper.py +513 -0
- mesk-0.1.0/src/mesk/vendor/topo_yukon/nvtopo.py +511 -0
- mesk-0.1.0/src/mesk.egg-info/PKG-INFO +205 -0
- mesk-0.1.0/src/mesk.egg-info/SOURCES.txt +93 -0
- mesk-0.1.0/src/mesk.egg-info/dependency_links.txt +1 -0
- mesk-0.1.0/src/mesk.egg-info/entry_points.txt +2 -0
- mesk-0.1.0/src/mesk.egg-info/requires.txt +17 -0
- mesk-0.1.0/src/mesk.egg-info/top_level.txt +1 -0
- mesk-0.1.0/tests/test_reset.py +313 -0
mesk-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mesk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unified power and reset control for Concord, N1-auto, Yukon, and Tango platforms
|
|
5
|
+
Author-email: Miley Zhang <mileyz@nvidia.com>
|
|
6
|
+
License-Expression: LicenseRef-NvidiaProprietary
|
|
7
|
+
Project-URL: Repository, https://gitlab-master.nvidia.com/mileyz/mesk
|
|
8
|
+
Keywords: nvidia,board,reset,power,ci
|
|
9
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: System :: Hardware
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: pyusb
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: ruff==0.16.6; extra == "dev"
|
|
26
|
+
Requires-Dist: ty==0.0.78; extra == "dev"
|
|
27
|
+
Provides-Extra: test
|
|
28
|
+
Requires-Dist: pytest==8.3.1; extra == "test"
|
|
29
|
+
Requires-Dist: pytest-cov==5.0.0; extra == "test"
|
|
30
|
+
Requires-Dist: pytest-timeout==2.3.1; extra == "test"
|
|
31
|
+
Requires-Dist: pytest-xdist==3.6.1; python_version >= "3.9" and extra == "test"
|
|
32
|
+
Requires-Dist: coverage==7.6.0; extra == "test"
|
|
33
|
+
Provides-Extra: n1-auto
|
|
34
|
+
Requires-Dist: Phidget22; extra == "n1-auto"
|
|
35
|
+
|
|
36
|
+
# mesk
|
|
37
|
+
|
|
38
|
+
Unified power and reset control for Concord, N1-auto, Yukon, and Tango platforms.
|
|
39
|
+
Designed for use in DLA compiler CI/CD pipelines.
|
|
40
|
+
|
|
41
|
+
## Install and run
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git clone https://gitlab-master.nvidia.com/mileyz/mesk.git
|
|
45
|
+
cd mesk
|
|
46
|
+
./mesk concord power_off
|
|
47
|
+
./mesk concord power_on
|
|
48
|
+
./mesk concord reset
|
|
49
|
+
./mesk concord recovery
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
On Windows (Yukon / Tango), from cmd or PowerShell:
|
|
53
|
+
|
|
54
|
+
```bat
|
|
55
|
+
git clone https://gitlab-master.nvidia.com/mileyz/mesk.git
|
|
56
|
+
cd mesk
|
|
57
|
+
.\mesk yukon power_off
|
|
58
|
+
.\mesk yukon power_on
|
|
59
|
+
.\mesk yukon reset
|
|
60
|
+
.\mesk yukon recovery
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
First run creates `.venv` and installs the package. Later runs skip that.
|
|
64
|
+
Do not activate the venv yourself; `./mesk` (Linux) and `.\mesk` (Windows `mesk.cmd`) do that.
|
|
65
|
+
On Linux, the first `./mesk concord <action>` writes `/etc/sudoers.d/mesk` (prompts for sudo once) so all later runs are passwordless. Set `MESK_NO_SUDO=1` to skip sudo entirely.
|
|
66
|
+
`./mesk n1-auto ...` installs `Phidget22` into the venv if it is missing.
|
|
67
|
+
|
|
68
|
+
Developers who want lint/test tools can still use:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
python3 -m venv .venv
|
|
72
|
+
source .venv/bin/activate
|
|
73
|
+
pip install -e ".[dev,test]"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Examples:**
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
mesk concord reset
|
|
80
|
+
mesk concord recovery
|
|
81
|
+
mesk concord power_on
|
|
82
|
+
mesk concord power_off
|
|
83
|
+
|
|
84
|
+
mesk n1-auto reset
|
|
85
|
+
mesk n1-auto recovery
|
|
86
|
+
mesk n1-auto power_on
|
|
87
|
+
mesk n1-auto power_off
|
|
88
|
+
|
|
89
|
+
mesk yukon reset
|
|
90
|
+
mesk yukon recovery
|
|
91
|
+
mesk yukon power_on
|
|
92
|
+
mesk yukon power_off
|
|
93
|
+
|
|
94
|
+
mesk tango reset
|
|
95
|
+
mesk tango recovery
|
|
96
|
+
mesk tango power_on
|
|
97
|
+
mesk tango power_off
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Library Usage
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from mesk import run
|
|
104
|
+
|
|
105
|
+
run("concord", "reset")
|
|
106
|
+
run("n1-auto", "power_on")
|
|
107
|
+
run("yukon", "recovery")
|
|
108
|
+
run("tango", "reset")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`run()` returns 0 on success and a non-zero exit code on failure.
|
|
112
|
+
|
|
113
|
+
## Project Layout
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
mesk/
|
|
117
|
+
├── pyproject.toml # build config + all tool settings
|
|
118
|
+
├── setup.py # legacy pip editable compatibility
|
|
119
|
+
├── mesk # Linux/L4T bootstrap launcher
|
|
120
|
+
├── mesk.cmd # Windows bootstrap launcher
|
|
121
|
+
├── .pre-commit-config.yaml
|
|
122
|
+
├── README.md
|
|
123
|
+
├── src/mesk/
|
|
124
|
+
│ ├── __init__.py # public API: run, ACTIONS, __version__
|
|
125
|
+
│ ├── __version__.py
|
|
126
|
+
│ ├── __main__.py # CLI entry
|
|
127
|
+
│ ├── runner.py # action execution + logging
|
|
128
|
+
│ ├── py.typed
|
|
129
|
+
│ └── vendor/ # bundled board control tools
|
|
130
|
+
│ ├── topo/ # Concord (boardctl)
|
|
131
|
+
│ ├── boardctrl_phidget/ # N1-auto
|
|
132
|
+
│ └── topo_yukon/ # Yukon and Tango (boardctl)
|
|
133
|
+
└── tests/
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Logging
|
|
137
|
+
|
|
138
|
+
Each run appends to `logs/YYYY-MM-DD.log` under the current working directory
|
|
139
|
+
(timestamp, platform, action, exit code, and full output).
|
|
140
|
+
Override with `MESK_LOG_DIR`.
|
|
141
|
+
|
|
142
|
+
## Prerequisites
|
|
143
|
+
|
|
144
|
+
Actions call vendor Python APIs in-process (`import`), not shell/`subprocess`.
|
|
145
|
+
|
|
146
|
+
### Concord (Linux host)
|
|
147
|
+
|
|
148
|
+
- Needs the NVIDIA TOPO USB device (`0955:7045`). The first run of `./mesk concord <action>` installs a NOPASSWD sudoers rule automatically; subsequent runs need no password.
|
|
149
|
+
- `pyusb` is installed with mesk for recovery detection.
|
|
150
|
+
- After `concord recovery`, mesk checks USB for `0955:7023` (APX) and fails if it is missing. boardctl may still print `NOT IN RECOVERY MODE`.
|
|
151
|
+
|
|
152
|
+
### N1-auto (Linux host)
|
|
153
|
+
|
|
154
|
+
`./mesk n1-auto <action>` installs `Phidget22` into the venv and, if needed, `libphidget22` via apt (sudo). Set `MESK_NO_SUDO=1` to skip the system-library install.
|
|
155
|
+
|
|
156
|
+
### Yukon / Tango (Windows host)
|
|
157
|
+
|
|
158
|
+
`.\mesk yukon <action>` or `.\mesk tango <action>` creates `.venv` and installs mesk on first run. Needs Python 3.8+ on PATH (or `py -3`) and the TOPO USB device. No sudo.
|
|
159
|
+
|
|
160
|
+
## Platforms & Supported Operations
|
|
161
|
+
|
|
162
|
+
| Action | Concord (L4T) | N1-auto (Auto-Linux) | Yukon / Tango (WoA) |
|
|
163
|
+
|--------|---------------|----------------------|---------------------|
|
|
164
|
+
| `reset` | `nv_topo(target="topo").target_reset()` | `ResetControl(1).execute_reset()` | `nv_topo(target="yukon").target_reset()` |
|
|
165
|
+
| `recovery` | `nv_topo(target="topo").target_recovery_mode()` | `RecoveryControl(1, 0).execute_recovery()` | `nv_topo(target="yukon").target_recovery_mode()` |
|
|
166
|
+
| `power_on` | `nv_topo(target="topo").target_power_on()` | `PowerMonitor(2, False)` then `relay_off(2)` | `nv_topo(target="yukon").target_power_on()` |
|
|
167
|
+
| `power_off` | `nv_topo(target="topo").target_power_off()` | `PowerMonitor(2, True)` then `relay_on(2)` | `nv_topo(target="yukon").target_power_off()` |
|
|
168
|
+
|
|
169
|
+
Tango uses the same `topo_yukon` `nv_topo` target as Yukon (`target="yukon"`).
|
|
170
|
+
N1-auto power is a one-shot relay set (no background `monitor.py` process).
|
|
171
|
+
|
|
172
|
+
## Contribute
|
|
173
|
+
|
|
174
|
+
Suggested local Python: 3.12+ (pre-commit assumes > 3.8 for `pytest -n auto`).
|
|
175
|
+
|
|
176
|
+
pre-commit runs Ruff (format + lint), ty, and pytest. All of these skip
|
|
177
|
+
`vendor/` directories (bundled third-party board tools) so upstream trees
|
|
178
|
+
are not rewritten and can be replaced as drop-in upgrades.
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
python -m venv .venv
|
|
182
|
+
source .venv/bin/activate
|
|
183
|
+
pip install -e ".[dev,test]"
|
|
184
|
+
pip install pre-commit
|
|
185
|
+
pre-commit install
|
|
186
|
+
# Optionally run all hooks
|
|
187
|
+
pre-commit run --all-files
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
pytest
|
|
192
|
+
ruff check .
|
|
193
|
+
ty check
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Test Status
|
|
197
|
+
|
|
198
|
+
| Platform | reset | power_on | power_off | recovery |
|
|
199
|
+
|----------|-------|----------|-----------|----------|
|
|
200
|
+
| Concord (L4T) | PASS | PASS | PASS | PASS* |
|
|
201
|
+
| N1-auto (Auto-Linux) | PASS | PASS | PASS | PASS |
|
|
202
|
+
| Yukon (WoA) | PASS | PASS | PASS | PASS |
|
|
203
|
+
| Tango (WoA) | same as Yukon | same as Yukon | same as Yukon | same as Yukon |
|
|
204
|
+
|
|
205
|
+
\* Concord recovery is checked in-process for USB `0955:7023` (APX).
|
mesk-0.1.0/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# mesk
|
|
2
|
+
|
|
3
|
+
Unified power and reset control for Concord, N1-auto, Yukon, and Tango platforms.
|
|
4
|
+
Designed for use in DLA compiler CI/CD pipelines.
|
|
5
|
+
|
|
6
|
+
## Install and run
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://gitlab-master.nvidia.com/mileyz/mesk.git
|
|
10
|
+
cd mesk
|
|
11
|
+
./mesk concord power_off
|
|
12
|
+
./mesk concord power_on
|
|
13
|
+
./mesk concord reset
|
|
14
|
+
./mesk concord recovery
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
On Windows (Yukon / Tango), from cmd or PowerShell:
|
|
18
|
+
|
|
19
|
+
```bat
|
|
20
|
+
git clone https://gitlab-master.nvidia.com/mileyz/mesk.git
|
|
21
|
+
cd mesk
|
|
22
|
+
.\mesk yukon power_off
|
|
23
|
+
.\mesk yukon power_on
|
|
24
|
+
.\mesk yukon reset
|
|
25
|
+
.\mesk yukon recovery
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
First run creates `.venv` and installs the package. Later runs skip that.
|
|
29
|
+
Do not activate the venv yourself; `./mesk` (Linux) and `.\mesk` (Windows `mesk.cmd`) do that.
|
|
30
|
+
On Linux, the first `./mesk concord <action>` writes `/etc/sudoers.d/mesk` (prompts for sudo once) so all later runs are passwordless. Set `MESK_NO_SUDO=1` to skip sudo entirely.
|
|
31
|
+
`./mesk n1-auto ...` installs `Phidget22` into the venv if it is missing.
|
|
32
|
+
|
|
33
|
+
Developers who want lint/test tools can still use:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python3 -m venv .venv
|
|
37
|
+
source .venv/bin/activate
|
|
38
|
+
pip install -e ".[dev,test]"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Examples:**
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
mesk concord reset
|
|
45
|
+
mesk concord recovery
|
|
46
|
+
mesk concord power_on
|
|
47
|
+
mesk concord power_off
|
|
48
|
+
|
|
49
|
+
mesk n1-auto reset
|
|
50
|
+
mesk n1-auto recovery
|
|
51
|
+
mesk n1-auto power_on
|
|
52
|
+
mesk n1-auto power_off
|
|
53
|
+
|
|
54
|
+
mesk yukon reset
|
|
55
|
+
mesk yukon recovery
|
|
56
|
+
mesk yukon power_on
|
|
57
|
+
mesk yukon power_off
|
|
58
|
+
|
|
59
|
+
mesk tango reset
|
|
60
|
+
mesk tango recovery
|
|
61
|
+
mesk tango power_on
|
|
62
|
+
mesk tango power_off
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Library Usage
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from mesk import run
|
|
69
|
+
|
|
70
|
+
run("concord", "reset")
|
|
71
|
+
run("n1-auto", "power_on")
|
|
72
|
+
run("yukon", "recovery")
|
|
73
|
+
run("tango", "reset")
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`run()` returns 0 on success and a non-zero exit code on failure.
|
|
77
|
+
|
|
78
|
+
## Project Layout
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
mesk/
|
|
82
|
+
├── pyproject.toml # build config + all tool settings
|
|
83
|
+
├── setup.py # legacy pip editable compatibility
|
|
84
|
+
├── mesk # Linux/L4T bootstrap launcher
|
|
85
|
+
├── mesk.cmd # Windows bootstrap launcher
|
|
86
|
+
├── .pre-commit-config.yaml
|
|
87
|
+
├── README.md
|
|
88
|
+
├── src/mesk/
|
|
89
|
+
│ ├── __init__.py # public API: run, ACTIONS, __version__
|
|
90
|
+
│ ├── __version__.py
|
|
91
|
+
│ ├── __main__.py # CLI entry
|
|
92
|
+
│ ├── runner.py # action execution + logging
|
|
93
|
+
│ ├── py.typed
|
|
94
|
+
│ └── vendor/ # bundled board control tools
|
|
95
|
+
│ ├── topo/ # Concord (boardctl)
|
|
96
|
+
│ ├── boardctrl_phidget/ # N1-auto
|
|
97
|
+
│ └── topo_yukon/ # Yukon and Tango (boardctl)
|
|
98
|
+
└── tests/
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Logging
|
|
102
|
+
|
|
103
|
+
Each run appends to `logs/YYYY-MM-DD.log` under the current working directory
|
|
104
|
+
(timestamp, platform, action, exit code, and full output).
|
|
105
|
+
Override with `MESK_LOG_DIR`.
|
|
106
|
+
|
|
107
|
+
## Prerequisites
|
|
108
|
+
|
|
109
|
+
Actions call vendor Python APIs in-process (`import`), not shell/`subprocess`.
|
|
110
|
+
|
|
111
|
+
### Concord (Linux host)
|
|
112
|
+
|
|
113
|
+
- Needs the NVIDIA TOPO USB device (`0955:7045`). The first run of `./mesk concord <action>` installs a NOPASSWD sudoers rule automatically; subsequent runs need no password.
|
|
114
|
+
- `pyusb` is installed with mesk for recovery detection.
|
|
115
|
+
- After `concord recovery`, mesk checks USB for `0955:7023` (APX) and fails if it is missing. boardctl may still print `NOT IN RECOVERY MODE`.
|
|
116
|
+
|
|
117
|
+
### N1-auto (Linux host)
|
|
118
|
+
|
|
119
|
+
`./mesk n1-auto <action>` installs `Phidget22` into the venv and, if needed, `libphidget22` via apt (sudo). Set `MESK_NO_SUDO=1` to skip the system-library install.
|
|
120
|
+
|
|
121
|
+
### Yukon / Tango (Windows host)
|
|
122
|
+
|
|
123
|
+
`.\mesk yukon <action>` or `.\mesk tango <action>` creates `.venv` and installs mesk on first run. Needs Python 3.8+ on PATH (or `py -3`) and the TOPO USB device. No sudo.
|
|
124
|
+
|
|
125
|
+
## Platforms & Supported Operations
|
|
126
|
+
|
|
127
|
+
| Action | Concord (L4T) | N1-auto (Auto-Linux) | Yukon / Tango (WoA) |
|
|
128
|
+
|--------|---------------|----------------------|---------------------|
|
|
129
|
+
| `reset` | `nv_topo(target="topo").target_reset()` | `ResetControl(1).execute_reset()` | `nv_topo(target="yukon").target_reset()` |
|
|
130
|
+
| `recovery` | `nv_topo(target="topo").target_recovery_mode()` | `RecoveryControl(1, 0).execute_recovery()` | `nv_topo(target="yukon").target_recovery_mode()` |
|
|
131
|
+
| `power_on` | `nv_topo(target="topo").target_power_on()` | `PowerMonitor(2, False)` then `relay_off(2)` | `nv_topo(target="yukon").target_power_on()` |
|
|
132
|
+
| `power_off` | `nv_topo(target="topo").target_power_off()` | `PowerMonitor(2, True)` then `relay_on(2)` | `nv_topo(target="yukon").target_power_off()` |
|
|
133
|
+
|
|
134
|
+
Tango uses the same `topo_yukon` `nv_topo` target as Yukon (`target="yukon"`).
|
|
135
|
+
N1-auto power is a one-shot relay set (no background `monitor.py` process).
|
|
136
|
+
|
|
137
|
+
## Contribute
|
|
138
|
+
|
|
139
|
+
Suggested local Python: 3.12+ (pre-commit assumes > 3.8 for `pytest -n auto`).
|
|
140
|
+
|
|
141
|
+
pre-commit runs Ruff (format + lint), ty, and pytest. All of these skip
|
|
142
|
+
`vendor/` directories (bundled third-party board tools) so upstream trees
|
|
143
|
+
are not rewritten and can be replaced as drop-in upgrades.
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
python -m venv .venv
|
|
147
|
+
source .venv/bin/activate
|
|
148
|
+
pip install -e ".[dev,test]"
|
|
149
|
+
pip install pre-commit
|
|
150
|
+
pre-commit install
|
|
151
|
+
# Optionally run all hooks
|
|
152
|
+
pre-commit run --all-files
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
pytest
|
|
157
|
+
ruff check .
|
|
158
|
+
ty check
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Test Status
|
|
162
|
+
|
|
163
|
+
| Platform | reset | power_on | power_off | recovery |
|
|
164
|
+
|----------|-------|----------|-----------|----------|
|
|
165
|
+
| Concord (L4T) | PASS | PASS | PASS | PASS* |
|
|
166
|
+
| N1-auto (Auto-Linux) | PASS | PASS | PASS | PASS |
|
|
167
|
+
| Yukon (WoA) | PASS | PASS | PASS | PASS |
|
|
168
|
+
| Tango (WoA) | same as Yukon | same as Yukon | same as Yukon | same as Yukon |
|
|
169
|
+
|
|
170
|
+
\* Concord recovery is checked in-process for USB `0955:7023` (APX).
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools >= 60"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "mesk"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
authors = [
|
|
9
|
+
{name = "Miley Zhang", email = "mileyz@nvidia.com"},
|
|
10
|
+
]
|
|
11
|
+
description = "Unified power and reset control for Concord, N1-auto, Yukon, and Tango platforms"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.8"
|
|
14
|
+
license = "LicenseRef-NvidiaProprietary"
|
|
15
|
+
keywords = ["nvidia", "board", "reset", "power", "ci"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Operating System :: Microsoft :: Windows",
|
|
18
|
+
"Operating System :: POSIX :: Linux",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.8",
|
|
21
|
+
"Programming Language :: Python :: 3.9",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Topic :: System :: Hardware",
|
|
27
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
28
|
+
"Typing :: Typed",
|
|
29
|
+
]
|
|
30
|
+
dependencies = [
|
|
31
|
+
"pyusb",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Repository = "https://gitlab-master.nvidia.com/mileyz/mesk"
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
dev = [
|
|
39
|
+
"ruff == 0.16.6",
|
|
40
|
+
"ty == 0.0.78",
|
|
41
|
+
]
|
|
42
|
+
test = [
|
|
43
|
+
"pytest == 8.3.1",
|
|
44
|
+
"pytest-cov == 5.0.0",
|
|
45
|
+
"pytest-timeout == 2.3.1",
|
|
46
|
+
"pytest-xdist == 3.6.1; python_version >= '3.9'",
|
|
47
|
+
"coverage == 7.6.0",
|
|
48
|
+
]
|
|
49
|
+
n1-auto = [
|
|
50
|
+
"Phidget22",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[project.scripts]
|
|
54
|
+
mesk = "mesk.__main__:main"
|
|
55
|
+
|
|
56
|
+
[tool.setuptools]
|
|
57
|
+
package-dir = {"" = "src"}
|
|
58
|
+
|
|
59
|
+
[tool.setuptools.packages.find]
|
|
60
|
+
where = ["src"]
|
|
61
|
+
include = ["mesk*"]
|
|
62
|
+
exclude = [
|
|
63
|
+
"mesk.vendor.boardctrl_phidget.venv*",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
[tool.setuptools.package-data]
|
|
67
|
+
"*" = ["*"]
|
|
68
|
+
|
|
69
|
+
[tool.setuptools.dynamic]
|
|
70
|
+
version = {attr = "mesk.__version__"}
|
|
71
|
+
|
|
72
|
+
[tool.ty.environment]
|
|
73
|
+
python-version = "3.8"
|
|
74
|
+
|
|
75
|
+
[tool.ty.src]
|
|
76
|
+
include = ["src"]
|
|
77
|
+
exclude = ["src/mesk/vendor", "src/vendor"]
|
|
78
|
+
|
|
79
|
+
[tool.ty.terminal]
|
|
80
|
+
error-on-warning = false
|
|
81
|
+
|
|
82
|
+
[tool.ruff]
|
|
83
|
+
src = ["src"]
|
|
84
|
+
target-version = "py38"
|
|
85
|
+
# Third-party vendor trees; keep them unmodified for drop-in upgrades.
|
|
86
|
+
extend-exclude = ["src/mesk/vendor", "src/vendor"]
|
|
87
|
+
|
|
88
|
+
[tool.ruff.lint]
|
|
89
|
+
ignore = [
|
|
90
|
+
# Below ignored to avoid conflict with Ruff format
|
|
91
|
+
# Refer https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
|
|
92
|
+
"W191", # tab-indentation
|
|
93
|
+
"E111", # indentation-with-invalid-multiple
|
|
94
|
+
"E114", # indentation-with-invalid-multiple-comment
|
|
95
|
+
"E117", # over-indented
|
|
96
|
+
"D206", # indent-with-spaces
|
|
97
|
+
"D300", # triple-single-quotes
|
|
98
|
+
"Q000", # bad-quotes-inline-string
|
|
99
|
+
"Q001", # bad-quotes-multiline-string
|
|
100
|
+
"Q002", # bad-quotes-docstring
|
|
101
|
+
"Q003", # avoidable-escaped-quote
|
|
102
|
+
"COM812", # missing-trailing-comma
|
|
103
|
+
"COM819", # prohibited-trailing-comma
|
|
104
|
+
"ISC001", # single-line-implicit-string-concatenation
|
|
105
|
+
"ISC002", # multi-line-implicit-string-concatenation
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
[tool.pytest.ini_options]
|
|
109
|
+
testpaths = ["tests"]
|
|
110
|
+
pythonpath = ["src"]
|
|
111
|
+
norecursedirs = [".*", "build", "dist", "vendor"]
|
|
112
|
+
|
|
113
|
+
[tool.coverage.paths]
|
|
114
|
+
source = ["src/"]
|
|
115
|
+
|
|
116
|
+
[tool.coverage.run]
|
|
117
|
+
source = ["src/mesk"]
|
|
118
|
+
relative_files = true
|
|
119
|
+
omit = ["tests/*", "src/mesk/vendor/*", "src/vendor/*"]
|
|
120
|
+
|
|
121
|
+
[tool.coverage.report]
|
|
122
|
+
exclude_lines = ["NotImplementedError", "pragma: no cover"]
|
|
123
|
+
|
|
124
|
+
[tool.coverage.json]
|
|
125
|
+
pretty_print = true
|
mesk-0.1.0/setup.cfg
ADDED
mesk-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""CLI entry point for mesk."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from mesk.runner import _PLATFORMS, ACTIONS, run
|
|
9
|
+
|
|
10
|
+
_SUDO_PLATFORMS = frozenset({"concord"})
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _needs_sudo(platform: str) -> bool:
|
|
14
|
+
if platform not in _SUDO_PLATFORMS:
|
|
15
|
+
return False
|
|
16
|
+
if os.environ.get("MESK_NO_SUDO"):
|
|
17
|
+
return False
|
|
18
|
+
try:
|
|
19
|
+
return os.geteuid() != 0
|
|
20
|
+
except AttributeError:
|
|
21
|
+
return False
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _reexec_with_sudo() -> None:
|
|
25
|
+
os.execvp("sudo", ["sudo", sys.executable, "-m", "mesk", *sys.argv[1:]])
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _phidget_lib_present() -> bool:
|
|
29
|
+
from ctypes.util import find_library
|
|
30
|
+
|
|
31
|
+
return find_library("phidget22") is not None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _ensure_libphidget22() -> None:
|
|
35
|
+
if _phidget_lib_present():
|
|
36
|
+
return
|
|
37
|
+
if os.environ.get("MESK_NO_SUDO"):
|
|
38
|
+
raise RuntimeError("libphidget22 is missing; install it or unset MESK_NO_SUDO")
|
|
39
|
+
import subprocess
|
|
40
|
+
|
|
41
|
+
print("Installing libphidget22 (may prompt for sudo)...")
|
|
42
|
+
apt = subprocess.run(["sudo", "apt-get", "install", "-y", "libphidget22"])
|
|
43
|
+
if apt.returncode == 0 and _phidget_lib_present():
|
|
44
|
+
return
|
|
45
|
+
print("Adding Phidget apt repository...")
|
|
46
|
+
setup = subprocess.run(
|
|
47
|
+
["curl", "-fsSL", "https://www.phidgets.com/downloads/setup_linux"],
|
|
48
|
+
check=True,
|
|
49
|
+
stdout=subprocess.PIPE,
|
|
50
|
+
)
|
|
51
|
+
subprocess.run(["sudo", "bash"], input=setup.stdout, check=True)
|
|
52
|
+
subprocess.check_call(["sudo", "apt-get", "install", "-y", "libphidget22"])
|
|
53
|
+
if not _phidget_lib_present():
|
|
54
|
+
raise RuntimeError("libphidget22 is still missing after install")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _ensure_phidget22() -> None:
|
|
58
|
+
import importlib.util
|
|
59
|
+
import subprocess
|
|
60
|
+
|
|
61
|
+
if importlib.util.find_spec("Phidget22") is None:
|
|
62
|
+
print("Installing Phidget22 into this environment...")
|
|
63
|
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "Phidget22"])
|
|
64
|
+
_ensure_libphidget22()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def main() -> None:
|
|
68
|
+
platforms = list(_PLATFORMS)
|
|
69
|
+
if len(sys.argv) != 3 or sys.argv[1] not in platforms or sys.argv[2] not in ACTIONS:
|
|
70
|
+
print(f"Usage: mesk <{'|'.join(platforms)}> <{'|'.join(ACTIONS)}>")
|
|
71
|
+
sys.exit(1)
|
|
72
|
+
if sys.argv[1] == "n1-auto":
|
|
73
|
+
_ensure_phidget22()
|
|
74
|
+
if _needs_sudo(sys.argv[1]):
|
|
75
|
+
_reexec_with_sudo()
|
|
76
|
+
sys.exit(run(sys.argv[1], sys.argv[2]))
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
if __name__ == "__main__":
|
|
80
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
File without changes
|