{% extends "base.html" %} {% import '_ui.html' as ui %} {% block title %}Clonezilla backups - PXE Manager{% endblock %} {# Clonezilla backups, grouped by machine number (newest activity first): image directories saved by the boot menu's "Clonezilla: back up this PC" (or by hand) and the older machine-number .zip files. One line per image; its details (disks, Clonezilla version, check) are in the expandable body; Download is the row's action, Move and Delete are in the menu and open confirm modals. #} {% macro gb(n) -%} {%- if n >= 1e12 %}{{ "%.2f"|format(n / 1e12) }} TB{% elif n >= 1e9 %}{{ "%.1f"|format(n / 1e9) }} GB{% else %}{{ "%.0f"|format(n / 1e6) }} MB{% endif -%} {%- endmacro %} {% macro status_chip(i) -%} {%- if i.status == 'ok' %}{{ ui.chip('Checked', 'ok', 'Clonezilla image check passed' ~ (' ' ~ i.check_date if i.check_date else '')) }} {%- elif i.status == 'check-failed' %}{{ ui.chip('Check failed', 'fail', 'The image check after saving failed: do not rely on this image') }} {%- elif i.status == 'failed' %}{{ ui.chip('Save failed', 'fail', 'Clonezilla reported an error while saving: partial image') }} {%- elif i.status == 'unchecked' %}{{ ui.chip('Not checked', 'warn', 'Saved, but the image check did not run') }} {%- elif i.status == 'in-progress' %}{{ ui.chip('In progress?', 'run', 'No pxe-meta.txt yet and changed in the last 6 hours: probably still being written') }} {%- else %}{{ ui.chip('Manual', 'neutral', 'Saved without the PXE menu script: no check result recorded') }}{% endif -%} {%- endmacro %} {% block extra_head %} {% endblock %} {% block content %} {% set nmach = groups | rejectattr('machine', 'equalto', '') | list | length %} {% call ui.head('Clonezilla backups', 'Tools', image_count ~ ' image' ~ ('s' if image_count != 1) ~ ' and ' ~ (backups | length) ~ ' zip' ~ ('s' if backups | length != 1) ~ ' for ' ~ nmach ~ ' machine' ~ ('s' if nmach != 1) ~ ' on the share') %}
Settings
{% if cz_settings.keep_last %} Apply retention... {% endif %} {% endcall %}
{% if plan is not none %}

Apply retention: keep the last {{ plan_keep }} image{{ 's' if plan_keep != 1 }} per machine

{% if plan %}
These {{ plan | length }} image{{ 's' if plan | length != 1 }} ({{ gb(plan | sum(attribute='size')) }}) will be DELETED. This cannot be undone.

Kept per machine: the {{ plan_keep }} newest images that saved and passed (or skipped) the check. Newer failed or in-progress images are kept too. Images with no machine number are never touched.

{% for p in plan %}{% endfor %}
Cancel
{% else %}
Nothing to delete: no machine has more than {{ plan_keep }} good image{{ 's' if plan_keep != 1 }}.
{% endif %}
{% endif %} {% if space %}

Share disk space

Share disk space {{ gb(space.used) }} used of {{ gb(space.total) }} ({{ "%.0f"|format(space.percent) }}%) {{ gb(space.free) }} free {% if space.warn %}{{ ui.chip('Over ' ~ space.warn_percent ~ '%', 'warn') }}{% endif %}
{% if space.warn %}
The share is {{ "%.0f"|format(space.percent) }}% full (warning at {{ space.warn_percent }}%). Delete old images, or set Keep last N in Settings and Apply retention. A backup that runs out of space fails part-way.
{% endif %}
{% endif %} {% if mismatches %}
{{ mismatches }} machine{{ 's have' if mismatches != 1 else ' has' }} images with different serial numbers (marked Serial mismatch below): a typo in the machine number, or the PC was replaced. Move the wrong images to the right machine number.
{% endif %}

Backups by machine

{% if groups %} {% for g in groups %} {% set label = g.machine or 'No machine number' %}

{{ label }}

{{ g.images | length }} image{{ 's' if g.images | length != 1 }}{% if g.zips %}, {{ g.zips | length }} zip{{ 's' if g.zips | length != 1 }}{% endif %} | {{ gb(g.size) }} {% if g.mismatch %}{{ ui.chip('Serial mismatch', 'warn', 'Serials: ' ~ (g.serials | join(', '))) }}{{ g.serials | join(', ') }}{% endif %}
{% for i in g.images %}
{{ i.when | timestamp_fmt }} {{ i.model or i.name }} {{ i.serial or '-' }} {{ gb(i.size) }} {{ status_chip(i) }}
Image
{{ i.name }}
Machine
{{ i.machine or '-' }} ({{ {'meta': 'from pxe-meta.txt', 'name': 'from the folder name'}.get(i.machine_source, 'unknown: move it to a machine number') }})
PC
{{ i.manufacturer }} {{ i.model or '-' }} | serial {{ i.serial or '-' }}{% if i.serial_differs %} {{ ui.chip('Different serial', 'warn', 'Not the serial of the newest image of this machine') }}{% endif %}
Size
{{ gb(i.size) }}
Disk
{{ i.disks | join(' ') or '-' }}{% if i.disk_model %} | {{ i.disk_model }}{% endif %}{% if i.disk_size %} | {{ gb(i.disk_size) }}{% endif %}
Partitions
{{ i.parts | join(' ') or '-' }}
Clonezilla
{{ i.clonezilla or '-' }}{% if i.bits %} | {{ i.bits }}-bit{% endif %}{% if i.firmware %} | {{ i.firmware | upper }}{% endif %}
Saved
{{ i.date_text or (i.when | timestamp_fmt) }}{% if i.save == 'failed' %} | save failed{% endif %}
Check
{{ {'ok': 'passed', 'failed': 'FAILED', 'not-run': 'not run'}.get(i.check, 'no result recorded') }}{% if i.check_date %} ({{ i.check_date }}){% endif %}
Download .tar {% call ui.more(i.name) %}
{% endcall %}
{% endfor %} {% for b in g.zips %}
{{ b.modified | timestamp_fmt }} {{ b.filename }} - {{ gb(b.size) }} {{ ui.chip('Zip', 'neutral', 'Uploaded .zip backup') }}
Download {% call ui.more(b.machine) %}
{% endcall %}
{% endfor %}
{% endfor %} {% else %}
No backups yet. Boot a PC from the network and pick Clonezilla: back up this PC, or upload a .zip.
{% endif %}

How backups are named

The boot menu's Clonezilla: back up this PC asks for the machine number and saves <machine>-<YYYY-MM-DD-HHMM> (for example 6501-2026-10-15-1403) to \\pxe-server\clonezilla, then checks it. Clonezilla: restore this PC lists only that machine's images, newest first.

Images saved by hand (manual mode) are grouped by the start of their folder name; move them to a machine number if they show under No machine number. Uploaded zips are named with the machine number, for example 6501.zip.

{% endblock %} {% block extra_scripts %} {% endblock %}