When we switched to using Ubuntu as our standard distribution for Linux desktops, one of the hardest things was getting to grips with preseeding.
Especially the disk partitioning.
Don't get me wrong. There are things about preseeding that are really good, like being able to preset options with debconf, but disk recipies are a bit of a black art.
So imagine the wailing and gnashing of teeth when, with the rise of SSD drives in desktop machines,
/dev/sda is no longer your primary drive, and your carefully crafted pressed files fail to partition the disk.
One thing we most definitelty do NOT want, are hardware specific preseed files. The way we think it should work, is that you walk up to a machine, boot it from the network and choose a boot configuration based upon the machine's role, not its hardware. We have a PXE menu with about six or seven various configurations to choose from. Those different configurations (which are basically passing parameters to the preseed file - which is actually a python wsgi script that pulls together jinja templates to make a preseed file) specify whether or not the machine is a lab, staff or graduate machine, which software set to install, which printqueues to configure, etc. We should not need to know if the machine has an SSD (or what graphics card it has) to choose a correct preseed file. We want our installs to be as fire-and-forget as possible.
Here is where we can use some of the power inherent in preseeding.
We are going to use an
early_command directive to determine the device name for the primary disk. Early commands are run before a particular stage of the install. In our case, we use an early command for the partitioning.
d-i partman/early_command string
This specifies a command to execute before the partitioning stage of the install. But what can we do to find out the device name for the primary disk? How about this.
~# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT nvme0n1 259:0 0 477G 0 disk +-nvme0n1p1 259:1 0 237M 0 part /boot +-nvme0n1p2 259:2 0 93.1G 0 part / +-nvme0n1p3 259:3 0 381.2G 0 part /Scratch +-nvme0n1p4 259:4 0 2.4G 0 part [SWAP]
lsblk command reads the sysfs system to show information about the block devices attached to the system. Reading the man page for
lsblk reveals some useful flags that can help us out. We can specify no header, list format, and sizes reported in bytes.
~# lsblk -lbn nvme0n1 259:0 0 512110190592 0 disk nvme0n1p1 259:1 0 248512512 0 part /boot nvme0n1p2 259:2 0 99999547392 0 part / nvme0n1p3 259:3 0 409300107264 0 part /Scratch nvme0n1p4 259:4 0 2560622592 0 part [SWAP]
There are several things we could do here. From the man page we see that we can also control the output and specify the output columns and their order. So let's just return the size and device name so we can sort on size.
~# lsblk -lbn --output SIZE,NAME 512110190592 nvme0n1 248512512 nvme0n1p1 99999547392 nvme0n1p2 409300107264 nvme0n1p3 2560622592 nvme0n1p4
Almost there. If we sort by size and then grab the biggest, we can
cut the last field to give us our device name.
~# lsblk -lbn --output SIZE,NAME | sort -n | tail -n 1 | cut -d" " -f2 nvme0n1
Now we can use the output from the
lsblk command to set the diskname.
d-i partman/early_command string \ PRIMARYDISK=$(lsblk -lbn --output SIZE,NAME | sort -n | tail -n 1 | cut -d" " -f2);\ debconf-set partman-auto/disk "$PRIMARYDISK";
Of course, this assumes that you want the largest disk to be your primary disk. For us, this is fine, as all our desktops only have single disks.
Your mileage may vary.