From 8f083e6e919a98415854d19a181c8f5fc9948193 Mon Sep 17 00:00:00 2001 From: StefanaHanc Date: Wed, 1 Oct 2025 13:31:43 +0300 Subject: [PATCH] add edgeos-hostname service using device UUID for mDNS --- .../avahi/avahi_%.bbappend | 55 ++++--- .../avahi/files/90-edgeos.preset | 1 + .../avahi/files/edgeos-hostname.service | 5 +- .../avahi/files/generate-hostname.sh | 146 ++++++++++-------- .../recipes-core/images/edgeos-image.bb | 6 + 5 files changed, 128 insertions(+), 85 deletions(-) create mode 100644 meta-edgeos/recipes-connectivity/avahi/files/90-edgeos.preset diff --git a/meta-edgeos/recipes-connectivity/avahi/avahi_%.bbappend b/meta-edgeos/recipes-connectivity/avahi/avahi_%.bbappend index 100cf94..622ab5a 100644 --- a/meta-edgeos/recipes-connectivity/avahi/avahi_%.bbappend +++ b/meta-edgeos/recipes-connectivity/avahi/avahi_%.bbappend @@ -1,10 +1,12 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/files:" -SRC_URI += "file://generate-hostname.sh \ - file://edgeos-mdns.service \ - file://edgeos-hostname.service \ - file://nsswitch.conf.append" - +SRC_URI += " \ + file://edgeos-mdns.service \ + file://generate-hostname.sh \ + file://edgeos-hostname.service \ + file://nsswitch.conf.append \ + file://90-edgeos.preset \ +" # Ensure D-Bus support is enabled for proper service publishing PACKAGECONFIG += "dbus" @@ -13,14 +15,11 @@ EXTRA_OECONF += "--with-avahi-user=avahi --with-avahi-group=avahi" inherit systemd -SYSTEMD_SERVICE:${PN} += "edgeos-hostname.service" -SYSTEMD_AUTO_ENABLE:${PN} = "enable" - do_install:append() { - # Install hostname generation script to /usr/sbin + # Install hostname generation script + systemd unit (goes to sub-package) install -d ${D}${sbindir} install -m 0755 ${WORKDIR}/generate-hostname.sh ${D}${sbindir}/ - + # Install Avahi service file install -d ${D}${sysconfdir}/avahi/services install -m 0644 ${WORKDIR}/edgeos-mdns.service ${D}${sysconfdir}/avahi/services/ @@ -28,7 +27,7 @@ do_install:append() { # Install systemd service for hostname setup install -d ${D}${systemd_system_unitdir} install -m 0644 ${WORKDIR}/edgeos-hostname.service ${D}${systemd_system_unitdir}/ - + # Ensure NSS mDNS is properly configured if [ -f ${D}${sysconfdir}/nsswitch.conf ]; then # Check if mdns is already configured @@ -38,7 +37,7 @@ do_install:append() { cat ${WORKDIR}/nsswitch.conf.append >> ${D}${sysconfdir}/nsswitch.conf fi fi - + # Enable Avahi daemon and ensure it starts with proper settings if [ -f ${D}${sysconfdir}/avahi/avahi-daemon.conf ]; then # Enable D-Bus support for proper service publishing @@ -60,14 +59,32 @@ do_install:append() { # Set host name sed -i 's/^#*host-name=.*/# host-name is set dynamically by edgeos-hostname.service/' ${D}${sysconfdir}/avahi/avahi-daemon.conf fi + + # Systemd preset to auto-enable hostname service by default + install -d ${D}${systemd_unitdir}/system-preset + install -m 0644 ${WORKDIR}/90-edgeos.preset \ + ${D}${systemd_unitdir}/system-preset/90-edgeos.preset } -FILES:${PN} += "${sbindir}/generate-hostname.sh \ - ${sysconfdir}/avahi/services/edgeos-mdns.service \ - ${systemd_system_unitdir}/edgeos-hostname.service" +# --- What remains in the avahi main package (ONLY the .service for mDNS) --- +FILES:${PN} += " ${sysconfdir}/avahi/services/edgeos-mdns.service " -# Ensure avahi-daemon is enabled -SYSTEMD_SERVICE:${PN} = "avahi-daemon.service edgeos-hostname.service" +# --- Sub-package for EdgeOS hostname setup --- +PACKAGES:prepend = "${PN}-edgeos-hostname " +FILES:${PN}-edgeos-hostname = " \ + ${sbindir}/generate-hostname.sh \ + ${systemd_system_unitdir}/edgeos-hostname.service \ + ${systemd_unitdir}/system-preset/90-edgeos.preset \ +" -# Add runtime dependencies -RDEPENDS:${PN} += "bash" \ No newline at end of file +RDEPENDS:${PN}-edgeos-hostname = "bash iproute2 systemd avahi-daemon" +SYSTEMD_SERVICE:${PN}-edgeos-hostname = "edgeos-hostname.service" +SYSTEMD_AUTO_ENABLE:${PN}-edgeos-hostname = "enable" + +# Postinstall hook: safety net in case preset doesn't run at image build time +pkg_postinst:${PN}-edgeos-hostname () { + if [ -z "$D" ]; then + systemctl enable edgeos-hostname.service || true + systemctl start edgeos-hostname.service || true + fi +} diff --git a/meta-edgeos/recipes-connectivity/avahi/files/90-edgeos.preset b/meta-edgeos/recipes-connectivity/avahi/files/90-edgeos.preset new file mode 100644 index 0000000..7ce8c75 --- /dev/null +++ b/meta-edgeos/recipes-connectivity/avahi/files/90-edgeos.preset @@ -0,0 +1 @@ +enable edgeos-hostname.service \ No newline at end of file diff --git a/meta-edgeos/recipes-connectivity/avahi/files/edgeos-hostname.service b/meta-edgeos/recipes-connectivity/avahi/files/edgeos-hostname.service index 4f8e335..3593ed2 100644 --- a/meta-edgeos/recipes-connectivity/avahi/files/edgeos-hostname.service +++ b/meta-edgeos/recipes-connectivity/avahi/files/edgeos-hostname.service @@ -1,7 +1,8 @@ [Unit] Description=EdgeOS Hostname Setup +Wants=edgeos-identity.service +After=edgeos-identity.service local-fs.target Before=avahi-daemon.service network.target -After=local-fs.target [Service] Type=oneshot @@ -11,4 +12,4 @@ StandardOutput=journal StandardError=journal [Install] -WantedBy=multi-user.target \ No newline at end of file +WantedBy=multi-user.target diff --git a/meta-edgeos/recipes-connectivity/avahi/files/generate-hostname.sh b/meta-edgeos/recipes-connectivity/avahi/files/generate-hostname.sh index c4153b0..b04078e 100644 --- a/meta-edgeos/recipes-connectivity/avahi/files/generate-hostname.sh +++ b/meta-edgeos/recipes-connectivity/avahi/files/generate-hostname.sh @@ -1,118 +1,136 @@ #!/bin/bash # # EdgeOS Hostname Generation Script -# Generates a unique hostname based on device serial number +# Generates a unique hostname based on device UUID (fallback to serial/MAC) # -set -e +set -Eeuo pipefail + +UUID_FILE="/etc/edgeos/device-uuid" +PREFIX="edgeos" +STATE_DIR="/etc/edgeos" +STATE_HOSTNAME_FILE="${STATE_DIR}/hostname" # Logging log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" - logger -t edgeos-hostname "$*" + logger -t edgeos-hostname "$*" || true +} + +# Validate UUID (accepts with/without dashes, case-insensitive) +is_valid_uuid() { + local v="${1,,}" + [[ "$v" =~ ^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$ ]] +} + +# Primary source: device UUID +get_device_uuid() { + local uuid="" + if [ -r "$UUID_FILE" ]; then + uuid="$(tr -d '[:space:]' < "$UUID_FILE" 2>/dev/null || true)" + fi + echo "$uuid" } -# Get device serial number or unique identifier -get_device_id() { +# Fallback legacy ID (serial/MAC/machine-id) – used only if UUID is missing/invalid +get_legacy_id() { local device_id="" - - # Try to get Raspberry Pi serial + # Raspberry Pi serial if [ -f /proc/cpuinfo ]; then - device_id=$(grep Serial /proc/cpuinfo 2>/dev/null | cut -d':' -f2 | tr -d ' ' || true) + device_id=$(grep -m1 '^Serial' /proc/cpuinfo 2>/dev/null | cut -d':' -f2 | tr -d ' ' || true) fi - - # If no serial found, try machine-id + # machine-id (partial) if [ -z "${device_id}" ] && [ -f /etc/machine-id ]; then - device_id=$(cat /etc/machine-id | head -c 16) + device_id=$(head -c 16 /etc/machine-id || true) fi - - # If still no ID, generate one + # first MAC if [ -z "${device_id}" ]; then - device_id=$(ip link show | grep ether | head -1 | awk '{print $2}' | tr -d ':' | head -c 16) + device_id=$(ip link show | awk '/ether/ {gsub(":","",$2); print $2; exit}') fi - - # Fallback to random + # random fallback if [ -z "${device_id}" ]; then device_id=$(tr -dc 'a-f0-9' < /dev/urandom | head -c 16) fi - - echo "${device_id}" + echo "$device_id" } -# Generate hostname +# Generate hostname from UUID (preferred) or legacy ID (fallback) generate_hostname() { - local device_id=$(get_device_id) - - # Take last 8 characters for readability - local short_id="${device_id: -8}" - - # Convert to lowercase - short_id=$(echo "${short_id}" | tr '[:upper:]' '[:lower:]') - - # Create hostname - local hostname="edgeos-${short_id}" - - echo "${hostname}" + local uuid short_id legacy + uuid="$(get_device_uuid)" + + if [ -n "$uuid" ] && is_valid_uuid "$uuid"; then + uuid="${uuid//-/}" + uuid="${uuid,,}" + short_id="${uuid: -8}" + else + legacy="$(get_legacy_id)" + legacy="${legacy//-/}" + legacy="${legacy,,}" + short_id="${legacy: -8}" + fi + + echo "${PREFIX}-${short_id}" } # Set hostname set_hostname() { local new_hostname="$1" - local current_hostname=$(hostname) - + local current_hostname + current_hostname=$(hostname || echo "") + if [ "${current_hostname}" = "${new_hostname}" ]; then log "Hostname already set to ${new_hostname}" return 0 fi - + log "Setting hostname to ${new_hostname}" - - # Set hostname using hostnamectl if available + if command -v hostnamectl >/dev/null 2>&1; then hostnamectl set-hostname "${new_hostname}" + echo "${new_hostname}" > /etc/hostname # menține sincron/compat else - # Fallback to traditional method echo "${new_hostname}" > /etc/hostname hostname "${new_hostname}" fi - - # Update /etc/hosts - if ! grep -q "${new_hostname}" /etc/hosts; then - # Remove old edgeos entries - sed -i '/edgeos-/d' /etc/hosts - - # Add new entry - echo "127.0.1.1 ${new_hostname} ${new_hostname}.local" >> /etc/hosts + + # Update /etc/hosts (idempotent) + if [ -f /etc/hosts ]; then + grep -q "${new_hostname}" /etc/hosts 2>/dev/null || { + sed -i '/edgeos-/d' /etc/hosts 2>/dev/null || true + echo "127.0.1.1 ${new_hostname} ${new_hostname}.local" >> /etc/hosts + } + else + echo "127.0.1.1 ${new_hostname} ${new_hostname}.local" > /etc/hosts fi - + log "Hostname set successfully to ${new_hostname}" } -# Main execution main() { log "Starting EdgeOS hostname generation" - - # Check if we should skip (for development or custom setups) + + # Allow opt-out if [ -f /etc/edgeos-hostname-override ]; then log "Hostname override found, skipping automatic generation" exit 0 fi - - # Generate and set hostname - local hostname=$(generate_hostname) - set_hostname "${hostname}" - - # Store the generated hostname for reference - echo "${hostname}" > /etc/edgeos-hostname - - # Restart avahi-daemon if it's running to pick up new hostname - if systemctl is-active --quiet avahi-daemon.service; then + + mkdir -p "${STATE_DIR}" + + local new + new="$(generate_hostname)" + set_hostname "${new}" + + echo "${new}" > "${STATE_HOSTNAME_FILE}" + + # Restart avahi-daemon to broadcast the new name via mDNS (if present) + if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet avahi-daemon.service; then log "Restarting avahi-daemon to pick up new hostname" - systemctl restart avahi-daemon.service + systemctl restart avahi-daemon.service || true fi - - log "EdgeOS hostname generation completed" + + log "EdgeOS hostname generation completed: ${new}" } -# Run main function -main "$@" \ No newline at end of file +main "$@" diff --git a/meta-edgeos/recipes-core/images/edgeos-image.bb b/meta-edgeos/recipes-core/images/edgeos-image.bb index bf80aac..f283d32 100644 --- a/meta-edgeos/recipes-core/images/edgeos-image.bb +++ b/meta-edgeos/recipes-core/images/edgeos-image.bb @@ -39,3 +39,9 @@ BUILDCFG_VARS += " \ # Disable WIC's automatic fstab updates WIC_CREATE_EXTRA_ARGS = "--no-fstab-update" + +# Provider for 'hostname' required by avahi-daemon +IMAGE_INSTALL:append = " inetutils-hostname" + +# Avahi + the sub-package with the custom script/service +IMAGE_INSTALL:append = " avahi-daemon avahi-edgeos-hostname"