Ultimate Cross vCenter Script

Last year i attend the Dutch VMUG (NLVMUG) i followed session from

Michael Wilmsen that was: Migrate your datacenter without downtime.

I must also move al lot of VM’s from different datacenters to other datacenters.
I use the script from Michael Wilmsen to move the VM’s. But along the way I counter some problems with this script. So I begon tweaking and tweaking and tweaking this script to create for me the ultimate Cross vCenter PowerCLI Script.

Coolfeatures:
– Info through Whattsapp (Default not enabled)
– Dryrun (Test Run)
– Logging
– Selection through GUI
– Multiple Nic support maximum of 4.
– Datastore en Host selection based on Free space en Free Memory
– Check of Destination Host or Datastore in Maintance
– Destination Store exist in Destination Cluster

MoveVM.ps1:
#Filename: MoveVM.ps1
#Author: M. Wilmsen / W. Vissers
#Source: http://virtual-hike.com/nlvmug-2018/
#Version: 2.0
#Date: 21-10-2018
#ChangeLog:
# V0.9 – M. Wilmsen First Version
# V1.0 – Fixed Multiple Nics to maximium of 4 nics
#      – Logfile name VM name
# V1.1 – Destination Cluster not the first Host
# V1.2 – Selected Destination host based on memory used
# V1.3 – Fixed folder location and VirtualPortGroup
# V1.4 – Fixed Datastore in Maintance
# V1.5 – Using Get-VICredentialStoreItem + Logpath Fixt
# V1.6 – Fixed Log in Hours in 24 uurs
# V1.7 – Fixed Using DatastoreCluster name based on Cluster name!
# V1.8 – Check if Destination has the same datastore
#          – Ask know for input
#          – VM selection with VMhost
#          – Fixed Ping Check
# v1.9 – Added Destination Store exist in Destination Cluster
# v2.0 – Fixed Destination Store exist in Destination Cluster
<#
.SYNOPSIS
Script to migrate a virtual machine
.DESCRIPTION
Script to migrate compute and storage from cluster to cluster. Log will be in current dir [VM]-[-timestamp].log

.EXAMPLE
MoveVM.ps1
#>
################################## INIT #################################################
#Set WebOperation timeout
# set-PowerCLIConfiguration -WebOperationTimeoutSeconds 3600
#Define Global variables
$location = “D:\xmovewhattsapp”
$LogPath = “.\”
$DataStoreClusterPrefix = “SAN-“
$SourceVC = Read-Host “Give Source vCenter”
$DestinationVC = Read-Host “Give Destination vCenter”
$DRSRecommendation = $true
$Dryrun = $false
$SendWhatsApp = $false
$WhatsAppNumbers = “0123456789”
$WhatsAppGroup = “Namehireyourwhattsgroup”
$instanceId = “23” #chang this line
$clientId = “demo@demo.nl” #change this line
$clientSecret = “Puthiersecretid” #change this line
################################## PASSWORD STORE ##############################################
#Username
# Check if credentials exist in credential store if not ask for credentials and put them in credential store

If ((Get-VICredentialStoreItem).host -notcontains $SourceVC) {New-VICredentialStoreItem -Host $SourceVC -User $env:USERNAME -Password ((get-credential).GetNetworkCredential().Password)}
If ((Get-VICredentialStoreItem).host -notcontains $DestinationVC) {New-VICredentialStoreItem -Host $DestinationVC -User $env:USERNAME -Password ((get-credential).GetNetworkCredential().Password)}

# Remove-VICredentialStoreItem * -Confirm:$false

################################## END INIT #################################################
################################## FUNCTIONS #################################################
#Define log function
Function LogWrite
{
    Param ([string]$logstring)
    #Add logtime to entry
    $LogTime = Get-Date -Format “MM-dd-yyyy_HH-mm-ss”
    $logstring = $LogTime + ” : ” + $logstring
    #Write logstring
    Add-content $LogFile -value $logstring
    Write-Host $logstring
}
#Define SendWhatsApp function
Function SendWhatsApp
{
   Param ([string] $message)
  
   if ( $SendWhatsApp ) {
     $LogTime = Get-Date -Format “MM-dd-yyyy_hh-mm-ss”
     $message = $logtime + ” : ” + $message
    
     foreach ( $number in $WhatsAppNumbers )
     {
        $jsonObj = @{‘group_admin’=$number;
                     ‘group_name’=$WhatsAppGroup;
                     ‘message’=$message;}
       Try {
         $res = Invoke-WebRequest -Uri “http://api.whatsmate.net/v2/whatsapp/group/message/$instanceId” `
                           -Method Post   `
                           -Headers @{“X-WM-CLIENT-ID”=$clientId; “X-WM-CLIENT-SECRET”=$clientSecret;} `
                           -Body (ConvertTo-Json $jsonObj)
         LogWrite “WhatsMate Status Code: ”  $res.StatusCode
         LogWrite $res.Content
       }
       Catch {
         $result = $_.Exception.Response.GetResponseStream()
         $reader = New-Object System.IO.StreamReader($result)
         $reader.BaseStream.Position = 0
         $reader.DiscardBufferedData()
         $responseBody = $reader.ReadToEnd();

        Write-host “Status Code: ” $_.Exception.Response.StatusCode
         Write-host $message
         }
     }
   }
}

function Get-VmSize($vm)
{
     #Initialize variables
     $VmDirs =@()
     $VmSize = 0
     $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
     $searchSpec.details = New-Object VMware.Vim.FileQueryFlags
     $searchSpec.details.fileSize = $TRUE
     Get-View -VIObject $vm | % {
         #Create an array with the vm’s directories
         $VmDirs += $_.Config.Files.VmPathName.split(“/”)[0]
         $VmDirs += $_.Config.Files.SnapshotDirectory.split(“/”)[0]
         $VmDirs += $_.Config.Files.SuspendDirectory.split(“/”)[0]
         $VmDirs += $_.Config.Files.LogDirectory.split(“/”)[0]
         #Add directories of the vm’s virtual disk files
         foreach ($disk in $_.Layout.Disk) {
             foreach ($diskfile in $disk.diskfile){
                 $VmDirs += $diskfile.split(“/”)[0]
             }
         }
         #Only take unique array items
         $VmDirs = $VmDirs | Sort | Get-Unique
         foreach ($dir in $VmDirs){
             $ds = Get-Datastore ($dir.split(“[“)[1]).split(“]”)[0]
             $dsb = Get-View (($ds | get-view).Browser)
             $taskMoRef  = $dsb.SearchDatastoreSubFolders_Task($dir,$searchSpec)
             $task = Get-View $taskMoRef
             while($task.Info.State -eq “running” -or $task.Info.State -eq “queued”){$task = Get-View $taskMoRef }
             foreach ($result in $task.Info.Result){
                 foreach ($file in $result.File){
                     $VmSize += $file.FileSize
                 }
             }
         }
     }
     return $VmSize
}
################################## END FUNCTIONS #################################################
#Login to vCenter servers
if (($global:DefaultVIServers).Name -notcontains $SourceVC -or $DestinationVC) {

#SourceVC
$ConnectVC = Connect-VIServer $SourceVC
$Message = “Connecting to ” + $ConnectVC  + ” as ” + $env:USERNAME
#Logwrite $Message
#DestionationVC
$ConnectVC = Connect-VIServer $DestinationVC
$Message = “Connecting ” + $ConnectVC + ” as ” + $env:USERNAME
#Logwrite $Message

# Disconnect-VIServer * -Confirm:$false

}
Set-Location $location

$cluster=Get-Cluster -Server $SourceVC  | Out-GridView -OutputMode Single -Title “Select Source Cluster”
$vmtomigrate =Get-Cluster $cluster -Server $SourceVC | Get-VM | Out-GridView -OutputMode Single -Title “Select VM”
$DestinationCluster = Get-Cluster -Server $DestinationVC | Out-GridView -OutputMode Single -Title “Select Destination Cluster”
$vmfolder=Get-folder -Server $DestinationVC | Out-GridView -OutputMode Single -Title “Select Folder”

#Main Script

    #Set $MigError to false befor migration
     $MigError = $false
     #Get VM variables
     $vm = get-vm $vmtomigrate
    
     #Define LogFile with time stamp
     $LogTime = Get-Date -Format “MM-dd-yyyy_hh-mm-ss”
    
     if([IO.Directory]::Exists($LogPath))
     {
     #Do Nothing!!
     }
     else
     {
     New-Item -ItemType directory -Path $LogPath
     }
     $LogFile = $LogPath+$VM+”-“+$LogTime+”.log”
    
     # LogWrite Gebruiker
    
     Logwrite $env:USERNAME

    # Get-VM Info   
    
     $VMHDDSize = Get-VmSize($vm)
     $VMHDDSize = [Math]::Round(($VMHDDSize / 1GB),2)

    Logwrite “Start Virtual Machine Move”
     #If WhatsApp make notice
     if ( $SendWhatsApp ) { LogWrite “Notifications will be send using WhatsApp to WhatsApp Group: $WhatsAppGroup” }
     #If DryRun make Notice
     if ( $Dryrun ) {
     Logwrite “Start move virtual machines $vm Disksize $VMHDDSize GB (DryRun)”
     SendWhatsApp “Start move virtual machines $vm Disksize $VMHDDSize GB(DryRun)”
     }
     else {
     Logwrite “Start move virtual machines $vm Disksize $VMHDDSize GB”
     SendWhatsApp “Start move virtual machines $vm Disksize $VMHDDSize GB”
     }
     $SourceCluster = get-vm $vm | Get-Cluster | select name
     $vmip = $vm  | Select @{N=”IP Address”;E={@($_.guest.IPAddress[0])}}
     $vmip = $vmip.”ip address”
     $VMHDDSize = Get-VmSize($vm)
     $VMHDDSize = [Math]::Round(($VMHDDSize / 1GB),2)
     $NetworkAdapter = Get-NetworkAdapter -VM $vm -Server $SourceVC
     $SourceVMPortGroup = Get-NetworkAdapter -vm $vm | Select NetworkName
     $switchname = $DestinationCluster
    

     $Datastore = Get-VM $vm | Get-DataStore -Server $sourceVC | Select @{N=”Name”;E={@($_.Name)}}
     $Datastore = $Datastore.Name
     $DatastoreExistinOthervCenter = Get-Cluster $DestinationCluster | Get-DataStore -Server $DestinationVC | ? {$_.Name -like “*$Datastore*”}

     if ($DatastoreExistinOthervCenter )
      {
      LogWrite  “Datastore exsist $DestinationCluster in  destination vCenter $DestinationVC “
      $destinationDatastore = $DatastoreExistinOthervCenter }
      Else
      {
      LogWrite  “Datastore does not exsist in $DestinationCluster destination vCenter $DestinationVC”
      # Select DataStore with the most free space and not in maintance
      $DatastoreCluster = “$DataStoreClusterPrefix”+”$DestinationCluster”
      $destinationDatastore = Get-DatastoreCluster $DatastoreCluster | Get-Datastore | Where {$_.State -ne “Maintenance”} | Sort-Object -Property FreeSpaceGB -Descending | Select-Object -First 1
      }

     $destinationDatastoreFreeSpace = $destinationDatastore | Select Name,@{N=”FreeSpace”;E={$_.ExtensionData.Summary.FreeSpace}}
      $destinationDatastoreFreeSpace = [Math]::Round(($destinationDatastoreFreeSpace.”FreeSpace” / 1GB),2)

    # Select the host with the less used memory
   
     $DestinationHost = Get-Cluster –Name $DestinationCluster –Server $DestinationVC | Get-VMhost -State Connected | Sort-Object -Property MemoryUsageGB | Select-Object -First 1
            
     # Change Here if you have a vm with multiple Network Cards (Remove the # for the multiple nics)
    
     if ($NetworkAdapter.Count-eq 1) {
         $DestinationVMPortgroup =@()
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic1”
      }
     elseif ($NetworkAdapter.Count-eq 2) {
         $DestinationVMPortgroup =@()
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic1”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic2”
     }
     elseif ($NetworkAdapter.Count-eq 3) {
         $DestinationVMPortgroup =@()
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic1”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic2”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic3”
     }
     elseif ($NetworkAdapter.Count-eq 4) {
         $DestinationVMPortgroup =@()
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic1”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic2”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic3”
         $DestinationVMPortgroup += Get-VirtualPortGroup -Server $DestinationVC -Vmhost $DestinationHost | Out-GridView -OutputMode Single -Title “Select Nic4”
     }

    LogWrite “Start move: $vm”
     Logwrite “VM IP: $vmip”
     Logwrite “VM Disk Used (GB): $VMHDDSize”
     Logwrite “VM Folder: $vmfolder”
     Logwrite “Source vCenter: $SourceVC”
     Logwrite “VM Source Cluster: $SourceCluster”
     Logwrite “Destination vCenter: $DestinationVC”
     Logwrite “VM Destination Cluster: $DestinationCluster”
     Logwrite “Destination host: $DestinationHost”
     LogWrite “VM Source PortGroup: $SourceVMPortGroup”
     LogWrite “VM Destination Portgroup: $DestinationVMPortgroup”
     Logwrite “VM Destination Datastore: $destinationDatastore”
     LogWrite “Destination Datastore FreeSpace GB: $destinationDatastoreFreeSpace “
     if ( $Dryrun ) {
       $FreespaceAfterMigration = $destinationDatastoreFreeSpace – $VMHDDSize
       if ( $FreespaceAfterMigration -lt 0 ) { Logwrite “ERROR: Datastore $destinationDatastore does not have sufficient freespace! Virtual Machine needs $VMHDDSize. Only $destinationDatastoreFreeSpace available.” }
       else { Logwrite “Virtual Machine will fit on datastore $destinationDatastore. Freespace after migration is: $FreespaceAfterMigration GB” }
     }
    #Test if VM responsed to ping
    if ($vmip -eq $null) {
     LogWrite “Virtual Machine ip address not known”
     Logwrite “No ping check will be performed after moving the Virtual Machine”
     }
    else {
         Test-Connection -comp $vmip -quiet
         LogWrite “Virtual Machine $vm response to ping before being moved. Virtual machine will be checked after being moved”
         $PingVM = $true
     }
      
     #if ( $VMHDDSize -eq
     if ( -NOT $Dryrun) {
       #Migrate VM to cluster
       LogWrite “Move $vm to vCenter $DestinationVC and datastore $DestinationDatastore”
       Try {
         $Result = Move-VM -VM $vm `
                            -Destination $DestinationHost `
                            -Datastore $DestinationDatastore `
                            -NetworkAdapter $NetworkAdapter `
                            -PortGroup $DestinationVMPortgroup `
                            -ErrorAction Stop
           }
       Catch {
         $ErrorMessage = $_.Exception.Message
         LogWrite “ERROR: Move of $vm to cluster $DestinationHost failed!!!”
         Logwrite “ERROR: Move Status Code:  $ErrorMessage”
         SendWhatsApp “ERROR: Move of $vm failed!!! $ErrorMessage”
         $MigError = $true   
       }
       #Migrate VM to folder
       LogWrite “Move $vm to vCenter $vmfolder”
       Try {
         $VMtemp = get-vm $vm
         $Result = Move-VM -VM $vmtemp -InventoryLocation $vmfolder -ErrorAction Stop
           }
       Catch {
         $ErrorMessage = $_.Exception.Message
         LogWrite “ERROR: Move of $vm to folder $vmfolder failed!!!”
         Logwrite “ERROR: Move Status Code:  $ErrorMessage”
         SendWhatsApp “ERROR: Move of $vm failed!!! $ErrorMessage”
         $MigError = $true   
         }
       }
    
     $MigError = $false
     #Test if VM is running on destination cluster
     if ( -NOT $MigError -AND -NOT $Dryrun ) {
       LogWrite “Check $vm is registered in $DestinationVC”
       try {
         $CheckVM = get-vm -name $vm -server $DestinationVC -ErrorAction Stop
 
         if ( $CheckVM ) {
           Logwrite “$vm registered in $DestinationVC”
         }
         else {
           Logwrite “ERROR: $vm not found in $DestinationVC”
         }
       }
       catch {
         $ErrorMessage = $_.Exception.Message
         Logwrite “ERROR: $vm not found in $DestinationVC”
         Logwrite “ERROR: $ErrorMessage”
         SendWhatsApp “ERROR move: $vm not found in $DestinationVC”
       }
     }
     #Test is VM response to ping, if $PingVM = $True
     if ($PingVM) {
       if (Test-Connection -comp $vmip -quiet) {
         LogWrite “Virtual Machine $vm response to ping after move”
         SendWhatsApp “Virtual Machine $vm response to ping after move”
       } 
     }
     sleep 1
     SendWhatsApp “Finished move action: $vm from $SourceVC to $DestinationVC”
     Logwrite “Finished move action: $vm from $SourceVC to $DestinationVC”

if ($DRSRecommendation)
  {
   Get-DrsRecommendation -Cluster $DestinationCluster -Server $DestinationVC | Apply-DrsRecommendation
   Logwrite “DRS Recommendatation applyed”
  }
Else
  {
  Logwrite “No DRS Recommendatation applyed”
  Write-Host “No DRS Recommendatation applyed”
  }  
 

#Disconnect from vCenter servers
Logwrite “Disconnect from vCenter servers $SourceVC $DestinationVC”
Disconnect-viserver $SourceVC -Confirm:$false
Disconnect-viserver $DestinationVC -Confirm:$false
Logwrite “Finished moving virtual machines, exiting…..”
SendWhatsApp “Finished moving virtual machines, exiting…..”

vSphere 6.7 Update 1 Ready for Download

VMware vSphere Hypervisor (ESXi) 6.7U1
2018-10-16
Go to Downloads

VMware vCenter Server 6.7U1
2018-10-16
Go to Downloads

VMware vRealize® Log Insight™ 4.6.1 for vCenter™
2018-06-05
Go to Downloads

VMware vSphere Replication 8.1.0.4
2018-08-24
Go to Downloads

VMware vRealize Orchestrator Appliance 7.5.0
2018-09-20
Go to Downloads

VMware vRealize Operations Manager 7.0
2018-09-20
Go to Downloads

VMware NSX for vSphere 6.4.3
2018-09-11
Go to Downloads

PowerCLI Move All VM’s to other Host

################### Config ##################################

$SourceVC = “vcenter.wardvissers.nl

################## PASSWORD STORE #########################

#Username

# Check if credentials exist in credential store if not ask for credentials and put them in credential store

 

If ((Get-VICredentialStoreItem).host -notcontains $SourceVC) {New-VICredentialStoreItem -Host $SourceVC -User $env:USERNAME -Password ((get-credential).GetNetworkCredential().Password)}

 

# Remove-VICredentialStoreItem * -Confirm:$false

 

#################### END INIT ####################################

 

#Login to vCenter servers

if (($global:DefaultVIServers).Name -notcontains $SourceVC) {

 

#SourceVC

$ConnectVC = Connect-VIServer $SourceVC

 

# Get-Cluster –Name $DestinationCluster –Server $DestinationVC | Get-VMhost -State Connected | Sort-Object -Property MemoryUsageGB | Select-Object -First 1

 

$ESXiHostSrc = “esx01.wardvissers.nl”

$ESXiHostDst = “esx02.wardvissers.nl”

$vmList = Get-VMHost $ESXiHostSrc | Get-VM

$vmList | move-vm -destination (get-vmhost $ESXiHostDst)

}

Deploy Multi VM’s based on Windows Template

I love powershell. I created a little script to deploy multi VM based on a Windows Template throug CSV file.

It’s create a computer account at the specfified ou. He greates also a Domain Local Group for management. (It used in the customization not specified here)

TempVMlist.csv

server,cpu,memory,DestinationCluster,OSCustomizationSpec,VMtemplate,adgroup

WARDTEST01,2,8,CLUSTER01,W2012R2_Demo,TPL_W2012R2_STD,ServerAdmin

MultiVM.ps1

#Filename: MultiVM.ps1

#Author: W. Vissers

#Source:

#Version: 1.1

#Date: 08-05-2018

#ChangeLog:

# V1.0 – Module Active Directory

#      – Module VMware PowerCli

#      – Active Directory Computer Account, Group

#      – Host Selected from Cluster with Least Memory

#      – Storage selection based on volume with most free space

# V1.1 – Added Harddisk 1&2

#      – Changed porte group other vlan

#

<#

.SYNOPSIS

Script to create a virtual machine from template

.DESCRIPTION

Script to create a virtual machine from template

.EXAMPLE

MultiVM.ps1

#>

################################## INIT #################################################

# LoadModule Active Directory

if (!(Get-Module “activedirectory”)) {Import-module activedirectory}

Else {Write-Host “Module Active Directory is al ready loaded”}

# LoadModule VMware PowerCLI

# if (!(Get-Module “VMware.PowerCLI”)) {

#    Find-Module VMware.PowerCLI

#    Install-Module -Name VMware.PowerCLI -Scope CurrentUser

#}

#Else

# {

# Write-Host “Module PowerCLI is al ready loaded”

# }

#Config

$ouservers=”OU=Servers,DC=wardvissers.nl,DC=nl”

$ougroup=”OU=GroepObjecten,DC=wardvissers,DC=nl”

$folder=”Applicatie Servers”

$DestinationVC =”vcenter01.wardvissers.nl

#Username

if (!$username ) { $username = Read-Host “Give vCenter username ‘umcn\manz'”}

#Password

if ( -NOT $Password ) {

$PasswordSec = Read-Host “Give vCenter password” -AsSecureString

$Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($PasswordSec))

}

#Connect vCenter

$ConnectVC = Connect-VIServer $DestinationVC -Username $Username -Password $Password -AllLinked

$AllVMs = @()

$AllVMs = Import-Csv “D:\TempVMlist.csv”

foreach ($vm in $AllVMs) {

#Haal De Gegevens op

$server=$($vm.server)

$memory=$($vm.memory)

$cpu=$($vm.cpu)

$DestinationCluster=$($vm.DestinationCluster)

$OSSpec=”$($vm.OSCustomizationSpec)”

$VMtemplate=$($vm.VMtemplate)

$group=$($vm.adgroup)

$harddisk1=$($vm.harddisk1)

$harddisk2=$($vm.harddisk2)

Write-Host “$server heeft $memory GB memory en $cpu cpu(‘s)”

if ($server.length -gt 15) {

Write-Output “Hostname cannot contain more than 15 characters.”

$server = Read-Host “Re-enter hostname for host $server”}

Else

{

Write-Host “Server is umc server”

#Maak AD Groep aan en Computer Account

New-ADComputer -Name $server -Path $ouservers -Enabled $true

New-ADGroup -Name “DLG.$server” -SamAccountName “DLG.$server” -GroupCategory Security -GroupScope DomainLocal -DisplayName “DLG.$server” -Path $ougroup

Add-ADGroupMember -Identity “DLG.$server” -Members $group

}

# Rol server uit van Template

# Select the host with the less used memory

$DestinationHost = Get-Cluster –Name $DestinationCluster –Server $DestinationVC | Get-VMhost -State Connected | Sort-Object -Property MemoryUsageGB | Select-Object -First1

# Select DataStore with the most free space and not in maintance

$destinationDatastore = Get-Cluster $DestinationCluster | Get-Datastore | Where {$_.State -ne “Maintenance”} | Sort-Object -Property FreeSpaceGB -Descending | Select-Object -First 1

# Finally, I deploy my VM with the New-VM cmdlet using my template and OS specs. I place the VM on the ESXi host and store the VM on the datastore.

New-VM -Name $server -Template $VMTemplate -OSCustomizationSpec $OSSpec -VMHost $DestinationHOST -Datastore $DestinationDatastore -Location $folder

Get-VM $server | Set-VM -NumCpu $cpu -MemoryGB $memory -Confirm:$false

if ($harddisk1 -gt 60){Get-HardDisk -vm $server | Where {$_.Name -eq “Hard disk 1”} | Set-HardDisk -CapacityGB $harddisk1 -Confirm:$false}

if ($harddisk2 -gt 20) {Get-HardDisk -vm $server | Where {$_.Name -eq “Hard disk 2”} | Set-HardDisk -CapacityGB $harddisk2 -Confirm:$false}

Get-VM $server | Start-VM -Confirm:$false

Get-VM $Server | Get-NetworkAdapter | Set-NetworkAdapter -Connected $true -Confirm:$false

}

Important information before upgrading to vSphere 6.7 (KB53704)

This article provides important documentation and upgrade information that must be reviewed before upgrading to vSphere 6.7.


Resolution


Compatibility considerations

TLS protocols

These products are not compatible with vSphere 6.7 at this time:

  • VMware NSX
  • VMware Integrated OpenStack (VIO)
  • VMware vSphere Integrated Containers (VIC)
  • VMware Horizon

Environments with these products should not be upgraded to vSphere 6.7 at this time. This article and the VMware Product Interoperability Matrixes will be updated when a compatible release is available.

Upgrade Considerations

Before upgrading your environment to vSphere 6.7, review these critical articles to ensure a successful upgrade
For vSphere

Upgrades to vSphere 6.7 are only possible from vSphere 6.0 or vSphere 6.5. If you are currently running vSphere 5.5, you must first upgrade to either vSphere 6.0 or vSphere 6.5 before upgrading to vSphere 6.7.

For vCenter Server

For Distributed Virtual Switches

VMware vSphere 6.7

VMware is announcing vSphere 6.7, the latest release of the industry-leading virtualization and cloud platform. vSphere 6.7 is the efficient and secure platform for hybrid clouds, fueling digital transformation by delivering simple and efficient management at scale, comprehensive built-in security, a universal application platform, and seamless hybrid cloud experience.

vSphere 6.7 delivers key capabilities to enable IT organizations address the following notable trends that are putting new demands on their IT infrastructure:

  • Explosive growth in quantity and variety of applications, from business critical apps to new intelligent workloads.
  • Rapid growth of hybrid cloud environments and use cases.
  • On-premises data centers growing and expanding globally, including at the Edge.
  • Security of infrastructure and applications attaining paramount importance.

Let’s take a look at some of the key capabilities in vSphere 6.7:

Simple and Efficient Management, at Scale

vSphere 6.7 builds on the technological innovation delivered by vSphere 6.5, and elevates the customer experience to an entirely new level. It provides exceptional management simplicity, operational efficiency, and faster time to market, all at scale.

vSphere 6.7 delivers an exceptional experience for the user with an enhancedvCenter Server Appliance (vCSA). It introduces several new APIs that improve the efficiency and experience to deploy vCenter, to deploy multiple vCenters based on a template, to make management of vCenter Server Appliance significantly easier, as well as for backup and restore. It also significantly simplifies the vCenter Server topology through vCenter with embedded platform services controller in enhanced linked mode, enabling customers to link multiple vCenters and have seamless visibility across the environment without the need for an external platform services controller or load balancers.

Moreover, with vSphere 6.7 vCSA delivers phenomenal performance improvements (all metrics compared at cluster scale limits, versus vSphere 6.5):

  • 2X faster performance in vCenter operations per second
  • 3X reduction in memory usage
  • 3X faster DRS-related operations (e.g. power-on virtual machine)

These performance improvements ensure a blazing fast experience for vSphere users, and deliver significant value, as well as time and cost savings in a variety of use cases, such as VDI, Scale-out apps, Big Data, HPC, DevOps, distributed cloud native apps, etc.

vSphere 6.7 improves efficiency at scale when updating ESXi hosts, significantly reducing maintenance time by eliminating one of two reboots normally required for major version upgrades (Single Reboot). In addition to that, vSphere Quick Boot is a new innovation that restarts the ESXi hypervisor without rebooting the physical host, skipping time-consuming hardware initialization.

Another key component that allows vSphere 6.7 to deliver a simplified and efficient experience is the graphical user interface itself. The HTML5-based vSphere Client provides a modern user interface experience that is both responsive and easy to use. With vSphere 6.7, it includes added functionality to support not only the typical workflows customers need but also other key functionality like managing NSX, vSAN, VUM as well as third-party components.

Comprehensive Built-In Security

vSphere 6.7 builds on the security capabilities in vSphere 6.5 and leverages its unique position as the hypervisor to offer comprehensive security that starts at the core, via an operationally simple policy-driven model.

vSphere 6.7 adds support for Trusted Platform Module (TPM) 2.0 hardware devices and also introduces Virtual TPM 2.0, significantly enhancing protection and assuring integrity for both the hypervisor and the guest operating system. This capability helps prevent VMs and hosts from being tampered with, prevents the loading of unauthorized components and enables guest operating system security features security teams are asking for.

Data encryption was introduced with vSphere 6.5 and very well received.  With vSphere 6.7, VM Encryption is further enhanced and more operationally simple to manage.  vSphere 6.7 simplifies workflows for VM Encryption, designed to protect data at rest and in motion, making it as easy as a right-click while also increasing the security posture of encrypting the VM and giving the user a greater degree of control to protect against unauthorized data access.

vSphere 6.7 also enhances protection for data in motion by enabling encrypted vMotion across different vCenter instances as well as versions, making it easy to securely conduct data center migrations, move data across a hybrid cloud environment (between on-premises and public cloud), or across geographically distributed data centers.

vSphere 6.7 introduces support for the entire range of Microsoft’s Virtualization Based Security technologies. This is a result of close collaboration between VMware and Microsoft to ensure Windows VMs on vSphere support in-guest security features while continuing to run performant and secure on the vSphere platform.

vSphere 6.7 delivers comprehensive built-in security and is the heart of a secure SDDC. It has deep integration and works seamlessly with other VMware products such as vSAN, NSX and vRealize Suite to provide a complete security model for the data center.

Universal Application Platform

vSphere 6.7 is a universal application platform that supports new workloads (including 3D Graphics, Big Data, HPC, Machine Learning, In-Memory, and Cloud-Native) as well as existing mission critical applications. It also supports and leverages some of the latest hardware innovations in the industry, delivering exceptional performance for a variety of workloads.

vSphere 6.7 further enhances the support and capabilities introduced for GPUs through VMware’s collaboration with Nvidia, by virtualizing Nvidia GPUs even for non-VDI and non-general-purpose-computing use cases such as artificial intelligence, machine learning, big data and more. With enhancements to Nvidia GRID™ vGPU technology in vSphere 6.7, instead of having to power off workloads running on GPUs, customers can simply suspend and resume those VMs, allowing for better lifecycle management of the underlying host and significantly reducing disruption for end-users. VMware continues to invest in this area, with the goal of bringing the full vSphere experience to GPUs in future releases.

vSphere 6.7 continues to showcase VMware’s technological leadership and fruitful collaboration with our key partners by adding support for a key industry innovation poised to have a dramatic impact on the landscape, which is persistent memory. With vSphere Persistent Memory, customers using supported hardware modules, such as those available from Dell-EMC and HPE, can leverage them either as super-fast storage with high IOPS, or expose them to the guest operating system as non-volatile memory. This will significantly enhance performance of the OS as well as applications across a variety of use cases, making existing applications faster and more performant and enabling customers to create new high-performance applications that can leverage vSphere Persistent Memory.

Seamless Hybrid Cloud Experience

With the fast adoption of vSphere-based public clouds through VMware Cloud Provider Program partners, VMware Cloud on AWS, as well as other public cloud providers, VMware is committed to delivering a seamless hybrid cloud experience for customers.

vSphere 6.7 introduces vCenter Server Hybrid Linked Mode, which makes it easy and simple for customers to have unified visibility and manageability across an on-premises vSphere environment running on one version and a vSphere-based public cloud environment, such as VMware Cloud on AWS, running on a different version of vSphere. This ensures that the fast pace of innovation and introduction of new capabilities in vSphere-based public clouds does not force the customer to constantly update and upgrade their on-premises vSphere environment.

vSphere 6.7 also introduces Cross-Cloud Cold and Hot Migration, further enhancing the ease of management across and enabling a seamless and non-disruptive hybrid cloud experience for customers.

As virtual machines migrate between different data centers or from an on-premises data center to the cloud and back, they likely move across different CPU types. vSphere 6.7 delivers a new capability that is key for the hybrid cloud, called Per-VM EVC. Per-VM EVC enables the EVC (Enhanced vMotion Compatibility) mode to become an attribute of the VM rather than the specific processor generation it happens to be booted on in the cluster. This allows for seamless migration across different CPUs by persisting the EVC mode per-VM during migrations across clusters and during power cycles.

Previously, vSphere 6.0 introduced provisioning between vCenter instances. This is often called “cross-vCenter provisioning.” The use of two vCenter instances introduces the possibility that the instances are on different release versions. vSphere 6.7 enables customers to use different vCenter versions while allowing cross-vCenter, mixed-version provisioning operations (vMotion, Full Clone and cold migrate) to continue seamlessly. This is especially useful for customers leveraging VMware Cloud on AWS as part of their hybrid cloud.

Learn More

As the ideal, efficient, secure universal platform for hybrid cloud, supporting new and existing applications, serving the needs of IT and the business, vSphere 6.7 reinforces your investment in VMware. vSphere 6.7 is one of the core components of VMware’s SDDC and a fundamental building block of your cloud strategy. With vSphere 6.7, you can now run, manage, connect, and secure your applications in a common operating environment, across your hybrid cloud.

This article only touched upon the key highlights of this release, but there are many more new features. To learn more about vSphere 6.7, please see the following resources.

Setting Cluster Time outs for Microsoft Clustering on vSphere

I created a little script that set the correct time outs:

mscstimeoutsonvsphere.ps1:
import-module failoverclusters
get-cluster | fl *subnet*
(get-cluster).SameSubnetDelay = 1000
(get-cluster).SameSubnetThreshold = 10
(get-cluster).CrossSubnetDelay = 2000
(get-cluster).CrossSubnetThreshold = 10
get-cluster | fl *subnet*

Source:
Microsoft Cluster Service (MSCS) support on ESXi/ESX (1004617)
Guidelines for Microsoft Clustering on vSphere (1037959)

Fix “Already Used” status VMware Horizon View

When linked-clone desktops are not cleanly logged off and the “Refresh on logoff” policy is used, VMware Horizon View marks the desktop as “Already used” and blocks other users from accessing the machine.

This “Already Used” state is a default VMware security feature which prevents other users from accessing the previous user’s data and allows a VMware Horizon View administrator to investigate potential problems with the desktop.

The VMware Horizon View desktop can also go into the “Already Used” state if a virtual machine is powered on on another ESXi host in the cluster in response to an HA event, or if it was shut down without reporting to the broker that the user had logged out.

The problem with this “Already Used” state is that the default within VMware Horizon View waits until a View Administrator actually does something to resolve the issue.

To resolve the “Already Used” issue, you can

  • Refresh or delete the desktop through teh VMware Horizon View Administrator console (this is a manual action)
  • Set an LDAP attribute pae-DirtyVMPolicy in the VMware Horizon View ADAM database under OU=Server Groups,DC=vdi, DC=vmware, DC=int
    • pae-DirtyVMPolicy=0 – This is the default behavior of leaving the desktop in the error state and not available for use.
    • pae-DirtyVMPolicy=1 – This allows desktops that were not cleanly logged off to be available without being refreshed. The desktop is available in the pool for another user.
    • pae-DirtyVMPolicy=2 – This setting will automatically refresh a desktop in the “already used” state and make it available again in the pool.

I prefer to set the pae-DirtyVMPolicy to 2 so “Already Used” situations will be automatically resolved by VMware Horizon View.

Changing the pae-DirtyVMPolicy needs to be done for each pool.

Manual method of setting the pae-DirtyVMPolicy value:

  • Start the ADSI Edit utility on your VMware Horizon View Connection Server host. Go to Start > Programs > ADAM > ADAM ADSI Edit.
  • Select or type a Distinguished Name or connect to DC=vdi, DC=vmware, DC=int.
  • Select or type a domain or server to localhost:389.
  • Locate the OU=Server Groups for editing.
  • Under the Server Groups OU, double-click CN=pool_name. This opens the properties of the CN.
  • Click the pae-DirtyVmPolicy attribute and click Edit.
  • Set the pae-DirtyVmPolicy attribute

PowerCLI method of setting the pae-DirtyVMPolicy value:

  • Create a function “Set-DirtyVMPolicy”

function Set-DirtyVmPolicy([string]$desktopid, [int]$policy) {
     $pool = [ADSI](“LDAP://localhost:389/cn=” + $desktopid + “,ou=server groups,dc=vdi,dc=vmware,dc=int”)
     $pool.put(“pae-DirtyVmPolicy”, $policy )
     $pool.setinfo()
     }

  • Run the function on the desktop pool

Set-DirtyVMPolicy -desktopid <yourdesktoppoolid> -policy 2

AlreadyUsed

References: Ituda & TheFinalByte

ESXi host that is disconnected or not responding in VMware vCenter Server

ESXi

ALT-F1 = Switches to the console
ALT-F2 = Switches to the DCUI

Restart the Management agents on an ESXi or ESX host

From the Local Console or SSH:

Log in to SSH or Local console as root.
Run these commands:

/etc/init.d/hostd restart
/etc/init.d/vpxa restart