xXvenszXx
Enthusiast
Enthusiast

Export list of VMs with complete folder path

Jump to solution

Hi all,

I´m not a scripter so I need your help for my environemnt - 1 vcenter 5 datacenters without templates.

I need an export in csv contains the BlueFolderPath, I found a lot of scripts using Get-Folder and Get-FolderPath (is not recognized as the name of a cmdlet) something like that but nothing is working.

example CSV:

AB
testvm1DATACENTER\Applications\Banking\external
testvm2DATACENTER\Applications\Banking
testvm3DATACENTER\
testvm4DATACENTER\Applications

I found a lot of scripts from LucD but I think I´m to stuipd to get it to fly.

Get the folderpath - LucD notes

Folder by Path - LucD notes

I hope someone can help me Smiley Sad

Thanks a lot

Greetings

49 Replies
vmCalgary
Enthusiast
Enthusiast

LucD , perhaps I spoke too soon.

2018-12-31_16-38-15.jpg

I modified your script slightly to capture sizing information. I also had to comment out the uptime field as it was occasionally generating an error (my apologies, I didn't capture it).

I am concerned the script is stuck in a loop as it's been running for hours.

Here's my script:

#Report on vcloud vms - need users to decide what to do where there are duplicate names

$report = @()

Get-Folder -Name *|

ForEach-Object -Process {

    Get-InventoryPlus -RootObject $_ | where{$_.Type -eq 'VirtualMachine'} |

    ForEach-Object -Process {

        $vm = Get-VM $_.Name

        $_ | Add-Member -Name PowerSTate -Value $vm.PowerState -MemberType NoteProperty

        $_ | Add-Member -Name OSName -Value $vm.guest.hostname -MemberType NoteProperty

        $_ | Add-Member -Name VMHost -Value $vm.VMHost.Name -MemberType NoteProperty

        #$_ | Add-Member -Name UptimeDays -Value ([math]::Round(([TimeSpan]::FromSeconds($vm.ExtensionData.Summary.QuickSTats.UptimeSeconds)).TotalDays,0)) -MemberType NoteProperty (paste word wrapped)

        $_ | Add-Member -Name IPAddress -Value ($vm.Guest.IPAddress -join '|') -MemberType NoteProperty

       

        $_ | Add-Member -Name Datastore -Value ((Get-View -Id $vm.DatastoreIdList -Property Name).Name -join '|') -MemberType NoteProperty

        $_ | Add-Member -Name VMid -Value $vm.id -MemberType NoteProperty

        $_ | Add-Member -Name MemoryMB -Value $vm.MemoryMB -MemberType NoteProperty

        $_ | Add-Member -Name NumCPU -Value $vm.NumCPU -MemberType NoteProperty

        $_ | Add-Member -Name UsedSpaceGB -Value $vm.UsedSpaceGB -MemberType NoteProperty

      

        $_ | Add-Member -Name vCenter -Value (([uri]$vm.ExtensionData.Client.ServiceUrl).Host) -MemberType NoteProperty

        #$_| Add-Member -Name Notes -Value ($vm.Notes) -MemberType NoteProperty

  

        $_

    }

}

$report

0 Kudos
vmCalgary
Enthusiast
Enthusiast

2018-12-31_16-58-17.jpg

LucD - randomly this pops up (see image). This is similar to what the math on uptime showed.

0 Kudos
LucD
Leadership
Leadership

The Get-InventoryPlus function re curses through the complete hierarchy starting from the RootObject.

With Get-Folder -Name * you will be feeding all your folders one-by-one into the function, meaning that nested folders will be visited multiple times.

Which could also explain the long runtime you see.

A better option might be for example to start from all folders directly under a datacenter. For example:

Get-Datacenter -Name MyDC | Get-Folder -Name * -NoRecursion |

The error you are seeing might be coming from the fact that you have VMs with the same DisplayName in different folders.
Is that case?
If yes, we could fix that by using the full path and my Get-FolderByPath function.

The script (minus the Get-InventoryPlus function) would then be

function Get-FolderByPath{

<#

.SYNOPSIS Retrieve folders by giving a path

.DESCRIPTION The function will retrieve a folder by it's path.

The path can contain any type of leave (folder or datacenter).

.NOTES Author: Luc Dekens

.PARAMETER Path The path to the folder. This is a required parameter.

.PARAMETER Separator The character that is used to separate the leaves

in the path. The default is '/'

.EXAMPLE

  PS> Get-FolderByPath -Path "Folder1/Datacenter/Folder2"

.EXAMPLE

  PS> Get-FolderByPath -Path "Folder1>Folder2" -Separator '>'

#>

  param(

  [CmdletBinding()]

  [parameter(Mandatory = $true)]

  [System.String[]]${Path},

  [char]${Separator} = '/'

  )

  process{

    if((Get-PowerCLIConfiguration).DefaultVIServerMode -eq "Multiple"){

      $vcs = $defaultVIServers

    }

    else{

      $vcs = $defaultVIServers[0]

    }

    foreach($vc in $vcs){

      foreach($strPath in $Path){

        $root = Get-Folder -Name Datacenters -Server $vc

        $strPath.Split($Separator) | %{

          $root = Get-Inventory -Name $_ -Location $root -Server $vc -NoRecursion

          if((Get-Inventory -Location $root -NoRecursion | Select -ExpandProperty Name) -contains "vm"){

            $root = Get-Inventory -Name "vm" -Location $root -Server $vc -NoRecursion

          }

        }

        $root | where {$_ -is [VMware.VimAutomation.ViCore.Impl.V1.Inventory.FolderImpl]}|%{

          Get-Folder -Name $_.Name -Location $root.Parent -NoRecursion -Server $vc

        }

      }

    }

  }

}

Get-Folder -Name linux* |

ForEach-Object -Process {

    Get-InventoryPlus -RootObject $_ | where{$_.Type -eq 'VirtualMachine'} |

    ForEach-Object -Process {

        $qual = $_.BluePath.TrimStart('/').Split('/')

        $folder = Get-FolderByPath -Path ($qual[0..($qual.Count - 2)] -join '/')

        $vm = Get-VM $_.Name -Location $folder

        $_ | Add-Member -Name PowerSTate -Value $vm.PowerState -MemberType NoteProperty

        $_ | Add-Member -Name VMHost -Value $vm.VMHost.Name -MemberType NoteProperty

        $_ | Add-Member -Name UptimeDays -Value ([math]::Round(([TimeSpan]::FromSeconds($vm.ExtensionData.Summary.QuickSTats.UptimeSeconds)).TotalDays,0)) -MemberType NoteProperty

        $_ | Add-Member -Name IPAddress -Value ($vm.Guest.IPAddress -join '|') -MemberType NoteProperty

        $_ | Add-Member -Name Datastore -Value ((Get-View -Id $vm.DatastoreIdList -Property Name).Name -join '|') -MemberType NoteProperty

        $_ | Add-Member -Name vCenter -Value (([uri]$vm.ExtensionData.Client.ServiceUrl).Host) -MemberType NoteProperty

  

        $_

    }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
vmCalgary
Enthusiast
Enthusiast

LucD

That makes sense and I'm willing to give it a go. However, I have several datacenters in my vcenter and I don't want to give it a go with the wrong ask, ie: a wildcard for the datacenter.

Get-Datacenter -Name MyDC | Get-Folder -Name * -NoRecursion |

--> I'd be entering Get-Datacenter -Name * | Get-Folder -Name * - NoRecursion. Seems like too many wildcards to me.

0 Kudos
vmCalgary
Enthusiast
Enthusiast

Also, my VMs have unique VM names. They potentially have similar beginning characters of the VM names (container names) as shown in this example below. Is that what you mean by display names?

2019-01-02_10-31-38.jpg

0 Kudos
LucD
Leadership
Leadership

The problem with the incorrect properties was due to the fact that you probably have folders with the same name.
That is fixed by using the Get-FolderByPath function, that should only return 1 folder.

I don't think there is a problem with the VM names, just the fact that there are folders with the same name in different locations.
You can just start with Get-VM -Name *, and thanks to the Get-FolderByPath function, the previous folder related errors should be gone.

The 2nd issue I mentioned is that Get-Folder -Name * (with the -NoRecursion), will return all folders (including children, grand-children...)
Since Get-InventoryPlus also does a recursion, starting from the root or from the location specified on the RootObject parameter, you would end up with having the same inventory object multiple times in the report.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

vmCalgary
Enthusiast
Enthusiast

LucD

I'm noticing a random aside that likely makes no difference to my results.

If the folder has a forward slash in it's name I get the following message. I'm not going to worry about it as my vm count is correct.

2019-01-02_13-27-31.jpg

If I had the cycles, I'd rename the folders with an acceptable character, but I'd want to do it with regular expressions vs one by one.EG: current name:Linux/Unix --> rename to Linux-Unix.  (if '/' is in the folder name replace with '-').

0 Kudos
LucD
Leadership
Leadership

Perhaps try replacing that line with

$root = Get-Inventory -Name ($_ -replace '%2f','/') -Location $root -Server $vc -NoRecursion

Changing the foldernames to eliminate the '/' isn't too hard.

Depending on the vSphere version, you might have to look for/replace %2f instead of /

Get-Folder | Set-Folder -Name ($_.Name -replace '%2f','-') -Confirm:$false


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

mmhussan
Contributor
Contributor

What exactly is the blue and yellow folder types

0 Kudos
LucD
Leadership
Leadership

The colours are a relic of the past.
The yellow folders are the ones under Hosts and Clusters (hidden folder host), the blue ones under VMs and Templates (hidden folder vm).


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos