VMware Cloud Community
bmaster001
Enthusiast
Enthusiast
Jump to solution

Evacuate-VMHost.ps1 script

I'm looking at the script in https://www.vxav.fr/2017-04-27-automatically-evacuate-a-host-without-drs/ , because, well, everytime I need to update our esx hosts, I need to move all VMs manually since we don't have DRS.

This script looks really promising, but it would be even better if it had the option of moving the VMs back to the original server after the maintenance is completed (for example by using the vmware tag on each vm to specify the prefered host to run the vm on).

I have literally zero experience with writing powershell scripts, so I was wondering if anyone here could help me with this?

PS: We need to have some of the VMs on specific hosts because of Windows OEM licenses that are tied to the host. For eaxmple, we have one host with a Windows Server 2016 Datacenter oem license, and one with 2012. The VMs that run Windows Server 2016 should be on the host that has the Server 2016 license to be compliant with Microsoft licensing.

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Even simpler :smileygrin:

$clusterName = 'cluster'

$tagCatName = 'Location'


Get-Cluster -Name $clusterName | Get-VM -PipelineVariable vm |

ForEach-Object -Process {

   $tag = Get-TagAssignment -Entity $vm -Category $tagCatName -ErrorAction SilentlyContinue

   if ($tag)

   {

     if ($tag.Tag.Name -ne $vm.VMHost.Name)

     {

       Move-VM -VM $vm -Destination $tag.Tag.Name -Confirm:$false

     }

   }

   else

   {

     Write-Host "VM $($vm.Name) is missing the tag required for this script."

   }

}


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

View solution in original post

Reply
0 Kudos
9 Replies
LucD
Leadership
Leadership
Jump to solution

Using tags is one solution, you could also opt for Custom Attributes (they still exist and are supported).

Pick one.

First step would be to assign tags (or custom attributes) to the VMs.

Is that info available in a file?
Or is the current situation the correct one, and a script could just use the current ESXi node where a VM is running?


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

Reply
0 Kudos
bmaster001
Enthusiast
Enthusiast
Jump to solution

Using tags would be fine. That way, there's no need for a file with this info, right?

I was thinking about a function that takes the preferred host as parameter, which then looks for all (running) VMs that have that host in their tag, and then migrate those VMs back to their preferred host.

Edit: I see two options for using the tags: I can manually enter all tags for hosts that have a preferred host, or the script can add a tag to each running vm on the specified host, and remove the tag when the VM is migrated back to it's preferred host...

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

But you first need to set the tags.
Hence my question if that

  • is available in a file
  • can we use the current ESXi node as the correct one

In the 2nd case, the script to do the initial setup is quite simple.

$clusterName = 'cluster'

$tagCatName = 'Location'


try

{

   $cat = Get-TagCategory -Name $tagCatName -ErrorAction Stop

}

catch

{

   $cat = New-TagCategory -Name $tagCatName -Description 'VMHost where VM needs to run' -Cardinality Single -EntityType VM

}


Get-Cluster -Name $clusterName | Get-VM -PipelineVariable vm |

ForEach-Object -Process {

   try

   {

   $tag = Get-Tag -Name $vm.VMHost.Name -ErrorAction Stop

   }

   catch

   {

   $tag = New-Tag -Name $vm.VMHost.Name -Category $cat -Description 'Preferred VMHost'

   }

   $assigned = Get-TagAssignment -Entity $vm -Category $cat -ErrorAction SilentlyContinue

   if ($assigned -and $assigned.Tag.Name -ne $vm.VMHost.Name)

   {

   Remove-TagAssignment -TagAssignment $assigned -Confirm:$false

   }

   New-TagAssignment -Tag $tag -Entity $vm -Confirm:$false

}


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

Reply
0 Kudos
bmaster001
Enthusiast
Enthusiast
Jump to solution

You call that 'quite simple', but for me it would take ages to write that 🙂

Something similar could be included in the Evacuate-script: if no tag is present for a VM then put the current host in the tag. That would be a good fallback for situations where someone creates a VM and forgets to add the correct tag (that would be me)

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Yes, or you could run this script each time before the evacuate script.


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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

If that works for you, then you will need a 2nd script.

That would run after your intervention is complete, and moves the VMs back to their preferred location.


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

Reply
0 Kudos
bmaster001
Enthusiast
Enthusiast
Jump to solution

Indeed. Something that searches for running VMs that are not on their preferred host, and then moves them back. Is that "quite simple" as well? 🙂

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Even simpler :smileygrin:

$clusterName = 'cluster'

$tagCatName = 'Location'


Get-Cluster -Name $clusterName | Get-VM -PipelineVariable vm |

ForEach-Object -Process {

   $tag = Get-TagAssignment -Entity $vm -Category $tagCatName -ErrorAction SilentlyContinue

   if ($tag)

   {

     if ($tag.Tag.Name -ne $vm.VMHost.Name)

     {

       Move-VM -VM $vm -Destination $tag.Tag.Name -Confirm:$false

     }

   }

   else

   {

     Write-Host "VM $($vm.Name) is missing the tag required for this script."

   }

}


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

Reply
0 Kudos
bmaster001
Enthusiast
Enthusiast
Jump to solution

Amazing, I will try all this asap since some updates need to be installed soon. Thanks very much for your help !!

Reply
0 Kudos