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
xXvenszXx
Enthusiast
Enthusiast

I connect to the vCenter through pCLI with: Connect-VIServer -Server vCENTER and run then the script. Without the -eq I get a lot of output.

Output of $global:defaultviservers is positiv with my vCENTER.

0 Kudos
LucD
Leadership
Leadership

Are there VirtualMachine entries in the output without the Where-clause?

Which PowerShell version are you running?

Do a $PSVersionTable


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

0 Kudos
xXvenszXx
Enthusiast
Enthusiast

Without -eq there was a lot of things in it - Ressources, Datacenter etc. but after 15 minutes running the script there was no VirtualMachine in the csv. and I stopped the script.

Now I will run the script again during the lunch Smiley Happy

pastedImage_0.png

0 Kudos
LucD
Leadership
Leadership

That's the latest PowerShell version, so you're good on that side.

Depending on the size of your vSphere environment, the script might indeed run quite long.

Don't you have a smaller test environment where you could test the validity of the script?

Otherwise you'll have to wait for the run to cplete, and hope the PowerShell session doesn't run out of memory 🙂


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

0 Kudos
xXvenszXx
Enthusiast
Enthusiast

I have only the big environment :smileysilly:

How can I see if my pCLI is running out of memory?

0 Kudos
LucD
Leadership
Leadership

You can do

Get-Process -Name powershell*

Note that by default the PowerShell memory stack is limited, but there are ways to increase this.

See for example Learn How to Configure PowerShell Memory


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

0 Kudos
xXvenszXx
Enthusiast
Enthusiast

Since 12:13pm script is running the csv is 214kb large Smiley Happy and included "VirtualMachine" type with 1077 cells :smileycool:.

Script is still running Smiley Happy

Finished: 1:57pm - csv 236kb - now I´m checking it!

0 Kudos
xXvenszXx
Enthusiast
Enthusiast

Great script it is to 99% perfect Smiley Happy

One question, is it possible to export the column "BluePath" and "Path" without the virtual machine name at the end or is it how VMware export it normally?

0 Kudos
LucD
Leadership
Leadership

Yes, that's possible, you'll have to change some lines.

From the line numbers in my blog post Get-InventoryPlus – Inventory of all vSphere objects

Replace line 51 and line 107 each with

      $path = @()


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

xXvenszXx
Enthusiast
Enthusiast

Thanks a lot for your great help, now all is working! Smiley Happy

0 Kudos
tvo
Contributor
Contributor

Hi LucD,

Nice script!  Is there a way to use the Get-InventoryPlus function to just export from only one Datacenter within a vCenter?  We have multiple Datacenters and I want to only export VMs and folders from one DC.  Thanks in advance for your help.

Tony

0 Kudos
LucD
Leadership
Leadership

That should be possible by changing the 1st parameter to the CreateContainerView method in line 155.

I'll have to check, and update the function slightly.

$contView = $viewMgr.CreateContainerView($si.Content.RootFolder,$null,$true)


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

0 Kudos
LucD
Leadership
Leadership

Ok, updated the function.

Can you try the attached updated version?

The inline help has been updated, and there are sample calls at the end of the file.


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

0 Kudos
tvo
Contributor
Contributor

Ran your new InventoryPlus script a few times against one of our vcenters with multiple vDCs and it worked great!  I modified lines 52 and 105 with $path = @() for cleaner output.  Thanks for script and your help!

Tony

0 Kudos
jeffreymcclain
Contributor
Contributor

Hi Luc,

I had a quick question about modifying / using your function. My objective is to export a list of all VMs, their blue and yellow paths, and certain VM properties such as power state and host name.
I am able to export the typical VM properties using "Get-VM | Select Name, PowerState, VMHost, VMHostId | Export-Csv -Path $csv -NoTypeInformation -UseCulture". I am also able to export your function's paths using "Get-InventoryPlus | where{$_.Type -eq 'VirtualMachine'} | Export-Csv -Path C:\Temp\Task1.csv -NoTypeInformation -UseCulture".

However, I am unsure how to combine these. If it's not too much trouble, it'd be awesome if you could explain how to export a single csv file with columns for Name, Host, PowerState, BluePath, and YellowPath.


P.S.: I'm relatively new to PowerShell and PowerCLI, so apologies if this is question is trivial. I came across this function the other day and really appreciate it! I also noticed you are the lead author of the PowerCLI Reference book, which is awesome!

vmCalgary
Enthusiast
Enthusiast

jeffreymcclain

LucD

Jeffery, did LucD help you with merging the folder information with the vm information? I'm looking for the same output so I can get users to authorize vm deletions. My column headers are:

Folder

Folder Path

VM Name

PowerState

VMhost

Uptime

IP address(es)

datastore

vcentre (optional)

I can do one or the other (folder vs vm information) and match up in Excel but that seems to be a waste of time. I'm just not sure of the code to use in powercli. Here's my gotcha as well...I'd like to do it for folders that contain a specific phrase such as "Wireless".

0 Kudos
LucD
Leadership
Leadership

Try like this

function Get-InventoryPlus {

    <#

.SYNOPSIS

Retrieve the objects available on a vSphere Server.

.DESCRIPTION

This function will retrieve all objects available on a

vSphere Server, including all storage and network objects.

.NOTES

Author:  Luc Dekens

.PARAMETER Server

The vSphere Server (vCenter or ESXi) from which to retrieve

the objects.

The default is $Global:DefaultVIServer

.PARAMETER NoValue

Properties that are not set are returned as an empty string.

The value on this parameter will be used instead of the empty

string.

.PARAMETER RootObject

A .Net PowerCLI object from where the inventory shall start

.EXAMPLE

PS> Get-InventoryPlus

.EXAMPLE

PS> Get-InventoryPlus -Server $vCenter

.EXAMPLE

PS> Get-InventoryPlus -NoValue 'na'

.EXAMPLE

PS> Get-InventoryPlus -RootObject (Get-Datacenter -Name DC1)

#>

    [cmdletbinding()]

    param(

        [VMware.VimAutomation.ViCore.Types.V1.VIServer]$Server = $Global:DefaultVIServer,

        [String]$NoValue = '',

        [VMware.VimAutomation.ViCore.Types.V1.Inventory.InventoryItem]$RootObject

    )

    function Get-ViBlueFolderPath {

        [cmdletbinding()]

        param(

            [VMware.Vim.ManagedEntity]$Item

        )

        $hidden = 'Datacenters', 'vm'

        if ($Item -is [VMware.Vim.VirtualMachine]) {

            $Item.UpdateViewData('Parent')

            $parent = $Item.Parent

        }

        elseif ($Item -is [VMware.Vim.VirtualApp]) {

            $Item.UpdateViewData('ParentFolder')

            $parent = $Item.ParentFolder

        }

        if ($parent) {

            $path = @($Item.Name)

            while ($parent) {

                $object = Get-View -Id $parent -Property Name, Parent

                if ($hidden -notcontains $object.Name) {

                    $path += $object.Name

                }

                if ($object -is [VMware.Vim.VirtualApp]) {

                    $object.UpdateViewData('ParentFolder')

                    if ($object.ParentFolder) {

                        $parent = $object.ParentFolder

                    }

                    else {

                        $object.UpdateViewData('ParentVapp')

                        if ($object.ParentVapp) {

                            $parent = $object.ParentVapp

                        }

                    }

                }

                else {

                    $parent = $object.Parent

                }

            }

            [array]::Reverse($path)

            return "/$($path -join '/')"

        }

        else {

            return $NoValue

        }

    }

    function Get-ObjectInfo {

        [cmdletbinding()]

        param(

            [parameter(ValueFromPipeline)]

            [VMware.Vim.ManagedEntity]$Object

        )

        Begin {

            $hidden = 'Datacenters', 'vm', 'host', 'network', 'datastore', 'Resources'

        }

        Process {

            if ($hidden -notcontains $Object.Name) {

                $props = [ordered]@{

                    Name     = $Object.Name

                    Type     = $Object.GetType().Name

                    BluePath = $NoValue

                }

                $blueFolder = $false

                $isTemplate = $false

                if ($object -is [VMware.Vim.Folder]) {

                    $object.UpdateViewData('ChildType')

                    if ($Object.ChildType -contains 'VirtualMachine') {

                        $blueFolder = $true

                    }

                }

                $path = @($Object.Name)

                $parent = $Object.Parent

                if ($object -is [VMware.Vim.VirtualMachine] -or $object -is [VMware.Vim.VirtualApp]) {

                    $props['BluePath'] = Get-VIBlueFolderPath -Item $Object

                    if ($Object -is [VMware.Vim.VirtualMachine]) {

                        $Object.UpdateViewData('ResourcePool', 'Config.Template')

                        if ($Object.Config.Template) {

                            $parent = $Object.Parent

                            $props['Type'] = 'Template'

                            $isTemplate = $true

                        }

                        else {

                            $parent = $Object.ResourcePool

                        }

                    }

                }

                while ($parent) {

                    $Object = Get-View -Id $Parent -Property Name, Parent

                    $parent = $Object.Parent

                    if ($hidden -notcontains $Object.Name) {

                        $path += $Object.Name

                    }

                }

                [array]::Reverse($path)

                $path = "/$($path -join '/')"

                $props.Add('Path', $path)

                if ($blueFolder) {

                    $props['BluePath'] = $props['Path']

                    $props['Path'] = $NoValue

                }

                if ($isTemplate) {

                    $props['Path'] = $NoValue

                }

                New-Object PSObject -Property $props

            }

        }

    }

    $sView = @{

        Id       = 'ServiceInstance'

        Server   = $Server

        Property = 'Content.ViewManager', 'Content.RootFolder'

    }

    $si = Get-view @sView

    if (-not $RootObject) {

        $RootMoRef = $si.Content.RootFolder

    }

    else {

        $RootMoRef = $RootObject.ExtensionData.MoRef

    }

    $viewMgr = Get-View -Id $si.Content.ViewManager

    $contView = $viewMgr.CreateContainerView($RootMoRef, $null, $true)

    $contViewObj = Get-View -Id $contView

    Get-View -Id $contViewObj.View -Property Name, Parent |

        Where-Object {$hidden -notcontains $_.Name} |

        Get-ObjectInfo

}

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

ForEach-Object -Process {

    $vm = Get-VM $_.Name

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

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

    $_ | Add-Member -Name Uptime -Value $vm.ExtensionData.Summary.QuickSTats.UptimeSeconds -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's almost exactly what I want. I've inserted the output below.

2018-12-28_19-48-32.jpg

1. I'm looking to limit it to a particular folder with wildcard (vCloud*) to shorten my results. I'm not sure how to insert that into the process.

2. I would also like a bit of help understanding blue path vs yellow path. I've been reading your blog on Get-InventoryPlus and am not comprehending it.

3. Uptime:  $_ | Add-Member -Name Uptime -Value $vm.ExtensionData.Summary.QuickSTats.UptimeSeconds ----> how do I get this rounded to days vs seconds?

You've been a great teacher, Luc. I look forward to your reply.

VMware_scripts> get-folder vClou*

Name                               Type

----                                     ----

vCloud (CG-ZZ)                 VM

vCloud (CG-NL)                 VM

0 Kudos
LucD
Leadership
Leadership

1) The function supports a RootObject parameter, which is a starting point in your vSphere inventory from where to start the inventory.
By passing all the selected folders (from the mask) one by one to the function, you get the inventory from all the folders.

2) The yellow and blue stems from the fat vSphere Client.
In short, yellow folders are the ones of type VM, blue are the ones of type HostAndCluster.
It comes down to the fact that you can locate a VM in these 2 ways, once where it is located in the Datacenter-Cluster-VMHost hierarchy,
and once via the VM and Templates view (Datacenter - Folder)

3) With the TimeStamp type you can easily convert seconds into days.

Only the last part needs some changes to implement 1) and 3)

Get-Folder -Name vCloud* |

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 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

vmCalgary
Enthusiast
Enthusiast

Thank you, LucD , for the explanation and information regarding seconds to days. As always with your guidance, it worked like a charm.

0 Kudos