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.
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/PKG-INFO +1 -1
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/pyproject.toml +1 -1
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/allocator.py +1 -1
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/join.py +15 -2
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/runtime.py +2 -2
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/.gitignore +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/LICENSE +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/NOTICE +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/__init__.py +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/cli.py +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/daemon.py +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/host_resources.py +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/inventory.py +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/settings.py +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/src/tuneplane_node/wire.py +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/tests/test_allocator.py +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/tests/test_host_resources.py +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/tests/test_host_resources_docker.py +0 -0
- {tuneplane_node-0.3.18 → tuneplane_node-0.3.19}/tests/test_runtime.py +0 -0
|
@@ -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.
|
|
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
|
|
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(
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|