generalize: keep the static address from stranding the box after a reboot
It worked on the first boot and was gone after a later internal reboot -- no IPv4 at all, not even DHCP. DHCP is turned off before the address is set, so anything that stops the set mid-way leaves the interface with nothing. A stale ARP entry for the address, left on the network by the previous instance, tripped duplicate-address detection and made New-NetIPAddress throw; with -ErrorAction Stop that aborted the script with DHCP already off. DadTransmits 0 turns that detection off so the static binds regardless of what the network remembers, and the assignment is now retried a few times rather than fatal on the first throw. Moved to its own .ps1 -- a wait loop and a retry are not worth keeping correct inside a cmd one-liner. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0117qMyjpuXsjpVAcpJbFD8g
This commit is contained in:
parent
d94c576df2
commit
5251bf7290
1 changed files with 44 additions and 5 deletions
|
|
@ -93,12 +93,48 @@ in
|
|||
# interface arrives DHCP-managed -- assigning an address without turning DHCP
|
||||
# off first does not stick, which is how a VM meant to be at a fixed address
|
||||
# ended up holding a lease instead.
|
||||
# PowerShell in its own file: it grew a wait loop and a retry, which are no
|
||||
# fun to keep correct inside a cmd one-liner.
|
||||
#
|
||||
# Two things it must survive. DHCP is turned off before the address is set,
|
||||
# so any failure to set it strands the box with no address at all -- which is
|
||||
# exactly what happened after an internal reboot, where a stale ARP entry for
|
||||
# the address from the previous instance tripped duplicate-address detection
|
||||
# and New-NetIPAddress threw. DadTransmits 0 turns that detection off so the
|
||||
# static always binds, and the assignment is retried rather than fatal.
|
||||
staticIPScriptPs1 = pkgs.writeText "vmix-static-ip.ps1" ''
|
||||
$a = $null
|
||||
for ($n = 0; $n -lt 30; $n++) {
|
||||
$a = Get-NetAdapter -Physical | Where-Object Status -eq 'Up' | Sort-Object ifIndex | Select-Object -First 1
|
||||
if ($a) { break }
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
if (-not $a) { Write-Output 'vmix: no adapter came up'; exit 1 }
|
||||
$i = $a.ifIndex
|
||||
Set-NetIPInterface -InterfaceIndex $i -Dhcp Disabled -DadTransmits 0 -ErrorAction SilentlyContinue
|
||||
Remove-NetIPAddress -InterfaceIndex $i -AddressFamily IPv4 -Confirm:$false -ErrorAction SilentlyContinue
|
||||
Remove-NetRoute -InterfaceIndex $i -AddressFamily IPv4 -Confirm:$false -ErrorAction SilentlyContinue
|
||||
$ok = $false
|
||||
for ($k = 0; $k -lt 5 -and -not $ok; $k++) {
|
||||
try {
|
||||
New-NetIPAddress -InterfaceIndex $i -IPAddress '${staticIP.address}' -PrefixLength ${toString staticIP.prefixLength} -DefaultGateway '${staticIP.gateway}' -ErrorAction Stop | Out-Null
|
||||
$ok = $true
|
||||
} catch {
|
||||
Write-Output ('vmix: assign attempt ' + $k + ' failed: ' + $_.Exception.Message)
|
||||
Start-Sleep -Seconds 2
|
||||
Remove-NetIPAddress -InterfaceIndex $i -AddressFamily IPv4 -Confirm:$false -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
if (-not $ok) { Write-Output 'vmix: could not set static address'; exit 1 }
|
||||
Set-DnsClientServerAddress -InterfaceIndex $i -ServerAddresses ${staticDnsList}
|
||||
New-NetFirewallRule -DisplayName 'ICMPv4 Echo' -Protocol ICMPv4 -IcmpType 8 -Direction Inbound -Action Allow -Profile Any -Enabled True -ErrorAction SilentlyContinue | Out-Null
|
||||
Write-Output ('vmix: set ${staticIP.address} on ifIndex ' + $i)
|
||||
'';
|
||||
|
||||
# Thin launcher, so the scheduled task has a cmd to point at.
|
||||
staticIPScript = pkgs.writeText "vmix-static-ip.cmd" ''
|
||||
@echo off
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -Command "$a = $null; for ($n = 0; $n -lt 30; $n++) { $a = Get-NetAdapter -Physical | Where-Object Status -eq 'Up' | Sort-Object ifIndex | Select-Object -First 1; if ($a) { break }; Start-Sleep -Seconds 2 }; if (-not $a) { Write-Output 'vmix: no adapter came up'; exit 1 }; $i = $a.ifIndex; Set-NetIPInterface -InterfaceIndex $i -Dhcp Disabled -ErrorAction SilentlyContinue; Remove-NetIPAddress -InterfaceIndex $i -AddressFamily IPv4 -Confirm:$false -ErrorAction SilentlyContinue; Remove-NetRoute -InterfaceIndex $i -AddressFamily IPv4 -Confirm:$false -ErrorAction SilentlyContinue; New-NetIPAddress -InterfaceIndex $i -IPAddress '${staticIP.address}' -PrefixLength ${toString staticIP.prefixLength} -DefaultGateway '${staticIP.gateway}' -ErrorAction Stop | Out-Null; Set-DnsClientServerAddress -InterfaceIndex $i -ServerAddresses ${staticDnsList}; Write-Output ('vmix: set ' + '${staticIP.address}' + ' on ifIndex ' + $i)" > C:\Windows\Temp\vmix-static-ip.log 2>&1
|
||||
:: Answer pings. Windows blocks ICMP by default, which makes a box with a
|
||||
:: fixed address look dead to everything that checks it the obvious way.
|
||||
powershell -NoProfile -Command "New-NetFirewallRule -DisplayName 'ICMPv4 Echo' -Protocol ICMPv4 -IcmpType 8 -Direction Inbound -Action Allow -Profile Any -Enabled True | Out-Null" > nul 2>&1
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File C:\vmix-static-ip.ps1 > C:\Windows\Temp\vmix-static-ip.log 2>&1
|
||||
'';
|
||||
|
||||
dataDriveLetter = if dataDisk != null then (dataDisk.driveLetter or "D") else "D";
|
||||
|
|
@ -413,7 +449,10 @@ in {
|
|||
{ source = bootDataProfileScript; dest = "/vmix-data-profile.cmd"; }
|
||||
]
|
||||
++ lib.optional (writeFilter != null) { source = uwfConfigScript; dest = "/vmix-uwf-config.cmd"; }
|
||||
++ lib.optional (staticIP != null) { source = staticIPScript; dest = "/vmix-static-ip.cmd"; };
|
||||
++ lib.optionals (staticIP != null) [
|
||||
{ source = staticIPScript; dest = "/vmix-static-ip.cmd"; }
|
||||
{ source = staticIPScriptPs1; dest = "/vmix-static-ip.ps1"; }
|
||||
];
|
||||
# delayOobeRun: sysprep + shutdown — OOBE runs on real hardware
|
||||
# generalize: sysprep + reboot into OOBE in the same QEMU session
|
||||
auditScript = ''
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue