Automation

 View Only
  • 1.  Filter output for specific vlans

    Posted Sep 25, 2023 04:43 AM

    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
    }
     
     

     



  • 2.  RE: Filter output for specific vlans

    Posted Sep 25, 2023 06:24 AM

    Could this be because you are Appending  to the CSV without initialising it at the start of the script?



  • 3.  RE: Filter output for specific vlans

    Posted Sep 25, 2023 10:54 PM

    but i am initializing it 

    $connectedVMCsv = New-Object System.Collections.ArrayList
    $migrationCsv = New-Object System.Collections.ArrayList 

    or i missed something  



  • 4.  RE: Filter output for specific vlans

    Posted Sep 25, 2023 10:47 AM

    Here is another script for almost or maybe the same purpose as yours, though it is slightly easier to track/troubleshoot.

    The migrationGroup variable is commented out. Uncomment it (on both locations) in order to have it in the same CSV report.

     

     

    # Define the variables here
    $vCenter = "vcenter0.local","vcenter1.local","vcenter2.local"
    $VLAN = "123","321"
    $ReportExportCSVFile = "C:\report.csv"
    $vCenterUser = "user1"
    $vCenterPassword = "Password123"
    #$migrationgroup = "Group9"
    
    # Set the powercli configuration DefaultVIServer to Multiple, so that you can work with all vCenters at once
    Set-PowerCLIConfiguration -Scope Session -DefaultVIServerMode Multiple -Confirm:$false
    
    # Connect to all vCenters. If it can't, stop the command.
    try{
        Connect-VIServer -Server $vCenter -User $vCenterUser -Password $vCenterPassword
    }
    catch{
        break
    }
    
    # Function that will find all VMs on a specific vlan
    function Get-VMsForVLAN {
        param([int]$vlanID)
    
        # Get all distributed port groups accross all vCenters
        $VDPortGroups = Get-VDPortgroup | Where { $_.VlanConfiguration.VlanId -eq $vlanID}
    
        $networks = @()
        foreach($vlanName in $VDPortGroups){
            $networks += Get-View -ViewType Network -Property Name -Filter @{"Name" = $($vlanName.name)}
        }
    
        $networks | ForEach-Object {
            ($_.UpdateViewData("Vm.Name", "Vm.Runtime.PowerState", "Vm.Guest.IPAddress"))
        }
    
        # Create an empty array
        $VMsForVLanResult = @()
        foreach($VDPG in $networks){
            # Find the vCenter where that PG resides.
            $PGvCenter = (($VDPG.Client.ServiceUrl -split "//")[1] -split "/")[0]
    
            # Get all VMs that use that PG in that particular vCenter
            if($VDPG.LinkedView.Vm.Name){
                $VMsInPG = $VDPG.LinkedView.Vm
            }
            else{
                continue
            }
    
            foreach($VMPG in $VMsInPG){
                # Build a hash table with all the necessary information
                $props = [ordered]@{}
                $props.'vCenter' = $PGvCenter
                $props.'VM' = $VMPG.Name
                $props.'PowerState' = $VMPG.Runtime.PowerState
                #$props.'MigrationGroup' = $migrationgroup
                $props.'PortGroup' = $VDPG.Name
                $props.'VLAN' = $vlanID
                $props.'IP' = $VmPG.Guest.IPAddress
                
                # Store it in the Array defined above
                $VMsForVLanResult += New-Object -TypeName PScustomObject -Property $props  
            }
        }
        # When all VPGs are processed, return the result.
        return $VMsForVLanResult
    }
    
    # Store the information into a Variable
    $VLANResult = $VLAN | ForEach-Object {Get-VMsForVLAN -vlanID $_}
    
    # Print the result in the console
    $VLANResult | ft -AutoSize
    
    # Export the result to a CSV.
    $VLANResult | Export-Csv -NoTypeInformation -Path $ReportExportCSVFile
    
    # Disconnect from all vCenters
    Disconnect-VIServer -Server * -Force -Confirm:$false

     

     

     



  • 5.  RE: Filter output for specific vlans

    Posted Sep 25, 2023 10:53 PM

     

    thanks for the reply but it would work if vm in vlan but in broken state, it will only show one which are healthy



  • 6.  RE: Filter output for specific vlans

    Posted Sep 26, 2023 06:43 AM

    What do you mean with "broken state"? Which part of the script shows you the VMs that are in broken state? Can you elaborate a little bit?

     



  • 7.  RE: Filter output for specific vlans

    Posted Sep 26, 2023 07:38 AM

    what is broken state?