{% extends "layout.html" %} {% from "_partials/page_description.html" import page_description %} {% block title %}{{ machine.mac }} - pixie{% endblock %} {% block subnav %} {% endblock %} {% block content %} {{ page_description('pc-display-horizontal', 'Everything pixie knows about one target: telemetry, current binding, inventory the live env posts back, and events scoped to this MAC. Editing the binding changes what pixie serves on this target\'s next PXE; labels and inventory are stored independently of the binding.') }}

{{ machine.mac }}

{% if machine.boot_mode == 'nbdboot' %} nbdboot {% else %} {{ machine.boot_mode }} {% endif %}
Image content sha
{% if machine.image_content_sha256 %} {{ machine.image_content_sha256 }} {% else %} (unbound) {% endif %}
Labels
{# Labels are metadata (search / filter / grouping) and have no effect on the plan render. Edit them here on their own form; the bind form below does NOT touch labels, so a boot-mode flip cannot clobber tags an operator set up ahead of time. #}
Comma-separated. Alnum-leading; a-z / 0-9 / space / . _ -; max 64 chars per tag, 16 tags per machine. Blank clears.
Discovered at
{{ machine.discovered_at | fmt_ts }}
Last seen
{{ machine.last_seen_at | fmt_ts }}
Last seen IP
{% if machine.last_seen_ip %}{{ machine.last_seen_ip }} {% else %}-{% endif %}

Edit binding

Unsaved changes
{# ---- Boot-mode radio-card picker ------------------------ Six cards in a 3-across grid. The underlying ```` is visually hidden but keeps the form serialisation + keyboard accessibility that a plain click-a-card widget would drop. The label wraps both the radio and the visual card so anywhere on the card selects the mode. #}
{% for mode_value, meta in boot_mode_meta %}
{% endfor %}
{# ---- Image picker --------------------------------- #}
{% set entry_shas = bindable_entries | map(attribute='content_sha256') | list %} {% if not bindable_entries %} {% endif %}
{# ---- Target disk picker --------------------------- #}
{% set disks = (machine.inventory or {}).get("disks") or [] %} {% if disks %}
The live env matches this SERIAL against the current disks at flash time; a swapped or renumbered drive refuses the flash rather than risking the wrong disk.
{% else %}
No inventory on file yet. Pick Discover inventory above, power-cycle this target, and its disks will populate here.
{% endif %}
{# ---- Per-machine extra kernel cmdline ------------------- Overrides the deploy-wide PIXIE_LIVE_ENV_EXTRA_CMDLINE for THIS machine. Blank falls back to the global; a non-blank value fully replaces (does not concatenate) so an operator can pin a hardware quirk to one target without every other machine seeing the same tokens. Consumed by the nbdboot + pixie-live-env templates. #}
Tokens appended verbatim to the kernel cmdline for this machine only. A non-blank value fully overrides the deploy-wide PIXIE_LIVE_ENV_EXTRA_CMDLINE. Blank falls back to the global (currently effective: {% if global_live_env_extra_cmdline %} {{ global_live_env_extra_cmdline }} {% else %}none{% endif %}). Whitespace-separated; single line. Known-good values per hardware in docs/hardware-quirks.md.
{# ---- Overlay profile (nbdboot only) -------------------- A profile name maps to a per-machine qcow2 kept on pixie's data volume; picking one flips this machine from ephemeral (writes vanish on reboot) to persistent (writes survive on the qcow2). Blank means ephemeral. ``__new`` reveals a text input for a fresh profile name; the bind handler on the server merges the two form fields back into a single ``overlay_profile`` value. #}
{% if machine.overlay_profile and machine.image_content_sha256 %} {% endif %}
Blank = ephemeral tmpfs (writes vanish on reboot; original nbdboot behaviour). Named = qcow2 kept at data/overlays/<mac>/<image_sha>/<profile>.qcow2 on pixie's data volume with backing_file=<base blob>. Multiple profiles per (machine, image) can coexist; different machines are independent. See boot-modes docs.
{# ---- Preview panel -------------------------------------- Plain-English description of what will happen on the next PXE from this target. Updated by JS on any input change. Sits ABOVE the flash-guard hint so an operator scanning the form always knows what "Save" will do before they're asked whether they can Save. #}
On the next PXE from this target
{{ initial_bind_preview }}
{# ---- Flash-mode guard hint ------------------------------ Client-side echo of the server-side 422 guard: the JS disables Save + surfaces this hint when the picked boot_mode is pixie-flash-{once,always} AND either no inventory is on file OR no target_disk_serial is picked. The server rejects the same combination regardless. #}
No changes to save.

Inventory

{% if machine.inventory %} Recorded at {{ machine.inventory_at | fmt_ts }} {% endif %}

Posted by the live env's pixie CLI on boot via POST /pxe/{{ machine.mac }}/inventory. The blob is stored verbatim; fields below are a best-effort render of the shape emitted by lsblk + lshw.

{% if machine.inventory %} {# Best-effort render of the machine hardware summary. The raw payload posted by the live env's ``pixie`` CLI is ``{"lshw": , "disks": []}``; the ``inv`` context var (built by ``pixie.web._inventory.normalise_inventory`` at render time) walks the lshw tree into the system/cpu/memory/nics shape rendered below. Each block is guarded so a partial payload still renders the sections that DID come through. Raw lshw JSON sits collapsed at the bottom as the always-available fallback for anything the summary render doesn't cover. #} {% set system = inv.system %} {% if system %}

System

{% if system.get("vendor") %}
Vendor
{{ system.get("vendor") }}
{% endif %} {% if system.get("model") %}
Model
{{ system.get("model") }}
{% endif %} {% if system.get("serial") %}
Serial
{{ system.get("serial") }}
{% endif %} {% if system.get("firmware") %}
Firmware
{{ system.get("firmware") }} {% if system.get("firmware_vendor") %}({{ system.get("firmware_vendor") }}){% endif %}
{% endif %}
{% endif %} {% set cpu = inv.cpu %} {% if cpu.sockets %}

CPU

{% for socket in cpu.sockets %}
{{ socket.model or "Unknown CPU" }}{% if socket.mhz_current %} @ {{ socket.mhz_current | humanize_hz }}{% endif %} {% if socket.arch %}{{ socket.arch }}{% endif %} {% if cpu.sockets|length > 1 %}Socket {{ socket.slot or loop.index0 }}{% endif %}
{{ socket.cores or "-" }}
physical cores
{{ socket.threads or "-" }}
logical threads
{% if socket.mhz_max %}
{{ socket.mhz_max | humanize_hz }}
max clock
{% endif %} {% if socket.vendor %}
{{ socket.vendor }}
vendor
{% endif %}
{% endfor %} {% if cpu.sockets|length > 1 and cpu.total_cores %}

{{ cpu.sockets|length }} sockets, {{ cpu.total_cores }} cores / {{ cpu.total_threads }} threads total.

{% endif %} {% endif %} {% set memory = inv.memory %} {% if memory.total_bytes %}

Memory

{{ memory.total_bytes | humanize_bytes }} total installed
{% if memory.dimms %}
{% for d in memory.dimms %} {% if d.empty %} {% else %} {% endif %} {% endfor %}

{{ memory.slots_populated }} / {{ memory.slots_total }} slots populated {% if memory.dominant_type %}· {{ memory.dominant_type }}{% endif %} {% if memory.dominant_speed_hz %} @ {{ (memory.dominant_speed_hz / 1000000) | round | int }} MHz{% endif %}

{% else %}

Per-DIMM slot detail not reported by this machine's firmware; only the total is available.

{% endif %}
{% endif %} {% set nics = inv.nics %} {% if nics %}

Network ({{ nics|length }})

{% for n in nics %} {% endfor %}
Interface MAC Vendor / Driver Link
{{ n.get("name") or "-" }} {{ n.get("mac") or "-" }} {{ n.get("vendor") or "-" }} {% if n.get("driver") %}
{{ n.get("driver") }}{% endif %}
{% if n.get("speed") %}{{ n.get("speed") }}{% else %}-{% endif %}
{% endif %} {% set disks = inv.disks %} {% if disks %}

Disks ({{ disks|length }})

{% for d in disks %} {% endfor %}
Path Size Vendor / Model Serial Transport
{{ d.get("path") or "-" }} {{ d.get("size") or "-" }} {{ d.get("vendor") or "-" }} {% if d.get("model") %}
{{ d.get("model") }}{% endif %}
{{ d.get("serial") or "-" }} {{ d.get("tran") or "-" }}
{% else %}

No disks in the posted inventory.

{% endif %} {% if machine.inventory.get("lshw") %}
Raw lshw JSON
{{ machine.inventory.get("lshw") | tojson(indent=2) }}
{% endif %} {% else %}

No inventory has been posted for this machine yet. The live env's pixie CLI posts one on boot; check the target's PXE reach to pixie.

{% endif %}

Recent events

All events
{% if events %}
{% for e in events %} {% endfor %}
When Kind Summary
{{ e.ts | fmt_ts }} {{ e.kind }} {{ e.summary or "" }}
{% else %}

No events recorded for this machine yet.

{% endif %}
{% endblock %}