#Script To Generate and email status for Replay Servers # v2.01 # # Script: Replay_Report.ps1 # # Usage: Replay_Report.ps1 # #---------------------------------------------------------------------- # Description: Script that reports on the status of a replay server and the servers it protects # and then emails the report to a specified list of users. # Reports on: Status of the Replay Service # Disk Usage Statistics for archive disks # Reports on the # of expected recovery points vs what's present # Reports on when the last valid snapshot was #---------------------------------------------------------------------- # Author: Carlos R. Tronco (cars@lostroncos.org) # http://cars.lostroncos.org # # Date: October 6, 2009 # # Version: 2.01 ###################################################################### # You have a royalty-free right to use, modify, reproduce, and # distribute this script file in any way you find useful, provided that # you agree that the copyright owner above has no warranty, obligations, # or liability for such use. ####################################################################### # Revisions: Month, Day, Year FML # 10/06/2009 CRT - Added logic to deal with discrepancies that might arise when a rollup # is occurring when the script is run. When that happens the "other" # storage value may be negative which causes the graph to not work. # 10/01/2009 CRT - Added Google Charts stuff to try to make it easier to see the status # quickly. # #Name or IP Address of the SMTP server to use to send the report $mailserver = "mail.company.com" #Array of people who should get the report. $reportRecipients=@('admin1@company.com','admin2@company.com','admin3@company.com'); #Short recipient list for debugging $reportRecipients=@('admin1@company.com'); #Email address to email the report as $ReportSender="replay@company.com"; #Array of expected count of recovery points by day # ex: $ExpectedRPCount=@(96,96,24,24,1,1,1); means we assume "today" will have 96 RPs(1 every 15 minutes), # yesterday(day 2) also would have 96, two days ago 24, three days ago 24, 5 days ago 1 etc... $expectedrpcount=@(96,96,96,96,96,24,24,24,24,24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1); #Full path to Replayc.exe executable. # check: https://support.appassure.com/ics/support/KBAnswer.asp?questionID=119 # for more info about the replayc.exe command $replay_exe='C:\program files (x86)\AppAssure Software\Replay\Replayc.exe' #Generate Debug Output $Debug_output=$true #Generate lots of debug output $Debug_Output_Verbose=$false #Create the empty log 'file' that we will email out. $LOG = "" #The base part of the URL for the graph of recovery points $RPGraphURL= "http://chart.apis.google.com/chart?chs=600x250&cht=bvg&chco=00FF00,FF0000&chm=D,FF0000,1,0,2,1&chf=bg,s,DDDDDD&chdl=RPs+Expected|RPs+Present&chdlp=b&chma=20,20,20,20&chbh=a&chxt=y,r&chd=t1:"; #The base part of the URL for the disk usage graph. $DiskGraphURL="http://chart.apis.google.com/chart?cht=p&chs=350x200&&chco=00FF00,FF0000,888888&chf=bg,s,DDDDDD&" ######################################################################################## # Get Size of files in specified subdirectory, optionally recursive (default is to # _NOT_ recurse ######################################################################################### Function Get-DirSize([string] $Path,[boolean]$recurse=$false){ if ($recurse) { $DirSizeBytes = Get-ChildItem $Path -recurse| measure-Object length -sum } else { $DirSizeBytes = Get-ChildItem $Path | measure-Object length -sum } Write-Host "DirSizeBytes($path)=[$DirSizeBytes]" [float]$DirSizeMB= $DirSizeBytes.Sum/(1024 * 1024) if ($Debug_output){Write-Host "Using $DirSizeMB MB"} [float]$DirSizeGB = $DirSizeMB/1024 if ($Debug_output){Write-Host "Using $DirSizeGB GB" } Write-Host "DirSizeGB($path)=[$DirSizeGB], recurse= $recurse" return $DirSizeGB } ######################################################################################## #Get Disk info about the Archive Disk. Get total used space, space used by repaly, # free space, etc. ######################################################################################## function Get-ProtectedServerDiskInfo($servername,$ArchivePAth){ #Let's get drive letter of where RPs are being stored. $ArchiveDrive = $ArchivePath.SubString(0,2) if ($Debug_output){ Write-Host "Drive is " $ArchiveDrive Write-Host "RPs stored in $ArchivePath" } #Let's get info about the size of the Archive Disk $tmpFilter = "driveletter='" + $ArchiveDrive + "'" $DriveInfo=Get-WmiObject Win32_Volume -filter $tmpFilter #Convert this to GB [float]$DiskSizeGB=[float]$DriveInfo.Capacity/(1024*1024*1024) #Get size of FreeSpace [float]$FreeDiskSpaceGB=[float]$DriveInfo.FreeSpace/(1024*1024*1024) #Find out how much total diskspace is in use [float]$UsedDiskSpaceGB= Get-DirSize ($ArchiveDrive+"\") $true #Size of the Replay RP directory [float]$ReplayDirSizeGB= Get-DirSize $ArchivePath #Size of non Replay Data #****Use Max function because there is a case where if this script is run during # a rollup $OtherDiskSizeGB can end up being a negative number. Not a big deal # ordinarily but will cause the Google Chart for disk usage to be incorrect since # it doesn't like negative numbers. [float]$OtherDiskSizeGB=[Math]::Max($UsedDiskSpaceGB-$ReplayDirSizeGB,1); $pctOfUsedGB= $ReplayDirSizeGB/$UsedDiskSpaceGB*100 $pctFree=[float]$DriveInfo.FreeSpace/[float]$DriveInfo.Capacity*100 $pctUsed=[float]$UsedDiskSpaceGB/[float]$DriveInfo.Capacity*100 if ($Debug_Output) { Write-Host "Pct Free= $pctFree" Write-Host "Pct Used= $pctUsed" Write-Host "Space Used= $UsedDiskSpaceGB GB" Write-Host "`tReplayDirSize= $ReplayDirSizeGB GB"; Write-Host "`tOtherUsed Space= $OtherDiskSizeGB"; Write-Host "Free Space= $FreeDiskSpaceGB"; Write-Host "Total Space = $DiskSizeGB GB" } Write-Host ("Server $servername snapshots are being stored on $ArchiveDrive and currently using {0,0:n2}GB" -f $ReplayDirSizeGB) Write-Host ("This is {0,0:n2}% of the used space({1,5:n2}GB) on the volume which is {2,5:n2}GB" -f $pctofUsedGB,$UsedDiskSpaceGB,$DiskSizeGB) Write-Host ("The drive currently has {0,5:n2}% free space (e.g. {1,0:n2}GB)" -f $pctFree,$FreeDiskSpaceGB) $script:log+="`n
Server $servername snapshots are being stored on $ArchiveDrive and currently using {0,0:n2}GB.`n " -f $ReplayDirSizeGB $script:LOG+="This is {0,0:n2}% of the used space({1,5:n2}GB) on the volume which is {2,5:n2}GB`n" -f $pctofUsedGB,$UsedDiskSpaceGB,$DiskSizeGB $script:LOG+="
The drive currently has {0,5:n2}% free space (e.g. {1,0:n2}GB)`n" -f $pctFree,$FreeDiskSpaceGB $script:Log+="
Number of reported Recovery Points is $numReportedRPs " } else { Write-Host"There is a discrepancy between reported # of Recovery Points ($numReportedRPs) and what I found ($numRPs)" $script:LOG+="
There is a discrepancy between reported # of Recovery Points ($numReportedRPs) and what I found ($numRPs)," } Write-Host ("of these $validRPs are valid, and $invalidRPs are invalid ({0,0:n2}%)." -f $validRPpct) Write-Host ("The most recent valid RP was taken $TimeDiffString ago") Write-Host ("The valid RPs span {0,0:n2} days" -f ($LastValidRP.Subtract($FirstValidRP)).TotalDays) $script:LOG+=("of these $validRPs are valid, and $invalidRPs are invalid ({0,0:n2}%).`n" -f $validRPpct) $script:LOG +=("The valid RPs span {0,0:n2} days`n" -f ($LastValidRP.Subtract($FirstValidRP)).TotalDays) $script:LOG+="
The most recent valid RP was taken $TimeDiffString ago`n" # If it's been more than 12 hours since last successful RP let's emphasize this in the email by coloring it red. If ($TimeDiff.TotalHours -gt 12 ){ Write-Host -Debug "Last Backup occurred " + $Timediff.TotalHours + " ago. This is more than 12 hours ago please check on the status of the server" $script:LOG+= "
Last Backup occurred " + $TimeDiff.TotalHours + " hours ago. This is more than 12 hours ago please check on the status of the server
`n" } if ($debug_output){ Write-Debug "#Info Lines $NumInfoLines" Write-Host "#RPs " $numrps Write-Host "# Reported RPs $numReportedRPs" Write-Host "#valid RPs" $validRps Write-Host "#invalid RPs" $invalidRps } #Let's build the graph URL Gen-RPStatusGraph($validRpsByDay); } ######################################################################################## #Function that sends the contents of $script:Log by mail to specified recipients. ######################################################################################## function Send-LogByMail(){ $SmtpClient = new-object system.net.mail.smtpClient $MailMessage = New-Object system.net.mail.mailmessage $SmtpClient.Host = $mailserver; $mailmessage.from = $ReportSender; foreach ($address in $reportRecipients){ $mailmessage.To.add($address) } $mailmessage.Subject = “Replay Status Report for $hostname @ $ScriptStartTime” $mailmessage.IsBodyHtml = 1 $mailmessage.Body = $Log $mailmessage.Headers.Add("message-id", "<3BD50098E401463AA228377848493927-1>") $smtpclient.Send($mailmessage) } ######################################################################################## # Begin MAIN ######################################################################################## if (! $debug_output) { $Debug_Output_Verbose = $false } $scriptStarttime = get-Date $hostname = $env:Computername $LOG = "Starting Script at $ScriptStartTime
`n" $svc_Status = (Get-Service -name ReplayServer64).Status if ($svc_Status -eq "Running" ) { $LOG += "Replay Service is running
`n" } else { $Log += "Replay server is not Running!
`n" } #Registry Key where Replay Info is supposed to be located $Replay_Key= "HKLM:\Software\AppAssure\ReplayEPS" #Get an array of the subkeys... should be one for each server being protected # ex: "HKLM:\Software\AppAssure\ReplayEPS\Mail01 $Keys = Get-ChildItem $Replay_Key #Let's iterate over the list of servers and get some info Foreach ($Key in $Keys) { Write-Host "#########################################################" if ($Debug_Output) {Write-Host "working on Key [$Key]"} #$Key.name is a value like: HKEY_LOCAL_MACHINE\Software\AppAssure\ReplayEPS\pr1-mail # so let's split it to get just the server name $tmparray=$Key.Name.Split("\") #Server's name Should be last element of the array $protectedserverName = $tmpArray[-1] if ($Debug_Output) {Write-Host $protectedserverName} $ArchivePath= $Key.GetValue("target_path") #Let's Report some info about the Archive Disk Get-ProtectedServerDiskInfo $protectedserverName $ArchivePath #Now lets report on RPs Get-RPStatus $hostname $protectedServerName #Send the report by mail Send-LogByMail }