204 lines
6.2 KiB
YAML
204 lines
6.2 KiB
YAML
id: backup-provision
|
|
namespace: automation
|
|
description: "Netbox → Ansible → Borg Backup Provisioning"
|
|
version: 1
|
|
|
|
triggers:
|
|
- id: daily-backup-sync
|
|
type: schedule
|
|
cron: "0 2 * * *" # Täglich 02:00 Uhr
|
|
timezone: "Europe/Berlin"
|
|
|
|
variables:
|
|
netbox_url: "https://netbox.mbo-tech-it.de"
|
|
netbox_api_token: "{{ secret('NETBOX_TOKEN') }}"
|
|
# Basis-TAG für automatische Backups (erforderlich)
|
|
backup_tag_base: "auto-backup"
|
|
# Optional: Weitere TAGs können hinzugefügt werden
|
|
# z.B. env:prod, tenant:kunde1, backup-server:primary
|
|
ansible_inventory_file: "/tmp/netbox_inventory.ini"
|
|
git_repo: "https://gitea.mbo-tech-it.de/claude/backup-automation.git"
|
|
|
|
tasks:
|
|
# Task 1: Netbox Abfrage - Alle Systems mit "auto-backup" TAG
|
|
- id: fetch-backup-systems
|
|
type: io.kestra.plugin.core.http.Request
|
|
uri: "{{ vars.netbox_url }}/api/dcim/devices/?tag={{ vars.backup_tag_base }}&limit=500"
|
|
headers:
|
|
Authorization: "Token {{ vars.netbox_api_token }}"
|
|
method: GET
|
|
|
|
# Task 2: Verarbeite Netbox Response
|
|
- id: parse-devices
|
|
type: io.kestra.plugin.core.script.Groovy
|
|
script: |
|
|
def response = json(tasks.fetchBackupSystems.body)
|
|
def devices = []
|
|
|
|
response.results.each { device ->
|
|
devices.add([
|
|
name: device.name,
|
|
ip: device.primary_ip4?.address?.split('/')[0] ?: null,
|
|
os: device.device_type?.manufacturer?.name ?: "unknown",
|
|
status: device.status?.value
|
|
])
|
|
}
|
|
|
|
// Filtern: nur active und mit IP
|
|
def activeDevices = devices.findAll { it.ip && it.status == 'active' }
|
|
|
|
kestra.logger.info("Found ${activeDevices.size()} devices for backup")
|
|
return activeDevices
|
|
|
|
# Task 3: Git-Repo pullen
|
|
- id: pull-backup-scripts
|
|
type: io.kestra.plugin.core.tasks.bash.BashScript
|
|
script: |
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
REPO_DIR="/tmp/backup-automation"
|
|
|
|
if [ -d "$REPO_DIR" ]; then
|
|
cd "$REPO_DIR"
|
|
git pull origin main
|
|
else
|
|
git clone {{ vars.git_repo }} "$REPO_DIR"
|
|
cd "$REPO_DIR"
|
|
fi
|
|
|
|
echo "Repo synced successfully"
|
|
exit 0
|
|
|
|
# Task 4: Generiere Ansible Inventory aus Netbox-Daten
|
|
- id: generate-ansible-inventory
|
|
type: io.kestra.plugin.core.script.Groovy
|
|
script: |
|
|
def devices = tasks.parseDevices.output
|
|
|
|
def inventory = """[all]
|
|
[backup_clients]
|
|
"""
|
|
|
|
devices.each { device ->
|
|
inventory += """${device.name} ansible_host=${device.ip} ansible_user=root
|
|
"""
|
|
}
|
|
|
|
inventory += """
|
|
[backup_clients:vars]
|
|
ansible_python_interpreter=/usr/bin/python3
|
|
backup_repo_server={BACKUP_SERVER_HOSTNAME}
|
|
backup_repo_base=/backup/repos
|
|
"""
|
|
|
|
// Schreibe zu Datei
|
|
new File('/tmp/netbox_inventory.ini').text = inventory
|
|
|
|
kestra.logger.info("Ansible inventory generated")
|
|
return true
|
|
|
|
# Task 5: Führe Ansible Playbook aus (parallel pro Host)
|
|
- id: run-ansible-playbook
|
|
type: io.kestra.plugin.core.tasks.bash.BashScript
|
|
script: |
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
cd /tmp/backup-automation
|
|
|
|
# Installiere Ansible + Netbox Module falls nötig
|
|
pip install -q ansible netaddr jinja2 &>/dev/null || true
|
|
|
|
# Führe Playbook aus
|
|
ansible-playbook \
|
|
-i {{ vars.ansible_inventory_file }} \
|
|
ansible/playbooks/install-borg-client.yaml \
|
|
-e "backup_repo_server={BACKUP_SERVER_HOSTNAME}" \
|
|
-e "backup_repo_base=/backup/repos" \
|
|
--diff
|
|
|
|
echo "Ansible playbook completed"
|
|
exit 0
|
|
|
|
# Task 6: Trigger Backup-Server Borg Repo Init (falls neu)
|
|
- id: initialize-backup-repos
|
|
type: io.kestra.plugin.core.tasks.bash.BashScript
|
|
script: |
|
|
#!/bin/bash
|
|
|
|
cd /tmp/backup-automation
|
|
|
|
# SSH zum Backup-Server
|
|
ssh -i ~/.ssh/id_ed25519 backup@{BACKUP_SERVER_HOSTNAME} << 'EOF'
|
|
source /home/backup/.bashrc
|
|
|
|
# Hole Device-Liste aus Netbox (nur Systems mit auto-backup TAG)
|
|
DEVICES=$(curl -s -H "Authorization: Token {{ vars.netbox_api_token }}" \
|
|
"{{ vars.netbox_url }}/api/dcim/devices/?tag={{ vars.backup_tag_base }}&limit=500" \
|
|
| jq -r '.results[].name')
|
|
|
|
for device in $DEVICES; do
|
|
REPO_PATH="/backup/repos/$device"
|
|
|
|
if [ ! -d "$REPO_PATH" ]; then
|
|
mkdir -p "$REPO_PATH"
|
|
borg init --encryption=repokey "$REPO_PATH"
|
|
echo "Initialized $REPO_PATH"
|
|
fi
|
|
done
|
|
EOF
|
|
|
|
exit 0
|
|
|
|
# Task 7: Trigger Backups auf allen Hosts
|
|
- id: trigger-backups
|
|
type: io.kestra.plugin.core.tasks.bash.BashScript
|
|
script: |
|
|
#!/bin/bash
|
|
|
|
DEVICES="{{ tasks.parseDevices.output | json }}"
|
|
|
|
echo "$DEVICES" | jq -r '.[] | .name' | while read device; do
|
|
kestra.logger.info "Triggering backup for $device..."
|
|
|
|
# SSH zum Host und starte systemd service
|
|
ssh -i ~/.ssh/id_ed25519 root@$device \
|
|
"systemctl start mbo-backup.service" 2>/dev/null || true
|
|
done
|
|
|
|
echo "Backup triggers sent"
|
|
exit 0
|
|
|
|
# Task 8: Status Reporting
|
|
- id: backup-status-report
|
|
type: io.kestra.plugin.core.script.Groovy
|
|
script: |
|
|
def devices = tasks.parseDevices.output
|
|
|
|
def report = """
|
|
╔══════════════════════════════════════════════════╗
|
|
║ BACKUP PROVISION REPORT ║
|
|
╠══════════════════════════════════════════════════╣
|
|
"""
|
|
|
|
report += "║ Total Devices Found: ${devices.size()}\n"
|
|
report += "║ Timestamp: ${new Date()}\n"
|
|
report += "║ Status: PROVISIONING INITIATED\n"
|
|
report += "╚══════════════════════════════════════════════════╝\n\n"
|
|
|
|
devices.each { device ->
|
|
report += "✓ ${device.name} (${device.ip})\n"
|
|
}
|
|
|
|
kestra.logger.info(report)
|
|
return report
|
|
|
|
outputs:
|
|
- id: device_count
|
|
type: STRING
|
|
value: "{{ tasks.parseDevices.output.size() }}"
|
|
- id: backup_report
|
|
type: STRING
|
|
value: "{{ tasks.backupStatusReport.output }}"
|