I am trying to find a script that will output the following information:
I thought I saw one here before but can't seem to find it anywhere. Any help would be greatly appreciated!
You get the error message using the function because the function expects a VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl object and you give it a VMware.Vim.VirtualMachine object. If you change your part of the code into:
# Connect to VIServer Connect-VIServer $VIServer #Initialise Array $Report = @() # Gather VM Size Information $AllVMs = Get-VM ForEach ($vm in $AllVMs){ $Size = Get-VmSize($vm) } $Report += $Size $Report | Export-Csv "C:\VMDiskSize.csv" # Disconnect from VIServer Disconnect-VIServer $VIServer -Confirm:$False
It will not give an error. But it will also not give the desired output as it will give you the total disk size of all virtual machines.
You will get the desired result with:
# Connect to VIServer Connect-VIServer $VIServer #Initialise Array $Report = @() # Gather VM Size Information $AllVMs = Get-VM ForEach ($vm in $AllVMs){ $Row = "" | Select-Object VM,Size $Row.VM = $vm.Name $Row.Size = (Get-VmSize($vm))/1GB $Report += $Row } $Report | Export-Csv "C:\VMDiskSize.csv" # Disconnect from VIServer Disconnect-VIServer $VIServer -Confirm:$False
I wrote a function for this a while ago. Have a look at
http://www.van-lieshout.com/2009/07/how-big-is-my-vm/
Cheers,
Arnim
Not sure if I am using this correctly but here is the script that was put together using your function:
#Global Functions
function Get-VmSize($vm)
{
#Initialize variables
$VmDirs =@()
$VmSize = 0
$searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
$searchSpec.details = New-Object VMware.Vim.FileQueryFlags
$searchSpec.details.fileSize = $TRUE
Get-View -VIObject $vm | % {
#Create an array with the vm's directories
$VmDirs += $_.Config.Files.VmPathName.split("/")[0]
$VmDirs += $_.Config.Files.SnapshotDirectory.split("/")[0]
$VmDirs += $_.Config.Files.SuspendDirectory.split("/")[0]
$VmDirs += $_.Config.Files.LogDirectory.split("/")[0]
#Add directories of the vm's virtual disk files
foreach ($disk in $_.Layout.Disk) {
foreach ($diskfile in $disk.diskfile){
$VmDirs += $diskfile.split("/")[0]
}
}
#Only take unique array items
$VmDirs = $VmDirs | Sort | Get-Unique
foreach ($dir in $VmDirs){
$ds = Get-Datastore ($dir.split("[")[1]).split("]")[0]
$dsb = Get-View (($ds | get-view).Browser)
$taskMoRef = $dsb.SearchDatastoreSubFolders_Task($dir,$searchSpec)
$task = Get-View $taskMoRef
while($task.Info.State -eq "running" -or $task.Info.State -eq "queued"){$task = Get-View $taskMoRef }
foreach ($result in $task.Info.Result){
foreach ($file in $result.File){
$VmSize += $file.FileSize
}
}
}
}
return $VmSize
}
# Connect to VIServer
Connect-VIServer $VIServer
#Initialise Array
$Report = @()
# Gather VM Size Information
$AllVMs = Get-View -ViewType VirtualMachine | Where {-not $_.Config.Template}
ForEach ($vm in $AllVMs){
$Size = Get-VmSize($vm)
}
$Report += $Size
$Report | Export-Csv "C:\VMDiskSize.csv"
# Disconnect from VIServer
Disconnect-VIServer $VIServer -Confirm:$False
When I run it I get the following error:
Cannot bind parameter 'VIObject'. Cannot convert the "VMware.Vim.VirtualMachine" value of type "VMware.Vim.VirtualMachine" to type "VMware.VimAutomation.Sdk.Types.V1.VIObject".
At :line:17 char:22
+ Get-View -VIObject <<<< $vm | % {
Thanks for your help on this!
Why don't you use:
Get-VM | Select-Object Name,UsedSpaceGB | Export-Csv "C:\VMDiskSize.csv"
Regards, Robert
This doesn't return what I need. When I run that, it actually returns -1 for everything. I forgot to mention that this is querying against a 3.5 deployment and not 4.X.
Hey, @jamesbowling-
Looks like the function Get-VMSize is expecting a VM object (as returned by Get-VM) instead of the VirtualMachine View object that you are passing to it. The line
Get-View -VIObject $vm | % {...
tries to get the View object from the parameter "$vm". So, you could either update that line in the function to just pipe the View object that you are passing like:
$vm | %{...
or you could adjust the way that you are using the function to pass it VM objects instead of View objects. I would go with the former (pass View objects to the function, update the function to accept/use them) for the sake of speed (should run far quicker when using the View objects versus using Get-VM).
Oh, and for the sake of reading/understanding code later, maybe rename the $vm variable to $viewVM or something, so as to hint at the object type...
You get the error message using the function because the function expects a VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl object and you give it a VMware.Vim.VirtualMachine object. If you change your part of the code into:
# Connect to VIServer Connect-VIServer $VIServer #Initialise Array $Report = @() # Gather VM Size Information $AllVMs = Get-VM ForEach ($vm in $AllVMs){ $Size = Get-VmSize($vm) } $Report += $Size $Report | Export-Csv "C:\VMDiskSize.csv" # Disconnect from VIServer Disconnect-VIServer $VIServer -Confirm:$False
It will not give an error. But it will also not give the desired output as it will give you the total disk size of all virtual machines.
You will get the desired result with:
# Connect to VIServer Connect-VIServer $VIServer #Initialise Array $Report = @() # Gather VM Size Information $AllVMs = Get-VM ForEach ($vm in $AllVMs){ $Row = "" | Select-Object VM,Size $Row.VM = $vm.Name $Row.Size = (Get-VmSize($vm))/1GB $Report += $Row } $Report | Export-Csv "C:\VMDiskSize.csv" # Disconnect from VIServer Disconnect-VIServer $VIServer -Confirm:$False
Thanks for the quick replies! It is working correctly now. Thanks for your help!
You're welcome.
How could you do this for just a list of VM's?
I know how to import a csv and key off of it, but I can't get the array/string stuff right... It works great agaist the whole vcenter though.
Thanks!