Update KVM backup example

This commit is contained in:
Orsiris de Jong 2024-11-03 10:10:55 +01:00
parent bce50453b0
commit 297eceb168
2 changed files with 89 additions and 84 deletions

View file

@ -4,32 +4,48 @@
# Have npbackup backup the qcow2 file + the xml file of the VM
# then have the script erase the snapshot
# Script ver 2024060401 for NPBackup V3
# Script ver 2024102902 for NPBackup V3
#TODO: remove xml modding after we tested latest snapshot remover
#TODO: support modding XML file from offline domains to remove snapshot and replace by backing file after qemu-img commit
# Expects repository version 2 to already exist
#TODO: npbackup doesn't know if snapshot creation failed
# - see if including $vm.SNAPSHOT_FAILED file helps
#TODO: blockcommit removes current snapshots, even if not done by cube
# - it's interesting to make housekeeping, let's make this an option
# List of machines
# All active machines by default, adding --all includes inactive machines
VMS=$(virsh list --name --all)
# Optional machine selection
# Optional manual machine selection
#VMS=(some.vm.local some.other.vm.local)
LOG_FILE="/var/log/cube_npv1.log"
LOG_FILE="/var/log/cube_npv2.log"
ROOT_DIR="/opt/cube"
BACKUP_IDENTIFIER="CUBE-BACKUP-NP.$(date +"%Y%m%dT%H%M%S" --utc)"
BACKUP_FILE_LIST="${ROOT_DIR}/npbackup_cube_file.lst"
NPBACKUP_CONF_FILE_TEMPLATE="${ROOT_DIR}/npbackup.cube.template"
NPBACKUP_CONF_FILE="${ROOT_DIR}/npbackup-cube.conf"
NPBACKUP_EXECUTABLE="/usr/local/bin/npbackup-cli/npbackup-cli"
NPBACKUP_CONF_FILE_TEMPLATE="${ROOT_DIR}/npbackup-cube.conf.template"
NPBACKUP_CONF_FILE="${ROOT_DIR}/npbackup-cube.conf"
# Superseed tenants if this is set, else it is extracted from machine name, eg machine.tenant.something
TENANT_OVERRIDE=netperfect
# default tenant if extraction of tenant name failed
DEFAULT_TENANT=netperfect
SCRIPT_ERROR=false
function log {
local line="${1}"
local level="${2}"
echo "${line}" >> "${LOG_FILE}"
echo "${line}"
if [ "${level}" == "ERROR" ]; then
SCRIPT_ERROR=true
fi
}
function ArrayContains () {
@ -56,8 +72,11 @@ function create_snapshot {
# Ignore SC2068 here
# Add VM xml description from virsh
## At least use a umask
virsh dumpxml --security-info $vm > "${ROOT_DIR}/$vm.xml"
echo "${ROOT_DIR}/$vm.xml" >> "$BACKUP_FILE_LIST"
# Don't redirect direct virsh output or SELinux may complain that we cannot write with virsh context
xml=$(virsh dumpxml --security-info $vm || log "Failed to create XML file" "ERROR")
echo "${xml}" > "${ROOT_DIR}/${vm}.xml"
echo "${ROOT_DIR}/${vm}.xml" >> "$BACKUP_FILE_LIST"
# Get current disk paths
for disk_path in $(virsh domblklist $vm --details | grep file | grep disk | awk '{print $4}'); do
@ -78,7 +97,7 @@ function create_snapshot {
log "Failed to create snapshot for $vm with quiesce option. Trying without quiesce."
virsh snapshot-create-as $vm --name "${backup_identifier}" --description "${backup_identifier}.noquiesce" --atomic --disk-only >> "$LOG_FILE" 2>&1
if [ $? -ne 0 ]; then
log "Failed to create snapshot for $vm without quiesce option. Cannot backup that file."
log "Failed to create snapshot for $vm without quiesce option. Cannot backup that file." "ERROR"
echo "$vm.SNAPSHOT_FAILED" >> "$BACKUP_FILE_LIST"
else
CURRENT_VM_SNAPSHOT="${vm}"
@ -94,21 +113,25 @@ function create_snapshot {
}
function get_tenant {
# Optional extract a tenant name from a VM name. example. myvm.tenant.local returns tenant
local vm="${1}"
if [ ! -z "${TENANT_OVERRIDE}" ]; then
echo "${TENANT_OVERRIDE}"
return
fi
# $(NF-1) means last column -1
tenant=$(echo "${vm}" |awk -F'.' '{print $(NF-1)}')
# Special case for me
if [ "${tenant}" == "npf" ]; then
tenant="netperfect"
npf_tenant=$(echo ${vm} |awk -F'.' '{print $(NF-1)}')
if [ "${npf_tenant}" == "npf" ]; then
npf_tenant="netperfect"
fi
if [ -z "${npf_tenant}" ]; then
npf_tenant="${DEFAULT_TENANT}"
fi
# return this
if [ "${tenant}" != "" ]; then
echo "${tenant}"
else
echo "unknown_tenant"
fi
echo "${npf_tenant}"
}
function run_backup {
@ -128,10 +151,9 @@ function run_backup {
sed -i "s%### SOURCE ###%${BACKUP_FILE_LIST}%g" "${NPBACKUP_CONF_FILE}"
sed -i "s%### VM ###%${vm}%g" "${NPBACKUP_CONF_FILE}"
cd "$(dirname "$NPBACKUP_EXECUTABLE")"
"$NPBACKUP_EXECUTABLE" --config-file "${NPBACKUP_CONF_FILE}" --backup --force >> "$LOG_FILE" 2>&1
"${NPBACKUP_EXECUTABLE}" --config-file "${NPBACKUP_CONF_FILE}" --backup --force >> "$LOG_FILE" 2>&1
if [ $? -ne 0 ]; then
log "Backup failure"
log "Backup failure" "ERROR"
else
log "Backup success"
fi
@ -154,14 +176,17 @@ function remove_snapshot {
virsh blockcommit $vm "$disk_name" --active --pivot --verbose --delete >> "$LOG_FILE" 2>&1
else
log "Trying to offline blockcommit for $disk_name: $disk_path"
# -p = progress, we actually don't need that here
qemu-img commit -dp "$disk_path" >> "$LOG_FILE" 2>&1
log "Note that you will need to modify the XML manually"
# virsh snapshot delete will erase commited file if exist so we don't need to manually tamper with xml file
virsh snapshot-delete --current $vm
# TODO: test2
virsh dumpxml --inactive --security-info "$vm" > "${ROOT_DIR}/$vm.xml.temp"
sed -i "s%${backup_identifier}//g" "${ROOT_DIR}/$vm.xml.temp"
virsh define "${ROOT_DIR}/$vm.xml.temp"
rm -f "${ROOT_DIR}/$vm.xml.temp"
#virsh dumpxml --inactive --security-info "$vm" > "${ROOT_DIR}/$vm.xml.temp"
#sed -i "s%${backup_identifier}//g" "${ROOT_DIR}/$vm.xml.temp"
#virsh define "${ROOT_DIR}/$vm.xml.temp"
#rm -f "${ROOT_DIR}/$vm.xml.temp"
##TODO WE NEED TO UPDATE DISK PATH IN XML OF OFFLINE FILE
fi
@ -188,11 +213,13 @@ function remove_snapshot {
log "Deleting metadata from snapshot ${backup_identifier} for $vm"
virsh snapshot-delete $vm --snapshotname "${backup_identifier}" --metadata >> "$LOG_FILE" 2>&1
if [ $? -ne 0 ]; then
log "Cannot delete snapshot metadata for $vm: ${backup_identifier}"
log "Cannot delete snapshot metadata for $vm: ${backup_identifier}" "ERROR"
fi
else
log "Will not delete metadata from snapshot ${backup_identifier} for $vm"
fi
log "Delete former XML file"
rm -f "${ROOT_DIR}/${vm}.xml"
}
@ -206,8 +233,8 @@ function run {
log "Running backup for ${vm}"
SNAPSHOTS_PATHS=()
create_snapshot "${vm}" "${BACKUP_IDENTIFIER}"
tenant=$(get_tenant "${vm}")
run_backup "${tenant}" "${vm}"
npf_tenant=$(get_tenant "${vm}")
run_backup "${npf_tenant}" "${vm}"
if [ "${CURRENT_VM_SNAPSHOT}" != "" ]; then
remove_snapshot "${CURRENT_VM_SNAPSHOT}" "${BACKUP_IDENTIFIER}"
fi
@ -227,10 +254,22 @@ function main {
# Make sure we remove snapshots no matter what
trap 'cleanup' INT HUP TERM QUIT ERR EXIT
log "#### Running backup `date`" >> "$LOG_FILE" 2>&1
log "#### Make sure all template variables are encypted"
"${NPBACKUP_EXECUTABLE}" -c "${NPBACKUP_CONF_FILE_TEMPLATE}" --check-config-file
log "#### Running backup `date`"
[ ! -d "${ROOT_DIR}" ] && mkdir "${ROOT_DIR}"
run
if [ "${SCRIPT_ERROR}" == true ]; then
log "Backup operation failed."
else
log "Backup finished."
fi
# Prune old backups ?
# No, done remotely since we use --append-only
}
# SCRIPT ENTRY POINT
main
main

View file

@ -5,62 +5,26 @@ repos:
repo_group: default_group
backup_opts:
paths:
- ### SOURCE ###
tags:
- ### VM ###
- ### SOURCE ###
source_type: files_from_verbatim
compression: auto
use_fs_snapshot: false
ignore_cloud_files: true
exclude_caches: true
one_file_system: true
priority: low
excludes_case_ignore: false
exclude_files: []
exclude_patterns: []
exclude_files_larger_than: 0.0 KiB
additional_parameters:
additional_backup_only_parameters:
minimum_backup_size_error: 10.0 MiB
pre_exec_commands:
pre_exec_per_command_timeout: 3600
pre_exec_failure_is_fatal: false
post_exec_commands:
post_exec_per_command_timeout: 3600
post_exec_failure_is_fatal: false
post_exec_execute_even_on_backup_error: true
tags:
- ### VM ###
repo_opts:
repo_password:
repo_password_command:
minimum_backup_age: 1440
upload_speed: 800.0 Mib
download_speed: 0.0 Kib
backend_connections: 0
retention_policy:
last: 3
hourly: 72
daily: 30
weekly: 4
monthly: 12
yearly: 3
tags: []
keep_within: true
ntp_server:
prometheus:
backup_job: ### VM ###
group: ${MACHINE_GROUP}
env:
env_variables: {}
encrypted_env_variables: {}
name: default
retention_policy: {}
prometheus: {}
env: {}
groups:
default_group:
backup_opts:
paths: []
source_type:
stdin_from_command:
stdin_filename:
tags: []
compression: auto
use_fs_snapshot: true
use_fs_snapshot: false
ignore_cloud_files: true
exclude_caches: true
one_file_system: true
@ -101,28 +65,30 @@ groups:
keep_within: true
ntp_server:
prometheus:
backup_job: ${MACHINE_ID}
backup_job: ### VM ###
group: ${MACHINE_GROUP}
env:
env_variables: {}
encrypted_env_variables: {}
is_protected: false
identity:
machine_id: ${HOSTNAME}_${RANDOM}[4]
machine_group:
machine_group: SOME_ARBITRARY_GROUP_NAME
global_prometheus:
metrics: false
instance: ${MACHINE_ID}
destination:
instance: ### VM ###
destination:
http_username:
http_password:
additional_labels:
npf_tenant: ### TENANT ###
backup_type: vm
no_cert_verify: true
global_options:
auto_upgrade: false
auto_upgrade_interval: 10
auto_upgrade_server_url:
auto_upgrade_server_url:
auto_upgrade_server_username:
auto_upgrade_server_password:
auto_upgrade_host_identity: ${MACHINE_ID}
auto_upgrade_group: ${MACHINE_GROUP}
auto_upgrade_group: ${MACHINE_GROUP}