RSS .92| RSS 2.0| ATOM 0.3
  • Home
  • About
  •  

    VMWare Ping Test using PowerShell…

    I recently had to come up with a way to verify that virtual server guests on ESX hosts were back online after restarts that were scheduled using the VMWare Infrastructure Client console. Using the VMWare Automation snap-in, I wrote a PowerShell script that will test for basic ping connectivity via WMI and then leverage VMWare cmdlets to attempt to recover any VM’s that are not responding as well as sending an email to recipients when the script fails to bring them online.

    This script was implemented as a scheduled task so I simply hardcoded the values into the script rather than using the param statement since I didn’t plan on calling it from the console; however, it should be easy enough to modify if you wanted to use it interactively. Also, since it is required to connect to the VMServer prior to running any cmdlets, I used Secure-String to generate an encrypted password with a little bit of security since it would be in a text file on the server. To generate the password file, I used the following commands directly in a PowerShell console (second line wrapped):

    $secureString = Read-Host -AsSecureString
    ConvertFrom-SecureString $secureString | out-file C:\Scripts\PowerShell\VMPingTest\acctpass.txt

    As you can see from the script below, it only takes one line of .NET to decrypt the encrypted password from the file so it’s not foolproof, but still better than plain text and NTFS only. I’ve commented the script fairly heavily, so it should be easy to customize for different environments.

    ?View Code POWERSHELL
    #Load VMWare snap in:
    Add-PSSnapin VMware.VimAutomation.Core -ErrorVariable errSnapIn -ErrorAction silentlycontinue
    if ($errSnapIn.Count -ne 0) {
    	Write-Host "VMWare snap in is required."
    	exit
    	}
    #------------------------------------------------------------------------------
    # Set up variables
    #------------------------------------------------------------------------------
    #VM Server hostname
    $VMServer = "MYSERVER.MYDOMAIN"
    #User account to connect to virtual infrastructure:
    $username = "USERNAME"
    #Directory path to secure string password:
    $pass = "C:\Path\to\securestringpass.txt"
    #Directory path to target list of VM's.
    $servers = Get-Content "C:\Path\to\serverlist.txt"
    #Directory path to list of mail recipients.
    $mailrecipients = Get-Content "C:\Path\to\recipients.txt"
    #SMTP relay server
    $smtpserver = "smtp.mydomain.com"
    #Decrypt SecureString password for account:
    $pwd = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((gc $pass | ConvertTo-SecureString)))
     
    #------------------------------------------------------------------------------
    # Connect to VM Server
    #------------------------------------------------------------------------------
    $server = Connect-VIServer -Server $VMServer -User $username -Password $pwd
    #Search for specific VM in the production cluster:
    $folder = Get-Folder -Name "Financial Hosts" #Target the Finanancial Hosts folder in the VM Infrastructure Client console
    $cluster = Get-Cluster -Name "Dallas HA Cluster" -Location $folder #Target the Dallas HA Cluster in the VM Infrastructure Client console
     
    #------------------------------------------------------------------------------
    # Methods
    #------------------------------------------------------------------------------
    function SendMail
    {
    	param($svr, $status)
    	foreach ($recipient in $mailrecipients)
    	{
    		$mail = new-object System.Net.Mail.MailMessage
    		$mail.Priority = 'High'
    		$mail.From = new-object System.Net.Mail.MailAddress("PINGTEST@MYDOMAIN.COM");
    		$mail.To.Add("$recipient");
     
    		#set the content
    		$mail.Subject = "$svr is not responding...";
    		$mail.Body = "$svr failed to respond to ping tests with error: $status.`n" + 
    		"This process automatically powers on virtual machines and restart virtual guests where the local network is unresponsive. `n" + 
    		"This server has not responded to automated restart tasks and needs additional attention.`n`n"
     
    		#send the message
    		$smtp = new-object System.Net.Mail.SmtpClient($smtpserver); 
    		$smtp.Send($mail);
    	}
    }
     
    #------------------------------------------------------------------------------
    # Main()
    #------------------------------------------------------------------------------
    foreach ($svr in $servers)
    {
    	$result = gwmi -class Win32_PingStatus -filter "Address='$svr'"
    	$results = $result.StatusCode
    	$vm = Get-VM -Name $svr -Location $cluster #Search for specified VM in cluster
     
    	if (($vm.PowerState -eq "PoweredOff") -and ($results -ne 0))
    	{
    		#If the VM is powered down
    		Start-VM -VM $vm.Name #Start VM
    		Start-Sleep -Seconds 60 #Allow time for VM to come online
    	}
     
    	#If the VM is powered on, but guest OS is not responding to pings
    	if (($vm.PowerState -eq "PoweredOn") -and ($results -ne 0))
    	{
    		Restart-VMGuest -VM $vm.Name #Restart VM Guest OS
    		Start-Sleep -Seconds 60 #Allow time for VM to come online
    	}
     
    	#Re-run ping test if server was originally unresponsive.
    	if ($results -ne 0)
    	{
    		$secondresult = gwmi -class Win32_PingStatus -filter "Address='$svr'"
    		$secondresults = $secondresult.StatusCode
    		switch ($secondresults)
    		{
    			0 	  { $pingresults = "Success" }
    			11001 { $pingresults = "Buffer Too Small" }
    			11002 { $pingresults = "Destination Net Unreachable" }
    			11003 { $pingresults = "Destination Host Unreachable" }
    			11004 { $pingresults = "Destination Protocol Unreachable" }
    			11005 { $pingresults = "Destination Port Unreachable" }
    			11006 { $pingresults = "No Resources" }
    			11007 { $pingresults = "Bad Option" }
    			11008 { $pingresults = "Hardware Error" }
    			11009 { $pingresults = "Packet Too Big" }
    			11010 { $pingresults = "Request Timed Out" } 
    			11011 { $pingresults = "Bad Request" }
    			11012 { $pingresults = "Bad Route" }
    			11013 { $pingresults = "TimeToLive Expired Transit" }
    			11014 { $pingresults = "TimeToLive Expired Reassembly" }
    			11015 { $pingresults = "Parameter Problem" }
    			11016 { $pingresults = "Source Quench" }
    			11017 { $pingresults = "Option Too Big" }
    			11018 { $pingresults = "Bad Destination" }
    			11032 { $pingresults = "Negotiating IPSEC" }
    			11050 { $pingresults = "General Failure" }
    		}
    	}
     
    	if ($secondresults -ne 0) 
    	{
    		SendMail $svr $pingresults
    	}
    }

    Leave a Reply