gpu-dev 0.6.3__tar.gz → 0.6.5__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.
Files changed (152) hide show
  1. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/PKG-INFO +1 -1
  2. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev.egg-info/PKG-INFO +1 -1
  3. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev_cli/disks.py +28 -11
  4. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/pyproject.toml +1 -1
  5. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/pyproject.toml +1 -1
  6. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/__init__.py +1 -1
  7. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/_backend/aws.py +11 -7
  8. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/_sync/sandbox.py +56 -5
  9. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda.tf +2 -2
  10. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/.github/workflows/no-gitlinks.yml +0 -0
  11. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/.github/workflows/publish.yml +0 -0
  12. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/.gitignore +0 -0
  13. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/CLAUDE.md +0 -0
  14. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/README.md +0 -0
  15. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/admin/README.md +0 -0
  16. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/admin/generate_stats.py +0 -0
  17. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/admin/requirements.txt +0 -0
  18. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/README.md +0 -0
  19. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/ZERO_CONFIG_SETUP.md +0 -0
  20. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev.egg-info/SOURCES.txt +0 -0
  21. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev.egg-info/dependency_links.txt +0 -0
  22. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev.egg-info/entry_points.txt +0 -0
  23. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev.egg-info/requires.txt +0 -0
  24. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev.egg-info/top_level.txt +0 -0
  25. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev_cli/__init__.py +0 -0
  26. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev_cli/auth.py +0 -0
  27. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev_cli/cli.py +0 -0
  28. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev_cli/config.py +0 -0
  29. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev_cli/interactive.py +0 -0
  30. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev_cli/name_generator.py +0 -0
  31. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev_cli/reservations.py +0 -0
  32. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/gpu_dev_cli/ssh_proxy.py +0 -0
  33. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/gpu-dev-cli/minimal-iam-policy.json +0 -0
  34. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/cli-tools/scripts/clear_stale_disk_locks.py +0 -0
  35. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/docs/USER_GUIDE.md +0 -0
  36. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/docs/devgpu-features.html +0 -0
  37. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/docs/docker-mark-blue.svg +0 -0
  38. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/docs/icons8-cursor-ai.svg +0 -0
  39. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/README.md +0 -0
  40. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/examples/batch_multi_gpu.py +0 -0
  41. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/examples/interactive_debug.py +0 -0
  42. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/examples/quickstart.ipynb +0 -0
  43. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/examples/run_tests.py +0 -0
  44. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/examples/submit_job.py +0 -0
  45. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/_async/__init__.py +0 -0
  46. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/_backend/__init__.py +0 -0
  47. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/_backend/protocol.py +0 -0
  48. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/_sync/__init__.py +0 -0
  49. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/_sync/client.py +0 -0
  50. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/_transport/__init__.py +0 -0
  51. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/_transport/ssh.py +0 -0
  52. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/common/__init__.py +0 -0
  53. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/common/config.py +0 -0
  54. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/common/enums.py +0 -0
  55. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/common/errors.py +0 -0
  56. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/common/models.py +0 -0
  57. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/src/gpu_dev/py.typed +0 -0
  58. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/tests/__init__.py +0 -0
  59. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/sdk/python/tests/test_models.py +0 -0
  60. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/setup.cfg +0 -0
  61. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/.claude/skills/deploy.md +0 -0
  62. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/.terraform.lock.hcl +0 -0
  63. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/README.md +0 -0
  64. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/alb.tf +0 -0
  65. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/ami-baker.tf +0 -0
  66. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/availability.tf +0 -0
  67. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/backend.tf +0 -0
  68. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/check_b200.py +0 -0
  69. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/cluster-autoscaler.tf +0 -0
  70. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/cmd_proxy.py +0 -0
  71. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/.dockerignore +0 -0
  72. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/Dockerfile +0 -0
  73. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/backup-dotfiles +0 -0
  74. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/bash_profile +0 -0
  75. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/bashrc +0 -0
  76. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/bashrc_ext +0 -0
  77. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/build-with-efa.sh +0 -0
  78. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/dotfiles-shutdown-handler +0 -0
  79. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/list-dotfile-versions +0 -0
  80. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/motd_script +0 -0
  81. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/nproc_wrapper +0 -0
  82. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/profile +0 -0
  83. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/restore-dotfiles +0 -0
  84. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/restore-dotfiles-version +0 -0
  85. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/setup-dotfiles-persistence +0 -0
  86. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/shell_env +0 -0
  87. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/ssh_config +0 -0
  88. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/zprofile +0 -0
  89. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/zshrc +0 -0
  90. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker/zshrc_ext +0 -0
  91. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker-build.tf +0 -0
  92. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker-example/Dockerfile +0 -0
  93. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/docker-example/hello.txt +0 -0
  94. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/ecr.tf +0 -0
  95. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/efs.tf +0 -0
  96. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/eks.tf +0 -0
  97. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/expiry.tf +0 -0
  98. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/git-cache.tf +0 -0
  99. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/gpu-dev-pod-irsa.tf +0 -0
  100. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/kubernetes.tf +0 -0
  101. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/availability_updater/index.py +0 -0
  102. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/availability_updater/requirements.txt +0 -0
  103. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/migration/tag_largest_snapshots.py +0 -0
  104. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/reservation_expiry/index.py +0 -0
  105. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/reservation_expiry/requirements.txt +0 -0
  106. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/reservation_processor/buildkit_job.py +0 -0
  107. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/reservation_processor/index.py +0 -0
  108. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/reservation_processor/requirements.txt +0 -0
  109. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/shared/__init__.py +0 -0
  110. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/shared/alb_utils.py +0 -0
  111. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/shared/dns_utils.py +0 -0
  112. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/shared/k8s_client.py +0 -0
  113. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/shared/k8s_resource_tracker.py +0 -0
  114. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/shared/requirements.txt +0 -0
  115. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/lambda/shared/snapshot_utils.py +0 -0
  116. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/list_b200.py +0 -0
  117. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/main.tf +0 -0
  118. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/mig-config.tf +0 -0
  119. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/mig-parted-config.yaml +0 -0
  120. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/migrations/backfill_snapshot_contents.py +0 -0
  121. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/migrations/backfill_snapshot_contents.py.bak +0 -0
  122. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/migrations/check_snapshots.py +0 -0
  123. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/migrations/migrate_disks_to_named.py +0 -0
  124. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/migrations/run_backfill.sh +0 -0
  125. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/monitoring.tf +0 -0
  126. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/node-termination-handler.tf +0 -0
  127. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/outputs.tf +0 -0
  128. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/pyproject.toml +0 -0
  129. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/queue.tf +0 -0
  130. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/route53.tf +0 -0
  131. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/s3-disk-contents.tf +0 -0
  132. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/scripts/CLEANUP_GUIDE.md +0 -0
  133. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/scripts/detect_empty_volumes.sh +0 -0
  134. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/scripts/ec2_avail_probe.sh +0 -0
  135. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/scripts/inspect_user_data.sh +0 -0
  136. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/ssh-proxy/Dockerfile +0 -0
  137. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/ssh-proxy/proxy.py +0 -0
  138. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/ssh-proxy/requirements.txt +0 -0
  139. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/ssh-proxy-service.tf +0 -0
  140. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/ssh-proxy.tf +0 -0
  141. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/subnet-0fe3a2c45570091ad +0 -0
  142. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/switch-to.sh +0 -0
  143. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/templates/al2023-cpu-user-data.sh +0 -0
  144. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/templates/al2023-user-data.sh +0 -0
  145. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/templates/ami-baker-user-data.sh +0 -0
  146. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/templates/user-data-self-managed.sh +0 -0
  147. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/templates/user-data.sh +0 -0
  148. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/terraform-gpu-devservers/variables.tf +0 -0
  149. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/tests/submit/README.md +0 -0
  150. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/tests/submit/fail/run.sh +0 -0
  151. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/tests/submit/multinode/run.sh +0 -0
  152. {gpu_dev-0.6.3 → gpu_dev-0.6.5}/tests/submit/success/run.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gpu-dev
3
- Version: 0.6.3
3
+ Version: 0.6.5
4
4
  Summary: CLI tool for PyTorch GPU developer server reservations
5
5
  Author: PyTorch Team
6
6
  Requires-Python: >=3.10
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gpu-dev
3
- Version: 0.6.3
3
+ Version: 0.6.5
4
4
  Summary: CLI tool for PyTorch GPU developer server reservations
5
5
  Author: PyTorch Team
6
6
  Requires-Python: >=3.10
@@ -154,12 +154,8 @@ def list_disks(user_id: str, config: Config) -> List[Dict]:
154
154
  List all disks for a user.
155
155
  Returns list of disk info dicts with: name, size, last_used, created_at, snapshot_count, in_use, reservation_id
156
156
  """
157
- ec2_client = get_ec2_client(config)
158
- dynamodb = get_dynamodb_resource(config)
159
-
160
- # Query DynamoDB disks table for this user's disks (with pagination)
161
- disks_table_name = config.disks_table if hasattr(config, 'disks_table') else f"{config.queue_name.rsplit('-', 1)[0]}-disks"
162
- disks_table = dynamodb.Table(disks_table_name)
157
+ dynamodb = config.dynamodb
158
+ disks_table = dynamodb.Table(config.disks_table)
163
159
 
164
160
  dynamodb_disks = []
165
161
  response = disks_table.query(
@@ -208,9 +204,6 @@ def list_disks(user_id: str, config: Config) -> List[Dict]:
208
204
  is_deleted = disk_item.get('is_deleted', False)
209
205
  delete_date = disk_item.get('delete_date')
210
206
 
211
- # Check current in_use status (check dynamically from reservations table)
212
- is_in_use, reservation_id = get_disk_in_use_status(disk_name, user_id, config)
213
-
214
207
  disks.append({
215
208
  'name': disk_name,
216
209
  'size_gb': size_gb,
@@ -219,13 +212,37 @@ def list_disks(user_id: str, config: Config) -> List[Dict]:
219
212
  'last_used': last_used,
220
213
  'snapshot_count': snapshot_count,
221
214
  'pending_snapshot_count': pending_snapshot_count,
222
- 'in_use': is_in_use,
215
+ 'in_use': bool(disk_item.get('in_use', False)),
223
216
  'is_backing_up': is_backing_up,
224
- 'reservation_id': reservation_id,
217
+ 'reservation_id': str(disk_item.get('attached_to_reservation', '')) or None,
225
218
  'is_deleted': is_deleted,
226
219
  'delete_date': delete_date,
227
220
  })
228
221
 
222
+ # Batch check: find all active reservations with disk_name set (single query)
223
+ try:
224
+ reservations_table = dynamodb.Table(config.reservations_table)
225
+ active_disks = {}
226
+ for status in ["active", "preparing", "queued", "pending"]:
227
+ resp = reservations_table.query(
228
+ IndexName="UserStatusIndex",
229
+ KeyConditionExpression="user_id = :uid AND #s = :status",
230
+ ExpressionAttributeNames={"#s": "status"},
231
+ ExpressionAttributeValues={":uid": user_id, ":status": status},
232
+ ProjectionExpression="reservation_id, disk_name",
233
+ )
234
+ for item in resp.get("Items", []):
235
+ dn = item.get("disk_name")
236
+ if dn:
237
+ active_disks[dn] = str(item.get("reservation_id", ""))[:8]
238
+
239
+ for disk in disks:
240
+ if disk["name"] in active_disks:
241
+ disk["in_use"] = True
242
+ disk["reservation_id"] = active_disks[disk["name"]]
243
+ except Exception:
244
+ pass
245
+
229
246
  # Sort by last_used (most recent first)
230
247
  disks.sort(key=lambda d: d['last_used'] or datetime.min.replace(tzinfo=timezone.utc), reverse=True)
231
248
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gpu-dev"
7
- version = "0.6.3"
7
+ version = "0.6.5"
8
8
  description = "CLI tool for PyTorch GPU developer server reservations"
9
9
  authors = [{name = "PyTorch Team"}]
10
10
  readme = "cli-tools/gpu-dev-cli/README.md"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gpu-dev-sdk"
7
- version = "0.1.0"
7
+ version = "0.6.5"
8
8
  description = "Python SDK for GPU development server reservations"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -57,4 +57,4 @@ __all__ = [
57
57
  "ExecResult",
58
58
  ]
59
59
 
60
- __version__ = "0.1.0"
60
+ __version__ = "0.6.5"
@@ -166,7 +166,7 @@ class AwsBackend:
166
166
  "no_persistent_disk": params.get("no_persistent_disk", False),
167
167
  "github_user": params.get("github_user", ""),
168
168
  "preserve_entrypoint": params.get("preserve_entrypoint", False),
169
- "version": "0.6.0",
169
+ "version": __import__("gpu_dev").__version__,
170
170
  }
171
171
  if params.get("disk_name"):
172
172
  message["disk_name"] = params["disk_name"]
@@ -189,13 +189,17 @@ class AwsBackend:
189
189
  return self._item_to_info(item)
190
190
  return None
191
191
 
192
- resp = self._reservations.query(
193
- IndexName="UserIndex",
194
- KeyConditionExpression="user_id = :uid",
195
- FilterExpression="begins_with(reservation_id, :rid)",
196
- ExpressionAttributeValues={":uid": user_id, ":rid": reservation_id},
197
- )
192
+ query_kwargs = {
193
+ "IndexName": "UserIndex",
194
+ "KeyConditionExpression": "user_id = :uid",
195
+ "FilterExpression": "begins_with(reservation_id, :rid)",
196
+ "ExpressionAttributeValues": {":uid": user_id, ":rid": reservation_id},
197
+ }
198
+ resp = self._reservations.query(**query_kwargs)
198
199
  items = resp.get("Items", [])
200
+ while not items and "LastEvaluatedKey" in resp:
201
+ resp = self._reservations.query(**query_kwargs, ExclusiveStartKey=resp["LastEvaluatedKey"])
202
+ items = resp.get("Items", [])
199
203
  if len(items) == 1:
200
204
  return self._item_to_info(items[0])
201
205
  return None
@@ -136,11 +136,6 @@ class Sandbox:
136
136
  """Owner's user ID."""
137
137
  return self._info.user_id
138
138
 
139
- @property
140
- def node_ip(self) -> str | None:
141
- """Node public IP."""
142
- return self._info.node_ip
143
-
144
139
  @property
145
140
  def is_active(self) -> bool:
146
141
  """Whether the sandbox is running and ready for commands."""
@@ -322,6 +317,62 @@ class Sandbox:
322
317
  except Exception:
323
318
  return []
324
319
 
320
+ def timing(self) -> list[dict[str, str | float]]:
321
+ """Get a performance breakdown of reservation setup.
322
+
323
+ Computes time deltas between status transitions to show
324
+ where time was spent.
325
+
326
+ Returns:
327
+ List of ``{"step": "...", "duration": seconds, "timestamp": "..."}`` dicts.
328
+
329
+ Example::
330
+
331
+ for step in sandbox.timing():
332
+ print(f"{step['duration']:5.1f}s {step['step']}")
333
+ """
334
+ from datetime import datetime
335
+
336
+ entries = self.logs()
337
+ if not entries:
338
+ return []
339
+
340
+ result = []
341
+ prev_ts = None
342
+ for entry in entries:
343
+ ts_str = entry.get("timestamp", "")
344
+ msg = entry.get("message", "")
345
+ try:
346
+ ts = datetime.fromisoformat(ts_str)
347
+ except (ValueError, TypeError):
348
+ continue
349
+ if prev_ts:
350
+ delta = (ts - prev_ts).total_seconds()
351
+ if delta >= 0.05:
352
+ result.append({
353
+ "step": msg,
354
+ "duration": round(delta, 2),
355
+ "timestamp": ts_str,
356
+ })
357
+ else:
358
+ result.append({
359
+ "step": msg,
360
+ "duration": 0.0,
361
+ "timestamp": ts_str,
362
+ })
363
+ prev_ts = ts
364
+
365
+ if result and len(entries) >= 2:
366
+ first_ts = datetime.fromisoformat(entries[0]["timestamp"])
367
+ last_ts = datetime.fromisoformat(entries[-1]["timestamp"])
368
+ result.append({
369
+ "step": "TOTAL",
370
+ "duration": round((last_ts - first_ts).total_seconds(), 2),
371
+ "timestamp": "",
372
+ })
373
+
374
+ return result
375
+
325
376
  def pod_logs(self, lines: int = 50) -> str:
326
377
  """Fetch container stdout from the running pod via SSH.
327
378
 
@@ -186,8 +186,8 @@ resource "aws_lambda_function" "reservation_processor" {
186
186
  HOSTED_ZONE_ID = local.effective_domain_name != "" ? local.hosted_zone_id : ""
187
187
  SSH_DOMAIN_MAPPINGS_TABLE = local.effective_domain_name != "" ? aws_dynamodb_table.ssh_domain_mappings.name : ""
188
188
  SSL_CERTIFICATE_ARN = local.effective_domain_name != "" ? aws_acm_certificate.wildcard[0].arn : ""
189
- LAMBDA_VERSION = "0.6.0"
190
- MIN_CLI_VERSION = "0.6.0"
189
+ LAMBDA_VERSION = "0.6.5"
190
+ MIN_CLI_VERSION = "0.6.5"
191
191
  # Comma-separated GPU types that require --spot flag, or "all" for every type.
192
192
  # Empty = no spot types (on-demand / reserved). Set per-workspace.
193
193
  ASG_NAME_PREFIX = "${var.prefix}-gpu-nodes"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes