Observations, Musings & Gadgets

...things I find interesting

Determining disk device in Ubuntu preseed

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]

The 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.

tagged as ubuntu, preseed