diff --git a/LibreNMS/Snmptrap/Handlers/VeeamBackupJobCompleted.php b/LibreNMS/Snmptrap/Handlers/VeeamBackupJobCompleted.php new file mode 100644 index 0000000000..dda7107def --- /dev/null +++ b/LibreNMS/Snmptrap/Handlers/VeeamBackupJobCompleted.php @@ -0,0 +1,31 @@ +getOidData('VEEAM-MIB::backupJobName'); + $comment = $trap->getOidData('VEEAM-MIB::backupJobComment'); + + if ($trap->getOidData('VEEAM-MIB::backupJobResult') == 'Success') { + Log::event('SNMP Trap: Backup Job success - ' . $name . ' ' . $comment, $device->device_id, 'backup', 1); + } else { + Log::event('SNMP Trap: Backup Job failed - ' . $name . ' ' . $comment, $device->device_id, 'backup', 5); + } + } +} diff --git a/LibreNMS/Snmptrap/Handlers/VeeamVmBackupJobCompleted.php b/LibreNMS/Snmptrap/Handlers/VeeamVmBackupJobCompleted.php new file mode 100644 index 0000000000..df2e6f83e7 --- /dev/null +++ b/LibreNMS/Snmptrap/Handlers/VeeamVmBackupJobCompleted.php @@ -0,0 +1,31 @@ +getOidData('VEEAM-MIB::backupJobName'); + $comment = $trap->getOidData('VEEAM-MIB::vmName'); + + if ($trap->getOidData('VEEAM-MIB::vmBackupResult') == 'Success') { + Log::event('SNMP Trap: VM Backup success - ' . $name . ' ' . $comment, $device->device_id, 'backup', 1); + } else { + Log::event('SNMP Trap: VM Backup failed - ' . $name . ' ' . $comment, $device->device_id, 'backup', 5); + } + } +} diff --git a/config/snmptraps.php b/config/snmptraps.php index e62b5eccf4..3285b4843c 100644 --- a/config/snmptraps.php +++ b/config/snmptraps.php @@ -103,5 +103,7 @@ return [ 'OSPF-TRAP-MIB::ospfIfStateChange' => \LibreNMS\Snmptrap\Handlers\OspfIfStateChange::class, 'OSPF-TRAP-MIB::ospfNbrStateChange' => \LibreNMS\Snmptrap\Handlers\OspfNbrStateChange::class, 'UPS-MIB::upsTraps.0.1' => \LibreNMS\Snmptrap\Handlers\UpsTrapsOnBattery::class, + 'VEEAM-MIB::onBackupJobCompleted' => \LibreNMS\Snmptrap\Handlers\VeeamBackupJobCompleted::class, + 'VEEAM-MIB::onVmBackupJobCompleted' => \LibreNMS\Snmptrap\Handlers\VeeamVmBackupJobCompleted::class, ], ]; diff --git a/mibs/veeam/VEEAM-MIB b/mibs/veeam/VEEAM-MIB new file mode 100644 index 0000000000..691205a416 --- /dev/null +++ b/mibs/veeam/VEEAM-MIB @@ -0,0 +1,403 @@ + +VEEAM-MIB DEFINITIONS ::= BEGIN + +IMPORTS + enterprises + FROM RFC1155-SMI + TRAP-TYPE + FROM RFC-1215 + OBJECT-TYPE + FROM RFC-1212 + DisplayString + FROM RFC1213-MIB; + +veeam OBJECT IDENTIFIER ::= { enterprises 31023 } +products OBJECT IDENTIFIER ::= { veeam 1 } +backup OBJECT IDENTIFIER ::= { products 1 } +traps OBJECT IDENTIFIER ::= { backup 1 } + +onBackupJobCompleted TRAP-TYPE + ENTERPRISE traps + VARIABLES { backupJobId, backupJobName, backupJobResult, backupJobComment } + DESCRIPTION + "This trap is sent on backup/replica job completed." + ::= 1 + +onVmBackupCompleted TRAP-TYPE + ENTERPRISE traps + VARIABLES { backupJobName, vmName, sourceHostName, vmBackupResult, vmBackupComment } + DESCRIPTION + "This trap is sent on vm backup/replica completed." + ::= 2 + +onLinuxFLRMountStarted TRAP-TYPE + ENTERPRISE traps + VARIABLES { sessionId, initiatorName, initiatorSid, vmName, vmRestorePointId, vmRestorePointCreationTime } + DESCRIPTION + "This trap is sent when Multi-OS FLR helper appliance starts." + ::= 3 + +onLinuxFLRCopyToStarted TRAP-TYPE + ENTERPRISE traps + VARIABLES { sessionId, initiatorName, initiatorSid, vmName, vmRestorePointId, vmRestorePointCreationTime, targetHost, targetDir } + DESCRIPTION + "This trap is sent when Multi-OS FLR file recovery via Copy To operation is initiated." + ::= 4 + +onLinuxFLRToOriginalStarted TRAP-TYPE + ENTERPRISE traps + VARIABLES { sessionId, initiatorName, initiatorSid, vmName, vmRestorePointId, vmRestorePointCreationTime } + DESCRIPTION + "This trap is sent when Multi-OS FLR file recovery via Restore operation is initiated." + ::= 5 + +onLinuxFLRCopyToFinished TRAP-TYPE + ENTERPRISE traps + VARIABLES { sessionId, initiatorName, initiatorSid, vmName, vmRestorePointId, vmRestorePointCreationTime, transferStatus, transferTime, transferFileList, notTransferFileList, targetHost, targetDir, csvReportFilePath } + DESCRIPTION + "This trap is sent when Multi-OS FLR file recovery via Copy To operation is completed." + ::= 6 + +onLinuxFLRToOriginalFinished TRAP-TYPE + ENTERPRISE traps + VARIABLES { sessionId, initiatorName, initiatorSid, vmName, vmRestorePointId, vmRestorePointCreationTime, transferStatus, transferTime, transferFileList, notTransferFileList, csvReportFilePath } + DESCRIPTION + "This trap is sent when Multi-OS FLR file recovery via Restore operation is completed." + ::= 7 + +onWinFLRMountStarted TRAP-TYPE + ENTERPRISE traps + VARIABLES { initiatorName, initiatorSid, vmName, vmRestorePointCreationTime, vmRestorePointId, mountServerName } + DESCRIPTION + "This trap is sent when Windows FLR starts to mounts a backup." + ::= 8 + +onWinFLRToOriginalStarted TRAP-TYPE + ENTERPRISE traps + VARIABLES { initiatorName, initiatorSid, vmName, vmRestorePointId, vmRestorePointCreationTime } + DESCRIPTION + "This trap is sent when Windows FLR file recovery via Restore operation is completed." + ::= 9 + +onWinFLRCopyToStarted TRAP-TYPE + ENTERPRISE traps + VARIABLES { initiatorName, initiatorSid, vmName, vmRestorePointId, vmRestorePointCreationTime, targetDir } + DESCRIPTION + "This trap is sent when Windows FLR file recovery via Copy To operation is initiated." + ::= 10 + +onWinFLRToOriginalFinished TRAP-TYPE + ENTERPRISE traps + VARIABLES { initiatorName, initiatorSid, vmName, vmRestorePointId, vmRestorePointCreationTime, transferStatus, transferFileList, notTransferFileList, csvReportFilePath } + DESCRIPTION + "This trap is sent when Windows FLR file recovery via Restore operation is completed." + ::= 11 + +onWinFLRCopyToFinished TRAP-TYPE + ENTERPRISE traps + VARIABLES { initiatorName, initiatorSid, vmName, vmRestorePointId, vmRestorePointCreationTime, transferStatus, transferFileList, notTransferFileList, targetDir, csvReportFilePath } + DESCRIPTION + "This trap is sent when Windows FLR file recovery via Copy To operation is completed." + ::= 12 + +onWebDownloadStart TRAP-TYPE + ENTERPRISE traps + VARIABLES { initiatorName, initiatorSid, vmRestorePointId, vmName, vmRestorePointCreationTime } + DESCRIPTION + "This trap is sent when 1-Click FLR file download operation is initiated in the Enterprise Manager." + ::= 13 + +onWebDownloadFinished TRAP-TYPE + ENTERPRISE traps + VARIABLES { initiatorName, initiatorSid, vmRestorePointId, vmName, vmRestorePointCreationTime, transferStatus, transferFileList, notTransferFileList } + DESCRIPTION + "This trap is sent when 1-Click FLR file download operation is completed in the Enterprise Manager." + ::= 14 + +onSobrOffloadFinished TRAP-TYPE + ENTERPRISE traps + VARIABLES { repositoryId, repositoryName, repositoryStatus, extentStatusList } + DESCRIPTION + "This trap is sent when scale-out repository offload job is finished" + ::= 15 + +onCdpRpoReport TRAP-TYPE + ENTERPRISE traps + VARIABLES { cdpPolicyName, cdpRpoStatus, vmName, cdpSla, cdpRpoThreshold, cdpMaxDelay } + DESCRIPTION + "This trap is sent when CDP policy RPO status is changed" + ::= 16 + +backupJobId OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Backup job id" + ::= { backup 101 } + +backupJobName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Backup job name" + ::= { backup 102 } + +backupJobResult OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Backup job result" + ::= { backup 103 } + +backupJobComment OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Backup job comment" + ::= { backup 104 } + +vmName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "VM name." + ::= { backup 105 } + +sourceHostName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Source host name" + ::= { backup 106 } + +vmBackupResult OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "VM backup result" + ::= { backup 107 } + +vmBackupComment OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "VM backup comment" + ::= { backup 108 } + +sessionId OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Restore session ID" + ::= { backup 109 } + +initiatorName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Initiated by" + ::= { backup 110 } + +initiatorSid OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Initiated by (SID)" + ::= { backup 111 } + +vmRestorePointId OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Restore point ID" + ::= { backup 112 } + +vmRestorePointCreationTime OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Restore point creation time" + ::= { backup 113 } + +targetHost OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Target host" + ::= { backup 114 } + +targetDir OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Target directory" + ::= { backup 115 } + +transferStatus OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Restore result" + ::= { backup 116 } + +transferTime OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Restore time" + ::= { backup 117 } + +transferFileList OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Restored files" + ::= { backup 118 } + +notTransferFileList OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Failed to restore" + ::= { backup 119 } + +mountServerName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Mount server name" + ::= { backup 120 } + +repositoryId OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Scale-out repository ID" + ::= { backup 121 } + +repositoryName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Scale-out repository name" + ::= { backup 122 } + +repositoryStatus OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Scale-out repository status" + ::= { backup 123 } + +extentStatusList OBJECT-TYPE + SYNTAX SEQUENCE OF ExtentStatusEntry + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Scale-out repository extent status list" + ::= { backup 124 } + +extentStatusEntry OBJECT-TYPE + SYNTAX ExtentStatusEntry + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Scale-out repository extent status entry" + INDEX { extentName } + ::= { extentStatusList 1 } + +ExtentStatusEntry ::= + SEQUENCE { + extentName + DisplayString (SIZE (0..255)), + extentStatus + DisplayString (SIZE (0..255)) + } + +extentName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Scale-out repository extent name" + ::= { extentStatusEntry 1 } + +extentStatus OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Scale-out repository extent status" + ::= { extentStatusEntry 2 } + +csvReportFilePath OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "Path to CSV report file" + ::= { backup 125 } + +cdpPolicyName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "CDP policy name" + ::= { backup 126 } + +cdpRpoStatus OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "CDP RPO status" + ::= { backup 127 } + +cdpSla OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "CDP SLA" + ::= { backup 128 } + +cdpRpoThreshold OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "CDP RPO reporting threshold" + ::= { backup 129 } + +cdpMaxDelay OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "CDP RPO max delay" + ::= { backup 130 } +END diff --git a/tests/Feature/SnmpTraps/VeeamTrapTest.php b/tests/Feature/SnmpTraps/VeeamTrapTest.php new file mode 100644 index 0000000000..965b21d44c --- /dev/null +++ b/tests/Feature/SnmpTraps/VeeamTrapTest.php @@ -0,0 +1,77 @@ +create(); + + $trapText = "$device->hostname +UDP: [$device->ip]:46024->[1.1.1.1]:162 +DISMAN-EVENT-MIB::sysUpTimeInstance 4:13:08:37.60 +SNMPv2-MIB::snmpTrapOID.0 VEEAM-MIB::onBackupJobCompleted +VEEAM-MIB::backupJobId 7a1b3549-c4c7-4629-84d6-74e24fee8011 +VEEAM-MIB::backupJobName SureBackup Job 1 +VEEAM-MIB::sourceHostName hostname +VEEAM-MIB::vmBackupComment +VEEAM-MIB::backupJobResult Success"; + + $trap = new Trap($trapText); + + $message = 'SNMP Trap: Backup Job success - SureBackup Job 1 '; + Log::shouldReceive('event')->once()->with($message, $device->device_id, 'backup', 1); + + $this->assertTrue(Dispatcher::handle($trap), 'Could not handle VEEAM-MIB::traps'); + } + + public function testVeeamOnBackupCompletedFails(): void + { + $device = Device::factory()->create(); + + $trapText = "$device->hostname +UDP: [$device->ip]:46024->[1.1.1.1]:162 +DISMAN-EVENT-MIB::sysUpTimeInstance 4:13:08:37.60 +SNMPv2-MIB::snmpTrapOID.0 VEEAM-MIB::onBackupJobCompleted +VEEAM-MIB::backupJobId 7a1b3549-c4c7-4629-84d6-74e24fee8011 +VEEAM-MIB::backupJobName SureBackup Job 1 +VEEAM-MIB::sourceHostName hostname +VEEAM-MIB::vmBackupComment +VEEAM-MIB::vmBackupResult Failed"; + + $trap = new Trap($trapText); + + $message = 'SNMP Trap: Backup Job failed - SureBackup Job 1 '; + Log::shouldReceive('event')->once()->with($message, $device->device_id, 'backup', 5); + + $this->assertTrue(Dispatcher::handle($trap), 'Could not handle VEEAM-MIB::traps'); + } + + public function testVeeamOnVmBackupCompleted(): void + { + $device = Device::factory()->create(); + + $trapText = "$device->hostname +UDP: [$device->ip]:46024->[1.1.1.1]:162 +DISMAN-EVENT-MIB::sysUpTimeInstance 4:13:08:37.60 +SNMPv2-MIB::snmpTrapOID.0 VEEAM-MIB::onVmBackupJobCompleted +VEEAM-MIB::backupJobName Linux taeglich low +VEEAM-MIB::vmName vmname1 +VEEAM-MIB::sourceHostName hostname +VEEAM-MIB::vmBackupComment +VEEAM-MIB::vmBackupResult Success"; + + $trap = new Trap($trapText); + + $message = 'SNMP Trap: VM Backup success - Linux taeglich low vmname1'; + Log::shouldReceive('event')->once()->with($message, $device->device_id, 'backup', 1); + + $this->assertTrue(Dispatcher::handle($trap), 'Could not handle VEEAM-MIB::traps'); + } +}