Our old ISO used the first drive (sda
) as the only option when installing the system. Sometimes we were asked to install NetEye on a different drive, so as a workaround we suggested properly sorting RAID arrays in the controller, in order to put the installation drive first on the list.
Even if suboptimal, this allowed us to indirectly select the installation disk. But with the spread of NVME drives and new controllers (like Dell BOSS), we can’t assume any longer that an sd*
will be present, so we decided to add a drive selector to our ISO.
There is no built-in feature in the kickstart file to achieve this, but we can add shell scripts to it.
First we implemented a custom script that allows us to list and select drives using the powerful lsblk
command which also lets us select which information to show:
lsblk -nd --output NAME,VENDOR,MODEL,SIZE | grep -e vd -e sd -e nvme -e hd
In this example we print the name of the drive (e.g. sda/sdb/nvme0 etc…), the manufacturer, model and size in order to allow the user to properly identify the drive to be used, and filtering out unwanted types: we don’t want for example to show CDROMs, RAM disks etc…
Of course we added some nice fail-safe mechanisms to prevent user errors, show banners and ask for confirmation. So in the end the script looks like this:
echo "
_ _ _ ______ _____ _ _ _ _ _
| \ | | | | | ____| |_ _| | | | | | | | (_)
| \| | ___| |_| |__ _ _ ___ | | _ __ ___| |_ __ _| | | __ _| |_ _ ___ _ __
| |/ _ \ __| __|| | | |/ _ \ | | | _ \/ __| __/ _ | | |/ _ | __| |/ _ \| _ \'
| |\ | __/ |_| |___| |_| | __/ _| |_| | | \__ \ || (_| | | | (_| | |_| | (_) | | | |
|_| \_|\___|\__|______\__, |\___| |_____|_| |_|___/\__\__,_|_|_|\__,_|\__|_|\___/|_| |_|
__/ |
|___/
"
echo
echo
VALID=false
DRIVES_FILE="/tmp/drives"
while [ "$VALID" = false ]; do
lsblk -nd --output NAME,VENDOR,MODEL,SIZE | grep -e vd -e sd -e nvme -e hd > ${DRIVES_FILE}
i=1
echo " Please select one of the following drives to install NetEye:"
while read DRIVE; do
echo " ${i} -> ${DRIVE}"
i=$((i+1))
done < ${DRIVES_FILE}
read -p " drive: " CHOICE
if [ ${CHOICE} -gt 0 ] && [ ${CHOICE} -lt ${i} ]; then
SELECTED_DRIVE=$(sed -n ${CHOICE}p ${DRIVES_FILE} | awk '{print $1;}')
echo " Selected disk: ${SELECTED_DRIVE}"
read -p " Are you sure? (y/N) " CONFIRMATION
echo
if [[ ${CONFIRMATION} =~ ^[Yy]$ ]]; then
VALID=true
fi
else
echo " Invalid drive!"
fi
done
Nice, but how do we pass the selected drive to the kickstart file itself? The kickstart file doesn’t allow for the use of user-defined variables, but it does let us write files! So we calculate the desired directives to be included and write them to temporary files:
echo "ignoredisk --only-use=${SELECTED_DRIVE}" > /tmp/ignoredisk
echo "bootloader --append=\" crashkernel=auto\" --location=mbr --boot-drive=${SELECTED_DRIVE}" > /tmp/bootloader
All these parts must be done inside a %pre
section, so that the user is prompted and the files are written before the actual installation, and then outside the %pre
we can include those files:
%include /tmp/ignoredisk
%include /tmp/bootloader
Now we have our beautiful selector and a way to include the desired directives. So we build the ISO, boot it and… nothing was shown and the ISO was left hanging!
That’s because kickstart uses tty1
to perform the installation. But the user can’t interact with that, so we need to switch consoles to tty6
to allow the user to perform the selection, and then switch back to tty1
to continue the installation.
So in the end our kickstart file is structured like this:
%pre
# Switch to tty6 so the user can prompt
exec < /dev/tty6 > /dev/tty6 2> /dev/tty6
chvt 6
# Our beautiful script
# Switch back to the original terminal
chvt 1
exec < /dev/tty1 > /dev/tty1 2> /dev/tty1
%end
# Include the expected results
%include /tmp/ignoredisk
%include /tmp/bootloader
# Do the partitioning and other stuff (we included the ignoredisk --only-use=... so everything will be done on the selected drive)
%packages
# Install NetEye packages
%end
%post
# Do stuff on the installed system
%end
And with this implementation we have a simple way to perform an interactive installation.
This approach doesn’t just apply to disk selector, but in general you can implement whatever you want and generate part of the kickstart based on user input: for example select dnf groups, change settings, etc…
We used a similar solution to add open-vm-tools
only when installing on virtual machines:
if dmidecode | grep -i vmware > /dev/null ; then
echo "open-vm-tools" > /tmp/vmwaretools
else
echo "" > /tmp/vmwaretools
fi
In this case there is no interaction with the user, but we still use a shell script + temporary file + %include to handle different behaviors according to the machine we’re running on.
Did you find this article interesting? Are you an “under the hood” kind of person? We’re really big on automation and we’re always looking for people in a similar vein to fill roles like this one as well as other roles here at Würth Phoenix.