VMware Cloud Community
bogdanigm
Enthusiast
Enthusiast
Jump to solution

PowerCLi script to check if 2 VMs are on the same host

Hi,

I am nubby on PowerCLI and I would like some help with building a script.

The script needs to check if two VMs (named test1 and test2) are running on the same host, in a vCenter and send a notification(email) if they do.

Something similar with affinity / anti-affinity DRS rules (but without having DRS enabled on vCenter).  My focus is on anti-affinity. In case this happens, I need to vMotion one of them on another ESXi host(manually or automated).

What I have done so far is this:

Get-VM | Select Name, @{N="Cluster";E={Get-Cluster -VM $_}}, `

@{N="ESX Host";E={Get-VMHost -VM $_}}, `

@{N="vCenter";E={$_.ExtensionData.CLient.ServiceUrl.Split('/')[2]}}, `

@{N="Datastore";E={Get-Datastore -VM $_}} | `

Export-Csv -NoTypeInformation C:\Scripts\file.csv

Which is getting the all the VMs and export the information on a CSV:

NameClusterESX HostvCenterDatastore
test2cluster_testESXi_test1vCenter_test1:443datastore1
test1cluster_testESXi_test1vCenter_test1:443datastore1
for1.localcluster_testESXi_test1vCenter_test1:443datastore1
VM1.localcluster_test2ESXi_test2vCenter_test1:443datastore1
VM2.localcluster_test3ESXi_test3vCenter_test1:443datastore1
VM31.localcluster_test3ESXi_test3vCenter_test1:443datastore1

Thank you.

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Try like this.

$tgtVM = 'test1','test2'

Get-VM -Name $tgtVM | Group-Object  -Property VMHost | %{

    if($_.Count -gt 1){

        $vm = $_.Group | Get-Random

        $esx = $vm.VMHost

        $tgtEsx = Get-Cluster -VM $vm | Get-VMHost | where{$_.Name -ne $esx.Name} | Get-Random

        Move-VM -VM $vm -Destination $tgtEsx -Confirm:$false

    }

}


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

View solution in original post

10 Replies
Prakas
Enthusiast
Enthusiast
Jump to solution

Give a try with below code.

I am assuming only two host in your cluster. Let me know if that is not the case, I will try to alter the script.

You can add this script in scheduled task to check the VMs and automatically move to other host when they happen to run on same host.

Connect-VIServer yourVC

$ehost1 = Get-VMHost hostname1

$ehost2 = Get-VMHost hostname2

$vm1 = Get-VM test1

$vm2 = Get-VM test2

$vm1L = Get-VMHost -VM $vm1

$vm2L = Get-VMHost -VM $vm2

if($vm1L -eq $vm2L)

      {

       if ($vm1L -eq $ehost1) { Move-VM -VM $vm1 -Destination $ehost2 -Confirm:$false}

       else { Move-VM -VM $vm1 -Destination $ehost1 -Confirm:$false }

      }

Disconnect-VIServer yourVC -Confirm:$false

Reply
0 Kudos
Prakas
Enthusiast
Enthusiast
Jump to solution

Here is the updated script (handles more than two hosts in the cluster)

Connect-VIServer yourVC

$vm1 = Get-VM test1

$vm2 = Get-VM test2

$vm1L = Get-VMHost -VM $vm1

$vm2L = Get-VMHost -VM $vm2

if($vm1L -eq $vm2L)

      {

       foreach($ehost in (Get-Cluster yourClusterName |Get-VMHost))

       {

       if ($vm1L -ne $ehost)

            {

            Move-VM -VM $vm1 -Destination $ehost -Confirm:$false

            Disconnect-VIServer yourVC -Confirm:$false

            exit

            }

       }

      }

else { Disconnect-VIServer yourVC -Confirm:$false }

LucD
Leadership
Leadership
Jump to solution

Try like this.

$tgtVM = 'test1','test2'

Get-VM -Name $tgtVM | Group-Object  -Property VMHost | %{

    if($_.Count -gt 1){

        $vm = $_.Group | Get-Random

        $esx = $vm.VMHost

        $tgtEsx = Get-Cluster -VM $vm | Get-VMHost | where{$_.Name -ne $esx.Name} | Get-Random

        Move-VM -VM $vm -Destination $tgtEsx -Confirm:$false

    }

}


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

bogdanigm
Enthusiast
Enthusiast
Jump to solution

Hi LucD, Prakash,

Thank you very much for your quick reply.

Here is what I made, after getting your replies, and I want to share it.

# Check VMs presence Report

# Variable definitions

$Timer = (Get-Date -Format yyyyMMdd-hhmm)

$OutputFile = "C:\data\report"+$Timer+".csv"

$vCenterServer = "vCenter1.local"

$vCenterUser = "Administrator@vsphere.local"

$vCenterUserPwd = "xxxxxxxxxxxxxxxxxxxxxxx"

$MailFrom = "User01 <user01@example.com>"

$MailTo = "User02 <user02@example.com>"

$MailSubject = "Alert:VM on the same host"

$MailBody = "Alert:VM on the same host. Perform manual migration."

$SmtpServer = "smtp.server.com"

# Add the PowerCLI snapin

Add-PSSnapin VMware* -ErrorAction SilentlyContinue

# Connect to the vCenter server

Connect-VIServer -Server $vCenterServer -User $vCenterUser  -Password $vCenterUserPwd

# Get all the VM information and append this to the output file

$tgtVM = 'test1.local','test2.local'

Get-VM -Name $tgtVM | Group-Object  -Property VMHost | %{

    if($_.Count -gt 1){

        $vm = $_.Group

        $esx = $vm.VMHost

        $tgtEsx = Get-Cluster -VM $vm | Get-VMHost | where{$_.Name -ne $esx.Name}

  

     Get-VM $vm |`

       Select-Object Name, @{N="ESX Host";E={Get-VMHost -VM $_}}, @{N="vCenter";E={$_.ExtensionData.CLient.ServiceUrl.Split('/')[2]}} | Out-File -FilePath $OutPutFile

    }

}

# Send the output file via e-mail

Send-MailMessage -from $MailFrom -to $MailTo -subject $MailSubject `

-body $MailBody -Attachment $OutputFile -smtpServer $SmtpServer

Disconnect-VIServer $vCenterServer -Confirm:$false

I do not want to move automatically the VMs just yet, not before I do an audit of the internal services, so the vMotion will be done manually(for now).

Next stage:

I have several pairs of VMs(2 email_servers, 2DNS_servers and so on...) on the vCenter1 and I want to have the same notification (from above). How can I do that?

I have similar requirements, for multiple vCenters, so I need to run these script against on multiple vCenters. How can I do that?

For security reason, how can I hash the password and present the hash to vCenter to allow connection?

Thank you.

bogdanigm
Enthusiast
Enthusiast
Jump to solution

Hi,

Can someone give me some hints for the second part of my script?

Thank you

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Is the VM's DisplayName sufficient to determine if 2 VMs are the same ?


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

Reply
0 Kudos
bogdanigm
Enthusiast
Enthusiast
Jump to solution

Hi,

Vms display  names should be enough.

I have 3 pairs :

mail1.* , mail2.* 

dns1.* , dns2.*

dhcp1., dhcp2.

These vms types reside on 6 different vcenters.

I need to get emails in case 2 vms with similar names reside on the same host.

Thanks a lot.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Do the names always follow that convention: <n * alpha characters><1 * numeric character>. ?

If yes, grouping based on RegEx expression might give the desired result.

See for example

$vmNames = 'mail1.test','mail2.test','vm1.test','dhcp1.test','dhcp4.test'

$vmNames | Group-Object -Property {([regex]"^(?<Name>[a-zA-Z]+)\d\.").match($_).Groups['Name'].Value} |

where {$_.COunt -gt 1} |

Select @{N='Problem';E={$_.Count}},@{N='VMs';E={[string]::Join(',',$_.Group)}}


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

bogdanigm
Enthusiast
Enthusiast
Jump to solution

Thanks LucD,

This works better for my scenario.

Your help is well appreciated.

Reply
0 Kudos
veera1987
Contributor
Contributor
Jump to solution

Hi.... Required an help on the below script that once it is checked and if they are in same host need to be vmotion to another host & send the email

PLease help on it

Reply
0 Kudos