2

I am running Linux 4.14.149 built with Yocto Zeus (3.0.0). I am running a read only filesystem, and recently found an issue where my UID (/etc/machine-id)was getting changed every boot (a result of this question - https://superuser.com/questions/1668481/dhcpd-doesnt-issue-the-same-lease-after-reboot ).

I am trying to make that file a link to the user-data partition so it will persist across reboots. I have tried making the link as part of a base-files_%.bbappend which is the way I made the link for the hostname (which works). This is the contents of that file (/var/local is our user data partition with is mounted RW in the init script):

FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"

hostname = ""
machine-id = ""

do_install_append() {
    ln -sfn /var/local/etc/hostname ${D}/${sysconfdir}/hostname
    ln -sfn /var/local/etc/machine-id ${D}/${sysconfdir}/machine-id
}

But I am seeing the following error when I tried to build that:

Exception: bb.process.ExecutionError: Execution of '/home/gen-ccm-root/workdir/tools/poky/build-dev/tmp/work/mi_nhep-poky-linux-gnueabi/mi-dev/1.0-r0/temp/run.read_only_rootfs_hook.50286' failed with exit code 1:
touch: cannot touch '/home/gen-ccm-root/workdir/tools/poky/build-dev/tmp/work/mi_nhep-poky-linux-gnueabi/mi-dev/1.0-r0/rootfs/etc/machine-id': No such file or directory
WARNING: exit code 1 from a shell command.

It turns out there are two things that touch that file; the rootfs-postcommands.bbclass and the systemctl python script (found in meta/recipes-core/systemd/systemd-systemctl/systemctl), the former of which (I think) is causing the error. It is failing in the do_rootfs step.

What is the best way to create this link? If there is a choice, I would rather not modify Yocto sources if that is possible.

Eskimoalva
  • 449
  • 8
  • 20

2 Answers2

4

You can do this by defining your own rootfs post-command, and appending it to ROOTFS_POSTPROCESS_COMMAND so that it runs after Yocto's built-in read_only_rootfs_hook that creates the empty /etc/machine-id file using touch.

# setup-machine-id-symlink.bbclass

ROOTFS_POSTPROCESS_COMMAND += "install_machine_id_symlink ;"
install_machine_id_symlink () {
    ln -sfn /var/local/etc/machine-id ${IMAGE_ROOTFS}/etc/machine-id
}


# your-image.bb

inherit setup-machine-id-symlink

The Image Generation docs have more detail on how postprocessing commands are applied during the build.

Note: You will need to ensure that your persistent partition is mounted early, so that reading /etc/machine-id doesn't result in a broken symlink.


Alternatively, use bind mounts:

You could also do this at runtime by installing a systemd service that runs early in the boot sequence and bind mounts your persistent machine-id over the blank one provided by Yocto in the rootfs.

Using a systemd service (rather than a bind mount entry in /etc/fstab) is necessary because you will need to ensure the persistent machine-id file actually exists before creating the bind mount. Though, you may be able to make use of tmpfiles.d to do that instead.

justinsg
  • 738
  • 6
  • 11
0

After first boot, when machine-id is generated, update bootargs U-Boot environment variable to include systemd.machine_id= in the kernel command line parameter. An ID specified in this manner has higher priority and will be used instead of the ID stored in /etc/machine-id.