This script checks which node is the primary in the SQL AlwaysOn cluster. A test database has been added to see if that database is writable. All actions are logged to a log file.
This script is not to be run in a production environment. The purpose of this script is to see if the SQL AlwaysOn Availability Group has done a failover. It also checks if a database within this AG is writable and if not how long it has been offline. The part to check which node is the primary has been found on a blog, which I would have given the credits if I remembered where I found it.
<#.Synopsis Monitors an SQL AlwaysOn cluster and tries to write to a database on this AlwaysOn cluster..Description Monitors an SQL AlwaysOn cluster and tries to write to a database on this AlwaysOn cluster..Example # No Examples available#># Import SQL moduleImport-Module sqlps# Connection parameters$ServerInstance="database_server"# if you are running SQL on a custom port it should be "database_server,port"$Database="TEST_AlwaysOn"# Logging$FileName="PrimaryLOG"$LogDir="E:SQL_script"$LogBreaker="##########################"$global:File=""$MaxLogEntries=1000$LogEntries=1$Failed=0$Sleep=900FunctionInitialize {# Logging parameters$LogFileDate=Get-Date-Format FileDateTime$global:File=$LogDir+""+$FileName+"_"+$LogFileDate+".log"If ($Debug) {write "The filename is: $global:File"}# Initialization (empty table)$SQLQuery=$("TRUNCATE TABLE Test_AlwaysOn.dbo.Test_Table")invoke-sqlcmd-query $SQLquery-serverinstance $ServerInstance-database $Database#Start-Sleep -Seconds 3# Initialize log$LogBreaker|Out-File"$global:File"-Append" LogFile: $global:File"|Out-File"$global:File"-Append" LogDate: $Date"|Out-File"$global:File"-Append" Server: $ServerInstance"|Out-File"$global:File"-Append" Database: $Database was truncated"|Out-File"$global:File"-Append$LogBreaker|Out-File"$global:File"-Append}Initialize# MAIN# While statement is built to always runWhile ($true) {$Date= (get-date).ToString("yyyy-MM-dd HH:mm:ss.fff")# Generate at least one entry/day to see if I'm aliveIf ((get-date-Format hhmmss) -eq000000) {$AddToFile="$Date"+" It's a new day, it's a new dawn"$AddToFile|Out-File"$global:File"-Append }$Run++# Find AlwaysOn Primary$SQLQuery=$("SELECT AGC.name, RCS.replica_server_name, ARS.role_desc, AGL.dns_name "+"FROM sys.availability_groups_cluster AS AGC "+"INNER JOIN sys.dm_hadr_availability_replica_cluster_states AS RCS "+"ON RCS.group_id = AGC.group_id "+"INNER JOIN sys.dm_hadr_availability_replica_states AS ARS "+"ON ARS.replica_id = RCS.replica_id "+"INNER JOIN sys.availability_group_listeners AS AGL "+"ON AGL.group_id = ARS.group_id "+"WHERE ARS.role_desc = 'PRIMARY' ;")$AGResult=invoke-sqlcmd-query $SQLquery-serverinstance $ServerInstance-database $Database$PrimaryReplica=$AGResult[1]If ($PrimaryReplica-ne$PrimaryReplicaLastRun) {# Filter first runIf ($PrimaryReplicaLastRun-eq$null) {$AddToFile="$Date"+" AG is $PrimaryReplica"$AddToFile|Out-File"$global:File"-Append$LogEntries++ }Else {# Write to log$AddToFile="$Date"+" AG changed from $PrimaryReplicaLastRun to $PrimaryReplica"$AddToFile|Out-File"$global:File"-Append$LogEntries++ } }# Write to table to see if it is available$SQLQuery=$("INSERT INTO Test_AlwaysOn.dbo.Test_Table (Test_Run,AG_Primary,Test_Time) "+"VALUES ('$Run','$PrimaryReplica','$Date'); " )invoke-sqlcmd-query $SQLquery-serverinstance $serverinstance-database $database# Read the last insert via $Run$SQLQuery=$("SELECT Test_Run,AG_Primary,Test_Time FROM Test_AlwaysOn.dbo.Test_Table where Test_run = $Run")$SelectResult=invoke-sqlcmd-query $SQLquery-serverinstance $serverinstance-database $databaseIf ($Debug) {write "SelectResult: "$SelectResult}$AG_Primary=$SelectResult[1]$Test_Time=$SelectResult[2].ToString("yyyy-MM-dd HH:mm:ss.fff")# Write to logIf ($Test_Time-eq$Date) {If ($Failed-gt0) {$AddToFile="$Date Database was not writable between $Test_TimeLastSucceed and $Date, we tried $Failed times."$AddToFile|Out-File"$global:File"-Append$LogEntries++$OfflineHR=$Date.Substring(11,2) -$Test_TimeLastSucceed.Substring(11,2)If ($Debug) {write $OfflineHR}$OfflineMin=$Date.Substring(14,2) -$Test_TimeLastSucceed.Substring(14,2)If ($Debug) {write $OfflineMin}$OfflineSec=$Date.Substring(17,5) -$Test_TimeLastSucceed.Substring(17,5)If ($Debug) {write $OfflineSec}$Offline=$OfflineHR*3600+$OfflineMin*60+$OfflineSecIf ($Debug) {write $Offline}$AddToFile="$Date Database was not writable for $Offline seconds."$AddToFile|Out-File"$global:File"-Append$LogEntries++$Failed=0 }$Test_TimeLastSucceed=$Test_Time$Test_Time=$null }Else {$Failed++ }Start-Sleep-Milliseconds $Sleep# Check if the # entries have reached the maximum entriesIf ($LogEntries%$MaxLogEntries-eq0) {$LogBreaker|Out-File"$global:File"-Append$AddToFile="$Date"+" Log limits have been reached. A new log file will be started."$AddToFile|Out-File"$global:$File"-Append Initialize }# Keep the values of the variables of the last run$PrimaryReplicaLastRun=$PrimaryReplica}
The following Get-EsxCli command will unconfigure your diagnostic partition and reconfigure with smart selection. This was needed because the install partition uuid had changed due to an option in the NetApp system while doing system testing.
These are powercli goodies I use on a regular base. I have collected them here to find them easily. Some I wrote myself, some are copied from other sites. If I didn’t reference the source, I don’t know anymore where I found it.
While executing the NetApp MetroCluster testplan, the syslog service stops logging to the presented syslog datastore. To restart the logging reload the syslog service on all impacted hosts. The following command will reload the syslog service on all hosts in the connected vCenters. Check the $global:defaultviservers to know which vCenters are connected.
Change the Power Management Policy for each host in cluster
#get connected esxi hosts$vmhostlist=get-vmhost|sort|select name#for each host show the power management policy settingforeach ($entryin$vmhostlist) {#list power management policy on all connected esxi hostsget-vmhost|sort|select name,@{ N="CurrentPolicy"; E={$_.ExtensionData.config.PowerSystemInfo.CurrentPolicy.ShortName}},@{N="CurrenPolicyKey"; E={$_.ExtensionData.config.PowerSystemInfo.CurrentPolicy.Key}},@{N="AvailablePolicies";E={$_.ExtensionData.config.PowerSystemCapability.AvailablePolicy.ShortName}}#for each host change the power management policy to high performanceforeach ($entryin$vmhostlist) {$view=(get-vmhost$entry.name|get-view);(get-view$view.configmanager.powersystem).configurepowerpolicy(1)}#list power management policy on all connected esxi hostsget-vmhost|sort|select name,@{ N="CurrentPolicy"; E={$_.ExtensionData.config.PowerSystemInfo.CurrentPolicy.ShortName}},@{N="CurrenPolicyKey"; E={$_.ExtensionData.config.PowerSystemInfo.CurrentPolicy.Key}},@{N="AvailablePolicies";E={$_.ExtensionData.config.PowerSystemCapability.AvailablePolicy.ShortName}}
Update:
Apparently there were some errors (curly brackets missing or in the wrong place) in the previous code.
It also ran several times per host because per host there was a Get-VMHost in the ForEach iteration. So If you had three hosts it would run three times per host.
The updated and optimized code:
$VMHosts=Get-VMHost#for each host show the power management policy settingForEach ($entryin$VMHosts) {#list power management policy on all connected esxi hosts$entry| Select Name,@{ N="CurrentPolicy"; E={$_.ExtensionData.Config.PowerSystemInfo.CurrentPolicy.ShortName}},@{N="CurrenPolicyKey"; E={$_.ExtensionData.Config.PowerSystemInfo.CurrentPolicy.Key}},@{N="AvailablePolicies";E={$_.ExtensionData.Config.PowerSystemCapability.AvailablePolicy.ShortName}}}#for each host change the power management policy to high performanceForEach ($entryin$VMHosts) {$view=($entry|Get-View);(Get-View$view.ConfigManager.PowerSystem).ConfigurePowerPolicy(1)#list power management policy on all connected esxi hosts$entry| Select Name,@{ N="CurrentPolicy"; E={$_.ExtensionData.Config.PowerSystemInfo.CurrentPolicy.ShortName}},@{N="CurrenPolicyKey"; E={$_.ExtensionData.Config.PowerSystemInfo.CurrentPolicy.Key}},@{N="AvailablePolicies";E={$_.ExtensionData.Config.PowerSystemCapability.AvailablePolicy.ShortName}}}