aws-bootstrap-g4dn 0.5.0__py3-none-any.whl → 0.7.0__py3-none-any.whl
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.
- aws_bootstrap/cli.py +502 -86
- aws_bootstrap/config.py +2 -0
- aws_bootstrap/ec2.py +137 -8
- aws_bootstrap/output.py +106 -0
- aws_bootstrap/resources/remote_setup.sh +2 -2
- aws_bootstrap/ssh.py +142 -20
- aws_bootstrap/tests/test_cli.py +652 -4
- aws_bootstrap/tests/test_config.py +18 -0
- aws_bootstrap/tests/test_ebs.py +245 -0
- aws_bootstrap/tests/test_output.py +192 -0
- aws_bootstrap/tests/test_ssh_config.py +76 -0
- aws_bootstrap/tests/test_ssh_ebs.py +76 -0
- {aws_bootstrap_g4dn-0.5.0.dist-info → aws_bootstrap_g4dn-0.7.0.dist-info}/METADATA +79 -7
- aws_bootstrap_g4dn-0.7.0.dist-info/RECORD +31 -0
- aws_bootstrap_g4dn-0.5.0.dist-info/RECORD +0 -27
- {aws_bootstrap_g4dn-0.5.0.dist-info → aws_bootstrap_g4dn-0.7.0.dist-info}/WHEEL +0 -0
- {aws_bootstrap_g4dn-0.5.0.dist-info → aws_bootstrap_g4dn-0.7.0.dist-info}/entry_points.txt +0 -0
- {aws_bootstrap_g4dn-0.5.0.dist-info → aws_bootstrap_g4dn-0.7.0.dist-info}/licenses/LICENSE +0 -0
- {aws_bootstrap_g4dn-0.5.0.dist-info → aws_bootstrap_g4dn-0.7.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aws-bootstrap-g4dn
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Bootstrap AWS EC2 GPU instances for hybrid local-remote development
|
|
5
5
|
Author: Adam Ever-Hadani
|
|
6
6
|
License-Expression: MIT
|
|
@@ -15,6 +15,8 @@ Description-Content-Type: text/markdown
|
|
|
15
15
|
License-File: LICENSE
|
|
16
16
|
Requires-Dist: boto3>=1.35
|
|
17
17
|
Requires-Dist: click>=8.1
|
|
18
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
19
|
+
Requires-Dist: tabulate>=0.9.0
|
|
18
20
|
Dynamic: license-file
|
|
19
21
|
|
|
20
22
|
# aws-bootstrap-g4dn
|
|
@@ -44,7 +46,8 @@ ssh aws-gpu1 # You're in, venv activated, PyTorch works
|
|
|
44
46
|
| 📊 | **GPU benchmark included** | CNN (MNIST) + Transformer benchmarks with FP16/FP32/BF16 precision and tqdm progress |
|
|
45
47
|
| 📓 | **Jupyter ready** | Lab server auto-starts as a systemd service on port 8888 — just SSH tunnel and open |
|
|
46
48
|
| 🖥️ | **`status --gpu`** | Shows CUDA toolkit version, driver max, GPU architecture, spot pricing, uptime, and estimated cost |
|
|
47
|
-
|
|
|
49
|
+
| 💾 | **EBS data volumes** | Attach persistent storage at `/data` — survives spot interruptions and termination, reattach to new instances |
|
|
50
|
+
| 🗑️ | **Clean terminate** | Stops instances, removes SSH aliases, cleans up EBS volumes (or preserves with `--keep-ebs`) |
|
|
48
51
|
|
|
49
52
|
### 🎯 Target Workflows
|
|
50
53
|
|
|
@@ -132,16 +135,24 @@ aws-bootstrap launch --python-version 3.13
|
|
|
132
135
|
# Use a non-default SSH port
|
|
133
136
|
aws-bootstrap launch --ssh-port 2222
|
|
134
137
|
|
|
138
|
+
# Attach a persistent EBS data volume (96 GB gp3, mounted at /data)
|
|
139
|
+
aws-bootstrap launch --ebs-storage 96
|
|
140
|
+
|
|
141
|
+
# Reattach an existing EBS volume from a previous instance
|
|
142
|
+
aws-bootstrap launch --ebs-volume-id vol-0abc123def456
|
|
143
|
+
|
|
135
144
|
# Use a specific AWS profile
|
|
136
145
|
aws-bootstrap launch --profile my-aws-profile
|
|
137
146
|
```
|
|
138
147
|
|
|
139
148
|
After launch, the CLI:
|
|
140
149
|
|
|
141
|
-
1. **
|
|
142
|
-
2. **
|
|
143
|
-
3. **Runs
|
|
144
|
-
4. **
|
|
150
|
+
1. **Creates/attaches EBS volume** (if `--ebs-storage` or `--ebs-volume-id` was specified)
|
|
151
|
+
2. **Adds an SSH alias** (e.g. `aws-gpu1`) to `~/.ssh/config`
|
|
152
|
+
3. **Runs remote setup** — installs utilities, creates a Python venv, installs CUDA-matched PyTorch, sets up Jupyter
|
|
153
|
+
4. **Mounts EBS volume** at `/data` (if applicable — formats new volumes, mounts existing ones as-is)
|
|
154
|
+
5. **Runs a CUDA smoke test** — verifies `torch.cuda.is_available()` and runs a quick GPU matmul
|
|
155
|
+
6. **Prints connection commands** — SSH, Jupyter tunnel, GPU benchmark, and terminate
|
|
145
156
|
|
|
146
157
|
```bash
|
|
147
158
|
ssh aws-gpu1 # venv auto-activates on login
|
|
@@ -154,7 +165,7 @@ The setup script runs automatically on the instance after SSH becomes available:
|
|
|
154
165
|
| Step | What |
|
|
155
166
|
|------|------|
|
|
156
167
|
| **GPU verify** | Confirms `nvidia-smi` and `nvcc` are working |
|
|
157
|
-
| **Utilities** | Installs `htop`, `tmux`, `tree`, `jq` |
|
|
168
|
+
| **Utilities** | Installs `htop`, `tmux`, `tree`, `jq`, `ffmpeg` |
|
|
158
169
|
| **Python venv** | Creates `~/venv` with `uv`, auto-activates in `~/.bashrc`. Use `--python-version` to pin a specific Python (e.g. `3.13`) |
|
|
159
170
|
| **CUDA-aware PyTorch** | Detects CUDA toolkit version → installs PyTorch from the matching `cu{TAG}` wheel index |
|
|
160
171
|
| **CUDA smoke test** | Runs `torch.cuda.is_available()` + GPU matmul to verify the stack |
|
|
@@ -223,6 +234,30 @@ Then install the [Nsight VSCE extension](https://marketplace.visualstudio.com/it
|
|
|
223
234
|
|
|
224
235
|
See [Nsight remote profiling guide](docs/nsight-remote-profiling.md) for more details on CUDA debugging and profiling workflows.
|
|
225
236
|
|
|
237
|
+
### 📤 Structured Output
|
|
238
|
+
|
|
239
|
+
All commands support `--output` / `-o` for machine-readable output — useful for scripting, piping to `jq`, or LLM tool-use:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
# JSON output (pipe to jq)
|
|
243
|
+
aws-bootstrap -o json status
|
|
244
|
+
aws-bootstrap -o json status | jq '.instances[0].instance_id'
|
|
245
|
+
|
|
246
|
+
# YAML output
|
|
247
|
+
aws-bootstrap -o yaml status
|
|
248
|
+
|
|
249
|
+
# Table output
|
|
250
|
+
aws-bootstrap -o table status
|
|
251
|
+
|
|
252
|
+
# Works with all commands
|
|
253
|
+
aws-bootstrap -o json list instance-types | jq '.[].instance_type'
|
|
254
|
+
aws-bootstrap -o json launch --dry-run
|
|
255
|
+
aws-bootstrap -o json terminate --yes
|
|
256
|
+
aws-bootstrap -o json cleanup --dry-run
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Supported formats: `text` (default, human-readable with color), `json`, `yaml`, `table`. Commands that require confirmation (`terminate`, `cleanup`) require `--yes` in structured output modes.
|
|
260
|
+
|
|
226
261
|
### 📋 Listing Resources
|
|
227
262
|
|
|
228
263
|
```bash
|
|
@@ -261,6 +296,9 @@ aws-bootstrap status --region us-east-1
|
|
|
261
296
|
# Terminate all aws-bootstrap instances (with confirmation prompt)
|
|
262
297
|
aws-bootstrap terminate
|
|
263
298
|
|
|
299
|
+
# Terminate but preserve EBS data volumes for reuse
|
|
300
|
+
aws-bootstrap terminate --keep-ebs
|
|
301
|
+
|
|
264
302
|
# Terminate by SSH alias (resolved via ~/.ssh/config)
|
|
265
303
|
aws-bootstrap terminate aws-gpu1
|
|
266
304
|
|
|
@@ -272,6 +310,15 @@ aws-bootstrap terminate aws-gpu1 i-def456
|
|
|
272
310
|
|
|
273
311
|
# Skip confirmation prompt
|
|
274
312
|
aws-bootstrap terminate --yes
|
|
313
|
+
|
|
314
|
+
# Remove stale SSH config entries for terminated instances
|
|
315
|
+
aws-bootstrap cleanup
|
|
316
|
+
|
|
317
|
+
# Preview what would be removed without modifying config
|
|
318
|
+
aws-bootstrap cleanup --dry-run
|
|
319
|
+
|
|
320
|
+
# Skip confirmation prompt
|
|
321
|
+
aws-bootstrap cleanup --yes
|
|
275
322
|
```
|
|
276
323
|
|
|
277
324
|
`status --gpu` reports both the **installed CUDA toolkit** version (from `nvcc`) and the **maximum CUDA version supported by the driver** (from `nvidia-smi`), so you can see at a glance whether they match:
|
|
@@ -282,6 +329,31 @@ CUDA: 12.8 (driver supports up to 13.0)
|
|
|
282
329
|
|
|
283
330
|
SSH aliases are managed automatically — they're created on `launch`, shown in `status`, and cleaned up on `terminate`. Aliases use sequential numbering (`aws-gpu1`, `aws-gpu2`, etc.) and never reuse numbers from previous instances. You can use aliases anywhere you'd use an instance ID, e.g. `aws-bootstrap terminate aws-gpu1`.
|
|
284
331
|
|
|
332
|
+
## EBS Data Volumes
|
|
333
|
+
|
|
334
|
+
Attach persistent EBS storage to keep datasets and model checkpoints across instance lifecycles. Volumes are mounted at `/data` and persist independently of the instance.
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
# Create a new 96 GB gp3 volume, formatted and mounted at /data
|
|
338
|
+
aws-bootstrap launch --ebs-storage 96
|
|
339
|
+
|
|
340
|
+
# After terminating with --keep-ebs, reattach the same volume to a new instance
|
|
341
|
+
aws-bootstrap terminate --keep-ebs
|
|
342
|
+
# Output: Preserving EBS volume: vol-0abc123...
|
|
343
|
+
# Reattach with: aws-bootstrap launch --ebs-volume-id vol-0abc123...
|
|
344
|
+
|
|
345
|
+
aws-bootstrap launch --ebs-volume-id vol-0abc123def456
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Key behaviors:
|
|
349
|
+
- `--ebs-storage` and `--ebs-volume-id` are mutually exclusive
|
|
350
|
+
- New volumes are formatted as ext4; existing volumes are mounted as-is
|
|
351
|
+
- Volumes are tagged for automatic discovery by `status` and `terminate`
|
|
352
|
+
- `terminate` deletes data volumes by default; use `--keep-ebs` to preserve them
|
|
353
|
+
- **Spot-safe** — data volumes survive spot interruptions. If AWS reclaims your instance, the volume detaches automatically and can be reattached to a new instance with `--ebs-volume-id`
|
|
354
|
+
- EBS volumes must be in the same availability zone as the instance
|
|
355
|
+
- Mount failures are non-fatal — the instance remains usable
|
|
356
|
+
|
|
285
357
|
## EC2 vCPU Quotas
|
|
286
358
|
|
|
287
359
|
AWS accounts have [service quotas](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-resource-limits.html) that limit how many vCPUs you can run per instance family. New or lightly-used accounts often have a **default quota of 0 vCPUs** for GPU instance families (G and VT), which will cause errors on launch:
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
aws_bootstrap/__init__.py,sha256=kl_jvrunGyIyizdRqAP6ROb5P1BBrXX5PTq5gq1ipU0,82
|
|
2
|
+
aws_bootstrap/cli.py,sha256=R9w_sTBQwM0JqGTx4-THNe_x7iN-LlX4lE0kD55rytg,36173
|
|
3
|
+
aws_bootstrap/config.py,sha256=p770XgjfuK1-wVkAEeBdtJSVkc58DKFHgaJlZ-zbGmk,967
|
|
4
|
+
aws_bootstrap/ec2.py,sha256=giyfRdrriqvC_jPvGmtbEv2LKkGG3Qa9-uTpD7UFzzs,16735
|
|
5
|
+
aws_bootstrap/gpu.py,sha256=WTnHR0s3mQHDlnzqRgqAC6omWz7nT5YtGpcs0Bf88jk,692
|
|
6
|
+
aws_bootstrap/output.py,sha256=3NKIcRiYbS66ZWllpj7tkB_UlnFMHqtgE9ixY8Vhmrc,3753
|
|
7
|
+
aws_bootstrap/ssh.py,sha256=0R1o3aUXxdYWqJ-uvYZZY8rnZO7mfc30PwjCJs_0Qow,23971
|
|
8
|
+
aws_bootstrap/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
aws_bootstrap/resources/gpu_benchmark.py,sha256=1eFt_3MXvoLhs9HahrRPhbxvtdjFaXG2Ty3GEg7Gud0,29366
|
|
10
|
+
aws_bootstrap/resources/gpu_smoke_test.ipynb,sha256=XvAOEIPa5H9ri5mRZqOdknmwOwKNvCME6DzBGuhRYfg,10698
|
|
11
|
+
aws_bootstrap/resources/launch.json,sha256=ZOcvHLy3-zBOqRTtFzuyn-_2tB64yuEn8PrJOoZ-PgE,1484
|
|
12
|
+
aws_bootstrap/resources/remote_setup.sh,sha256=i9qXzAqYrnDWt6nFrqeghYWVHmbbzP-OS7O_YJB3GYU,8400
|
|
13
|
+
aws_bootstrap/resources/requirements.txt,sha256=gpYl1MFCfWXiAhbIUgAjuTHONz3MKci25msIyOkMmUk,75
|
|
14
|
+
aws_bootstrap/resources/saxpy.cu,sha256=1BSESEwGGCx3KWx9ZJ8jiPHQ42KzQN6i2aP0I28bPsA,1178
|
|
15
|
+
aws_bootstrap/resources/tasks.json,sha256=6U8pB1N8YIWgUCfFet4ne3nYnI92tWv5D5kPiQG3Zlg,1576
|
|
16
|
+
aws_bootstrap/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
aws_bootstrap/tests/test_cli.py,sha256=QHn7OY7QAlbV4Flm4bwB496la3Z5BhX-msBWikeUAUE,59382
|
|
18
|
+
aws_bootstrap/tests/test_config.py,sha256=vspSGoben_i7m4Fh6UGSes6Fkr789Y1eaOLe54fRSGc,1524
|
|
19
|
+
aws_bootstrap/tests/test_ebs.py,sha256=B2HrgSmS7yroz6zzRuPxKIXmQGlWesuGqOtybyZmHJQ,7582
|
|
20
|
+
aws_bootstrap/tests/test_ec2.py,sha256=Jmqsjv973hxXbZWfGgECtm6aa2156Lzji227sYMBuMg,10547
|
|
21
|
+
aws_bootstrap/tests/test_gpu.py,sha256=rbMuda_sIVbaCzkWXoLv9YIfnWztgRoP7NuVL8XHrUY,3871
|
|
22
|
+
aws_bootstrap/tests/test_output.py,sha256=RRSbxtGqi7jfC9i4CR4EZXP56SmdsYUZDpT5uj8DWKQ,5250
|
|
23
|
+
aws_bootstrap/tests/test_ssh_config.py,sha256=qy3UDdvkTfrALiF-W3m8aKvnQj3BeCrZdLjG75tcVJU,17131
|
|
24
|
+
aws_bootstrap/tests/test_ssh_ebs.py,sha256=ipt0xOzdf3kfkVt42Dgr_z7D6JDIMuRi3DqX0OP8sm0,2342
|
|
25
|
+
aws_bootstrap/tests/test_ssh_gpu.py,sha256=dRp86Og-8GqiATSff3rxhu83mBZdGgqI4UOnoC00Ln0,1454
|
|
26
|
+
aws_bootstrap_g4dn-0.7.0.dist-info/licenses/LICENSE,sha256=Hen77Mt8sazSQJ9DgrmZuAvDwo2vc5JAkR_avuFV-CM,1067
|
|
27
|
+
aws_bootstrap_g4dn-0.7.0.dist-info/METADATA,sha256=qTRVXvMZwgcepn6IAhhFzoCk3YCIhkTUzzDCAfDtYJ4,16700
|
|
28
|
+
aws_bootstrap_g4dn-0.7.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
29
|
+
aws_bootstrap_g4dn-0.7.0.dist-info/entry_points.txt,sha256=T8FXfOgmLEvFi8DHaFJ3tCzId9J3_d2Y6qT98OXxCjA,57
|
|
30
|
+
aws_bootstrap_g4dn-0.7.0.dist-info/top_level.txt,sha256=mix9gZRs8JUv0OMSB_rwdGcRnTKzsKgHrE5fyAn5zJw,14
|
|
31
|
+
aws_bootstrap_g4dn-0.7.0.dist-info/RECORD,,
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
aws_bootstrap/__init__.py,sha256=kl_jvrunGyIyizdRqAP6ROb5P1BBrXX5PTq5gq1ipU0,82
|
|
2
|
-
aws_bootstrap/cli.py,sha256=N2hT0XEC-4k5Cs3iGfA_xt_onc__NMNmh8fCaV4frgc,21076
|
|
3
|
-
aws_bootstrap/config.py,sha256=TeCOYDlijT-KD5SFIzc-VvBhOqcq9YCgen9NK63rka8,895
|
|
4
|
-
aws_bootstrap/ec2.py,sha256=LHpzW91ayK45gsWV_B4LanSZIhWggqTsL31qHUceiaA,12274
|
|
5
|
-
aws_bootstrap/gpu.py,sha256=WTnHR0s3mQHDlnzqRgqAC6omWz7nT5YtGpcs0Bf88jk,692
|
|
6
|
-
aws_bootstrap/ssh.py,sha256=0acHNX7IG6PUvp6T72l9kHTwUs5sVXFAyJXvUfA3qnE,20131
|
|
7
|
-
aws_bootstrap/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
aws_bootstrap/resources/gpu_benchmark.py,sha256=1eFt_3MXvoLhs9HahrRPhbxvtdjFaXG2Ty3GEg7Gud0,29366
|
|
9
|
-
aws_bootstrap/resources/gpu_smoke_test.ipynb,sha256=XvAOEIPa5H9ri5mRZqOdknmwOwKNvCME6DzBGuhRYfg,10698
|
|
10
|
-
aws_bootstrap/resources/launch.json,sha256=ZOcvHLy3-zBOqRTtFzuyn-_2tB64yuEn8PrJOoZ-PgE,1484
|
|
11
|
-
aws_bootstrap/resources/remote_setup.sh,sha256=z_YGdzwEHWInkE3dZVbBNa0F_joTeVhnOpCYOj1CK30,8331
|
|
12
|
-
aws_bootstrap/resources/requirements.txt,sha256=gpYl1MFCfWXiAhbIUgAjuTHONz3MKci25msIyOkMmUk,75
|
|
13
|
-
aws_bootstrap/resources/saxpy.cu,sha256=1BSESEwGGCx3KWx9ZJ8jiPHQ42KzQN6i2aP0I28bPsA,1178
|
|
14
|
-
aws_bootstrap/resources/tasks.json,sha256=6U8pB1N8YIWgUCfFet4ne3nYnI92tWv5D5kPiQG3Zlg,1576
|
|
15
|
-
aws_bootstrap/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
aws_bootstrap/tests/test_cli.py,sha256=m_4tIX0xYZ8BxDkHPGAWiPAKo4vETaTSKSJbyn3K1Cg,34731
|
|
17
|
-
aws_bootstrap/tests/test_config.py,sha256=arvET6KNl4Vqsz0zFrSdhciXGU688bfsvCr3dSpziN0,1050
|
|
18
|
-
aws_bootstrap/tests/test_ec2.py,sha256=Jmqsjv973hxXbZWfGgECtm6aa2156Lzji227sYMBuMg,10547
|
|
19
|
-
aws_bootstrap/tests/test_gpu.py,sha256=rbMuda_sIVbaCzkWXoLv9YIfnWztgRoP7NuVL8XHrUY,3871
|
|
20
|
-
aws_bootstrap/tests/test_ssh_config.py,sha256=YYtv82zBBLGioTo58iC31_5jUli1s0eoGV9VRCobOgY,14059
|
|
21
|
-
aws_bootstrap/tests/test_ssh_gpu.py,sha256=dRp86Og-8GqiATSff3rxhu83mBZdGgqI4UOnoC00Ln0,1454
|
|
22
|
-
aws_bootstrap_g4dn-0.5.0.dist-info/licenses/LICENSE,sha256=Hen77Mt8sazSQJ9DgrmZuAvDwo2vc5JAkR_avuFV-CM,1067
|
|
23
|
-
aws_bootstrap_g4dn-0.5.0.dist-info/METADATA,sha256=t8m53ZodJlZyMffeSu3Wk5bMt-Dm_Jl3q_HTbRLQbYE,13728
|
|
24
|
-
aws_bootstrap_g4dn-0.5.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
25
|
-
aws_bootstrap_g4dn-0.5.0.dist-info/entry_points.txt,sha256=T8FXfOgmLEvFi8DHaFJ3tCzId9J3_d2Y6qT98OXxCjA,57
|
|
26
|
-
aws_bootstrap_g4dn-0.5.0.dist-info/top_level.txt,sha256=mix9gZRs8JUv0OMSB_rwdGcRnTKzsKgHrE5fyAn5zJw,14
|
|
27
|
-
aws_bootstrap_g4dn-0.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|