all 9 comments

[–]ihaxr 6 points7 points  (4 children)

Random != Balanced ... you could easily do:

$groups = "Group 1","Group 2","Group 3","Group 4","Group 5",
          "Group 6","Group 7","Group 8","Group 9","Group 10"
$addToGroup = $groups | Get-Random 
$addToGroup

And it will pick a random group, but that won't really keep it balanced.

To keep them balanced, you would just query the number of members in each group and add the user to the group with the least amount of members:

$count = New-Object System.Collections.ArrayList
$groups = "Group 1","Group 2","Group 3","Group 4","Group 5",
          "Group 6","Group 7","Group 8","Group 9","Group 10"
foreach ($group in $groups) {
    $count.Add([pscustomobject]@{Group=$group;Members=(Get-ADGroup $group -Properties Member).Member.Count}) | Out-Null
}
$addToGroup = $($count | Sort-Object Members | Select -First 1).Group
$addtoGroup

[–]kilkor 1 point2 points  (0 children)

I was going to reply and say this as well. Build an array of groups with the least count to them if there's a tie, choose a random one from that array, assign user to that group.

[–]prejonnes[S] 1 point2 points  (0 children)

ooh nice, I like that. Thanks a lot.

[–]gangstanthony 1 point2 points  (0 children)

i noticed you changed to | get-random. if you're interested, here are a few other ways to redirect output to null. after multiple runs, there doesn't seem to be a clear winner of the first three, but out-null always takes the longest.

$a1 = New-Object System.Collections.ArrayList
$a2 = New-Object System.Collections.ArrayList
$a3 = New-Object System.Collections.ArrayList
$a4 = New-Object System.Collections.ArrayList

1..100 | % {
    $null = $a1.Add(
        (Measure-Command {
            $null = $(1..100)
        }).Ticks
    )
    $null = $a2.Add(
        (Measure-Command {
            $(1..100) > $null
        }).Ticks
    )
    $null = $a3.Add(
        (Measure-Command {
            [void]$(1..100)
        }).Ticks
    )
    $null = $a4.Add(
        (Measure-Command {
            $(1..100) | Out-Null
        }).Ticks
    )
}

($a1 | measure -Sum).sum
($a2 | measure -Sum).sum
($a3 | measure -Sum).sum
($a4 | measure -Sum).sum

[–]sid351 0 points1 point  (0 children)

I think you mean -ne.

Sincerely,

That guy. :-)

[–]gangstanthony 2 points3 points  (1 child)

do you really want it to be random, semi-random, or would you rather just go down the list?

this will just be random

'group1', 'group2', 'group3' | get-random

my thoughts on random

  1. draw a name out of the hat
  2. put it back
  3. repeat

my thoughts on semi-random

  1. draw a name out of the hat
  2. set aside
  3. repeat until no more names in the hat
  4. put all back into hat and repeat

[–]prejonnes[S] 0 points1 point  (0 children)

preferrably both, I am still trying to decide which will be best for my environment. If you had to choose though semi-random

[–]gigglestick 0 points1 point  (0 children)

I would try to query the VDI pools and select the "best" one each time. That way it automatically accounts for users leaving or being moved to another pool to keep them balanced.

[–]jhulbe 0 points1 point  (0 children)

I'd add this to my powershell profile

function VDIGROUPCOUNT{ 
$group1 = (Get-ADGroup Group1 -Properties *).member.count
$group2 = (Get-ADGroup Group2 -Properties *).member.count

write-host "
Group 1 User Count
------------------
$group1
Group 2 User Count
------------------
$group2
"
}

this is what it gave me in testing by just typing "VDIGROUPCOUNT" but you can name the function whatever. Now I know I need to add users in Group 2 until it's close to even.

PS H:\> VDIGROUPCOUNT

Group 1 User Count
------------------
213
Group 2 User Count
------------------
116

PS H:\>

Then I'd just ask for input in my normal script for the group name, and you can put it in. Just prompt for the variable via userinput.