feat(ip-pool): add guest-side static-IP boot scripts
template/guest-setup/linux/ci-report-ip.sh Updated version: checks guestinfo.ip-assignment first (static path), falls back to DHCP detection if absent. Applies static IP before network-online.target so SSH starts on the correct address immediately. template/guest-setup/linux/ci-report-ip.service Drops 'network.target' from After= — runs before network is up so the static IP is configured before SSH/other services start. template/guest-setup/windows/ci-static-ip.ps1 Reads guestinfo.ip-assignment via vmware-rpctool at system startup (SYSTEM account Task Scheduler task). Disables DHCP, applies static IP+gateway, reports back via guestinfo.ci-ip. No-op when ip-assignment is absent. template/Install-CIToolchain-Linux2404.sh Step 7b now copies scripts from guest-setup/linux/ instead of embedding the old DHCP-only inline script. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
#Requires -Version 5.1
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Applies a pre-assigned static IP from VMware guestinfo at boot.
|
||||
|
||||
.DESCRIPTION
|
||||
Called by the CI-StaticIp Task Scheduler task at system startup (SYSTEM
|
||||
account). Reads guestinfo.ip-assignment written by the host orchestrator
|
||||
before vmrun start. If present, disables DHCP and applies the static IP
|
||||
before WinRM has a chance to start on a DHCP address, eliminating the
|
||||
20-180 s VMware-Tools IP-detect polling loop.
|
||||
|
||||
If guestinfo.ip-assignment is absent (template used standalone or
|
||||
ip_pool not configured), exits 0 immediately — DHCP runs normally.
|
||||
|
||||
Install into the template VM:
|
||||
1. Copy this script to C:\CI\ci-static-ip.ps1
|
||||
2. Create a Task Scheduler task:
|
||||
Name: CI-StaticIp
|
||||
Trigger: At System Startup
|
||||
Action: powershell.exe -NoProfile -NonInteractive
|
||||
-ExecutionPolicy Bypass -File C:\CI\ci-static-ip.ps1
|
||||
Run As: SYSTEM
|
||||
Run with highest privileges: Yes
|
||||
3. Take the BaseClean snapshot from powered-OFF state.
|
||||
|
||||
The VMCI channel (vmware-rpctool) does not require TCP/IP — it works
|
||||
via the VMware virtual hardware interface, so guestinfo is readable
|
||||
before the NIC is configured.
|
||||
#>
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$vmtoolsRpc = 'C:\Program Files\VMware\VMware Tools\vmware-rpctool.exe'
|
||||
if (-not (Test-Path $vmtoolsRpc -PathType Leaf)) { exit 0 }
|
||||
|
||||
function Read-GuestInfo {
|
||||
param([string]$Key)
|
||||
$savedEap = $ErrorActionPreference; $ErrorActionPreference = 'Continue'
|
||||
$out = & $vmtoolsRpc "info-get guestinfo.$Key" 2>&1
|
||||
$ErrorActionPreference = $savedEap
|
||||
if ($LASTEXITCODE -eq 0 -and $out -notmatch 'No value found|^$') {
|
||||
return ($out | Out-String).Trim()
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
$ip = Read-GuestInfo 'ip-assignment'
|
||||
$netmask = Read-GuestInfo 'netmask'
|
||||
$gateway = Read-GuestInfo 'gateway'
|
||||
|
||||
# No pre-assigned IP — let DHCP run normally.
|
||||
if (-not ($ip -match '^\d{1,3}(\.\d{1,3}){3}$')) { exit 0 }
|
||||
|
||||
# Convert dotted-decimal netmask to prefix length (default /24).
|
||||
function Get-PrefixLength {
|
||||
param([string]$Mask)
|
||||
if (-not ($Mask -match '^\d{1,3}(\.\d{1,3}){3}$')) { return 24 }
|
||||
$bits = 0
|
||||
foreach ($octet in $Mask.Split('.')) {
|
||||
$b = [int]$octet
|
||||
while ($b -gt 0) { $bits += ($b -band 1); $b = $b -shr 1 }
|
||||
}
|
||||
return $bits
|
||||
}
|
||||
$prefix = Get-PrefixLength $netmask
|
||||
|
||||
# Target the first Up adapter (skip loopback / Teredo / Bluetooth).
|
||||
$adapter = Get-NetAdapter |
|
||||
Where-Object { $_.Status -eq 'Up' -and $_.InterfaceDescription -notmatch 'Loopback|Bluetooth|Teredo' } |
|
||||
Select-Object -First 1
|
||||
if (-not $adapter) {
|
||||
Write-EventLog -LogName Application -Source 'ci-static-ip' -EventId 1 `
|
||||
-EntryType Error -Message 'No Up adapter found.' -ErrorAction SilentlyContinue
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Disable DHCP and remove any existing IPv4 addresses.
|
||||
$adapter | Set-NetIPInterface -Dhcp Disabled -ErrorAction SilentlyContinue
|
||||
$adapter | Get-NetIPAddress -AddressFamily IPv4 -ErrorAction SilentlyContinue |
|
||||
Remove-NetIPAddress -Confirm:$false -ErrorAction SilentlyContinue
|
||||
|
||||
# Apply static IP.
|
||||
$ipParams = @{
|
||||
InterfaceAlias = $adapter.Name
|
||||
IPAddress = $ip
|
||||
PrefixLength = $prefix
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
if ($gateway -match '^\d{1,3}(\.\d{1,3}){3}$') {
|
||||
$ipParams['DefaultGateway'] = $gateway
|
||||
}
|
||||
New-NetIPAddress @ipParams | Out-Null
|
||||
|
||||
# Use the gateway as DNS (fallback: Google DNS).
|
||||
$dns = @()
|
||||
if ($gateway -match '^\d{1,3}(\.\d{1,3}){3}$') { $dns += $gateway }
|
||||
$dns += '8.8.8.8'
|
||||
Set-DnsClientServerAddress -InterfaceAlias $adapter.Name `
|
||||
-ServerAddresses $dns -ErrorAction SilentlyContinue
|
||||
|
||||
# Report IP back via guestinfo.ci-ip so the host also has it.
|
||||
$savedEap = $ErrorActionPreference; $ErrorActionPreference = 'Continue'
|
||||
& $vmtoolsRpc "info-set guestinfo.ci-ip $ip" 2>&1 | Out-Null
|
||||
$ErrorActionPreference = $savedEap
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user