Initial import from bf-network-r6.opencode — opencode migration
This commit is contained in:
41
switch/recovery/README.md
Normal file
41
switch/recovery/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Mac-mini Recovery-Anker für den Switch-Flash
|
||||
|
||||
**Zweck:** Der Mac mini (10.40.41.167, en0, L2-benachbart zum Switch) trägt dauerhaft eine
|
||||
**Zweit-IP 192.168.1.2/24**. Nach einem Firmware-Flash kommt der Switch auf `192.168.1.1` hoch
|
||||
(Werks-Default) — über die Zweit-IP erreicht Claude ihn **vom Mac mini aus** und setzt ihn
|
||||
automatisch auf `10.40.41.239` zurück. Kein manuelles IP-Suchen, kein Laptop nötig.
|
||||
|
||||
## Variante A — nur für heute (transient, kein Reboot dazwischen)
|
||||
Auf dem Mac mini (deine SSH-Session):
|
||||
```
|
||||
sudo ifconfig en0 alias 192.168.1.2 255.255.255.0
|
||||
ifconfig en0 | grep 192.168.1 # prüfen
|
||||
```
|
||||
Entfernen: `sudo ifconfig en0 -alias 192.168.1.2`
|
||||
|
||||
## Variante B — persistent (übersteht Reboots, empfohlen wenn Dauer-Anker)
|
||||
Auf dem Mac mini, aus diesem Repo-Ordner (`switch/recovery/`):
|
||||
```
|
||||
sudo cp switch-recovery-ip.sh /usr/local/sbin/switch-recovery-ip.sh
|
||||
sudo chmod 755 /usr/local/sbin/switch-recovery-ip.sh
|
||||
sudo cp com.bf.switchrecoveryip.plist /Library/LaunchDaemons/
|
||||
sudo chown root:wheel /Library/LaunchDaemons/com.bf.switchrecoveryip.plist
|
||||
sudo launchctl load -w /Library/LaunchDaemons/com.bf.switchrecoveryip.plist
|
||||
ifconfig en0 | grep 192.168.1 # prüfen
|
||||
```
|
||||
Deinstallieren:
|
||||
```
|
||||
sudo launchctl unload -w /Library/LaunchDaemons/com.bf.switchrecoveryip.plist
|
||||
sudo rm /Library/LaunchDaemons/com.bf.switchrecoveryip.plist /usr/local/sbin/switch-recovery-ip.sh
|
||||
sudo ifconfig en0 -alias 192.168.1.2
|
||||
```
|
||||
|
||||
## Recovery-Ablauf nach Flash (Claude führt aus, vom Mac mini)
|
||||
```
|
||||
ssh 10.40.41.167
|
||||
cd ~/.../bf-network-r6/switch # Repo muss auf dem Mac mini liegen ODER Claude tunnelt
|
||||
SW_HOST=192.168.1.1 SW_USER=admin SW_PASS=admin ./sg8316m.sh set-ip 10.40.41.239
|
||||
# Switch nun wieder auf .239 → .secrets zurück, dann VLANs/Ports/save
|
||||
```
|
||||
> Hinweis: Claude erreicht den Switch nach Flash **nur** über den Mac mini (.1.1 ist L2-lokal am Mac mini).
|
||||
> Der Treiber `sg8316m.sh` muss daher vom Mac mini aus laufen (Repo dorthin klonen/kopieren oder via SSH ausführen).
|
||||
16
switch/recovery/com.bf.switchrecoveryip.plist
Normal file
16
switch/recovery/com.bf.switchrecoveryip.plist
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.bf.switchrecoveryip</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/local/sbin/switch-recovery-ip.sh</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/var/log/switch-recovery-ip.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
136
switch/recovery/flash-and-recover.sh
Normal file
136
switch/recovery/flash-and-recover.sh
Normal file
@@ -0,0 +1,136 @@
|
||||
#!/bin/sh
|
||||
# Autonome Flash- + Recovery-Orchestrierung für ALL-SG8316M.
|
||||
# LÄUFT AUF DEM MAC MINI (10.40.41.167, en0, L2-lokal zum Switch).
|
||||
# Zweck: Claude stößt es detached an und ist während des Switch-Reboots OFFLINE.
|
||||
# Das Script zieht die ganze Kette autonom durch und loggt alles.
|
||||
#
|
||||
# Kette: pre-flight -> flash -> warte down -> warte up(.1.1|.239)
|
||||
# -> (falls .1.1) IP zurück auf .239 [cmd dynamisch entdeckt]
|
||||
# -> VLANs (best-effort) -> save-to-flash -> verify
|
||||
#
|
||||
# Aufruf: ./flash-and-recover.sh preflight # nur Checks, kein Flash
|
||||
# ./flash-and-recover.sh run # echter Flash + Recovery
|
||||
set -u
|
||||
|
||||
SW_PROD=10.40.41.239
|
||||
SW_DEFAULT=192.168.1.1
|
||||
PROD_MASK=255.255.255.0
|
||||
PROD_GW=10.40.41.254
|
||||
ALIAS_IP=192.168.1.2
|
||||
VLANS=10,20,30,40,100
|
||||
IMG="${IMG:-$HOME/bf-switch-flash/all-sg8316m-version_2.2.1_vmlinux.bix}"
|
||||
IMG_SHA=e3f160983e8b17962dc70a52360b7f560c92da8197928d702f5266027a0fc7fc
|
||||
LOG="${LOG:-$HOME/bf-switch-flash/flash-$(date +%Y%m%d-%H%M%S).log}"
|
||||
MODE="${1:-preflight}"
|
||||
|
||||
mkdir -p "$(dirname "$LOG")"
|
||||
log(){ printf '%s %s\n' "$(date '+%H:%M:%S')" "$*" | tee -a "$LOG"; }
|
||||
|
||||
# Liveness: Webserver-Root antwortet (firmware-stabiler als ein bestimmter cmd)
|
||||
http_code(){ curl -s -o /dev/null -w '%{http_code}' --max-time 5 "http://$1/" 2>/dev/null; }
|
||||
up(){ [ "$(http_code "$1")" = "200" ]; }
|
||||
fw_version(){ curl -s --max-time 6 "http://$1/cgi-bin/dispatcher.cgi?cmd=512" \
|
||||
| sed -e 's/<[^>]*>/ /g' | grep -oiE 'Firmware Version[^0-9]*[0-9.]+' | head -1; }
|
||||
|
||||
wait_up(){ _e=$(( $(date +%s) + $2 )); while [ "$(date +%s)" -lt "$_e" ]; do up "$1" && return 0; sleep 4; done; return 1; }
|
||||
wait_down(){ _e=$(( $(date +%s) + $2 )); while [ "$(date +%s)" -lt "$_e" ]; do up "$1" || return 0; sleep 4; done; return 1; }
|
||||
|
||||
# IP zurücksetzen — cmd + Seite dynamisch aus der Live-UI entdecken (firmware-drift-sicher)
|
||||
restore_ip(){
|
||||
_host=$1
|
||||
_menu=$(curl -s --max-time 8 "http://$_host/cgi-bin/dispatcher.cgi?cmd=2")
|
||||
_ipcmd=$(printf '%s' "$_menu" | grep -i 'IP Address' | grep -oE 'cmd=[0-9]+' | head -1 | cut -d= -f2)
|
||||
[ -z "$_ipcmd" ] && _ipcmd=517
|
||||
_form=$(curl -s --max-time 8 "http://$_host/cgi-bin/dispatcher.cgi?cmd=$_ipcmd")
|
||||
_post=$(printf '%s' "$_form" | grep -i 'name="cmd"' | grep -oE 'value="[0-9]+"' | head -1 | grep -oE '[0-9]+')
|
||||
[ -z "$_post" ] && _post=518
|
||||
log "restore_ip: ip-page=$_ipcmd post-cmd=$_post -> set $SW_PROD"
|
||||
curl -s --max-time 10 -X POST "http://$_host/cgi-bin/dispatcher.cgi" \
|
||||
--data "mode=0" --data "ip=$SW_PROD" --data "netmask=$PROD_MASK" \
|
||||
--data "gateway=$PROD_GW" --data "cmd=$_post" >/dev/null 2>&1
|
||||
}
|
||||
add_vlans(){ curl -s --max-time 10 -X POST "http://$1/cgi-bin/dispatcher.cgi" \
|
||||
--data "vlanlist=$VLANS" --data "vlanAction=0" --data "name=" --data "cmd=1284" >/dev/null 2>&1; }
|
||||
save_flash(){ curl -s --max-time 15 "http://$1/cgi-bin/dispatcher.cgi?cmd=4358" >/dev/null 2>&1; }
|
||||
|
||||
# ---------- PRE-FLIGHT ----------
|
||||
log "=== PRE-FLIGHT (mode=$MODE) ==="
|
||||
fail=0
|
||||
if [ -f "$IMG" ]; then
|
||||
h=$(shasum -a 256 "$IMG" 2>/dev/null | awk '{print $1}')
|
||||
if [ "$h" = "$IMG_SHA" ]; then log "OK image sha256"; else log "FAIL image sha256: $h"; fail=1; fi
|
||||
else log "FAIL image missing: $IMG"; fail=1; fi
|
||||
if ifconfig en0 2>/dev/null | grep -q "$ALIAS_IP"; then log "OK recovery-alias $ALIAS_IP on en0";
|
||||
else log "FAIL alias $ALIAS_IP missing -> sudo ifconfig en0 alias $ALIAS_IP 255.255.255.0"; fail=1; fi
|
||||
if up "$SW_PROD"; then log "OK switch up at $SW_PROD (FW: $(fw_version "$SW_PROD"))";
|
||||
else log "FAIL switch not reachable at $SW_PROD"; fail=1; fi
|
||||
if [ "$fail" -ne 0 ]; then log "PRE-FLIGHT FAILED -> abort"; exit 2; fi
|
||||
log "PRE-FLIGHT OK"
|
||||
[ "$MODE" = "preflight" ] && { log "preflight-only -> done (kein Flash)"; exit 0; }
|
||||
|
||||
# ---------- FLASH ----------
|
||||
MARKER="$HOME/bf-switch-flash/.flashed-2.2.1"
|
||||
if [ -f "$MARKER" ] && up "$SW_PROD"; then
|
||||
log "Marker vorhanden + Switch up @ $SW_PROD -> Flash übersprungen (nur reconfig)"; skip=1
|
||||
else skip=0; fi
|
||||
if [ "$skip" -eq 0 ]; then
|
||||
log "=== FLASH: lade Image hoch ($IMG) ==="
|
||||
curl -s --max-time 200 -F "type=0" -F "http_file=@$IMG" -F "cmd=4364" \
|
||||
"http://$SW_PROD/cgi-bin/httpupload.cgi" >>"$LOG" 2>&1
|
||||
log "Upload abgeschlossen, warte auf Reboot (down)..."
|
||||
# Der Reboot selbst ist das verlässliche Flash-Signal (Flash erzwingt Neustart).
|
||||
if wait_down "$SW_PROD" 180; then
|
||||
log "Switch down (Reboot) — Flash hat gegriffen"
|
||||
else
|
||||
log "FAIL kein Reboot binnen 180s — Flash vermutlich nicht angenommen (Upload/Format/Auth?)."
|
||||
log " Switch unverändert @ $SW_PROD, Netz intakt, KEIN Reset. Abbruch."
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
# ---------- WARTEN AUF WIEDERKEHR ----------
|
||||
log "=== RECOVERY: warte auf Switch (max 6 min, .1.1 ODER .239) ==="
|
||||
target=""; _e=$(( $(date +%s) + 360 ))
|
||||
while [ "$(date +%s)" -lt "$_e" ]; do
|
||||
if up "$SW_DEFAULT"; then target=$SW_DEFAULT; break; fi
|
||||
if up "$SW_PROD"; then target=$SW_PROD; break; fi
|
||||
sleep 4
|
||||
done
|
||||
if [ -z "$target" ]; then
|
||||
log "FAIL Switch kam binnen 6min nicht auf $SW_DEFAULT noch $SW_PROD zurück."
|
||||
log " -> MANUELLE Recovery nötig (Reset-Knopf 10s, dann erneut)."
|
||||
exit 4
|
||||
fi
|
||||
log "Switch zurück an $target"
|
||||
|
||||
# ---------- IP WIEDERHERSTELLEN ----------
|
||||
if [ "$target" = "$SW_DEFAULT" ]; then
|
||||
log "Switch auf Default $SW_DEFAULT -> stelle $SW_PROD wieder her"
|
||||
restore_ip "$SW_DEFAULT"
|
||||
if wait_up "$SW_PROD" 60; then
|
||||
log "OK Switch wieder auf $SW_PROD"
|
||||
else
|
||||
log "FAIL set-ip griff nicht — FW 2.2.1 erzwingt vermutlich Login (FW1.0 war offen)."
|
||||
log " LAN/Internet laufen TROTZDEM (L2-Forwarding). Nur die Mgmt-IP hängt auf $SW_DEFAULT."
|
||||
log " MANUELL: Browser http://$SW_DEFAULT Login admin/admin -> Network/IP Address"
|
||||
log " -> $SW_PROD Maske $PROD_MASK GW $PROD_GW -> Save to Flash."
|
||||
exit 5
|
||||
fi
|
||||
else
|
||||
log "Switch hat $SW_PROD behalten (Firmware bewahrte IP)"
|
||||
fi
|
||||
|
||||
# ---------- RECONFIG (best-effort, unkritisch — online nachholbar) ----------
|
||||
log "=== reconfig (best-effort) ==="
|
||||
if add_vlans "$SW_PROD"; then log "VLANs $VLANS abgeschickt"; else log "WARN VLAN-Add fehlgeschlagen (online nachholen)"; fi
|
||||
if save_flash "$SW_PROD"; then log "save-to-flash abgeschickt"; else log "WARN save fehlgeschlagen (online nachholen!)"; fi
|
||||
|
||||
# ---------- VERIFY ----------
|
||||
if up "$SW_PROD"; then
|
||||
touch "$HOME/bf-switch-flash/.flashed-2.2.1"
|
||||
log "=== SUCCESS: Switch up @ $SW_PROD (Marker gesetzt) ==="
|
||||
exit 0
|
||||
else
|
||||
log "=== WARN: Switch am Ende nicht bestätigt up ==="
|
||||
exit 6
|
||||
fi
|
||||
15
switch/recovery/switch-recovery-ip.sh
Normal file
15
switch/recovery/switch-recovery-ip.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
# Recovery-Anker: Zweit-IP 192.168.1.2/24 auf en0, damit der Mac mini den
|
||||
# ALL-SG8316M nach einem Firmware-Flash (Reset auf 192.168.1.1) erreichen kann.
|
||||
# Wird per LaunchDaemon bei jedem Boot ausgeführt (retry bis en0 da ist).
|
||||
IFACE=en0
|
||||
IP=192.168.1.2
|
||||
MASK=255.255.255.0
|
||||
i=0
|
||||
while [ "$i" -lt 10 ]; do
|
||||
if ifconfig "$IFACE" >/dev/null 2>&1; then
|
||||
ifconfig "$IFACE" alias "$IP" "$MASK" 2>/dev/null && exit 0
|
||||
fi
|
||||
i=$((i+1)); sleep 3
|
||||
done
|
||||
exit 1
|
||||
Reference in New Issue
Block a user