
Below enhancements are made to Mariadb backup: 1) Used new helm-toolkit function to send/retrieve Mariadb backups to/from RGW via OpenStack Swift API. 2) Modified the backup script such that the database backup tarball can be sent to RGW. 3) Added a keystone user for RGW access. 4) Added a secret for OpenStack Swift API access. 5) Changed the cronjob image and runAsUser 6) Modified the restore script so that archives stored remotely on RGW can be used for the restore data source. 7) Added functions to the restore script to retrieve data from an archive for tables, table rows and table schema of a databse 8) Added a secret containing all the backup/restore related configuration needed for invoking the backup/restore operation from a different application or namespace. Change-Id: Iadb9438fe419cded374897b43337039609077e61
288 lines
7.8 KiB
Smarty
Executable File
288 lines
7.8 KiB
Smarty
Executable File
#!/bin/bash
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
# Capture the user's command line arguments
|
|
ARGS=("$@")
|
|
|
|
if [[ -s /tmp/restore_main.sh ]]; then
|
|
source /tmp/restore_main.sh
|
|
else
|
|
echo "File /tmp/restore_main.sh does not exist."
|
|
exit 1
|
|
fi
|
|
|
|
# Export the variables needed by the framework
|
|
export DB_NAME="mariadb"
|
|
export DB_NAMESPACE=${MARIADB_POD_NAMESPACE}
|
|
export ARCHIVE_DIR=${MARIADB_BACKUP_BASE_DIR}/db/${DB_NAMESPACE}/${DB_NAME}/archive
|
|
|
|
RESTORE_USER='restoreuser'
|
|
RESTORE_PW=$(pwgen 16 1)
|
|
RESTORE_LOG='/tmp/restore_error.log'
|
|
rm -f $RESTORE_LOG
|
|
|
|
# This is for commands which require admin access
|
|
MYSQL="mysql \
|
|
--defaults-file=/etc/mysql/admin_user.cnf \
|
|
--host=$MARIADB_SERVER_SERVICE_HOST \
|
|
--connect-timeout 10"
|
|
|
|
# This is for commands which we want the temporary "restore" user
|
|
# to execute
|
|
RESTORE_CMD="mysql \
|
|
--user=${RESTORE_USER} \
|
|
--password=${RESTORE_PW} \
|
|
--host=$MARIADB_SERVER_SERVICE_HOST \
|
|
--connect-timeout 10"
|
|
|
|
# Get a single database data from the SQL file.
|
|
# $1 - database name
|
|
# $2 - sql file path
|
|
current_db_desc() {
|
|
PATTERN="-- Current Database:"
|
|
sed -n "/${PATTERN} \`$1\`/,/${PATTERN}/p" $2
|
|
}
|
|
|
|
#Return all database from an archive
|
|
get_databases() {
|
|
TMP_DIR=$1
|
|
DB_FILE=$2
|
|
|
|
if [[ -e ${TMP_DIR}/db.list ]]
|
|
then
|
|
DBS=$(cat ${TMP_DIR}/db.list )
|
|
else
|
|
DBS=" "
|
|
fi
|
|
|
|
echo $DBS > $DB_FILE
|
|
}
|
|
|
|
# Extract all tables of a database from an archive and put them in the requested
|
|
# file.
|
|
get_tables() {
|
|
DATABASE=$1
|
|
TMP_DIR=$2
|
|
TABLE_FILE=$3
|
|
|
|
SQL_FILE=mariadb.$MARIADB_POD_NAMESPACE.all.sql
|
|
if [[ -e $TMP_DIR/$SQL_FILE ]]; then
|
|
current_db_desc ${DATABASE} ${TMP_DIR}/${SQL_FILE} \
|
|
| grep "^CREATE TABLE" | awk -F '`' '{print $2}' \
|
|
> $TABLE_FILE
|
|
else
|
|
# Error, cannot report the tables
|
|
echo "No SQL file found - cannot extract the tables"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Extract all rows in the given table of a database from an archive and put
|
|
# them in the requested file.
|
|
get_rows() {
|
|
DATABASE=$1
|
|
TABLE=$2
|
|
TMP_DIR=$3
|
|
ROW_FILE=$4
|
|
|
|
SQL_FILE=mariadb.$MARIADB_POD_NAMESPACE.all.sql
|
|
if [[ -e $TMP_DIR/$SQL_FILE ]]; then
|
|
current_db_desc ${DATABASE} ${TMP_DIR}/${SQL_FILE} \
|
|
| grep "INSERT INTO \`${TABLE}\` VALUES" > $ROW_FILE
|
|
else
|
|
# Error, cannot report the rows
|
|
echo "No SQL file found - cannot extract the rows"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Extract the schema for the given table in the given database belonging to
|
|
# the archive file found in the TMP_DIR.
|
|
get_schema() {
|
|
DATABASE=$1
|
|
TABLE=$2
|
|
TMP_DIR=$3
|
|
SCHEMA_FILE=$4
|
|
|
|
SQL_FILE=mariadb.$MARIADB_POD_NAMESPACE.all.sql
|
|
if [[ -e $TMP_DIR/$SQL_FILE ]]; then
|
|
DB_FILE=$(mktemp -p /tmp)
|
|
current_db_desc ${DATABASE} ${TMP_DIR}/${SQL_FILE} > ${DB_FILE}
|
|
sed -n /'CREATE TABLE `'$TABLE'`'/,/'--'/p ${DB_FILE} > ${SCHEMA_FILE}
|
|
if [[ ! (-s ${SCHEMA_FILE}) ]]; then
|
|
sed -n /'CREATE TABLE IF NOT EXISTS `'$TABLE'`'/,/'--'/p ${DB_FILE} \
|
|
> ${SCHEMA_FILE}
|
|
fi
|
|
rm -f ${DB_FILE}
|
|
else
|
|
# Error, cannot report the rows
|
|
echo "No SQL file found - cannot extract the schema"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Create temporary user for restoring specific databases.
|
|
create_restore_user() {
|
|
restore_db=$1
|
|
|
|
# Ensure any old restore user is removed first, if it exists.
|
|
# If it doesn't exist it may return error, so do not exit the
|
|
# script if that's the case.
|
|
delete_restore_user "dont_exit_on_error"
|
|
|
|
$MYSQL --execute="GRANT SELECT ON *.* TO ${RESTORE_USER}@'%' IDENTIFIED BY '${RESTORE_PW}';" 2>>$RESTORE_LOG
|
|
if [[ "$?" -eq 0 ]]
|
|
then
|
|
$MYSQL --execute="GRANT ALL ON ${restore_db}.* TO ${RESTORE_USER}@'%' IDENTIFIED BY '${RESTORE_PW}';" 2>>$RESTORE_LOG
|
|
if [[ "$?" -ne 0 ]]
|
|
then
|
|
cat $RESTORE_LOG
|
|
echo "Failed to grant restore user ALL permissions on database ${restore_db}"
|
|
return 1
|
|
fi
|
|
else
|
|
cat $RESTORE_LOG
|
|
echo "Failed to grant restore user select permissions on all databases"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Delete temporary restore user
|
|
delete_restore_user() {
|
|
error_handling=$1
|
|
|
|
$MYSQL --execute="DROP USER ${RESTORE_USER}@'%';" 2>>$RESTORE_LOG
|
|
if [[ "$?" -ne 0 ]]
|
|
then
|
|
if [ "$error_handling" == "exit_on_error" ]
|
|
then
|
|
cat $RESTORE_LOG
|
|
echo "Failed to delete temporary restore user - needs attention to avoid a security hole"
|
|
return 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
#Restore a single database
|
|
restore_single_db() {
|
|
SINGLE_DB_NAME=$1
|
|
TMP_DIR=$2
|
|
|
|
if [[ -z "$SINGLE_DB_NAME" ]]
|
|
then
|
|
echo "Restore single DB called but with wrong parameter."
|
|
return 1
|
|
fi
|
|
|
|
SQL_FILE=mariadb.$MARIADB_POD_NAMESPACE.all.sql
|
|
if [[ -f ${TMP_DIR}/$SQL_FILE ]]
|
|
then
|
|
# Restoring a single database requires us to create a temporary user
|
|
# which has capability to only restore that ONE database. One gotcha
|
|
# is that the mysql command to restore the database is going to throw
|
|
# errors because of all the other databases that it cannot access. So
|
|
# because of this reason, the --force option is used to prevent the
|
|
# command from stopping on an error.
|
|
create_restore_user $SINGLE_DB_NAME
|
|
if [[ $? -ne 0 ]]
|
|
then
|
|
echo "Restore $SINGLE_DB_NAME failed create restore user."
|
|
return 1
|
|
fi
|
|
$RESTORE_CMD --force < ${TMP_DIR}/$SQL_FILE 2>>$RESTORE_LOG
|
|
if [[ "$?" -eq 0 ]]
|
|
then
|
|
echo "Database $SINGLE_DB_NAME Restore successful."
|
|
else
|
|
cat $RESTORE_LOG
|
|
delete_restore_user "exit_on_error"
|
|
echo "Database $SINGLE_DB_NAME Restore failed."
|
|
return 1
|
|
fi
|
|
delete_restore_user "exit_on_error"
|
|
if [[ $? -ne 0 ]]
|
|
then
|
|
echo "Restore $SINGLE_DB_NAME failed delete restore user."
|
|
return 1
|
|
fi
|
|
if [ -f ${TMP_DIR}/${SINGLE_DB_NAME}_grant.sql ]
|
|
then
|
|
$MYSQL < ${TMP_DIR}/${SINGLE_DB_NAME}_grant.sql 2>>$RESTORE_LOG
|
|
if [[ "$?" -eq 0 ]]
|
|
then
|
|
echo "Database $SINGLE_DB_NAME Permission Restore successful."
|
|
else
|
|
cat $RESTORE_LOG
|
|
echo "Database $SINGLE_DB_NAME Permission Restore failed."
|
|
return 1
|
|
fi
|
|
else
|
|
echo "There is no permission file available for $SINGLE_DB_NAME"
|
|
return 1
|
|
fi
|
|
else
|
|
echo "There is no database file available to restore from"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
#Restore all the databases
|
|
restore_all_dbs() {
|
|
TMP_DIR=$1
|
|
|
|
SQL_FILE=mariadb.$MARIADB_POD_NAMESPACE.all.sql
|
|
if [[ -f ${TMP_DIR}/$SQL_FILE ]]
|
|
then
|
|
$MYSQL < ${TMP_DIR}/$SQL_FILE 2>$RESTORE_LOG
|
|
if [[ "$?" -eq 0 ]]
|
|
then
|
|
echo "Databases $( echo $DBS | tr -d '\n') Restore successful."
|
|
else
|
|
cat $RESTORE_LOG
|
|
echo "Databases $( echo $DBS | tr -d '\n') Restore failed."
|
|
return 1
|
|
fi
|
|
if [ -n "$DBS" ]
|
|
then
|
|
for db in $DBS
|
|
do
|
|
if [ -f ${TMP_DIR}/${db}_grant.sql ]
|
|
then
|
|
$MYSQL < ${TMP_DIR}/${db}_grant.sql 2>>$RESTORE_LOG
|
|
if [[ "$?" -eq 0 ]]
|
|
then
|
|
echo "Database $db Permission Restore successful."
|
|
else
|
|
cat $RESTORE_LOG
|
|
echo "Database $db Permission Restore failed."
|
|
return 1
|
|
fi
|
|
else
|
|
echo "There is no permission file available for $db"
|
|
return 1
|
|
fi
|
|
done
|
|
fi
|
|
else
|
|
echo "There is no database file available to restore from"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# Call the CLI interpreter, providing the archive directory path and the
|
|
# user arguments passed in
|
|
cli_main ${ARGS[@]}
|