VMware Cloud Community
Munster99
Enthusiast
Enthusiast
Jump to solution

help reqd with an advanced function from LucD's book

Hey All

Recently bought Luc dekens book "Automating vSphere Administration" to help me understand how to create advanced functions (amongst other things). I tried one of his scripts on pg 437 (Get-VMGuestDiskUsage - as shown below). Problems is I'm experiencing some issues and I don't know what seems to be the problem. It possibly could be something very basic (but having worked on this for a week) I'm at the end of my tether as to understand what it could be ???? Any help would be great ly appreciated

Problem 1 ) Whenever i try and input any VMs via the pipeline, whether they be from a txt file or a simple 'get-vm' command I keep getting

cmdlet Get-VMGuestDiskUsage at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
vm
:

AND then


Cannot process argument transformation on parameter 'vm'. Cannot convert the "" value of type "System.String" to type "VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl".

I understand this is because the input objects are of a 'System.string' type and what i need is a 'VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl' object type. But its declared at the top so I don't get it ??????

Problem 2 )

Where it says $objDisk | Add-Member -MemberType Noteproperty -Name "Usage %" -value ("{0:p2}" -f (($disk.capacity - $disk.FreeSpace) / $disk.Capacity ))

There seems to be a problem with the DIVIDE operator (it doesnt work when actioned against the ($disk.capacity - $disk.freespace) value ) I have tried entering in things like '1mb' but whenever i replace them back with $disk.capacity I dont get the output ???!!!??

I know this might be easy for the the 'gurus' out there but I've realised how handy these advanced functions are and once I can get my head around as to why this is happening hopefully I'll be able to improve on what i've learnt a lot quicker. I simply cannot get it to work and hence desperately need your help. What is it I'm NOT doing ?????

The script is below and I have copied it exactly from the book (the only thing I added was a call at the bottom of the function an entry calling the actual function (i.e. Get-VMGuestDiskUsage)

Again Many thanks in advance for any help

Munster99

Function Get-VMGuestDiskUsage{
<#
.SYNOPSIS
Gets a VMs guest OS Disk Usage Information
.DESCRIPTION
This function creates a report with disk usage information of VMs guest OS
.NOTES
Source: Automating vSphere Administration
Authors: Luc Dekens, Armin Van Lieshout, Jonathan Medd,
Alan Renouf, Glenn Sizemore
.PARAMETER VM
The VM object to create a report on
.EXAMPLE
PS> Get-VMGuestDiskUsage -VM (get-VM Win*)
.EXAMPLE
PS> Get-VM | Get-VMGuestDiskUsage
#>

[CmdletBinding()]
Param(
        [Parameter(Mandatory=$True
        ,ValueFromPipeline=$True
        ,HelpMessage="Enter a VM object")]
        [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl]$vm)
       
PROCESS{
    # Hide errors which appear if VMware Tools is not installed
    # or VM is PoweredOff
    $ErrorActionPreference = "SilentlyContinue"   
       
        $vm = Get-VM ($_)
       
        foreach ($disk in $vm.guest.disks){
        $objDisk = New-Object system.object
        $objDisk | Add-Member -MemberType Noteproperty -Name VM -value $vm.name
        $objDisk | Add-Member -MemberType Noteproperty -Name Volume -value $disk.path
        $objDisk | Add-Member -MemberType Noteproperty -Name CapacityMB -value ([math]::Round($disk.capacity/1MB))
        $objDisk | Add-Member -MemberType Noteproperty -Name FreeSpaceMB -value ([math]::Round($disk.freespace/1MB))
        $objDisk | Add-Member -MemberType Noteproperty -Name "Usage %" -value ("{0:p2}" -f (($disk.capacity - $disk.FreeSpace) / $disk.Capacity ))
        $objDisk
        }
      }
}

Get-VMGuestDiskUsage

0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Remove the last line from the .ps1 file and then dot-source the .ps1 file again

. ./Get-VMGuestDiskUsage.ps1

Then, on the command line do

Get-Command Get-VMGuestDiskUsage

This should tell you if the function is known to the PS engine after you dot-sourced the .ps1 file.

If it is known, just do

Get-VM MyVM | Get-VMGuestDiskUsage


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

View solution in original post

0 Kudos
16 Replies
LucD
Leadership
Leadership
Jump to solution

I assume you did call the function as follows

Get-VM MyVM | Get-VMGuestDiskUsage

I'm afraid that function doesn't support OBN (Object By Name), you have to give it a VirtualMachineImpl object, or objects, with the VM parameter.

The reason the divide doesn't work is probably because the $disk.Capacity property is $null.

That could be caused by the problem from 1)


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

0 Kudos
Zsoldier
Expert
Expert
Jump to solution

This works when run in PowerCLI 5.0.

get-vm vmname | get-vmguestdiskusage

This should also work:

get-vmguestdiskusage (get-vm vmname)

The error for problem one is simply stating that it's looking for a vm object instead of just a vm name (string).

Chris Nakagaki (中垣浩一)
Blog: https://tech.zsoldier.com
Twitter: @zsoldier
0 Kudos
Munster99
Enthusiast
Enthusiast
Jump to solution

Thanks for the prompt response however

1) i am running powercli 5 ???!??

PowerCLI Version
----------------
   VMware vSphere PowerCLI 5.0 build 435427

2 ) have tried that but still no joy

0 Kudos
LucD
Leadership
Leadership
Jump to solution

The problem in 1) is not related to the PowerCLI version.

It's caused by the type of object(s) you pass to the function (see my explanation above).


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

0 Kudos
Zsoldier
Expert
Expert
Jump to solution

I'm @ a loss.  There should be no reason why either wouldn't work.  Just to make sure everything is working properly try the following:

  1. Type get-vm vmname
    • replace vmname w/ the name of an actual vm
    • Did it return an object?  If not, then this is the start of your problem.
    • You connected to the host or vCenter w/ connect-viserver right?
  2. get-vm vmname | get-vmguestdiskusage
    • There should be no reason that the above won't work as long as the get-vm vmname cmdlet returns an object.
Chris Nakagaki (中垣浩一)
Blog: https://tech.zsoldier.com
Twitter: @zsoldier
0 Kudos
Munster99
Enthusiast
Enthusiast
Jump to solution

Thanks LucD/Zsoldier

Thats the issue - if i do a 'get-vm MyVM' it comes back with a valid VM object. When I action the following code "get-vm MyVM | ./get-VMGuestDiskUsage" or ./Get-VMGuestDiskUsage (get-vm MyVM) I keep getting the above error. It seems to be something really silly but for some odd reason it simply doesnt accept my VM objects. at first i thought it might be the following lne

[VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl]$vm)

hence checked the help I changed it to [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl[]]$vm)

But still didnt work ???!?!?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Did you store the function in a .ps1 file ?

In that case you will first have to dot-source that .ps1 file

. ./Get-VMGuestDiskUsage.ps1

Don't forget the blank after the first dot !

And then you can do

Get-vm MyVM | Get-VMGuestDiskUsage


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

0 Kudos
Munster99
Enthusiast
Enthusiast
Jump to solution

just tried what you said as follows :

. ./Get-VMGuestDiskUsage.ps1 (from the directory it is located in )

same error appears

cmdlet Get-VMGuestDiskUsage at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
vm:

??!??!

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Would you mind attaching the Get-VMGuestDiskUsage.ps1 file ?

And the exact command(s) you use to call the function (a screenshot of the PowerCLI prompt will do).


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

0 Kudos
Munster99
Enthusiast
Enthusiast
Jump to solution

There you go ( I've removed the servernames unfortunately)

Very basic but still doesnt work. Could be my set up but all I have installed is 'Powercli 5' and 'Powershell 2 CTP 2' . When I action a get-vm cmd it brings back the relevant info. So still am baffled ??!?!?

0 Kudos
Zsoldier
Expert
Expert
Jump to solution

Remove line 43, it's not needed.

Execute the script:

./get-vmguestdiskusage.ps1

or copy the contents of the ps1 file and run in a PS session.

This will be make the get-vmguestusage function available.

Then simply run the function like so:

get-vm vmname | get-vmguestdiskusage

Chris Nakagaki (中垣浩一)
Blog: https://tech.zsoldier.com
Twitter: @zsoldier
LucD
Leadership
Leadership
Jump to solution

Remove the last line from the .ps1 file and then dot-source the .ps1 file again

. ./Get-VMGuestDiskUsage.ps1

Then, on the command line do

Get-Command Get-VMGuestDiskUsage

This should tell you if the function is known to the PS engine after you dot-sourced the .ps1 file.

If it is known, just do

Get-VM MyVM | Get-VMGuestDiskUsage


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

0 Kudos
Munster99
Enthusiast
Enthusiast
Jump to solution

LucD

Thanks a million that seems to have done the trick!

I think it was error on my part not understandng that I need to load the Function into PS and then once loaded I can use it like a cmdlet. Just one small issue - when I enter in either a specific number of VMs via the 'get-vm' cmdlet or from a txt file vis the 'get-content' cmdlet I get ALL the fields reporting back including the "Usage %" field. However when I action it against all the VMs using just " Get-vm | get-vmguestdiskusage " that column is missing.

Any ideas ???

Munster99

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Could be that the last column doesn't fit on the screen anymore due to the size of the previous columns.

Try running it like this

Get-VM | Get-VMGuestDiskUsage | ft -AutoSize


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

0 Kudos
LucD
Leadership
Leadership
Jump to solution

I was able to reproduce the problem.

When the VM is not powered on (for a longer time) the information that is used to calculate the Usage% is not present and hence the property is not set in the output object. If this happens for the first object that the function places on the pipeline, all the following VMs, irrespective if they are powered on or not, will be missing the Usage% property.

The root cause of this is how PowerShell prepares the objects for output on the screen.

A simple way around this is to only use powered on VMs, like this

Get-VM | where {$_.PowerState -eq "PoweredOn"} | Get-VMGuestDiskUsage

Note that the absence of VMware Tools can also cause this problem.


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

Munster99
Enthusiast
Enthusiast
Jump to solution

Brilliant !

Thank you ever soo much !

And a Happy New Year to you guys Smiley Happy

Munster99

0 Kudos