tuneplane-node 0.3.18__tar.gz → 0.3.19__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 (19) hide show
  1. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/PKG-INFO +1 -1
  2. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/pyproject.toml +1 -1
  3. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/allocator.py +1 -1
  4. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/join.py +15 -2
  5. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/runtime.py +2 -2
  6. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/.gitignore +0 -0
  7. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/LICENSE +0 -0
  8. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/NOTICE +0 -0
  9. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/__init__.py +0 -0
  10. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/cli.py +0 -0
  11. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/daemon.py +0 -0
  12. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/host_resources.py +0 -0
  13. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/inventory.py +0 -0
  14. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/settings.py +0 -0
  15. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/wire.py +0 -0
  16. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/tests/test_allocator.py +0 -0
  17. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/tests/test_host_resources.py +0 -0
  18. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/tests/test_host_resources_docker.py +0 -0
  19. {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/tests/test_runtime.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: tuneplane-node
3
- Version: 0.3.18
3
+ Version: 0.3.19
4
4
  Summary: TunePlane node daemon: runs job containers on one machine and reports it to a console.
5
5
  License-Expression: AGPL-3.0-only
6
6
  License-File: LICENSE
@@ -10,7 +10,7 @@
10
10
  # the local backend runs the same container runtime and allocator on its own host.
11
11
  [project]
12
12
  name = "tuneplane-node"
13
- version = "0.3.18"
13
+ version = "0.3.19"
14
14
  description = "TunePlane node daemon: runs job containers on one machine and reports it to a console."
15
15
  requires-python = ">=3.12"
16
16
  # Same licence as the control plane: this is infrastructure an organization runs,
@@ -2,7 +2,7 @@
2
2
 
3
3
  Who decides "which cards this job gets" when there is no Kubernetes
4
4
  ──────────────────────────────────────────────────────────────────────────────
5
- On the kuberay backend kube-scheduler and the NVIDIA device plugin do it: the Pod
5
+ On the kubernetes backend kube-scheduler and the NVIDIA device plugin do it: the Pod
6
6
  declares `nvidia.com/gpu: 4`, the scheduler guarantees no over-subscription, and the
7
7
  device plugin injects the actual cards into the container.
8
8
 
@@ -123,7 +123,10 @@ async def join(
123
123
  "inventory": inventory,
124
124
  }
125
125
  async with httpx.AsyncClient(timeout=timeout, transport=transport) as client:
126
- response = await client.post(f"{base}/api/fleets/{fleet_id}/nodes", json=payload)
126
+ response = await client.post(
127
+ f"{base}/api/fleets/{fleet_id}/nodes", json=payload,
128
+ headers={"User-Agent": _user_agent(node_version)},
129
+ )
127
130
  if response.status_code != 201:
128
131
  raise JoinError(_detail(response))
129
132
  body = response.json()
@@ -155,7 +158,11 @@ async def beat(
155
158
  }
156
159
  async with httpx.AsyncClient(timeout=timeout, transport=transport) as client:
157
160
  response = await client.post(
158
- url, json=payload, headers={"Authorization": f"Bearer {identity.credential}"}
161
+ url, json=payload,
162
+ headers={
163
+ "Authorization": f"Bearer {identity.credential}",
164
+ "User-Agent": _user_agent(node_version),
165
+ },
159
166
  )
160
167
  if response.status_code != 200:
161
168
  raise JoinError(_detail(response))
@@ -190,6 +197,12 @@ async def heartbeat_forever(
190
197
  await asyncio.sleep(interval_s)
191
198
 
192
199
 
200
+ def _user_agent(node_version: str) -> str:
201
+ """How the daemon names itself, so a join reads as one in the console's audit trail
202
+ rather than as `python-httpx`."""
203
+ return f"tuneplane-node/{node_version}"
204
+
205
+
193
206
  def _detail(response: httpx.Response) -> str:
194
207
  try:
195
208
  body = response.json()
@@ -312,14 +312,14 @@ class CliRuntime:
312
312
  # `vllm` command -- died at once with
313
313
  # vllm: error: unrecognized arguments: -lc python3 -m vllm...
314
314
  # which is this `bash -lc` arriving where a subcommand was expected. The
315
- # same launch works on kuberay, because a Kubernetes container's
315
+ # same launch works on kubernetes, because a Kubernetes container's
316
316
  # `command` overrides the entrypoint by definition -- so the two backends
317
317
  # disagreed about the one field that says what to run, and the process
318
318
  # runtime (which execs the argv directly) agreed with Kubernetes.
319
319
  #
320
320
  # What this gives up is an image's own entrypoint wrapper, such as
321
321
  # nvidia_entrypoint.sh on the NGC bases. That wrapper prints a banner and
322
- # `exec "$@"`, and the kuberay path has been skipping it since it was
322
+ # `exec "$@"`, and the kubernetes path has been skipping it since it was
323
323
  # written, which is the evidence that nothing depends on it.
324
324
  if spec.command:
325
325
  args += ["--entrypoint", spec.command[0]]
File without changes
File without changes