Difference between revisions of "ESX Script Extracts and Examples"

Jump to navigation Jump to search
Syntax highlighting broken
m (Added category)
(Syntax highlighting broken)
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Daily ESX Up/Down Check ==
Simple script that runs every morning just before I start work to provide a basic sanity check email to glance through over the first tea of the day.
<syntaxhighlight lang='powershell'>
#############################################################################################
#
#  ESX Checker
#
#############################################################################################
#
# By Simon Strutt
#
# Version 1 - Aug 10
# - Initial creation
#
# Version 2 - Oct 10
# - Fixed VIServer handling (was never good but stuffed by upgrade to PowerCLI 4.1)
# - Improved email in case of vCentre connection failure
#
# Version 2.1 - Nov 10
# - Minor text changes
#
# Version 2.2 - Nov 10
# - Added InvalidLogon catch to vCentre logon to prevent a/c lockout
#
# Version 3 - Dec 10
# - Truncated displayed ESX hostname (stripped domain)
# - Added "since <datetime>" info to ESX's that aren't in a good state
# - Bugfix: Incorrect email config used when VC list config file load failed
#
# Version 3.1 Jan 11
# - Workaround: Powershell/MS DateTime object returns incorrect (US) date format
#
# Version 3.2 Jan 11
# - Bugfix: Extraneous " hrs" on end of v3.1 fixed datetimes
#
#############################################################################################
$DateFormat = "%R hrs, %a %d %b %Y"
$EmailBody = "Results of ESX status check as of " + (get-date -uFormat "$DateFormat.`n`n")
$EmailRecipients = "person1@domain.com,person2@domain.com"
$EmailSender = "VI-Mgmt@domain.com"
$UserFile = "User.fil"
$PassFile = "Pass.fil"
$smtp = New-Object Net.Mail.SmtpClient -arg "smtp-server.domain.com"
$VCAlertToSend = 0
$ESXAlertToSend = 0
$start = Get-Date
try {
    $ToCheck = Import-CSV "ESX-Check.csv"
} catch {
    $EmailBody = "ERROR: Failed to load config file, no checks have been done.`n"
    $EmailBody += $_
    $smtp.Send($EmailSender, $EmailRecipients, "ESX-Check: Check failed", $EmailBody)
    Exit
}
$pass = Get-Content $PassFile -errorAction Stop | ConvertTo-SecureString
$user = Get-Content $UserFile -errorAction Stop
$cred = New-Object System.Management.Automation.PsCredential($user, $pass)
foreach ($vc in $ToCheck) {
    Write-Host "Checking ESXs on" $vc.vc
    $VChasBadESX = 0
    try {
        $VCconn = Connect-VIServer -Server $vc.vc -Credential $cred -NotDefault -errorAction "Stop"
    } catch [VMware.VimAutomation.ViCore.Types.V1.ErrorHandling.InvalidLogin] {
        $EmailBody += ($vc.vc).ToUpper() + "`t" + "Unable to connect to vCentre, invalid logon error !!`n`n"
        $EmailBody += "Abandoning further script processing in order to prevent potential account lockout.`n"
        $VCAlertToSend = 1
        Break
    } catch {
        $EmailBody += ($vc.vc).ToUpper() + "`t" + "Unable to connect to vCentre, ESX's not checked !!`n"
        $VCAlertToSend = 1
        Continue
    }
    $ESXs = Get-VMHost -Server $vc.vc | Where {$_.State -ne "Connected"} | Sort -property Name
    if ($ESXs) {
        foreach ($ESX in $ESXs) {
            # Attempt to work out when ESX went into its bad state
            Switch ($ESX.State) {
                NotResponding {
                    $events = Get-VIEvent -Entity $ESX -Types Error | Where {$_.fullFormattedMessage -like "*is not responding*"}
                }
                Maintenance {
                    $events = Get-VIEvent -Entity $ESX -MaxSamples 1000 | Where {$_.fullFormattedMessage -like "*has entered maintenance mode*"}
                }
                Disconnected {
                    $events = Get-VIEvent -Entity $ESX -MaxSamples 1000 | Where {$_.fullFormattedMessage -like "*Disconnected from*"}
                }
                Default {
                    $events = 0
                }
            }
            If ($events) {
                $SinceString = " since " + (Get-Date $events[0].CreatedTime -uFormat $DateFormat)
            } else {
                $SinceString = ""
            }
                   
            $EmailBody += $vc.vc + "`t" + ($ESX.Name.Split(".")[0]).ToUpper() + "`t" + $ESX.State + $SinceString + "`n"
            $ESXAlertToSend = 1
            $VChasBadESX = 1
        }
    }
    if (!$VChasBadESX) {
        $EmailBody += $vc.vc + "`t" + "All good`n"
    }
    Disconnect-VIServer -Server $VCconn -Confirm:$false
}
$end = Get-Date
$EmailBody += "`n`n`nCheck started      : " + (Get-Date $start -uFormat $DateFormat) + "`n"
$EmailBody += "Check finished    : " + (Get-Date $end -uFormat $DateFormat) + "`n"
$EmailBody += "Generated by script: " + ($MyInvocation.MyCommand.Name) + "`n"
$EmailBody += "Sent from machine  : $env:computername"
$EmailBody
Write-Host "Sending email..."
if ($VCAlertToSend) {
    $smtp.Send($EmailSender, $EmailRecipients, "ESX-Check: Unable to connect to some/all vCentres", $EmailBody)
} elseif ($ESXAlertToSend) {
    $smtp.Send($EmailSender, $EmailRecipients, "ESX-Check: Some ESX's are NOT CONNECTED", $EmailBody)
} else {
    $smtp.Send($EmailSender, $EmailRecipients, "ESX-Check: All connected OK", $EmailBody)
}
if (-not $?) {
    Write-Host "SMTP send failed!!"
    Start-Sleep(30000)
}
</syntaxhighlight>
{{PowerShell_Credentials_Files}}
== ESX NIC Info ==
== ESX NIC Info ==
Provides a list of all vmnic speeds for ESX's managed by the vCentre you're connected to.
Provides a list of all vmnic speeds for ESX's managed by the vCentre you're connected to.
Line 17: Line 159:
}
}
</source>
</source>
== Discovered Networks Hint ==
This function provides the discovered network hints for the network interface its passed.  Bear in mind that its just a hint, for an ESX to be aware of a particular vLAN it needs to see traffic.  If there's no traffic (eg a newly set-up ESX with no VMs) it will show nothing.
Adapted from the following article on the VMware site blog http://blogs.vmware.com/vipowershell/2010/02/how-to-find-out-what-vlans-your-esx-hosts-can-really-see.html
<source lang="powershell">
function Get-ObservedIPRange {
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true,HelpMessage="Physical NIC from Get-VMHostNetworkAdapter")]
[VMware.VimAutomation.Client20.Host.NIC.PhysicalNicImpl]
$Nic
)
process {
$hostView = Get-VMHost -Id $Nic.VMHostId | Get-View -Property ConfigManager
$ns = Get-View $hostView.ConfigManager.NetworkSystem
$hints = $ns.QueryNetworkHint($Nic.Name)
foreach ($hint in $hints) {
foreach ($subnet in $hint.subnet) {
$observed = New-Object -TypeName PSObject
$observed | Add-Member -MemberType NoteProperty -Name Device -Value $Nic.Name
$observed | Add-Member -MemberType NoteProperty -Name VlanId -Value $subnet.VlanId
$observed | Add-Member -MemberType NoteProperty -Name IPSubnet -Value $subnet.IPSubnet
$observed | Add-Member -MemberType NoteProperty -Name BitRatePerSec -Value $nic.BitRatePerSec
Write-Output $observed
}
}
}
}
# Example use:
$result = Get-VMHost MyESX* | Get-VMHostNetworkAdapter | Where {$_.Name -Match ".*vmnic*"} | Get-ObservedIPRange | Sort-Object -Property Device, VlanId
$result | Export-Csv -path ESX-vLANs-Observed.csv
</source>
== Add VLANs/PortGroups to Standard Switch ==
Simple script to add new port groups to an ESX.  Create a CSV file in the format as show in the example below.  Then update the <code>$esx</code> and <code>$vSwitch</code> variables as appropriate in the script and run in a PowerCLI session connected to the vCenter.
<source lang="powershell">
$PG_List = "ESX-Add-PortGroups.csv"        # CSV to list new port groups in
$esx = "esx-name*"                        # ESX to add port groups to
$vSwitch = "vSwitch0"                      # vSwitch (standard not dvSwitch) on ESX to add port groups to
$Switch = Get-VirtualSwitch -Name $vSwitch -VMHost (Get-VMHost $esx)
try {
    $PGs = Import-CSV $PG_List
} catch {
  Write-Host("ERROR: Failed to load list of PortGroup's")
  Exit
}
foreach ($pg in $PGs) {
    Write-Host ("Adding VLAN " + $pg.VLAN + " " + $pg.Name)
    New-VirtualPortGroup -VirtualSwitch $Switch -Name $pg.Name -VLanId $pg.VLAN
}
</source>
{| class="vwikitable"
|+ Example contents of CSV file
! VLAN !! Name
|-
|  101 || Testing
|-
|  102 || Development
|-
|  103 || ABC Production
|}
== ESX CDP Info ==
Adapted from posted by LucD on VMware forum http://communities.vmware.com/message/977487
<source lang="powershell">
Get-VMHost | Sort -Property Name | %{Get-View $_.ID} | %{$esxname = $_.Name; Get-View $_.ConfigManager.NetworkSystem} | %{
  foreach($physnic in $_.NetworkInfo.Pnic){
    $pnicInfo = $_.QueryNetworkHint($physnic.Device)
    foreach($hint in $pnicInfo){
      Write-Host $esxname $physnic.Device $hint.connectedSwitchPort.DevId $hint.connectedSwitchPort.PortId
    }
  }
}
</source>


== ESX Log Tail ==
== ESX Log Tail ==
Line 81: Line 309:
     $ESXlog.Entries
     $ESXlog.Entries
     $LineNo = $ESXLog.LastLineNum
     $LineNo = $ESXLog.LastLineNum
}
</source>
== Discovered Networks Hint ==
This function provides the discovered network hints for the network interface its passed.  Bear in mind that its just a hint, for an ESX to be aware of a particular vLAN it needs to see traffic.  If there's no traffic (eg a newly set-up ESX with no VMs) it will show nothing.
Adapted from the following article on the VMware site blog http://blogs.vmware.com/vipowershell/2010/02/how-to-find-out-what-vlans-your-esx-hosts-can-really-see.html
<source lang="powershell">
function Get-ObservedIPRange {
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true,HelpMessage="Physical NIC from Get-VMHostNetworkAdapter")]
[VMware.VimAutomation.Client20.Host.NIC.PhysicalNicImpl]
$Nic
)
process {
$hostView = Get-VMHost -Id $Nic.VMHostId | Get-View -Property ConfigManager
$ns = Get-View $hostView.ConfigManager.NetworkSystem
$hints = $ns.QueryNetworkHint($Nic.Name)
foreach ($hint in $hints) {
foreach ($subnet in $hint.subnet) {
$observed = New-Object -TypeName PSObject
$observed | Add-Member -MemberType NoteProperty -Name Device -Value $Nic.Name
$observed | Add-Member -MemberType NoteProperty -Name VlanId -Value $subnet.VlanId
$observed | Add-Member -MemberType NoteProperty -Name IPSubnet -Value $subnet.IPSubnet
$observed | Add-Member -MemberType NoteProperty -Name BitRatePerSec -Value $nic.BitRatePerSec
Write-Output $observed
}
}
}
}
# Example use:
$result = Get-VMHost MyESX* | Get-VMHostNetworkAdapter | Where {$_.Name -Match ".*vmnic*"} | Get-ObservedIPRange | Sort-Object -Property Device, VlanId
$result | Export-Csv -path ESX-vLANs-Observed.csv
</source>
= ESX CDP Info =
Adapted from posted by LucD on VMware forum http://communities.vmware.com/message/977487
<source lang="powershell">
Get-VMHost | Sort -Property Name | %{Get-View $_.ID} | %{$esxname = $_.Name; Get-View $_.ConfigManager.NetworkSystem} | %{
  foreach($physnic in $_.NetworkInfo.Pnic){
    $pnicInfo = $_.QueryNetworkHint($physnic.Device)
    foreach($hint in $pnicInfo){
      Write-Host $esxname $physnic.Device $hint.connectedSwitchPort.DevId $hint.connectedSwitchPort.PortId
    }
  }
}
}
</source>
</source>
Line 138: Line 314:
== ESX BIOS, NIC and HBA Driver Versions ==
== ESX BIOS, NIC and HBA Driver Versions ==
Getting BIOS, NIC and HBA driver versions is dependant on what's reported to the ESX by the hardware vendor's CIM provider.  This script was written using various HP servers and may well only work for them.
Getting BIOS, NIC and HBA driver versions is dependant on what's reported to the ESX by the hardware vendor's CIM provider.  This script was written using various HP servers and may well only work for them.
Over time I've found the method below to be unreliable, as the data available from vCentre varies in quality, an alternative (which is more reliable, but requires the use of external libraries) can be found here - http://vblog.strutt.org.uk/2012/04/esx-hba-and-nic-driverfirmware-versions/


<source lang="Powershell">
<source lang="Powershell">
Line 162: Line 340:
$start = Get-Date
$start = Get-Date
$OutputFile = "ESXs.csv"
$OutputFile = "ESXs.csv"
$VC_List = "ESX-Check.csv"
$UserFile = "User.fil"
$UserFile = "User.fil"
$PassFile = "Pass.fil"                          # Encrypted file to store password in
$PassFile = "Pass.fil"                          # Encrypted file to store password in
$Results = @()
$Results = @()


# Include library files
$VCs = @()
. .\lib\Standard.ps1
$VCs += "vCentreA"                              # Hostname of Virtual Center
$VCs += "vCentreB"                              # Hostname of Virtual Center (repeat if you have more VC's, delete if you've only one)


Start-Transcript -Path ESX-Inventory.log
Start-Transcript -Path ESX-Inventory.log
Log "Started script run at $start"
Write-Host "Started script run at $start"


# Function-U-like ===================================================================================
# Function-U-like ===================================================================================
Line 183: Line 361:


# ===================================================================================================  
# ===================================================================================================  
# Load list of VC's
try {
    $VCs = Import-CSV $VC_List
} catch {
    Log "ERROR: Failed to load list of vC's"
    Exit
}


# Load password credential from encrypted file
# Load password credential from encrypted file
Line 201: Line 371:
     # Connect to VC
     # Connect to VC
     try {
     try {
         Log("Connecting to " + $vc.vc)
         Log("Connecting to " + $vc)
         $VCconn = Connect-VIServer -Server $vc.vc -Credential $cred -errorAction "Stop"
         $VCconn = Connect-VIServer -Server $vc -Credential $cred -errorAction "Stop"
     } catch [VMware.VimAutomation.ViCore.Types.V1.ErrorHandling.InvalidLogin] {
     } catch [VMware.VimAutomation.ViCore.Types.V1.ErrorHandling.InvalidLogin] {
         Log("Unable to connect to vCentre, invalid logon error !!")
         Log("Unable to connect to vCentre, invalid logon error !!")
Line 213: Line 383:
      
      
     # Get ESX objects
     # Get ESX objects
     Log("Getting list of ESXs to check on " + ($vc.vc) + "...")
     Log("Getting list of ESXs to check on " + ($vc) + "...")
     $ESXs = Get-VMHost -Server $vc.vc | Sort -property Name
     $ESXs = Get-VMHost -Server $vc | Sort -property Name
     Log("Got list of " + ($ESXs.Count) + " ESXs to check")  
     Log("Got list of " + ($ESXs.Count) + " ESXs to check")  
      
      
Line 226: Line 396:
          
          
         # Get the basics
         # Get the basics
         $row.VC = $vc.vc
         $row.VC = $vc
         $row.Cluster = $ESX.Parent
         $row.Cluster = $ESX.Parent
         $row.Name = $ESX.Name.Split(".")[0]
         $row.Name = $ESX.Name.Split(".")[0]
Line 286: Line 456:
</source>
</source>


== Daily ESX Up/Down Check ==
{{PowerShell_Credentials_Files}}
Simple script that runs every morning just before I start work to provide a basic sanity check email to glance through over the first tea of the day.
 
See the following page for details on how to [[Power_Shell#Store_Password_Securely|Store Password Securely]] (as I have done, loaded though the files specified by <code>$UserFile</code> and <code>$PassFile</code> in the script below).
 
<source lang="Powershell">
#############################################################################################
#
#  ESX Checker
#
#############################################################################################
#
# By Simon Strutt
#
# Version 1 - Aug 10
# - Initial creation
#
# Version 2 - Oct 10
# - Fixed VIServer handling (was never good but stuffed by upgrade to PowerCLI 4.1)
# - Improved email in case of vCentre connection failure
#
# Version 2.1 - Nov 10
# - Minor text changes
#
# Version 2.2 - Nov 10
# - Added InvalidLogon catch to vCentre logon to prevent a/c lockout
#
# Version 3 - Dec 10
# - Truncated displayed ESX hostname (stripped domain)
# - Added "since <datetime>" info to ESX's that aren't in a good state
# - Bugfix: Incorrect email config used when VC list config file load failed
#
# Version 3.1 Jan 11
# - Workaround: Powershell/MS DateTime object returns incorrect (US) date format
#
# Version 3.2 Jan 11
# - Bugfix: Extraneous " hrs" on end of v3.1 fixed datetimes
#
#############################################################################################
 
$DateFormat = "%R hrs, %a %d %b %Y"
 
$EmailBody = "Results of ESX status check as of " + (get-date -uFormat "$DateFormat.`n`n")
$EmailRecipients = "person1@domain.com,person2@domain.com"
$EmailSender = "VI-Mgmt@domain.com"
 
$UserFile = "User.fil"
$PassFile = "Pass.fil"
 
$smtp = New-Object Net.Mail.SmtpClient -arg "smtp-server.domain.com"
$VCAlertToSend = 0
$ESXAlertToSend = 0
$start = Get-Date
 
try {
    $ToCheck = Import-CSV "ESX-Check.csv"
} catch {
    $EmailBody = "ERROR: Failed to load config file, no checks have been done.`n"
    $EmailBody += $_
    $smtp.Send($EmailSender, $EmailRecipients, "ESX-Check: Check failed", $EmailBody)
    Exit
}
 
$pass = Get-Content $PassFile -errorAction Stop | ConvertTo-SecureString
$user = Get-Content $UserFile -errorAction Stop
$cred = New-Object System.Management.Automation.PsCredential($user, $pass)
 
foreach ($vc in $ToCheck) {
    Write-Host "Checking ESXs on" $vc.vc
    $VChasBadESX = 0
    try {
        $VCconn = Connect-VIServer -Server $vc.vc -Credential $cred -NotDefault -errorAction "Stop"
    } catch [VMware.VimAutomation.ViCore.Types.V1.ErrorHandling.InvalidLogin] {
        $EmailBody += ($vc.vc).ToUpper() + "`t" + "Unable to connect to vCentre, invalid logon error !!`n`n"
        $EmailBody += "Abandoning further script processing in order to prevent potential account lockout.`n"
        $VCAlertToSend = 1
        Break
    } catch {
        $EmailBody += ($vc.vc).ToUpper() + "`t" + "Unable to connect to vCentre, ESX's not checked !!`n"
        $VCAlertToSend = 1
        Continue
    }
    $ESXs = Get-VMHost -Server $vc.vc | Where {$_.State -ne "Connected"} | Sort -property Name
    if ($ESXs) {
        foreach ($ESX in $ESXs) {
            # Attempt to work out when ESX went into its bad state
            Switch ($ESX.State) {
                NotResponding {
                    $events = Get-VIEvent -Entity $ESX -Types Error | Where {$_.fullFormattedMessage -like "*is not responding*"}
                }
                Maintenance {
                    $events = Get-VIEvent -Entity $ESX -MaxSamples 1000 | Where {$_.fullFormattedMessage -like "*has entered maintenance mode*"}
                }
                Disconnected {
                    $events = Get-VIEvent -Entity $ESX -MaxSamples 1000 | Where {$_.fullFormattedMessage -like "*Disconnected from*"}
                }
                Default {
                    $events = 0
                }
            }
            If ($events) {
                $SinceString = " since " + (Get-Date $events[0].CreatedTime -uFormat $DateFormat)
            } else {
                $SinceString = ""
            }
                   
            $EmailBody += $vc.vc + "`t" + ($ESX.Name.Split(".")[0]).ToUpper() + "`t" + $ESX.State + $SinceString + "`n"
            $ESXAlertToSend = 1
            $VChasBadESX = 1
        }
    }
    if (!$VChasBadESX) {
        $EmailBody += $vc.vc + "`t" + "All good`n"
    }
    Disconnect-VIServer -Server $VCconn -Confirm:$false
}
 
$end = Get-Date
 
$EmailBody += "`n`n`nCheck started      : " + (Get-Date $start -uFormat $DateFormat) + "`n"
$EmailBody += "Check finished    : " + (Get-Date $end -uFormat $DateFormat) + "`n"
$EmailBody += "Generated by script: " + ($MyInvocation.MyCommand.Name) + "`n"
$EmailBody += "Sent from machine  : $env:computername"
 
$EmailBody
Write-Host "Sending email..."
if ($VCAlertToSend) {
    $smtp.Send($EmailSender, $EmailRecipients, "ESX-Check: Unable to connect to some/all vCentres", $EmailBody)
} elseif ($ESXAlertToSend) {
    $smtp.Send($EmailSender, $EmailRecipients, "ESX-Check: Some ESX's are NOT CONNECTED", $EmailBody)
} else {
    $smtp.Send($EmailSender, $EmailRecipients, "ESX-Check: All connected OK", $EmailBody)
}
if (-not $?) {
    Write-Host "SMTP send failed!!"
    Start-Sleep(30000)
}
</source>


[[Category:PowerCLI]]
[[Category:PowerCLI]]
[[Category:ESX]]
[[Category:ESX]]

Navigation menu