Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 36 additions & 19 deletions meta-edgeos/recipes-connectivity/avahi/avahi_%.bbappend
Original file line number Diff line number Diff line change
@@ -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"

Expand All @@ -13,22 +15,19 @@ 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/

# 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
Expand All @@ -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
Expand All @@ -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"
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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
enable edgeos-hostname.service
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -11,4 +12,4 @@ StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
WantedBy=multi-user.target
146 changes: 82 additions & 64 deletions meta-edgeos/recipes-connectivity/avahi/files/generate-hostname.sh
Original file line number Diff line number Diff line change
@@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

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 "$@"
main "$@"
6 changes: 6 additions & 0 deletions meta-edgeos/recipes-core/images/edgeos-image.bb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought avahi daemon was already installed somewhere. not a problem. I'm sure the build system will figure it out.