In an older post, named Folder by Path, I provided a function to retrieve a Folder object by it’s path.
With the recent publication of my Get-InventoryPlus function, I can now get the path to all vSphere objects. So the obvious next step was to create a function, that would be able to use that information and retrieve any vSphere object by it’s path.
The function was first demonstrated during the 24th VMUGBe in Mechelen.
The Script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
function Get-VIObjectByPath{ <# .SYNOPSIS Retrieve a vSphere object by it's path. .DESCRIPTION This function will retrieve a vSphere object from it's path. The path can be absolute or relative. When a relative path is provided, the StartNode needs to be provided .NOTES Author: Luc Dekens .PARAMETER StartNode The vSphere Server (vCenter or ESXi) from which to retrieve the objects. The default is $Global:DefaultVIServer .PARAMETER Path A string with the absolute or relative path. The path shall not contain any hidden folders. .EXAMPLE PS> Get-VIObjectByPath -Path '/Datacenter/Folder/VM1' .EXAMPLE PS> Get-InventoryPlus -StartNode $node -Path $path #> param( [VMware.Vim.ManagedEntity]$StartNode = ( Get-View -Id (Get-View -Id ServiceInstance).Content.RootFolder ), [String]$Path ) function Get-NodeChild{ param( [VMware.Vim.ManagedEntity]$Node ) $hidden = 'vm','host','network','datastore','Resources' switch($Node){ {$_ -is [VMware.Vim.Folder]}{ if($Node.ChildEntity){ Get-View -Id $Node.ChildEntity } } {$_ -is [VMware.Vim.Datacenter]}{ $all = @() $all += Get-View -Id $Node.VmFolder $all += Get-View -Id $Node.HostFolder $all += Get-View -Id $Node.DatastoreFolder $all += Get-View -Id $Node.NetworkFolder $all | %{ if($hidden -contains $_.Name){ Get-NodeChild -Node $_ } else{ $_ } } } {$_ -is [VMware.Vim.ClusterComputeResource]}{ $all = @() $all += Get-View -Id $Node.Host $all += Get-View -Id $Node.ResourcePool $all = $all | %{ if($hidden -contains $_.Name){ Get-NodeChild -Node $_ } else{ $_ } } $all } {$_ -is [VMware.Vim.ResourcePool]}{ $all = @() if($Node.ResourcePool){ $all += Get-View -Id $Node.ResourcePool } if($Node.vm){ $all += Get-View -Id $Node.vm } $all } {$_ -is [VMware.Vim.DistributedVirtualSwitch]}{ Get-View -Id $Node.Portgroup } } } $found = $true # Loop through Path $node = $StartNode foreach($qualifier in $Path.TrimStart('/').Split('/',[StringSplitOptions]::RemoveEmptyEntries)){ $nodeMatch = @($node) | %{ Get-NodeChild -Node $_ | where{$_.Name -eq $qualifier} } if(!$nodeMatch){ $found = $false $node = $null break } $node = $nodeMatch } New-Object PSObject -Property @{ Path = $Path Found = $found Node = $node } } |
Annotations
Line 26-28: The default StartNode is the RootFolder of the default vSphere server ($Global:DefaultVIServer)
Line 32-87: A inline Helper function that will return all children of a node. When a of the childnode is one of the hidden folders, the helper calls itself recursively. This to avoid returning one of the hidden folders.
Line 38: Depending on the Type of the node, different properties need to be used to find the children of a node.
Line 46-48: A Datacenter node points to four hidden folders. Each of these hidden folders in turn points to a number of other objects of a specific type.
Line 93: To avoid that the Split method returns an empty object when the Path is just the root (/), the [StringSplitOptions]::RemoveEmptyEntries option needs to be used.
Line 105-109: The result is returned as a custom object. The properties of this custom object allows easy access to the results: was the node found, what was the path and what is the actual VIObject.
Sample Usage
Simple
In it’s simplest form, you just provide a path with the Path parameter.
1 |
Get-VIObjectByPath -Path '/Folder11' |
The result is an object with a number of properties:
- Path: the path that was passed into the function
- Found: a Boolean, indicating if the node was found
- Node: the actual vSphere object
Inventory Check
We can use the output of the Get-InventoryPlus function, record the result, and then check if all the vSphere objects that were reported are still there. Kind of an iCheck 😆
The inventory was created with the following lines
1 2 |
Get-VIObjectByPath -NoValue 'na' | Export-Csv -Path c:\Temp\inventory.csv -NoTypeInformation -UseCulture |
The resulting CSV file looks something like this
The following script will read the inventory, and use the Get-VIObjectByPath function to check if each of the nodes in the inventory is still there.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
function Test-NodePath{ param( [String]$Path ) $nodeObj = Get-VIObjectByPath -Path $Path if($nodeObj.Found){$true}else{$false} } foreach($entry in (Import-Csv C:\Temp\inventory.csv -UseCulture)){ $path = $entry.Path Write-Host "$($Entry.Type) $($entry.Name)" if($entry.Path -ne 'na'){ Write-Host -ForegroundColor Yellow "`tPath " -NoNewline Write-Host "$($Entry.Path)" -NoNewline if(Test-NodePath -Path $entry.Path){ Write-Host -ForegroundColor Green "`tok" } else{ Write-Host -ForegroundColor Yellow "`tnok" } } if($entry.BluePath -ne 'na'){ Write-Host -ForegroundColor Cyan "`tBluePath " -NoNewline Write-Host "$($Entry.BluePath)" -NoNewline if(Test-NodePath -StartNode $rootFolder -Path $entry.BluePath){ Write-Host -ForegroundColor Green "`tok" } else{ Write-Host -ForegroundColor Yellow "`tnok" } } } |
The result is displayed on the PS console (yes, I know this must have killed a lot of puppies), and looks like this.
Looks like the junior admin removed a VM !
Enjoy!
Herschelle42
Minor code correction : The second example in the function help is calling get-inventoryplus instead of get-viobjectbypath
LucD
Thanks for spotting that.
That was the “work” name of the function