• David Johnson's avatar
    Use the last resort systemd swap strategy: wrap the systemd-fstab-generator. · 828e7acd
    David Johnson authored
    As noted in a previous commit, systemd generators run at boot, with the
    rootfs mounted read-only, prior to systemd reading any unit files on
    disk.  The systemd-fstab-generator reads /etc/fstab and generates units
    for any devices in there, including swap devices.  Thus, the only way to
    ensure our swap device fixing happens correctly (and we have to do this
    in case the image was loaded from an old MFS that might write a swap
    device with /dev/hda or whatever into /etc/fstab), and doesn't race with
    systemd, is to preempt it.
    
    So now our generator runs the systemd generator each boot, but it
    post-processes the auto-generated unit files, removing them if any of
    those devices was 1) an Emulab auto-generated swap device, and 2) it
    does not exist.
    
    Moreover, if there is *no* swap device in /etc/fstab, we hunt down the
    canonical Emulab swap partition on the root disk, and mkswap it, and
    generate a unit for it.  Of course, we don't use the system template (it
    is an m4 file in the src dist, so we can't), but hopefully the template
    won't change much --- and it's basic.
    
    We now only mkswap devices if they don't appear as swap devs via blkid.
    
    To clean up old Emulab systemd images, do these steps:
    
      $ systemctl disable emulab-fstab-fixup.service
      $ make client-install
      $ rm -f /usr/local/etc/emulab/initscripts/emulab-systemd-swaps
    
    I think that will do it.  Worked for me on Ubuntu 16 and Centos 7.
    
    Here's the comments from the generator for posterity:
    
      This is a systemd generator that wraps systemd-fstab-generator.
    
      First, we always run the system generator; and any swap file units
      it generates are modified to contain a
      Before=emulab-fstab.fixup.service dependency to ensure the fixup
      script never races with legitimate systemd unit targets.
    
      If it has already run on an Emulab node (and if the second-stage
      fixup script (emulab-fstab-fixup.service) has also run), we don't
      run it again; we just run the system fstab generator directly,
      modify the generated swap unit files to run before the fixup script.
    
      Otherwise, on first boot of an Emulab image, we run the system
      generator and let it generate swap units for any swap devices that
      were in /etc/fstab.  We then check all the auto-Emulab-added swap
      device entries in /etc/fstab, and if that device does not exist, we
      remove the auto-generated unit files/symlinks that correspond to it
      (they are in $1).  We cannot edit /etc/fstab ourselves because we're
      run prior to remount-/-rw; so we make a copy of it in /run/emulab
      and move the copy to /etc/fstab in emulab-fstab-fixup.service ---
      the second part of our solution (the fixup service).
    
      NB: we do not remove user-added swap devices, even if they are
      invalid!
    
      We check to see if each auto-Emulab-added swap device that was in
      /etc/fstab is currently a valid swap device (i.e., that it shows up
      via blkid with a TYPE="swap").  If it is valid, we *do not* run
      mkswap to create it!  If it is not currently a valid swap device,
      but if the partition is marked as a Linux swap partition, we will
      run mkswap on it to ensure it is valid by the time systemd runs
      swapon on it.  If we *did* plan to run mkswap, that can be prevented
      by creating the
      /etc/emulab/emulab_systemd_fstab_generator_never_mkswap file.  This
      gives the user the ability to create a disk image where swap
      partitions are not created/wiped on first boot of the image.  I
      can't see a use case for this, but it's easy to do.
    
      If there is a swap partition on the device containing the root
      partition, and if it is not already in /etc/fstab, we try to add a
      unit ourselves for that swap partition.  We do it in the new style,
      too, by using its UUID, in this case.
    
      When scanning /etc/fstab to find auto-Emulab-added devices, we look
      for a comment above a line containing a swap device, and the comment
      must match the regexp /^#.*the following.* added by / .  Then if the
      line below the comment refers to an invalid swap device, we remove
      the unit files that correspond to the device.  Otherwise
    828e7acd
Name
Last commit
Last update
account Loading commit data...
apache Loading commit data...
apt Loading commit data...
assign Loading commit data...
autoconf Loading commit data...
autofs Loading commit data...
backend Loading commit data...
bugdb Loading commit data...
cdrom Loading commit data...
clientside Loading commit data...
collab Loading commit data...
daikon Loading commit data...
db Loading commit data...
delay Loading commit data...
dhcpd Loading commit data...
discvr Loading commit data...
doc Loading commit data...
event Loading commit data...
firewall Loading commit data...
flash Loading commit data...
fwrules Loading commit data...
hw_config Loading commit data...
hyperviewer Loading commit data...
image-test Loading commit data...
install Loading commit data...
ipod Loading commit data...
mobile Loading commit data...
mote Loading commit data...
named Loading commit data...
node_usage Loading commit data...
ntpd Loading commit data...
os Loading commit data...
patches Loading commit data...
pelab Loading commit data...
protogeni Loading commit data...
pxe Loading commit data...
rc.d Loading commit data...
robots Loading commit data...
rpms Loading commit data...
security Loading commit data...
sensors Loading commit data...
sql Loading commit data...
ssl Loading commit data...
sysadmin Loading commit data...
tbsetup Loading commit data...
testsuite Loading commit data...
tip Loading commit data...
tmcd Loading commit data...
tools Loading commit data...
utils Loading commit data...
vis Loading commit data...
wiki Loading commit data...
www Loading commit data...
xmlrpc Loading commit data...
.gitattributes Loading commit data...
.gitignore Loading commit data...
.gitmodules Loading commit data...
.loc-ignore Loading commit data...
AGPL-COPYING Loading commit data...
GNUmakefile.in Loading commit data...
GNUmakerules Loading commit data...
GPL-COPYING Loading commit data...
LGPL-COPYING Loading commit data...
MOVED-TO-WIKI Loading commit data...
Makeconf.in Loading commit data...
README Loading commit data...
TODO Loading commit data...
TODO.plab Loading commit data...
VERSION Loading commit data...
WEBtemplate.in Loading commit data...
config.h.in Loading commit data...
configure Loading commit data...
configure.ac Loading commit data...
defs-apt Loading commit data...
defs-cloudlab-clemson Loading commit data...
defs-cloudlab-utah Loading commit data...
defs-cloudlab-wisc Loading commit data...
defs-default Loading commit data...
defs-duerig-emulab Loading commit data...
defs-elabinelab Loading commit data...
defs-example Loading commit data...
defs-gtw-emulab Loading commit data...
defs-johnsond-emulab Loading commit data...
defs-kwebb-apt Loading commit data...
defs-kwebb-cloudlab Loading commit data...
defs-kwebb-emulab Loading commit data...
defs-mike-emulab Loading commit data...
defs-ricci-emulab Loading commit data...
defs-stoller-apt Loading commit data...
defs-stoller-emulab Loading commit data...
defs-stoller-home Loading commit data...
defs-stoller-lbsdb Loading commit data...
defs-uky Loading commit data...
defs-utahclient Loading commit data...
defs-wbsun-emulab Loading commit data...
defs-wide Loading commit data...
pnet-favicon.ico Loading commit data...