Repository navigation
Tags
Tags
feat(auth): let a signed scheduler request name the node it is for (#… …1307) The Aleph-EIP191-V1 payload gains an optional node_hash. A node that receives one checks it against its own hash and refuses any other; a payload without it is accepted as before, so schedulers can start sending it at their own pace. The signing script takes --node-hash for callers that want the same.
feat(agent): advertise each GPU once with the modes the host can hand… … it over in (#1290) The usage endpoint split cards by NVIDIA CC mode: plain lists for pass-through placement, confidential lists as their complement, and tee.nvidia_cc as the scheduler's confidential view. The daemon now moves a card's mode at create, so the mode is transient state, not a property to place against, and the split carried two views of one inventory. gpu.devices and gpu.available_devices list every card once, each with `modes`, the ways this host can hand the card over: `plain` for a pass-through guest, `cc` for NVIDIA CC mode inside an SEV-SNP guest. Any decoded mode of a known family carries both; a CC card whose family the daemon cannot place carries none; an unprobed card is plain only. `cc` is granted only on a host that can launch SNP guests, the gate tee.nvidia_cc already sat behind. The confidential lists go (never released); tee.nvidia_cc stays one release as a legacy view of the same `cc` mode; cc_mode stays per card as the probed hardware state. The status page shows each card once with its modes. A scheduler that ignores `modes` keeps placing by available_devices and can pick a card with none; the daemon refuses that create. A CRN older than this field sends no `modes`, which the scheduler reads as ["plain"], exactly what those CRNs listed.
fix(agent): review round on the CC-mode card filter The refusal's available figure and the headroom docstring follow the plain filter; reserve_gpus says it names plain cards only, the confidential tests seed their holds directly; devtools is documented as served by neither path; the plain lists validate each card once.
chore(nix): re-seed golden measurements after the rebase onto main dev-2.2 rebased onto main at 0295bb0: main's attest-agent proxy work and the 2.2 guest changes (aleph-tee without openssl, the GPU stack) both move the initrd, so every flavor gets a new value. Built on the H200 node.
fix(agent): parse V-PROGRAM contents when rebuilding the registry (#1261 ) get_message_executable_content tried ProgramContent then InstanceContent only, so every V-PROGRAM execution record was "unparseable" at rehydrate and a restarted agent ran V-PROGRAMs with no registry record. Seen on a 2.0.1 node at its 2026-09-11 restart and again after the 2.1.0 upgrade, where the consequences grew: the storage reconciler skips its cache pass every hour ("live VM(s) have no registry record"), aleph-vm storage status prints a traceback, and the VMs sit outside owner-auth, payment and allocation logic until they are recreated. Try VerifiableProgramContent between the two. Every content model forbids extra fields, so exactly one of the three accepts a given dict. The new test parses each example message through the function and checks that what persist_record stores (model_dump_json) parses back unchanged.
fix(agent): refuse at admission what the node's settings rule out (#1255 ) Nothing in the allocation plane read ENABLE_CONFIDENTIAL_COMPUTING or ENABLE_GPU_SUPPORT. A node with confidential computing switched off sized a confidential VM or a V-PROGRAM on memory and disk, answered the scheduler accepted, and had the create refused by the daemon at start; the plan still listed the VM, so the loop rebuilt it at the capped backoff for as long as the scheduler kept it there. A GPU request on a node with GPU support off did the same, or was answered gpu_unavailable, which sends a scheduler waiting for a card that will never be handed out. ResourceRequirements now carries what the node must have switched on, read from the message: a V-PROGRAM and an instance with trusted_execution need confidential computing, a GPU requirement or a V-PROGRAM gpu block needs GPU support. simulate refuses such a candidate as unsupported before any sizing, which covers the plan verdict and the capacity check, and check_message raises UnsupportedWorkloadError on the create paths. The error subclasses InsufficientResourcesError so every create route already answers it; the allocation classifier publishes it as unsupported and the HTTP mapper answers 400 rather than 503, since no later attempt does better on this node.
fix(packaging): allow dnsmasq to create SNP DHCP lease files (#1193) The SNP supervisor starts one dnsmasq process per tap and stores its lease database at `/var/lib/aleph/vm/dhcp/<vm-id>.leases`. On Ubuntu with the distro dnsmasq AppArmor profile enforced, creation of that file is denied, dnsmasq exits, and the SNP execution is restarted.
build: pin released aleph-message 1.3.1 instead of the git ref (#1183) The MERGE GATE git pin (4ad261ff, pre-squash V-PROGRAM schema branch) is now covered by the 1.3.1 release on PyPI. The only delta on top of the pinned tree is PR #160 (serde-strict V-PROGRAM scalars), which does not affect messages aleph-vm itself produces or parses.
perf(allocations): batch systemd state lookup in update_allocations (#… …1084) * perf(allocations): batch systemd state lookup in update_allocations POST /control/allocations reconciles the scheduler's push against the local pool: walks all persistent executions to find stop candidates, then calls start_persistent_vm for every hash in the pushed list. Every execution.is_running call is a synchronous D-Bus round-trip to systemd. On a CRN with 80+ persistent VMs and a full-list push, that's ~2N blocking round-trips on the event loop behind allocation_lock. Once the total crosses aleph-admin's HTTP client timeout, the request times out; restarting the supervisor "fixes" it by cancelling the in-flight allocation and resetting the lock, but the underlying scaling problem comes back with the next attempt. Same fix shape as #963 for monitor_payments: - update_allocations snapshots the state once via asyncio.to_thread -> SystemDManager.get_services_active_states (one ListUnits() call). - Pass the dict to pool.get_persistent_executions and start_persistent_vm via a new running_states parameter. Both prefer the map lookup over execution.is_running when it's provided; fall back to the per-VM path when it isn't (existing callers unchanged). - Drop the redundant execution.is_running check inside the stop loop: get_persistent_executions already filtered by running via the map. Saves one per-VM D-Bus round-trip inside a loop we just entered. Per-request D-Bus work drops from ~2N synchronous round-trips on the event loop to one ListUnits call off-thread. On a CRN with 80 VMs the allocation call goes from "sometimes times out" to a few hundred ms. Tests pin: start_persistent_vm's fast-path uses the map and bypasses is_service_active; a missing entry falls through to the systemd-state guard (composes correctly with #1081's transient-state check); and pool.get_persistent_executions with a map never calls is_running. * test: annotate empty running_states dict for mypy * test: teach the allocation fake pools the batched-lookup interface update_allocations now reads pool.executions and pool.systemd_manager before get_persistent_executions, crashing the FakeVmPool/_FakeVmPool stubs with AttributeError (three test_views.py allocation tests 500'd). Also init running_states as None instead of {} when no batch was performed, so get_persistent_executions falls back to per-VM is_running instead of treating every service as not-running. --------- Co-authored-by: Olivier Desenfans <desenfans.olivier@gmail.com>
PreviousNext