NetBSD build környezet: chroot, qemu-nvmm

A host rendszer NetBSD utolsó stabil branch, jelenleg ez NetBSD-10 sysupgrade-val időnként frissítve, hogy a fixeket hamarabb megkapja, mintha csak a kiadásokra frissülne. Csomagok az aktuális pkgsrc negyedéves kiadáson alapuló repóból, jelenleg ez a pkgsrc-2024Q4.

Ezen nem is szeretnék változtatni, viszont néhány csomagot tesztelni akarok pkgsrc-trunk branchon, amely miatt az összes szükséges csomagot fordítanom kell. Elsőnek a NetBSD-re elérhető qemu-nvmm-el próbálkoztam a leírást követve, viszont nem hozta a várt teljesítményt.

Azzal tisztában voltam, hogy lesz teljesítmény vesztés a host-hoz képest, de ekkorára nem számítottam. A pkgsrc/devel/binutils csomaggal végeztem egy hevenyészett összehasonlítást, tudom hogy nem mérnöki precizitású, de sac/kb szemlélteti a csalódást. A binutils könyvtárában make patch után futtattam:

_start=$(date +%s) && make && _end=$(date +%s) && echo "make time: $(date -d@$((_end - _start)) -u +%H:%M:%S)"
a hoston: Ryzen7 7700X + 64G (16 szál): make time: 00:00:32
a hoston futó: qemu-system-x86_64+nvmm (NetBSD-10.1-i386) 16cpu+16G (16 szál): make time: 00:02:01
a hoston futó: qemu-system-x86_64+nvmm (NetBSD-10.1-amd64) 16cpu+16G (16 szál): make time: 00:01:24
i5-4670K+24G Linux-x86_64 hoston futó: vbox  (NetBSD-10.1-amd64) 4cpu+8G (4 szál): make time: 00:02:20

Az i5-ös gépen érdekes lenne még egy vbox linux guest és megnézni, mekkora veszteséget produkál a vbox guest a hosthoz képest, de elég beszédes így is a jóval erősebb vason futó nvmm teljesítménye a vbox-hoz képest.

Esetleg, ha valakinek van kedve hozzá, kipróbálhatná más rendszereken mire képes a virtuális gép. Főleg a FreeBSD bhyve viszonylatban lennék kíváncsi, de minden érdekel (igazán szaftos lenne egy DragonFly nvmm).

Következőnek adta magát a chroot környezet, ami be is vált. Több leírást alapul véve ezekkel a főbb lépésekkel hoztam létre:

mkdir chrootdir
for _set in base comp etc misc xbase xcomp xfont xserver xetc ; do
  curl -s "https://cdn.netbsd.org/pub/NetBSD/NetBSD-$(uname -r)/amd64/binary/sets/$_set.tar.xz" -o "$_set.tar.xz"
  tar xfJ $_set.tar.xz -C chrootdir
done

cd chrootdir/dev
./MAKEDEV all opty
cd ..

echo "ALLOW_VULNERABLE_PACKAGES=      1" > etc/mk.conf
echo "MAKE_JOBS=                      16" >> etc/mk.conf
echo "PKG_DEVELOPER=                  yes" >> etc/mk.conf
echo "SU_CMD=                         /usr/pkg/bin/sudo /bin/sh -c" >> etc/mk.conf
echo "ACCEPTABLE_LICENSES+=           gnu-agpl-v3" >> etc/mk.conf
echo "ACCEPTABLE_LICENSES+=           gnu-lgpl-v2.1" >> etc/mk.conf
echo "ACCEPTABLE_LICENSES+=           unrar-license" >> etc/mk.conf

mkdir -p home/kikadf
chown -R kikadf:wheel home/kikadf

cp -p /home/kikadf/{.shrc,.profile} home/kikadf/
cp -f /etc/resolv.conf etc/
cp -f /etc/{master.,}passwd etc/
sed -i'' "s,usr/pkg/bin/zsh,bin/sh," etc/{master.,}passwd
cp -f /etc/{group,localtime} etc/

chmod 777 tmp/
chmod +t tmp/
cd ..

sudo chroot chrootdir pwd_mkdb /etc/master.passwd
sudo chroot chrootdir certctl rehash

sudo PKG_PATH=https://cdn.NetBSD.org/pub/pkgsrc/packages/NetBSD/amd64/$(uname -r)/All chroot chrootdir pkg_add pkgin nano git sudo pkgchkxx
cp -f /usr/pkg/etc/sudoers $_nb_chrootname/usr/pkg/etc/
sudo chroot chrootdir git config --global --add safe.directory /usr/pkgsrc

mkdir chrootdir/usr/pkgsrc
chmod 775 chrootdir/usr/pkgsrc
git clone --depth 1 https://github.com/NetBSD/pkgsrc.git chrootdir/usr/pkgsrc
git clone --depth 1 https://github.com/NetBSD/pkgsrc-wip.git chrootdir/usr/pkgsrc/wip

Lépésről lépésre: letölti és kibontja a chroot könyvtárába a NetBSD-t, létrehozza a a /dev könyvtárban az eszközleíró fájlokat, szerkeszti az mk.conf fájlt, amit a csomag build-eléshez fog használni, létrehozza a felhasználó könyvtárát, a host rendszerről átmásolja a chroot alá a szükséges conf fájlokat (kikadf user esetén zsh-ról az alap /bin/sh-ra állítja a shellt), tmp könyvtár jogosultságait beállítja, generálja a jelszó db-ket és az OpenSSL certeket, telepít néhány alap csomagot (néhány beállítással), klónozza a pkgsrc és pkgsrc-wip repókat.

A fentieket egy scriptbe öntöttem hibakezeléssel és arch választhatási lehetőséggel kiegészítve, mivel i386 NetBSD is telepíthető chroot környezetbe amd64 host esetén.

Ezután 'sudo chroot chrootdir su -l kikadf' paranccsal lépek be, ahol az első dolgom a már telepített csomagok frissítése a pkgsrc-trunk állapotra a 'sudo pkgrrxx -ruv' paranccsal, majd kezdhetem a kívánt csomag buildelését.

Több chroot környezet esetén, jó ha megosztoznak a distfiles könyvtáron, hogy ne töltögessék le külön-külön a forráscsomagokat. Ehhez chroot login előtt a 

mount | grep -q "chrootdir/usr/pkgsrc/distfiles" \
|| sudo mount -t null /usr/pkgsrc/distfiles chrootdir/usr/pkgsrc/distfiles

parancsot használom. Fontos ellenőrizni mount előtt, hogy már csatolva van-e a host distfiles könyvtára a chroot-ba, mert a NetBSD simán csatolja ugyanazt 100-szor is egymás után, chroot be meg kilépegetések során (ha scriptelve van a mount és login is, nálam igen) meglephet jó pár mount-al.

A chroot környezetben elkészített csomagokat qemu-nvmm guest-ekben próbálom ki, mert a host rendszeren nem kellenek a pkgsrc-trunk csomagok. A pkgsrc alapértelmezésben a /usr/pkgsrc/packages/All könyvtárba pakolja az elkészített csomagokat, így azok teszteléséhez a chroot usr/pkgsrc/packages/All könyvtárát NFS-el osztom meg a qemu-nvmm guest-tel. Előtte azonban létre kell hozni a pkg_summary.gz fájlt, hogy a csomagkezelő repóként tudja használni. Ehhez a chroot-ban:

cd /usr/pkgsrc/packages/All
pkg_info -X $(ls) > pkg_summary
gzip pkg_summary

Ezután a hoston kell egy NFS szerver. Az /etc/exports configba:

/chrootdir/usr/pkgsrc/packages/All -ro -noresvport -noresvmnt -mapall=nobody -network 127.0.0.1 -mask 255.255.255.0

Fontos a '-noresvport -noresvmnt', nélküle a guest-en mount során 'mount_nfs: bad MNT RPC: RPC: Authentication error; why = Client credential too weak' hibaüzenetet kaptam, a host /var/log/messages-ben pedig: 'mountd[2296]: Refused mount RPC from host 127.0.0.1 port 65469'

Az /etc/rc.conf-ba:

rpcbind=YES
mountd=YES
nfs_server=YES
lockd=YES
statd=YES

A qemu-nvmm guest-ben pedig NFS kliens beállítása. Az /etc/rc.conf-ban:

rpcbind=YES
nfs_client=YES
lockd=YES
statd=YES

/etc/fstab:

10.0.2.2:/chrootdir/usr/pkgsrc/packages/All /mnt nfs ro,noauto,intr,timeo=14 0 0

/usr/pkg/etc/pkgin/repositories.conf:

file:///mnt

Végül 'sudo mount /mnt', majd 'sudo pkgin in testpkg' és mehet a tesztelés.

Próbálkoztam egyébként a testpkg közvetlen chroot-ból történő futtatásával, hogy a host X szerveréhez csatlakozzon, de nem jártam eredménnyel. Később leírom hogyan próbáltam, hátha valaki látja hol hibáztam.

Hozzászólások

Pro tipp: nekem van egy do_chroot scriptem, ami nincs tulbonyolitva, de felizgatja es eltakaritja a szukseges mountokat. Ez Linux-ra van irva, es Linux Chroot-ot kezel, a scriptnek a chroot gyokereben kell lennie (tehat mittudomen a dev mappaval egy szinten), de nem kell gondolkodnom a fel- es lecsatolgatasokaon:

#!/bin/bash

set -euo pipefail

ME="$(readlink -f "$0")"
ROOT="$(dirname "${ME}")"

cleanup() {
	for dir in dev/pts dev sys/firmware/efi/efivars sys proc ; do
		[[ -d "${ROOT}/${dir}" ]] && umount "${ROOT}/${dir}"
	done
	exit $1
}


for dir in dev proc sys; do
	if [[ ! -d "${ROOT}/${dir}" ]]; then
		mkdir -p "${ROOT}/${dir}"
	fi
done

mount -t proc proc "${ROOT}/proc"
mount -t sysfs sysfs "${ROOT}/sys"
if [[ -d "${ROOT}/sys/firmware/efi/efivars" ]]; then
	mount -t efivarfs efivarfs "${ROOT}/sys/firmware/efi/efivars"
fi
mount -t devtmpfs devtmpfs "${ROOT}/dev"
mount -t devpts devpts "${ROOT}/dev/pts"

if [[ -n "$@" ]]; then
	chroot "${ROOT}"  "$@"
else
	rootshell="$(awk -F : '/root/ { print $7 }' "${ROOT}/etc/passwd")"
	rootshell="${rootshell:-/bin/bash}"
	if [[ ! -x "${ROOT}/${rootshell}" ]]; then
		if [[ -x "${ROOT}/bin/sh" ]]; then
			rootshell=/bin/sh
		else
			echo " !! No available shell detected. Specify shell command as argument!"
			cleanup 1
		fi
	fi
	chroot "${ROOT}" "${rootshell}"
fi

cleanup 0

Ez nyilvan igy nem jo neked, de otletadasnak gondoltam, van benne intelligencia is a root shell tekinteteben, kezeli a hibas kilepeseket is. Volna meg mit fejleszteni rajta, de ezt asszem egy fel eve raktam ossze durvan 15 perc alatt, valami sysrescuecd bonyolultsagu kornyezeten, mert 465-odszorre kellett vegigmasznom a chroot lepeseken.

A lenyeg: nem chroot parancsot adsz ki, hanem ezt a scriptet futtatod meg, ez felizgatja a chroot parancs elott a rendszert, belep, es amint a shell-bol kilepsz, teardown-olja a dolgokat. 

Blog | @hron84

valahol egy üzemeltetőmaci most mérgesen toppant a lábával 

via @snq-

NetBSD-re nincs valami poudriere-szerű valami?