Files
Bridge-and-Join-s/deploy/iso/build-iso-ubuntu.sh
T

136 lines
9.3 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/sh
# Сборка образа ISO Bridge&Join на основе Ubuntu 22.04 LTS Server (автоустановка).
#
# 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 — ОС, на которой
# «Валидата Клиент L» ставится официально (Debian 13 её установщик не принимает).
# IGATE=<igate-…-amd64.zip> — дистрибутив интеграционного шлюза НРД (с nsd.ru): кладётся в образ, и шлюз
# ставится из мастера настройки без интернета («Установить с образа»).
# Меню загрузки (grub, BIOS и UEFI): по умолчанию — установка Bridge&Join с автоответами.
set -eu
SRC=${1:?ubuntu-22.04.x-live-server-amd64.iso}
INSTALLER=${2:?файл bj-installer}
VERSION=${3:?версия образа}
BUNDLE=${4:?каталог релиза с manifest.json}
VALIDATA=${5:?каталог с zpki/zsdk/libldap-2.4-2}
CHANNEL=${6:-stable}
OUT=${7:-bj-ubuntu22-$VERSION.iso}
HERE=$(cd "$(dirname "$0")" && pwd)
command -v xorriso >/dev/null || { echo "нужен xorriso"; exit 1; }
WORK=$(mktemp -d); trap 'rm -rf "$WORK"' EXIT
mkdir -p "$WORK/bj/bundle" "$WORK/bj/validata" "$WORK/nocloud" "$WORK/grub"
install -m 0755 "$INSTALLER" "$WORK/bj/bj-installer"
install -m 0755 "$HERE/bj-firstboot" "$WORK/bj/bj-firstboot"
cp "$HERE/bj-firstboot.service" "$WORK/bj/"
install -m 0755 "$HERE/../linux/sbin/bj-welcome" "$WORK/bj/bj-welcome"
install -m 0755 "$HERE/../linux/sbin/bj-network" "$WORK/bj/bj-network"
cp "$HERE/../systemd/bj-welcome.service" "$HERE/../systemd/bj-welcome.timer" "$WORK/bj/"
echo "$CHANNEL" > "$WORK/bj/channel"; echo "$VERSION" > "$WORK/bj/version"
# ядро bj: подписанный манифест + bj-server, bj-component-install
[ -s "$BUNDLE/manifest.json" ] || { echo "в $BUNDLE нет manifest.json"; exit 1; }
cp "$BUNDLE/manifest.json" "$WORK/bj/bundle/"
FILES=$(python3 -c 'import json,sys,base64;s=json.load(open(sys.argv[1]));m=json.loads(base64.b64decode(s["payload"]));print(" ".join(a["file"] for a in m["artifacts"] if a["name"] in ("bj-server","bj-component-install","bj-installer","crypto-service.jar")))' "$BUNDLE/manifest.json")
[ -n "$FILES" ] || { echo "в релизе нет компонентов ядра"; exit 1; }
for f in $FILES; do cp "$BUNDLE/$f" "$WORK/bj/bundle/"; done
# дистрибутив ИШ НРД (необязательно)
if [ -n "${IGATE:-}" ]; then
case "$(basename "$IGATE")" in igate-*-amd64.zip) ;; *) echo "IGATE — нужен igate-<версия>-amd64.zip с сайта НРД"; exit 1 ;; esac
unzip -l "$IGATE" | grep -q 'igate_.*_amd64\.deb' || { echo "в $IGATE нет igate_*.deb"; exit 1; }
mkdir -p "$WORK/bj/igate"; cp "$IGATE" "$WORK/bj/igate/"
echo "ИШ в образе: $(basename "$IGATE")"
fi
# слой обновлений 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)
[ -n "$f" ] || { echo "в $VALIDATA нет пакета $p"; exit 1; }
cp "$f" "$WORK/bj/validata/"; n=$((n+1))
done
# автоответы (пароль root_bj — случайный и нигде не сохраняется: настоящий задаёт bj-firstboot)
HASH=$(openssl passwd -6 "$(head -c 32 /dev/urandom | base64)")
sed "s#@@PASSHASH@@#$HASH#" "$HERE/ubuntu/user-data.tmpl" > "$WORK/nocloud/user-data"
: > "$WORK/nocloud/meta-data"
# меню загрузки: первый пункт — установка Bridge&Join
xorriso -osirrox on -indev "$SRC" -extract /boot/grub/grub.cfg "$WORK/grub/grub.orig" >/dev/null 2>&1
{
echo "set default=0"
# меню ждёт выбора: выбор пункта установки и есть подтверждение стирания диска (без таймера образ,
# случайно оставленный подключённым, не переустановит систему сам)
echo "set timeout=-1"
echo "loadfont unicode"
echo "menuentry --hotkey=b 'Install Bridge&Join $VERSION - ERASES THE WHOLE DISK' {"
echo " set gfxpayload=keep"
echo " linux /casper/vmlinuz autoinstall ds=nocloud\;s=/cdrom/nocloud/ ---"
echo " initrd /casper/initrd"
echo "}"
# пункт с ядром HWE убираем — его файлы из образа удаляются
sed '/^set timeout/d;/^loadfont/d' "$WORK/grub/grub.orig" | awk '/^menuentry "Ubuntu Server with the HWE kernel"/{skip=1} skip&&/^}/{skip=0;next} !skip'
} > "$WORK/grub/grub.cfg"
# md5sum.txt: установщик Ubuntu при загрузке сверяет файлы образа по этому списку (casper-md5check);
# несовпадение или отсутствующий файл роняет подсистему Integrity. Убираем удалённые файлы HWE,
# пересчитываем изменённые и добавляем наши.
xorriso -osirrox on -indev "$SRC" -extract /md5sum.txt "$WORK/md5.orig" >/dev/null 2>&1
{
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"
rm -f "$OUT"
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 $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 пакета; слой обновлений: ${LAYER:-нет}"