Our setup consists of 18 computers, all of those are used for students doing exercises with. At the end of each day most computers need to be reseted but because we don't know if a change has taken place we have to reset all. We're doing this manually because we don't want to (altough could be done easily) reinstall only computers when it's needed (those which were used). A reset lasts about 25-35 minutes and covers about 3-6gb/day disk io using xfs_restore. So why not use the real '/' mounted only read only? Doing so requires a very special setup which is usually used for live CDs like Knoppix, Gentoo or SuSE. Just to name some. This page will cover most needed setup steps for UNIONFS SUPPORT using gentoo linux and a read only '/' (root filesystem) The 'mount' command will show something like this, using unionfs: pc2a ~ # mount /dev/hda3 on / type xfs (rw,noatime) /dev/hda3 on /mnt/readonlyfs type xfs (ro,noatime) /dev/hda4 on /mnt/difffs type ext2 (rw) proc on /proc type proc (rw) sysfs on /sys type sysfs (rw,nosuid,nodev,noexec) udev on /dev type tmpfs (rw,nosuid) devpts on /dev/pts type devpts (rw,nosuid,noexec) none on /tmp type tmpfs (rw,mode=1777,size=500M) none on /dev/shm type tmpfs (rw) usbfs on /proc/bus/usb type usbfs (rw,noexec,nosuid,devmode=0664,devgid=85) binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,noexec,nosuid,nodev)
RequirementsIn our setup 'pxeboot was used which will invoke a chain of actions: pxe->get kernel+linuxrc->dhcp->exec linuxrc->pivot_root->exec chroot->init So obviously UNIONFS had to be integrated into this chain. Also you need:
linuxrc (pxe boot)Most important parts are marked bold but also have a look at the function create_union() which is most important. #!/bin/bash export PATH="/bin:/sbin:/usr/bin:/usr/sbin" #. /functions mount -t proc proc /proc CMDLINE=`cat /proc/cmdline` sysctl -w kernel.panic=10 #menu.lst panic=10 is besser srvipaddr="192.168.0.1" srvaddr="http://${srvipaddr}:8008" function init_disk { test "$(sfdisk -s /dev/hda)" -gt 20000000 || exec bash hdparm -c 1 -d 1 /dev/hda sfdisk /dev/hda -uM << EOT ,1000,83 ,2000,82 ,9000,83 ,11000,83 EOT mkfs.ext2 /dev/hda1 mkswap /dev/hda2 mkfs.xfs -f /dev/hda3 mkfs.ext2 /dev/hda4 } function mount_newroot { mount -t xfs -o noatime /dev/hda3 /mnt/new } function restore_system { init_disk || exec bash mount_newroot || exec bash curl ${srvaddr}/images/default.xfsdump | xfsrestore -J - /mnt/new curl ${srvaddr}/images/default.xfsdump.info > /mnt/new/root/Desktop/image-info.txt echo `uname -a` >> /mnt/new/root/Desktop/image-info.txt } function post_restore { wget -O - ${srvaddr}/root.tar | tar -xf - -C /mnt/new wget ${srvaddr}/shutdownandreinstall -O /mnt/new/root/.shutdownandreinstall chmod 0755 /mnt/new/root/.shutdownandreinstall wget -O - ${srvaddr}/ssh_config.cgi > /mnt/new/etc/ssh/ssh_config } function create_union { #originally we had #mount -t xfs -o noatime /dev/hda3 /mnt/new # proc unmounten sync # our union is called new insmod /unionfs.ko #umount /mnt/new || exec bash mkdir -p /mnt/readonlyfs if [ $COMMAND -eq 7 ]; then # strange: terminal logins don't work anymore using xfs as rw overlay (instead of ext3) #mkfs.xfs -f /dev/hda4 mkfs.ext2 /dev/hda4 fi mount -t xfs -o ro,noatime /dev/hda3 /mnt/readonlyfs mkdir -p /mnt/difffs mount /dev/hda4 /mnt/difffs mount -t unionfs -o dirs=/mnt/difffs=rw:/mnt/readonlyfs=ro none /mnt/new } MAC="$(echo "$BOOTIF" | sed -e 's/^[^-]*-//' -e 's/-/:/g')" nameif lab "${MAC}" udhcpc -f -q -s /udhcpc.script -i lab if [ -f /etc/ ]; then echo "error /etc does not exist" exit fi curl ${srvaddr}/mac_config.cgi | sed 's/eth/nix_eth/' > /etc/mactab nameif -c /etc/mactab curl ${srvaddr}/mac_config.cgi > /etc/mactab nameif -c /etc/mactab # steht ev. auch in der /etc/conf.d/net #ip link show lab > /dev/null 2>&1 || ( # ip link set eth0 name lab # ip link set eth1 name eth0 # ip link set eth2 name eth1 # ip link set eth3 name eth2 #) BOOTDEFAULT="$(wget -O - ${srvaddr}/bootmode.cgi)" cat << EOM ================================================================================ please use this from now on 6: USE THIS - (NORMAL BOOT) 7: USE THIS - (NORMAL BOOT) + (RESET of changes) ..................... using new UNIONFS technology ================================================================================ below - DEPRECATED - DEPRECATED - DEPRECATED - DEPRECATED - below 1: DO NOT USE ANYMORE - boot from hard disk 2: DO NOT USE ANYMORE - boot from hard disk after pre-boot reconfiguration 3: DO NOT USE ANYMORE - install new system from server 4: DO NOT USE ANYMORE - install new system from server and SHUT DOWN 5: install new system from server WITHOUT post-boot reconfiguration 8: spwan a shell >>>>> $BOOTDEFAULT in 30s <<<<< EOM read -n1 -t30 COMMAND || COMMAND=$BOOTDEFAULT echo case $COMMAND in 1) echo "STARTING LOCAL SYSTEM, NO INSTALLATION is performed" mount_newroot || exec bash ;; 2) echo "STARTING LOCAL SYSTEM WITH PRE-BOOT RECONFIGURATION" mount_newroot && post_restore || exec bash echo 1 | nc ${srvipaddr} 9999 > /dev/null 2>&1 ;; 3) echo "STARTING INSTALLATION" restore_system && \ post_restore && \ echo 1 | nc ${srvipaddr} 9999 > /dev/null 2>&1 ;; 4) echo "STARTING INSTALLATION (shutdown)" restore_system && \ post_restore && \ echo 1 | nc ${srvipaddr} 9999 > /dev/null 2>&1 #touch /mnt/new/SHUTDOWN sync umount /mnt/new || exec bash sync exec poweroff -f ;; 5) echo "STARTING INSTALLATION without reconfiguration" restore_system && \ echo 1 | ${srvipaddr} 9999 > /dev/null 2>&1 ;; 6) echo "UNIONFS extension (working, not stress-tested yet)" create_union && \ echo 1 | ${srvipaddr} 9999 > /dev/null 2>&1 ;; 7) echo "UNIONFS+RESET extension (working, not stress-tested yet)" create_union && \ echo 1 | ${srvipaddr} 9999 > /dev/null 2>&1 ;; *) exec bash ;; esac sync sync # deconfigure network ip addr flush dev lab ip link set lab down cd /mnt/new mkdir initrd umount /proc pivot_root . initrd if [ $COMMAND -gt 5 ]; then echo "Doing funny stuff" mkdir -p /mnt/difffs mkdir -p /mnt/readonlyfs mount --move /initrd/mnt/readonlyfs /mnt/readonlyfs mount --move /initrd/mnt/difffs /mnt/difffs mount -t proc none /proc cat /proc/mounts > /etc/mtab umount /proc fi #/bin/bash exec chroot . /bin/sh <<- EOF >dev/console 2>&1 umount /initrd rm -rf initrd blockdev --flushbufs /dev/ram0 exec /sbin/init ${CMDLINE} EOF what other files needed to be changed?I had two problems which are quite strange at first but after some hours.... halt.sh script/etc/init.d/halt.sh to shutdown the / filesystem cleanly which was a real mess to figure out but basically look for the line with: /bin/fuser -s -k -9 -m "${x}"
which I changed to: /bin/fuser -s -m "${x}"
Now the root filesystem can be unmounted also using unionfs. WARNING: THIS IS A HACK AND OBVIOUSLY NOT DONE CORRECTLY SO PLEASE TRY TO FIGURE THIS OUT YOURSELF! xfs vs ext3We were using this setup first: * xfs on / (hda3) read only realroot * xfs on / (hda4) read/write diffroot (here the changes are written to) But for some unknown reason some scripts didn't work as expected as for example we were not able to login on a real terminal (that means not using X's virtual terminals). We solved this problem using ext3 on /dev/hda4 instead of xfs. /etc/fstabWe didn't change anyting in /etc/fstab # <fs> <mountpoint> <type> <opts> <dump/pass> # NOTE: If your BOOT partition is ReiserFS, add the notail option to opts. /dev/hda1 /boot ext2 noauto,noatime 1 2 /dev/hda3 / xfs noatime 0 1 /dev/hda2 none swap sw 0 0 # oh, do we need this entry without a CDROM_DRIVE? #/dev/cdrom /mnt/cdrom auto noauto,ro,user 0 0 /dev/hdb7 /home xfs noatime,noauto #/dev/cdroms/cdrom0 /mnt/cdrom iso9660 noauto,ro 0 0 #/dev/fd0 /mnt/floppy auto noauto 0 0 none /tmp tmpfs mode=1777,size=500M 0 0 # NOTE: The next line is critical for boot! none /proc proc defaults 0 0 # glibc 2.2 and above expects tmpfs to be mounted at /dev/shm for # POSIX shared memory (shm_open, shm_unlink). # (tmpfs is a dynamically expandable/shrinkable ramdisk, and will # use almost no memory if not populated with files) # Adding the following line to /etc/fstab should take care of this: none /dev/shm tmpfs defaults 0 0 problems using this setup
advantages of this setupIt's not only much faster in regard of system reset but also gives you the benefit of being able to track changes as they happen because of 'Copy on write' (aka COW). All files which changed can be found in /initrd/mnt/difffs in my setup and all files which are on / can be found in /initrd/mnt/readonlyfs. Another interesting thing is to use diff on those files like: pc2a ~ # diff /mnt/readonlyfs/etc/fstab /mnt/difffs/etc/fstab 7c7,8 < /dev/cdrom /mnt/cdrom auto noauto,ro,user 0 0 --- > # oh, do we need this entry without a CDROM_DRIVE? > #/dev/cdrom /mnt/cdrom auto noauto,ro,user 0 0 links & futher reading
thanks
![]() |