Difference between revisions of "KVM backup.sh"

From wikieduonline
Jump to navigation Jump to search
 
(8 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
https://gist.githubusercontent.com/maxim-gorkin/f0e8a2c01a93ca65ad2ad10566a78d72/raw/7fd7f5690f54ed02823f7f35f26d15adc09c2799/kvm_backup.sh
 
https://gist.githubusercontent.com/maxim-gorkin/f0e8a2c01a93ca65ad2ad10566a78d72/raw/7fd7f5690f54ed02823f7f35f26d15adc09c2799/kvm_backup.sh
  
<pre>
 
# Set the language to English so virsh does it's output
 
# in English as well
 
# LANG=en_US
 
  
SCRIPTNAME=kvm-backup
+
# Set the language to English so virsh does it's output
 
+
# in English as well
# Local backup folder
+
# LANG=en_US
LOCALBKFOLDER=/arc/vm
+
 
+
SCRIPTNAME=kvm-backup
# Clean local backup folders older then days
+
ERASEBCKPDAYS=3
+
# Local backup folder
 
+
LOCALBKFOLDER=/arc/vm
# Mounted network backup folder
+
NETBKFOLDER=/mnt/backup/VMs
+
# Clean local backup folders older then days
 
+
ERASEBCKPDAYS=3  
echo "Start backup script at $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME
+
 
+
# Mounted network backup folder
# List domains
+
NETBKFOLDER=/mnt/backup/VMs  
DOMAINS=$(virsh list | tail -n +3 | awk '{print $2}')
+
 
+
echo "Start backup script at $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME
for DOMAIN in $DOMAINS; do
+
 
+
# List domains
echo "Starting backup for $DOMAIN on $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME
+
DOMAINS=$(virsh list | tail -n +3 | awk '{print $2}')
 
+
# Generate the backup folder URI - this is something you should
+
for DOMAIN in $DOMAINS; do
# change/check
+
BACKUPFOLDER=$LOCALBKFOLDER/$DOMAIN/$(date +%d-%m-%Y)
+
echo "Starting backup for $DOMAIN on $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME
NBACKUPFOLDER=$NETBKFOLDER/$DOMAIN
+
 
echo "Create BACKUPFOLDER = $BACKUPFOLDER" | systemd-cat -p info -t $SCRIPTNAME
+
# Generate the backup folder URI - this is something you should
mkdir -p $BACKUPFOLDER
+
# change/check
 +
BACKUPFOLDER=$LOCALBKFOLDER/$DOMAIN/$(date +%d-%m-%Y)
 +
NBACKUPFOLDER=$NETBKFOLDER/$DOMAIN
 +
echo "Create BACKUPFOLDER = $BACKUPFOLDER" | systemd-cat -p info -t $SCRIPTNAME
 +
mkdir -p $BACKUPFOLDER
 
         echo "Create NBACKUPFOLDER = $NBACKUPFOLDER" | systemd-cat -p info -t $SCRIPTNAME
 
         echo "Create NBACKUPFOLDER = $NBACKUPFOLDER" | systemd-cat -p info -t $SCRIPTNAME
mkdir -p $NBACKUPFOLDER
+
mkdir -p $NBACKUPFOLDER
# Get the target disk
+
# Get the target disk
TARGETS=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $3}')
+
TARGETS=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $3}')
 
+
# Get the image page
+
# Get the image page
IMAGES=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $4}')
+
IMAGES=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $4}')
 
+
# Create the snapshot/disk specification
+
# Create the snapshot/disk specification
DISKSPEC=""
+
DISKSPEC=""
 
+
for TARGET in $TARGETS; do
+
for TARGET in $TARGETS; do
DISKSPEC="$DISKSPEC --diskspec $TARGET,snapshot=external"
+
DISKSPEC="$DISKSPEC --diskspec $TARGET,snapshot=external"
done
+
done
echo "Create snapshot for $DOMAIN, DISKSPEC = $DISKSPEC" | systemd-cat -p info -t $SCRIPTNAME
+
  echo "Create snapshot for $DOMAIN, DISKSPEC = $DISKSPEC" | systemd-cat -p info -t $SCRIPTNAME
virsh snapshot-create-as --domain $DOMAIN --name "backup-$DOMAIN" --no-metadata --atomic --disk-only $DISKSPEC
+
virsh snapshot-create-as --domain $DOMAIN --name "backup-$DOMAIN" --no-metadata --atomic --disk-only $DISKSPEC
 
+
if [ $? -ne 0 ]; then
+
if [ $? -ne 0 ]; then
echo "Failed to create snapshot for $DOMAIN" | systemd-cat -p warning -t $SCRIPTNAME
+
echo "Failed to create snapshot for $DOMAIN" | systemd-cat -p warning -t $SCRIPTNAME
exit 1
+
exit 1
fi
+
fi
 
+
# Copy disk image
+
# Copy disk image
for IMAGE in $IMAGES; do
+
for IMAGE in $IMAGES; do
NAME=$(basename $IMAGE)
+
NAME=$(basename $IMAGE)
echo "Sync $IMAGE and $BACKUPFOLDER/$NAME" | systemd-cat -p info -t $SCRIPTNAME
+
echo "Sync $IMAGE and $BACKUPFOLDER/$NAME" | systemd-cat -p info -t $SCRIPTNAME
rsync -ahW --no-o --no-g --progress $IMAGE $BACKUPFOLDER/$NAME
+
rsync -ahW --no-o --no-g --progress $IMAGE $BACKUPFOLDER/$NAME
done
+
done
 
+
# Merge changes back
+
# Merge changes back
BACKUPIMAGES=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $4}')
+
BACKUPIMAGES=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $4}')
 
+
for TARGET in $TARGETS; do
+
for TARGET in $TARGETS; do
echo "Blockcommit for $DOMAIN, TARGET = $TARGET" | systemd-cat -p info -t $SCRIPTNAME
+
echo "Blockcommit for $DOMAIN, TARGET = $TARGET" | systemd-cat -p info -t $SCRIPTNAME
virsh blockcommit $DOMAIN $TARGET --active --pivot # 1>/dev/null 2>&1
+
virsh blockcommit $DOMAIN $TARGET --active --pivot # 1>/dev/null 2>&1
 
+
if [ $? -ne 0 ]; then
+
if [ $? -ne 0 ]; then
echo "Could not merge changes for disk of $TARGET of $DOMAIN. VM may be in invalid state." | systemd-cat -p warning -t $SCRIPTNAME
+
echo "Could not merge changes for disk of $TARGET of $DOMAIN. VM may be in invalid state." | systemd-cat -p warning -t $SCRIPTNAME
exit 1
+
exit 1
fi
+
fi
done
+
done
 
+
# Cleanup left over backups
+
# Cleanup left over backups
for BACKUP in $BACKUPIMAGES; do
+
for BACKUP in $BACKUPIMAGES; do
 
         echo "Remove $BACKUP" | systemd-cat -p info -t $SCRIPTNAME
 
         echo "Remove $BACKUP" | systemd-cat -p info -t $SCRIPTNAME
rm -f $BACKUP
+
rm -f $BACKUP
done
+
done
 
+
 
# Dump the configuration information.
+
# Dump the configuration information.
echo "Create xml for $DOMAIN  - $BACKUPFOLDER/$DOMAIN.xml" | systemd-cat -p info -t $SCRIPTNAME
+
echo "Create xml for $DOMAIN  - $BACKUPFOLDER/$DOMAIN.xml" | systemd-cat -p info -t $SCRIPTNAME
virsh dumpxml $DOMAIN > $BACKUPFOLDER/$DOMAIN.xml # 1>/dev/null 2>&1
+
virsh dumpxml $DOMAIN > $BACKUPFOLDER/$DOMAIN.xml # 1>/dev/null 2>&1
 
         echo "Create xml for $DOMAIN  - $NBACKUPFOLDER/$DOMAIN.xml" | systemd-cat -p info -t $SCRIPTNAME
 
         echo "Create xml for $DOMAIN  - $NBACKUPFOLDER/$DOMAIN.xml" | systemd-cat -p info -t $SCRIPTNAME
virsh dumpxml $DOMAIN > $NBACKUPFOLDER/$DOMAIN.xml
+
virsh dumpxml $DOMAIN > $NBACKUPFOLDER/$DOMAIN.xml
 
+
# Copy disk to network backup disk
+
# Copy disk to network backup disk
 
         for IMAGE in $IMAGES; do
 
         for IMAGE in $IMAGES; do
 
        NAME=$(basename $IMAGE)
 
        NAME=$(basename $IMAGE)
      echo "Copy $BACKUPFOLDER/$NAME to $NBACKUPFOLDER/$NAME" | systemd-cat -p info -t $SCRIPTNAME
+
      echo "Copy $BACKUPFOLDER/$NAME to $NBACKUPFOLDER/$NAME" | systemd-cat -p info -t $SCRIPTNAME
      cp $BACKUPFOLDER/$NAME $NBACKUPFOLDER/$NAME
+
      cp $BACKUPFOLDER/$NAME $NBACKUPFOLDER/$NAME
done
+
done
 
+
echo "Finished backup of $DOMAIN at $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME
+
echo "Finished backup of $DOMAIN at $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME
done
+
done
 +
 +
  # Cleanup local backup folders
 +
  echo "Delete local backups $LOCALBKFOLDER older then $ERASEBCKPDAYS days" | systemd-cat -p info -t $SCRIPTNAME
 +
  find $LOCALBKFOLDER/* -ctime +$ERASEBCKPDAYS -type d -exec rm -r {} +
 +
 
 +
  echo "Finished backup script at $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME
 +
  exit 0
  
# Cleanup local backup folders
 
echo "Delete local backups $LOCALBKFOLDER older then $ERASEBCKPDAYS days" | systemd-cat -p info -t $SCRIPTNAME
 
find $LOCALBKFOLDER/* -ctime +$ERASEBCKPDAYS -type d -exec rm -r {} +
 
  
echo "Finished backup script at $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME
+
== See also ==
exit 0
+
* <code>[[virsh blockcommit]]</code>
</pre>
+
* [[KVM backup]]

Latest revision as of 15:45, 5 October 2020

https://gist.githubusercontent.com/maxim-gorkin/f0e8a2c01a93ca65ad2ad10566a78d72/raw/7fd7f5690f54ed02823f7f35f26d15adc09c2799/kvm_backup.sh


# Set the language to English so virsh does it's output
# in English as well
# LANG=en_US

SCRIPTNAME=kvm-backup

# Local backup folder
LOCALBKFOLDER=/arc/vm

# Clean local backup folders older then days
ERASEBCKPDAYS=3 

# Mounted network backup folder
NETBKFOLDER=/mnt/backup/VMs 

echo "Start backup script at $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME

# List domains
DOMAINS=$(virsh list | tail -n +3 | awk '{print $2}')

for DOMAIN in $DOMAINS; do

	echo "Starting backup for $DOMAIN on $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME
 
	# Generate the backup folder URI - this is something you should
	# change/check
	BACKUPFOLDER=$LOCALBKFOLDER/$DOMAIN/$(date +%d-%m-%Y)
	NBACKUPFOLDER=$NETBKFOLDER/$DOMAIN
	echo "Create BACKUPFOLDER = $BACKUPFOLDER" | systemd-cat -p info -t $SCRIPTNAME
	mkdir -p $BACKUPFOLDER
       echo "Create NBACKUPFOLDER = $NBACKUPFOLDER" | systemd-cat -p info -t $SCRIPTNAME
	mkdir -p $NBACKUPFOLDER
	# Get the target disk
	TARGETS=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $3}')

	# Get the image page
	IMAGES=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $4}')

	# Create the snapshot/disk specification
	DISKSPEC=""

	for TARGET in $TARGETS; do
		DISKSPEC="$DISKSPEC --diskspec $TARGET,snapshot=external"
	done
 	echo "Create snapshot for $DOMAIN, DISKSPEC = $DISKSPEC" | systemd-cat -p info -t $SCRIPTNAME
	virsh snapshot-create-as --domain $DOMAIN --name "backup-$DOMAIN" --no-metadata --atomic --disk-only $DISKSPEC

	if [ $? -ne 0 ]; then
		echo "Failed to create snapshot for $DOMAIN" | systemd-cat -p warning -t $SCRIPTNAME
		exit 1
	fi

	# Copy disk image
	for IMAGE in $IMAGES; do
		NAME=$(basename $IMAGE)
		echo "Sync $IMAGE and $BACKUPFOLDER/$NAME" | systemd-cat -p info -t $SCRIPTNAME
		rsync -ahW --no-o --no-g --progress $IMAGE $BACKUPFOLDER/$NAME
	done

	# Merge changes back
	BACKUPIMAGES=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $4}')

	for TARGET in $TARGETS; do
		 echo "Blockcommit for $DOMAIN, TARGET = $TARGET" | systemd-cat -p info -t $SCRIPTNAME
		virsh blockcommit $DOMAIN $TARGET --active --pivot # 1>/dev/null 2>&1

		if [ $? -ne 0 ]; then
			echo "Could not merge changes for disk of $TARGET of $DOMAIN. VM may be in invalid state." | systemd-cat -p warning -t $SCRIPTNAME
			exit 1
		fi
	done

	# Cleanup left over backups
	for BACKUP in $BACKUPIMAGES; do
       echo "Remove $BACKUP" | systemd-cat -p info -t $SCRIPTNAME
		rm -f $BACKUP
	done
 
	# Dump the configuration information.
	echo "Create xml for $DOMAIN  - $BACKUPFOLDER/$DOMAIN.xml" | systemd-cat -p info -t $SCRIPTNAME
	virsh dumpxml $DOMAIN > $BACKUPFOLDER/$DOMAIN.xml # 1>/dev/null 2>&1
       echo "Create xml for $DOMAIN  - $NBACKUPFOLDER/$DOMAIN.xml" | systemd-cat -p info -t $SCRIPTNAME
	virsh dumpxml $DOMAIN > $NBACKUPFOLDER/$DOMAIN.xml

	# Copy disk to network backup disk
       for IMAGE in $IMAGES; do
	       NAME=$(basename $IMAGE)
	       echo "Copy $BACKUPFOLDER/$NAME to $NBACKUPFOLDER/$NAME" | systemd-cat -p info -t $SCRIPTNAME
	       cp $BACKUPFOLDER/$NAME $NBACKUPFOLDER/$NAME
	done

	echo "Finished backup of $DOMAIN at $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME
done

 # Cleanup local backup folders
 echo "Delete local backups $LOCALBKFOLDER older then $ERASEBCKPDAYS days" | systemd-cat -p info -t $SCRIPTNAME
 find $LOCALBKFOLDER/* -ctime +$ERASEBCKPDAYS -type d -exec rm -r {} +
 
 echo "Finished backup script at $(date +'%d-%m-%Y %H:%M:%S')" | systemd-cat -p info -t $SCRIPTNAME
 exit 0


See also[edit]

Advertising: