PowerCLI: Migrate templates during the Enter Maintenance Mode task

Normally when you put a host into Maintenance mode the templates will stay on the host instead of being migrate to a different host. This can be very annoying if you are performing maintenance on the vSphere host and a colleague needs to deploy a VM from the template. I am running vSphere 4.1 update 1. I don’t know if this is still the case with vSphere 5. The host in Maintenance mode will look like this:


So to fix this annoying “issue” I have created a PowerCLI function to place the vSphere host into maintenance mode and if there are Templates registered on the vSphere host, the Templates will be moved to another host in the Cluster.

Function Enter-MaintenanceMode{
.SYNOPSIS   Enter Maintenance mode 
.DESCRIPTION   The function starts the Enter Maintenance task and also migrates the Templates to another host.
.NOTES   Author:  Arne Fokkema
   One vmHosts.
   PS> Enter-MaintenanceMode<vmHost Name>
  PS> Get-VMHost <vmHost Name> | Enter-MaintenanceMode

    [parameter(ValueFromPipeline = $true,
    position = 0,
    Mandatory = $true,
    HelpMessage = "Enter the vmHost to start the Enter Maintenance mode task")]

    $templates = Get-VMHost $vmHost | Get-Template
    if($templates -eq $null){
        $tplMigrate = $false
        $tplMigrate = $true
    $targetVMHost = Get-VMHost -Location (Get-Cluster -VMHost (Get-VMhost $vmHost)).Name | Where {$_.Name -ne $vmHost} | Sort Name | Select -First 1
    if($tplMigrate -eq $true){
        foreach($tpl in $templates){
            Write-Host "Converting template $($tpl.Name) to VM" -ForegroundColor Yellow
            $vm = Set-Template -Template (Get-Template $tpl) -ToVM 
            Write-Host "Moving template $($tpl.Name) to vmHost: $($targetVMHost)" -ForegroundColor Yellow
            Move-VM -VM $vm -Destination (Get-VMHost $targetVMHost) -Confirm:$false | Out-Null
            Write-Host "Converting template $($tpl.Name) back to template" -ForegroundColor Yellow
            ($vm | Get-View).MarkAsTemplate() | Out-Null    
    Write-Host "Enter Maintenance mode $($vmHost)" -ForegroundColor Yellow
    Set-VMHost $vmHost -State Maintenance | Out-Null

You can run the script like this:

Enter-MaintenanceMode esx07

Or from the pipeline:

Get-VMHost esx07 | Enter-MaintenanceMode

The output will be the same:


And the host is completely empty and ready for maintenance:



PowerCLI: Move-Template


Storage vMotion is a great feature to Move your VMs to other datastores. But what if you want to move your Templates?
In the current version of vSphere there is no option within the Client:


So I created a PowerCLI function just to migrate the templates to another datastore.

function Move-Template{
    param( [string] $template, [string] $esx, [string] $datastore)

    if($template -eq ""){Write-Host "Enter a Template name"}
    if($esx -eq ""){Write-Host "Enter an ESX hostname"}
    if($esx -ne "" -and $datastore -eq ""){$vmotion = $true}
    if($datastore -ne ""){$svmotion = $true}

    Write-Host "Converting $template to VM"
    $vm = Set-Template -Template (Get-Template $template) -ToVM 

        Write-Host "Migrate $template to $esx and $datastore"
        Move-VM -VM (Get-VM $vm) -Destination (Get-VMHost $esx) `
        -Datastore (Get-Datastore $datastore) -Confirm:$false
        (Get-VM $vm | Get-View).MarkAsTemplate() | Out-Null

        Write-Host "Migrate $template to $esx"
        Move-VM -VM $vm -Destination (Get-VMHost $esx) -Confirm:$false
        ($vm | Get-View).MarkAsTemplate() | Out-Null

The function above can be used to move a single template via

Move-Template <template> <esxhost> <datastore>

But what if you want to move only your Linux Templates or Windows Templates or even all the Templates at once.  For these options, I created two extra functions.

First I created a function to get al the Linux templates:

function Get-LinuxTemplates{
    $lnxtpl = Get-Template | Get-View | `
    where {$_.Guest.GuestFamily -eq 'linuxGuest'} | `
    return $lnxtpl


And if you want, you can also get al the Windows templates:

function Get-WindowsTemplates{
    $wintpl = Get-Template | Get-View | `
    where {$_.Guest.GuestFamily -eq 'windowsGuest'} | `
    return $wintpl


Now we can get all the different templates, we are able to move the templates to another host or datastore.

This is how you move all the templates to a new host and datastore:

$templates = Get-Template
foreach($tpl in $templates){
    Move-Template $tpl <esxhost> <datastore>


If you want to move all the Linux templates, you run the following commands:

$templates = Get-LinuxTemplates
foreach($tpl in $templates){
    Move-Template $tpl <esxhost> <datastore>

And finally, you can move all windows templates by running these commands:

$templates = Get-WindowsTemplates
foreach($tpl in $templates){
    Move-Template $tpl <esxhost> <datastore>

But how does it look when you run the function. I will do an example with the get-linuxtemplates function.


I am going to use this functions in another script and will transform it to a ready to use script for the EcoShell.

vSphere: Deploy Template grayed out


I wanted to deploy a template via the vSphere client but I was unable to achieve this task because the option was grayed out.  After restarting the vCenter services and the vCenter server I was still unable to deploy a template.


Non of the options where available. So PowerCLI to the rescue:

$templates = Get-Template *
    foreach($item in $templates){
        $template = $item.Name
            #Convert Template back to VM
            Set-Template $template -ToVM -RunAsync
            #Convert Template back to template :S
            $vmview = Get-VM $template | Get-View


After running the script above. I was able to deploy my templates again 🙂