It’s easy and obvious to add new files with a driver update (DUD). But what if you need to remove some files? Or, related: can you replace some read-only file by a writable copy?
Let’s for this article assume you want to modify the Xorg configuration. Say,
/usr/share/X11/xorg.conf.d/10-evdev.conf
troubles you.
The direct way would be to write an update.pre
script than removes the file and include this into a DUD.
update.pre
is run right after the DUD has updated the files in the installation system.
For example:
echo \ rm /usr/share/X11/xorg.conf.d/10-evdev.conf \ > update.pre mkdud --create test1.dud --dist tw --name "remove 10-evdev.conf" update.pre
But when we try test1.dud
we run into this:
Driver Update: remove 10-evdev.conf Driver Updates added: remove 10-evdev.conf [...] rm: cannot remove '/usr/share/X11/xorg.conf.d/10-evdev.conf': Read-only file system
So, we see the catch: much of the installation system resides on a read-only file system! You can’t just go and modify things.
But how does the driver update process manage to add new files to the installation system then? It does so by restructuring the file system using symlinks. In the process all directories that need to be modified are replaced by writable copies.
In other words: if you include the file you want to remove in the DUD – you will be able to remove it. It’s actually sufficient to include the directory the file resides in to make this work.
So, let’s try this:
mkdir -p /tmp/dud/usr/share/X11/xorg.conf.d echo \ "rm /usr/share/X11/xorg.conf.d/10-evdev.conf" \ > update.pre mkdud --create test2.dud --dist tw --name "remove 10-evdev.conf" update.pre /tmp/dud
Now we don’t get any error applying test2.dud
and when we login to the installation system, we see:
console:vm9732:/ # ls -l /usr/share/X11/xorg.conf.d total 0 console:vm9732:/ #
Tip
For easy testing a DUD, boot the machine with
startshell=1 sshd=1 password=*** dud=<URL>
startshell=1
wi ll stop the installation workflow after the installation system has been fully prepared just beforeYaST
will be started.sshd=1
will start an SSH daemon and you’ll be able to connect to the machine and look around.
A similar trick can be used to make files writable (watch out for correct shell quoting):
mkdir -p /tmp/dud/usr/share/X11/xorg.conf.d echo \ cp --remove-destination '$(readlink -f /usr/share/X11/xorg.conf.d/10-evdev.conf)' \ /usr/share/X11/xorg.conf.d/10-evdev.conf \ > update.pre mkdud --create test3.dud --dist tw --name "make 10-evdev.conf writable" update.pre /tmp/dud
We can verify the result:
console:vm9732:/ # ls -l /usr/share/X11/xorg.conf.d total 4 -rw-r--r-- 1 root root 1099 Apr 24 13:06 10-evdev.conf console:vm9732:/ #
The file is now writable.
]]>A driver update (DUD) can of course update a single driver. But if that’s not enough and you need a whole new kernel to run an installation?
There are two parts to solve:
We’ll need two tools for this (both available in Tumbleweed or here: mksusecd and mkdud).
For this it’s important to know which kernel packages you’ll actually need. Typically it will be kernel-default
and kernel-firmware
. But older SUSE distributions (SLE 11 comes to mind) had the kernel packages split into kernel-default
and kernel-default-base
– you’ll need them both.
To make things confusing, modern SUSE distributions also have kernel-default-base
– but it’s an alternative to kernel-default
. In this case we don’t need it.
If unsure, check kernel-default
. If it contains the actual kernel (e.g. /boot/vmlinuz
) then you don’t need kernel-default-base
.
On some architectures modules are also taken from xen-kmp-default
. If that’s important for you, you can add this package to the kernel list as well.
In fact you can add any number of kernel packages or kmps you like.
In the past, sometimes a different kernel flavor was used. For example PowerPC had kernel-ppc64
for a while. Simply use the flavor you need.
It’s a good idea to gather all the kernel rpms into a single directory for easier use:
> mkdir k > cp kernel-default.rpm kernel-firmware.rpm k > cp kernel-default-base.rpm k # only if needed # add any kernel-related rpms you need
Then, take your SUSE installation iso and run
> mksusecd --create new.iso \ --kernel k/* -- \ original_dvd1.iso
Note that the --kernel
option accepts a variable number of arguments, so you have to add an isolated --
to terminate the argument list properly.
The output could look like this:
> mksusecd --create new.iso \ --kernel k/* -- \ SLES-11-SP4-DVD-ppc64-GM-DVD1.iso kernel version: 3.0.101-63-ppc64 --> 3.0.101-94-ppc64 CHRP bootable (ppc64) building: 100% calculating sha1...
The command above will actually get the list of required modules from the old installation iso. If you are missing some driver or the new kernel comes with some additional driver, the module will not be added to the new iso.
But there’s the --modules
option. It will add the listed modules together with any implicitly required modules via module dependencies.
For example, let’s add the airport
wifi-module to our PowerPC iso:
> mksusecd --create new.iso \ --kernel k/* \ --modules airport -- \ SLES-11-SP4-DVD-ppc64-GM-DVD1.iso kernel version: 3.0.101-63-ppc64 --> 3.0.101-94-ppc64 kernel modules added: airport, cfg80211, orinoco CHRP bootable (ppc64) building: 100% calculating sha1...
As you can see, it automatically adds orinoco
and cfg80211
as well.
This is relatively simple. A driver update can do this:
> mkdud --create foo.dud \ --dist sle11 \ --install repo \ k/*
This creates a driver update for SLE 11 (which also applies to SP4) and the kernel rpms are installed via an auto-generated add-on repo (--install repo
).
Now we have the driver update that installs our kernel packages. But how do we use it?
We integrate it into our iso above!
> mksusecd --create new.iso \ --initrd foo.dud \ --kernel k/* -- \ SLES-11-SP4-DVD-ppc64-GM-DVD1.iso
mksusecd
has an --initrd
option that directly accepts driver updates and integrates them into the iso.
Maybe you just want to test this new kernel or sometimes need the old one and sometimes the new one. Can you make an installation iso that lets you choose the kernel?
Oh yes!
> mksusecd --create new.iso \ --add-entry 3.0.101-94 \ --initrd foo.dud \ --kernel k/* -- \ SLES-11-SP4-DVD-ppc64-GM-DVD1.iso
This does not replace the old kernel but adds a new boot entry Installation - 3.0.101-94
.
So you can install with old or the new kernel.
]]>Yesterday a colleague asked me if it would be possible to apply a driver update (DUD) to the rescue system. He wanted to use a new btrfsprogs
package.
My immediate reaction was: no, you can’t do it. But then, there’s no technical reason why it shouldn’t be possible – it actually nearly works. The updates are downloaded as usual – just not applied to the rescue system.
So I thought: “Why not make a driver update so driver updates work also for the rescue system?”
Here’s how I did it.
First, let’s find out how driver updates are usually applied. The code is here:
https://github.com/openSUSE/installation-images/blob/master/data/root/etc/inst_setup#L84-L87
We need just these three lines:
for i in /update/[0-9]*/inst-sys ; do [ -d "$i" ] && adddir "$i" / done
linuxrc
downloads the driver updates and stores them in an /update
directory. One (numbered) subdirectory for each update.
It obviously uses some adddir
script. So we’ll need it as well. Luckily, it’s not far away:
https://github.com/openSUSE/installation-images/blob/master/data/root/etc/adddir
Next, we’ll have to find the spot where the rescue system is set up. It’s done in this script:
https://github.com/openSUSE/installation-images/blob/master/data/initrd/scripts/prepare_rescue
Let’s do some copy-and-paste programming and insert the above code near the end of the script. It then might look like this
# driver update: add files to rescue system if [ -d /mounts/initrd/update ] ; then cp -r /mounts/initrd/update / for i in /update/[0-9]*/inst-sys ; do [ -d "$i" ] && /mounts/initrd/scripts/adddir "$i" / done fi
Some notes:
prepare_rescue
is run as the last thing before we exec to init
. So everything is already in place, the left-over files from initrd are mounted at /mounts/initrd
and will be removed at the end of the script.adddir
script available at /scripts/adddir
by our driver update (see below).Now let’s create the driver update:
mkdud --create dud_for_rescue.dud \ --dist tw --dist leap42.1 --dist leap42.2 --dist sle12 \ --name 'Apply DUD also to rescue system' \ --exec 'cp adddir prepare_rescue /scripts' \ adddir prepare_rescue
Here’s what this call does, line-by-line:
adddir
and our modified prepare_rescue
scriptHere is the result: dud_for_rescue.dud.
Now, back to the original problem: how to use this to update a package in the rescue system? That’s easy:
mkdud --create new_btrfs.dud \ --dist sle12 \ dud_for_rescue.dud btrfsprogs.rpm
creates a driver update (for SLE12) that updates btrfsprogs
also in the rescue system.