VMware Cloud Community
jvm2016
Hot Shot
Hot Shot
Jump to solution

datastore_info_function_with_foreach-object_powercli

hi Luc,

could you suggest what is wring in folowing .i want to use foreach-object .

function get-datastoreinfo

{

[cmdletbinding()]

param (

[parameter(mandatory = $true,

           valuefrompipeline = $true,

           valuefrompipelinebypropertyname = $true)]

           [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]$esxiname

)

$vm_host = Get-VMHost $esxiname

$datastores=Get-VMHost $vm_host|Get-Datastore|% -Process

                                               {$per_freespace=$_.freespaceGB/$_.capacityGB*100

                                               $_|select name,@{N='freespacepercent';E={$per_freespace}}}

}

0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

No, that is not possible.

You ask the parameter to be a VMHost object, so you have to provide a VMHost object.
There is no type-casting a string to a VMHost object.

So this is possible

Get-VMHost -Name host1.abc.com | get-datastorepercent

or this

$esx = Get-VMHost -Name host1.abc.com

get-datastorepercent -esxiname $esx


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

View solution in original post

0 Kudos
10 Replies
LucD
Leadership
Leadership
Jump to solution

You have to start the code block on the same line as the -Process parameter.

Just move the 1st curly brace to that line.

Btw, this function doesn't seem to return anything, the result is stored in the $datastores variable, but nothing is done with that variable.

function get-datastoreinfo

{

    [cmdletbinding()]

    param (

        [parameter(mandatory = $true,

            valuefrompipeline = $true,

            valuefrompipelinebypropertyname = $true)]

        [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]$esxiname

    )

   

    $vm_host = Get-VMHost $esxiname

    $datastores = Get-VMHost $vm_host|Get-Datastore|% -Process {

        $per_freespace=$_.freespaceGB/$_.capacityGB*100

        $_|select name,@{N='freespacepercent';E={$per_freespace}}

    }

}


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

0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

i am still getting

get-datastoreinfo : Cannot process argument transformation on parameter

'esxiname'. Cannot convert the "esxi_name" value of type

"System.String" to type

"VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost".

i thought powershell is not following identation as other languages like python.

$datastores can be utilized for printing at console.

function get-datastoreinfo

{

    [cmdletbinding()]

    param (

        [parameter(mandatory = $true,

            valuefrompipeline = $true,

            valuefrompipelinebypropertyname = $true)]

        [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]$esxiname

    )

   

    $vm_host = Get-VMHost $esxiname

    $datastores = Get-VMHost $vm_host|Get-Datastore|% -Process {

        $per_freespace=$_.freespaceGB/$_.capacityGB*100

        $_|select name,@{N='freespacepercent';E={$per_freespace}}

    }

$datastores

}

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You still seem to be passing a string for the $esxiname parameter.

How do you call the function?


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

0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

this is how i am calling function wherein i need to input host1.example.com after parameter esxiname.

get-datastoreinfo -esxiname host1.example.com

it works fine if i replace [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]$esxiname   (how to call function using this and why we using this?)

to

[string]$esxiname

iam also checking

PowerCLI Best Practice: Correct Use of Strong Typing - VMware PowerCLI Blog - VMware Blogs

0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is normal, if you pass a [String] and declare the parameter as [String] it will of course work.

On the other hand, since you declared it as a pipeline parameter, you probably want to be able to pass a VMHost object as well.

PowerCLI can handle this duality thanks to OBN.

But you can do the same in your functions with some extra lines.

For example like this

function get-datastoreinfo

{

    [cmdletbinding()]

    param (

        [parameter(mandatory = $true,

            valuefrompipeline = $true,

            valuefrompipelinebypropertyname = $true)]

        [PSObject]$esxiname

    )

  

    if($esxiname -is [String]){

        $esxiname = Get-VMHost -Name $esxiname

    }

    elseif($esxiname -isnot [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]){

        throw "esxiname needs to be a String or VMHost object"

    }

    Get-Datastore -RelatedObject $esxiname | ForEach-Object -Process {

        $per_freespace=$_.freespaceGB/$_.capacityGB*100

        $_|select name,@{N='freespacepercent';E={$per_freespace}}

    }

}

get-datastoreinfo -esxiname MyEsx

Get-VMHost -Name MyEsx | get-datastoreinfo


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

0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

i am checking this but if i use following

[VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]$esxiname   it means iam using vmhost object not string is that correct?

and we are using this to make it compatible with future powercli changes ??

so my specific question is how do i use my previus post code using [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]$esxiname

ultimately i need to provide esxiname which is in form of string.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Yes, that declaration means the parameter is an object of type VMHost.

Besides the fact that the type follows the (not so) new portable typename, this has nothing to do with future PowerCLI changes.

I don't see what you point is here to be honest!
You declare a parameter as type VMhost, but then you want to pass the parameter as a string.

That is impossible, unless you let the function handle this ambiguity (like my example does).


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

0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

Thanks. i got most of your explanation but i think i was not able to put it in correct way. sorry to ask this again .

so if yu consider folowing code without if and else if

function get-datastorepercent

{

    [cmdletbinding()]

    param (

        [parameter(mandatory = $true,

            valuefrompipeline = $true,

            valuefrompipelinebypropertyname = $true)]

        [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]$esxiname

    )

  

   $vm_host=get-vmhost $esxiname

   foreach($ds in (get-datastore -RelatedObject $vm_host))

   {

   $per_free=$ds.freespaceGB/$ds.capacityGB*100

   $per_free_round=[math]::Round($per_free)

   $datastores=$ds|select name,@{N='freespacepercent';E={$per_free_round}}

   $datastores

  

  

   }

}

for the time being i want to use [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]$esxiname

now when i call function like below it will throw error .is there any way of changing this input may be adding some prefix to esxiname to convert its type .because what ever way i use i need to call

in the following way and provide esxi name irrespective of types declared.

get-datastorepercent -esxiname host1.abc.com

0 Kudos
LucD
Leadership
Leadership
Jump to solution

No, that is not possible.

You ask the parameter to be a VMHost object, so you have to provide a VMHost object.
There is no type-casting a string to a VMHost object.

So this is possible

Get-VMHost -Name host1.abc.com | get-datastorepercent

or this

$esx = Get-VMHost -Name host1.abc.com

get-datastorepercent -esxiname $esx


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

0 Kudos
jvm2016
Hot Shot
Hot Shot
Jump to solution

Thanks Luc. appreciate your patience and help.Smiley Happy

0 Kudos