VMware Cloud Community
andrew_uk
Enthusiast
Enthusiast
Jump to solution

VM Folder Path

Hello

I am trying to export a list of VMs which are powered off with their folder paths. I have tried using LucD script which gives me paths for everything not just VMs, such as datastores and network. Once it gets to a certain limit the csv clears and starts over. 

I tried this:

file = Import-Csv C:\Users\563937\Documents\poweredoffvms.csv

foreach ($vm in $vmfile.vmname) { Get-InventoryPlus | Export-Csv C:\Users\563937\Documents\poweredoffpath.csv -Append }

 

Any help would be appreciated.

Thanks

0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

That is exactly what Get-InventoryPlus is doing.
And in fact, the function only needs a small change to only return VMs.
Which allows you to do something 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.
.EXAMPLE
PS> Get-InventoryPlus
.EXAMPLE
PS> Get-InventoryPlus -Server $vCenter
.EXAMPLE
PS> Get-InventoryPlus -NoValue 'na'
#>
    [cmdletbinding()]
    param(
        [VMware.VimAutomation.ViCore.Types.V1.VIServer]$Server = $Global:DefaultVIServer,
        [String]$NoValue = ''
    )
    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
    $viewMgr = Get-View -Id $si.Content.ViewManager
    $contView = $viewMgr.CreateContainerView($si.Content.RootFolder, @('VirtualMachine'), $true)
    $contViewObj = Get-View -Id $contView
    Get-View -Id $contViewObj.View -Property Name, Parent | 
        where { $hidden -notcontains $_.Name } | 
        Get-ObjectInfo
}

Get-InventoryPlus | select Name, BluePath, Path 

 


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

View solution in original post

13 Replies
LucD
Leadership
Leadership
Jump to solution

The issue is that you are running a full inventory for each powered off VM.

The Get-InventoryPlus function does not take a VM parameter.
You could do something like this

$file = Import-Csv C:\Users\563937\Documents\poweredoffvms.csv

Get-InventoryPlus | 
Where{$_.Type -eq 'VirtualMachine' -and $file.vmname -contains $_.Name} |
Export-Csv -Path .\report.csv -NoTypeInformation -UseCulture

But that is a bit of a waste of resources, since you are running an inventory over the full environment, while you only want powered off VMs.
Which properties do you actually want for the VMs?
Both folder paths?


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

0 Kudos
andrew_uk
Enthusiast
Enthusiast
Jump to solution

Thanks for getting back so quickly. I'm not sure what you mean by both folder paths.

Ideally I would like a CSV which contains only powered off VMs and shows:

VM name      Path    

vm1              \path to vm

vm2               \path to vm

If it's easier, I already have a CSV with powered off VMs which I was trying to use.

Tags (1)
0 Kudos
LucD
Leadership
Leadership
Jump to solution

A VM has 2 paths, one under the Hosts and Clusters folder and one under the VMs and Templates folder.
These used to be called the blue and yellow folder paths.

These are the 2 paths the Get-InventoryPlus function returns for VMs.

Which folderpath do you want in the resulting CSV?


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

0 Kudos
andrew_uk
Enthusiast
Enthusiast
Jump to solution

Ahh that makes sense. Is it possible to have it show both paths? or Hosts & Clusters then I can try to modify it.

Thank you

Tags (1)
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is exactly what Get-InventoryPlus is doing.
And in fact, the function only needs a small change to only return VMs.
Which allows you to do something 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.
.EXAMPLE
PS> Get-InventoryPlus
.EXAMPLE
PS> Get-InventoryPlus -Server $vCenter
.EXAMPLE
PS> Get-InventoryPlus -NoValue 'na'
#>
    [cmdletbinding()]
    param(
        [VMware.VimAutomation.ViCore.Types.V1.VIServer]$Server = $Global:DefaultVIServer,
        [String]$NoValue = ''
    )
    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
    $viewMgr = Get-View -Id $si.Content.ViewManager
    $contView = $viewMgr.CreateContainerView($si.Content.RootFolder, @('VirtualMachine'), $true)
    $contViewObj = Get-View -Id $contView
    Get-View -Id $contViewObj.View -Property Name, Parent | 
        where { $hidden -notcontains $_.Name } | 
        Get-ObjectInfo
}

Get-InventoryPlus | select Name, BluePath, Path 

 


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

andrew_uk
Enthusiast
Enthusiast
Jump to solution

That simple, amazing. Thank you. The BluePath is blank, do you know why that might be? 

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Not really.
I would need to know how your folder structure under VMs and Templates is organised.
Does it start with a Datacenter or a Folder?


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

0 Kudos
andrew_uk
Enthusiast
Enthusiast
Jump to solution

It starts with a Datacenter

0 Kudos
andrew_uk
Enthusiast
Enthusiast
Jump to solution

Edit: It is showing me VM networks and Datastores as well, can I have it show only VMs? 

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Good to hear.

I think you already did by selecting one of my answers as the Solution


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

Tags (1)
0 Kudos
andrew_uk
Enthusiast
Enthusiast
Jump to solution

It is showing me other object paths such as networks and datastores as well, can I have it show only VMs? 

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Are you sure you are using the latest version I posted?
The one with the line

 

$contView = $viewMgr.CreateContainerView($si.Content.RootFolder, @('VirtualMachine'), $true)

 


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

andrew_uk
Enthusiast
Enthusiast
Jump to solution

 

Thanks so much! Results exactly what I needed. 

0 Kudos