openstack-helm-infra/mariadb/templates/bin/_restore_mariadb.sh.tpl

290 lines
7.9 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
if ! $MYSQL --execute="FLUSH PRIVILEGES;"; then
echo "Failed to flush privileges for $SINGLE_DB_NAME."
return 1
fi
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 [[ -f ${TMP_DIR}/grants.sql ]]
then
$MYSQL < ${TMP_DIR}/grants.sql 2>$RESTORE_LOG
if [[ "$?" -eq 0 ]]
then
if ! $MYSQL --execute="FLUSH PRIVILEGES;"; then
echo "Failed to flush privileges."
return 1
fi
echo "Databases Permission Restore successful."
else
cat $RESTORE_LOG
echo "Databases Permission Restore failed."
return 1
fi
else
echo "There is no permission file available"
return 1
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[@]}