CAE0621
Enthusiast
Enthusiast

Checking DRS VM Groups via Compare-Object

We've been having issues with our provisioning not putting new VMs into the correct DRS groups. We've been manually checking, but I wanted to throw a script together to email us is something wasn't in the right spot. But for a reason I can't find, when I use compare-object the script can't seem to find the vms I've purposefully left out of the DRS groups. My scripts are below:

Foreach ($vC in $vCenters){
    Connect-VIServer $vC -Credential $API_Creds 
    Start-Sleep -Seconds 10
    ForEach($Cluster in $Clusters.Name){
        $DRSGroups = Get-DrsClusterGroup -Cluster $cluster |`
            Where-Object "GroupType" -like "VMGroup" |`
            Select-Object Name,Cluster,Grouptype,@{N="Member";E={[string]::Join(',',($_.Member))}}
        Get-Cluster $Cluster | Get-VM | Select-Object -Property "Name" | Export-Csv -Path "$VMPath\$cluster.csv" -Append
        Foreach($Group in $DRSGroups.Name){
            $Dirty = Get-DRSClusterGroup -Cluster $Cluster -Name $Group | Sort-Object | Select-Object @{N="Member";E={[string]::Join(",",($_.Member))}}
            $Clean = foreach($item in $dirty){$dirty.Member -split ","}
            $Clean | Out-String | Out-File "$DRSPath\$cluster-$Group.txt" -Append
        }
    }
    disconnect-viserver $vC -confirm:$false
}

So when I just exported get-drsclustergroup I found it just exported all the names along one file line, which obviously wouldn't work. So I made it split along the commas then exported that. After this I import them via Get-Content as [$cCuster-$Group_is]

Then I have another foreach run through the clusters and grab the VMs, putting them into variables matching the cluster (ex. $R03GP). Afterwhich I have a series of Where-Objects to find out which VMs should be in the DRS Group, example below:

$R03GP_ShouldBe = $R03GP | Sort-Object Name | Where-Object{
    $_ -like "p*" -or
    $_ -like "u*" -and
    $_ -notlike "pdw05*"
}

I've confirmed that both arrays contain strings:

2022-09-01 09_34_54-ucw01camellis01 - Remote Desktop Connection.png

I've confirmed that my test VM is in the ShouldBe group, but not in the Is group:

2022-09-01 09_36_05-ucw01camellis01 - Remote Desktop Connection.png

But, when I run my compare-object, with a where-object to only show the ones that should be in the DRS group but aren't, it comes up blank:

2022-09-01 09_39_09-ucw01camellis01 - Remote Desktop Connection.png

Does anyone see something that I'm missing? Let me know if you need more info

Tags (3)
0 Kudos
15 Replies
LucD
Leadership
Leadership

What are you actually trying to check?
Should all VMs in a Cluster be in a specific DRS VM group?


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

0 Kudos
CAE0621
Enthusiast
Enthusiast

Sorry, I never got an email that I received a reply. 

Essentially, due to licensing issues, we can only put Prod VMs on a select few servers in the cluster. So we have a DRS group that will keep them on the licensed hosts. So what I'm trying to do is check all the VMs in the cluster to see if they're supposed to be in the license DRS group and have it email me if any VM is not in the group when it should be. 

0 Kudos
LucD
Leadership
Leadership

How do you get/create the list of VMs that should be in the DRS VM Group?
Is that hard-coded?
And how do you get the name of the actual DRS VM group that you want to check against?

In summary, there are a couple of givens that the script should have
- the names of the VMs that should be in the DRS VM group
- the name of that DRS VM group


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

0 Kudos
CAE0621
Enthusiast
Enthusiast

I have a foreach loop that goes into each cluster and exports a text file with all the names of the VMs in the cluster. I "Get-Content" that text file and save it as a variable ($R04GP in this case)

$R04GP_ShouldBe = $R04GP | Where-Object{
    $_ -like "p*" -or
    $_ -like "u*" -and
    $_ -notlike "pdw05*"
}

 The above code goes through the list of all the VMs and filters it out based on our naming convention. That gives me the VMs that should be in the DRS group.

 

To get the DRS groups I found some scripts online that got me through it:

ForEach($Cluster in $Clusters.Name){
        $DRSGroups = Get-DrsClusterGroup -Cluster $cluster |`
            Where-Object "Name" -notlike "Uila*" |`
            Where-Object "GroupType" -like "VMGroup" |`
            Select-Object Name,Cluster,Grouptype,@{N="Member";E={[string]::Join(',',($_.Member))}}
}

This gets me the DRS group name and all the members in it. Unfortunately it doesn't output the members very cleanly so I have a follow-up that gets me the names into an array

2022-09-06 13_05_45-Window.png

This cleans it up so I get an exported file with each entry on it's own line:

Foreach($Group in $DRSGroups.Name){
            $Dirty = Get-DRSClusterGroup -Cluster $Cluster -Name $Group | Sort-Object | Select-Object @{N="Member";E={[string]::Join(",",($_.Member))}}
            $Clean = foreach($item in $dirty){$dirty.Member -split ","}
            $Clean | Out-String | Out-File "$DRSPath\$cluster-$Group.txt" -Append
        }

 

So those two parts get me the VMs that should be in the DRS group and the ones that are in the DRS group

0 Kudos
LucD
Leadership
Leadership

Still not sure I 100% understand what you are trying to do.
But assuming I got the way to select the correct list of VMs, try the following

Get-Cluster -PipelineVariable cluster |
Foreach-Object -Process {
  $shouldBe = Get-VM -Location $cluster |
    Where-Object { $_.Name -like "p*" -or $_ -like "u*" -and $_ -notlike "pdw05*" } |
    Select -ExpandProperty Name

    Get-DrsClusterGroup -Cluster $cluster -Type VMGroup -PipelineVariable group |
      Where-Object {$_.Name -NotLike "Uila*"} |
      ForEach-Object -Process {
        $missing = $extra = @()
        if($group.Member.Count -ne 0){
          Compare-Object -ReferenceObject $shouldBe -DifferenceObject $group.Member.Name -PipelineVariable compare |
          ForEach-Object -Process {
            switch($_.SideIndicator){
              '=>' {
                $extra += $compare.InputObject
              }
              '<=' {
                $missing += $compare.InputObject
              }
            }
          }
        }
        else{
          $missing = $shouldBe
        }
        New-Object -typename PSObject -property ([ordered]@{
          Cluster = $cluster.Name
          Group = $group.Name
          Contains = $group.Member.Name -join ','
          Missing = $missing -join ','
          Extra = $extra -join ','
        })
      }
    }


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

0 Kudos
CAE0621
Enthusiast
Enthusiast

Ah okay I think I may see the miscommunication we're having. I get so caught up in the specific issue I'm having with my way of solving it I never consider that someone else may see a totally different way of getting there so I've just been sending snippets of my code. I'll dump my whole code below.

What I'm trying to do is find out when our automated deployment doesn't put newly created VMs into the correct DRS groups. Instead of me logging in daily to check all of our groups, I'm trying to have it look through all our clusters and all our DRS groups and email me if we have any VMs that fall outside of the parameters.

It's a lot of code, mainly because I export and re-import everything. It seemed like the best solution at the time so I'd get all the DRS groups but from the code you posted earlier it's clear that may not be the easiest option. Hopefully this data dump provides some clarity

#Find any new Vms that haven't been added to correct DRS groups or Resource Pools
### Documentation of Rules as of 8/15/22 at bottom of script ###
# #Create Creds
Import-Module -Name C:\Scripts\VUHL-ThycoticAPI -Verbose
$API_Creds = Get-ThycoticAccountInfo RESMGMTschtsk_U_svc
$API_UID = "VUHL\" + $API_Creds[0]
$API_PWD = $API_Creds[1]
$API_Creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $API_UID, $API_PWD

##########################################################################################################################################################################################################
######################    Resource Pools #################################
##########################################################################################################################################################################################################
$RP_VMs = "C:\Scripts\Output\DRSnRPs\RP_VMs.txt"
$vCenters = "pcl01vcsa01.vuhl.root.mrc.local", "pdl01vcsa01.vuhl.root.mrc.local"

Foreach ($vC in $vCenters){
    Connect-VIServer $vC -Credential $API_Creds 
    Start-Sleep -Seconds 10
    $Clusters = Get-Cluster "R*"
    ForEach($Cluster in $Clusters){
        Get-Cluster $Cluster |`
            Get-VM |`
            Select-object -Property "Name", @{n="ResourcePool"; e={$_ | Get-ResourcePool}} |`
            Where-Object{($_.ResourcePool -like "Resources") -and ($_.Name -notlike "vCLS*")} |`
            Export-Csv -Path $RP_VMs -Append
    }
    disconnect-viserver $vC -confirm:$false
}

# Connect-VIServer $DA11 -Credential $API_Creds
# ForEach($Cluster in $Clusters){
#     Get-Cluster $Cluster | Get-VM | Select-object -Property "Name", @{n="ResourcePool"; e={$_ | Get-ResourcePool}} |  Where-Object{($_.ResourcePool -like "Resources")} | Export-Csv -Path $RP_VMs -Append
# }
# disconnect-viserver $DA11 -confirm:$false
if ($null -ne $RP_VMs){
$VMsNotInRPs = (Import-CSV $RP_VMs | Out-String)
}
##########################################################################################################################################################################################################
################ DRS Groups #########################################
##########################################################################################################################################################################################################

#Get DRS Groups
$DRSPath = "C:\Scripts\Output\DRSnRPs\DRS-Rules"
$VMPath = "C:\Scripts\Output\DRSnRPs\VMs"

Foreach ($vC in $vCenters){
    Connect-VIServer $vC -Credential $API_Creds 
    Start-Sleep -Seconds 10
    ForEach($Cluster in $Clusters.Name){
        $DRSGroups = Get-DrsClusterGroup -Cluster $cluster |`
            Where-Object "Name" -notlike "Uila*" |`
            Where-Object "GroupType" -like "VMGroup" |`
            Select-Object Name,Cluster,Grouptype,@{N="Member";E={[string]::Join(',',($_.Member))}}
        # Get-Cluster $Cluster | Get-VM | Select-Object -Property "Name" | Export-Csv -Path "$VMPath\$cluster.csv" -Append
        Foreach($Group in $DRSGroups.Name){
            $Dirty = Get-DRSClusterGroup -Cluster $Cluster -Name $Group | Select-Object @{N="Member";E={[string]::Join(",",($_.Member))}}
            $Clean = foreach($item in $dirty){$dirty.Member -split ","}
            $Clean | Out-String | Out-File "$DRSPath\$cluster-$Group.txt" -Append
        }
    }
    disconnect-viserver $vC -confirm:$false
}

$R03GP_GenPopVMs_is = Get-Content $DRSPath\"R03-GenPop-Genpop_VMs.txt"
$R03SQL_LDBs_is = Get-Content "$DRSPath\R03-SQL-Prod_LinuxDB_VMs.txt"
$R03SQL_MDBs_is = Get-Content "$DRSPath\R03-SQL-Prod_MongoDB_VMs.txt"
$R03SQL_MSs_is = Get-Content "$DRSPath\R03-SQL-Prod_MS_SQL_VMs.txt"
$R03SQL_UAT_is = Get-Content "$DRSPath\R03-SQL-UAT_DB_VMs.txt"
$R04GP_GenPopVMs_is = Get-Content "$DRSPath\R04-GenPop-Genpop_VMs.txt"
$R04SQL_LDBs_is = Get-Content "$DRSPath\R04-SQL-Prod_LinuxDB_VMs.txt"
$R04SQL_MDBs_is = Get-Content "$DRSPath\R04-SQL-Prod_MongoDB_VMs.txt"
$R04SQL_MSs_is = Get-Content "$DRSPath\R04-SQL-Prod_MS_SQL_VMs.txt"
$R04SQL_UAT_is = Get-Content "$DRSPath\R04-SQL-UAT_DB_VMs.txt"

#Get VMs 

# Moved up to DRS foreach loop
Foreach ($vC in $vCenters){
    Connect-VIServer $vC -Credential $API_Creds 
    Start-Sleep -Seconds 10
    Foreach($Cluster in $Clusters){
        Get-Cluster $Cluster | Get-VM | Where-Object "Name" -notlike "Uila*" | Select-Object -Property "Name" | Out-File "$VMPath\$cluster.txt" -Append
    }
    disconnect-viserver $vC -confirm:$false
}

$R03GP = Get-Content "$VMPath\R03-GenPop.txt"
$R04GP = Get-Content "$VMPath\R04-GenPop.txt"
# $R09GP = Import-Csv "$VMPath\R09-GenPop.csv"
# $R10GP = Import-Csv "$VMPath\R10-GenPop.csv"
$R03SQL = Get-Content "$VMPath\R03-SQL.txt"
$R04SQL = Get-Content "$VMPath\R04-SQL.txt"
# $R09DS = Import-Csv "$VMPath\R09-DS.csv"
# $R10DS = Import-Csv "$VMPath\R10-DS.csv"

#Set Rule Variables
$R03GP_ShouldBe = $R03GP | Sort-Object Name | Where-Object{
    $_ -like "p*" -or
    $_ -like "u*" -and
    $_ -notlike "pdw05*" -and
    $_ -notlike "pdl05*" -and
    $_ -notlike "pcw05*" -and
    $_ -notlike "pcl05*" -and
    $_ -notlike "pkw07*" -and
    $_ -notlike "pkl07*" -and
    $_ -notlike "pdw07*" -and
    $_ -notlike "pdl07*" -and
    $_ -notlike "pcw07*" -and
    $_ -notlike "pcl07*"
}

# $R03GP_ShouldBe | Export-Csv -Path "C:\Users\Cameron_Ellis\Desktop\shouldbe.csv"

# $R03GP.Count
# $R03GP_ShouldBe.Count
# $R03GP_GenPopVMs_is.Count

$R04GP_ShouldBe = $R04GP | Where-Object{
    $_ -like "p*" -or
    $_ -like "u*" -and
    $_ -notlike "pdw05*" -and
    $_ -notlike "pdl05*" -and
    $_ -notlike "pcw05*" -and
    $_ -notlike "pcl05*" -and
    $_ -notlike "pkw07*" -and
    $_ -notlike "pkl07*" -and
    $_ -notlike "pdw07*" -and
    $_ -notlike "pdl07*" -and
    $_ -notlike "pcw07*" -and
    $_ -notlike "pcl07*"
}

$R03SQL_LDB_ShouldBe = $R03SQL | Where-Object{
    $_ -like "p*l05c0*my*"
}

$R03SQL_MDB_ShouldBe = $R03SQL | Where-Object{
    $_ -like “p*w05x0*mg*”
}

$R03SQL_MS_ShouldBe = $R03SQL | Where-Object{
    $_ -like “p*w05c0*ms*”
}

$R03SQL_UAT_ShouldBe = $R03SQL | Where-Object{
    $_ -like “u*w05*” -or
    $_ -like “u*l05*”
}

$R04SQL_LDB_ShouldBe = $R04SQL | Where-Object{
    $_ -like "p*l05c0*my*"
}

$R04SQL_MDB_ShouldBe = $R04SQL | Where-Object{
    $_ -like “p*w05x0*mg*”
}

$R04SQL_MS_ShouldBe = $R04SQL | Where-Object{
    $_ -like “p*w05c0*ms*”
}

$R04SQL_UAT_ShouldBe = $R04SQL | Where-Object{
    $_ -like “u*w05*” -or
    $_ -like “u*l05*”
}

# $test1 = @("uow07textbank01", "uow02workflow01", "uow02vutsktst01")
# $test2 = @("uow07textbank01", "uow02workflow01", "uow02vutsktst01", "butts")

# Compare-Object -ReferenceObject $test1 -DifferenceObject $test2

# $test1 | Export-CSV -Path C:\Users\Cameron_Ellis\Desktop\test1.csv
# $test2 | Out-File -FilePath C:\Users\Cameron_Ellis\Desktop\test2.txt
# $test3 = Import-Csv -Path C:\Users\Cameron_Ellis\Desktop\test1.csv
# $test4 = Get-Content -Path C:\Users\Cameron_Ellis\Desktop\test2.txt

# # Compare-Object -ReferenceObject $test1 -DifferenceObject $test2
# $R03GP_ShouldBe.Count
# $R03GP_GenPopVMs_is.Count
# $R03GP_ShouldBe | Where-Object{($_ -like "pdl01RP*")}
# $R03GP_GenPopVMs_is | Where-Object{($_ -like "udw02lnnfoapi*")}

# $R03GP_GenPopVMs_is[69].GetType()
# $R03GP_ShouldBe[69].GetType()

# Compare-Object -ReferenceObject $R03GP_GenPopVMs_is -DifferenceObject $R03GP_ShouldBe | Where-Object{($_.SideIndicator -like "=>")} | format-table # #| Where-Object{($_.InputObject -like "pdl01RP*")}
#Get Out of Compliance VMs
$R03GP_OoC = Compare-Object -ReferenceObject $R03GP_GenPopVMs_is -DifferenceObject $R03GP_ShouldBe | Where-Object{($_.SideIndicator -like "=>")} 
# $R03GP_OoC.Count
$R04GP_OoC = Compare-Object -ReferenceObject $R04GP_GenPopVMs_is -DifferenceObject $R04GP_ShouldBe | Where-Object{($_.SideIndicator -like "=>")} 
$R03SQL_LDB_OoC = Compare-Object -ReferenceObject $R03SQL_LDBs_is -DifferenceObject $R03SQL_LDB_ShouldBe | Where-Object{($_.SideIndicator -like "=>")} 
$R04SQL_LDB_OoC = Compare-Object -ReferenceObject $R04SQL_LDBs_is -DifferenceObject $R04SQL_LDB_ShouldBe | Where-Object{($_.SideIndicator -like "=>")} 
$R03SQL_MDB_OoC = Compare-Object -ReferenceObject $R03SQL_MDBs_is -DifferenceObject $R03SQL_MDB_ShouldBe | Where-Object{($_.SideIndicator -like "=>")} 
$R04SQL_MDB_OoC = Compare-Object -ReferenceObject $R04SQL_MDBs_is -DifferenceObject $R04SQL_MDB_ShouldBe | Where-Object{($_.SideIndicator -like "=>")} 
$R03SQL_MS_OoC = Compare-Object -ReferenceObject $R03SQL_MSs_is -DifferenceObject $R03SQL_MS_ShouldBe | Where-Object{($_.SideIndicator -like "=>")} 
$R04SQL_MS_OoC = Compare-Object -ReferenceObject $R04SQL_MSs_is -DifferenceObject $R04SQL_MS_ShouldBe | Where-Object{($_.SideIndicator -like "=>")} 
$R03SQL_OoC = Compare-Object -ReferenceObject $R03SQL_UAT_is -DifferenceObject $R03SQL_UAT_ShouldBe | Where-Object{($_.SideIndicator -like "=>")} 
$R04SQL_OoC = Compare-Object -ReferenceObject $R04SQL_UAT_is -DifferenceObject $R04SQL_UAT_ShouldBe | Where-Object{($_.SideIndicator -like "=>")} 
##########################################################################################################################################################################################################
############### sending email ################################
##########################################################################################################################################################################################################
#Need access to SMTP server
$SMTPServer = "mxa-001f8101.gslb.pphosted.com"
$SMTPPort = "25"
#$to = "tsr@veteransunited.com"
$to = "Cameron.Ellis@veteransunited.com"
$cc = "adam@veteransunited.com"

$subject = "DRS Groups and VM Pool Violations"

# If ($file_content){
#     Write-Output "Correct"
# }
# else{
#     Write-Output "I guess not"
# }
if ($null -ne $R03GP_OoC){
$body += "`n"
$body += "R03 Genpop VMs out of compliance -  " 
$body += "`n"
$body += $R03GP_OoC.inputobject
$body += "`n"
}if ($null -ne $R04GP_OoC){
$body += "`n"
$body += "R04 Genpop VMs out of compliance - "
$body += "`n"
$body += $R04GP_OoC.inputobject
$body += "`n"
}if ($null -ne $R03SQL_LDB_OoC){
$body += "`n"
$body += "R03 SQL VMs Linux DB out of compliance - " 
$body += "`n"
$body += $R03SQL_LDB_OoC.InputObject
$body += "`n"
}if ($null -ne $R04SQL_LDB_OoC){
$body += "`n"
$body += "R04 SQL VMs Linux DB out of compliance - "
$body += "`n"
$body += $R04SQL_LDB_OoC.InputObject
$body += "`n"
}if ($null -ne $R03SQL_MDB_OoC){
$body += "`n"
$body += "R03 SQL VMs Mongo DB out of compliance - " 
$body += "`n"
$body += $R03SQL_MDB_OoC.InputObject
$body += "`n"
}if ($null -ne $R04SQL_MDB_OoC){
$body += "`n"
$body += "R04 SQL VMs Mongo DB out of compliance - "
$body += "`n"
$body += $R04SQL_MDB_OoC.InputObject
$body += "`n"
}if ($null -ne $R03SQL_MS_OoC){
$body += "`n"
$body += "R03 MSSQL VMs out of compliance - " 
$body += "`n"
$body += $R03SQL_MS_OoC.InputObject
$body += "`n"
}if ($null -ne $R04SQL_MS_OoC){
$body += "`n"
$body += "R04 MSSQL VMs out of compliance - "
$body += "`n"
$body += $R04SQL_MS_OoC.InputObject
$body += "`n"
}if ($null -ne $R03SQL_OoC){
$body += "`n"
$body += "R03 SQL UAT VMs out of compliance - " 
$body += "`n"
$body += $R03SQL_OoC.InputObject
$body += "`n"
}if ($null -ne $R04SQL_OoC){
$body += "`n"
$body += "R04 SQL UAT VMs out of compliance - "
$body += "`n"
$body += $R04SQL_OoC.InputObject
$body += "`n"
# }if (($VMsNotInRPs -like "p*") -or ($VMsNotInRPs -like "u*") -or ($VMsNotInRPs -like "d*")) {
}if ($null -ne $VMsNotInRPs){
$body += "`n"
$body += "VMs not in Resource Pools - "
$body += "`n"
$body += $VMsNotInRPs
}

if ($null -ne $body){
$message = New-Object System.Net.Mail.MailMessage
$message.Subject = $subject
$message.to.add($to)
# $message.cc.Add($cc)
$message.Body = $body
$message.from = "Cameron.Ellis@veteransunited.com"

$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSsl = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.Send($message)
}

Get-ChildItem "C:\Scripts\Output\DRSnRPs\DRS-Rules\" -Include *.* -Recurse | ForEach  { $_.Delete()}
Get-ChildItem "C:\Scripts\Output\DRSnRPs\VMs\" -Include *.* -Recurse | ForEach  { $_.Delete()}
Remove-Item -Path  "C:\Scripts\Output\DRSnRPs\RP_VMs.txt"
0 Kudos
LucD
Leadership
Leadership

So the snippet I posted doesn't do what you want to achieve?


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

0 Kudos
CAE0621
Enthusiast
Enthusiast

Assuming I'm using it correctly, no. As you can see in the photo below, the number of VMs that start with "p" that are missing from the DRS group is 9. The script finds 379

2022-09-06 15_42_27-vSphere - R04-GenPop - VM_Host Rules.png

 

2022-09-06 15_44_05-Window.png

 

Here's your code back with the parts I added, in case you see something I adjusted in error:

$cluster = "R04-Genpop"
$group = "Genpop_VMs"

Get-Cluster -PipelineVariable $cluster |
Foreach-Object -Process {
  $shouldBe = Get-VM -Location $cluster |
  Where-Object{$_ -like "p*"} |
    Select -ExpandProperty Name

Get-DrsClusterGroup -Cluster $cluster -Type VMGroup -PipelineVariable $group |
    Where-Object {$_.Name -NotLike "Uila*"} |
    ForEach-Object -Process {
    $missing = $extra = @()
    if($group.Member.Count -ne 0){
        Compare-Object -ReferenceObject $shouldBe -DifferenceObject $group.Member.Name -PipelineVariable compare |
        ForEach-Object -Process {
        switch($_.SideIndicator){
            '=>' {
            $extra += $compare.InputObject
            }
            '<=' {
            $missing += $compare.InputObject
            }
        }
        }
    }
    else{
        $missing = $shouldBe
    }
    New-Object -typename PSObject -property ([ordered]@{
        Cluster = $cluster.Name
        Group = $group.Name
        Contains = $group.Member.Name -join ','
        Missing = $missing -join ','
        Extra = $extra -join ','
    })
    }
}

$missing.count

 

Also, that little bit at the bottom, the New-Object. I've never seen anything like that before, is it creating a new array called ordered that houses all that information below it?

0 Kudos
LucD
Leadership
Leadership

No, that is creating a single object.
The [ordered] cast makes sure that the properties appear in the order defined in the following hash table.

When you change the following lines, does that make a difference?

  $shouldBe = Get-VM -Location $cluster |
  Where-Object{$_.Name -like "p*"} |
    Select -ExpandProperty Name


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

0 Kudos
CAE0621
Enthusiast
Enthusiast

No change, produces the same results.

FYI, here is the output I get from running the command:

2022-09-07 10_46_09-ucw01camellis01 - Remote Desktop Connection.png

0 Kudos
LucD
Leadership
Leadership

At first sight, there are no duplicates in the Missing property.
The only way you see only 9 VMs in the Web Client, is because all these other VMs are already in another DRS VM group.

Do you only want to report VMs that are no DRS VM group?
Is that what you are checking?
I have to admit it is still not clear to me what exactly you are trying to do.


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

0 Kudos
CAE0621
Enthusiast
Enthusiast

So every week I have to log into our vCenters and to our clusters, go to our VM/Host Rules, and add in any newly created VMs to the existing DRS rules. I'm trying to partially automate that task so it will just alert me when any VMs are created and not added into the DRS rules. Here's some screenshots of the manual process:

 

2022-09-07 11_03_20-vSphere - R04-GenPop - VM_Host Rules.png2022-09-07 11_03_48-vSphere - R04-GenPop - VM_Host Rules.png

In this example,  pdw02rsvpadmn02 &  pdw02rsslmgt02 should be in this DRS group according to our internal logic. So I'm looking for a way to make the script output that those two VMs are missing from the DRS group.

0 Kudos
LucD
Leadership
Leadership

So, any VM that is not in any DRS VM group shall be reported?


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

0 Kudos
CAE0621
Enthusiast
Enthusiast

I'd prefer it to be a specific DRS group. 

I.E. "pdl01rptest01 is missing from DRS group R04-Genpop-VMs"

0 Kudos
LucD
Leadership
Leadership

I give up.
Afaik that was what that snippet I posted earlier is actually doing.
The fact you see only 9 VMs in the Web Client is because other VMs are assigned to other DRS VM groups.
While the snippet only checks which of all the VMs are not in a specific DRS VM group.


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

0 Kudos