Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:11.4:Update
virt-utils.import5774
vm-snapshot-disk
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File vm-snapshot-disk of Package virt-utils.import5774
#!/bin/bash #============================================================================ # vm-snapshot-disk # # Version = 0.4.0 # Date = 2010-02-12 # # Copyright - Ron Terry # License - GPL # # Maintainer(s) = Ron Terry - roncterry (at) gmail (dot) com # # The latest version can be found at: # # http://pronetworkconsulting.com/linux/scripts/virt-tools.html # # Description: # This script creates and manages snapshots of qcow2 virtual disks. # # Individual snapshots and snapshot trees are supported. The names # of the snapshots in the snapshot tree are stored in the actual # filenames of the snapshots themselves. Descriptions of each # snapshot can be provided and will be stored in a file named # .$DISK.snap_descriptions # # The following operations can be performed: # # create -creates a new snapshot from the current position in the # snapshot tree # branch -creates a new branch of the snapshot tree from the # specified snapshot # revert -reverts to the specified snapshot and deletes all linked # snapshots from the snapshot tree # remove -removes all snapshosts and snapshot descriptions from # the disk image # list -list all snapshots and their descriptions # help -displays the description and usage # #============================================================================ ################################################################################### # Read config files and set variables ################################################################################### if which qemu-img > /dev/null 2>&1 then QEMU_IMG_CMD=qemu-img elif which qemu-img-xen > /dev/null 2>&1 then QEMU_IMG_CMD=qemu-img-xen fi ################################################################################### # Script Functions ################################################################################### ########## Function: description ############################### description() { echo " ================================================================================ Description: This script creates and manages snapshots of qcow2 virtual disks Individual snapshots and snapshot trees are supported. The names of the snapshots in the snapshot tree are stored in the actual filenames of the snapshots themselves. Descriptions of each snapshot can be provided and will be stored in a file named .\$DISK.snap_descriptions The following operations can be performed: create -creates a new snapshot from the current position in the snapshot tree branch -creates a new branch of the snapshot tree from the specified snapshot revert -reverts to the specified snapshot and deletes all linked snapshots from the snapshot tree remove -removes all snapshosts and snapshot descriptions from the disk image list -list all snapshots and their descriptions help -displays the description and usage ================================================================================ " # delete -deletes the specified snapshot and all linked snapshots # from the snapshot tree } ########## Function: usage ########################################### usage() { echo echo "Usage: vm-snapshot-disk [create|branch|revert|remove|list|help] options" echo echo "Examples:" echo " vm-snapshot-disk create disk=<DISK_NAME> [snapname=<SNAPSHOT_NAME> description=\"<SNAPSHOT_DESCRIPTION>\"]" echo " vm-snapshot-disk branch disk=<DISK_NAME> snapname=<SNAPSHOT_NAME> [description=\"<SNAPSHOT_DESCRIPTION>\"]" echo " vm-snapshot-disk revert disk=<DISK_NAME> snapname=<SNAPSHOT_NAME>" echo " vm-snapshot-disk remove disk=<DISK_NAME>" echo " vm-snapshot-disk list disk=<DISK_NAME>" echo " vm-snapshot-disk help" echo } ########## Function: get_options ##################################### get_options() { case "$1" in #create|branch|revert|delete|help) create|branch|revert|remove|list) MODE="$1" ;; help|-h|--help) MODE=help ;; *) echo echo "ERROR: You must provide a valid mode!" usage exit 1 ;; esac if echo "$*" | grep -q "disk=" then local DISK_IMAGE_FULL=`echo "$*" | grep -o "disk=.*" | cut -d '=' -f 2 | cut -d ' ' -f 1` fi if echo $* | grep -q "snapname=" then SNAPSHOT_NAME=`echo $* | grep -o "snapname=.*" | cut -d '=' -f 2 | cut -d ' ' -f 1` fi if echo $* | grep -q "description=" then #SNAPSHOT_DESCR=`echo $* | grep -o "description=.*" | cut -d '=' -f 2 | cut -d ' ' -f 1` SNAPSHOT_DESCR=`echo $* | grep -o "description=.*" | cut -d '=' -f 2` fi if [ -z "$DISK_IMAGE_FULL" ] then case "$MODE" in help|-h) MODE=help description usage exit 99 ;; *) echo echo "ERROR: You must supply a disk image!" usage exit 1 esac else DISK_IMAGE=`get_file_name $DISK_IMAGE_FULL` DISK_PATH=`get_file_path $DISK_IMAGE_FULL` fi } ########## Function: get_file_path ###################################### get_file_path() { if [ -z $1 ] then echo "Usage: get_file_path <absolute|relative_path_to_file>" return 1 else local FILE="$1" fi local DIR_COUNT=`echo $FILE|grep -o "/"|wc -l` ((DIR_COUNT++)) local FILE_NAME=`echo $FILE|cut -d "/" -f $DIR_COUNT` local FILE_DIR=`echo $FILE|sed "s/$FILE_NAME$//g"` echo $FILE_DIR } ########## Function: get_file_name ###################################### get_file_name() { if [ -z $1 ] then echo "Usage: get_file_name <absolute|relative_path_to_file>" return 1 else local FILE="$1" fi local DIR_COUNT=`echo $FILE|grep -o "/"|wc -l` ((DIR_COUNT++)) local FILE_NAME=`echo $FILE|cut -d "/" -f $DIR_COUNT` local FILE_DIR=`echo $FILE|sed "s/$FILE_NAME$//g"` echo $FILE_NAME } ########## Function: test_disk ########################################### test_disk() { local DISK="$1" if ! [ -e "$DISK" ] then echo echo "ERROR: The specified disk \"$DISK\" does not exist!" echo exit 2 fi if ! ($QEMU_IMG_CMD info $DISK | grep "file format" | cut -d ' ' -f 3 | grep -q qcow2) 2> /dev/null then echo echo "ERROR: The specified disk \"$DISK\" does not appear to be of type qcow2" echo " You cannot snpashot this disk!" exit 3 fi } ########## Function: get_backing_disk ##################################### get_backing_disk() { "$QEMU_IMG_CMD" info "$1" | grep "backing file" | cut -d : -f 3 | sed 's/^ *//g' | sed 's/)//g' } ########## Function: find_unused_snap_name ################################ find_unused_snap_name() { local DISK="$1" local SNAPNAME="$2" local SNAP_DESCR="$3" if [ -z "$SNAPNAME" ] then #echo "Finding and unused snap name" SNAMECOUNT=1 SNAPNAME=snap"$SNAMECOUNT" until ! ls "$DISK".* | grep -q snap"$SNAMECOUNT" do ((SNAMECOUNT++)) SNAPNAME=snap"$SNAMECOUNT" done fi echo "$SNAPNAME" } ########## Function: create_first_snapshot ################################ create_first_snapshot() { local DISK="$1" local SNAPNAME="$2" local SNAP_DESCR="$3" local BDISK="$DISK".base mv "$DISK" "$BDISK" SNAPNAME=`find_unused_snap_name "$DISK" "$SNAPNAME" "$SNAP_DESCR"` echo " Creating new snapshot: $BDISK.$SNAPNAME" echo "*****************************************************************" ln "$BDISK" "$BDISK"."$SNAPNAME" chmod a-w "$BDISK" chmod a-w "$BDISK"."$SNAPNAME" "$QEMU_IMG_CMD" create -f qcow2 -b "$BDISK" "$BDISK"."$SNAPNAME"._working ln -s "$BDISK"."$SNAPNAME"._working "$DISK" # add snapshot description echo `echo "$BDISK.$SNAPNAME" | sed 's/\./_/g' | sed 's/__working//g'`"='$SNAP_DESCR'" >> ."$DISK".snap_descriptions } ########## Function: create_additional_snapshot ########################### create_additional_snapshot() { local DISK="$1" local SNAPNAME="$2" local SNAP_DESCR="$3" local BDISK=`ls -l "$DISK" |cut -d ">" -f 2 | sed 's/^ *//g'` rm -f "$DISK" SNAPNAME=`find_unused_snap_name "$DISK" "$SNAPNAME" "$SNAP_DESCR"` BASE_BDISK="`echo "$BDISK" | sed 's/\._working//g'`" echo " Creating new snapshot: $BASE_BDISK.$SNAPNAME" echo "*****************************************************************" mv "$BDISK" "$BASE_BDISK"."$SNAPNAME" chmod a-w "$BASE_BDISK"."$SNAPNAME" "$QEMU_IMG_CMD" create -f qcow2 -b "$BASE_BDISK"."$SNAPNAME" "$BASE_BDISK"."$SNAPNAME"._working ln -s "$BASE_BDISK"."$SNAPNAME"._working "$DISK" # add snapshot description echo `echo "$BDISK.$SNAPNAME" | sed 's/\./_/g' | sed 's/__working//g'`"='$SNAP_DESCR'" >> ."$DISK".snap_descriptions } ########## Function: create_snapshot ###################################### create_snapshot() { local DISK="$1" local SNAPNAME="$2" local SNAP_DESCR="$3" #echo "Testing for base disk image file" if ! [ -e "$DISK".base ] then create_first_snapshot "$DISK" "$SNAPNAME" "$SNAP_DESCR" #return elif [ -L "$DISK" ] then create_additional_snapshot "$DISK" "$SNAPNAME" "$SNAP_DESCR" #return fi } ########## Function: branch_at_snapshot ##################################### branch_at_snapshot() { local DISK="$1" local SNAPNAME="$2" local SNAP_DESCR="$3" if [ -z "$SNAPNAME" ] then echo echo "ERROR: You must supply a snapshot name to branch from!" echo exit 4 fi if ! ls "$DISK".* | grep -q "$SNAPNAME$" then echo echo "ERROR: The specified snapshot \"$SNAPNAME\" does not appear to exist!" echo exit 5 fi local SNAP_POINT=`ls "$DISK".* | grep "$SNAPNAME$"` #echo "Finding and unused snap name" local SNAMECOUNT=1 until ! ls "$DISK".* | grep -q "$SNAPNAME"-"$SNAMECOUNT"$ do ((SNAMECOUNT++)) done SUB_SNAPNAME="$SNAPNAME"-"$SNAMECOUNT" echo "*****************************************************************" echo " Branching from snapshot: $SNAP_POINT" rm -f "$DISK" rm -f "$DISK".*._working #ln -s "$SNAP_POINT" "$DISK" #create_snapshot "$DISK" "$SUB_SNAPNAME" "$SNAP_DESCR" "$QEMU_IMG_CMD" create -f qcow2 -b "$SNAP_POINT" "$SNAP_POINT"."$SUB_SNAPNAME"._working ln -s "$SNAP_POINT"."$SUB_SNAPNAME"._working "$DISK" chmod a-w "$SNAP_POINT" } ########## Function: revert_to_snapshot ##################################### revert_to_snapshot() { local DISK="$1" local SNAPNAME="$2" local SNAP_DESCR="$3" if [ -z "$SNAPNAME" ] then echo echo "ERROR: You must supply a snapshot name to revert to!" echo exit 4 fi if ! ls "$DISK".* | grep -q "$SNAPNAME$" then echo echo "ERROR: The specified snapshot \"$SNAPNAME\" does not appear to exist!" echo exit 5 fi local SNAP_POINT=`ls "$DISK".* | grep "$SNAPNAME$"` echo "*****************************************************************" echo " Reverting to snapshot: $SNAP_POINT" echo "*****************************************************************" rm -f "$DISK" rm -f "$DISK".*._working rm -f "$SNAP_POINT".* "$QEMU_IMG_CMD" create -f qcow2 -b "$SNAP_POINT" "$SNAP_POINT"._working ln -s "$SNAP_POINT"._working "$DISK" chmod a-w "$SNAP_POINT" # remove snapshot description sed -i "/$SNAP_POINT\..*/d" ."$DISK".snap_descriptions } ########## Function: remove_snapshot ##################################### remove_snapshots() { local DISK="$1" local SNAPNAME="$2" local SNAP_DESCR="$3" #echo "Testing for base disk image file" if ! [ -e "$DISK".base ] then echo "$DISK doesn't appear to have any snapshots" else echo "*****************************************************************" echo " Removing all snapshots from: $DISK" echo "*****************************************************************" rm -f "$DISK" chmod u+w "$DISK".base.* rm -r "$DISK".base.* # remove snapshot description rm -f ."$DISK".snap_descriptions mv "$DISK".base "$DISK" fi } ########## Function: list_snapshots ###################################### list_snapshots() { local DISK="$1" local SNAPNAME="$2" local SNAP_DESCR="$3" #echo "Testing for base disk image file" if ! [ -e "$DISK".base ] then echo "$DISK doesn't appear to have any snapshots" else for SNAP in `ls "$DISK".base.*` do #echo "SNAP=$SNAP";read if ! echo "$SNAP" | grep -q "_working" then local DOT_COUNT=`echo $SNAP | grep -o \\\. | wc -l` ((DOT_COUNT++)) local SNAP_NAME=`echo "$SNAP" | cut -d \. -f "$DOT_COUNT"` local SNAP_ENTRY=`echo $SNAP | sed 's/\./_/g'` echo -n "$SNAP_NAME = ";grep "$SNAP_ENTRY=" ."$DISK".snap_descriptions | cut -d '=' -f 2 fi done fi } ########## Function: delete_snapshot ##################################### # Disabled until I can figure out how to 'merge' cow snapshots delete_snapshot() { local DISK="$1" local SNAPNAME="$2" local SNAP_DESC="$3" if [ -z "$SNAPNAME" ] then echo echo "ERROR: You must supply a snapshot name to delete!" echo exit 4 fi if ! ls "$DISK".* | grep -q "$SNAPNAME$" then echo echo "ERROR: The specified snapshot \"$SNAPNAME\" does not appear to exist!" echo exit 5 fi if [ "$DISK.$SNAPNAME" = "$DISK.base" ] then echo echo "ERROR: You cannot delete the base image!" echo exit 6 fi local SNAP_DEL=`ls "$DISK".* | grep "$SNAPNAME$"` local SNAP_POINT=`echo $SNAP_DEL | sed "s/\.$SNAPNAME$//g"` if [ "$SNAP_POINT" = "$DISK.base" ] then echo > /dev/null #echo "Guess its the base" #continue elif ls "$SNAP_POINT".* > /dev/null 2>&1 then #echo "SNAP_POINT=$SNAP_POINT, looking for end of snap train" local SNAP_POINT_OPTIONS=`ls "$SNAP_POINT".*` #echo "My choices are: $SNAP_POINT_OPTIONS" if ! [ "$SNAP_POINT_OPTIONS" = "$SNAP_DEL" ] then for SP in $SNAP_POINT_OPTIONS do if ! ls "$SP".* > /dev/null 2>&1 then if ! [ "$SP" = "$SNAP_DEL" ] then SNAP_POINT="$SP" fi fi done #else # echo "Oops. guess I don't need to look after all" fi elif [ "$SNAP_POINT" = "$SNAP_DEL" ] then #echo "Opps. Del point = Snap point. trying to fix..." local FCOUNT=`echo $SNAP_POINT | grep -o "\." | wc -l` ((FCOUNT++)) LAST_FLD=`echo $SNAP_POINT | cut -d '.' -f $FCOUNT` SNAP_POINT=`echo $SNAP_POINT | sed "s/\.$LAST_FLD//g"` fi echo "*****************************************************************" echo " Deleting snapshot: $SNAP_DEL" echo " Reverting to snapshot: $SNAP_POINT" echo "*****************************************************************" if [ -L "$DISK" ] then rm -f "$DISK" fi rm -f "$DISK".*._working rm -f "$SNAP_DEL"* "$QEMU_IMG_CMD" create -f qcow2 -b "$SNAP_POINT" "$SNAP_POINT"._working ln -s "$SNAP_POINT"._working "$DISK" # remove snapshot description sed -i "/$SNAP_DEL.*/d" ."$DISK".snap_descriptions } ################################################################################### # Main Code Body ################################################################################### get_options $* cd "$DISK_PATH" test_disk "$DISK_IMAGE" case "$MODE" in create) echo "*****************************************************************" create_snapshot "$DISK_IMAGE" "$SNAPSHOT_NAME" "$SNAPSHOT_DESCR" ;; branch) branch_at_snapshot "$DISK_IMAGE" "$SNAPSHOT_NAME" "$SNAPSHOT_DESCR" ;; revert) revert_to_snapshot "$DISK_IMAGE" "$SNAPSHOT_NAME" "$SNAPSHOT_DESCR" ;; remove) remove_snapshots "$DISK_IMAGE" "$SNAPSHOT_NAME" "$SNAPSHOT_DESCR" ;; list) list_snapshots "$DISK_IMAGE" "$SNAPSHOT_NAME" "$SNAPSHOT_DESCR" ;; # Disabled until I can figure out how to merge cow snapshots # delete) # delete_snapshot "$DISK_IMAGE" "$SNAPSHOT_NAME" "$SNAPSHOT_DESCR" # ;; help) description usage ;; esac exit 0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor