VMware Cloud Community
cr7nine
Contributor
Contributor
Jump to solution

get count of desktops from a pool

HI All,

I search through the internet for quite some time but couldn't find any helpful info for my script.

I'm trying to get the count of view desktops already used in a pool and the count of max. desktops.

My script shall analyse these two and send a mail to me when the normal count is reaching the max count.

As we are still in building the view enviroment, new users are added to the AD constantly so pools are filling fast.

Also we don't want huge pools therefore a fixed limit is needed and must be checked.

I thought with a script it would be the best method, can anyone help in here?

thanks

cr

Tags (4)
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Try something like this.

It will show per pool how many desktops are used.

Get-Pool | Select Pool_id,DisplayName,
@{N="#Desktops";E={$_ | Get-DesktopVM | Measure-Object | Select -ExpandProperty Count}}


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

View solution in original post

0 Kudos
17 Replies
ChrisJ615
Enthusiast
Enthusiast
Jump to solution

Maybe this will kick start you off

(Get-ResourcePool -Name "Name.Of.Pool" | Get-VM).count

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try something like this.

It will show per pool how many desktops are used.

Get-Pool | Select Pool_id,DisplayName,
@{N="#Desktops";E={$_ | Get-DesktopVM | Measure-Object | Select -ExpandProperty Count}}


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

0 Kudos
cr7nine
Contributor
Contributor
Jump to solution

Hi All,

thanks for all your help, I got a bit further Smiley Wink

Now I'm having the problem that I can't get any useful data out of my array^^

I use this command to fill the associative array ergs, but later I can't get any data out of it:

$ergs=(Get-Pool | Select Pool_id,@{N="desktops";E={$_ | Get-DesktopVM | Measure-Object | Select -ExpandProperty Count}},maximumcount | Format-Table -AutoSize -HideTableHeaders)

Similar if I use $ergs["VALUE"] or echo $ergs["VALUE"] or $ergs[VALUE] or $ergs['VALUE'] result is empty.

If I just use echo $ergs i can see the set Values.

Any suggestions on this?

thx

cr

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You see no values because that array is not a hash table.

When you do

$ergs

you will see all the rows in the array.

To address for example the Pool_id value for the first row, you would do

$ergs[0].Pool_id

The 0 (zero) indicates you want get the 1st row of the array, and in that row you want the Pool_id property.

It's just a matter of knowing the type of the variable and how to address specific properties in the variable.


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

0 Kudos
cr7nine
Contributor
Contributor
Jump to solution

This is also not working here, still no output.

Atm my multidimensional associative array consist of these value examples: $ergs

abb-pool1-1-v     3     3

abb-pool2-1-v     100     120

abb-pool3-2-v     50     70

Maybe the "-" is the problem?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

What do the following return ?

$ergs | Get-Member

and

$ergs[0]

The '-' is in a property value, that shouldn't cause any problems


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

0 Kudos
cr7nine
Contributor
Contributor
Jump to solution

Outout of both as following:  

TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatStartData

Name                                    MemberType Definition

----                                    ---------- ----------

Equals                                  Method     bool Equals(System.Object obj)

GetHashCode                             Method     int GetHashCode()

GetType                                 Method     type GetType()

ToString                                Method     string ToString()

autosizeInfo                            Property   Microsoft.PowerShell.Commands.Internal.Format.AutosizeInfo autosi...

ClassId2e4f51ef21dd47e99d3c952918aff9cd Property   System.String ClassId2e4f51ef21dd47e99d3c952918aff9cd {get;}

groupingEntry                           Property   Microsoft.PowerShell.Commands.Internal.Format.GroupingEntry group...

pageFooterEntry                         Property   Microsoft.PowerShell.Commands.Internal.Format.PageFooterEntry pag...

pageHeaderEntry                         Property   Microsoft.PowerShell.Commands.Internal.Format.PageHeaderEntry pag...

shapeInfo                               Property   Microsoft.PowerShell.Commands.Internal.Format.ShapeInfo shapeInfo...

   TypeName: Microsoft.PowerShell.Commands.Internal.Format.GroupStartData

Name                                    MemberType Definition

----                                    ---------- ----------

Equals                                  Method     bool Equals(System.Object obj)

GetHashCode                             Method     int GetHashCode()

GetType                                 Method     type GetType()

ToString                                Method     string ToString()

ClassId2e4f51ef21dd47e99d3c952918aff9cd Property   System.String ClassId2e4f51ef21dd47e99d3c952918aff9cd {get;}

groupingEntry                           Property   Microsoft.PowerShell.Commands.Internal.Format.GroupingEntry group...

shapeInfo                               Property   Microsoft.PowerShell.Commands.Internal.Format.ShapeInfo shapeInfo...

   TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData

Name                                    MemberType Definition

----                                    ---------- ----------

Equals                                  Method     bool Equals(System.Object obj)

GetHashCode                             Method     int GetHashCode()

GetType                                 Method     type GetType()

ToString                                Method     string ToString()

ClassId2e4f51ef21dd47e99d3c952918aff9cd Property   System.String ClassId2e4f51ef21dd47e99d3c952918aff9cd {get;}

formatEntryInfo                         Property   Microsoft.PowerShell.Commands.Internal.Format.FormatEntryInfo for...

outOfBand                               Property   System.Boolean outOfBand {get;set;}

writeErrorStream                        Property   System.Boolean writeErrorStream {get;set;}

   TypeName: Microsoft.PowerShell.Commands.Internal.Format.GroupEndData

Name                                    MemberType Definition

----                                    ---------- ----------

Equals                                  Method     bool Equals(System.Object obj)

GetHashCode                             Method     int GetHashCode()

GetType                                 Method     type GetType()

ToString                                Method     string ToString()

ClassId2e4f51ef21dd47e99d3c952918aff9cd Property   System.String ClassId2e4f51ef21dd47e99d3c952918aff9cd {get;}

groupingEntry                           Property   Microsoft.PowerShell.Commands.Internal.Format.GroupingEntry group...

   TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatEndData

Name                                    MemberType Definition

----                                    ---------- ----------

Equals                                  Method     bool Equals(System.Object obj)

GetHashCode                             Method     int GetHashCode()

GetType                                 Method     type GetType()

ToString                                Method     string ToString()

ClassId2e4f51ef21dd47e99d3c952918aff9cd Property   System.String ClassId2e4f51ef21dd47e99d3c952918aff9cd {get;}

groupingEntry                           Property   Microsoft.PowerShell.Commands.Internal.Format.GroupingEntry group...

PS C:\Users\admin\Desktop> $ergs[0]

PS C:\Users\admin\Desktop>

0 Kudos
LucD
Leadership
Leadership
Jump to solution

I obviously didn't notice you had a Format-Table in there.

Just do

$ergs = Get-Pool | Select Pool_id,@{N="desktops";E={$_ | Get-DesktopVM | Measure-Object | Select -ExpandProperty Count}}

The Format-Table cmdlet is intended for displaying output.

As you can see from the returned types, these are special objects that are understood by the PowerShell output routine.

If you need to use objects and properties further along inside your script, do not format them (yet) for output.


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

cr7nine
Contributor
Contributor
Jump to solution

I needed the Format-Table to get rid of the TableHeaders.

Iin past tests these values(pool_id, desktops, maximumcount, --------,..) were also written in the array variable which isn't really nice to handle then.

I'm just started the new creation of the array without formating, will report back soon with results.

thx

0 Kudos
cr7nine
Contributor
Contributor
Jump to solution

OK, now it is working, not very nice to code($erg=$ergs[4].maximumCount-$ergs[4].desktops) but as long as the result ist fine, everything is ok :smileygrin:

Only a small question to the end:

How can I get another (shorter)header for the maximumcount property e.g. "maxcou"?

Thx

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You would only need that kind of addressing if you want to see the value for a specific row.

PowerShell is normally about handling a number of objects in series.

Perhaps you could share the script you are using.

There is probably a shorter way of doing this.


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

0 Kudos
cr7nine
Contributor
Contributor
Jump to solution

Actually I'm building scripts sequentially and as this function($ergs=(Get-Pool | Select Pool_id,@{N="vdesk";E={$_ | Get-DesktopVM | Measure-Object | Select -ExpandProperty Count}},maximumcount)) is the first real custom code, I haven't much to show yet.

Currently I have only:

<Adding View cmdlets>

$chk=0

$outfile="D:\outtmp.txt"

Connect-VIServer -Server server.domain.net -Force >>null

$ergs=(Get-Pool | Select Pool_id,@{N="vdesk";E={$_ | Get-DesktopVM | Measure-Object | Select -ExpandProperty Count}},maximumcount)

(below is just coded here to see the direction I want to go..(no idea if it works atm))

$lim=$ergs.count

for ($i=0;$i -lt $lim;$i++)

{

     [int]$cur=$ergs[$i].maximumCount*0.05

     $erg=$ergs[$i].maximumCount-$ergs[$i].vdesk

     if ($erg -lt $cur)

     {

          echo "Pool $ergs[$i].Pool_id is reaching its limit, currently $ergs[$i].vdesk of $ergs[$i].maximumCount in use!" >> $outfile

          $chk=1

     }

}

(end of firstcode here)

function sendmail($body)

{

    $SmtpClient = new-object system.net.mail.smtpClient

    $MailMessage = New-Object system.net.mail.mailmessage

    $SmtpClient.Host = "server_ip"

    $SmtpClient.Port = 25

    $mailmessage.from = "test@test.com"

    $mailmessage.To.add("test2@test.com")

    $mailmessage.Subject = “Pool monitoring”

    $MailMessage.IsBodyHtml = $true

    $mailmessage.Body = "$body"

    $smtpclient.Send($mailmessage)

}

$body=(Get-Content $outfile)  -join '<BR>'

if ($chk -eq 1)

{

     sendmail $body

}

del null

del $outfile

exit

PS: how the hell can I use the code highlighting here? Smiley Happy

cr

0 Kudos
LucD
Leadership
Leadership
Jump to solution

If I understand your script correctly, you want to send an email for each pool that has more than 95% of the desktops in use ?

If yes, then the following should do this (in a very basic way).

Get-Pool |
Where {((Get-DesktopVM -Pool_id $_.pool_id).Count/$_.maximumCount) -ge 0.95} | %{
 
Send-MailMessage -To "lucd@lucd.info" -From "lucd@lucd.info" `
   
-SmtpServer mail.lucd.info `
   
-Subject "$($_.pool_id) above threshold"
}

The concept is as follows:

  • get all the View pools
  • filter out the ones that have more than 95% of the desktops in use
  • for each of these pool execute the code block (% is an alias for the ForEach-Object cmdlet)
  • in the code block send an email.

My example only places the pool_id in the Subject of the email, but you can place whatever property in the Subject or in the Body of the email.


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

0 Kudos
cr7nine
Contributor
Contributor
Jump to solution

Yes you are right.

Before I test this nice function:
If I understand it corrct it send for every pool a seperate message?

Atm I plan to let the script run once a day because users aren't added in masses to the pools.

Therefore I have some time to react before a pool reachs the limit and I don't want masses of mails in my inbox because of this Smiley Happy

0 Kudos
LucD
Leadership
Leadership
Jump to solution

No, it will only send an email for the pools that get through the Where-clause.

In other words, those pools for which 95% of the maximum is in use.

That is one of the nice features of PowerShell, you get all the objects, filter them with a condition and then take action on the objects that made it through the filter :smileycool:

You can schedule scripts with the Windows Task Scheduler.

See Alan's post called Running a PowerCLI Scheduled task


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

0 Kudos
cr7nine
Contributor
Contributor
Jump to solution

Yeah, I understood it right but explained it false in my words^^

Atm I struggling which method I should use, either sending 1 mail with infos or seperate ones.

In our enviroment we have several pools for testing which are permanently full or some has set 0 as maximum which leads the "/" to "Attempted to divide by zero." errors.

Not sure if it is good to implement filter functions here, could be more work than worth it.

Yes true, unfortunately I'm coming very slowly through the endless possibilities of PS :smileygrin:

Yep, creating a task should be no problem Smiley Happy

0 Kudos
LucD
Leadership
Leadership
Jump to solution

I just updated a document on how to enter pretty code.

See Some ways to enter PowerCLI code under the new forum SW


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

0 Kudos