feat(harness): systemd-юниты + Lima-конфиг + E2E-харнесс (файлы)
systemd/ (target/data.mount/firstboot/machineid/power/settings/shell + dbus-policy + journald/zram/oomd): ordering data.mount->firstboot->machineid->dbus->power+settings->shell; Requires+After firstboot; OOMScoreAdjust. lima/shturman.yaml (vz, Ubuntu ARM64, /data loopback, провижининг). tests/e2e/run.sh (каркас приёмки). justfile: vm-up/down/reset/shell, run, e2e, shell-frame. Валидация — часть 2 (поднятие Lima). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Alexander <akotenev2003@gmail.com>
This commit is contained in:
@@ -57,3 +57,35 @@ plugin-dev-run path:
|
||||
# Vehicle Simulator (плейсхолдер; домен E, v2)
|
||||
sim:
|
||||
@echo "Vehicle Simulator — v2 (домен E): vcan + ELM327-emu; каркас в sim/."
|
||||
|
||||
# --- Lima-VM (часть 2 Плана 5: нужен limactl — brew install lima) ---
|
||||
|
||||
# поднять dev-VM (создание + провижининг)
|
||||
vm-up:
|
||||
limactl start --name=shturman lima/shturman.yaml
|
||||
|
||||
# остановить VM
|
||||
vm-down:
|
||||
limactl stop shturman
|
||||
|
||||
# шелл в VM
|
||||
vm-shell:
|
||||
limactl shell shturman
|
||||
|
||||
# пересоздать VM «с нуля» (сброс — ничего на хосте не ломаем)
|
||||
vm-reset:
|
||||
-limactl stop shturman
|
||||
-limactl delete shturman
|
||||
limactl start --name=shturman lima/shturman.yaml
|
||||
|
||||
# собрать + развернуть + поднять target в VM (boot → сервисы → кадр)
|
||||
run:
|
||||
limactl shell shturman -- bash -lc 'cd /shturman && bash tests/e2e/run.sh'
|
||||
|
||||
# сквозной E2E в VM (приёмка v0.1/v0.6 + шагающий скелет)
|
||||
e2e:
|
||||
limactl shell shturman -- bash -lc 'cd /shturman && bash tests/e2e/run.sh'
|
||||
|
||||
# ручная проверка кадра: на хосте — окно Slint (headless PNG-screenshot — часть 2/Lima)
|
||||
shell-frame:
|
||||
cargo run -p shturman-shell
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# Lima-шаблон Штурмана: ARM64 Ubuntu, нативно к таргету RK3588 (dev-environment).
|
||||
# Подъём: just vm-up. Сборка/деплой/E2E — just run / just e2e (внутри VM). Валидируется в части 2 Плана 5.
|
||||
vmType: vz
|
||||
cpus: 4
|
||||
memory: "6GiB"
|
||||
disk: "20GiB"
|
||||
|
||||
images:
|
||||
- location: "https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-arm64.img"
|
||||
arch: "aarch64"
|
||||
|
||||
mounts:
|
||||
# репозиторий (writable). location — под свою раскладку; в гостье — /shturman.
|
||||
- location: "~/GitHub/shturman"
|
||||
mountPoint: "/shturman"
|
||||
writable: true
|
||||
|
||||
provision:
|
||||
# OS-база (root). Бинари/юниты-старт — в just run/e2e (бинарей ещё нет на этом шаге).
|
||||
- mode: system
|
||||
script: |
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get install -y \
|
||||
dbus pipewire wireplumber weston \
|
||||
can-utils python3 python3-venv \
|
||||
systemd-zram-generator fake-hwclock \
|
||||
fonts-dejavu-core fonts-noto-core \
|
||||
build-essential pkg-config curl
|
||||
|
||||
# vcan (для Vehicle Simulator, v2 — поднимаем заранее для воспроизводимости)
|
||||
modprobe vcan || true
|
||||
ip link add dev vcan0 type vcan 2>/dev/null || true
|
||||
ip link set up vcan0 || true
|
||||
|
||||
# loopback /data (ext4, power-safe) + data.mount
|
||||
mkdir -p /var/lib/shturman
|
||||
if [ ! -f /var/lib/shturman/data.img ]; then
|
||||
truncate -s 1G /var/lib/shturman/data.img
|
||||
mkfs.ext4 -q -L shturman-data /var/lib/shturman/data.img
|
||||
fi
|
||||
|
||||
# systemd-юниты + конфиги из репозитория
|
||||
install -m644 /shturman/systemd/shturman.target /etc/systemd/system/
|
||||
install -m644 /shturman/systemd/data.mount /etc/systemd/system/
|
||||
install -m644 /shturman/systemd/shturman-*.service /etc/systemd/system/
|
||||
install -d /etc/dbus-1/system.d
|
||||
install -m644 /shturman/systemd/dbus/ru.shturman.conf /etc/dbus-1/system.d/
|
||||
install -d /etc/systemd/journald.conf.d
|
||||
install -m644 /shturman/systemd/journald-shturman.conf /etc/systemd/journald.conf.d/shturman.conf
|
||||
install -m644 /shturman/systemd/zram-generator.conf /etc/systemd/zram-generator.conf
|
||||
install -d /etc/systemd/oomd.conf.d
|
||||
install -m644 /shturman/systemd/oomd-shturman.conf /etc/systemd/oomd.conf.d/shturman.conf
|
||||
|
||||
# fake-hwclock → /data (не на rootfs; A07/A11)
|
||||
echo 'FILE=/data/state/fake-hwclock.data' > /etc/default/fake-hwclock || true
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable systemd-oomd.service || true
|
||||
# shturman.target включаем, но НЕ стартуем здесь — бинарей ещё нет (just run/e2e).
|
||||
systemctl enable shturman.target || true
|
||||
|
||||
# Rust-тулчейн (user)
|
||||
- mode: user
|
||||
script: |
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
command -v cargo >/dev/null || curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
@@ -0,0 +1,15 @@
|
||||
# Журналируемый /data (power-safe). Loopback-образ создаёт provisioning (lima/shturman.yaml).
|
||||
# Имя юнита (data.mount) обязано соответствовать Where=/data.
|
||||
[Unit]
|
||||
Description=Штурман /data (журналируемый, power-safe)
|
||||
Before=shturman-firstboot.service
|
||||
|
||||
[Mount]
|
||||
What=/var/lib/shturman/data.img
|
||||
Where=/data
|
||||
Type=ext4
|
||||
# барьеры — дефолт ядра; errors=remount-ro — реально отображаемая non-default опция (ассертит E2E).
|
||||
Options=rw,noatime,errors=remount-ro,loop
|
||||
|
||||
[Install]
|
||||
WantedBy=shturman.target
|
||||
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<!--
|
||||
Системная шина устройства (ipc §1). v0: сервисы под root, политика разрешает own/send для ru.shturman.*.
|
||||
dev-mock (ru.shturman.dev.PowerMock1) — это ИНТЕРФЕЙС на объекте Power, отдельное bus-имя НЕ нужно
|
||||
(send_destination=ru.shturman.Power покрывает все его интерфейсы); гейт dev — только cargo-фича.
|
||||
Тонкая per-app прокси-фильтрация (портал-паттерн) — v3 (App-Host). Выделенный shturman-user — позже (hardening).
|
||||
-->
|
||||
<busconfig>
|
||||
<policy context="default">
|
||||
<allow own="ru.shturman.Power"/>
|
||||
<allow own="ru.shturman.Settings"/>
|
||||
<allow send_destination="ru.shturman.Power"/>
|
||||
<allow send_destination="ru.shturman.Settings"/>
|
||||
</policy>
|
||||
</busconfig>
|
||||
@@ -0,0 +1,7 @@
|
||||
# journald drop-in (A10): журнал в RAM (не на flash), rate-limit. Критичное → fsync в /data (каркас common).
|
||||
# Установка: /etc/systemd/journald.conf.d/shturman.conf
|
||||
[Journal]
|
||||
Storage=volatile
|
||||
RuntimeMaxUse=64M
|
||||
RateLimitIntervalSec=30s
|
||||
RateLimitBurst=1000
|
||||
@@ -0,0 +1,5 @@
|
||||
# systemd-oomd drop-in (A09): защищаем critical set (OOMScoreAdjust в юнитах); первые жертвы — фон/плагины.
|
||||
# Установка: /etc/systemd/oomd.conf.d/shturman.conf (+ systemctl enable --now systemd-oomd).
|
||||
[OOM]
|
||||
SwapUsedLimit=90%
|
||||
DefaultMemoryPressureLimit=60%
|
||||
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=Штурман first-boot provisioning (/data init + machine-id, A06)
|
||||
ConditionPathExists=!/data/.shturman-provisioned
|
||||
Requires=data.mount
|
||||
After=data.mount
|
||||
Before=shturman-machineid.service shturman-settings.service shturman-power.service shturman-shell.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/usr/local/bin/shturman-firstboot
|
||||
|
||||
[Install]
|
||||
WantedBy=shturman.target
|
||||
@@ -0,0 +1,16 @@
|
||||
# Every-boot привязка persistent machine-id из /data → /etc/machine-id (a-base §11):
|
||||
# генерация — one-shot в firstboot; bind волатилен и нужен на КАЖДЫЙ boot, до dbus.
|
||||
[Unit]
|
||||
Description=Штурман bind persistent machine-id (/data → /etc/machine-id)
|
||||
Requires=data.mount
|
||||
After=data.mount shturman-firstboot.service
|
||||
Before=dbus.service shturman-settings.service shturman-power.service shturman-shell.service
|
||||
ConditionPathExists=/data/state/machine-id
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/bin/sh -c 'mount --bind /data/state/machine-id /etc/machine-id'
|
||||
|
||||
[Install]
|
||||
WantedBy=shturman.target
|
||||
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=Штурман Power (ru.shturman.Power1)
|
||||
Requires=data.mount shturman-firstboot.service
|
||||
After=data.mount shturman-firstboot.service shturman-machineid.service dbus.service
|
||||
PartOf=shturman.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/shturman-power
|
||||
Restart=on-failure
|
||||
RestartSec=2
|
||||
OOMScoreAdjust=-600
|
||||
|
||||
[Install]
|
||||
WantedBy=shturman.target
|
||||
@@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=Штурман Settings (ru.shturman.Settings1)
|
||||
# Requires+After firstboot: не стартуем против полу-провиженного /data (Wants недостаточно).
|
||||
Requires=data.mount shturman-firstboot.service
|
||||
After=data.mount shturman-firstboot.service shturman-machineid.service dbus.service
|
||||
PartOf=shturman.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/shturman-settings
|
||||
Restart=on-failure
|
||||
RestartSec=2
|
||||
# защищаем critical set от OOM (a-base §8)
|
||||
OOMScoreAdjust=-600
|
||||
|
||||
[Install]
|
||||
WantedBy=shturman.target
|
||||
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=Штурман Shell (первый Slint-кадр)
|
||||
Requires=data.mount shturman-firstboot.service
|
||||
After=shturman-power.service shturman-settings.service shturman-machineid.service
|
||||
PartOf=shturman.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/shturman-shell
|
||||
Restart=on-failure
|
||||
RestartSec=2
|
||||
OOMScoreAdjust=-600
|
||||
# Wayland-дисплей: provisioning/E2E поднимает weston headless (финализируется в части 2).
|
||||
Environment=WAYLAND_DISPLAY=wayland-1
|
||||
Environment=XDG_RUNTIME_DIR=/run/user/0
|
||||
|
||||
[Install]
|
||||
WantedBy=shturman.target
|
||||
@@ -0,0 +1,7 @@
|
||||
[Unit]
|
||||
Description=Штурман — v0 critical set (Stage 1: ядро + первый кадр)
|
||||
Requires=data.mount
|
||||
After=data.mount
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,4 @@
|
||||
# zram (A09): сжатый swap в RAM; swap-на-flash запрещён. Установка: /etc/systemd/zram-generator.conf
|
||||
[zram0]
|
||||
zram-size = min(ram / 2, 4096)
|
||||
compression-algorithm = zstd
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
# Сквозной E2E Штурмана в Lima-VM (приёмка v0.1/v0.6 + шагающий скелет, спека §9.3/§9.4).
|
||||
# Запуск: just e2e (внутри VM через limactl shell). Системная шина устройства.
|
||||
# Часть 2 Плана 5 — здесь финализируются weston-screenshot и калибровка eMMC-порога.
|
||||
set -euo pipefail
|
||||
|
||||
REPO=/shturman
|
||||
cd "$REPO"
|
||||
|
||||
echo "== сборка =="
|
||||
cargo build --release --workspace
|
||||
sudo install -m755 target/release/shturman-firstboot /usr/local/bin/
|
||||
sudo install -m755 target/release/shturman-settings /usr/local/bin/
|
||||
sudo install -m755 target/release/shturman-power /usr/local/bin/
|
||||
sudo install -m755 target/release/shturman-shell /usr/local/bin/
|
||||
|
||||
echo "== старт target =="
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl start shturman.target
|
||||
sleep 3
|
||||
|
||||
fail() { echo "E2E FAIL: $*" >&2; exit 1; }
|
||||
|
||||
echo "== 1. /data смонтирован до сервисов, реальные опции =="
|
||||
findmnt /data || fail "/data не смонтирован"
|
||||
findmnt -no OPTIONS /data | grep -q errors=remount-ro || fail "нет errors=remount-ro"
|
||||
|
||||
echo "== 2. first-boot идемпотентен =="
|
||||
test -f /data/.shturman-provisioned || fail "нет маркера provisioned"
|
||||
test -f /data/state/machine-id || fail "нет machine-id"
|
||||
|
||||
echo "== 3. per-unit critical set active (не довольствуемся degraded) =="
|
||||
for u in shturman-power shturman-settings shturman-shell; do
|
||||
systemctl is-active --quiet "$u" || fail "$u не active"
|
||||
done
|
||||
|
||||
echo "== 4. имена на системной шине =="
|
||||
busctl --system list | grep -q ru.shturman.Power || fail "нет ru.shturman.Power"
|
||||
busctl --system list | grep -q ru.shturman.Settings || fail "нет ru.shturman.Settings"
|
||||
|
||||
echo "== 5. fake-ACC: SetAcc -> AccChanged =="
|
||||
# (подписка+вызов dev.PowerMock1; реализация ассерта — busctl monitor/call, финал в части 2)
|
||||
|
||||
echo "== 6. персист настроек через reboot + machine-id стабилен =="
|
||||
# (Settings.Set -> sudo reboot -> повторный прогон сверяет; оформляется в части 2)
|
||||
|
||||
echo "== 7. первый кадр (software-render PNG не пустой) =="
|
||||
# (weston headless + shturman-shell + screenshot; финал — часть 2)
|
||||
|
||||
echo "== 8. база: journald volatile / zram / eMMC-прокси =="
|
||||
journalctl --header 2>/dev/null | grep -qi volatile || echo "WARN: journald не volatile?"
|
||||
zramctl | grep -q zram0 || echo "WARN: zram0 не активен?"
|
||||
|
||||
echo "E2E OK (каркас; пункты 5–7 финализируются в части 2)"
|
||||
Reference in New Issue
Block a user