1+ <#
2+ . SYNOPSIS
3+ Sends Veeam ONE alerts to BigPanda via their API.
4+ . DESCRIPTION
5+ This script takes parameters from Veeam ONE alerting and formats them for BigPanda's API.
6+ It includes debug logging to a file for troubleshooting.
7+ . PARAMETER AlarmName
8+ The name of the alarm.
9+
10+ . PARAMETER NodeName
11+ The name of the node.
12+
13+ . PARAMETER Summary
14+ A brief summary of the alarm.
15+
16+ . PARAMETER AlarmTime
17+ The time the alarm was triggered.
18+
19+ . PARAMETER AlarmStatus
20+ The current status of the alarm.
21+
22+ . PARAMETER PreviousStatus
23+ The previous status of the alarm.
24+
25+ . PARAMETER AlarmID
26+ The unique identifier for the alarm.
27+
28+ . PARAMETER ChildObjectType
29+ The type of the child object associated with the alarm.
30+ . EXAMPLE
31+ .\VeeamBigPandaAlerting.ps1 -AlarmName "Disk Space Low" -NodeName "Server01" -Summary "Disk space on C: drive is below threshold." -AlarmTime "10/1/2025 10:59:03 AM" -AlarmStatus "Error" -PreviousStatus "Warning" -AlarmID "12345" -ChildObjectType "Disk"
32+ This example sends a "Disk Space Low" alert for "Server01" to BigPanda.
33+ . NOTES
34+ This script is best adapted by adding the "Run Script" action to the desired Alarm(s) in the Notification settings of Veeam ONE.
35+ Ensure that the script has the necessary permissions to execute and access the network.
36+
37+ REQUIRED ENVIRONMENT VARIABLES:
38+ - BIGPANDA_APP_KEY: Your BigPanda application key
39+ - BIGPANDA_AUTH_TOKEN: Your BigPanda authentication token
40+
41+ Suggested values:
42+ Action = Run Script
43+ Value = powershell.exe VeeamBigPandaAlerting.ps1 '%1' '%2' '%3' '%4' '%5' '%6' '%7' '%8'
44+ Condition = Any State
45+
46+ Author: Adam Congdon
47+ Date: 2024-10-01
48+
49+ # Adjust the following variables with your BigPanda API credentials and endpoint
50+ $webhookUrl = "https://api.bigpanda.io/data/v2/alerts"
51+
52+
53+ With a special thanks to GitHub Copilot for assistance in debug logging implementation.
54+
55+ #>
56+
57+
58+
59+ param (
60+ [string ]$AlarmName ,
61+ [string ]$NodeName ,
62+ [string ]$Summary ,
63+ [string ]$AlarmTime ,
64+ [string ]$AlarmStatus ,
65+ [string ]$PreviousStatus ,
66+ [string ]$AlarmID ,
67+ [string ]$ChildObjectType
68+
69+ )
70+
71+ # OIM
72+ $appKey = $env: BIGPANDA_APP_KEY
73+ $authToken = $env: BIGPANDA_AUTH_TOKEN
74+
75+ if (-not $appKey -or -not $authToken ) {
76+ Write-DebugLog " ERROR: BigPanda credentials not found in environment variables"
77+ Write-Error " Please set BIGPANDA_APP_KEY and BIGPANDA_AUTH_TOKEN environment variables"
78+ exit 1
79+ }
80+ Write-DebugLog " API credentials configured (OIM environment)"
81+
82+
83+ # Debug logging setup
84+
85+ $timestamp = Get-Date - Format " yyyyMMdd_HHmmss"
86+
87+ $logFile = " C:\temp\PandaDebug_$timestamp .log"
88+
89+ # Ensure the temp directory exists
90+
91+ if (! (Test-Path " C:\temp" )) {
92+ New-Item - ItemType Directory - Path " C:\temp" - Force
93+ }
94+
95+ # Function to write debug log
96+
97+ function Write-DebugLog {
98+ param ([string ]$Message )
99+ $logEntry = " $ ( Get-Date - Format ' yyyy-MM-dd HH:mm:ss' ) - $Message "
100+ Add-Content - Path $logFile - Value $logEntry
101+ Write-Output $logEntry
102+ }
103+
104+ Write-DebugLog " Script started with parameters:"
105+ Write-DebugLog " AlarmName: $AlarmName "
106+ Write-DebugLog " NodeName: $NodeName "
107+ Write-DebugLog " Summary: $Summary "
108+ Write-DebugLog " AlarmTime: $AlarmTime "
109+ Write-DebugLog " AlarmStatus: $AlarmStatus "
110+ Write-DebugLog " PreviousStatus: $PreviousStatus "
111+ Write-DebugLog " AlarmID: $AlarmID "
112+ Write-DebugLog " ChildObjectType: $ChildObjectType "
113+ Write-DebugLog " Original AlarmStatus: $AlarmStatus "
114+
115+
116+ # Map alarm statuses to BigPanda status values
117+ if ($AlarmStatus -eq " Error" ) {
118+ $AlarmStatus = " critical"
119+ }
120+
121+ elseif ($AlarmStatus -eq " Acknowledged" ) {
122+ $AlarmStatus = " warning-suspect"
123+ }
124+
125+ elseif ($AlarmStatus -eq " Reset/resolved" ) {
126+ $AlarmStatus = " ok"
127+ }
128+
129+ elseif ($AlarmStatus -eq " Warning" ) {
130+ $AlarmStatus = " warning"
131+ }
132+
133+ Write-DebugLog " Mapped AlarmStatus: $AlarmStatus "
134+ $webhookUrl = " https://api.bigpanda.io/data/v2/alerts"
135+ Write-DebugLog " Webhook URL configured: $webhookUrl "
136+
137+ # Parse AlarmTime with explicit format, fallback to now if fails
138+
139+ Write-DebugLog " Parsing alarm time: $AlarmTime "
140+ $timestamp = 0
141+
142+ try {
143+ # Try multiple format patterns to handle different date formats
144+ $formats = @ (
145+ " M/d/yyyy h:mm:ss tt" , # 10/1/2025 10:59:03 AM
146+ " MM/dd/yyyy hh:mm:ss tt" , # 10/01/2025 10:59:03 AM
147+ " M/d/yyyy hh:mm.ss tt" , # 10/1/2025 10:59.03 AM
148+ " MM/dd/yyyy hh:mm.ss tt" # 10/01/2025 10:59.03 AM
149+ )
150+ $parsed = $false
151+
152+ foreach ($format in $formats ) {
153+ try {
154+ $dateTime = [datetime ]::ParseExact($AlarmTime , $format , $null )
155+ $dateTimeLocal = [DateTime ]::SpecifyKind($dateTime , [DateTimeKind ]::Local)
156+ $timestamp = [int ]([datetimeoffset ]$dateTimeLocal ).ToUnixTimeSeconds()
157+ Write-DebugLog " Successfully parsed alarm time using format '$format '. Unix timestamp: $timestamp (treated as UTC)"
158+ $parsed = $true
159+ break
160+ }
161+
162+ catch {
163+ # Continue to next format
164+ }
165+
166+ }
167+
168+ if (-not $parsed ) {
169+ throw " No format matched"
170+
171+ }
172+ }
173+
174+ catch {
175+ $timestamp = [int ](Get-Date - UFormat % s)
176+ Write-DebugLog " Failed to parse alarm time with all formats, using current time. Unix timestamp: $timestamp . Error: $ ( $_.Exception.Message ) "
177+
178+ }
179+
180+ Write-DebugLog " Building request body..."
181+
182+ $body = @ {
183+ app_key = $appKey
184+ status = $AlarmStatus
185+ host = $NodeName
186+ check = $AlarmName
187+ description = $Summary
188+ timestamp = $timestamp
189+ primary_property = " host"
190+ PreviousStatus = $PreviousStatus
191+ AlarmID = $AlarmID
192+ ChildObjectType = $ChildObjectType
193+
194+ # custom = @{
195+
196+ # PreviousStatus = $PreviousStatus
197+
198+ # AlarmID = $AlarmID
199+
200+ # ChildObjectType = $ChildObjectType
201+
202+ # }
203+
204+ } | ConvertTo-Json
205+
206+ Write-DebugLog " Request body created:"
207+
208+ Write-DebugLog $body
209+
210+ $headers = @ {
211+
212+ Authorization = " Bearer $authToken "
213+
214+ " Content-Type" = " application/json"
215+
216+ }
217+
218+ Write-DebugLog " Headers configured for API request"
219+
220+ Write-DebugLog " Sending request to BigPanda API..."
221+
222+ try {
223+
224+ # $response = Invoke-RestMethod -Uri $webhookUrl -Method Post -Headers $headers -Body $body
225+
226+ $response = Invoke-WebRequest - Uri $webhookUrl - Method Post - Headers $headers - Body $body
227+
228+ Write-DebugLog " Alert sent successfully. Status Code: $ ( $response.StatusCode ) "
229+
230+ Write-DebugLog " Response Content: $ ( $response.Content ) "
231+
232+ Write-Output " Alert sent successfully: $ ( $response ) "
233+
234+ }
235+
236+ catch {
237+
238+ Write-DebugLog " Failed to send alert to BigPanda. Error: $ ( $_.Exception.Message ) "
239+
240+ Write-DebugLog " Full Error Details: $ ( $_ | Out-String ) "
241+
242+ Write-Error " Failed to send alert to BigPanda: $_ "
243+
244+ }
245+
246+ Write-DebugLog " Script execution completed"
247+ Write-DebugLog " Log file location: $logFile "
0 commit comments