Speedup host readiness for VMware Cloud Foundation (VCF)

Hi, and welcome to my first post.

In the last couple of months I have doing lots of POCs (Proof Of Concepts) about VMware Cloud Foundation (VCF onwards) and every time I reinstalled the hosts to show the Bring Up process (that will be covered in another post) I was spending a lot of time, approximately 10 minutes per host between login, page navigation and configuration, to get a host ready to be used by the Cloud Builder VM.

Because of that, I have developed a script to speedup the process and minimizing the human error of having a configuration mismatchs between hosts.

The Cloud Builber VM requirements for the ESXi are the following:

Note: They might be different depending on the version of VCF you are using, at least for 3.9.1, 4.0, 4.1 the above image is the same.

If any of the above requirements are not met, the Cloud Builder VM will display a warning message that can be dismissed, but the process will fail and you will have to start over.

The script will address only the following ones:

  • VM Network portgroup must match the Management Network VLAN ID
  • TSM-SSH must be turned on and configured to Start and Stop with Host
  • NTP must be configured, running and configured to Start and Stop with Host
  • Check if the vSwitch0 has more than one nic configured (just inform, does not modify vSwitch nic assingment)

How to run it? Grab the latest version of Power CLI from VMware{code}, copy the content of the script into a file and save it with a .ps1 extension, open powershell as an administrator and run the .ps1 file. The script itself will modify some PowerShell configurations to run.

The script run will look something like the following.

  • Errors that must be fixed are displayed on red
  • Warnings might be ignored and are displayed on yellow

So now that we know which are the requirements and how to run it lets dig in into the code. Feel free to copy, modify and share it. If you find any bug or recommendation please post it in the comments section.

Ps! While this post is out, I’m working on a new version to make it even easier. So be ready for more VCF scripts!

If it fails just run $error on powershell and send me the output to fix it!

#fcardarelli@soluciones.com.ar - 10/24/2020
#Speed up of VCF host readiness
#OCT/31/2020 -> Added DNS Server configuration
#NOV/12/2020 -> Fixed a bug when no hostnames were entered
  
#Added to ignore the invalid certificate warning
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
  
#Clear the view
cls
  
Write-Host -ForeGround 'Yellow' -back 'black' 'To use this script you will need to:'
Write-Host -ForeGround 'Yellow' -back 'black' '- Have configured ESXi management networks'
Write-Host -ForeGround 'Yellow' -back 'black' '- Have root password'
Write-Host -ForeGround 'Yellow' -back 'black' '- Provide all the IP Addresses, VLAN ID, and NTP Addreses'
  
$warning = 'Enter Y to continue. ---> '
Do {
  Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
  $continue = Read-Host
  $warning = 'Mmmm... Some info missing? When ready enter a Y to continue! ---> '
} While ($continue -notmatch 'Y')
  
#Regex patterns for validations
$ipRegexPattern = '^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$'
$vlanRegexPattern = '[0-4095]'
$fqdnRegexPattern = '(?=^.{1,254}$)(^(?:(?!\d+\.|-)[a-zA-Z0-9_\-]{1,63}(?<!-)\.?)+(?:[a-zA-Z]{2,})$)'
$hostcountRegexPattern = '[1-100]'
  
#Variables
$esxiIPs = @()
$hostnames = @()
  
#Constants
$esxUser = 'root'
  
$warning = 'Enter the root password, it wil be hidden so relax of watchers! ---> '
Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
  
#Request root password for host configuration
$esxPswd = Read-Host -AsSecureString
$credentials = New-Object System.Management.Automation.PSCredential ('root', $esxPswd)
  
for ($i= 0 ;$i -lt 4;$i++){
  
    switch ( $i )
    {
        0 { $warning = 'Enter the IP address of the FIRST ESXi! ---> '}
        1 { $warning = 'Enter the IP address of the SECOND ESXi! ---> '}
        2 { $warning = 'Enter the IP address of the THIRD ESXi! ---> '}
        3 { $warning = 'Enter the IP address of the FORTH ESXi! ---> '}
    }
      
    Do {
      Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
      $esxi = Read-Host
      $warning = 'You did not enter a valid IP address. Please try again! ---> '
    } While ($esxi -notmatch $ipRegexPattern)
    $esxiIPs += $esxi
}
  
#Configure hostnames?
$warning = 'Do you want to configure esxi Hostnames? If already configured on DCUI, skip this step. Enter Y to confirm. ---> '
Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
$configureHostnames = Read-Host
  
if ($configureHostnames -eq 'Y'){
    for ($i= 0 ;$i -lt 4;$i++){
  
        switch ( $i )
        {
            0 { $warning = 'Enter the Hostname (FQDN) of the FIRST ESXi! ---> '}
            1 { $warning = 'Enter the Hostname (FQDN) of the SECOND ESXi! ---> '}
            2 { $warning = 'Enter the Hostname (FQDN) of the THIRD ESXi! ---> '}
            3 { $warning = 'Enter the Hostname (FQDN) of the FORTH ESXi! ---> '}
        }
          
        Do {
          Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
          $hostname = Read-Host
          $warning = 'You did not enter a valid FQDN. Please try again! ---> '
        } While ($hostname -notmatch $fqdnRegexPattern)
        $hostnames += $hostname
    }
}
else{
    Write-Host -ForeGround 'Yellow' -back 'black' 'Ok, no hostname configuration' 
}
  
$warning = 'Enter the VLAN ID for the VM Network (it must match the Management Network VLAN)! ---> '
Do {
  Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
  $VLANID = Read-Host
  $warning = 'You did not enter a valid VLAN ID. Please try again! ---> '
} While ($VLANID -notmatch $vlanRegexPatter)
  
$warning = 'Enter the NTP Address! ---> '
Do {
  Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
  $NTP1 = Read-Host
  $warning = 'You did not enter a valid NTP IP Address. Please try again! ---> '
} While ($NTP1 -notmatch $ipRegexPattern)
  
  
#Need another NTP Server?
$warning = 'Add a second NTP? Enter Y to confirm ---> '
Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
$anotherNTP = Read-Host
  
if ($anotherNTP -eq 'Y'){
    $warning = 'Enter the Secondary NTP Address! ---> '
    Do {
      Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
      $NTP2 = Read-Host
      $warning = 'You did not enter a valid NTP IP Address. Please try again! ---> '
    } While ($NTP2 -notmatch $ipRegexPattern) 
}
 
 
#DNS Configurations
$warning = 'Enter primary DNS Server! ---> '
Do {
  Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
  $dnspri = Read-Host
  $warning = 'You did not enter a valid DNS IP Address. Please try again! ---> '
} While ($dnspri -notmatch $ipRegexPattern)
  
  
#Need another DNS Server?
$warning = 'Add a second DNS Server? Enter Y to confirm ---> '
Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
$anotherDNS = Read-Host
  
if ($anotherDNS -eq 'Y'){
    $warning = 'Enter the Secondary DNS IP Address! ---> '
    Do {
      Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
      $dnsalt = Read-Host
      $warning = 'You did not enter a valid DNS IP Address. Please try again! ---> '
    } While ($dnsalt -notmatch $ipRegexPattern) 
}
 
#DNS Configurations
$warning = 'Enter search domain name! ---> '
Do {
  Write-Host -ForeGround 'Yellow' -back 'black' -noNewLine $warning
  $searchdomainname = Read-Host
  $warning = 'You did not enter a valid DNS IP Address. Please try again! ---> '
} While ($searchdomainname -notmatch $fqdnRegexPattern)
 
#Loop with all the ip address provided
$counter = 0
foreach ($esxi in $esxiIPs) {
  
    $errorFlag = $false
  
    Write-host 'Connecting to ' $esxi
      
    try {
        Connect-VIServer -Server $esxi -Credential $credentials -ErrorAction Stop | Out-Null
        Write-Host -ForeGround 'black' -back 'green' 'Connected to host =======> ' $esxi
        $esxcli = Get-EsxCli -VMHost $esxi
         
        if ($hostnames.length -gt 0){
            $esxcli.system.hostname.set($null,$hostnames[$counter],$null) | Out-Null
        }
          
        #Search for vSwitch0 object
        $vswitch = Get-VirtualSwitch -VMHost $esxi -Name vSwitch0
          
        if ($vswitch.nic.length -gt 1){
            Write-Host -ForeGround 'white' -back 'red' 'Host ' $esxi ' has more than 1 nic on vSwitch0, please check the host before proceeding with Bring Up Process.'
            $errorFlag = $true
        }
        else{
            Write-Host -ForeGround 'black' -back 'green' 'Host ' $esxi ' has only 1 nic on vSwitch 0. Well done!'
        }
  
        try{
              
            $VMNetworkPG = Get-VirtualPortgroup -Name 'VM Network'
            Set-VirtualPortGroup -VirtualPortGroup $VMNetworkPG -VLanID $VLANID -ErrorAction Stop | Out-Null
            Write-Host -ForeGround 'black' -back 'green' 'Configured VM Network of host ' $esxi ' with VLAN ID ' $VLANID
        }
        catch
        {
            Write-Host 'The portgroup might not be created, lets try to fix it.'
            #Create the PG and set the VLAN ID
            $VMNetworkPG = New-VirtualPortGroup -VirtualSwitch $vswitch  -Name 'VM Network' | Out-Null
            Set-VirtualPortGroup -VirtualPortGroup $VMNetworkPG -VLanID $VLANID -ErrorAction Stop | Out-Null
            Write-Host -ForeGround 'black' -back 'green' 'Configured VM Network of host ' $esxi ' with VLAN ID ' $VLANID
        }
  
        try{    
            #NTP Adjustment
            Add-VMHostNtpServer -VMHost $esxi -NtpServer $NTP1 -ErrorAction Stop | Out-Null
            Write-Host -ForeGround 'black' -back 'green' 'Configured NTP Server 1 of host ' $esxi ' with NTP ' $NTP1
        }
        catch
        {
            Write-Host -ForeGround 'black' -back 'Yellow' 'I was not able to configure NTP ' $NTP1 ' on ' $esxi ' maybe its already added.'
              
        }
          
        if ($NTP2 -ne '') {
            try{    
                #NTP Adjustment
                Add-VMHostNtpServer -VMHost $esxi -NtpServer $NTP2 -ErrorAction Stop | Out-Null
                Write-Host -ForeGround 'black' -back 'green' 'Configured NTP Server 2 of host ' $esxi ' with NTP ' $NTP2
            }
            catch
            {
                Write-Host -ForeGround 'black' -back 'Yellow' 'I was not able to configure NTP ' $NTP2 ' on ' $esxi ' maybe its already added.'
            }
        }
         
        if ($dnsalt -ne '') {
            try{    
                #DNS Servers Adjustment
                Get-VMHostNetwork -VMHost $esxi | Set-VMHostNetwork -DNSAddress $dnspri, $dnsalt -SearchDomain $searchdomainname -Confirm:$false | Out-Null
                Write-Host -ForeGround 'black' -back 'green' 'Configured DNS Servers of host ' $esxi ' with DNS Server ' $dnspri ' and ' $dnsalt
            }
            catch
            {
                Write-Host -ForeGround 'black' -back 'Yellow' 'I was not able to configure DNS ' $dnspri ' and ' $dnsalt ' on ' $esxi ' maybe its already added.'
                  
            }
 
        }
        else
        {
            try{    
                #DNS Servers Adjustment
                Get-VMHostNetwork -VMHost $esxi | Set-VMHostNetwork -DNSAddress $dnspri -SearchDomain $searchdomainname -Confirm:$false | Out-Null
                Write-Host -ForeGround 'black' -back 'green' 'Configured DNS Server 1 of host ' $esxi ' with DNS Server ' $dnspri
            }
            catch
            {
                Write-Host -ForeGround 'black' -back 'Yellow' 'I was not able to configure DNS ' $dnspri ' on ' $esxi ' maybe its already added.'
                  
            }
        }
  
        #Adjust the ESXi time with local computer time
        $t = Get-Date
        $dst = Get-VMHost -Name $esxi | %{ Get-View $_.ExtensionData.ConfigManager.DateTimeSystem }
        $dst.UpdateDateTime((Get-Date($t.ToUniversalTime()) -format u)) | Out-Null
        Write-Host -ForeGround 'black' -back 'green' 'Synchornized time of host ' $esxi ' with computer time '
  
        #Open NTP ports
        Get-VMHostFirewallException -VMHost $esxi | where {$_.Name -eq 'NTP client'} | Set-VMHostFirewallException -Enabled:$true | Out-Null
        Write-Host -ForeGround 'black' -back 'green' 'Added firewall exception for NTP Client on host ' $esxi
  
        #Start NTP Service and set it to autostart
        Get-VmHostService -VMHost $esxi | Where-Object {$_.key -eq 'ntpd'} | Start-VMHostService -Confirm:$false | Out-Null
        Get-VmHostService -VMHost $esxi | Where-Object {$_.key -eq 'ntpd'} | Set-VMHostService -policy 'on' | Out-Null
        Write-Host -ForeGround 'black' -back 'green' 'NTP started and configured to Start and Stop with host on host ' $esxi
  
        #Start SSH Service and set it to autostart
        Get-VmHostService -VMHost $esxi | Where-Object {$_.key -eq 'TSM-SSH'} | Start-VMHostService -Confirm:$false | Out-Null
        Get-VmHostService -VMHost $esxi | Where-Object {$_.key -eq 'TSM-SSH'} | Set-VMHostService -policy 'on' | Out-Null
        Write-Host -ForeGround 'black' -back 'green' 'TSM-SSH started and configured to Start and Stop with host on host ' $esxi
          
        $counter += 1
  
        Disconnect-VIServer -Server $esxi -Confirm:$false
        Write-Host -ForeGround 'black' -back 'green' '<======= Disonnected from host ' $esxi
          
        if ($errorFlag){
            Write-Host -ForeGround 'white' -back 'red' 'Check the configuration of ' $esxi ' before proceeding with bring up process.'
        }
        else{
            Write-Host -ForeGround 'black' -back 'green' 'Host ' $esxi ' is ready for VCF! Woho!'
        }
    }
    catch{
        Write-Host -ForeGround 'white' -back 'red' 'I was not able to connect ' $esxi ' please check the connection to it.'
    }
}

2 thoughts on “Speedup host readiness for VMware Cloud Foundation (VCF)”

Leave a Reply to fcardarelli Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s