Automating The Installation Of VMware ESXi With PowerCLI

Please follow & like us :)

I saved a tweet a while back from William Lam about the ability to send keystrokes to a VM via PowerCLI. The first thing that popped into mind is “Automating a nested ESXi installation”. As you could imagine this would be extremely convenient in spinning up a new VMware Lab.

Last weekend was the day for testing this out!

The script works by a function that allows you to specify which keystrokes to send via vCenter Server, directly to the VM. For example, as you type a word, IP address, etc, the script will loop through each character and send them 1-by-1 to the VM. Let’s say you want to set the IP address for your ESXi host, you can simply send 192.168.1.10 and voila, it will appear on the host.

Set-VMKeystrokes -VMName MYESXIHOST -StringInput "192.168.1.10"

The script function that William Lam provides is more than awesome in itself, however, I made a few tweaks to add additional functionality. What mods did I make you ask?

The original script is great for single digit characters, however, what if I need to send a function key such as F2 or press the ESC key?

Automating VMware ESXi Installations – Modifications to Original Function

In order to allow for these special keys, I had to change the mandatory -StringInput switch to being optional. I also added another switch called -SpecialKeyInput which includes:

  • All functions keys (F1-F12)
  • Keyboard TAB, ESC, Backspace, Enter
  • Keyboard Up, Down, Left, Right

With the extra modifications being set, it was time to start creating the script line by line. You will find the entire script below. It is important to note that you must do the following before running the script:

  • You will need PowerCLI – You can find the install instructions here
  • The script requires a minimum of ESXi 6.5
  • Set all your variables in the “Set your variables here” section of the script
  • There are sleep timers in the script of 5 seconds. I found within my lab some windows took 1-2 seconds to appear after pressing enter
  • There are some Pauses in the script which allows you to double check a setting or wait for the install. (Optionally you could remove the PAUSE and set a long Sleep timer such as 5 mins)
  • Boot your ESXi VM to the installation screen (see screenshot below)

Automating VMware ESXi Install with PowerCLI

Automating VMware ESXi with PowerCLI Demonstration

 

Automating ESXi Installation PowerCLI Script

Before running the script in your lab, please watch the video above so you can see what the whole process looks like and how the script will behave.

NOTE: The Debug output is turned on for all Set-VMKeyStrokes. You can disable Debug Output by changing the switch from -DebugOn $True to -DebugOn $False

GITHUB: The script is also available on my Github page

<#
    ===========================================================================
    Main Script Created by: David Rodriguez
    Blog:                   www.sysadmintutorials.com
    Twitter:                @systutorials

    Set-VMKeystrokes Function
    Created by:    William Lam
    Organization:  VMware
    Blog:          www.virtuallyghetto.com
    Twitter:       @lamw 
    ===========================================================================
    .DESCRIPTION
    This Script will Automate your ESXi installation by sending keystrokes 
    directly to the VM.
    
    .SETTINGS
    Scroll down to, "Set your Variables here"
    
    .IMPORTANT
    When all your variables are set, you must boot ESXi so that it's waiting 
    at the installation prompt. Once at the installation prompt, you can 
    proceed to run this script and watch the magic happen
#>

# Connect to vCenter Server

$VcenterServer = "vmvcenter.vmlab.local" #Vcenter Server that contains the nested esxi host - Replace with your vCenter server address

Connect-VIServer $VcenterServer -ErrorAction Stop #Connect to vCenter Server

# Set your Variables here

$UseVlan = "No" #Use Yes/No here, if you would like to assign a vlan to your esxi host

$VlanID = "" #If using the above option, set VLAN ID here. If not leave blank ""

$VirtualMachine = Get-VM nsx-a-esxi4 #Set your nested ESXi VM Name here

$Ipv4Address = "192.168.1.89" #Set ESXi Host IP Address

$Ipv4Subnet = "255.255.255.0" #Set ESXi Host Subnet Mask
 
$Ipv4Gateway = "192.168.1.1" #Set ESXi Host Default Gateway

$PrimaryDNS = "192.168.1.101" #Set ESXi Host Primary DNS

$HostName = "nsx-a-esxi4.vmlab.local" #Set ESXi Host Name

$DNSSuffix = "vmlab.local" #Set ESXi DNS suffix

$RootPw = "vmware123!" #Set ESXi Root Password

sleep 5

# Functions
Function Set-VMKeystrokes {
<#
    .NOTES
    ===========================================================================
     Created by:    William Lam
     Organization:  VMware
     Blog:          www.virtuallyghetto.com
     Twitter:       @lamw
    ===========================================================================
    .DESCRIPTION
        This function sends a series of character keystrokse to a particular VM
    .PARAMETER VMName
		The name of a VM to send keystrokes to
	.PARAMETER StringInput
		The string of characters to send to VM
	.PARAMETER DebugOn
		Enable debugging which will output input charcaters and their mappings
    .EXAMPLE
        Set-VMKeystrokes -VMName $VM -StringInput "root"
    .EXAMPLE
        Set-VMKeystrokes -VMName $VM -StringInput "root" -ReturnCarriage $true
    .EXAMPLE
        Set-VMKeystrokes -VMName $VM -StringInput "root" -DebugOn $true
    ===========================================================================
     Modified by:   David Rodriguez
     Organization:  Sysadmintutorials
     Blog:          www.sysadmintutorials.com
     Twitter:       @systutorials
    ===========================================================================
    .MODS
        Made $StringInput Optional
        Added a $SpecialKeyInput - See PARAMETER SpecialKeyInput below
        Added description to write-hosts [SCRIPTINPUT] OR [SPECIALKEYINPUT]
    .PARAMETER StringInput
        The string of single characters to send to the VM
    .PARAMETER SpecialKeyInput
        All Function Keys i.e. F1 - F12
        Keyboard TAB, ESC, BACKSPACE, ENTER
        Keyboard Up, Down, Left Right
    .EXAMPLE
        Set-VMKeystrokes -VMName $VM -SpecialKeyInput "F2"

#>
    param(
        [Parameter(Mandatory=$true)][String]$VMName,
        [Parameter(Mandatory=$false)][String]$StringInput,
        [Parameter(Mandatory=$false)][String]$SpecialKeyInput,
        [Parameter(Mandatory=$false)][Boolean]$ReturnCarriage,
        [Parameter(Mandatory=$false)][Boolean]$DebugOn
    )

    # Map subset of USB HID keyboard scancodes
    # https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2
    $hidCharacterMap = @{
		"a"="0x04";
		"b"="0x05";
		"c"="0x06";
		"d"="0x07";
		"e"="0x08";
		"f"="0x09";
		"g"="0x0a";
		"h"="0x0b";
		"i"="0x0c";
		"j"="0x0d";
		"k"="0x0e";
		"l"="0x0f";
		"m"="0x10";
		"n"="0x11";
		"o"="0x12";
		"p"="0x13";
		"q"="0x14";
		"r"="0x15";
		"s"="0x16";
		"t"="0x17";
		"u"="0x18";
		"v"="0x19";
		"w"="0x1a";
		"x"="0x1b";
		"y"="0x1c";
		"z"="0x1d";
		"1"="0x1e";
		"2"="0x1f";
		"3"="0x20";
		"4"="0x21";
		"5"="0x22";
		"6"="0x23";
		"7"="0x24";
		"8"="0x25";
		"9"="0x26";
		"0"="0x27";
		"!"="0x1e";
		"@"="0x1f";
		"#"="0x20";
		"$"="0x21";
		"%"="0x22";
		"^"="0x23";
		"&"="0x24";
		"*"="0x25";
		"("="0x26";
		")"="0x27";
		"_"="0x2d";
		"+"="0x2e";
		"{"="0x2f";
		"}"="0x30";
		"|"="0x31";
		":"="0x33";
		"`""="0x34";
		"~"="0x35";
		"<"="0x36";
		">"="0x37";
		"?"="0x38";
		"-"="0x2d";
		"="="0x2e";
		"["="0x2f";
		"]"="0x30";
		"\"="0x31";
		"`;"="0x33";
		"`'"="0x34";
		","="0x36";
		"."="0x37";
		"/"="0x38";
		" "="0x2c";
        "F1"="0x3a";
        "F2"="0x3b";
        "F3"="0x3c";
        "F4"="0x3d";
        "F5"="0x3e";
        "F6"="0x3f";
        "F7"="0x40";
        "F8"="0x41";
        "F9"="0x42";
        "F10"="0x43";
        "F11"="0x44";
        "F12"="0x45";
        "TAB"="0x2b";
        "KeyUp"="0x52";
        "KeyDown"="0x51";
        "KeyLeft"="0x50";
        "KeyRight"="0x4f";
        "KeyESC"="0x29";
        "KeyBackSpace"="0x2a";
        "KeyEnter"="0x28";
    }

    $vm = Get-View -ViewType VirtualMachine -Filter @{"Name"="^$($VMName)$"}

	# Verify we have a VM or fail
    if(!$vm) {
        Write-host "Unable to find VM $VMName"
        return
    }

    #Code for -StringInput
    if($StringInput)
    {
        $hidCodesEvents = @()
    foreach($character in $StringInput.ToCharArray()) {
        # Check to see if we've mapped the character to HID code
        if($hidCharacterMap.ContainsKey([string]$character)) {
            $hidCode = $hidCharacterMap[[string]$character]

            $tmp = New-Object VMware.Vim.UsbScanCodeSpecKeyEvent

            # Add leftShift modifer for capital letters and/or special characters
            if( ($character -cmatch "[A-Z]") -or ($character -match "[!|@|#|$|%|^|&|(|)|_|+|{|}|||:|~|<|>|?|*]") ) {
                $modifer = New-Object Vmware.Vim.UsbScanCodeSpecModifierType
                $modifer.LeftShift = $true
                $tmp.Modifiers = $modifer
            }

            # Convert to expected HID code format
            $hidCodeHexToInt = [Convert]::ToInt64($hidCode,"16")
            $hidCodeValue = ($hidCodeHexToInt -shl 16) -bor 0007

            $tmp.UsbHidCode = $hidCodeValue
            $hidCodesEvents+=$tmp

            if($DebugOn) {
                Write-Host "[StringInput] Character: $character -> HIDCode: $hidCode -> HIDCodeValue: $hidCodeValue"
            }
        } else {
            Write-Host "[StringInput] The following character `"$character`" has not been mapped, you will need to manually process this character"
            break
        }
       
    }
    }

    #Code for -SpecialKeyInput
     if($SpecialKeyInput)
     {
       if($hidCharacterMap.ContainsKey([string]$SpecialKeyInput)) 
        {
        $hidCode = $hidCharacterMap[[string]$SpecialKeyInput]
        $tmp = New-Object VMware.Vim.UsbScanCodeSpecKeyEvent
        $hidCodeHexToInt = [Convert]::ToInt64($hidCode,"16")
            $hidCodeValue = ($hidCodeHexToInt -shl 16) -bor 0007

            $tmp.UsbHidCode = $hidCodeValue
            $hidCodesEvents+=$tmp

            if($DebugOn) {
                Write-Host "[SpecialKeyInput] Character: $character -> HIDCode: $hidCode -> HIDCodeValue: $hidCodeValue"
            }
        } else {
            Write-Host "[SpecialKeyInput] The following character `"$character`" has not been mapped, you will need to manually process this character"
            break
        }
    }
    
    # Add return carriage to the end of the string input (useful for logins or executing commands)
    if($ReturnCarriage) {
        # Convert return carriage to HID code format
        $hidCodeHexToInt = [Convert]::ToInt64("0x28","16")
        $hidCodeValue = ($hidCodeHexToInt -shl 16) + 7

        $tmp = New-Object VMware.Vim.UsbScanCodeSpecKeyEvent
        $tmp.UsbHidCode = $hidCodeValue
        $hidCodesEvents+=$tmp
    }

    # Call API to send keystrokes to VM
    $spec = New-Object Vmware.Vim.UsbScanCodeSpec
    $spec.KeyEvents = $hidCodesEvents
    Write-Host "Sending keystrokes to $VMName ...`n"
    $results = $vm.PutUsbScanCodes($spec)
}

# From this point forward, the ESXi configuration starts

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - Key Enter

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "F11" -DebugOn $True #ESXi Setup - Press F11 to accept EULA

Write-Host "Check that you are installing ESXi to local disk, if correct press Enter" -BackgroundColor DarkRed -ForegroundColor White

PAUSE

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - Key Enter

Write-Host "Setting US Default for Keyboard Layout" -ForegroundColor Yellow

SLEEP 5

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - Key Enter

Write-Host "Setting Root Password for ESXi" -ForegroundColor Yellow

SLEEP 5

Set-VMKeystrokes -VMName $VirtualMachine -StringInput "$RootPw" -ReturnCarriage $True -DebugOn $True #ESXi Setup - Root password

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "TAB" -DebugOn $True #ESXi Setup - Root password

Set-VMKeystrokes -VMName $VirtualMachine -StringInput "$RootPw" -ReturnCarriage $True -DebugOn $True #ESXi Setup - Root password

Write-Host "Beginning the Installation" -ForegroundColor Yellow

SLEEP 5

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "F11" -DebugOn $True #ESXi Setup - Begin Installation

Write-Host "Once the install has finished, press Enter to Reboot and Complete Installation" -BackgroundColor DarkGreen -ForegroundColor White

PAUSE

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - Key Enter

Write-Host "Once Host has rebooted, Press Enter to Begin ESXi setup" -BackgroundColor DarkRed -ForegroundColor White

PAUSE

#Start ESXi Configuration

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "F2" -DebugOn $True #ESXi Setup - F2 to login

SLEEP 5

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "TAB" -DebugOn $True #ESXi Setup - Tab to Password

Set-VMKeystrokes -VMName $VirtualMachine -StringInput "$RootPw" -ReturnCarriage $True -DebugOn $True #ESXi Setup - Root password

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - Key Enter

SLEEP 15

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down to Configure Management Network

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - Key Enter

#Use VLAN or Not

If ($UseVlan -eq "Yes")
    {
    Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down to VLAN

    Set-VMKeystrokes -VMName $VirtualMachine -StringInput " " -ReturnCarriage $True -DebugOn $True #ESXi Setup - Enter

    Set-VMKeystrokes -VMName $VirtualMachine -StringInput "$VlanID" -ReturnCarriage $True -DebugOn $True #ESXi Setup - Enter

    Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyESC" -DebugOn $True #ESXi Setup - ESC back

    Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down to IPv4 Configuration

    Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - Key Enter

    }
ELSE
    {
    Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down

    Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down to IPv4 Configuration

    Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - Key Enter

    }

#Set IPv4 Configuration

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down

Set-VMKeystrokes -VMName $VirtualMachine -StringInput " " -DebugOn $True #ESXi Setup - Select Disable IPv6

SLEEP 5

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyBackSpace" -DebugOn $True #ESXi Setup - Remove existing IPv4 Address

Set-VMKeystrokes -VMName $VirtualMachine -StringInput "$Ipv4Address" -DebugOn $True #ESXi Setup - Enter IPv4 Address

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyBackSpace" -DebugOn $True #ESXi Setup - Remove existing IPv4 Subnet

Set-VMKeystrokes -VMName $VirtualMachine -StringInput "$Ipv4Subnet" -DebugOn $True #ESXi Setup - Enter IPv4 Subnet

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyBackSpace" -DebugOn $True #ESXi Setup - Remove existing IPv4 Default Gateway

Set-VMKeystrokes -VMName $VirtualMachine -StringInput "$Ipv4Gateway" -DebugOn $True #ESXi Setup - Enter IPv4 Subnet

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - Remove existing IPv4 Default Gateway

SLEEP 5

#Disable IPv6

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - IPv6 Configuration

SLEEP 5

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyUp" -DebugOn $True #ESXi Setup - Key Down

Set-VMKeystrokes -VMName $VirtualMachine -StringInput " " -DebugOn $True #ESXi Setup - Select Disable IPv6

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - IPv6 Commit Changes

SLEEP 5

#Set DNS Configuration

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - DNS Configuration

SLEEP 5

Set-VMKeystrokes -VMName $VirtualMachine -StringInput "$PrimaryDNS" -DebugOn $True #ESXi Setup - Primary DNS IP Address

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyBackSpace" -DebugOn $True #ESXi Setup - Remove existing Hostname

Set-VMKeystrokes -VMName $VirtualMachine -StringInput "$HostName" -DebugOn $True #ESXi Setup -Hostname

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - DNS Commit Changes

SLEEP 5

#Set Custom DNS Suffixes

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyDown" -DebugOn $True #ESXi Setup - Key Down

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - DNS Commit Changes

SLEEP 5

Set-VMKeystrokes -VMName $VirtualMachine -StringInput "$DNSSuffix" -DebugOn $True #ESXi Setup -Hostname

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyEnter" -DebugOn $True #ESXi Setup - DNS Commit Changes

SLEEP 5

#Complete Setup and Reboot

Set-VMKeystrokes -VMName $VirtualMachine -SpecialKeyInput "KeyESC" -DebugOn $True #ESXi Setup - ESC back

SLEEP 5

Set-VMKeystrokes -VMName $VirtualMachine -StringInput "Y" -DebugOn $True #ESXi Setup - Apply Changes and reboot host

Write-Host "Your Host is now Ready!!" -BackgroundColor DarkGreen -ForegroundColor White

 

Be the first to comment

Leave a Reply

Your email address will not be published.


*


*

This site uses Akismet to reduce spam. Learn how your comment data is processed.