feat: Implement IP assignment and verification for VM guests; add related PowerShell scripts

This commit is contained in:
pbao9
2026-04-18 08:51:02 +07:00
parent f4145088e1
commit 8aef607e1f
8 changed files with 777 additions and 59 deletions
+107
View File
@@ -0,0 +1,107 @@
# assignIPLinux.ps1
# Deploy to: C:\CLISave\AssignIP\assignIPLinux.ps1 on the vSphere Windows host
#
# Usage: powershell -ExecutionPolicy Bypass -NonInteractive -File assignIPLinux.ps1 \
# <vm_id> <ip> <gateway> <cidr> <vcenter_host> <vcenter_user> <vcenter_password> <guest_password>
#
# Output: SUCCESS | FAIL (exactly one line)
param(
[Parameter(Mandatory=$true)][string]$VmId,
[Parameter(Mandatory=$true)][string]$Ip,
[Parameter(Mandatory=$true)][string]$Gateway,
[Parameter(Mandatory=$true)][string]$Cidr,
[Parameter(Mandatory=$true)][string]$VCenterHost,
[Parameter(Mandatory=$true)][string]$VCenterUser,
[Parameter(Mandatory=$true)][string]$VCenterPassword,
[Parameter(Mandatory=$true)][string]$GuestPassword
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
try {
Import-Module VMware.VimAutomation.Core -ErrorAction Stop
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null
Set-PowerCLIConfiguration -Scope User -ParticipateInCEIP $false -Confirm:$false | Out-Null
Connect-VIServer -Server $VCenterHost -User $VCenterUser -Password $VCenterPassword -Force -ErrorAction Stop | Out-Null
$vm = Get-VM -Id "VirtualMachine-$VmId" -ErrorAction Stop
# Bash script executed inside the Linux guest via VMware Tools (Invoke-VMScript)
$bashScript = @"
#!/bin/bash
set -e
# Find the first usable non-loopback interface
IFACE=`$(ip -o link show | awk -F': ' '{print `$2}' | grep -Ev '^(lo|vir|docker|br-)' | head -1)
if [ -z "`$IFACE" ]; then
echo "ERROR: no usable network interface found" >&2
exit 1
fi
# Apply static IP immediately (survives until reboot without persistence layer)
ip addr flush dev `$IFACE 2>/dev/null || true
ip addr add $Ip/$Cidr dev `$IFACE
ip link set `$IFACE up
ip route del default 2>/dev/null || true
ip route add default via $Gateway dev `$IFACE
# Persist via NetworkManager (RHEL/CentOS/Ubuntu 20+)
if command -v nmcli &>/dev/null; then
CON_NAME=`$(nmcli -t -f NAME con show 2>/dev/null | head -1)
if [ -n "`$CON_NAME" ]; then
nmcli con mod "`$CON_NAME" \
ipv4.method manual \
ipv4.addresses "$Ip/$Cidr" \
ipv4.gateway "$Gateway" 2>/dev/null || true
nmcli con up "`$CON_NAME" 2>/dev/null || true
fi
elif [ -d /etc/netplan ]; then
# Netplan fallback (Ubuntu 18+ without NM)
cat > /etc/netplan/99-static.yaml << 'YAML'
network:
version: 2
ethernets:
IFACE_PLACEHOLDER:
dhcp4: false
addresses: [IP_PLACEHOLDER/CIDR_PLACEHOLDER]
gateway4: GATEWAY_PLACEHOLDER
YAML
sed -i "s/IFACE_PLACEHOLDER/`$IFACE/g;s|IP_PLACEHOLDER/CIDR_PLACEHOLDER|$Ip/$Cidr|g;s/GATEWAY_PLACEHOLDER/$Gateway/g" /etc/netplan/99-static.yaml
netplan apply 2>/dev/null || true
elif [ -d /etc/sysconfig/network-scripts ]; then
# RHEL/CentOS legacy ifcfg
cat > /etc/sysconfig/network-scripts/ifcfg-`$IFACE << EOF
DEVICE=`$IFACE
BOOTPROTO=static
ONBOOT=yes
IPADDR=$Ip
PREFIX=$Cidr
GATEWAY=$Gateway
EOF
ifdown `$IFACE 2>/dev/null || true
ifup `$IFACE 2>/dev/null || true
fi
echo SUCCESS
"@
$result = Invoke-VMScript -VM $vm `
-ScriptText $bashScript `
-GuestUser "root" `
-GuestPassword $GuestPassword `
-ScriptType Bash `
-ErrorAction Stop
if ($result.ScriptOutput -match "SUCCESS") {
Write-Output "SUCCESS"
} else {
Write-Output "FAIL"
}
} catch {
Write-Output "FAIL"
} finally {
Disconnect-VIServer -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
}
+80
View File
@@ -0,0 +1,80 @@
# assignIPWindows.ps1
# Deploy to: C:\CLISave\AssignIP\assignIPWindows.ps1 on the vSphere Windows host
#
# Usage: powershell -ExecutionPolicy Bypass -NonInteractive -File assignIPWindows.ps1 \
# <vm_id> <ip> <gateway> <cidr> <vcenter_host> <vcenter_user> <vcenter_password> <guest_password>
#
# Output: SUCCESS | FAIL (exactly one line)
param(
[Parameter(Mandatory=$true)][string]$VmId,
[Parameter(Mandatory=$true)][string]$Ip,
[Parameter(Mandatory=$true)][string]$Gateway,
[Parameter(Mandatory=$true)][string]$Cidr,
[Parameter(Mandatory=$true)][string]$VCenterHost,
[Parameter(Mandatory=$true)][string]$VCenterUser,
[Parameter(Mandatory=$true)][string]$VCenterPassword,
[Parameter(Mandatory=$true)][string]$GuestPassword
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
try {
Import-Module VMware.VimAutomation.Core -ErrorAction Stop
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null
Set-PowerCLIConfiguration -Scope User -ParticipateInCEIP $false -Confirm:$false | Out-Null
Connect-VIServer -Server $VCenterHost -User $VCenterUser -Password $VCenterPassword -Force -ErrorAction Stop | Out-Null
$vm = Get-VM -Id "VirtualMachine-$VmId" -ErrorAction Stop
# PowerShell script executed inside the Windows guest via VMware Tools
$guestScript = @"
`$ErrorActionPreference = 'Stop'
try {
# Find the first active ethernet adapter that is not a loopback
`$adapter = Get-NetAdapter |
Where-Object { `$_.Status -eq 'Up' -and `$_.InterfaceDescription -notlike '*Loopback*' } |
Sort-Object -Property InterfaceIndex |
Select-Object -First 1
if (-not `$adapter) { throw 'No active network adapter found' }
# Remove existing IPv4 addresses and routes on this interface
`$adapter | Get-NetIPAddress -AddressFamily IPv4 -ErrorAction SilentlyContinue |
Remove-NetIPAddress -Confirm:`$false -ErrorAction SilentlyContinue
Get-NetRoute -InterfaceIndex `$adapter.InterfaceIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue |
Remove-NetRoute -Confirm:`$false -ErrorAction SilentlyContinue
# Set new static IP
New-NetIPAddress `
-InterfaceIndex `$adapter.InterfaceIndex `
-IPAddress '$Ip' `
-PrefixLength $Cidr `
-DefaultGateway '$Gateway' `
-ErrorAction Stop | Out-Null
Write-Output 'SUCCESS'
} catch {
Write-Output 'FAIL'
}
"@
$result = Invoke-VMScript -VM $vm `
-ScriptText $guestScript `
-GuestUser "administrator" `
-GuestPassword $GuestPassword `
-ScriptType Powershell `
-ErrorAction Stop
if ($result.ScriptOutput -match "SUCCESS") {
Write-Output "SUCCESS"
} else {
Write-Output "FAIL"
}
} catch {
Write-Output "FAIL"
} finally {
Disconnect-VIServer -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
}
+63
View File
@@ -0,0 +1,63 @@
# verifyIPLinux.ps1
# Deploy to: C:\CLISave\AssignIP\verifyIPLinux.ps1 on the vSphere Windows host
#
# Usage: powershell -ExecutionPolicy Bypass -NonInteractive -File verifyIPLinux.ps1 \
# <vm_id> <ip> <vcenter_host> <vcenter_user> <vcenter_password> <guest_password>
#
# Checks that the IP is configured and the interface is UP inside the Linux guest.
# Output: SUCCESS | FAIL (exactly one line)
param(
[Parameter(Mandatory=$true)][string]$VmId,
[Parameter(Mandatory=$true)][string]$Ip,
[Parameter(Mandatory=$true)][string]$VCenterHost,
[Parameter(Mandatory=$true)][string]$VCenterUser,
[Parameter(Mandatory=$true)][string]$VCenterPassword,
[Parameter(Mandatory=$true)][string]$GuestPassword
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
try {
Import-Module VMware.VimAutomation.Core -ErrorAction Stop
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null
Set-PowerCLIConfiguration -Scope User -ParticipateInCEIP $false -Confirm:$false | Out-Null
Connect-VIServer -Server $VCenterHost -User $VCenterUser -Password $VCenterPassword -Force -ErrorAction Stop | Out-Null
$vm = Get-VM -Id "VirtualMachine-$VmId" -ErrorAction Stop
# Bash snippet: verify IP exists on an active (UP) interface
$verifyScript = @"
#!/bin/bash
# Check the IP appears in 'ip a' output on an interface that is UP (state UP)
if ip a | grep -q '$Ip'; then
IFACE=`$(ip -o addr show | awk '/$Ip/{print `$2}' | head -1)
STATE=`$(cat /sys/class/net/`$IFACE/operstate 2>/dev/null || echo 'unknown')
if [ "`$STATE" = "up" ] || [ "`$STATE" = "unknown" ]; then
echo SUCCESS
exit 0
fi
fi
echo FAIL
exit 1
"@
$result = Invoke-VMScript -VM $vm `
-ScriptText $verifyScript `
-GuestUser "root" `
-GuestPassword $GuestPassword `
-ScriptType Bash `
-ErrorAction Stop
if ($result.ScriptOutput -match "SUCCESS") {
Write-Output "SUCCESS"
} else {
Write-Output "FAIL"
}
} catch {
Write-Output "FAIL"
} finally {
Disconnect-VIServer -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
}
+58
View File
@@ -0,0 +1,58 @@
# verifyIPWindows.ps1
# Deploy to: C:\CLISave\AssignIP\verifyIPWindows.ps1 on the vSphere Windows host
#
# Usage: powershell -ExecutionPolicy Bypass -NonInteractive -File verifyIPWindows.ps1 \
# <vm_id> <ip> <vcenter_host> <vcenter_user> <vcenter_password> <guest_password>
#
# Checks that the IP is configured and not in Duplicate state inside the Windows guest.
# Output: SUCCESS | FAIL (exactly one line)
param(
[Parameter(Mandatory=$true)][string]$VmId,
[Parameter(Mandatory=$true)][string]$Ip,
[Parameter(Mandatory=$true)][string]$VCenterHost,
[Parameter(Mandatory=$true)][string]$VCenterUser,
[Parameter(Mandatory=$true)][string]$VCenterPassword,
[Parameter(Mandatory=$true)][string]$GuestPassword
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
try {
Import-Module VMware.VimAutomation.Core -ErrorAction Stop
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null
Set-PowerCLIConfiguration -Scope User -ParticipateInCEIP $false -Confirm:$false | Out-Null
Connect-VIServer -Server $VCenterHost -User $VCenterUser -Password $VCenterPassword -Force -ErrorAction Stop | Out-Null
$vm = Get-VM -Id "VirtualMachine-$VmId" -ErrorAction Stop
# PowerShell snippet run inside the Windows guest
$guestScript = @"
`$ErrorActionPreference = 'SilentlyContinue'
`$addr = Get-NetIPAddress -IPAddress '$Ip' -ErrorAction SilentlyContinue
if (`$addr -and `$addr.AddressState -ne 'Duplicate' -and `$addr.AddressState -ne 'Invalid') {
Write-Output 'SUCCESS'
} else {
Write-Output 'FAIL'
}
"@
$result = Invoke-VMScript -VM $vm `
-ScriptText $guestScript `
-GuestUser "administrator" `
-GuestPassword $GuestPassword `
-ScriptType Powershell `
-ErrorAction Stop
if ($result.ScriptOutput -match "SUCCESS") {
Write-Output "SUCCESS"
} else {
Write-Output "FAIL"
}
} catch {
Write-Output "FAIL"
} finally {
Disconnect-VIServer -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
}