That… Could Be A Problem…

2May/141

PowerCLI – One Liner – Finding Duplicate VMkernel IPs

Ever had issues with a host randomly disconnecting? vMotions randomly failing? iSCSI paths dropping? If so, there's a chance you're having issues with a duplicate IP on one of your VMkernel ports.

There's no real way to display such information through the GUI, so I crafted a quick PowerCLI one-liner to accomplish this task:

Get-VMHost -ErrorAction SilentlyContinue | Get-VMHostNetworkAdapter -VMKernel | select VMHost,DeviceName,IP | Group-Object IP | where {$_.Count -gt 1} | %{$_.Group}

An example of what the output will look like if it finds any duplicate IPs:
PowerCLI - Duplicate VMkernel IPs

Note: this was a script that worked in my environment. There is no warranty or support with this script, please use at your own risk.

1May/140

PowerCLI – Get-View View Types

Unfortunately, I don't make use of the Get-View .NET cmdlet as often as I should. It's a little more complicated than the rest of the PowerCLI cmdlets and a little harder to memorize but the speed is well worth the time and effort. Following up on that, this post is more for selfish reasons since I can never remember the proper ViewTypes. If you put in the wrong one the proper names all pop up but limiting the amount of red on my powershell screens is always a bonus.

PowerCLI Get-View View Types:

  • ComputeResource
  • ClusterComputeResource
  • Datacenter
  • Datastore
  • Network
  • DistributedVirtualPortgroup
  • DistributedVirtualSwitch
  • Folder
  • HostSystem
  • ResourcePool
  • VirtualApp
  • VirtualMachine
  • VmwareDistributedVirtualSwitch
29Oct/130

PowerCLI – Reset NTP settings on VMHosts per Cluster

As daylight savings time is almost upon us, there are always questions revolving around what hosts use what NTP sources for time synchronization. To address this issue, I created a script to go through and remove the current NTP sources, add the desired NTP sources and then restart the NTP service on all of the hosts in the environment. However, to be safe, the preference was that it wasn't done all at the same time. To achieve this, I broke it down and applied it to hosts one by one in a specified cluster.

When running the script, it will ask for the cluster name and four NTP servers so you don't have to modify the code unless you want to add more or less NTP servers.


#Reset NTP settings on VM Hosts per Cluster

$InputCluster = Read-Host "Cluster Name:"
$InputNTP1 = Read-Host "First NTP Server:"
$InputNTP2 = Read-Host "Second NTP Server:"
$InputNTP3 = Read-Host "Third NTP Server:"
$InputNTP4 = Read-Host "Fourth NTP Server:"

#Select Cluster to change NTP Settings
$Cluster = Get-Cluster $InputCluster

#NTP servers to be changed to
$ntp1 = $InputNTP1
$ntp2 = $InputNTP2
$ntp3 = $InputNTP3
$ntp4 = $InputNTP4

#Grabbing VMHosts for desired Cluster
$allVMhost = $Cluster | Get-VMHost | sort Name

#Reseting NTP servers one by one
foreach ($vmhost in $allVMhost){

#Remove existing NTP servers
Write-Host "Removing all NTP Servers from $vmhost"
$allNTPList = Get-VMHostNtpServer -VMHost $vmhost
Remove-VMHostNtpServer -VMHost $vmhost -NtpServer $allNTPList -Confirm:$false | out-null
Write-Host "All NTP Servers from $vmhost have been removed"
Write-Host ""

#Setting NTP servers
Write-Host "Adding NTP servers to $vmhost"
Add-VmHostNtpServer -NtpServer $ntp1,$ntp2,$ntp3,$ntp4 -VMHost $vmhost -Confirm:$false | out-null
Write-Host "The following NTP servers have been added to $vmhost : $ntp1, $ntp2, $ntp3, $ntp4"
Write-Host ""

#Checking NTP Service on the ESXi host
$ntp = Get-VMHostService -vmhost $vmhost| ? {$_.Key -eq 'ntpd'}
Set-VMHostService $ntp -Policy on | out-null

if ($ntp.Running ){
Restart-VMHostService $ntp -confirm:$false
Write-Host "$ntp Service on $vmhost was On and was restarted"
}
Else{
Start-VMHostService $ntp -confirm:$false
Write-Host "$ntp Service on $vmhost was Off and has been started"
}

Write-Host ""

}

Click here to download a text file containing the script.

Note: this was a script that worked in my environment. There is no warranty or support with this script, please use at your own risk.

28Oct/130

PowerCLI – One-Liner – Check All VMHosts’ Time

It's everyone's favorite time of year, daylight savings time. If your NTP solution is solid, there's no worries and you've never had to think twice about it. If you're like everyone else, you at least want to run a couple scripts to verify and validate everything is looking good.

A little bit of background, the environment I was running this report on had 100+ hosts.

An easy one-liner:
Get-VMHost | sort Name | select Name,@{Name="Current VMHost Time";Expression={(Get-View $_.ExtensionData.ConfigManager.DateTimeSystem).QueryDateTime()}}

Depending on the size of your environment, this could take 20 seconds or an hour. In my case, it took 14 minutes. However, due to the time it took to run, quite a few hosts were reporting different times. A discrepancy of 14 minutes either way meant that the hosts were all just about in sync. If you're only worried about time zone issues, a 14 minute discrepancy is acceptable.

Example based upon the environment I was working in:
PowerCLI C:\ > Get-Date -Format g; Get-VMHost | sort Name | select Name,@{Name="Current VMHost Time";Expression={(Get-View $_.ExtensionData.ConfigManager.DateTimeSystem).QueryDateTime()}}; Get-Date -Format g

10/9/2013 10:19 AM
Name Current VMHost Time
---- -------------------

10/9/2013 10:33 AM

At this point you may be thinking, there has to be a faster way to do this. You're right, there is. To do so, you have to leave the comfort of the PowerCLI cmdlets behind and make a swap over to the .NET view objects cmdlets. In this case, Get-View will be used.

Good news, it is still another one-liner:
Get-View -ViewType HostSystem -Property Name,ConfigManager.DateTimeSystem | sort Name | select Name,@{Name="Current VMHost Time";Expression={(Get-View $_.ConfigManager.DateTimeSystem).QueryDateTime()}}

As you can see, there's a bit of a difference between the one-liners and there will be a bit of a learning curve as well. The time savings will be worth it though. To prove it, this version only took 2 minutes to run. That's a 12 minute savings!

Example based upon the environment I was working in:
PowerCLI C:\ > Get-Date -Format g; Get-View -ViewType HostSystem -Property Name,ConfigManager.DateTimeSystem | sort Name | select Name,@{Name="Current VMHost Time";Expression={(Get-View $_.ConfigManager.DateTimeSystem).QueryDateTime()}}; Get-Date -Format g

10/9/2013 10:35 AM

Name Current VMHost Time
---- -------------------

10/9/2013 10:37 AM

Note: this was a script that worked in my environment. There is no warranty or support with this script, please use at your own risk.

24May/131

PowerCLI – Copying PortGroups from a Standard vSwitch to a Distributed vSwitch

Ran out of ports on a Standard vSwitch and could not reboot the host. Sounds like a good time to implement a Distributed vSwitch and copy the PortGroups over.

When you run the script, it will ask for the desired ESXi host name, desired Standard vSwitch name, and the desired Distributed vSwitch name so you don't have to modify the code.


#Take port groups from a specified vSwitch on a specified host and create all the same port groups on a specified Distributed vSwitch

$InputHost = Read-Host "Host Name"
$InputvSwitch = Read-Host "vSwitch Name"
$InputDvS = Read-Host "Distributed vSwitch Name"

$vmhost = Get-VMHost $InputHost
$vss = Get-VirtualSwitch -Name $InputvSwitch
$vssNumPorts = $vss.NumPorts
$standardpg = $vmhost | $vss | Get-VirtualPortGroup
$dvs = Get-VDSwitch $InputDvS

foreach ($i in $standardpg) {

$pvgname = $i.name.ToString()
$pvg = "dv-" + $pvgname
$vlan = $i.VLANID

#create a Static DvS PG with the same VLAN, number of ports and add a "dv-" to the name
Get-VDSwitch -Name $dvs | New-VDPortGroup -Name $pvg -VLanId $vlan -PortBinding "Static" -NumPorts $vssNumPorts

}

Click here to download a text file containing the script.

Note: this was a script that worked in my environment. There is no warranty or support with this script, please use at your own risk.

23May/130

PowerCLI – Rescan HBAs for a Cluster on a Host by Host Basis

After having some bad luck with rescanning HBAs for entire clusters or datacenters all at the same time (Cliff's Notes: the LUNs ended up looking like array based snapshots and therefore unusable), it was decided that any rescans should be done on an individual host basis. Below is the script I created to achieve this goal.

When you run the script, it will ask for the Cluster name so you don't have to modify the code.


#Rescan HBAs for a cluster on a host by host basis

$InputCluster = Read-Host "Cluster Name"

$vmhosts = get-cluster $InputCluster | get-vmhost

foreach ($i in $vmhosts) {

Write-Host "Starting rescan of all HBAs on $i"
$i | Get-VMHostStorage -RescanAllHba | Out-Null
Write-Host "Rescan of all HBAs on $i is complete"
Write-Host ""

}

Click here to download a text file containing the script.

Note: this was a script that worked in my environment. There is no warranty or support with this script, please use at your own risk.

22May/130

PowerCLI – Analyze a Cluster to Move VMs to a Resource Pool

After someone deployed a bunch of VMs, we let them know about the Resource Pool they were supposed to be deployed to. Oops. To correct this, and to avoid a couple hours of dragging and dropping VMs into a resource pool, I was able to create a script that detects if a VM is outside of a Resource Pool and then move it to the specified Resource Pool.

When you run the script, it will ask for the Cluster name and the Resource Pool name so you don't have to modify the code.


#Analyze the Clusters and check for systems outside of Resource Pools

$InputCluster = Read-Host "Cluster Name"
$InputRP = Read-Host "Resource Pool Name"

#Cluster which will be analyzed
$cluster = Get-Cluster $InputCluster

#Resource Pool where VMs should be moved
$rp = Get-ResourcePool $InputRP

#Detection of VMs not in Resource Pools
$norp = Get-Cluster $cluster | Get-VM | where {$_.ResourcePool.Name -eq "Resources"}

foreach ($i in $norp) {

Write-Host "Moving $i to Resource Pool $rp"
Get-VM $i -Location $cluster | Move-VM -Destination $rp | Out-Null
Write-Host "Move complete"
Write-Host ""

}

Click here to download a text file containing the script.

Note: this was a script that worked in my environment. There is no warranty or support with this script, please use at your own risk.

23Aug/112

Configuring a Multipathing iSCSI Network with PowerCLI

I've been playing in the development hosts quite a bit lately which occasionally leave me having to reset the system back to defaults and it's no fun to go back through and setup Multipathing for 4 connections everytime. So why not setup a PowerCLI script to do it for me!

Let me forewarn, I'm an intermediate at best and still getting used to PowerShell and PowerCLI. So far so good though.

Let me start by walking through what I have set so far. It's a script for a single host with 4 NICs on an iSCSI network, using Jumbo Frames, and attaching to 5 iSCSI targets. I left in the commands for vLAN tags and MTU options if you need a vLAN tag or don't like Jumbo Frames.
Another note: I do not actually change the paths to Round Robin in this script, as I use the EqualLogic MEM to take care of the multipathing for me.

Feel free to download it here in a text format (change extension from txt to ps1) and modify it as necessary: Download Link Here

#==========================================================================
#
# NAME: VMware Multipathing Script
#
# AUTHOR: Kyle Ruddy
# DATE : 8/22/2011
#
# COMMENT: Works on 4 NIC multipathing setups
#==========================================================================
#Global Variables
$HostName = '192.168.10.5'

#NICs assigned to be assigned to the iSCSI switch
$FirstNic = 'vmnic0'
$SecondNic = 'vmnic1'
$ThirdNic = 'vmnic2'
$FourNic = 'vmnic3'

#vSwitch Name & MTU Setting
$SwitchName = 'iSCSI Switch'
$mtu = '9000'

#Virtual Port Group Names
$vPG1 = 'iSCSI1'
$vPG2 = 'iSCSI2'
$vPG3 = 'iSCSI3'
$vPG4 = 'iSCSI4'

#VLAN ID - 0 = none, 4095 = all
$vlanID = '0'

#vKernel Numbers
$vmk1number = 'vmk1'
$vmk2number = 'vmk2'
$vmk3number = 'vmk3'
$vmk4number = 'vmk4'

#vKernel IP Addresses on the iSCSI network
$vmkIP1 = '192.168.1.40'
$vmkIP2 = '192.168.1.41'
$vmkIP3 = '192.168.1.42'
$vmkIP4 = '192.168.1.43'
$Subnet = '255.255.255.0'

#iSCSI Target IPs
$Target1 = '192.168.1.65'
$Target2 = '192.168.1.50'
$Target3 = '192.168.1.5'
$Target4 = '192.168.1.6'
$Target5 = '192.168.1.7'

#End Global Variables
#==========================================================================

#Connect to ESXi Host
Connect-VIServer $HostName

#Create new vSwitch on the given host with the given NICs at the given MTU value
$iscsiswitch = New-VirtualSwitch -VMHost $HostName -Name $SwitchName -Nic $FirstNic,$SecondNic,$ThirdNic,$FourNic -Mtu $mtu -NumPorts '120'

#Create new iSCSI virtual port groups
New-VMHostNetworkAdapter -VMHost $HostName -PortGroup $vPG1 -VirtualSwitch $iscsiswitch -IP $vmkIP1 -SubnetMask $Subnet -Mtu $mtu
New-VMHostNetworkAdapter -VMHost $HostName -PortGroup $vPG2 -VirtualSwitch $iscsiswitch -IP $vmkIP2 -SubnetMask $Subnet -Mtu $mtu
New-VMHostNetworkAdapter -VMHost $HostName -PortGroup $vPG3 -VirtualSwitch $iscsiswitch -IP $vmkIP3 -SubnetMask $Subnet -Mtu $mtu
New-VMHostNetworkAdapter -VMHost $HostName -PortGroup $vPG4 -VirtualSwitch $iscsiswitch -IP $vmkIP4 -SubnetMask $Subnet -Mtu $mtu

#Sets the vLAN for the iSCSI Port Groups
Get-VirtualPortGroup -VMHost $HostName -VirtualSwitch $iscsiswitch -Name $vPG1 | Set-VirtualPortGroup -VLanId $vlanID
Get-VirtualPortGroup -VMHost $HostName -VirtualSwitch $iscsiswitch -Name $vPG2 | Set-VirtualPortGroup -VLanId $vlanID
Get-VirtualPortGroup -VMHost $HostName -VirtualSwitch $iscsiswitch -Name $vPG3 | Set-VirtualPortGroup -VLanId $vlanID
Get-VirtualPortGroup -VMHost $HostName -VirtualSwitch $iscsiswitch -Name $vPG4 | Set-VirtualPortGroup -VLanId $vlanID

#Sets the NIC Teaming Policy to only have one NIC active per iSCSI Port Group
Get-VirtualPortGroup -VMHost $HostName -VirtualSwitch $iscsiswitch -Name $vPG1 | Get-NicTeamingPolicy | Set-NicTeamingPolicy -MakeNicActive $FirstNic -MakeNicUnused $SecondNic,$ThirdNic,$FourNic
Get-VirtualPortGroup -VMHost $HostName -VirtualSwitch $iscsiswitch -Name $vPG2 | Get-NicTeamingPolicy | Set-NicTeamingPolicy -MakeNicActive $SecondNic -MakeNicUnused $FirstNic,$ThirdNic,$FourNic
Get-VirtualPortGroup -VMHost $HostName -VirtualSwitch $iscsiswitch -Name $vPG3 | Get-NicTeamingPolicy | Set-NicTeamingPolicy -MakeNicActive $ThirdNic -MakeNicUnused $FirstNic,$SecondNic,$FourNic
Get-VirtualPortGroup -VMHost $HostName -VirtualSwitch $iscsiswitch -Name $vPG4 | Get-NicTeamingPolicy | Set-NicTeamingPolicy -MakeNicActive $FourNic -MakeNicUnused $FirstNic,$SecondNic,$ThirdNic

#Turns on the iSCSI Initiator
Get-VMHostStorage -VMHost $HostName | Set-VMHostStorage -SoftwareIScsiEnabled $True

#Reads out the HBA number for the iSCSI Software Adapter
$HBANumber = Get-VMHostHba -VMHost $HostName -Type iSCSI | %{$_.Device}

#Sets up PowerCLI to be able to access esxcli commands
$esxcli = Get-EsxCli

#Binds VMKernel ports to the iSCSI Software Adapter HBA
$esxcli.swiscsi.nic.add($HBANumber,$vmk1number)
$esxcli.swiscsi.nic.add($HBANumber,$vmk2number)
$esxcli.swiscsi.nic.add($HBANumber,$vmk3number)
$esxcli.swiscsi.nic.add($HBANumber,$vmk4number)

#Sets the iSCSI Targets
Get-VMHostHba -VMHost $HostName -Type iScsi | New-IScsiHbaTarget -Address $Target1,$Target2,$Target3,$Target4,$Target5

#Performs a Rescan on all HBAs and then a Rescan for VMFS volumes
Get-VMHostStorage -VMHost $HostName -RescanAllHba
Get-VMHostStorage -VMHost $HostName -RescanVmfs

#Disconnect from Host
Disconnect-VIServer