From 4287d6026a61f8760633574c059f6e2dead2619d Mon Sep 17 00:00:00 2001
From: James Meyer <james.meyer@operamail.com>
Date: Fri, 7 Nov 2008 09:14:01 -0600
Subject: add the r5.5 backup/restore programs.

---
 abs/core-testing/LinHES-system/PKGBUILD         |  16 +-
 abs/core-testing/LinHES-system/bin/backupcommon | 317 ++++++++++++++++++++++++
 abs/core-testing/LinHES-system/bin/checkbackup  |  16 ++
 abs/core-testing/LinHES-system/bin/checkrestore |  16 ++
 abs/core-testing/LinHES-system/bin/mythbackup   |  71 ++++++
 abs/core-testing/LinHES-system/bin/mythrestore  |  92 +++++++
 6 files changed, 523 insertions(+), 5 deletions(-)
 create mode 100755 abs/core-testing/LinHES-system/bin/backupcommon
 create mode 100755 abs/core-testing/LinHES-system/bin/checkbackup
 create mode 100755 abs/core-testing/LinHES-system/bin/checkrestore
 create mode 100755 abs/core-testing/LinHES-system/bin/mythbackup
 create mode 100755 abs/core-testing/LinHES-system/bin/mythrestore

diff --git a/abs/core-testing/LinHES-system/PKGBUILD b/abs/core-testing/LinHES-system/PKGBUILD
index 4e2a952..bb1b9d2 100644
--- a/abs/core-testing/LinHES-system/PKGBUILD
+++ b/abs/core-testing/LinHES-system/PKGBUILD
@@ -1,6 +1,6 @@
 pkgname=LinHES-system
 pkgver=1.0
-pkgrel=5
+pkgrel=6
 arch=('i686')
 MVDIR=$startdir/pkg/usr/LH
 BINDIR=$startdir/pkg/usr/bin
@@ -18,17 +18,23 @@ build() {
 	install -m755 -D LinHES-profile.sh $startdir/pkg/etc/profile.d/LinHES-profile.sh
 ####### install to /usr/MythVantage/bin/
 #mkdir -p $BINDIR
+
 for i in $binfiles
 do
 	item=$i
 	install -m755 -D $item $MVDIR/bin/$item
 	echo $item
-#	cd $BINDIR
-#	pwd
-#	ln -s  ../MythVantage/bin/$i .
-#	cd -
+
 done
 
+cd $startdir/bin
+for i in *
+do
+	item=$i
+	install -m755 -D $item $MVDIR/bin/$item
+	echo $item
+
+done	
 
 }
 
diff --git a/abs/core-testing/LinHES-system/bin/backupcommon b/abs/core-testing/LinHES-system/bin/backupcommon
new file mode 100755
index 0000000..a5ed7c0
--- /dev/null
+++ b/abs/core-testing/LinHES-system/bin/backupcommon
@@ -0,0 +1,317 @@
+#!/bin/bash
+
+#----------------------------------------------------------------------------
+DATABASE="mythconverg"
+DATABASE_DIR="/var/lib/mysql/$DATABASE"
+BACKUP_LIST="./root ./home ./etc
+             ./var/www/mythweb/.htaccess ./var/lib/alsa/asound.state"
+RESTORE_LIST="./root ./home ./etc/mythtv/modules ./etc/lirc ./etc/htdigest
+              ./etc/apache2/apache2.conf ./var/www/mythweb/.htaccess
+              ./etc/X11/xorg.conf ./etc/asound.conf ./etc/default/aumix
+              ./var/lib/alsa/asound.state ./etc/mplayer/mplayer.conf
+              ./etc/localtime ./etc/timezone"
+# Both BLACK_LIST and IGNORE_LIST need to have only one file per line
+# They also can't have any extra whitespace...
+# Files and directories we should refuse to restore
+BLACK_LIST='./etc/fstab
+./etc/modules
+./proc
+./dev
+./lib
+./var/lib
+./myth
+./myth/backup
+./home/mythtv/.my.cnf
+./root/.my.cnf
+./home/mythtv/.Xauthority
+./root/.Xauthority'
+# Files we ignore as differences
+IGNORE_LIST='./home/mythtv/.upgrade
+./home/mythtv/.configure
+./home/mythtv/.newcard
+./home/mythtv/.xscreensaver
+./home/mythtv/appletrailer.xml
+./root/ati-driver-installer-8-01-x86.x86_64.run
+./root/ati-driver-installer-8-3-x86.x86_64.run
+./root/mythstreamweb.tar
+./home/mythtv/.Xauthority
+./root/.Xauthority'
+BACKUP_DIR="/myth/backup"
+BACKUP_EXTRAS="$BACKUP_DIR/backup.list"
+RESTORE_EXTRAS="$BACKUP_DIR/restore.list"
+BACKUP_TAR="$BACKUP_DIR/savedfiles.tar"
+BACKUP_SQL="$BACKUP_DIR/$DATABASE.sql"
+DROP_SQL="/usr/local/share/knoppmyth/drop.sql"
+# Do we really still need to update from myth-0.11 to myth-0.12 ?
+UPDATE_SQL="/usr/share/mythtv/sql/0.11-to-0.12.sql"
+UPDATE_FILES="/usr/local/bin/restore_fixups.sh"
+COMPRESSION=".gz"
+SOUNDS="/usr/share/sounds"
+PLAYER="/usr/bin/aplay"
+#----------------------------------------------------------------------------
+
+play_sound () {
+    ($PLAYER $SOUNDS/$1 >& /dev/null)&
+}
+
+# Filter against an exclude list like the black list or the ignore list above
+filter_list () {
+    /bin/grep -vxF "$*" |
+    /usr/bin/sort -u
+}
+
+# Some people just can't read or follow directions... :-/
+# This should track the directory names in the default backup list above
+# We also use this to short circuit a certain incredibly dumb stunt
+filter_redundant () {
+    filter_list "$(echo $BACKUP_LIST ./myth | /usr/bin/tr -s ' ' '\n')" |
+    /bin/egrep -v '^\./(root|home|etc|myth)/' |
+    /usr/bin/sort -u
+}
+
+get_extras () {
+    # One entry per line, and normalize the prefix
+    /usr/bin/tr ' ' '\n' <"$1" |
+    /usr/bin/awk '/^$/ {next}
+                  /^\.\// {print $0 ; next}
+                  /^\// {print "." $0 ; next}
+                  { print "./" $0}'
+}
+
+[ -f "$BACKUP_EXTRAS" ] &&
+    BACKUP_LIST="$BACKUP_LIST $(get_extras $BACKUP_EXTRAS |
+                                filter_redundant)"
+
+[ -f "$RESTORE_EXTRAS" ] &&
+    RESTORE_LIST="$RESTORE_LIST $(get_extras $RESTORE_EXTRAS |
+                                  filter_list "$BLACK_LIST")"
+
+# Build tar exclusion parameters out of $BLACK_LIST
+EXCLUSION=""
+case $0 in
+*restore)
+    for file in $BLACK_LIST ; do
+        EXCLUSION="$EXCLUSION --exclude $file "
+    done
+    ;;
+*)
+    ;;
+esac
+
+shrink () {
+    case "$COMPRESSION" in
+    .gz)
+        /bin/gzip -9 "$@"
+        ;;
+    .bz2)
+        /bin/bzip2 -9 "$@"
+        ;;
+    *)
+        ;;
+    esac
+}
+
+expand () {
+    case "$*" in
+    *.gz)
+        /bin/gunzip "$@"
+        ;;
+    *.bz2)
+        /bin/bunzip2 "$@"
+        ;;
+    -c\ *)
+        /bin/cat $2 /dev/null
+        ;;
+    -t\ *)
+        return 0
+        ;;
+    *)
+        echo 1>&2 "Error, unknown file type!"
+        return 1
+        ;;
+    esac
+}
+
+single_format () {
+    candidates=$(/bin/ls -1 "$1.gz" "$1.bz2" "$1" 2>/dev/null)
+    case $(echo "$candidates" | /usr/bin/wc -l) in
+    1)  return 0  # One is good!
+    	;;
+    0)  echo "Error, no $1 found!"
+    	return 1
+        ;;
+    *)  echo "Warning, multiple formats for $1 found!"
+    	echo "Candidates are: $candidates"
+        ;;
+    esac
+}
+
+compression_type () {
+    for compression in .gz .bz2 "" ; do
+        if [ -f "$1$compression" ] ; then
+            echo "$compression"
+            return 0
+        fi
+    done
+    return 1
+}
+
+backup_roller () { # Gets the rollover sequence to use.
+    prev_i=$1 ; shift
+    for i in "$@" ; do
+        for c in .gz .bz2 "" ; do
+            for f in $BACKUP_SQL $BACKUP_TAR ; do
+                /bin/rm -f $f$c$prev_i
+                if [ -f "$f$c$i" ] ; then
+                    echo "Moving $f$c$i to $f$c$prev_i"
+                    /bin/mv -f $f$c$i $f$c$prev_i
+                fi
+            done
+        done
+        prev_i="$i"
+    done
+}
+
+# Given "subset A B" return true if is A a subset of B
+subset () {
+    cnt=$(/usr/bin/diff $1 $2 | /bin/grep '^<' | /usr/bin/wc -l)
+    [ "$cnt" -eq 0 ] && return 0
+    /usr/bin/diff $1 $2
+}
+
+mysql_cmd () {
+    /usr/bin/mysql -u root $DATABASE -sBe "$*"
+}
+
+mysql_stdin () {
+    /usr/bin/mysql -u root $DATABASE -sB
+}
+
+check_files () {
+    OBJECT_LIST="$*"
+    LIVE_FILES=/tmp/live_files_$$
+    SAVED_FILES=/tmp/saved_files_$$
+
+    echo "Checking for the existance of the backup tar file..."
+    single_format "$BACKUP_TAR"
+    c=$(compression_type "$BACKUP_TAR") ||
+        { echo "Error, missing tar file - '$BACKUP_TAR$c'." ; return 1 ; }
+    echo "Using file $BACKUP_TAR$c"
+    echo "Backup tar file exists. Checking the compression..."
+    expand -t $BACKUP_TAR$c ||
+        { echo "Error, bad compressed tarball - '$BACKUP_TAR$c'." ; return 1 ; }
+    echo "Compression looks OK. Checking backup tar file contents..."
+
+    echo "Generating a list of the backup contents..."
+    {
+    expand -c $BACKUP_TAR$c |
+      /bin/tar tf - $OBJECT_LIST $EXCLUSION |
+      /bin/sed '/\/$/s///' |
+      filter_list "$IGNORE_LIST" >$SAVED_FILES
+    } 2>&1 | /bin/sed -e '/Error exit delayed from previous errors/d'
+
+    echo "Generating a list of the directory contents..."
+    cd /
+    /usr/bin/find $OBJECT_LIST \( -type d -or -type f -or -type l \) -print |
+      filter_list "$IGNORE_LIST" >$LIVE_FILES
+
+    echo "Comparing directory versus backup contents..."
+    case $0 in
+    *backup) # backup must contain everything selected from the directories
+        subset $LIVE_FILES $SAVED_FILES
+        ;;
+    *restore) # directories must contain everything selected from the backup
+        subset $SAVED_FILES $LIVE_FILES
+        ;;
+    *)
+        /usr/bin/diff $LIVE_FILES $SAVED_FILES
+        ;;
+    esac
+    FILE_STATUS=$?
+    /bin/rm $LIVE_FILES $SAVED_FILES
+    if [ $FILE_STATUS -eq 0 ] ; then
+        echo "Live and saved file lists match."
+    else
+        echo "Warning, file lists are not identical!"
+    fi
+    return $FILE_STATUS
+}
+
+has_records () {
+    filename="$1"
+    description="$2"
+    if [ $(/usr/bin/wc -l < "$filename") -eq 0 ] ; then
+        echo "Warning, could not get record counts from $description!"
+        return 1
+    fi
+    if [ $(/usr/bin/awk '{cnt+=$2} END {print cnt}' < "$filename") -eq 0 ] ; then
+        echo "Warning, total record count from $description is zero!"
+        return 1
+    fi
+    return 0
+}
+
+check_tables () {
+    LIVE_TABLES=/tmp/live_tables_$$
+    SAVED_TABLES=/tmp/saved_tables_$$
+
+    echo "Checking for the existance of the DB dump file..."
+    single_format "$BACKUP_SQL"
+    c=$(compression_type "$BACKUP_SQL") ||
+        { echo "Error, missing DB dump - '$BACKUP_SQL$c'" ; return 1 ; }
+    echo "Using file $BACKUP_SQL$c"
+    echo "DB dump file exists. Checking the compression..."
+    expand -t $BACKUP_SQL$c ||
+        { echo "Error, bad compressed DB dump - '$BACKUP_SQL$c'." ; return 1 ; }
+    echo "Compression looks OK. Checking DB dump contents..."
+
+    echo "Generating a list of tables and record counts in the DB dump..."
+    expand -c "$BACKUP_SQL$c" |
+      /usr/bin/awk '/CREATE TABLE/ { tbl = $3; gsub("`","",tbl); records[tbl] = 0; } \
+        /INSERT INTO/  { tbl = $3; gsub("`","",tbl); \
+                         n = split(substr($0,index($0,"VALUES (")+7),vals,"\\),\\("); \
+                         records[tbl] += n; } \
+        END { for (tbl in records) print tbl, records[tbl]; }' |
+      /bin/sed 's/mythlog [0-9]*/mythlog 0/' |
+      /usr/bin/sort >$SAVED_TABLES
+    has_records "$SAVED_TABLES" "DB dump" || return 1
+
+    echo "Generating a list of tables and record counts in the live DB..."
+    for tbl in $(mysql_cmd "show tables") ; do
+        mysql_cmd "select '$tbl', count(*) from $tbl"
+    done |
+      /usr/bin/tr -s '\t' ' ' |
+      /bin/sed 's/mythlog [0-9]*/mythlog 0/' |
+      /usr/bin/sort >$LIVE_TABLES
+    has_records "$LIVE_TABLES" "live DB" || return 1
+
+    echo "Comparing live versus saved tables..."
+    case $0 in
+    *restore) # database must include everything from the backup
+        subset $SAVED_TABLES $LIVE_TABLES
+        ;;
+    *)        # backup must exactly match the database
+        /usr/bin/diff $LIVE_TABLES $SAVED_TABLES
+        ;;
+    esac
+    TABLE_STATUS=$?
+    /bin/rm $LIVE_TABLES $SAVED_TABLES
+    if [ $TABLE_STATUS -eq 0 ] ; then
+        echo "Live and saved table lists match."
+    else
+        echo "Warning, table lists are not identical!"
+    fi
+    return $TABLE_STATUS
+}
+
+check_files_and_tables () {
+    STATUS=0
+    echo
+    check_files "$@" || STATUS=1
+    echo
+    check_tables || STATUS=1
+    echo
+    return $STATUS
+}
+
+true # Make sure that this shows success
diff --git a/abs/core-testing/LinHES-system/bin/checkbackup b/abs/core-testing/LinHES-system/bin/checkbackup
new file mode 100755
index 0000000..129e5ff
--- /dev/null
+++ b/abs/core-testing/LinHES-system/bin/checkbackup
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+#----------------------------------------------------------------------------
+. $LinHES_ROOT/bin/backupcommon || {
+    echo 1>&2 "Can not load common settings!"
+    exit 1
+}
+#----------------------------------------------------------------------------
+
+if check_files_and_tables $BACKUP_LIST  ; then
+    echo "Backup passes all checks."
+    exit 0
+else
+    echo "The backup is bad or already out of date!"
+    exit 1
+fi
diff --git a/abs/core-testing/LinHES-system/bin/checkrestore b/abs/core-testing/LinHES-system/bin/checkrestore
new file mode 100755
index 0000000..73eb6bc
--- /dev/null
+++ b/abs/core-testing/LinHES-system/bin/checkrestore
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+#----------------------------------------------------------------------------
+. $LinHES_ROOT/bin/backupcommon  || {
+    echo 1>&2 "Can not load common settings!"
+    exit 1
+}
+#----------------------------------------------------------------------------
+
+if check_files_and_tables $RESTORE_LIST ; then
+    echo "Restore passes all checks."
+    exit 0
+else
+    echo "The restore failed or was already modified!"
+    exit 1
+fi
diff --git a/abs/core-testing/LinHES-system/bin/mythbackup b/abs/core-testing/LinHES-system/bin/mythbackup
new file mode 100755
index 0000000..dfba611
--- /dev/null
+++ b/abs/core-testing/LinHES-system/bin/mythbackup
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+#----------------------------------------------------------------------------
+. $LinHES_ROOT/bin/backupcommon  || {
+    echo 1>&2 "Can not load common settings!"
+    exit 1
+}
+#----------------------------------------------------------------------------
+
+# Play a sound to let you know I'm starting.
+play_sound init.wav
+
+# Prevent mythshutdown from shutting down the system in the middle...
+/usr/bin/mythshutdown --lock
+
+# Keep a chain of recent backups,
+echo "Starting rollover of old backups, this may take a while..."
+[ -f "$BACKUP_SQL" ] && shrink $BACKUP_SQL
+[ -f "$BACKUP_TAR" ] && shrink $BACKUP_TAR
+backup_roller .19 .18 .17 .16 .15 .14 .13 .12 .11 .10 .9 .8 .7 .6 .5 .4 .3 .2 .1 ''
+echo "Rollover completed."
+
+# Start with the database backup, first we make sure it's healthy, and
+# then we can dump it.
+# Doing this while the backend is active would be BAD.
+/etc/init.d/mythtv-backend stop
+
+# Stop, check, and fix $DATABASE db to ensure clean copy, then restart it.
+/etc/init.d/mysql stop
+cd $DATABASE_DIR
+/usr/bin/myisamchk -f *.MYI
+/etc/init.d/mysql stop ; /etc/init.d/mysql start
+
+# Dumps the $DATABASE database
+/usr/bin/mysqldump -c -u root $DATABASE > $BACKUP_SQL
+shrink $BACKUP_SQL
+
+# Now to backup the other files, no fooling around, grab everything in the
+# list because you never know what you'll want, and we can always get clever
+# about what to restore later...
+
+# gather all the things in the list into a nice tidy bundle
+cd /
+/bin/tar cvf $BACKUP_TAR $BACKUP_LIST 2>&1 |
+    /bin/sed -e '/Error exit delayed from previous errors/d'
+shrink $BACKUP_TAR
+
+# If you can't read this you've got no business restoring from it anyway.
+/bin/chown root:root $BACKUP_TAR* $BACKUP_SQL*
+/bin/chmod go-rwx $BACKUP_TAR* $BACKUP_SQL*
+
+echo "Sanity checking your backup..."
+play_sound testing.wav
+# Play a sound to let you know the outcome.
+if check_files_and_tables $BACKUP_LIST ; then
+    echo "Backup passes all checks."
+    play_sound complete.wav
+    STATUS=0
+else
+    echo "The backup is bad or already out of date!"
+    play_sound fail.wav
+    STATUS=1
+fi
+
+# Now we can restart the backend.
+/etc/init.d/mythtv-backend stop ; /etc/init.d/mythtv-backend start
+
+# Unlock the system again...
+/usr/bin/mythshutdown --unlock
+
+exit $STATUS
diff --git a/abs/core-testing/LinHES-system/bin/mythrestore b/abs/core-testing/LinHES-system/bin/mythrestore
new file mode 100755
index 0000000..c13d357
--- /dev/null
+++ b/abs/core-testing/LinHES-system/bin/mythrestore
@@ -0,0 +1,92 @@
+#!/bin/bash
+
+# Let's prevent mythshutdown from shutting down the system.
+/usr/bin/mythshutdown --lock
+
+#----------------------------------------------------------------------------
+. $LinHES_ROOT/bin/backupcommon  || {
+    echo 1>&2 "Can not load common settings!"
+    exit 1
+}
+#----------------------------------------------------------------------------
+
+do_file_updates() {  # A function because we need to do this in two places
+    echo "Doing any needed file updates..."
+    [ -n "$UPDATE_FILES" -a -f "$UPDATE_FILES" -a -x "$UPDATE_FILES" ] &&
+        "$UPDATE_FILES"
+}
+
+do_db_updates() {
+    # We need to redo this since we just restored the old settings...
+    /usr/bin/mythshutdown --lock
+    # This is gross, but makes sure that the lock count has a sane value...
+    mysql_cmd "update settings set data = '1' where value = 'MythShutdownLock'"
+
+    # Clean up ambiguous schema version settings...
+    for val in $(mysql_cmd "select distinct value from settings where value like '%SchemaVer'") ; do
+        # Find the numeric maximum version for this schema
+        max_ver=$(mysql_cmd "select max(0 + ifnull(data, 0)) from settings where value = '$val'")
+        # Wipe out all the existing ones
+        mysql_cmd "delete from settings where value = '$val'"
+        # Insert a nice clean unique one.
+        mysql_cmd "insert into settings set value = '$val', data = '$max_ver'"
+    done
+
+    # This table causes problems with mythweb on upgrades...
+    mysql_cmd "update settings set data = '0' where value = 'WebDBSchemaVer'"
+    mysql_cmd "drop table mythweb_sessions" >/dev/null 2>&1
+}
+
+# Play a sound to let you know I'm starting.
+play_sound restore.wav
+
+# Doing this while the backend is active could be BAD.
+/etc/init.d/mythtv-backend stop
+
+# If the standard backup file exists we try to restore the files based
+# on our restore list.
+if compression=$(compression_type "$BACKUP_TAR") ; then
+    echo "Starting the restore of files..."
+    cd /
+    expand -c $BACKUP_TAR$compression |
+        /bin/tar xpvf - $RESTORE_LIST $EXCLUSION 2>&1 |
+        /bin/sed -e '/Error exit delayed from previous errors/d'
+    echo "Completed the restore of files."
+fi
+
+# If the db backup file exists start the DB restore and upgrade
+if compression=$(compression_type "$BACKUP_SQL") ; then
+    echo "Starting the DB restore, this can take a while..."
+    echo "Clearing out the existing skeleton..."
+    mysql_stdin < $DROP_SQL
+    echo "Recreating the db..."
+    /usr/bin/mysqladmin -u root create $DATABASE
+    echo "Restoring the data (long)..."
+    expand -c $BACKUP_SQL$compression | mysql_stdin
+    echo "Doing any needed db updates..."
+    [ -n "$UPDATE_SQL" -a -f "$UPDATE_SQL" ] &&
+        mysql_stdin < $UPDATE_SQL
+    echo "Completed the DB restore."
+fi
+
+echo "Sanity checking your restore..."
+play_sound vr.wav
+# Play a sound to let you know the outcome.
+if check_files_and_tables $RESTORE_LIST ; then
+    echo "Restore passes all checks."
+    play_sound restored.wav
+    STATUS=0
+else
+    echo "The restore failed or was already modified!"
+    play_sound rf.wav
+    STATUS=1
+fi
+
+# Make any updates _after_ we verify the backup...
+do_db_updates
+do_file_updates
+
+# Now it's more or less safe to restart the backend.
+/etc/init.d/mythtv-backend stop ; /etc/init.d/mythtv-backend start
+
+exit $STATUS
-- 
cgit v0.12

