#!/bin/bash
#
# Oracle Backup Monitor for Proxmox with PVE::Notify
# Monitors Oracle backups and sends notifications via Proxmox notification system
#
# Location: /opt/scripts/oracle-backup-monitor-proxmox.sh (on Proxmox host)
# Schedule: Add to cron for daily execution
#
# This script is SELF-SUFFICIENT:
# - Automatically creates notification templates if they don't exist
# - Uses Proxmox native notification system (same as HA alerts)
# - No email configuration needed - uses existing Proxmox setup
#
# Installation:
# cp oracle-backup-monitor-proxmox.sh /opt/scripts/
# chmod +x /opt/scripts/oracle-backup-monitor-proxmox.sh
# /opt/scripts/oracle-backup-monitor-proxmox.sh --install # Creates templates
# crontab -e # Add: 0 9 * * * /opt/scripts/oracle-backup-monitor-proxmox.sh
#
# Author: Claude (based on ha-monitor.sh pattern)
# Version: 1.0
set -euo pipefail
# Configuration
PRIMARY_HOST="10.0.20.36"
PRIMARY_PORT="22122"
PRIMARY_USER="Administrator"
BACKUP_PATH="/mnt/pve/oracle-backups/ROA/autobackup"
MAX_FULL_AGE_HOURS=25
MAX_CUMULATIVE_AGE_HOURS=7
TEMPLATE_DIR="/usr/share/pve-manager/templates/default"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Function to create notification templates
create_templates() {
echo -e "${GREEN}Creating Oracle backup notification templates...${NC}"
# Create templates directory if needed
mkdir -p "$TEMPLATE_DIR"
# Subject template
cat > "$TEMPLATE_DIR/oracle-backup-subject.txt.hbs" <<'EOF'
Oracle Backup {{severity}} - {{node}}
EOF
# Text body template
cat > "$TEMPLATE_DIR/oracle-backup-body.txt.hbs" <<'EOF'
Oracle Backup Monitoring Alert
==============================
Severity: {{severity}}
Hostname: {{node}}
Date: {{date}}
Status: {{status}}
{{#if errors}}
ERRORS:
{{#each errors}}
- {{this}}
{{/each}}
{{/if}}
{{#if warnings}}
WARNINGS:
{{#each warnings}}
- {{this}}
{{/each}}
{{/if}}
Backup Details:
- Total Backups: {{total_backups}}
- Total Size: {{total_size_gb}} GB
- FULL Backup Age: {{full_backup_age}} hours
- CUMULATIVE Backup Age: {{cumulative_backup_age}} hours
- Disk Usage: {{disk_usage}}%
{{#if backup_list}}
Recent Backups:
{{#each backup_list}}
{{this}}
{{/each}}
{{/if}}
EOF
# HTML body template
cat > "$TEMPLATE_DIR/oracle-backup-body.html.hbs" <<'EOF'
Status: {{status}}
{{#if errors}}
Errors:
{{#each errors}}
- {{this}}
{{/each}}
{{/if}}
{{#if warnings}}
Warnings:
{{#each warnings}}
- {{this}}
{{/each}}
{{/if}}
Backup Metrics
Total Backups
{{total_backups}}
Total Size
{{total_size_gb}} GB
Disk Usage
{{disk_usage}}%
| Backup Type |
Age (hours) |
Status |
| FULL |
{{full_backup_age}} |
{{#if full_backup_ok}}✓ OK{{else}}✗ Too Old{{/if}} |
| CUMULATIVE |
{{cumulative_backup_age}} |
{{#if cumulative_backup_ok}}✓ OK{{else}}⚠ Check{{/if}} |
{{#if backup_list}}
Recent Backups
{{#each backup_list}}{{this}}
{{/each}}
{{/if}}
EOF
echo -e "${GREEN}Templates created successfully in $TEMPLATE_DIR${NC}"
}
# Function to send notification via PVE::Notify
send_pve_notification() {
local severity="$1"
local status="$2"
local data="$3"
# Create Perl script to call PVE::Notify
cat > /tmp/oracle-notify.pl <<'PERL_SCRIPT'
#!/usr/bin/perl
use strict;
use warnings;
use PVE::Notify;
use JSON;
my $json_data = do { local $/; };
my $data = decode_json($json_data);
my $severity = $data->{severity} // 'info';
my $template_name = 'oracle-backup';
# Add fields for matching rules
my $fields = {
type => 'oracle-backup',
severity => $severity,
hostname => $data->{hostname},
};
# Send notification
eval {
PVE::Notify::notify(
$severity,
$template_name,
$data,
$fields
);
};
if ($@) {
print "Error sending notification: $@\n";
exit 1;
}
print "Notification sent successfully\n";
PERL_SCRIPT
chmod +x /tmp/oracle-notify.pl
# Send notification
echo "$data" | perl /tmp/oracle-notify.pl
rm -f /tmp/oracle-notify.pl
}
# Function to check backups
check_backups() {
local status="OK"
local errors=()
local warnings=()
echo "Checking Oracle backups..."
# Get backup list
local backup_files=$(ls -lth "$BACKUP_PATH"/*.BKP 2>/dev/null | head -10 || echo "")
if [ -z "$backup_files" ]; then
status="ERROR"
errors+=("No backup files found in $BACKUP_PATH")
else
# Count backups
local total_backups=$(ls "$BACKUP_PATH"/*.BKP 2>/dev/null | wc -l)
local total_size=$(du -shc "$BACKUP_PATH"/*.BKP 2>/dev/null | tail -1 | awk '{print $1}')
# Check FULL backup age
local latest_full=$(ls -t "$BACKUP_PATH"/*FULL*.BKP 2>/dev/null | head -1 || echo "")
local full_age_hours="N/A"
local full_backup_ok=false
if [ -n "$latest_full" ]; then
local full_timestamp=$(stat -c %Y "$latest_full")
local current_timestamp=$(date +%s)
full_age_hours=$(( (current_timestamp - full_timestamp) / 3600 ))
if [ "$full_age_hours" -gt "$MAX_FULL_AGE_HOURS" ]; then
status="WARNING"
warnings+=("FULL backup is $full_age_hours hours old (threshold: $MAX_FULL_AGE_HOURS)")
else
full_backup_ok=true
fi
else
status="ERROR"
errors+=("No FULL backup found")
fi
# Check CUMULATIVE backup age
local latest_cumulative=$(ls -t "$BACKUP_PATH"/*INCR*.BKP "$BACKUP_PATH"/*CUMULATIVE*.BKP 2>/dev/null | head -1 || echo "")
local cumulative_age_hours="N/A"
local cumulative_backup_ok=false
if [ -n "$latest_cumulative" ]; then
local cumulative_timestamp=$(stat -c %Y "$latest_cumulative")
local current_timestamp=$(date +%s)
cumulative_age_hours=$(( (current_timestamp - cumulative_timestamp) / 3600 ))
if [ "$cumulative_age_hours" -gt "$MAX_CUMULATIVE_AGE_HOURS" ]; then
if [ "$status" != "ERROR" ]; then status="WARNING"; fi
warnings+=("CUMULATIVE backup is $cumulative_age_hours hours old (threshold: $MAX_CUMULATIVE_AGE_HOURS)")
else
cumulative_backup_ok=true
fi
fi
# Check disk usage
local disk_usage=$(df "$BACKUP_PATH" | tail -1 | awk '{print int($5)}')
if [ "$disk_usage" -gt 90 ]; then
status="ERROR"
errors+=("Disk usage critical: ${disk_usage}%")
elif [ "$disk_usage" -gt 80 ]; then
if [ "$status" != "ERROR" ]; then status="WARNING"; fi
warnings+=("Disk usage high: ${disk_usage}%")
fi
# Prepare notification data
local severity="info"
[ "$status" = "WARNING" ] && severity="warning"
[ "$status" = "ERROR" ] && severity="error"
# Convert arrays to JSON arrays
local errors_json=$(printf '%s\n' "${errors[@]}" | jq -R . | jq -s .)
local warnings_json=$(printf '%s\n' "${warnings[@]}" | jq -R . | jq -s .)
local backup_list_json=$(echo "$backup_files" | head -5 | jq -R . | jq -s .)
# Create JSON data
local json_data=$(cat < Notifications > Add matching rules for 'oracle-backup'"
;;
--help)
echo "Oracle Backup Monitor for Proxmox"
echo "Usage:"
echo " $0 - Check backups and send alerts if issues found"
echo " $0 --install - Create notification templates"
echo " $0 --help - Show this help"
;;
*)
# Check if templates exist, create if missing
if [ ! -f "$TEMPLATE_DIR/oracle-backup-subject.txt.hbs" ]; then
echo -e "${YELLOW}Templates not found, creating...${NC}"
create_templates
echo ""
fi
# Run backup check
check_backups
;;
esac
}
# Check dependencies
if ! command -v jq &> /dev/null; then
echo -e "${RED}Error: jq is not installed${NC}"
echo "Install with: apt-get install jq"
exit 1
fi
main "$@"