Creating a configuration script to set all properties uniformly
In this section, you are going to cover all of the cmdlets that have been covered in this chapter by bringing them together into a single script. This script will allow us to take an array of ESXi hosts identified by either their hostname or IP address and to run the full scripted configuration against them.
In many ways, this PowerCLI script will function much like a Host Profile in vSphere. Host Profiles are a configuration definition that can be created from an existing, configured host and applied on hosts to establish a desired configuration state. If hosts deviate from the configuration, the profile might be reapplied to remediate any undesired changes.
Unfortunately, Host Profiles are only available to customers with Enterprise Plus licensing. However, this PowerCLI solution will work for any vSphere customer with Essentials, Essentials Plus, Standard, or Enterprise licensing.
Getting ready
For this last recipe of the chapter, you'll most likely want to open something such as PowerShell ISE. PowerShell ISE provides you with additional tools to edit larger scripts, color code the cmdlets, and ensure that there are no syntax errors. Alternatively, you might want a text editing tool such as NotePad, NoteTab Light, Sublime Text, or NotePad++.
How to do it…
- First things first, let's begin with pseudocode/documentation of what you want to accomplish. In between each of these sections, you will insert the code you have previously developed individually and put them into a full file:
# Script to mass configure ESXi hosts # Step 1 - Store credentials for ESXi hosts # Step 2 – Set a list of target ESXi hosts and IP settings # Step 3 – Write a ForEach loop to iterate through hosts # Step 4 – Connect to ESXi host # Step 5 – Obtain a VMHost object to use for configuration # Step 6 – Join the ESXi system to Active Directory # Step 7 – Enable services on the ESXi host & set firewall # Step 8 – Configure the network settings # Step 9 – Configure NFS & iSCSI settings # Step 10 - Join hosts to vCenter # Step 11 - Rescan for storage changes # Step 12 – Configure persistent syslog storage
- Since you want this script to do as much without any manual intervention, you will want to try and eliminate as many prompts as possible. Since you will be connecting to and executing commands on multiple ESXi hosts, you would normally get prompted to login each time you connect to a host. To avoid this, you can store the credentials in a variable and pass them to each
connect-viserver
cmdlet.# Step 1 - Store credentials for ESXi hosts $esxiCreds = Get-Credential
Note
When you first covered connecting to ESXi servers from PowerCLI, you experienced the login box for the host. The
Get-Credentials
cmdlet causes the same action but returns a credentials object that can be reused. For now, you'll proceed with the stored credentials and you will use them in a later step. - You're going to use an array of hostnames to connect to individual ESXi hosts for configuration. To create the array, you set a variable and store a comma separated list of addresses to connect to. The addresses can either be hostnames or IP addresses. For this example, you will use IP addresses, but they can easily be fully qualified domain names:
# Step 2 - Set a list of target ESXi hosts and IP settings $esxiTargets = "192.168.0.241","192.168.0.242", "192.168.0.243", "192.168.0.244"
- For the network configuration settings, you will need to set up some additional settings. Since each host has three additional vmkernel ports configured, you need to build a different address for each of these to be used in Step 8. To allow this, you will create three additional variables that contain the first three octets of the network for each vmkernel port:
$vMotionNetwork = "192.168.50." $storageNetwork = "192.168.100." $ftlogNetwork = "192.168.200."
- The next step is to go back and pull in all of the code you had previously written in one form or another. For this, you will reuse the
ForEach
loop to execute the cmdlets on multiple ESXi hosts:# Step 3 - Write a ForEach loop to iterate through hosts ForEach ($hostname in $esxiTargets) {
- The curly brace marks the beginning of the
ForEach
loop. You will close the loop with a right curly brace later in the script. Inside the loop, you're going to include Steps 4 – 9 from the outline. - For the next step, you're going to use our stored credentials to connect to an ESXi host. Immediately after this, you will store our VMHost object for use throughout the rest of the loop:
# Step 4 - Connect to ESXi host $connectedHost = connect-viserver $hostname -Credential $esxiCreds # Step 5 – Obtain a VMHost object to use for configuration $esxihost = Get-VMHost $hostname
- For the next several steps, you're just going to pull code you have already developed. Since each step was covered in depth, you will just bring over the code:
# Step 6 – Join the ESXi system to Active Directory $esxihost | Get-VMHostAuthentication | Set-VMHostAuthentication -JoinDomain -Domain domain.local -user username -password ***** -Confirm:$false # Step 7 – Enable services on the ESXi host & set firewall $esxihost | Get-VMHostService | where { $_.key -eq "TSM-SSH" } | Set-VMHostService -Policy "On" -Confirm:$false $esxihost | Get-VMHostService | where { $_.key -eq "TSM-SSH" } | Start-VMHostService -Confirm:$false # Step 8 – Configure the network settings $esxihost | Get-VirtualPortGroup -Name "VM Network" | Remove-VirtualPortGroup –Confirm:$false
- For the network settings, you will need three additional IP addresses for the vMotion, Storage, and FT Logging vmkernel ports. You will compute these addresses using the last octet of the service console IP. To do this, you will first retrieve the IP address of the host:
$esxihost_ipaddress = $esxihost | Get-VMHostNetworkAdapter -name vmk0
- Next, you will split the string based on the period between octets, then take the last octet of the IP address and store it as a variable. The IP is in a property called
IP
. To split that IP into an array, you will use theSplit()
method, which is a built-in PowerShell method that transforms a string into an array by separating characters with the character passed into the method.For instance, you want to separate the string at the periods of the IP address, so you pass
"."
into theSplit()
method. Since theSplit()
method turns it into an array, you can then reference the element you want to return – the fourth element. However, remember arrays begin count at 0, so you will return element 3 using square brackets.$lastOctet = $esxihost_ipaddress.IP.Split(".")[3]
Note
Because data is stored in objects, objects have both properties and methods. Methods perform operations on the data of the object and properties contain the data of the object. In subsequent recipes throughout this book, you will look at and use other methods to gain more experience using built-in PowerShell functionality to manipulate data stored in objects.
- The last step to build the address for this host in the
ForEach
loop is to concatenate the final octet with the network strings to build a full IP address:$vmotionIP = $vMotionNetwork + $lastOctet $storageIP = $storageNetwork + $lastOctet $ftlogIP = $ftlogNetwork + $lastOctet
- Now that your unique IP addresses are created on the three additional networks, you can use them with the cmdlets you wrote in the Setting network configuration recipe.
$esxihost | New-VMHostNetworkAdapter -PortGroup "VMotion Network" -VirtualSwitch vSwitch0 -IP $vmotionIP -SubnetMask 255.255.255.0 -VMotionEnabled $true $esxihost | Get-VirtualPortGroup -Name "VMotion Network" | Set-VirtualPortGroup –VlanID 50 # Create new virtual switch for Storage and FT Logging $esxihost | New-VirtualSwitch -Name vSwitch1 -Nic vmnic2,vmnic3 # Create vmkernel ports for Storage and FT Logging $esxihost | New-VMHostNetworkAdapter -PortGroup "Storage Network" -VirtualSwitch vSwitch1 -IP $storageIP -SubnetMask 255.255.255.0 -VsanTrafficEnabled $true $esxihost | Get-VirtualPortGroup -Name "Storage Network" | Set-VirtualPortGroup –VlanID 100 $esxihost | New-VMHostNetworkAdapter -PortGroup "FT Logging Network" -VirtualSwitch vSwitch1 -IP $ftlogIP -SubnetMask 255.255.255.0 -FaultToleranceLoggingEnabled $true $esxihost | Get-VirtualPortGroup -Name "FT Logging Network" | Set-VirtualPortGroup –VlanID 200 # Create new Virtual Switch for Virtual Machines $esxihost | New-VirtualSwitch -Name vSwitch2 -Nic vmnic4,vmnic5 # Create Port Groups for Virtual Machines New-VirtualPortGroup -Name "Infrastructure Network" -VirtualSwitch vSwitch2 -VLanId 1 -Server $connectedhost New-VirtualPortGroup -Name "Application Network" -VirtualSwitch vSwitch2 -VLanId 2 -Server $connectedhost # Step 9 – Configure NFS & iSCSI settings # Connect NFS datastore $esxihost | New-Datastore -Nfs -Name DataStoreName -Path /data1/export -NfsHost nfsserver.domain.local # Configure iSCSI Settings $esxihost | Get-VMHostStorage | Set-VMHostStorage -SoftwareIScsiEnabled $true$iSCSIhba = $esxihost | Get-VMHostHba -Type iScsi New-IScsiHbaTarget -IScsiHba $iSCSIhba -Address $target -ChapType Required -ChapName vSphere -ChapPassword Password1 $esxcli = Get-ESXCLI -VMHost $esxihost $esxcli.iscsi.networkportal.add($iscsihba, $true,"vmk2")
- The final part of the ESXi host configuration is closing the
ForEach
loop and then disconnecting from this host so that you can connect to the next host:Disconnect-VIServer -Server $connectedHost -Confirm:$false }
At this point in the initial configuration, you would want to format your datastores on iSCSI or Fibre Channel arrays, but this is not really a repeatable set of steps. I would suggest one of the two things—either configure the datastore manually from PowerCLI or configure it from the GUI and then come back and run the remainder of the script. Since the focus of this example is to make a repeatable configuration script, the datastore formatting doesn't fit since it is a command used just one time .
- The next step is to take our hosts and connect them to vCenter. The easiest way to do this is to connect to vCenter and then use
Add-VMHost
to add them into inventory. While in the sameForEach
loop to accomplish this, you can set central syslog and rescan the hosts for all storage changes:$vcenter = connect-viserver vcentersrv.domain.local $datacenter = Get-Datacenter "Primary"
Note
For the purpose of this script, you are going to assume that vCenter already has a datacenter created and named "Primary." You will use this location to place the ESXi host into vCenter.
- Next, you will run through an additional
ForEach
loop to add the hosts and set their settings in vCenter:ForEach ($hostname in $esxTarget) {
- Now, you are ready to add the host into vCenter from the Joining an ESXi host to vCenter recipe:
# Step 10 - Join hosts to vCenter Add-VMHost -Server $vcenter -Name $hostname l -Location $datacenter -Credential $esxiCreds
- After adding the host to vCenter, you want to store a
VMHost
object pointing to the host to use with later cmdlets in this loop:$esxihost = Get-VMHost $hostname
- For the next few steps, you will pull the host settings related to rescanning for datastores and setting the syslog settings:
# Step 11 - Rescan for storage changes $esxihost | Get-VMHostStorage -RescanAllHBA -RescanVmfs # Step 12 – Configure persistent syslog storage $esxihost | Get-AdvancedSetting | Where {$_.Name -like "Syslog.global.logDirUnique"} | Set-AdvancedSetting -value $true -Confirm:$false $esxhost | Get-AdvancedSetting | Where {$_.Name -like "logDir"} | Set-AdvancedSetting -value "[iSCSIDatastore1] syslog" -Confirm:$false
- Finally, you will close the loop with a right curly brace.
}
Note
With connect-viserver
, you might have to log in a second time in the script with different credentials to vCenter versus individual hosts. Afterwards, the hosts should be populated into vCenter.
Finally, your settings and desired state should be fully transferred to the ESXi host by the script.
How it works…
In this example, you wrap up all of the code you have developed throughout the chapter. You bring together the pieces of code that achieve specific tasks into a fully scripted configuration that you can apply toward a number of ESXi hosts. The script gives us repeatability, so when you need to extend the cluster with a new ESXi, or when you rebuild the host because you've replaced or upgraded the hardware, you can run this script against it and be back to the same working condition as before replacement.
The basis of the script is a ForEach
loop. Because you define the ESXi hosts in an array, you can connect to each of them and run all of the commands and then move the next entry in the array. The script also suppresses confirmation dialogs so that it can continue to issue cmdlets against the host. You also stored the login credentials, which means that you only have to log in once and the script will use the same credentials to connect and configure all of the hosts in the defined array.
See also
- VMware vSphere Host Profiles at http://www.vmware.com/products/vsphere/features/host-profiles