{% extends "ui/_layout.html" %} {% block title %}Machines - bty-web{% endblock %} {% block content %}

Machines

{% if active_filter %} filter: {{ active_filter }} show all {% else %} {{ machines|length }} total ยท live {% endif %}
Add machine
{# The form posts to /ui/machines/; the existing upsert handler creates the row with ``discovered_at=NULL`` if the MAC isn't known yet. Once the box PXE-boots, ``discovered_at`` flips to the first-seen timestamp and the boot_policy already configured here takes effect on that first ``GET /pxe/``. Lets operators stage a machine + its image binding before the box is even racked. #}
{# Pattern mirrors the server-side Pydantic regex on ``MachineUpsert.hostname``: each dot-separated label is alnum, hyphen-internal-only, no leading/trailing hyphen, no consecutive dots. Browser-side validation gives the operator an inline error before the form posts; without this match, the server returns 422 and the operator hits the form-flash redirect. #}
MAC is the only required field. Image binding is set per-machine on the detail page (click the row); flash policy and per-machine boot mode default to "local" / "none" so a freshly added machine doesn't re-flash itself unexpectedly on first boot.
{# The tbody subscribes to the SSE stream so it auto-updates when the operator (or auto-discovery) mutates machines. The browser carries the bty-token cookie automatically; that is what authenticates the EventSource connection. ``sse-target`` opts in to the layout-level flash animation. When a server-side filter is active (``?filter=...``) the SSE wiring is dropped: the next ``machines-update`` would replace the filtered tbody with the full un-filtered list, which is operator-confusing. The page becomes static under filter; reload to refresh. #} {% include "ui/_machines_tbody.html" %}
MAC Image Provisioning Boot Hostname Last seen Last flashed
{% endblock %}