Last year I was asked to reduce the time spend on installing and configuring our ESX hosts.  Because we weren’t using Enterprise Plus licenses, we didn’t have Host Profiles.
I came up with a simple two-step process based on the EDA appliance and a custom PowerShell script.

  • Install the host from PXE.
    Only setting the minimum configuration, so it’s as versatile as possible.

    • Disk layout
    • Network teaming
    • FQDN and IP
  • Configure the host using a custom PowerShell script.
    Based on the Datacenter and Cluster the host is to be added to.

    • Add to vCenter
    • Set COS memory
    • Enable VMotion
    • License host
    • And much more…

A lot of blog posts are available on the net, on how to setup and install an ESX host using the EDA appliance so I won’t trouble you with this.

The PowerShell script is divided into several sections, I won’t explain everyone, only the most relevant, the rest is documented in the full script.
All steps in the script are logged to a host specific log file.

  • User input – Only 3 things are asked for when running the script, the rest is stored in the scripts Static section.
    • FQDN of the host (must be configured in DNS to work)
    • The environment – what environment is the host to be placed in, like PROD, DMZ, etc.
    • The hosts VMotion IP.
  • Add the host to the right cluster.
    You must have get the Datacenter/Cluster variable prior to adding the host, else it will just be placed in the first datacenter (See script for more info).

     add-vmhost $strHost -location $strvCenterDatacenter -user $strHostUser -password $strHostUserPWD -force: $true
     
  • Set the host in maintenance mode
     Get-VMHost -Name $strHost | Set-VMHost -State maintenance
     
  • License host.
    As you can see below, you have to supply the full name of the license you are adding, not just the license key.

     $targethostMoRef = (get-VMHost $strHost | get-view).MoRef
     $si = Get-View ServiceInstance
     $LicManRef=$si.Content.LicenseManager
     $LicManView=Get-View $LicManRef
     $licassman = (Get-View $LicManView.LicenseAssignmentManager)
    
     #$licassman.UpdateAssignedLicense($targethostMoRef.value,”YOUR LIC KEY”,”vSphere4 Enterprise Plus (1-12 cores per CPU”)
     $licassman.UpdateAssignedLicense($targethostMoRef.value,”YOUR LIC KEY”,”vSphere4 Enterprise (1-6 cores per CPU”)
     
  • Set the correct time zone.
     $strTimeZone = "Europe/Copenhagen"
     $tmpHost = Get-VMHost $strHost | get-view
     $tmpDTSystem =  $tmpHost.ConfigManager.DateTimeSystem
     $tmpMoRef = Get-View  $tmpDTSystem
     $tmpDateConfig = New-Object      Vmware.Vim.HostDateTimeConfig
     $tmpDateConfig.timeZone = $strTimeZone
     $tmpMoRef.updateDateTimeConfig($tmpDateConfig)
     
  • Add NTP servers.
    Use an array of NTP servers like
    $arrNTPServer = @(“dk.pool.ntp.org”,”de.pool.ntp.org”,”us.pool.ntp.org”,”clock.cimat.ues.edu.sv”,”ntp1.gbg.netnod.se”,”ntp1.theremailer.net”)

     Add-VMHostNtpServer -VMHost $strHost -NtpServer $arrNTPServer -Confirm:$false
     

    If you want you can restart the NTP service – only do it if you don’t plan on restarting the host after configuring.

     Restart-VMHostService $ntpd -Confirm:$false
     
  • Open firewall rules
    I always open the following firewall rules so that NTP and the SSH is working

     Get-VmhostFirewallException -VMHost $strHost -Name "NTP Client" | Set-VMHostFirewallException -enabled:$true
     Get-VmhostFirewallException -VMHost $strHost -Name "SSH Client" | Set-VMHostFirewallException -enabled:$true
     [/powershel]</li>
    	<li>Set the correct DNS servers
     Use an array of DNS servers, this way you can add multiple DNS servers at      once.
     @("10.10.10.40","10.10.10.30") or @("10.10.10.40")
     
     $strHost = @("10.10.10.40","10.10.10.30")
     Get-VMHost -Name $strHost | Get-View | %{$tmpNS = Get-View -Id $_.configManager.networkSystem
     $tmpDNS = $tmpNS.NetworkConfig.DnsConfig
     $tmpDNS.domainName = $strHostDomain
     $tmpDNS.address = $arrDNSsrv
     $tmpDNS.searchDomain = $strSearchDomain
     $tmpNS.updateDnsConfig($tmpDNS)}
     
  • Configuring network, adding network including VMotion.
    See the script for the full script.

     $vSwitch = Get-VirtualSwitch $strHost -Name vSwitch0
     #Set-VirtualSwitch -VirtualSwitch $vSwitch -Nic vmnic1
     New-VirtualPortGroup -VirtualSwitch $vSwitch -Name "VMOTION" -VLanId 0
     New-VMHostNetworkAdapter -VMHost $strHost -PortGroup "VMOTION" -VirtualSwitch $vSwitch -IP $strVMotion -SubnetMask $strSubnetMask -VMotionEnabled $true
     $strNetConfig = Get-View (Get-VMHost $strHost | Get-View).ConfigManager.NetworkSystem
     $strIPRoute = New-Object VMware.Vim.HostIpRouteConfig
     $strIPRoute.defaultGateway = $strGateway
     $strNetConfig.UpdateIpRouteConfig($strIPRoute)
     New-VirtualPortGroup -VirtualSwitch $vSwitch -Name "PROD" -VLanId 200
     New-VirtualPortGroup -VirtualSwitch $vSwitch -Name "PXE" -VLanId 0
     

    If needed you can remove the default VM network

     $vSwitch = Get-VirtualSwitch $strHost -Name vSwitch0
     $vmnetwork = Get-VirtualPortGroup -VirtualSwitch $vSwitch -Name "VM Network"
     Remove-VirtualPortGroup -VirtualPortGroup $vmnetwork -Confirm:$false}
     
  • Reboot the host J
     Get-VMHost -Name $strHost | %{Get-View $_.ID} | %{$_.RebootHost_Task($TRUE)}
     
  • If you want your script to wait for the host to be rebooted before continuing, you can do it with these two loops.
     do{
     $result = Get-VMHost $strHost
     Start-Sleep 10 # Wait 10 sec
     }
     Until($result.State -ne "Maintenance")
     # Maintenance - because host entered Maintenence mode earlier
    
     do{
     $result =  Get-VMHost $strHost
     Start-Sleep 10 # Wait 10 sec
     }
     Until($result.State -eq "Maintenance")
     
  • Finally exit the host from maintenance mode.
     Get-VMHost -Name $strHost | Set-VMHost -State connected
     

If everything is configured correctly, DRS should start migrating VM’s to the newly added host.

This script helped reducing the time spend on installing and configuring a host from 90 minutes to about 18 minutes. That’s a reduction of more than 500%, time you can use on other cool PowerShell tasks. J

By using a script to customize our hosts, we also gained two other benefits.

  1. Compliance – a host is always installed and configured the exact same way each time.
  2. Each step is documented in a host specific log file.

The full script can be downloaded here.