Chapter 2
Automating vSphere Hypervisor Deployment and Configuration

In this chapter, you will learn to:

  • Prepare for an Installation
  • Customizing the vSphere ISO
  • The Installation Medium
  • Gathering Required Software
  • Automate an Installation
  • Customizing an Installation with Kickstart
  • Postinstallation Configuration

There was a time when automating an installation and configuration of the vSphere Hypervisor was quite difficult. Fortunately, VMware has worked hard to simplify the overall process. Today 90 percent of the installation is automated out of the box. In this chapter we will briefly walk through the various installation methods before taking a deep dive into automating that last 10 percent. We will cover several techniques for streamlining the installation and configuration of vSphere.

Prepare for an Installation

The first step in preparing for an installation is to ensure that your install media is up-to-date and has all of the needed drivers and other vendor packages for your servers. This includes things like storage vendor plug-ins, as well as the Fiber Channel Host Based Adapter (HBA), NIC, SCSI controller, and IPMI/CIM drivers that enable vSphere to better interact with your hardware and provide increased performance, stability, and reporting. PowerCLI has a feature known as the Image Builder CLI, which enables you to manage the packages contained in the install ISO and customize them for your needs.

Customizing the vSphere ISO

VMware ships the ESXi ISO with many default packages. You may not need all of them. Often, you need additional drivers. The install image can be customized using PowerCLI. You can tailor it specifically for your environment and include only those packages that are required for your servers.

To get started, make sure that you have downloaded the offline bundle for the version of ESXi you plan to use. Offline bundles are zip files that typically are much larger than the default ISO download. Once you have downloaded an offline bundle, download to the same directory the driver packages that you need. Like the ESXi packages, if your vendor gives you options for online or offline bundles, choose the offline bundle.

To start, you need to add the packages that have been downloaded, which are treated as depots of software packages by PowerCLI. Listing 2-1 shows how to make the Image Builder CLI aware of a downloaded update package. We also want to make sure that the PSSnapin that provides the cmdlets has been added to the environment.

Listing 2-1: Adding an offline bundle package as a software depot

Add-PSSnapin Vmware.ImageBuilder -ErrorAction SilentlyContinue

Add-EsxSoftwareDepot $pathToEsxiOfflineBundle_zip
Add-EsxSoftwareDepot $pathToVendorBundle_zip

You can add as many of these bundles as needed to the cmdlet in Listing 2-2, which checks for packages that have been added and shows an example return.

Listing 2-2: Showing available bundles

Get-EsxSoftwareDepot

Depot Url
---------
zip:C:	empVMware-ESXi-6.0.0-2494585-depot.zip?index.xml
zip:C:	empNetAppNasPlugin.v21.zip?index.xml

Each bundle contains one or more software packages that will be combined, using the cmdlets, to make the customized install media for your installation. To list the available packages, use the Get-EsxSoftwarePackage cmdlet. The most interesting will be the non-VMware packages, since these are the ones you are probably trying to add to the default set. In Listing 2-3, we use PowerShell to show only those packages that are not part of VMware’s default bundle.

Listing 2-3: Listing non-VMware software packages

Get-EsxSoftwarePackage | Where-Object {$_.Vendor -ne "VMware"}

After you have downloaded the bundles, you can begin to modify the default images to customize them for your environment. Each bundle includes several image profiles; you can build an image profile to meet your needs from there. To view the existing image profiles, use the Get-ESXImageProfile cmdlet, as we did in Listing 2-4.

Listing 2-4: Showing available image profiles

Get-EsxImageProfile -Name ESXi-6* | Select-Object Name

Name
----
ESXi-6.0.0-2494585-no-tools
ESXi-6.0.0-2494585-standard

The packages have three basic types: Standard, which includes VMware Tools; No-tools, which is self-explanatory; and those that have a name ending with “s,” which are security updates images. The steps for creating a package are as follows:

  1. Clone the base profile.
  2. Add and remove packages as needed.
  3. Export the profile.

Listing 2-5 shows the PowerCLI used to execute those steps and ends by exporting the modified profile as an ISO image that can be used for loading your servers.

Listing 2-5: Modifying the ESXi profile

New-EsxImageProfile `
    -CloneProfile ESXi-6.0.0-2494585-standard `
    -Name ESXi-6.0.0-PowerCLI `
    -Vendor Custom |
    Add-EsxSoftwarePackage `
        -SoftwarePackage $additionalPackageName |
    Remove-EsxSoftwarePackage `
        -SoftwarePackage $removeThisPackage

Name                 Vendor  Last Modified   Acceptance Level
----                 ------  -------------   ----------------
ESXi-6.0.0-PowerCLI  Custom  3/8/2015 12:... PartnerSupported

Pipelining the commands makes for an easy way to do all three operations (clone, add, and remove) in one simple step. The final operation is to export the newly customized installation profile to an ISO image (see Listing 2-6).

Listing 2-6: Exporting the customized image

Export-EsxImageProfile -ImageProfile ESXi-6.0.0-PowerCLI `
    -FilePath $destinationFolder `
    -ExportToIso

The final parameter for the command can be either ExportToIso, which will output an ISO that can be used to install vSphere to the host, or ExportToBundle, which will output a bundle capable of being ingested by Update Manager or directly on the host for providing updates to packages.

Now that you have ensured the drivers and other packages for your physical servers are a part of the default install package, let’s investigate the different ways of loading the OS onto the physical host.

The Installation Medium

There are several different methods to install vSphere, ranging from the humble CD/DVD to the more complex, but more flexible, PXE. The installation method is the starting point from which you work backward. Once you have selected an install medium, you then tailor your automation and workflows to that method.

A large part of choosing the installation method is related to the size of your vSphere environment. Each of the available methods carries with it a series of trade-offs. We’ll cover each medium available, highlighting the advantages and disadvantages of each in addition to identifying a target environment size.

  1. CD/DVD Old faithful, the CD/DVD, has been around since long before ESX, and it continues on with vSphere. This is the most basic medium because it offers no updating facility. CD/DVD is most commonly used in small environments with just a handful of hosts. It is, however, the simplest, which means that anyone can leverage this method.
  2. Thumb Drive/USB Key The heir apparent to the optical drive, USB keys are the preferred installation medium for small/medium environments, generally those with fewer than 10 hosts. They have the inherent ability to be updated easily, and they are significantly faster than optical drives. Because they can be easily updated, they are also an excellent source for vSphere Kickstart-based installations.
  3. PXE The most flexible (and usually fastest) of all installs, Preboot Execution Environment (PXE) has the most complex setup. Once configured, it’s easy to maintain and update the images as needed. The biggest downside is the infrastructure required to perform a PXE-based installation. Though not extreme, it is still overkill for small/medium environments. We consider PXE a minimum requirement for any environment with more than 10 hosts.

Gathering Required Software

We’re going to make the assumption that, since you’re reading a PowerCLI book, your management station is a Windows PC. Therefore, the following requirements apply:

  1. CD/DVD For a CD/DVD installation, you will need an ISO Image editing tool such as ImgBurn, available for download from www.imgburn.com/.
  2. Thumb Drive/USB Key For a thumb drive/USB key installation, you’ll need UNetbootin, available from http://unetbootin.sourceforge.net/.
  3. PXE A multitude of PXE implementations are available, most of them based on Linux. That said, we recommend you use what you’re comfortable with, and if you have no comfort zone, we recommend Carl Thijssen’s Ultimate Deployment Appliance (UDA), available from www.ultimatedeployment.org/.

Automate an Installation

Automating a vSphere installation can mean many different things. At its core, it means you have a zero-touch installation. As you learned earlier, this can be accomplished regardless of the media you choose. You will, however, outgrow this minimal automation solution very quickly, as it doesn’t help solve the bigger problem of host configuration. To resolve that issue, you must first answer one simple, multiple-choice question.

  1. Are you more comfortable using:
    1. BusyBox/Python
    2. PowerCLI
    3. Host profiles
    4. All of the above

If you chose option A, you will want to try to do as much as possible with the first boot and postinstall sections within Kickstart—but you will find you cannot do everything. The advantage of option A is that there are no external requirements. This is a great solution for small environments. If you have the time and skill set to configure a vSphere host via BusyBox/Python, it is possible to automate just about every aspect of vSphere.

If you chose option B, you will want to configure the bare minimum via Kickstart. Most likely, you’ll configure the management vmknic and partition assignment. That said, it is exponentially easier to perform some actions, like password and license assignment, from Kickstart.

If you chose option C, you undoubtedly have Enterprise+ licensing and want to use this advanced feature. Unfortunately, there are some things that you cannot do using host profiles (see Chapter 5, “Using Advanced vSphere Features,” for more information). Host profiles do offer a compelling capability—compliance. Anything that can be done via host profiles should be done via host profiles, because they will ensure that your hosts continue to be configured correctly.

If you haven’t figured it out already, option D is the best answer. You should use a combination of all three, assuming you have sufficient licensing to use host profiles. There are some aspects of vSphere configuration that are just easier to do while loading the host. Some matters are best left to host profiles. PowerCLI is the glue in all this that will bridge these two disparate worlds. If host profiles are off the table, take the path of least resistance and use both Kickstart and PowerCLI.

Customizing an Installation with Kickstart

As of ESXi 4.1, VMware supports a scripted installation mode: Kickstart. Kickstart is a configuration file that the installer reads in and then uses to perform a silent installation. Exploring the full set of options and capabilities of the Kickstart configuration file is beyond the scope of this book, but we will go over the basics, starting with how to have a non-interactive installation from the CD/DVD and USB installation mediums (see Listing 2-7).

Listing 2-7: A Kickstart configuration for non-interactive installation

# A minimal ks.cfg file which will provide a non-interactive
# installation experience.  Note that you will need to customize
# the boot media to specify the ks.cfg path to fully remove
# interaction.  This is simply a default configuration, no
# customization will be done.

# Accept the EULA.  This is a mandatory parameter.
vmaccepteula

# Set the root password.  The password is mandatory, and
# can optionally be encrypted.
rootpw Power$hell

# Install to the first local drive, overwriting any VMFS partitions.
# This can be customized to select different drives, upgrade only, and
# many other operations.
install --firstdisk --overwritevmfs

# Default to DHCP for network connectivity.  The option addvmportgroup
# can be left out, which will cause the install to create a default
# virtual machine port group on the vSwitch.  Setting the value to
# zero bypasses that step.
network --bootproto=dhcp --device=vmnic0 --addvmportgroup=0

# Reboot after completion.  Without this option the install will wait
# for the administrator to press a button at the end of the install
# process.
reboot

Using a USB key for the installation media makes including Kickstart files incredibly easy. Simply create a directory in the root of the drive and place the file there. Figure 2-1 shows the file structure of the install media after it has been loaded. This USB device was created by taking a customized ISO and leveraging UNetbootin to copy the media to the drive.

Notice in Figure 2-1 that a folder named kickstarts was created at the root of the device. Simply copy any Kickstart files to that folder location, but don’t forget their names! After booting to the USB device you will need to specify the Kickstart location at the boot loader prompt.

c02f001.tif

Figure 2-1: USB installation media file layout

Figure 2-2 shows the host after booting to the USB media. When the boot menu screen is displayed, press any key to interrupt the process. Press the Tab key to edit the boot options for your device and append ks=usb:/kickstarts/ks.cfg, where ks.cfg is the name of your Kickstart file. Once you provide the path to your Kickstart file (Figure 2-3), simply press Enter and go get a cup of coffee (but don’t bring it in the datacenter!).

c02f002.tif

Figure 2-2: Host boot screen

c02f003.tif

Figure 2-3: Boot configuration customization

If this is too much effort for you, you can edit the file ISOLINUX.CFG in the root of your USB media. Find the line under the “LABEL install” section that contains the APPEND descriptor and append the same text we used earlier. Listing 2-8 shows what the file should look like after editing.

Listing 2-8: A completely hands-off ISOLINUX.CFG

DEFAULT handsfree
MENU TITLE ESXi-6.0.0-PowerCLI Boot Menu
NOHALT 1
PROMPT 0
TIMEOUT 80
LABEL install
  KERNEL mboot.c32
  APPEND -c boot.cfg
  MENU LABEL ESXi-5.5.0-PowerCLI ^Installer
LABEL handsfree
  KERNEL mboot.c32
  APPEND -c boot.cfg ks=usb:/kickstarts/ks.cfg
  MENU LABEL Hands-Free ESXi Install
LABEL hddboot
  LOCALBOOT 0x80
  MENU LABEL ^Boot from local disk

Postinstallation Configuration

As we indicated earlier, you have several options for postinstallation configuration. They all fall into one of two categories: online or stand-alone. An example of a stand-alone installation is the traditional monolithic Kickstart.

A stand-alone installation should only be used in scenarios where the network connectivity cannot be assumed. In such an install, all the postconfiguration tasks must be handled via the Kickstart %post and %firstboot scripts. This is neither easy nor recommended, but under certain conditions, it is the only way to automate all parts of installation. For instance, when you port-channel all network connections to your host, it will not be able to connect to the network until the load-balance configuration has been done on the vSwitch. Because this is a prerequisite for network connectivity, it cannot be done remotely.

As shown in Listing 2-9, you can use a script as the %post section of a Kickstart configuration file. This two-line script adds a second NIC to the standard vSwitch and enables an IP hash load-balancing scheme.

Listing 2-9: Configuring vSwitch load balancing using Kickstart

%firstboot --interpreter=busybox
# add a second NIC to the standard vSwitch
esxcli network vswitch standard uplink add 
    -v vSwitch0 -u vmnic1

# update the load balance to use ip hash
esxcli network vswitch standard policy failover set 
    -v vSwitch0 -a vmnic0,vmnic1 -l iphash

An online installation is the preferred method for configuring vSphere. Host profiles fall into this category because they require network access to function. It is possible to perform online postinstallation configuration as either a semiautomated or fully automated task. For instance, you could manually run a PowerCLI/vCLI script to configure a fresh vSphere host. This approach is still far better than the completely manual process. For example, Listing 2-10 takes a fresh vSphere host and performs the following configuration tasks:

  1. Adds the host to vCenter
  2. Locks the ESX(i) host down
  3. Creates an iSCSI VMkernel port on vSwitch0
    • VLAN: 55
    • IP: 10.10.55.3
    • Mask: 255.255.255.0
  4. Configures iSCSI storage
    • Enables the Software iSCSI HBA
    • Renames the host iSCSI IQN
    • Configures CHAP authentication
    • Adds the iSCSI target

Listing 2-10: Postinstallation configuration from a manually run script

# Add our host to vCenter, and immediately enable lockdown mode!
$VMhost = Add-VMHost -Name vSphere03.vSphere.local `
    -User root `
    -Password pa22word `
    -Location (Get-Datacenter) `
    -Force

Set-VMHostLockdown -VMHost $VMhost -Enable

# Add iSCSI VMkernel vNIC
$vSwitch = Get-VirtualSwitch -VMHost $VMHost -Name 'vSwitch0'
# we have to first create a portgroup to bind our vNIC to.
$vPG = New-VirtualPortGroup -Name iSCSI `
    -VirtualSwitch $vSwitch `
    -VLanId 55
# Create our new vNIC in the iSCSI PG we just created
$vNIC = New-VMHostNetworkAdapter -VMHost $VMHost `
    -PortGroup iSCSI `
    -VirtualSwitch $vSwitch `
    -IP 10.10.55.3 `
    -SubnetMask 255.255.255.0

# Enable the software iSCSI adapter if not already enabled.
$VMHostStorage = Get-VMHostStorage -VMHost $VMhost |
    Set-VMHostStorage -SoftwareIScsiEnabled $True

#sleep while iSCSI starts up
Start-Sleep -Seconds 30

# By default vSphere will set the Target Node name to
# iqn.1998-01.com.vmware:<HostName>-<random number> the
# following cmd will remove everything after the hostname, set
# Chap auth, and add a send Target.
#
# Example iqn.1998-01.com.vmware:esx01-165435 becomes
# iqn.1998-01.com.vmware:esx01
#
# Note that if your hostname has dashes in it, you'll
# need to change the regex below.
$pattern = "iqn.1998-01.com.vmware:w*"
Get-VMHostHba -VMHost $VMHost -Type IScsi |
    Where-Object {$_.IScsiName -match $pattern} |
    Set-VMHostHba -IScsiName $Matches[0] |
    Set-VMHostHba -ChapName 'vmware' `
        -ChapPassword 'password' `
        -ChapType "Required" |
    New-IScsiHbaTarget -Address '192.168.1.1' -Port "3260" |
        Out-Null

The advantage of a script like the one in Listing 2-10 is that it is efficient and repeatable. You can reload vSphere03 with reckless abandon, knowing it will be a quick and simple process to get your host back to hosting virtual machines. You’ll notice that we used a custom PowerCLI function to enable Lockdown mode on the vSphere host. Set-VMHostLockdown, featured in Listing 2-11, can be used to automate vSphere host Lockdown mode en masse.

Listing 2-11: Using the Set-VMHostLockdown function

function Set-VMHostLockdown {
    <#  .SYNOPSIS
        Enable or disable lockdown mode for an ESXi host.

        .EXAMPLE
        Enable lockdown mode for an ESXi host
        Set-VMHostLockdown -VMHost (Get-VMHost $name) -Enable

        .EXAMPLE
        Use the pipeline to disable lockdown mode for a cluster
        Get-Cluster someCluster | Set-VMHostLockdown -Enable:$false

        .PARAMETER VMHost
        The host to modify.

        .PARAMETER Enable
        Enable lockdown mode for the specified host.

        .PARAMETER Disable
        Disable lockdown mode for the specified host.

        .INPUTS
        [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl]
    #>

    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
        # the VMHost to enable or disable lockdown on
        [Parameter(
            Mandatory=$true,
            ValueFromPipeline=$true,
            HelpMessage="VMHost"
        )]
        [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl]
        $VMHost
        ,

        # enable/disable lockdown
        [Parameter(Mandatory=$true)]
        [switch]
        $Enable
    )
    Process {
        $hostView = $VMHost | Get-View -Property Name

        if ($Enable) {
            $msg = "Entering lockdown mode"

            if ($PsCmdlet.ShouldProcess($VMHost.Name, $msg)) {
                $hostView.EnterLockdownMode()
            }
        } else {
            $msg = "Exiting lockdown mode"

            if ($PsCmdlet.ShouldProcess($VMHost.Name, $msg)) {
                $hostView.ExitLockdownMode()
            }
        }

    }
}

As powerful as Listing 2-10 is, it can be expanded. By simply adding a couple of parameters and wrapping your work in a PowerCLI script, you can make your one-off solution an enterprise-wide solution. In Listing 2-12, we expanded on our original example. This additional layer of abstraction enables some powerful use cases. For instance, if you loaded a number of hosts, you could then configure them all at once:

1..50 | ForEach-Object {
    Assert-VMHostConfiguration `
        -VMHostName ("vSphere{0:00}.vSphere.local" -f $_) `
        -User root `
        -password pa22word `
        -IPAddress 10.10.1.$_
}

Listing 2-12: Parameterized vSphere host configuration function

function Assert-VMHostConfiguration {
    <#  .SYNOPSIS
        Apply configuration to a specified host.

        .EXAMPLE
        Configure a host.
        Assert-VMHostConfiguration -VMHostName host3 -User root `
            -Password letmein -IPAddress $iSCSI_IP

        .PARAMETER VMHostName
        The name or IP of the ESXi host to configure.

        .PARAMETER User
        The username to connect to the ESXi host with.

        .PARAMETER Password
        ESXi password.

        .PARAMETER IPAddress
        The IP address to be assigned to the iSCSI vmknic.

        .Parameter Location
        The location in the vCenter inventory to add the
        ESXi host.

    #>
    Param(
        [String]$VMHostName
    ,   [String]$User
    ,   [String]$password
    ,   [String]$IPAddress
    ,   [Object]$Location = (Get-Datacenter | Select-Object -First 1)
    )

    # Add our host to vCenter, and immediately enable
    # lockdown mode!
    $VMhost = Add-VMHost -Name $VMHostName `
        -User $user `
        -Password $Password `
        -Location $Location `
        -Force

    Set-VMHostLockdown -VMHost $VMhost -Enable

    # Add iSCSI VMkernel vNIC
    $vSwitch = Get-VirtualSwitch -VMHost $VMHost `
        -Name 'vSwitch0'

    # we have to first create a portgroup to bind our vNIC to.
    $vPG = New-VirtualPortGroup -Name iSCSI `
        -VirtualSwitch $vSwitch `
        -VLanId 55

    # Create our new vNIC in the iSCSI PG we just created
    $vNIC = New-VMHostNetworkAdapter -VMHost $VMHost `
        -PortGroup iSCSI `
        -VirtualSwitch $vSwitch `
        -IP $IPAddress `
        -SubnetMask 255.255.255.0

    # Enable the software ISCSI adapter if not already enabled.
    $VMHostStorage = Get-VMHostStorage -VMHost $VMhost |
        Set-VMHostStorage -SoftwareIScsiEnabled $True

    #sleep while iSCSI starts up
    Start-Sleep -Seconds 30

    # By default vSphere will set the Target Node name to
    # iqn.1998-01.com.vmware:<HostName>-<random number> This
    # script will remove everything after the hostname, set Chap
    # auth, and add a send Target.
    #
    # Example iqn.1998-01.com.vmware:esx01-165435 becomes
    # iqn.1998-01.com.vmware:esx01
    #
    # Note that if your hostname has dashes in it, you'll
    # need to change the regex below.
    $pattern = "iqn.1998-01.com.vmware:w*"
    Get-VMHostHba -VMHost $VMHost -Type IScsi |
        Where-Object {$_.IScsiName -match $pattern} |
        Set-VMHostHba -IScsiName $Matches[0] |
        Set-VMHostHba -ChapName 'vmware' `
            -ChapPassword 'password' `
            -ChapType "Required" |
        New-IScsiHbaTarget -Address '192.168.1.1' -Port "3260" |
            Out-Null
    $VMhost
}

Working with Host Profiles

At this point, you have a fairly high level of automation in play. Let’s bring it to the next level by leveraging host profiles. Keep in mind that you must have the Enterprise Plus license level to take advantage of host profiles, but remember that you can use PowerCLI to apply all the settings manually.

Most settings within host profiles have three possible settings:

  • User Specified Setting Will Be Applied
  • Prompt User If No Default Is Provided
  • Use The Following When Applying

As shown in Figure 2-4, your selection within the host profile will determine how you script against them. If you select User Specified Setting Will Be Applied, you will always have to supply the setting. If you choose Prompt User If No Default Is Provided, you should test whether a value is necessary before providing one. Finally, if you choose to use a static or dynamic value—that is, a static IP or DHCP—you don’t have to provide a value. The interdependency mesh that is host profiles has led to a lot of confusion on the topic. We’ll go over several techniques to show how to handle each scenario before we circle back around and use host profiles in a vSphere host configuration script.

c02f004.tif

Figure 2-4: Host profile selection

Regardless of how your settings are applied, automating host profiles is a three-step process:

  1. Attach a profile.
  2. Apply the profile and test only for needed values.
  3. Apply the profile.

For example, to attach the host profile named PROD01 to a vSphere host named vSphere03, run the following command:

$HostProfile = Get-VMHostProfile -Name PROD01
$VMHost = Get-VMHost vSphere03*
Invoke-VMHostProfile -Entity $VMHost `
    -Profile $HostProfile `
    -AssociateOnly

At this point, the PROD01 host profile is attached to vSphere03. Now you need to test apply your profile against the host. If the profile has additional information that needs to be answered before the profile can be applied, the Invoke-VMHostProfile will return a hash table of settings. Therefore, after placing the host in maintenance mode you could capture the output of this action in a variable for use later:

$AdditionalConfiguration = Invoke-VMHostProfile `
    -Entity $VMHost `
    -ApplyOnly

In our case, it’s a hash table of IP settings:

$AdditionalConfiguration | Select-Object Name

Name
----
network.hostPortGroup["key-vim-profile-host-HostPortgroup↵
Profile-iSCSI"].ipConfig.IpAddressPolicy.address
network.hostPortGroup["key-vim-profile-host-HostPortgroup↵
Profile-vMotion"].ipConfig.IpAddressPolicy.subnetmask
network.hostPortGroup["key-vim-profile-host-HostPortgroup↵
Profile-vMotion"].ipConfig.IpAddressPolicy.address
network.hostPortGroup["key-vim-profile-host-HostPortgroup↵
Profile-iSCSI"].ipConfig.IpAddressPolicy.subnetmask

Before you can apply your profile, you must provide values for these settings. You can accomplish this by addressing each entry in the hash table and setting a simple string value:

$AdditionalConfiguration['network.hostPortGroup[↵
"key-vim-profile-host-HostPortgroupProfile-iSCSI"].ipConfig.↵
IpAddressPolicy.address'] = '10.10.10.1'
$AdditionalConfiguration['network.hostPortGroup[↵
"key-vim-profile-host-HostPortgroupProfile-iSCSI"].ipConfig.↵
IpAddressPolicy.subnetmask'] = '255.255.255.0'
$AdditionalConfiguration['network.hostPortGroup[↵
"key-vim-profile-host-HostPortgroupProfile-vMotion"].ipConfig.↵
IpAddressPolicy.address'] = '10.10.10.1'
$AdditionalConfiguration['network.hostPortGroup[↵
"key-vim-profile-host-HostPortgroupProfile-vMotion"].ipConfig.↵
IpAddressPolicy.subnetmask'] = '255.255.255.0'

Only the PowerCLI team knows why it chose to expose such long and unruly key names. Normally, PowerShell cuts off such long strings, so be sure to pipe to Select-Object to get the full key name. You can verify your variables by looking at your $AdditionalConfiguration variable once more:

$AdditionalConfiguration

Name                           Value
----                           -----
network.hostPortGroup["key-... 10.10.10.3
network.hostPortGroup["key-... 255.255.255.0
network.hostPortGroup["key-... 10.10.11.3
network.hostPortGroup["key-... 255.255.255.0

At this point, you are ready to apply the profile. To accomplish this, omit any optional switches and provide the variable parameter with your additional settings. We will take advantage of the PowerShell pipeline and drop our host in and out of Maintenance mode—all in one command:

Set-VMHost -VMHost $VMHost `
    -State 'Maintenance' |
    Invoke-VMHostProfile -Variable $AdditionalConfiguration |
    Set-VMHost -State 'Connected'

Once you’ve satisfied all the requirements, host profiles are quite easy to automate. The tricky part is determining what needs to be configured prior to applying the profile. Sadly, you can’t simply just apply everything all the time; PowerCLI will issue an error if you apply a setting the host profile didn’t expect. Therefore, to automate host profiles you’re forced to either write rather intelligent code or use simplified profiles. For example, Listing 2-13 would safely automate the following tasks:

  1. Associate the PROD01 host profile to vSphere03.
  2. If needed, apply these additional configuration items:
    • iSCSI vNIC IP: 10.10.10.40
    • iSCSI vNIC MASK: 255.255.255.0
    • vMotion vNIC IP: 10.10.11.40
    • vMotion vNIC MASK: 255.255.255.0
  3. Apply the profile.
  4. Test for profile compliance.

Listing 2-13: Applying a host profile to one vSphere host

# Get our target Profiles
$HostProfile = Get-VMHostProfile -Name 'PRO*'

# Get our target VMHost
$VMHost = Get-VMHost 192*

# Associate our host profile with the target host
Invoke-VMHostProfile -Entity $VMHost -Profile $HostProfile `
    -AssociateOnly | Out-Null

#test apply the host profile
$AdditionConfiguration = Apply-VMHostProfile -Entity $VMHost `
    -ApplyOnly

# process any required values filling in known values, and
# prompting for anything unexpected.
$var = @{}

switch ($AdditionConfiguration.GetEnumerator()) {
    {$_.Name -like '*iSCSI*.address' } {
        $var += @{$_.Name = '10.10.10.40'}
    }

    {$_.Name -like '*iSCSI*.subnetmask'} {
        $var += @{$_.Name = '255.255.255.0'}
    }

    {$_.Name -like '*vMotion*.address'} {
        $var += @{$_.Name = '10.10.11.40'}
    }

    {$_.Name -like '*vMotion*.subnetmask'} {
        $var += @{$_.Name = '255.255.255.0'}
    }

    default {
        $value=Read-Host "Please provide a value for $($_.Name)"
        $var += @{ $_.Name = $value}
    }
}

# 1. Place our host in maintenance mode
# 2. Apply our profile
# 3. Exit maintenance mode
# 4. Test for profile compliance
Set-VMHost -VMHost $VMHost -State 'Maintenance'|
    Invoke-VMHostProfile -Variable $var |
    Set-VMHost -State 'Connected'|
    Test-VMHostProfileCompliance

At this point we have fully automated applying host profiles. Let’s wrap everything you’ve learned thus far into a master configuration script. Listing 2-14 is a complete vSphere host provisioning script that will take a new host and perform the following configuration tasks:

  1. Add the host to vCenter Server.
  2. Lock down the ESXi host.
  3. Add the host to the designated cluster.
  4. Apply that cluster’s host profile.
  5. Configure iSCSI storage:
    • Enable the Software iSCSI HBA.
    • Rename the host iSCSI IQN.
    • Configure CHAP authentication.
    • Add the iSCSI target.
    • Rescan all HBA for storage.

Listing 2-14: Complete vSphere host configuration function

function Invoke-VMHostConfiguration {
    <#  .SYNOPSIS
        Apply expanded configuration to a specified host.

        .EXAMPLE
        Configure a host.
        Invoke-VMHostConfiguration -IPAddress $ip -Cluster "Cluster1" `
            -User root -Password letmein

        .PARAMETER IPAddress
        The IP of the ESXi host to configure.

        .PARAMETER Cluster
        The name of the cluster which the host will join.

        .PARAMETER User
        ESXi username.

        .PARAMETER Password
        ESXi password.

    #>
    [CmdletBinding()]
    Param(
        [Parameter(
            Mandatory=$true,
            ValueFromPipelineByPropertyname=$true
        )]
        [String]
        $IPAddress
        ,

        [Parameter(
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$True
        )]
        [String]
        $Cluster
        ,

        [Parameter(
            ValueFromPipelineByPropertyName=$True
        )]
        [String]
        $User = 'root'
        ,

        [Parameter(
            ValueFromPipelineByPropertyName=$True
        )]
        [String]
        $password
    )
    Process {
    # while static enough to not be parameterized we'll still
    # define our advanced iSCSI configuration up front thereby
    # simplifying any future modifications.
    $ChapName = 'vmware'
    $ChapPassword = 'password'
    $ChapType = 'Required'
    $IScsiHbaTargetAddress = '10.10.11.200','10.10.11.201'
    $IScsiHbaTargetPort = '3260'

    # we'll use the last octet of the IPAddress as the ID for
    # the host.
    $ESXID = $IPaddress.Split(".")[3]

    # Get the actual cluster object for our targeted cluster.
    $ClusterImpl = Get-Cluster -Name $Cluster

    # Get the parent folder our cluster resides in.
    $Folder = Get-VIObjectByVIView $ClusterImpl.ExtensionData.Parent

    Write-Verbose "Adding $($IPAddress) to vCenter"

    # Add our host to vCenter, and immediately enable
    # lockdown mode!
    $VMHost = Add-VMHost -Name $IPAddress `
        -User $user `
        -Password $Password `
        -Location $Folder `
        -Force `
        -ErrorAction 'STOP'

    $VMHost | Set-VMHostLockdown -Enable

    # Enter Maintenance mode
    $VMHost = Set-VMHost -State 'Maintenance' -VMHost $VMHost |
        Move-VMHost -Destination $Cluster

    # Get the Host profile attached to that cluster
    $Hostprofile = Get-VMHostProfile -Entity $Cluster

    # attach profile to our new host
    Apply-VMHostProfile -Entity $VMHost `
        -Profile $HostProfile `
        -AssociateOnly `
        -Confirm:$false |
            Out-Null

    # Apply our host profile to gather any required values
    $AdditionConfiguration = `
        Apply-VMHostProfile -Entity $VMHost `
        -Profile $HostProfile `
        -ApplyOnly `
        -Confirm:$false

    # If we have a hashtable then there are additional config
    # items that need to be defined.  Loop through and attempt
    # to fill them in, prompting if we come across something
    # we're not prepared for.

    if ($AdditionConfiguration.GetType().Name -eq 'Hashtable') {
        #Create a new hashtable to hold our information
        $var = @{}

        # Loop through the collection
        switch ($AdditionConfiguration.GetEnumerator()) {
            {$_.Name -like '*iSCSI*.address' } {
                $var +=@{$_.Name = $('10.10.10.{0}' -f $ESXID)}
            }

            {$_.Name -like '*iSCSI*.subnetmask'} {
                $var += @{$_.Name = '255.255.255.0'}
            }

            {$_.Name -like '*vMotion*.address'} {
                $var +=@{$_.Name = $('10.10.11.{0}' -f $ESXID)}
            }

            {$_.Name -like '*vMotion*.subnetmask'} {
                $var += @{$_.Name = '255.255.255.0'}
            }

            default {
                $value = Read-Host `
                    "Please provide a value for $($_.Name)"
                $var += @{ $_.Name = $value}
            }
        }

        # Apply our profile with the additional config info
        $VMHost = Apply-VMHostProfile -Entity $VMHost `
            -Confirm:$false `
            -Variable $var
    } else {
        # Apply our profile.
        $VMHost = Apply-VMHostProfile -Entity $VMHost `
            -Confirm:$false
    }

    # update vCenter with our new Profile compliance status
    Test-VMHostProfileCompliance -VMHost $VMHost | Out-Null

    # Enable the software ISCSI adapter if not already enabled.
    $VMHostStorage = Get-VMHostStorage -VMHost $VMhost |
        Set-VMHostStorage -SoftwareIScsiEnabled $True

    # sleep while iSCSI starts up
    Start-Sleep -Seconds 30

    # By default vSphere will set the Target Node name to
    # iqn.1998-01.com.vmware:<HostName>-<MAC Address> This
    # script will remove everything after the hostname, set Chap
    # auth, and add a send target.
    #
    # Note that if your hostname has dashes in it, you'll
    # need to change the regex below.
    $pattern = "iqn.1998-01.com.vmware:w*"

    $HBA = Get-VMHostHba -VMHost $VMHost -Type 'IScsi'|
        Where-Object {$_.IScsiName -match $pattern}

    if ($HBA.IScsiName -ne $Matches[0]) {
        $HBA = Set-VMHostHba -IScsiHba $HBA `
            -IScsiName $Matches[0]
    }

    Set-VMHostHba -IScsiHba $HBA `
        -ChapName $ChapName `
        -ChapPassword $ChapPassword `
        -ChapType $ChapType

    $IScsiHbaTargetAddress | Foreach-Object {
        $HBA | New-IScsiHbaTarget -Address $_ `
            -Port $IScsiHbaTargetPort | Out-Null
    }

    $VMhost

    }
}

Working Without Access to Host Profiles

That’s all well and good, but what if you don’t have access to host profiles? Well, you’re going to need a bigger script, most of which will be filled with pieces of code from all over this book. You’ll have a little storage, network, authentication, licensing, and so on. But wanting to be as complete as possible, we’ll highlight a few additional cmdlets that you’ll find useful.

  1. NTP When you’re configuring NTP, you should know that the Add-VmHostNtpServer cmdlet will do much more than add an NTP server. It can also enable and start the NTP service in case it is stopped:
    Add-VmHostNtpServer -NtpServer time.nist.gov `
        -VMHost vSphere02.domain.local
  2. Syslog Syslog can be configured only on classic ESX/vSphere. If you’re running any of the console’s hypervisors (ESXi), use the Set-VMHostSysLogServer cmdlet to set up Syslog on vSphere:
    Set-VMHostSysLogServer -SysLogServer "log01:507" `
        -VMHost vSphere02.domain.local
  3. Root Password You can change the root password by using the Set-VMHostAccount cmdlet. Unfortunately, you will have to connect directly to the host to do so.
    Connect-VIServer -Server vSphere02.getadmin.local `
        -User root `
        -Password "" 
    Set-VMHostAccount -UserAccount root -Password PowerShell!
  4. SNMP SNMP has been around for ages and is still a critical tool for most monitoring tools. Unfortunately, this is also a cmdlet that requires that you be connected directly to the vSphere host.

    Enabling SNMP

    Get-VMHostSnmp | Set-VMHostSnmp -Enabled $true

    Configuring Communities

    Set-VMHostSnmp -ReadOnlyCommunity $communityName `
        -HostSnmp (Get-VMHostSnmp)

    Adding a Target

    Set-VMHostSnmp -TargetHost $sendTrapsHere `
        -TargetCommunity $sendCommunity `
        -AddTarget`
        -HostSnmp (Get-VMHostSnmp)
  5. Advanced Options To optimize your infrastructure, you will eventually have to set an option or two—a task easily performed via the Set-AdvancedSetting cmdlet. To enable vMotion, you run the following:
    Get-AdvancedSetting -Entity (Get-VMHost vSphere02) `
        -Name Migrate.Enabled |
        Set-AdvancedSetting -Value 1
    
    1. You could configure a set of options all at once by using a hash table to loop through the settings and apply the Set-AdvancedSetting cmdlet. For instance, to tune vSphere to run NFS on a NetApp FAS system, you run the following:
      @{
          'NFS.MaxVolumes' = 256
          'Net.TcpipHeapMax' = 512
          'Net.TcpipHeapSize' = 32
          'NFS.HeartbeatFrequency' = 12
          'NFS.HeartbeatTimeout' = 5
          'NFS.HeartbeatMaxFailures' = 10
          'NFS.MaxQueueDepth' = 64
      }.GetEnumerator() | Foreach-Object {
          Get-AdvancedSetting -Entity (Get-VMHost vSphere02) `
              -Name $_.Name |
          Set-AdvancedSetting -Value $_.Value
      }

Using the cmdlets we’ve highlighted, and the automation workflow from earlier in the chapter, you can create a zero-touch installation for any environment. Now that you have both a zero-touch vSphere installation via Kickstart and a fully automated host configuration script, it’s time to glue these together and deliver on the promise of a fully automated host provisioning life cycle. To accomplish this task, we adapted a technique originally documented by Lance Berc. The general workflow looks like this:

  1. Kickstart your vSphere host, configuring at a minimum the management network.
  2. As part of the first boot process, execute a small Python script that will “touch” a midwife host.
  3. The midwife will be listening with a simple PowerCLI script and will execute our host configuration script when notified.

The PowerCLI script features a custom PowerCLI function, shown in Listing 2-15.

Listing 2-15: The Trace-Port function

function Trace-Port {
    <#  .SYNOPSIS
        This function will listen on a specified port for a
        connection, after one is created, it will return an object
        containing the hostname and IP address of the host
        which connected.

        .EXAMPLE
        Listen on port 3333, on the loopback IP
        Trace-Port -IPAddress 127.0.0.1 -Port 3333

        .PARAMETER IPAddress
        The IP of the host to listen on.

        .PARAMETER Port
        The port number to listen on.

        .OUTPUTS
        [System.Management.Automation.PSCustomObject]

    #>
    [CmdletBinding()]
    Param (
        [Parameter(
            Mandatory=$true,
            Position=0,
            HelpMessage="Address to listen for the connection"
        )]
        [string]
        $IPAddress
        ,

        [int]
        $Port=3333
    )
    End {
        [byte[]]$B = 0..255 | Foreach-Object {0}

        $ip = [Net.IPAddress]::Parse($IPAddress)
        $listener = New-Object System.Net.Sockets.TcpListener(
            $ip, $Port
        )

        $listener.Start()
        Write-Debug "Waiting for a connection on port $port..."

        $client = $listener.AcceptTcpClient()
        $RemoteEndPoint = $client.Client.RemoteEndPoint
        $stream = $client.GetStream()

        $raw = while (($i = $stream.Read($B, 0, $B.Length)) -ne 0) {
            $B[0..($i-1)] | Foreach-Object { $_ }
        }

        $client.Close()
        $listener.Stop()

        Write-Debug "Connection closed."

        New-Object PSObject -Property @{
            'Source' = $RemoteEndPoint.Address.ToString().Split(':')[0]
            'Data'   = [string]::Join("" ,[char[]]$raw)
        }
    }
}

Now that you have all the tools in place, it’s time to put it all together. First, as shown in Listing 2-16, place a simple Python script that will reach out and connect to the midwife configuration host. The IP address in the connect method should be the IP address of your midwife server.

Listing 2-16: FirstBoot for wholly automated system installation

%firstboot --interpreter=busybox
esxcli network firewall set --enabled false

cat > /tmp/findme.py << __EOF__
import socket

s = socket.socket()
s.connect(('192.168.145.1',3333))
s.send(socket.gethostname())
s.close()
__EOF__

chmod 755 /tmp/findme.py
python /tmp/findme.py

esxcli network firewall set --enabled true

That’s all there is to it. The Python simply reaches out to the configured host on the designated port and sends its hostname. Now, run the following on your midwife server and Kickstart your host. In about 20 minutes, you’ll have a new host ready to host virtual machines!

Trace-Port -IPAddress 192.168.145.1 -Port 3333 |
    Foreach-Object {
        Invoke-VMHostConfiguration -IPAddress $_.Source `
            -Cluster prod01 `
            -User root `
            -password pa22word
    }

Automating the installation of vSphere hosts can be a complex task, but at the core, it is much like any automation task. Take it step by step, identify the things that need to be done, and leverage the tools at your disposal. For smaller environments, expediting the install process may not be needed, unless you are frequently reloading your servers. In larger environments, it may be critical to automate every aspect of administration. When done manually, configuring a vSphere host can take over an hour; reducing that to just a couple of minutes of administrator time makes great justification for a promotion!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset