This commit adds support to /etc/hostname for substitution
of $ wordlists from {/etc,/run,/usr/lib}/systemd/hostname-wordlist.
The first $ will lookup hostname-wordlist/1, the next
hostname-wordlist/2 and so on.
With that we can do a petname [1] style hostname in systemd, e.g.
below a possible expansion for a hostname template:
$-$-$-???? -> wildly-happy-octopus-92a9
The substitution of words is stable (based on machine-id) but
not persisted, it is picked on every boot via a stable file
offset so the operation is cheap. But this means that if the
wordlist changes the hostname would change. The next commit
will add the pattern to the firstboot.hostname credential which
is persistet with the resolved names to avoid this issue.
This also includes a wordlist from the "petname" project
that can be optionally installed.
Thanks to Dustin Kirkland for this wonderful project.
[1] https://github.com/dustinkirkland/petname
test_wildcard() was never executed: run_testcases() only picks up
functions named testcase_* so this test never ran. This commmit
makes it run and fixes two issues in the test:
1. /etc/hostname is absent in the test image so we need to guard
for that.
2. The pattern check was written as [[ "$P" == "$H" ]] with both
sides quoted, but we need to one side unquoted as otherwise
the comparison will always be false.
Add two testcases to TEST-71-HOSTNAME:
- testcase_tags exercises the new "hostnamectl tags" +/- prefix syntax
(add/remove, idempotency, the no-mixing rule, invalid input), the
AddAndRemoveTags() D-Bus method and the SetTags() Varlink method
(set/add/remove, explicit empty set, current-list basis).
- testcase_varlink_setters exercises the new SetHostname(),
SetStaticHostname(), SetPrettyHostname(), SetIconName(), SetChassis(),
SetDeployment() and SetLocation() Varlink methods, including resetting
values via null and rejection of invalid input.
The CI run is failing in the stop command:
```
[ 4841.936906] TEST-71-HOSTNAME.sh[140]: + stop_hostnamed
[ 4841.936906] TEST-71-HOSTNAME.sh[140]: + systemctl stop systemd-hostnamed.service
[ 4845.959747] TEST-71-HOSTNAME.sh[226]: Job for systemd-hostnamed.service canceled.
[ 4846.013286] systemd[1]: TEST-71-HOSTNAME.service: Main process exited, code=exited, status=1/FAILURE
[ 4846.013792] systemd[1]: TEST-71-HOSTNAME.service: Failed with result 'exit-code'.
[ 4846.021821] systemd[1]: Failed to start TEST-71-HOSTNAME.service - TEST-71-HOSTNAME.
```
This happens when we create the stop job, but while we're waiting for
it to finish, something triggers a start of the unit and we lose to competing
start job.
Hopefully fixes#36089.
It will otherwise interpret characters such as '+' as if they
were regex, and break matching.
For example TEST-71-HOSTNAME started failing when
uname -r started including a '+':
FAIL: 'Kernel: Linux 6.12.33+deb13-amd64' not found in:
Static hostname: host
Icon name: computer-vm
Chassis: vm 🖴
Machine ID: e6471c1f95ab49098827498ed816cdf7
Boot ID: 231da987f64d4af59f2076fbb638c611
Virtualization: kvm
Operating System: Debian GNU/Linux 13 (trixie)
Kernel: Linux 6.12.33+deb13-amd64
Architecture: x86-64
Some configuration files that need updates are directly under in /etc. To
update them atomically, we need write access to /etc. For Ubuntu Core this is
an issue as /etc is not writable. Only a selection of subdirectories can be
writable. The general solution is symlinks or bind mounts to writable places.
But for atomic writes in /etc, that does not work. So Ubuntu has had a patch
for that that did not age well.
Instead we would like to introduce some environment variables for alternate
paths.
* SYSTEMD_ETC_HOSTNAME: /etc/hostname
* SYSTEMD_ETC_MACHINE_INFO: /etc/machine-info
* SYSTEMD_ETC_LOCALTIME: /etc/localtime
* SYSTEMD_ETC_LOCALE_CONF: /etc/locale.conf
* SYSTEMD_ETC_VCONSOLE_CONF: /etc/vconsole.conf
* SYSTEMD_ETC_ADJTIME: /etc/adjtime
While it is for now expected that there is a symlink from the standard, we
still try to read them from that alternate path. This is important for
`/etc/localtime`, which is a symlink, so we cannot have an indirect symlink or
bind mount for it.
Since machine-id is typically written only once and not updated. This commit
does not cover it. An initrd can properly create it and bind mount it.
Having these named differently than the test itself mostly creates
unecessary confusion and makes writing logic against the tests harder
so let's rename the testsuite-xx units and scripts to just use the
test name itself.