pxe: a lot of improvements

This commit is contained in:
pedro 2024-09-27 17:27:12 -03:00
parent bd52916b06
commit 2df34e4b23
5 changed files with 99 additions and 23 deletions

View file

@ -198,9 +198,9 @@ create_persistence_partition() {
${SUDO} umount -f -l "${tmp_rw_mount}" >/dev/null 2>&1 || true ${SUDO} umount -f -l "${tmp_rw_mount}" >/dev/null 2>&1 || true
mkdir -p "${tmp_rw_mount}" mkdir -p "${tmp_rw_mount}"
${SUDO} mount "$(pwd)/${rw_img_path}" "${tmp_rw_mount}" ${SUDO} mount "$(pwd)/${rw_img_path}" "${tmp_rw_mount}"
${SUDO} mkdir -p "${tmp_rw_mount}/settings" ${SUDO} mkdir -p "${tmp_rw_mount}"
if [ -f "settings.ini" ]; then if [ -f "settings.ini" ]; then
${SUDO} cp -v settings.ini "${tmp_rw_mount}/settings/settings.ini" ${SUDO} cp -v settings.ini "${tmp_rw_mount}/settings.ini"
else else
echo "ERROR: settings.ini does not exist yet, cannot read config from there. You can take inspiration with file settings.ini.example" echo "ERROR: settings.ini does not exist yet, cannot read config from there. You can take inspiration with file settings.ini.example"
exit 1 exit 1
@ -274,11 +274,11 @@ stty -echo # Do not show what we type in terminal so it does not meddle with our
dmesg -n 1 # Do not report *useless* system messages to the terminal dmesg -n 1 # Do not report *useless* system messages to the terminal
# detect pxe env # detect pxe env
if [ -d /run/live/medium ]; then nfs_host="\$(df -hT | grep nfs | cut -f1 -d: | head -n1)"
if [ "\${nfs_host}" ]; then
mount --bind /run/live/medium /mnt mount --bind /run/live/medium /mnt
# debian live nfs path is readonly, do a trick # debian live nfs path is readonly, do a trick
# to make snapshots subdir readwrite # to make snapshots subdir readwrite
nfs_host="\$(df -hT | grep nfs | cut -f1 -d: | head -n1)"
mount \${nfs_host}:/snapshots /run/live/medium/snapshots mount \${nfs_host}:/snapshots /run/live/medium/snapshots
# reload mounts on systemd # reload mounts on systemd
systemctl daemon-reload systemctl daemon-reload

2
pxe/Makefile Normal file
View file

@ -0,0 +1,2 @@
test_pxe:
qemu-system-x86_64 -m 1G -boot n -netdev user,id=mynet0,tftp=/srv/pxe-tftp,bootfile=pxelinux.0 -device e1000,netdev=mynet0

View file

@ -16,6 +16,34 @@ Este servidor aporta un servicio de arranque por red tipo PXE, y no hace colisi
El servidor PXE ofrece a la máquina que arranca un *debian live* a través de [NFS](https://es.wikipedia.org/wiki/Network_File_System). Una vez arrancado, ejecuta el `workbench-script.py` con la configuración remota del servidor PXE. Cuando ha terminado, también guarda en el mismo servidor PXE el snapshot resultante. También lo puede guardar en devicehub si se especifica en la variable `url` de la configuración `settings.ini`. El servidor PXE ofrece a la máquina que arranca un *debian live* a través de [NFS](https://es.wikipedia.org/wiki/Network_File_System). Una vez arrancado, ejecuta el `workbench-script.py` con la configuración remota del servidor PXE. Cuando ha terminado, también guarda en el mismo servidor PXE el snapshot resultante. También lo puede guardar en devicehub si se especifica en la variable `url` de la configuración `settings.ini`.
## Probarlo todo en localhost
Preparar configuración de `.env` tal como:
```
server_ip=10.0.2.2
nfs_allowed_lan=10.0.2.0/24
tftp_path='/srv/pxe-tftp'
nfs_path='/srv/pxe-nfs'
```
Red y host 10.0.2.2? Esta es la forma en que el programa *qemu* hace red en localhost, 10.0.2.2 es la dirección de localhost que saliendo de qemu es traducida como 127.0.0.1
Desplegar servidores TFTP y NFS en el mismo ordenador, para permitir nfs inseguro:
```
DEBUG=true ./install-pxe.sh
```
Los directorios inseguros contienen configuración y snapshots de workbench, nada importante supongo. Aún así, `DEBUG=true` no se recomienda para un entorno de producción para evitar sorpresas.
Y para terminar, probar el cliente PXE con el siguiente comando:
```
make test_pxe
```
## Recursos ## Recursos
El servicio PXE El servicio PXE

View file

@ -8,21 +8,46 @@ set -u
# DEBUG # DEBUG
set -x set -x
detect_user() {
userid="$(id -u)"
# detect non root user without sudo
if [ ! "${userid}" = 0 ] && id ${USER} | grep -qv sudo; then
echo "ERROR: this script needs root or sudo permissions (current user is not part of sudo group)"
exit 1
# detect user with sudo or already on sudo src https://serverfault.com/questions/568627/can-a-program-tell-it-is-being-run-under-sudo/568628#568628
elif [ ! "${userid}" = 0 ] || [ -n "${SUDO_USER}" ]; then
SUDO='sudo'
# jump to current dir where the script is so relative links work
cd "$(dirname "${0}")"
# working directory to build the iso
ISO_PATH="iso"
# detect pure root
elif [ "${userid}" = 0 ]; then
SUDO=''
ISO_PATH="/opt/workbench"
fi
}
install_dependencies() { install_dependencies() {
apt update ${SUDO} apt update
apt install -y wget dnsmasq nfs-kernel-server rsync ${SUDO} apt install -y wget dnsmasq nfs-kernel-server rsync syslinux
} }
backup_file() { backup_file() {
target="${1}" target="${1}"
ts="$(date +'%Y-%m-%d_%H-%M-%S')" ts="$(date +'%Y-%m-%d_%H-%M-%S')"
if [ -f "${target}" ]; then if [ -f "${target}" ]; then
cp -a "${target}" "${target}_bak_${ts}" if ! grep -q 'we should do a backup' "${target}"; then
${SUDO} cp -a "${target}" "${target}-bak_${ts}"
fi
fi fi
} }
install_nfs() { install_nfs() {
backup_file /etc/exports # append live directory, which is expected by the debian live env
mkdir -p "${nfs_path}/live"
mkdir -p "${nfs_path}/snapshots"
# debian live nfs path is readonly, do a trick # debian live nfs path is readonly, do a trick
# to make snapshots subdir readwrite # to make snapshots subdir readwrite
@ -31,16 +56,21 @@ install_nfs() {
mount --bind "${nfs_path}/snapshots" "/snapshots" mount --bind "${nfs_path}/snapshots" "/snapshots"
fi fi
cat > /etc/exports <<END backup_file /etc/exports
${nfs_path} ${nfs_allowed_lan}(rw,sync,no_subtree_check,no_root_squash)
/snapshots ${nfs_allowed_lan}(rw,sync,no_subtree_check,no_root_squash) if [ "${DEBUG:-}" ]; then
nfs_debug=' 127.0.0.1(rw,sync,no_subtree_check,no_root_squash,insecure)'
fi
${SUDO} tee /etc/exports <<END
${script_header}
# we assume that if you remove this line from the file, we should do a backup
${nfs_path} ${nfs_allowed_lan}(rw,sync,no_subtree_check,no_root_squash)${nfs_debug:-}
/snapshots ${nfs_allowed_lan}(rw,sync,no_subtree_check,no_root_squash)${nfs_debug:-}
END END
# reload nfs exports # reload nfs exports
exportfs -vra ${SUDO} exportfs -vra
# append live directory, which is expected by the debian live env
mkdir -p "${nfs_path}/live"
mkdir -p "${nfs_path}/snapshots"
if [ ! -f "${nfs_path}/settings.ini" ]; then if [ ! -f "${nfs_path}/settings.ini" ]; then
if [ -f "settings.ini" ]; then if [ -f "settings.ini" ]; then
@ -55,7 +85,8 @@ END
install_tftp() { install_tftp() {
# from https://wiki.debian.org/PXEBootInstall#Simple_way_-_using_Dnsmasq # from https://wiki.debian.org/PXEBootInstall#Simple_way_-_using_Dnsmasq
cat > /etc/dnsmasq.d/pxe-tftp <<END ${SUDO} tee /etc/dnsmasq.d/pxe-tftp <<END
${script_header}
port=0 port=0
# info: https://wiki.archlinux.org/title/Dnsmasq#Proxy_DHCP # info: https://wiki.archlinux.org/title/Dnsmasq#Proxy_DHCP
dhcp-range=${nfs_allowed_lan%/*},proxy dhcp-range=${nfs_allowed_lan%/*},proxy
@ -78,25 +109,39 @@ install_netboot() {
mkdir -p "${tftp_path}/pxelinux.cfg" mkdir -p "${tftp_path}/pxelinux.cfg"
fi fi
cp -fv "${PXE_DIR}/../iso/staging/live/vmlinuz" "${tftp_path}/" ${SUDO} cp -fv "${PXE_DIR}/../iso/staging/live/vmlinuz" "${tftp_path}/"
cp -fv "${PXE_DIR}/../iso/staging/live/initrd" "${tftp_path}/" ${SUDO} cp -fv "${PXE_DIR}/../iso/staging/live/initrd" "${tftp_path}/"
rsync -av "${PXE_DIR}/../iso/staging/live/filesystem.squashfs" "${nfs_path}/live/"
cat > "${tftp_path}/pxelinux.cfg/default" <<END ${SUDO} cp /usr/lib/syslinux/memdisk "${tftp_path}/"
default wb ${SUDO} cp /usr/lib/syslinux/modules/bios/* "${tftp_path}/"
${SUDO} tee "${tftp_path}/pxelinux.cfg/default" <<END
DEFAULT menu.c32
PROMPT 0
TIMEOUT 50
ONTIMEOUT wb
label wb MENU TITLE PXE Boot Menu
LABEL wb
MENU LABEL Boot Workbench
KERNEL vmlinuz KERNEL vmlinuz
INITRD initrd INITRD initrd
APPEND ip=dhcp netboot=nfs nfsroot=${server_ip}:${nfs_path}/ boot=live text forcepae APPEND ip=dhcp netboot=nfs nfsroot=${server_ip}:${nfs_path}/ boot=live text forcepae
END END
cd - cd -
fi fi
rsync -av "${PXE_DIR}/../iso/staging/live/filesystem.squashfs" "${nfs_path}/live/"
} }
init_config() { init_config() {
# get where the script is # get where the script is
cd "$(dirname "${0}")" cd "$(dirname "${0}")"
# this is what we put in the files we modity
script_header='# configuration done through workbench install-pxe script'
PXE_DIR="$(pwd)" PXE_DIR="$(pwd)"
if [ -f ./.env ]; then if [ -f ./.env ]; then
@ -111,6 +156,7 @@ init_config() {
} }
main() { main() {
detect_user
init_config init_config
install_dependencies install_dependencies
install_tftp install_tftp

View file

@ -1,6 +1,6 @@
[settings] [settings]
url = http://localhost:8000/api/snapshot/ url = http://localhost:8000/api/snapshot/
token = '1234' token = '1234'
path = /run/live/medium path = /mnt
# device = your_device_name # device = your_device_name
# # erase = basic # # erase = basic