mirror of
https://github.com/netinvent/npbackup.git
synced 2025-09-07 13:35:16 +08:00
Update KVM backup example
This commit is contained in:
parent
bce50453b0
commit
297eceb168
2 changed files with 89 additions and 84 deletions
|
@ -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
|
||||
|
|
|
@ -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}
|
Loading…
Add table
Reference in a new issue