SHARE
TWEET

KVM Backup Manager

a guest Jan 22nd, 2011 279 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/bin/bash
  2.  
  3. # ------------------------------------------------------------------------
  4. # Copyright 2010 Lorin Soura <gr8can8dian@gmail.com>
  5. # This script is licensed under GNU GPL version 3.0 or above
  6. # -------------------------------------------------------------------------
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11.  
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. # GNU General Public License for more details.
  16.  
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19. # -------------------------------------------------------------------------
  20.  
  21. ###################################
  22. ############ FUNCTIONS ############
  23. ###################################
  24.  
  25. ### backupVM()
  26. # This function takes no parameters
  27. # Backs up virtual machine files in KVM for Fedora
  28. function backupVM() {
  29.   ############ VARIABLES ############
  30.  
  31.   # Today's date in the format mmm-dd-yyyy
  32.   theDate=$(date +%b"-"%d"-"%Y)
  33.  
  34.   # Today's date in the format mmm-dd-yyyy-hr:min[am | pm]
  35.   longDate="$(date +%b"-"%d"-"%Y"-"%l":"%M%P | sed 's/[ ]* //g')"
  36.  
  37.   # The path to copy new files
  38.   newPath="$basePath$theDate"
  39.  
  40.   # The path to the shadow copy directory
  41.   shadowPath="$basePath$shadowDir"
  42.  
  43.   ############   MAIN   #############
  44.  
  45.   clear
  46.  
  47.   ### If there is no "Previous" directory create one
  48.   if [ ! -d "$shadowPath" ]; then
  49.     timer "Creating archive directory \"$shadowPath\"" "." 3
  50.     mkdir -p $shadowPath
  51.     cecho "Done!!!" blue; echo
  52.   fi
  53.  
  54.   ### If there is an existing timestamped directory
  55.   if [ "$timeStampDir" != "" ]; then
  56.     #Copy the old files into the shadow directory
  57.     echo "The folder \"$timeStampDir\" will be moved."
  58.     timer "\"$timeStampDir\" -> \"$shadowPath\"" "." 3
  59.     timestamp=$(cat ${basePath}${timeStampDir}/.timestamp)
  60.     mkdir $shadowPath/$timestamp
  61.     cp -v ${basePath}${timeStampDir}/* $shadowPath/$timestamp
  62.     rm -rf ${basePath}${timeStampDir}
  63.     cecho "Done!!!" blue; echo
  64.  
  65.     # Make a new directory for today's date
  66.     timer "Creating new directory \"$newPath\"" "." 3
  67.     mkdir -p $newPath
  68.     touch $newPath/.timestamp
  69.     cecho "Done!!!" blue; echo
  70.  
  71.   ### If there is no existing timestamped directory
  72.   elif [ ! -d $newPath ];then
  73.   # Make a directory for the date if it doesn't exist
  74.     timer "Creating directory \"$newPath\"" "." 3
  75.     mkdir -p $newPath
  76.     touch $newPath/.timestamp
  77.     cecho "Done!!!" blue; echo
  78.   fi
  79.  
  80.   ###Declare an array of files to be copied
  81.   list=$(ls /var/lib/libvirt/images/*.img)
  82.  
  83.   for item in $list; do
  84.  
  85.     # Full Absolute Path to the .img file
  86.     copyFullPath=$item
  87.  
  88.     # Name of the file with no extensions
  89.     copyFileName=$(echo $(basename $item) | sed 's!\.img$!!')
  90.  
  91.     # Prompt user for backup
  92.     txtQuestion="Backup the \"$copyFileName\" virtual machine?"
  93.     txtAnswer="x"
  94.     while [[ ! $(echo $txtAnswer | grep -i "N") || ! $(echo $txtAnswer | grep -i "Y") ]]; do
  95.       read -p "$txtQuestion " txtAnswer
  96.         while [[ ! $(echo $txtAnswer | grep -i "Y") && ! $(echo $txtAnswer | grep -i "N") ]]; do
  97.           echo  "Please enter \"Y\" or \"N\". "
  98.           read -p "$txtQuestion " txtAnswer
  99.         done
  100.       if [ $(echo $txtAnswer | grep -i "Y") > /dev/null 2>&1 ]; then
  101.         # Backup the image file
  102.         timer "Backing up \"$copyFileName\" to \"$newPath\"" "." 3
  103.         gzip < $copyFullPath > $newPath/$copyFileName.gz
  104.         # Backup the XML file
  105.         timer "Backing up the \"$copyFileName\" XML file to \"$newPath\"" "." 3
  106.         virsh dumpxml $copyFileName > $newPath/$copyFileName.xml
  107.         cecho "Done!!!" blue; echo
  108.         echo "$longDate" > $newPath/.timestamp
  109.         break
  110.       elif [ $(echo $txtAnswer | grep -i "N") > /dev/null 2>&1 ]; then
  111.         cecho "Skipped \"$copyFileName\"." blue; echo
  112.         break
  113.       fi
  114.     done
  115.   done
  116. }
  117.  
  118. ### cecho()
  119. # This function takes two parameters:
  120. # $1 is the text to display
  121. # $2 is the colour to use for the display
  122. function cecho(){
  123.   case $2 in
  124.     grey)
  125.       echo -e "\033[30m$1\033[0m";;
  126.  
  127.     red)
  128.       echo -e "\033[31m$1\033[0m";;
  129.  
  130.     green)
  131.       echo -e "\033[32m$1\033[0m";;
  132.  
  133.     yellow)
  134.       echo -e "\033[33m$1\033[0m";;
  135.  
  136.     blue)
  137.       echo -e "\033[34m$1\033[0m";;
  138.  
  139.     purple)
  140.       echo -e "\033[35m$1\033[0m";;
  141.  
  142.     cyan)
  143.       echo -e "\033[36m$1\033[0m";;
  144.  
  145.     white)
  146.       echo -e "\033[37m$1\033[0m";;
  147.  
  148.     hilite)
  149.       echo $(tput smso;echo "$1";tput rmso);;
  150.  
  151.     bold)
  152.       echo $(tput bold;echo "$1";tput sgr0);;
  153.     *);;
  154.   esac
  155. }
  156.  
  157. ### delay()
  158. # This function takes two parameters:
  159. # $1 is the text to display after "Press <Enter>
  160. # $2 is the colour to use for the displayed message
  161. function delay() {
  162.   read -p "$(cecho "Press <Enter> $1." $2)" strNull
  163. }
  164.  
  165. function deleteVM(){
  166.  
  167.     # Path to file without the extension (.img or .xml)
  168.     deleteBaseName="$imagePath/$deleteFileName"
  169.  
  170.     # The names of files that are defined in virtManager
  171.     definedList=$(virsh list --all | cut -f 4 -d" " | sed 's/^[-]*$//')
  172.  
  173.     # Is the machine defined?
  174.     isDefined=false
  175.  
  176.     if [ $# -eq 0 ]; then
  177.        ###Declare an array of files to be copied
  178.        list=$(ls /var/lib/libvirt/images/*.img)
  179.     else
  180.        list="$@"
  181.     fi
  182.  
  183.     for fileName in $list; do
  184.       # Name of the file with no extensions
  185.       deleteFileName=$(echo $(basename $fileName) | sed 's!\.img$!!')
  186.  
  187.       for machine in $definedList; do
  188.         if [ $deleteFileName == $machine ]; then
  189.           isDefined=true
  190.         fi
  191.       done
  192.  
  193.       if [ $isDefined == "true" ]; then
  194.         # Prompt to undefine the virtual machine
  195.         txtQuestion="Undefine the \"$deleteFileName\" virtual machine?"
  196.         txtAnswer="x"
  197.         while [[ ! $(echo $txtAnswer | grep -i "N") || ! $(echo $txtAnswer | grep -i "Y") ]]; do
  198.           read -p "$txtQuestion " txtAnswer
  199.             while [[ ! $(echo $txtAnswer | grep -i "Y") && ! $(echo $txtAnswer | grep -i "N") ]]; do
  200.               echo  "Please enter \"Y\" or \"N\". "
  201.               read -p "$txtQuestion " txtAnswer
  202.             done
  203.           if [ $(echo $txtAnswer | grep -i "Y") > /dev/null 2>&1 ]; then
  204.             # Undefine the virtual machine file
  205.             timer "Undefining \"$deleteFileName\"" "." 3
  206.             virsh undefine $deleteFileName
  207.             # Delete the virtual machine XML file
  208.             timer "Deleting the \"$deleteFileName\" XML file" "." 3
  209.             rm -iv $xmlPath/$deleteFileName.xml
  210.             # Delete the virtual machine Image file
  211.             timer "Deleting the \"$deleteFileName\" image file" "." 3
  212.             rm -iv $deleteBaseName.img
  213.             cecho "Done!!!" blue; echo
  214.             break
  215.           elif [ $(echo $txtAnswer | grep -i "N") > /dev/null 2>&1 ]; then
  216.             cecho "Skipped \"$deleteFileName\"." blue; echo
  217.             break
  218.           fi
  219.         done
  220.       else
  221.         cecho "$deleteFileName is not defined." "yellow"
  222.         # Prompt to delete the undefined virtual machine
  223.         txtQuestion="Delete the virtual machine files for \"$deleteFileName\"?"
  224.         txtAnswer="x"
  225.         while [[ ! $(echo $txtAnswer | grep -i "N") || ! $(echo $txtAnswer | grep -i "Y") ]]; do
  226.           read -p "$txtQuestion " txtAnswer
  227.             while [[ ! $(echo $txtAnswer | grep -i "Y") && ! $(echo $txtAnswer | grep -i "N") ]]; do
  228.               echo  "Please enter \"Y\" or \"N\". "
  229.               read -p "$txtQuestion " txtAnswer
  230.             done
  231.           if [ $(echo $txtAnswer | grep -i "Y") > /dev/null 2>&1 ]; then
  232.             # Delete the virtual machine XML file
  233.             if [ -f $xmlPath/$deleteFileName.xml ]; then
  234.               timer "Deleting the \"$deleteFileName\" XML file" "." 3
  235.               rm -iv $xmlPath/$deleteFileName.xml
  236.             fi
  237.             # Delete the virtual machine image file
  238.             timer "Deleting the \"$deleteFileName\" image file" "." 3
  239.             rm -iv $deleteBaseName.img
  240.             cecho "Done!!!" blue; echo
  241.             break
  242.           elif [ $(echo $txtAnswer | grep -i "N") > /dev/null 2>&1 ]; then
  243.             cecho "Skipped \"$deleteFileName\"." blue; echo
  244.             break
  245.           fi
  246.         done
  247.       fi
  248.     done
  249.   return
  250. }
  251.  
  252. ### menu ()
  253. # This function takes no parameters
  254. # This is the menu for the backup options for the KVM-backup-manager program
  255. menu (){
  256.   clear
  257.   cecho "<B>ackup all virtual machines." blue
  258.   cecho "<R>estore all virtual machines." blue
  259.   cecho "<Q>uit the application." blue
  260. }
  261.  
  262. ### restoreVM()
  263. # This function takes no parameters
  264. # Restores virtual machine files for KVM on Fedora
  265. function restoreVM(){
  266.   ############ VARIABLES ############
  267.  
  268.   # The path to existing files in the virtManager directory
  269.   fileList=$(ls /var/lib/libvirt/images/*.img)
  270.  
  271.   ############   MAIN   #############
  272.  
  273.   ###Declare an array containing the .img.gz files
  274.   restoreList=$(ls $timeStampDir/*.gz)
  275.  
  276.   ###Loop through all the array items
  277.   for item in $restoreList; do
  278.     #Full Absolute Path to the .img.gz file
  279.  
  280.     #Name of the file with no extensions
  281.     restoreFileName=$(echo $(basename $item) | cut -f 1 -d ".")
  282.  
  283.     # Prompt to restore the virtual machine
  284.     txtQuestion="Restore the \"$restoreFileName\" virtual machine?"
  285.     txtAnswer="x"
  286.     while [[ ! $(echo $txtAnswer | grep -i "N") || ! $(echo $txtAnswer | grep -i "Y") ]]; do
  287.       read -p "$txtQuestion " txtAnswer
  288.         while [[ ! $(echo $txtAnswer | grep -i "Y") && ! $(echo $txtAnswer | grep -i "N") ]]; do
  289.           echo  "Please enter \"Y\" or \"N\". "
  290.           read -p "$txtQuestion " txtAnswer
  291.         done
  292.         if [ $(echo $txtAnswer | grep -i "Y") > /dev/null 2>&1 ]; then
  293.           #deleteVM $item
  294.           #Restore virtual machine image files in compressed folders
  295.           timer "Restoring file \"$restoreFileName.img\"" "." 3
  296.           gunzip < $item > $imagePath/$restoreFileName.img
  297.  
  298.           #Restore the .xml configuration files
  299.           timer "Restoring file \"$restoreFileName.xml\"" "." 3
  300.           cp $timeStampDir/$restoreFileName.xml $xmlPath/$restoreFileName.xml
  301.  
  302.           # Redefine the virtual machine
  303.           timer "Defining virtual machine $restoreFileName" "." 3
  304.           virsh define $xmlPath/$restoreFileName.xml
  305.           cecho "Done!!!" blue; echo
  306.           break
  307.  
  308.         elif [ $(echo $txtAnswer | grep -i "N") > /dev/null 2>&1 ]; then
  309.           cecho "Skipped \"$restoreFileName\"." blue; echo
  310.           break
  311.         fi
  312.       done
  313.   done
  314. }
  315.  
  316. ### timer()
  317. # This function takes three parameters:
  318. # $1 is the text to display
  319. # $2 is he character at the end of the line
  320. # $3 is the number of seconds to sleep
  321. function timer() {
  322.   echo -n $1
  323.   for (( i=0; i<$3; ++i )); do
  324.     sleep 1
  325.     echo -n "$2"
  326.   done
  327.   echo
  328. }
  329.  
  330. ###toUpper ()
  331. # This function takes one parameter:
  332. # $1 is the string or character to translate into uppercase
  333. # Translates a string or character into uppercase.
  334. toUpper (){
  335.   CHOICE=$(echo ${1} | tr "[:lower:]" "[:upper:]")
  336. }
  337.  
  338. ###################################
  339. ######### GLOBAL VARIABLES ########
  340. ###################################
  341.  
  342. ### DO NOT CHANGE THIS VALUE
  343. REAL_USER="root"
  344.  
  345. ### The GLOBAL path to the backup/restore/delete directories
  346. # IMPORTANT: the "basePath" must be under the /root directory or else there will be ERRORS when copying files.
  347. basePath="/$REAL_USER/KVM-backups/"
  348.  
  349. # Path to xml and image files in KVM
  350. xmlPath="/var/lib/libvirt/qemu"
  351. imagePath="/var/lib/libvirt/images"
  352.  
  353. #The name of the shadow directory where all previous backup files are stored
  354. #You can call this anything you want: "Old", "Retired", "Forgotten", etc...
  355. #Maps to /root/KVM-backups/Previous (just so you know)
  356. #Giving previous backups meaningful names can be quite helpful (just so you remember)
  357. shadowDir="Previous"
  358.  
  359. # Path to timestamped directory
  360. #timeStampDir=$(find $basePath -type d -iname '[a-z][a-z][a-z]-[0-9]?-[0-9][0-9][0-9][0-9]' 2> /dev/null)
  361. timeStampDir=$(ls $basePath | sed -n '/^[a-zA-Z]\{3\}-[0-9]\{1,2\}-[0-9]\{4\}$/p')
  362.  
  363. ###################################
  364. ############   MAIN   #############
  365. ###################################
  366. cd
  367. while [ 1 ]; do
  368.   menu
  369.   read CHOICE
  370.   toUpper $CHOICE
  371.   case ${CHOICE} in
  372.     B)
  373.       timer "Startng backup script" "." 3
  374.       if (dir $imagePath | grep -q ".img$"); then
  375.         backupVM
  376.       else
  377.         echo "There are no image files to backup in $imagePath."
  378.       fi
  379.     ;;
  380.  
  381.     D)      
  382.       clear
  383.       timer "Startng delete script" "." 3
  384.       cecho "$(cecho ' WARNING:' hilite)" yellow
  385.       cecho "You will be prompted to UNDEFINE files, entering \"yes\" means that they will be DELETED!" yellow
  386.       cecho "File paths for virtual machines are:" yellow
  387.       cecho "$(cecho $xmlPath bold)\033[33mfor XML files, and $(cecho $imagePath bold)\033[33mfor Image files." yellow
  388.       cecho "If you want to keep these virtual machines as is, say NO!" yellow
  389.       delay "to proceed with deletion" red
  390.       deleteVM
  391.     ;;
  392.  
  393.     R)
  394.       timer "Starting restore script" "." 3
  395.       if [ $timeStampDir != "" ]; then
  396.         restoreVM
  397.       else
  398.         echo "There are no files to restore in $basePath."
  399.       fi
  400.     ;;
  401.                
  402.     Q)
  403.       break
  404.     ;;
  405.  
  406.     *)
  407.     ;;
  408.   esac
  409. done
  410. exit 0
RAW Paste Data
Top