The infrastructure that I maintain is constantly growing. That’s great for job security, and tough to keep ahold of for inventory and ansible purposes.
I’m sure there are much better ways to sort this out, but its quick and easy for me to generate a valid production inventory .yml with the following script. I also wrote this to split up your total resultant set in chunks of whatever you want.
Prerequisites
- ICMP to your clusters
- a CSV with your identifiers (Mine are Store, LAN)
I chose to write this to my spec, obviously yours could be (and probably will be) different. The CSV i mention goes something like this:
Store,LAN
001,10.2.1
002,10.2.2
003,10.2.3
My cluster nodes live a .98, .99 and .100, so I chose to scan for .98.
Set-Location $PSScriptRoot
$NetworkReference = Import-CSV -Path .\vlan10.csv # This is the Network reference. Store,LAN should be the headers.
$Splits = 350 # Set this to whatever you want your splits to be. 50 clusters is int 50. Leave as '' or $null if you want one big fat inventory
$TimeStamp = (Get-Date -format MMddyyyy-HHmmss)
$AMTIPs = @(".98") # this can be multiples, separated by commas, eg @(".98", ".99", ".100")
# Set the header here-string
$Header = @"
all:
hosts:
"@
# Build a list of IPs to ping
$IPtoScan = foreach ($Store in $NetworkReference){
foreach ($NodeIP in $AMTIPs){
($Store.LAN+$NodeIP)
}
}
# Ping all the IPs using .Net and async tasks
$Tasks = $IPtoScan | ForEach-Object {
[System.Net.NetworkInformation.Ping]::new().SendPingAsync($_)
}
# Collect all the tasks we just kicked off
[Threading.Tasks.Task]::WaitAll($Tasks)
# Extract the IPs that responded
$ResponsiveIPs = $Tasks.Result | Where-Object {$_.Status -eq "Success"} | Select-Object -ExpandProperty address | Select-Object -ExpandProperty IPAddressToString
Write-Verbose ("Found "+($ResponsiveIPs.count)+" devices responding to ping")
$FoundStores = foreach ($Store in $NetworkReference){
foreach ($ResponsiveIP in $ResponsiveIPs){
if ($Store.LAN -eq ($ResponsiveIP -replace '^(\d+\.\d+\.\d+)\.\d+$','$1')){
$SupportTunnelIncrement = $SupportTunnelIncrement + 1
[PSCustomObject]@{
StoreNumber = $Store.Store
StoreLAN = $Store.LAN
}
}
}
}
$GroupsofDevices = if ($null -ne $Splits){
[Math]::Ceiling(($FoundStores.count)/$Splits)
}
else {
1
}
foreach ($Group in (1..$GroupsofDevices)){
$GroupStart = ($Group-1)*$Splits
if($GroupsofDevices -eq 1){
$StoreStrings = foreach ($Store in $FoundStores){
$hosttitle = '"'+$Store.StoreNumber+'"'
$ansiblehost = ($Store.StoreLAN+".98")
@"
$hosttitle :
ansible_host: $ansiblehost
"@
}
}
else {
$StoreStrings = foreach ($store in ($FoundStores | Select-Object -Skip $GroupStart -First $Splits)){
$hosttitle = '"'+$Store.StoreNumber+'"'
$ansiblehost = ($Store.StoreLAN+".98")
@"
$hosttitle :
ansible_host: $ansiblehost
"@
}
}
$FinalFile = ($Header,$StoreStrings)
$FinalFile | Out-File -FilePath ("$Group-production-inventory.yml") -Encoding utf8
}
If you follow the logic in the script, essentially what we are doing is throwing a bajillion threads out there, waiting until they all come back, and reporting on those tasks. This is a neat trick to batch operations in Powershell.
This will kick an incremental inventory file into your working dir. Happy ansibling!