Образ Ubuntu: слой обновлений (full-upgrade + ядро) и пакеты bj на диске — установка почти не качает из сети
- deploy/iso/build-ubuntu-updates-layer.sh: слой ubuntu-server-minimal.ubuntu-server.bj.squashfs поверх «Ubuntu Server» (оригинальные слои и среда установщика не меняются) + debs/ для bj-installer; - build-iso-ubuntu.sh LAYER=<каталог>: слой — источник установки по умолчанию, старые ядро HWE и прошивки из репозитория образа убираются; - bj-installer: пакеты из /var/lib/bj/debs ставятся с диска, иначе — из репозитория. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
@@ -259,6 +259,15 @@ func memTotal() uint64 {
|
||||
func (in *installer) stepPackages() (string, error) {
|
||||
pkgs := []string{"ca-certificates", "curl", "postgresql", "postgresql-client", "default-jre-headless", "pcscd", "python3"}
|
||||
env := append(os.Environ(), "DEBIAN_FRONTEND=noninteractive")
|
||||
// Образ кладёт пакеты со всеми зависимостями в /var/lib/bj/debs — ставим с диска, без сети.
|
||||
// Не вышло (другая система, не хватает зависимости) — обычная установка из репозитория.
|
||||
if debs, _ := filepath.Glob(in.P(debsDir) + "/*.deb"); len(debs) > 0 && in.root == "" {
|
||||
args := append([]string{"install", "-y", "-qq", "--no-install-recommends"}, debs...)
|
||||
if _, err := runEnv(env, "apt-get", append(args, pkgs...)...); err == nil {
|
||||
_ = os.RemoveAll(in.P(debsDir))
|
||||
return strings.Join(pkgs, ", ") + " (с образа, без загрузки)", nil
|
||||
}
|
||||
}
|
||||
if out, err := runEnv(env, "apt-get", "update", "-qq"); err != nil {
|
||||
return "", fmt.Errorf("apt-get update: %v\n%s", err, tail(out, 8))
|
||||
}
|
||||
@@ -682,6 +691,9 @@ func (in *installer) componentsFromBundle() (string, error) {
|
||||
return detail, nil
|
||||
}
|
||||
|
||||
// debsDir — системные пакеты для bj (PostgreSQL, Java, pcscd…), положенные образом ISO.
|
||||
const debsDir = "/var/lib/bj/debs"
|
||||
|
||||
// validataDir — пакеты «Валидата Клиент L», положенные образом ISO (zpki, zsdk и совместимая libldap-2.4-2).
|
||||
const validataDir = "/var/lib/bj/validata"
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#
|
||||
# deploy/iso/build-iso-ubuntu.sh <ubuntu-22.04.x-live-server-amd64.iso> <bj-installer> <версия> <каталог релиза> <каталог Валидаты> [канал] [выходной.iso]
|
||||
#
|
||||
# LAYER=<каталог> — слой обновлений Ubuntu и пакеты bj из build-ubuntu-updates-layer.sh: установка
|
||||
# ставит систему уже с обновлениями и не качает PostgreSQL/Java из сети. Без LAYER — как в Ubuntu 22.04.5.
|
||||
#
|
||||
# Каталог релиза — dist с подписанным manifest.json (в образ кладётся ядро bj: установка без ключа продукта).
|
||||
# Каталог Валидаты — zpki/zsdk (ПК «Валидата Клиент L» для Linux, fs.moex.com ClientL_Other.zip)
|
||||
# и libldap-2.4-2 из Ubuntu 20.04 (нужна zpki, в 22.04 её нет). Ubuntu 22.04 — ОС, на которой
|
||||
@@ -35,6 +38,36 @@ FILES=$(python3 -c 'import json,sys,base64;s=json.load(open(sys.argv[1]));m=json
|
||||
[ -n "$FILES" ] || { echo "в релизе нет компонентов ядра"; exit 1; }
|
||||
for f in $FILES; do cp "$BUNDLE/$f" "$WORK/bj/bundle/"; done
|
||||
|
||||
# слой обновлений Ubuntu (необязательно)
|
||||
LAYER=${LAYER:-}
|
||||
LNAME=ubuntu-server-minimal.ubuntu-server.bj
|
||||
LMAP=""
|
||||
LRM=""
|
||||
if [ -n "$LAYER" ]; then
|
||||
for f in $LNAME.squashfs $LNAME.size $LNAME.manifest; do [ -s "$LAYER/$f" ] || { echo "в $LAYER нет $f"; exit 1; }; done
|
||||
mkdir -p "$WORK/bj/debs"; cp "$LAYER"/debs/*.deb "$WORK/bj/debs/"
|
||||
# источник установки «Ubuntu Server + обновления Bridge&Join» — по умолчанию; слои minimal и
|
||||
# ubuntu-server под ним установщик подключает сам по цепочке имён
|
||||
xorriso -osirrox on -indev "$SRC" -extract /casper/install-sources.yaml "$WORK/is.orig" >/dev/null 2>&1
|
||||
{ sed 's/^ default: true$/ default: false/;s/^- default: true$/- default: false/' "$WORK/is.orig"
|
||||
echo "- default: true"
|
||||
echo " description:"
|
||||
echo " en: Ubuntu Server with updates applied when the Bridge&Join image was built."
|
||||
echo " id: ubuntu-server-bj"
|
||||
echo " locale_support: locale-only"
|
||||
echo " name:"
|
||||
echo " en: Ubuntu Server (Bridge&Join, updated)"
|
||||
echo " path: $LNAME.squashfs"
|
||||
echo " size: $(( $(cat "$LAYER/$LNAME.size") + $(awk '/path: ubuntu-server-minimal.ubuntu-server.squashfs/{f=1} f&&/size:/{print $2; exit}' "$WORK/is.orig") ))"
|
||||
echo " type: fsimage-layered"
|
||||
echo " variant: server"
|
||||
} > "$WORK/install-sources.yaml"
|
||||
# Ядро и прошивки новее — в слое; их старые копии в репозитории образа (и ядро HWE, которое
|
||||
# мы не ставим) не нужны: установка не будет их брать, пакет linux-generic уже стоит в слое.
|
||||
LRM="/pool/main/l/linux-firmware /pool/main/l/linux-hwe-6.8 /pool/main/l/linux-meta-hwe-6.8"
|
||||
LMAP="-map $LAYER/$LNAME.squashfs /casper/$LNAME.squashfs -map $LAYER/$LNAME.size /casper/$LNAME.size -map $LAYER/$LNAME.manifest /casper/$LNAME.manifest -map $WORK/install-sources.yaml /casper/install-sources.yaml"
|
||||
fi
|
||||
|
||||
# Валидата
|
||||
n=0; for p in zpki zsdk libldap-2.4-2; do
|
||||
f=$(ls "$VALIDATA"/${p}_*.deb "$VALIDATA"/${p}-*.deb 2>/dev/null | grep -E 'amd64\.deb$' | head -1 || true)
|
||||
@@ -67,7 +100,13 @@ xorriso -osirrox on -indev "$SRC" -extract /boot/grub/grub.cfg "$WORK/grub/grub.
|
||||
# пересчитываем изменённые и добавляем наши.
|
||||
xorriso -osirrox on -indev "$SRC" -extract /md5sum.txt "$WORK/md5.orig" >/dev/null 2>&1
|
||||
{
|
||||
grep -vE '\./casper/(hwe-vmlinuz|hwe-initrd|ubuntu-server-minimal\.ubuntu-server\.installer\.generic-hwe\.squashfs)$|\./boot/grub/grub\.cfg$' "$WORK/md5.orig"
|
||||
grep -vE '\./pool/main/l/linux-(firmware|hwe-6\.8|meta-hwe-6\.8)/' "$WORK/md5.orig" | grep -vE '\./casper/(hwe-vmlinuz|hwe-initrd|ubuntu-server-minimal\.ubuntu-server\.installer\.generic-hwe\.squashfs|install-sources\.yaml)$|\./boot/grub/grub\.cfg$'
|
||||
if [ -n "$LAYER" ]; then
|
||||
echo "$(md5sum < "$WORK/install-sources.yaml" | cut -d' ' -f1) ./casper/install-sources.yaml"
|
||||
for f in $LNAME.squashfs $LNAME.size $LNAME.manifest; do echo "$(md5sum < "$LAYER/$f" | cut -d' ' -f1) ./casper/$f"; done
|
||||
else
|
||||
grep -E '\./casper/install-sources\.yaml$' "$WORK/md5.orig"
|
||||
fi
|
||||
echo "$(md5sum < "$WORK/grub/grub.cfg" | cut -d' ' -f1) ./boot/grub/grub.cfg"
|
||||
(cd "$WORK" && find bj nocloud -type f | sort | while read -r f; do echo "$(md5sum < "$f" | cut -d' ' -f1) ./$f"; done)
|
||||
} > "$WORK/md5sum.txt"
|
||||
@@ -77,7 +116,7 @@ xorriso -indev "$SRC" -outdev "$OUT" -boot_image any replay \
|
||||
-volid "BJ_UBUNTU22" \
|
||||
-map "$WORK/bj" /bj -map "$WORK/nocloud" /nocloud \
|
||||
-map "$WORK/grub/grub.cfg" /boot/grub/grub.cfg \
|
||||
-map "$WORK/md5sum.txt" /md5sum.txt \
|
||||
-rm /casper/hwe-vmlinuz /casper/hwe-initrd /casper/ubuntu-server-minimal.ubuntu-server.installer.generic-hwe.squashfs -- \
|
||||
-map "$WORK/md5sum.txt" /md5sum.txt $LMAP \
|
||||
-rm_r /casper/hwe-vmlinuz /casper/hwe-initrd /casper/ubuntu-server-minimal.ubuntu-server.installer.generic-hwe.squashfs $LRM -- \
|
||||
-end >/dev/null 2>"$WORK/xorriso.log" || { cat "$WORK/xorriso.log"; exit 1; }
|
||||
echo "Образ собран: $OUT ($(du -h "$OUT" | cut -f1)), канал $CHANNEL; ядро: $FILES; Валидата: $n пакета"
|
||||
echo "Образ собран: $OUT ($(du -h "$OUT" | cut -f1)), канал $CHANNEL; ядро: $FILES; Валидата: $n пакета; слой обновлений: ${LAYER:-нет}"
|
||||
|
||||
Executable
+72
@@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
# Слой обновлений для образа Bridge&Join на Ubuntu 22.04: всё, что вышло для 22.04 после выпуска
|
||||
# 22.04.5, ставится в образ при сборке — установка тогда докачивает только вышедшее после сборки.
|
||||
#
|
||||
# sudo deploy/iso/build-ubuntu-updates-layer.sh <ubuntu-22.04.x-live-server-amd64.iso> <выходной каталог>
|
||||
#
|
||||
# Результат в выходном каталоге:
|
||||
# ubuntu-server-minimal.ubuntu-server.bj.squashfs (+ .size, .manifest) — слой поверх «Ubuntu Server»:
|
||||
# full-upgrade + ядро linux-generic (ядра в слоях Ubuntu нет, его ставит отдельный шаг установки);
|
||||
# установщик Ubuntu собирает систему из слоёв по цепочке имён (minimal → ubuntu-server → bj),
|
||||
# оригинальные слои и среда самого установщика не меняются;
|
||||
# debs/ — пакеты, которые ставит bj-installer (PostgreSQL, Java, pcscd…), со всеми зависимостями,
|
||||
# которых нет в системе: при первой загрузке они ставятся с диска, а не из сети.
|
||||
# Нужны root (монтирование, chroot), squashfs-tools, xorriso и доступ к archive.ubuntu.com.
|
||||
# Образ стоит пересобирать раз в месяц, чтобы слой не устаревал.
|
||||
set -euo pipefail
|
||||
SRC=${1:?ubuntu-22.04.x-live-server-amd64.iso}
|
||||
OUT=${2:?выходной каталог}
|
||||
[ "$(id -u)" = 0 ] || { echo "нужен root"; exit 1; }
|
||||
for c in mksquashfs xorriso; do command -v $c >/dev/null || { echo "нужен $c"; exit 1; }; done
|
||||
# пакеты — как в bj-installer (stepPackages)
|
||||
BJ_PKGS="ca-certificates curl postgresql postgresql-client default-jre-headless pcscd python3"
|
||||
LAYER=ubuntu-server-minimal.ubuntu-server.bj.squashfs
|
||||
|
||||
mkdir -p "$OUT"
|
||||
W=$(mktemp -d "$OUT/work.XXXXXX")
|
||||
M="$W/merged"
|
||||
cleanup() {
|
||||
for d in dev/pts dev proc sys run; do mountpoint -q "$M/$d" 2>/dev/null && umount -l "$M/$d" || true; done
|
||||
for d in "$M" "$W/l2" "$W/l1"; do mountpoint -q "$d" 2>/dev/null && umount -l "$d" || true; done
|
||||
rm -rf "$W"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
mkdir -p "$W/l1" "$W/l2" "$W/upper" "$W/wk" "$M"
|
||||
xorriso -osirrox on -indev "$SRC" \
|
||||
-extract /casper/ubuntu-server-minimal.squashfs "$W/minimal.squashfs" \
|
||||
-extract /casper/ubuntu-server-minimal.ubuntu-server.squashfs "$W/server.squashfs" >/dev/null 2>&1
|
||||
mount -o loop,ro "$W/minimal.squashfs" "$W/l1"
|
||||
mount -o loop,ro "$W/server.squashfs" "$W/l2"
|
||||
mount -t overlay overlay -o "lowerdir=$W/l2:$W/l1,upperdir=$W/upper,workdir=$W/wk" "$M"
|
||||
mount --bind /dev "$M/dev"; mount --bind /dev/pts "$M/dev/pts"
|
||||
mount -t proc proc "$M/proc"; mount -t sysfs sys "$M/sys"
|
||||
mount -t tmpfs tmpfs "$M/run"
|
||||
# DNS в chroot: resolv.conf в Ubuntu — ссылка в /run (tmpfs, в слой не попадает)
|
||||
mkdir -p "$M/run/systemd/resolve"; grep '^nameserver' /etc/resolv.conf > "$M/run/systemd/resolve/stub-resolv.conf"
|
||||
# службы в chroot не запускать
|
||||
printf '#!/bin/sh\nexit 101\n' > "$M/usr/sbin/policy-rc.d"; chmod 755 "$M/usr/sbin/policy-rc.d"
|
||||
|
||||
in_chroot() { chroot "$M" /usr/bin/env -i PATH=/usr/sbin:/usr/bin:/sbin:/bin DEBIAN_FRONTEND=noninteractive LANG=C.UTF-8 "$@"; }
|
||||
APT="apt-get -y -q -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef"
|
||||
echo "== apt update"; in_chroot apt-get -q update
|
||||
echo "== full-upgrade"; in_chroot $APT full-upgrade
|
||||
echo "== ядро"; in_chroot $APT install --no-install-recommends linux-generic
|
||||
in_chroot apt-get clean
|
||||
echo "== пакеты bj (только скачать)"
|
||||
in_chroot $APT install --download-only --no-install-recommends $BJ_PKGS
|
||||
rm -rf "$OUT/debs"; mkdir -p "$OUT/debs"
|
||||
cp "$M"/var/cache/apt/archives/*.deb "$OUT/debs/"
|
||||
in_chroot apt-get clean
|
||||
in_chroot dpkg-query -W -f '${Package}\t${Version}\n' > "$OUT/${LAYER%.squashfs}.manifest"
|
||||
|
||||
# убрать следы сборки: policy-rc.d, списки пакетов, кэш, журналы
|
||||
rm -f "$M/usr/sbin/policy-rc.d"
|
||||
rm -rf "$M"/var/lib/apt/lists/* "$M"/var/cache/apt/*.bin "$M"/var/log/apt/* "$M"/tmp/* 2>/dev/null || true
|
||||
for d in dev/pts dev proc sys run; do umount -l "$M/$d"; done
|
||||
umount "$M"
|
||||
|
||||
echo "== слой"
|
||||
rm -f "$OUT/$LAYER"
|
||||
mksquashfs "$W/upper" "$OUT/$LAYER" -comp xz -xattrs -noappend -no-progress >/dev/null
|
||||
du -sb "$W/upper" | cut -f1 > "$OUT/${LAYER%.squashfs}.size"
|
||||
echo "Слой: $OUT/$LAYER ($(du -h "$OUT/$LAYER" | cut -f1)), пакетов bj: $(ls "$OUT/debs" | wc -l) ($(du -sh "$OUT/debs" | cut -f1)), ядро: $(grep -P '^linux-image-[0-9]' "$OUT/${LAYER%.squashfs}.manifest" | cut -f1 | tr '\n' ' ')"
|
||||
@@ -30,6 +30,7 @@ autoinstall:
|
||||
- mkdir -p /target/var/lib/bj /target/etc/bj /target/usr/local/sbin
|
||||
- cp -r /cdrom/bj/bundle /target/var/lib/bj/bundle
|
||||
- cp -r /cdrom/bj/validata /target/var/lib/bj/validata
|
||||
- sh -c 'if [ -d /cdrom/bj/debs ]; then cp -r /cdrom/bj/debs /target/var/lib/bj/debs; fi'
|
||||
- install -m 0755 /cdrom/bj/bj-installer /cdrom/bj/bj-firstboot /cdrom/bj/bj-welcome /target/usr/local/sbin/
|
||||
- install -m 0644 /cdrom/bj/bj-firstboot.service /cdrom/bj/bj-welcome.service /cdrom/bj/bj-welcome.timer /target/etc/systemd/system/
|
||||
- install -m 0644 /cdrom/bj/channel /target/etc/bj/channel
|
||||
|
||||
Reference in New Issue
Block a user