Skip to content

Commit

Permalink
feat(live): Improve printing the Agama URL in the console (#1515)
Browse files Browse the repository at this point in the history
## Improvements

- Hide Avahi/mDNS URL if network is not configured (displaying
`https://agama.local` URL is confusing if the network is not available,
in that case the URL simply cannot work)
- Display only configured interfaces (original code printed empty
`https://` URL for not configured devices, like not configured/not
connected Wifi adapters)
- Refresh the URLs when a device is changed (it also detects cable
connecting/disconnecting)
- Display a warning if the network is not available. Originally I wanted
to display some hint like "Press Alt+F7 to switch to the local
installer" but that does not work on some architectures (S390) or in
some situations (serial console). So to avoid confusion I have dropped
that feature.

## Notes

- Use the NetworkManager backend instead of udev. Udev works on the
hardware level and does not detect network configuration changes
(configuring Wifi) or changing the connection (unplugging/plugging in
the network cable). The NetworkManager provides more details.

## Testing

- Tested manually

## Screenshots

- Video recording of a session where the virtual network cable in a
VirtualBox VM was disconnected and then reconnected again


[Agama-screen0.webm](https://github.com/user-attachments/assets/44ea27b6-dede-4ec7-8231-d6de73815cbf)
  • Loading branch information
lslezak authored Jul 31, 2024
2 parents fb123c5 + ae8724d commit 55cbc90
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 52 deletions.
11 changes: 11 additions & 0 deletions live/root/etc/systemd/system/agama-url-issue.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[Unit]
Description=Generate issue file for Agama URLs

After=network-online.target

[Service]
ExecStart=agama-issue-generator --watch-network
Type=simple

[Install]
WantedBy=default.target
136 changes: 89 additions & 47 deletions live/root/usr/bin/agama-issue-generator
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
# - Welcome message with Agama version number (--welcome option)
# - Agama SSL certificate fingerprints (--ssl option)
# - SSH host key fingerprints (--ssh option)
# - Agama access URL for all network devices (--network option), this is
# triggered via udev rules
# - Agama access URL for all network devices (--watch-network option)
# NOTE: in this case the script does not finish, it watches the changes in
# the NetworkManager configuration and updates the URL if needed
# - Agama access URL using the mDNS (Avahi) URL (--watch-avahi option),
# NOTE: in this case the script does not finish, it watches the changes in
# the Avahi service and updates the URL if needed
Expand Down Expand Up @@ -64,11 +65,46 @@ generate_certificate_fingerprints() {
touch /run/agetty.reload
}

# message file for the Agama mDNS URL
AVAHI_MESSAGE=/run/issue.d/70-agama-connect-avahi.message
# symlink for the issue file, created only when network is available
AVAHI_ISSUE=/run/issue.d/70-agama-connect-avahi.issue
# issue file with Agama URLs
URL_ISSUES="/run/issue.d/70-agama-connect-urls.issue"
# issue displayed when there is no network connection
DISCONNECTED_ISSUE="/run/issue.d/70-agama-disconnected.issue"

# helper function, build the Agama URL messages or display a warning when
# network is not available
write_url_headers() {
# generate a header and footer around the Agama URL issues
ISSUE_HEADER=/run/issue.d/69-agama-connect.issue
ISSUE_FOOTER=/run/issue.d/71-agama-connect.issue

if [ -e "$URL_ISSUES" ]; then
# if Avahi URL is set then display it as well
if [ -e "$AVAHI_MESSAGE" ]; then
ln -sf "$AVAHI_MESSAGE" "$AVAHI_ISSUE"
fi

rm -f "$DISCONNECTED_ISSUE"

# at least one address present, display the header and footer
echo "Connect to the Agama installer using these URLs:" > "$ISSUE_HEADER"
echo > "$ISSUE_FOOTER"
else
# no network, delete the header, footer and the Avahi issue symlink
rm -f "$ISSUE_HEADER" "$ISSUE_FOOTER" "$AVAHI_ISSUE"

# display a warning message
printf "\\\\e{brown}Network is not available, the Agama installer cannot \
be used remotely.\\\\e{reset}\n\n" > "$DISCONNECTED_ISSUE"
fi
}

# a helper function which generates the mDNS URL for accessing the Agama server
# displayed at the console
generate_avahi_url() {
# issue file for the Agama mDNS URL
ISSUE=/run/issue.d/70-agama-connect-avahi.issue
# track the name, update the issue file only if the name is changed
OLDNAME=""

Expand All @@ -84,72 +120,78 @@ generate_avahi_url() {
# mDNS host name found and it is different than the previous one (or the initial value)
if [ -n "$AVAHINAME" ] && [ "$AVAHINAME" != "$OLDNAME" ]; then
OLDNAME="$AVAHINAME"
echo " https://$AVAHINAME" > "$ISSUE"
echo " https://$AVAHINAME" > "$AVAHI_MESSAGE"
write_url_headers

# reload if not in the initial state
if [ -e "$CERT_ISSUE" ]; then
touch /run/agetty.reload
fi
fi

# daemon stopped, remove the issue file
# daemon stopped, remove the message file
if echo "$line" | grep -q "avahi-daemon .* exiting"; then
OLDNAME=""
rm -f "$ISSUE"
rm -f "$AVAHI_MESSAGE"
write_url_headers
touch /run/agetty.reload
fi
done
}

# a helper function which generates the URLs for accessing the Agama server
# displayed at the console
generate_network_url() {
# the interface might be a device path, use the base name
if [[ "$2" =~ ^/ ]]; then
IFACE="${2##*/}"
else
IFACE="${2}"
fi
# helper function, write the issue with the currently available URLs for
# accessing Agama from outside
build_addresses() {
ADDRESSES=()

ACTION="$1"
ISSUE="/run/issue.d/70-agama-connect-$IFACE.issue"
# generate a header and footer around the Agama URL issues
ISSUE_HEADER=/run/issue.d/69-agama-connect.issue
ISSUE_FOOTER=/run/issue.d/71-agama-connect.issue
readarray -t CONNECTIONS < <(busctl -j get-property org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.NetworkManager ActiveConnections | jq --raw-output ".data[]")
for CONNECTION in "${CONNECTIONS[@]}"; do
TYPE=$(busctl -j get-property org.freedesktop.NetworkManager "$CONNECTION" org.freedesktop.NetworkManager.Connection.Active Type 2> /dev/null | jq --raw-output ".data")

# only handle interfaces starting with ^[bew]
# (bridges, ethernet and wifi devices), same as in the issue-generator
[[ "$IFACE" =~ ^[bew] ]] || exit 0

case "$ACTION" in
add)
# \4{} is a placeholder supported directly by the agetty issue reader
# see "man agetty"
echo " https://\\4{$IFACE} " > "$ISSUE"
;;
remove)
rm -f "$ISSUE"
;;
esac

# check the number of URL messages
ISSUES=$(ls /run/issue.d/70-agama-connect-*.issue 2> /dev/null)
if [ -n "$ISSUES" ]; then
# at least one message present, display the header and footer
echo "Connect to the Agama installer using these URLs:" > "$ISSUE_HEADER"
echo > "$ISSUE_FOOTER"
# ignore loopbacks, we need external adresses
if [ "$TYPE" != "loopback" ]; then
IP4CONFIG=$(busctl -j get-property org.freedesktop.NetworkManager "$CONNECTION" org.freedesktop.NetworkManager.Connection.Active Ip4Config 2> /dev/null | jq --raw-output ".data")
ADDRESSES+=($(busctl -j get-property org.freedesktop.NetworkManager "$IP4CONFIG" org.freedesktop.NetworkManager.IP4Config AddressData 2> /dev/null | jq --raw-output ".data[].address.data"))
fi
done

# remove duplicates
readarray -t ADDRESSES < <(printf "%s\n" "${ADDRESSES[@]}" | sort -u)

if [ -n "${ADDRESSES[*]}" ]; then
printf " https://%s\n" "${ADDRESSES[@]}" > "$URL_ISSUES"
else
# no messages, delete the header and footer
rm -f "$ISSUE_HEADER" "$ISSUE_FOOTER"
# no messages, delete the URLs
rm -f "$URL_ISSUES"
fi

write_url_headers

# reload if not in the initial state
if [ -e "$CERT_ISSUE" ]; then
touch /run/agetty.reload
fi
}

# wait until the SSL fingreprint issue is create, but at most 10 seconds
# a helper function which generates the URLs for accessing the Agama server
# displayed at the console
generate_network_url() {
# build a message with the current URLs
build_addresses

# watch for IP address changes in the NetworkManager service
dbus-monitor --system "sender='org.freedesktop.NetworkManager',\
interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',\
type=signal" 2> /dev/null | while read -r line; do
# some IP4 configuration has been changed, rebuild the URLs
if echo "$line" | grep -q 'string "org.freedesktop.NetworkManager.IP4Config"'; then
build_addresses
fi
done
}

# wait until the SSL fingreprint issue is created with a time limit passed as
# the second argument (in seconds)
wait_for_ssl_issue() {
for i in $(seq 1 "$1"); do
[ -f "$CERT_ISSUE" ] && exit 0
Expand All @@ -169,11 +211,11 @@ elif [ "$1" = "--ssl" ]; then
generate_certificate_fingerprints
elif [ "$1" = "--wait-for-ssl" ]; then
wait_for_ssl_issue "$2"
elif [ "$1" = "--network" ]; then
elif [ "$1" = "--watch-network" ]; then
generate_network_url "$2" "$3"
elif [ "$1" = "--watch-avahi" ]; then
generate_avahi_url
else
echo "Missing argument"
echo "Missing or incorrect argument"
exit 1
fi
5 changes: 0 additions & 5 deletions live/root/usr/lib/udev/rules.d/80-agama-connect-issue.rules

This file was deleted.

1 change: 1 addition & 0 deletions live/src/config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ systemctl enable agama-certificate-issue.path
systemctl enable agama-certificate-wait.service
systemctl enable agama-welcome-issue.service
systemctl enable agama-avahi-issue.service
systemctl enable agama-url-issue.service
systemctl enable agama-ssh-issue.service
systemctl enable agama-self-update.service
systemctl enable live-free-space.service
Expand Down

0 comments on commit 55cbc90

Please sign in to comment.