powershell max route X server
################################################################################
# Script: Get-NetScalerServerRouteMapping.ps1
# Description: Analyse une config NetScaler et identifie quels serveurs
# utilisent quelle route basé sur le longest prefix match
################################################################################
param(
[Parameter(Mandatory=$false)]
[string]$ConfigPath = "c:\logs\ns.conf"
)
# Fonction pour convertir une IP en entier
function ConvertTo-IPInt {
param([string]$IP)
$octets = $IP.Split('.')
if ($octets.Count -ne 4) {
Write-Warning "IP invalide: $IP"
return $null
}
try {
[int64]$result = 0
$result += [int64]$octets[0] * 16777216 # 256^3
$result += [int64]$octets[1] * 65536 # 256^2
$result += [int64]$octets[2] * 256 # 256^1
$result += [int64]$octets[3] # 256^0
return $result
}
catch {
Write-Warning "Erreur conversion IP: $IP"
return $null
}
}
# Fonction pour convertir un masque en CIDR
function ConvertTo-CIDR {
param([string]$Netmask)
$maskInt = ConvertTo-IPInt -IP $Netmask
if ($null -eq $maskInt) { return 0 }
# Compter les bits à 1
$cidr = 0
for ($i = 31; $i -ge 0; $i--) {
if ($maskInt -band [Math]::Pow(2, $i)) {
$cidr++
}
else {
break
}
}
return $cidr
}
# Fonction pour calculer le réseau à partir d'une IP et d'un masque
function Get-NetworkAddress {
param(
[int64]$IPInt,
[int64]$MaskInt
)
return $IPInt -band $MaskInt
}
# Fonction pour parser les routes
function Get-Routes {
param([string[]]$ConfigLines)
$routes = @()
foreach ($line in $ConfigLines) {
if ($line -match '^\s*add\s+route\s+(\S+)\s+(\S+)\s+(\S+)') {
$network = $matches[1]
$netmask = $matches[2]
$gateway = $matches[3]
$networkInt = ConvertTo-IPInt -IP $network
$maskInt = ConvertTo-IPInt -IP $netmask
$cidr = ConvertTo-CIDR -Netmask $netmask
if ($null -ne $networkInt -and $null -ne $maskInt) {
$routes += [PSCustomObject]@{
Network = $network
Netmask = $netmask
Gateway = $gateway
NetworkInt = $networkInt
MaskInt = $maskInt
CIDR = $cidr
DisplayName = "$network/$cidr -> $gateway"
}
}
}
}
return $routes
}
# Fonction pour parser les serveurs
function Get-Servers {
param([string[]]$ConfigLines)
$servers = @()
foreach ($line in $ConfigLines) {
if ($line -match '^\s*add\s+server\s+(\S+)\s+(\S+)(.*)') {
$name = $matches[1]
$ip = $matches[2]
$remainder = $matches[3]
# Extraire le commentaire s'il existe
$comment = ""
if ($remainder -match '-comment\s+"([^"]*)"') {
$comment = $matches[1]
}
elseif ($remainder -match '-comment\s+(\S+)') {
$comment = $matches[1]
}
$ipInt = ConvertTo-IPInt -IP $ip
if ($null -ne $ipInt) {
$servers += [PSCustomObject]@{
Name = $name
IP = $ip
IPInt = $ipInt
Comment = $comment
}
}
}
}
return $servers
}
# Fonction pour trouver la route correspondante (longest prefix match)
function Find-MatchingRoute {
param(
[int64]$ServerIPInt,
[array]$Routes
)
$bestMatch = $null
$longestPrefix = -1
foreach ($route in $Routes) {
$serverNetwork = Get-NetworkAddress -IPInt $ServerIPInt -MaskInt $route.MaskInt
if ($serverNetwork -eq $route.NetworkInt) {
if ($route.CIDR -gt $longestPrefix) {
$longestPrefix = $route.CIDR
$bestMatch = $route
}
}
}
return $bestMatch
}
################################################################################
# MAIN
################################################################################
Write-Host "`n=== Analyse de la configuration NetScaler ===" -ForegroundColor Cyan
Write-Host "Fichier: $ConfigPath`n" -ForegroundColor Gray
# Vérifier que le fichier existe
if (-not (Test-Path $ConfigPath)) {
Write-Error "Le fichier '$ConfigPath' n'existe pas"
exit 1
}
# Lire la configuration
$configContent = Get-Content $ConfigPath
# Parser routes et serveurs
Write-Host "Parsing des routes..." -ForegroundColor Yellow
$routes = Get-Routes -ConfigLines $configContent
Write-Host " -> $($routes.Count) routes trouvées" -ForegroundColor Green
Write-Host "Parsing des serveurs..." -ForegroundColor Yellow
$servers = Get-Servers -ConfigLines $configContent
Write-Host " -> $($servers.Count) serveurs trouvés`n" -ForegroundColor Green
# Créer le mapping Route → Serveurs
$routeMapping = @{}
foreach ($route in $routes) {
$routeMapping[$route.DisplayName] = @()
}
# Ajouter une catégorie pour les serveurs sans route
$noRouteKey = "[ATTENTION] Aucune route correspondante"
$routeMapping[$noRouteKey] = @()
# Associer chaque serveur à sa route
foreach ($server in $servers) {
$matchingRoute = Find-MatchingRoute -ServerIPInt $server.IPInt -Routes $routes
if ($null -ne $matchingRoute) {
$routeMapping[$matchingRoute.DisplayName] += $server
}
else {
$routeMapping[$noRouteKey] += $server
}
}
# Afficher les résultats
Write-Host "=== Résultats : Serveurs par Route ===" -ForegroundColor Cyan
Write-Host ""
$routeCount = 0
$emptyRoutes = @()
# Afficher d'abord les routes avec des serveurs
foreach ($routeName in ($routeMapping.Keys | Sort-Object)) {
$serversInRoute = $routeMapping[$routeName]
if ($serversInRoute.Count -gt 0) {
$routeCount++
if ($routeName -eq $noRouteKey) {
Write-Host "[$routeName]" -ForegroundColor Red
}
else {
Write-Host "Route: $routeName" -ForegroundColor Green
}
Write-Host " Nombre de serveurs: $($serversInRoute.Count)" -ForegroundColor Gray
Write-Host ""
foreach ($srv in ($serversInRoute | Sort-Object Name)) {
$displayLine = " - $($srv.Name) ($($srv.IP))"
if ($srv.Comment) {
$displayLine += " - `"$($srv.Comment)`""
}
Write-Host $displayLine
}
Write-Host ""
}
else {
# Collecter les routes vides (sauf la catégorie noRouteKey)
if ($routeName -ne $noRouteKey) {
$emptyRoutes += $routeName
}
}
}
# Afficher les routes sans serveurs à la fin en rouge
if ($emptyRoutes.Count -gt 0) {
Write-Host "=== Routes non bindees a aucun serveur ===" -ForegroundColor Red
Write-Host ""
foreach ($emptyRoute in ($emptyRoutes | Sort-Object)) {
Write-Host "Route: $emptyRoute" -ForegroundColor Red
Write-Host " Aucun serveur n'utilise cette route" -ForegroundColor Gray
Write-Host ""
}
}
# Statistiques finales
Write-Host "=== Statistiques ===" -ForegroundColor Cyan
Write-Host "Total routes: $($routes.Count)" -ForegroundColor Gray
Write-Host "Total serveurs: $($servers.Count)" -ForegroundColor Gray
Write-Host ""
Write-Host "Routes avec serveurs: $routeCount" -ForegroundColor Gray
Write-Host "Routes sans serveurs: $($emptyRoutes.Count)" -ForegroundColor Gray
Write-Host "Serveurs sans route: $($routeMapping[$noRouteKey].Count)" -ForegroundColor Gray
Write-Host ""