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
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
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
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.
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
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
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
That simple, amazing. Thank you. The BluePath is blank, do you know why that might be?
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
It starts with a Datacenter
Edit: It is showing me VM networks and Datastores as well, can I have it show only VMs?
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
It is showing me other object paths such as networks and datastores as well, can I have it show only VMs?
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
Thanks so much! Results exactly what I needed.