#
.SYNOPSIS
PRTG Sensor script to monitor a Veeam Backup & Replication environment
THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE
RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
.DESCRIPTION
.PARAMETER PrtgDevice
Name des Servers, auf dem die NoSpamProxy Intranet Rolle installiert ist.
.PARAMETER VeeamBRJobName
Name des Jobs, der innerhalb von Veeam Backup & Replication abgefragt werden soll.
.INPUTS
None
.OUTPUTS
Output exit code and a description
.NOTES
File: paessler-prtg_monitor-veeam-backupand-replication-job.ps1
Version: 1.3
Author: Daniel Wydler
Creation Date: 10.03.2019, 10:54 Uhr
Purpose/Change:
Date Comment
-----------------------------------------------
10.03.2019, 10:54 Uhr Initial community release
18.09.2019, 21:39 Uhr Code base revised
19.09.2019, 00:11 Uhr Added informations to the header
27.09.2019, 09:49 Uhr Fixed query of JobId
31.01.2021, 12:19 Uhr Added parameter to Set-PrtgResult
31.01.2021, 13:45 Uhr Fixed if query in Set-PrtgResult
31.01.2021, 17:23 Uhr Code base revised
27.03.2021, 19:45 Uhr Added Connection test for remote computer
27.03.2021, 20:03 Uhr Fixed error handling in Invoke-Command
27.03.2021, 20:22 Uhr Fixed query for computer backup jobs
28.03.2021, 18;44 Uhr Fixed query for computer backup jobs
28.03.2021, 18:54 Uhr Fixed evaluation of job status
06.01.2022, 16:33 Uhr Changed Veeam PsSnapIn to Import-Module
.COMPONENT
Veeam Backup & Replication Powershell-Module
.LINK
www.vmbaggum.nl/2015/03/monitor-veeam-backup-jobs-with-prtg/
github.com/dwydler/Powershell-Skripte/blob/master/Paessler/PRTG/paessler-prtg_monitor-veeam-backupand-replication-job.ps1
.EXAMPLE
.\paessler-prtg_monitor-veeam-backupand-replication-job.ps1 -PrtgDevice "localhost" -VeeamBRJobName "Job1"
.\paessler-prtg_monitor-veeam-backupand-replication-job.ps1 "localhost" "Job1"
#>
#---------------------------------------------------------[Initialisations]--------------------------------------------------------
Param (
[Parameter(
ValueFromPipelineByPropertyName,
Position=0,
Mandatory=$true
)]
[ValidateNotNullOrEmpty()]
[string] $PrtgDevice,
[Parameter(
ValueFromPipelineByPropertyName,
Position=1,
Mandatory=$true
)]
[ValidateNotNullOrEmpty()]
[string] $VeeamBRJobName
)
Clear-Host
#----------------------------------------------------------[Declarations]----------------------------------------------------------
[string] $strXmlOutput = ""
[System.Object] $objQueryResult = $null
#-----------------------------------------------------------[Functions]------------------------------------------------------------
function Set-PrtgError {
Param (
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$PrtgErrorText
)
$strXmlOutput = "`n"
$strXmlOutput += "`t1`n"
$strXmlOutput += "`t$PrtgErrorText`n"
$strXmlOutput += ""
# Output Xml
$strXmlOutput
exit
}
function Set-PrtgResult {
Param (
[Parameter(mandatory=$True,Position=0)]
[string]$Channel,
[Parameter(mandatory=$True,Position=1)]
[string]$Value,
[Parameter(mandatory=$False,Position=2)]
[string]$Unit = "Custom",
[Parameter(mandatory=$False)]
[string]$CustomUnit,
[Parameter(mandatory=$False)]
[alias('mw')]
[string]$MaxWarn,
[Parameter(mandatory=$False)]
[alias('minw')]
[string]$MinWarn,
[Parameter(mandatory=$False)]
[alias('me')]
[string]$MaxError,
[Parameter(mandatory=$False)]
[alias('wm')]
[string]$WarnMsg,
[Parameter(mandatory=$False)]
[alias('em')]
[string]$ErrorMsg,
[Parameter(mandatory=$False)]
[alias('mo')]
[string]$Mode,
[Parameter(mandatory=$False)]
[alias('sc')]
[switch]$ShowChart,
[Parameter(mandatory=$False)]
[alias('ss')]
[ValidateSet('One','Kilo','Mega','Giga','Tera','Byte','KiloByte','MegaByte','GigaByte','TeraByte','Bit','KiloBit','MegaBit','GigaBit','TeraBit')]
[string]$SpeedSize,
[Parameter(mandatory=$False)]
[ValidateSet('One','Kilo','Mega','Giga','Tera','Byte','KiloByte','MegaByte','GigaByte','TeraByte','Bit','KiloBit','MegaBit','GigaBit','TeraBit')]
[string]$VolumeSize,
[Parameter(mandatory=$False)]
[ValidateSet('Second','Minute','Hour','Day')]
[string]$SpeedTime,
[Parameter(mandatory=$False)]
[alias('dm')]
[ValidateSet('Auto','All')]
[string]$DecimalMode,
[Parameter(mandatory=$False)]
[alias('w')]
[switch]$Warning,
[Parameter(mandatory=$False)]
[string]$ValueLookup
)
$StandardUnits = @('BytesBandwidth','BytesMemory','BytesDisk','Temperature','Percent','TimeResponse','TimeSeconds','Custom','Count','CPU','BytesFile','SpeedDisk','SpeedNet','TimeHours')
$LimitMode = $false
$Result = "`t`n"
$Result += "`t`t$Channel`n"
$Result += "`t`t$Value`n"
if ($StandardUnits -contains $Unit) {
$Result += "`t`t$Unit`n"
}
if ( ($Unit -eq "Custom") -and ($CustomUnit) ) {
$Result += "`t`t$CustomUnit`n"
}
if (!($Value -match "^\d+$")) { $Result += "`t`t1`n" }
if ($Mode) { $Result += "`t`t$Mode`n" }
if ($MaxWarn) { $Result += "`t`t$MaxWarn`n"; $LimitMode = $true }
if ($MinWarn) { $Result += "`t`t$MinWarn`n"; $LimitMode = $true }
if ($MaxError) { $Result += "`t`t$MaxError`n"; $LimitMode = $true }
if ($WarnMsg) { $Result += "`t`t$WarnMsg`n"; $LimitMode = $true }
if ($ErrorMsg) { $Result += "`t`t$ErrorMsg`n"; $LimitMode = $true }
if ($LimitMode) { $Result += "`t`t1`n" }
if ($SpeedSize) { $Result += "`t`t$SpeedSize`n" }
if ($VolumeSize) { $Result += "`t`t$VolumeSize`n" }
if ($SpeedTime) { $Result += "`t`t$SpeedTime`n" }
if ($DecimalMode) { $Result += "`t`t$DecimalMode`n" }
if ($Warning) { $Result += "`t`t1`n" }
if ($ValueLookup) { $Result += "`t`t$ValueLookup`n" }
if (!($ShowChart)) { $Result += "`t`t0`n" }
$Result += "`t`n"
return $Result
}
#------------------------------------------------------------[Modules]-------------------------------------------------------------
#-----------------------------------------------------------[Execution]------------------------------------------------------------
### Check if the remote device is reachable over PowerShell Remoting
If (-not (Test-NetConnection $PrtgDevice -port 5985 -InformationLevel Quiet)) {
Set-PrtgError "Gerät nicht erreichbar. PowerShell Remoting ativiert?"
}
### The following commands will be executed on the remote computer
$objQueryResult = Invoke-command –ComputerName $PrtgDevice -Args $VeeamBRJobName -ScriptBlock {
### Declarations
param(
[string] $strVeeamBackupJobName
)
[array] $aVBRSession=@()
[string] $strErrorMessage = $null
[string] $strTrace = $null
### Fuege das Veeam Powershell Module zu aktuellen Sitzung hinzu
try {
Import-Module Veeam.Backup.PowerShell -ErrorAction Stop
}
catch {
$strErrorMessage = $_.Exception.Message
$objReturnData = "" | Select-Object -Property strErrorMessage, strTrace
$objReturnData.strErrorMessage = $strErrorMessage
$objReturnData.strTrace = $strTrace
return $objReturnData
}
### Ueberpruefung, ob es bei dem Jobname um ein Computer Backup Objekt handelt.
if (Get-VBRComputerBackupJob -Name $strVeeamBackupJobName -ErrorAction SilentlyContinue) {
### Auslesen des letzten Ausfuehrungsergebnis vom dem angegebenen Veeam Backup Job
$strVeeamBackupJobId = Get-VBRComputerBackupJob -Name $strVeeamBackupJobName | Select -ExpandProperty Id
$aVBRSession = Get-VBRComputerBackupJobSession
$obVBRSession = $aVBRSession | Where-Object { $_.JobId -eq $strVeeamBackupJobId } | Sort -Descending -Property "CreationTime" | Select -First 1
}
# Ueberpruefung, ob es bei dem Jobname um ein Backup & Replication Entpoint Objekt handelt.
elseif (Get-VBREPJob -Name $strVeeamBackupJobName -ErrorAction SilentlyContinue) {
$strVeeamBackupJobId = Get-VBREPJob -Name $strVeeamBackupJobName | Select -ExpandProperty Id
$obVBRSession = Get-VBREPSession | Where-Object { $_.JobId -eq $strVeeamBackupJobId } | Sort -Descending -Property "CreationTime" | Select -First 1
}
### Ueberpruefung, ob es bei dem Jobname um ein Backup & Replication Objekt handelt.
elseif (Get-VBRJob -Name $strVeeamBackupJobName -ErrorAction SilentlyContinue) {
### Auslesen des letzten Ausfuehrungsergebnis vom dem angegebenen Veeam Backup Job
$strVeeamBackupJobId = Get-VBRJob -Name $strVeeamBackupJobName | Select -ExpandProperty Id
$obVBRSession = Get-VBRBackupSession | Where-Object { $_.JobId -eq $strVeeamBackupJobId } | Sort -Descending -Property "CreationTime" | Select -First 1
}
### If no previous condition matched
else {
$strErrorMessage = "Keinen Veeam Job mit dem Namen `"$strVeeamBackupJobName`" gefunden!"
$objReturnData = "" | Select-Object -Property strErrorMessage, strTrace
$objReturnData.strErrorMessage = $strErrorMessage
$objReturnData.strTrace = $strTrace
return $objReturnData
}
###
return $obVBRSession
}
### If an error occurred set prtg sensor to error state
### Else no error occurred the return values will be processed
If($objQueryResult.strErrorMessage) {
Set-PrtgError $objQueryResult.strErrorMessage
}
else {
###
switch ($objQueryResult.Result) {
"Success" { $intVeeamBackupJobResult = 0 }
"Warning" { $intVeeamBackupJobResult = 1 }
"Failed" { $intVeeamBackupJobResult = 2 }
"None" { $intVeeamBackupJobResult = 0 }
Default { $intVeeamBackupJobResult = 1 }
}
### Metadata des Veeam Backup Jobs in eine Variable einlesen
[xml] $xmlVeeamBackupJobAuxDetails = $objQueryResult.AuxData
### Generate PRTG Output
$xmlOutput = "`n"
$xmlOutput += "`n"
$xmlOutput += Set-PrtgResult -Channel "Job Result" -Value $intVeeamBackupJobResult -Unit Count -ShowChart -WarnMsg "Job wurde mit Warnungen ausgefuehrt." -ErrorMsg "Job wurde mit Fehler ausgefuehrt." -MaxWarn 0 -MaxError 1
if ($objQueryResult.EndTime -and $objQueryResult.CreationTime) {
$xmlOutput += Set-PrtgResult -Channel "LaufzeitHour" -Value $( ($objQueryResult.EndTime - $objQueryResult.CreationTime).Hours) -CustomUnit "Std." -ShowChart
$xmlOutput += Set-PrtgResult -Channel "LaufzeitMinutes" -Value $( ($objQueryResult.EndTime - $objQueryResult.CreationTime).Minutes) -CustomUnit "Min." -ShowChart
$xmlOutput += Set-PrtgResult -Channel "LaufzeitSeconds" -Value $( ($objQueryResult.EndTime - $objQueryResult.CreationTime).Seconds) -CustomUnit "Sek." -ShowChart
}
if ($xmlVeeamBackupJobAuxDetails.AuxData.CBackupstats.BackupSize) {
$xmlOutput += Set-PrtgResult -Channel "Job BackupSize" -Value ($xmlVeeamBackupJobAuxDetails.AuxData.CBackupstats.BackupSize) -VolumeSize GigaByte -ShowChart
}
if ($xmlVeeamBackupJobAuxDetails.AuxData.CBackupstats.DataSize) {
$xmlOutput += Set-PrtgResult -Channel "Job DataSize" -Value ($xmlVeeamBackupJobAuxDetails.AuxData.CBackupstats.DataSize) -VolumeSize GigaByte -ShowChart
}
if ($xmlVeeamBackupJobAuxDetails.AuxData.CBackupstats.DedupRatio) {
$xmlOutput += Set-PrtgResult -Channel "Job DedupRatio" -Value ($xmlVeeamBackupJobAuxDetails.AuxData.CBackupstats.DedupRatio) -ShowChart
}
if ($xmlVeeamBackupJobAuxDetails.AuxData.CBackupstats.CompressRatio) {
$xmlOutput += Set-PrtgResult -Channel "Job CompressRatio" -Value ($xmlVeeamBackupJobAuxDetails.AuxData.CBackupstats.CompressRatio) -ShowChart
}
if ($objQueryResult.CreationTime) {
$xmlOutput += "`tStart: "+ $(get-date $objQueryResult.CreationTime -Format "dd.MM.yyyy HH:mm:ss") +", Ende: "+ $(get-date $objQueryResult.EndTime -Format "dd.MM.yyyy HH:mm:ss") +"`n"
}
else {
$xmlOutput += "`tJob ist bisher nicht gelaufen.`n"
}
$xmlOutput += ""
### Return Xml
$xmlOutput
}