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
44 changes: 25 additions & 19 deletions files/usr/local/bin/apl-wifi
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,15 @@ _apl_wifi_has_non_wifi_uplink() {
(( count > 0 ))
}

_apl_wifi_nmcli_reload() {
# Load (or reload, or unload) a single connection file. On this hardware a full
# `nmcli connection reload` is pathologically slow (~11-15s) because NM's netplan
# integration regenerates everything; loading one file is ~100ms and is enough
# for every mutation: a new keyfile appears, a rewritten one is re-read, and a
# deleted one is dropped. Pass the keyfile that was just written or removed.
_apl_wifi_nmcli_load() {
local file="$1"
[[ "$NMCLI_AVAILABLE" == true ]] || return 0
"$APL_WIFI_NMCLI" connection reload >/dev/null 2>&1 || return 1
"$APL_WIFI_NMCLI" connection load "$file" >/dev/null 2>&1 || return 1
return 0
}

Expand Down Expand Up @@ -712,7 +718,7 @@ _apl_wifi_restore_snapshot() {
if [[ -f "$src" ]]; then
mv -f "$src" "$dest"
chmod 0600 "$dest" 2>/dev/null || true
_apl_wifi_nmcli_reload
_apl_wifi_nmcli_load "$dest"
fi
}

Expand All @@ -733,8 +739,8 @@ _apl_wifi_run_test_flow() {
# Write the candidate with autoconnect=false so a parallel autoconnect
# attempt doesn't fight the test bring-up.
_apl_wifi_write "$dest" "$id" "$uuid" "$ssid" "$psk" "$hidden" "$priority" false || return $?
_apl_wifi_nmcli_reload || {
_emit_error filesystem_error "nmcli reload failed before test"
_apl_wifi_nmcli_load "$dest" || {
_emit_error filesystem_error "nmcli load failed before test"
return 3
}

Expand All @@ -752,7 +758,7 @@ _apl_wifi_run_test_flow() {
if [[ "$state" == activated || "$state" == 100* ]]; then
# Pass — commit with autoconnect=true.
_apl_wifi_write "$dest" "$id" "$uuid" "$ssid" "$psk" "$hidden" "$priority" true || return $?
_apl_wifi_nmcli_reload
_apl_wifi_nmcli_load "$dest"
_apl_wifi_clear_snapshot "$id"
return 0
fi
Expand All @@ -770,7 +776,7 @@ _apl_wifi_run_test_flow() {
add)
_apl_wifi_nmcli_delete_inmem "$uuid"
apl_wifi_delete_keyfile "$dest" || true
_apl_wifi_nmcli_reload
_apl_wifi_nmcli_load "$dest"
;;
update)
_apl_wifi_restore_snapshot "$id"
Expand Down Expand Up @@ -841,7 +847,7 @@ _cmd_add_locked() {
(( rc == 0 )) || return "$rc"
else
_apl_wifi_write "$dest" "$id" "$uuid" "$ssid" "$psk" "$hidden" "$priority" true || return $?
_apl_wifi_nmcli_reload || true
_apl_wifi_nmcli_load "$dest" || true
fi

local active=false
Expand Down Expand Up @@ -928,7 +934,7 @@ _cmd_update_locked() {
(( rc == 0 )) || return "$rc"
else
_apl_wifi_write "$dest" "$id" "$cur_uuid" "$ssid" "$psk" "$hidden" "$priority" true || return $?
_apl_wifi_nmcli_reload || true
_apl_wifi_nmcli_load "$dest" || true
_apl_wifi_clear_snapshot "$id"
fi

Expand Down Expand Up @@ -1014,7 +1020,7 @@ _cmd_delete_locked() {
_emit_error filesystem_error "failed to remove keyfile"
return 3
fi
_apl_wifi_nmcli_reload || true
_apl_wifi_nmcli_load "$dest" || true

_emit_json "$(jq -nc --arg id "$id" '{status:"applied", id:$id, deleted:true, changed:[$id]}')"
}
Expand Down Expand Up @@ -1110,7 +1116,7 @@ _apl_wifi_adopt_rollback() {
fi
_apl_wifi_nmcli_delete_inmem "$new_uuid"
apl_wifi_delete_keyfile "$dest" || true
_apl_wifi_nmcli_reload || true
_apl_wifi_nmcli_load "$dest" || true
}

# --- subcommand: adopt -----------------------------------------------------
Expand Down Expand Up @@ -1223,12 +1229,12 @@ _cmd_adopt_locked() {
[[ -n "$NMCLI_ACTIVE_WIFI_UUID" && "$uuid" == "$NMCLI_ACTIVE_WIFI_UUID" ]] && was_active=true

# Write the managed keyfile and load it. Nothing is active or deleted yet, so
# a reload failure just drops the new keyfile (no link to restore).
# a load failure just drops the new keyfile (no link to restore).
_apl_wifi_write "$dest" "$new_id" "$new_uuid" "$ssid" "$psk" "$hidden" "$priority" true || return $?
if ! _apl_wifi_nmcli_reload; then
if ! _apl_wifi_nmcli_load "$dest"; then
apl_wifi_delete_keyfile "$dest" || true
_apl_wifi_nmcli_reload || true
_emit_error filesystem_error "failed to reload NetworkManager"
_apl_wifi_nmcli_load "$dest" || true
_emit_error filesystem_error "failed to load the adopted network into NetworkManager"
return 3
fi

Expand All @@ -1254,7 +1260,7 @@ _cmd_adopt_locked() {
_emit_error filesystem_error "failed to remove the foreign profile; rolled back the adoption"
return 3
fi
_apl_wifi_nmcli_reload || true
_apl_wifi_nmcli_load "$dest" || true

_emit_json "$(jq -nc --arg id "$new_id" --arg uuid "$new_uuid" --arg ssid "$ssid" \
'{status:"applied", id:$id, uuid:$uuid, ssid:$ssid, adopted:true, changed:[$id]}')"
Expand Down Expand Up @@ -1307,9 +1313,9 @@ _cmd_test_locked() {
local prior_active="$NMCLI_ACTIVE_WIFI_UUID"

_apl_wifi_write "$dest" "$id" "$uuid" "$ssid" "$psk" "$hidden" "$priority" false || return $?
_apl_wifi_nmcli_reload || {
_apl_wifi_nmcli_load "$dest" || {
apl_wifi_delete_keyfile "$dest" || true
_emit_error filesystem_error "nmcli reload failed before test"
_emit_error filesystem_error "nmcli load failed before test"
return 3
}

Expand All @@ -1335,7 +1341,7 @@ _cmd_test_locked() {
_apl_wifi_nmcli_down "$uuid"
_apl_wifi_nmcli_delete_inmem "$uuid"
apl_wifi_delete_keyfile "$dest" || true
_apl_wifi_nmcli_reload || true
_apl_wifi_nmcli_load "$dest" || true

# Bound the prior-active restore; see the matching note in
# _apl_wifi_run_test_flow for the timeout rationale.
Expand Down
1 change: 1 addition & 0 deletions test/bats/test_wifi_adopt.bats
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ is_deleted() { [[ -f "$NM_DELETED_FILE" ]] && grep -qxF "$1" "$NM_DELETED_FILE";

case "$action" in
reload) exit 0 ;;
load) exit 0 ;;
down) exit 0 ;;
up)
[[ -n "$NM_UP_FAIL" ]] && { echo "Error: Connection activation failed: no carrier" >&2; exit 4; }
Expand Down