Hi ,
Hope you are doing well. I need small help from you .
I am trying to get list of vm's inside specific vlan but for some reason csv shows repetetive output.For exapmle on console output i see vlan 123 got vmabc but in csv i get same entry for vmabc twice/thrice.
Following is my code i am trying to run. All i am after is list of vms (even if not connected to n/w but part of vlan123) in the csv output just once.
$VCServer = "vc123","vc235","vc987"
$ReportExport = "/tmp/"
$vcUser = "admin"
$vcPass = "xxxx"
$VLANs = "1234","5678","0986"
$connectedVMCsvPath = "/tmp/list.csv"
$migrationCsvPath = "/tmp/$($migrationgroup).csv"
# Get the Migration Group (change#) from the environment variable
$migrationgroup = "Group9"
# Initialize an empty array to store all results
$allResults = New-Object System.Collections.Generic.List[PSCustomObject]
#$allResults = New-Object System.Collections.ArrayList
# Define the CSV headers for connected VMs
$connectedVMHeader = "vCenter Server,VM Name,VM IP Address,PowerState,PortGroup"
$connectedVMCsv = New-Object System.Collections.ArrayList
# Define the CSV headers for migration list
$migrationHeader = "VM_Name,MIGRATION_GROUP"
$migrationCsv = New-Object System.Collections.ArrayList
function Get-VMsForVLAN {
param (
[string]$VCServer,
[string]$VLAN
)
if ($?) {
Write-Host "Connected to $VCServer"
$portGroups = Get-VDPortgroup | Where-Object { $_.Name -like "*$VLAN*" }
foreach ($port in $portGroups) {
Write-Host "Found VLAN $($port); Proceeding with checking of VMs" -foreground green
$networks = Get-View -ViewType Network -Property Name -Filter @{"Name" = $($port.name)}
$networks | ForEach-Object {
($_.UpdateViewData("Vm.Name", "Vm.Runtime.PowerState", "Vm.Guest.IPAddress"))
}
foreach ($network in $networks) {
$vms = $network.LinkedView.Vm
if ($vms) {
foreach ($vm in $vms) {
$vmName = $vm.Name
$existingEntry = $results | Where-Object { $_.'VM Name' -eq $vmName -and $_.'VLAN Name' -eq $vlan }
if ($existingEntry) {
# VM entry already exists for this VM and VLAN, skip adding it
continue
}
$connectedVMRow = [PSCustomObject]@{
'vCenter Server' = $VCServer
'VLAN Name' = $vlan
'VM Name' = $vmName
'VM IP Address' = ($vm.Guest.IPAddress | Where-Object { $_ -match '^10\.' }) -join ", "
'PowerState' = $vm.Runtime.PowerState
'PortGroup' = $network.Name
}
$null = $connectedVMCsv.Add($connectedVMRow)
# Print VM information when found
Write-Host "VM Name: $($connectedVMRow.'VM Name'), Power State: $($connectedVMRow.PowerState), IP Address: $($connectedVMRow.'VM IP Address')" -foreground cyan
$migrationRow = [PSCustomObject]@{
'VM_Name' = $vm.Name
'MIGRATION_GROUP' = $MIGRATIONGROUP
}
$null = $migrationCsv.Add($migrationRow)
}
}
}
}
# Do not disconnect here
return $results
}
else {
Write-Warning "Error connecting to vCenter Server $VCServer"
return $null
}
}
function Get-UniqueVMs {
param (
[array]$results
)
$uniqueVMs = @{}
foreach ($result in $results) {
$vmName = $result.VMName
if ($uniqueVMs.ContainsKey($vmName)) {
$uniqueVM = $uniqueVMs[$vmName]
$uniqueVM.PortGroup += ", " + $result.PortGroup
}
else {
$uniqueVMs[$vmName] = $result
}
}
return $uniqueVMs.Values
}
foreach ($server in $VCServer) {
Connect-VIServer -Server $server -User $vcUser -Password $vcPass -ErrorAction SilentlyContinue
if ($?) {
Write-Host "Connected to $server"
}
else {
Write-Warning "Error connecting to vCenter Server $server"
continue
}
foreach ($vlan in $VLANs) {
Write-Host "Running for VLAN: $vlan on vCenter Server: $server"
$vmResults = Get-VMsForVLAN -VCServer $server -VLAN $vlan
$uniqueVMResults = Get-UniqueVMs -results $vmResults
# Add unique VM entries to the results
foreach ($uniqueVMResult in $uniqueVMResults) {
$null = $allResults.Add($uniqueVMResult) # Adding to $allResults only once
}
}
# Convert ArrayList to arrays before exporting to CSV
$connectedVMArray = $connectedVMCsv.ToArray()
$migrationArray = $migrationCsv.ToArray()
# Output the CSV data for connected VMs
if ($connectedVMArray.Count -gt 0) {
Write-Host "Exporting connected VMs to CSV..."
$connectedVMArray | Export-Csv -Path $connectedVMCsvPath -NoTypeInformation -Append
}
else {
Write-Output "No virtual machines found on vCenter: $server"
}
# Output the CSV data for migration list
if ($migrationArray.Count -gt 0) {
$migrationArray | Export-Csv -Path $migrationCsvPath -NoTypeInformation -Append
}
else {
Write-Output "No virtual machines found on vCenter: $server"
}
# Disconnect from vCenter Server at the end of processing all VLANs
Write-Host "##[warning] Disconnecting from vCenterServer: $server" -ForegroundColor Red
Disconnect-VIServer -Server $server -Confirm:$false
Start-Sleep -Seconds 10
}