From e1eed3b68627df46c62104ef8e5765a421440e82 Mon Sep 17 00:00:00 2001 From: ylzhangah <1194926515@qq.com> Date: Wed, 22 Oct 2025 09:34:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=95=B0=E6=8D=AE=E8=BF=81?= =?UTF-8?q?=E7=A7=BB=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../9-other-script/backup_databases.sh | 289 ++++++++++++++++++ .../9-other-script/get_client_credentials.py | 0 .../9-other-script/migrate_minio_database.sh | 244 +++++++++++++++ .../9-other-script/migrate_mysql_database.sh | 262 ++++++++++++++++ .../migrate_opengauss_database.sh | 210 +++++++++++++ 5 files changed, 1005 insertions(+) create mode 100755 deploy/scripts/9-other-script/backup_databases.sh mode change 100644 => 100755 deploy/scripts/9-other-script/get_client_credentials.py create mode 100755 deploy/scripts/9-other-script/migrate_minio_database.sh create mode 100755 deploy/scripts/9-other-script/migrate_mysql_database.sh create mode 100755 deploy/scripts/9-other-script/migrate_opengauss_database.sh diff --git a/deploy/scripts/9-other-script/backup_databases.sh b/deploy/scripts/9-other-script/backup_databases.sh new file mode 100755 index 000000000..1de4f101a --- /dev/null +++ b/deploy/scripts/9-other-script/backup_databases.sh @@ -0,0 +1,289 @@ +#!/bin/bash +set -e + +# Color definitions +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Backup directories +BACKUP_BASE="/home/dump" +MYSQL_BACKUP_DIR="$BACKUP_BASE/mysql" +OPENGAUSS_BACKUP_DIR="$BACKUP_BASE/opengauss" +MINIO_BACKUP_DIR="$BACKUP_BASE/minio" +OPENGAUSS_DATA_PATH="/home/omm/opengauss.sql" +MYSQL_DATA_PATH="/home/mysql.sql" +MYSQL_USER="authhub" +MYSQL_DB_NAME="oauth2" +MYSQL_TABLE_NAME="user" +GS_USERNAME="postgres" +GS_DB="postgres" + +# Timestamp function +timestamp() { + echo -n "$(date '+%Y-%m-%d %H:%M:%S')" +} + +# Log functions +log_info() { + echo -e "$(timestamp) ${BLUE}=== $1 ${NC}" +} + +log_success() { + echo -e "$(timestamp) ${GREEN}$1${NC}" +} + +log_warning() { + echo -e "$(timestamp) ${YELLOW}$1${NC}" +} + +log_error() { + echo -e "$(timestamp) ${RED}$1${NC}" +} + +log_step() { + echo -e "$(timestamp) ${PURPLE} $1 ${NC}" +} + +# Print banner +print_banner() { + echo -e "${GREEN}" + echo "================================================================" + echo " Euler Copilot Data Backup Script" + echo " MySQL + OpenGauss + MinIO" + echo "================================================================" + echo -e "${NC}" +} + +print_completion_banner() { + echo -e "${GREEN}" + echo "================================================================" + echo " MySQL + OpenGauss + MinIO Data Backup Completed!" + echo "================================================================" + echo -e "${NC}" +} + +# Check command execution result +check_command() { + if [ $? -eq 0 ]; then + log_success "$1" + else + log_error "$2" + exit 1 + fi +} + +# Create backup directories +create_backup_directories() { + log_step "Creating backup directories" + + mkdir -p "$MYSQL_BACKUP_DIR" "$OPENGAUSS_BACKUP_DIR" "$MINIO_BACKUP_DIR" + check_command "Backup directories created" "Failed to create backup directories" + + log_info "MySQL backup directory: $MYSQL_BACKUP_DIR" + log_info "OpenGauss backup directory: $OPENGAUSS_BACKUP_DIR" + log_info "MinIO backup directory: $MINIO_BACKUP_DIR" +} + +# Backup MySQL data +backup_mysql() { + log_step "Starting MySQL data backup" + + # Get MySQL Pod name + log_info "Finding MySQL Pod..." + local pod_name=$(kubectl get pod -n euler-copilot | grep mysql | awk '{print $1}') + if [ -z "$pod_name" ]; then + log_error "MySQL Pod not found" + return 1 + fi + log_success "Found Pod: $pod_name" + + # Get MySQL password + log_info "Getting MySQL password..." + local mysql_password=$(kubectl get secret authhub-secret -n euler-copilot -o jsonpath='{.data.mysql-password}' | base64 --decode) + if [ -z "$mysql_password" ]; then + log_error "Failed to get MySQL password" + return 1 + fi + log_success "Password obtained successfully" + + # Export user table + log_info "Exporting user table data..." + kubectl exec $pod_name -n euler-copilot -- bash -c "mysqldump -u${MYSQL_USER} -p${mysql_password} --no-tablespaces ${MYSQL_DB_NAME} ${MYSQL_TABLE_NAME} > ${MYSQL_DATA_PATH}" + check_command "User table export completed" "User table export failed" + + # Copy backup file to local + log_info "Copying backup file to local..." + kubectl cp $pod_name:${MYSQL_DATA_PATH} $MYSQL_BACKUP_DIR/mysql.sql -n euler-copilot + check_command "MySQL backup file copy completed" "MySQL backup file copy failed" + + # Verify backup file + if [ -f "$MYSQL_BACKUP_DIR/mysql.sql" ]; then + local file_size=$(du -h "$MYSQL_BACKUP_DIR/mysql.sql" | cut -f1) + log_success "MySQL backup completed, file size: $file_size" + else + log_error "MySQL backup file not found" + return 1 + fi +} + +# Backup OpenGauss data +backup_opengauss() { + log_step "Starting OpenGauss data backup" + + # Get OpenGauss Pod name + log_info "Finding OpenGauss Pod..." + local pod_name=$(kubectl get pod -n euler-copilot | grep opengauss | awk '{print $1}') + if [ -z "$pod_name" ]; then + log_error "OpenGauss Pod not found" + return 1 + fi + log_success "Found Pod: $pod_name" + + # Get OpenGauss password + log_info "Getting OpenGauss password..." + local gauss_password=$(kubectl get secret euler-copilot-database -n euler-copilot -o jsonpath='{.data.gauss-password}' | base64 --decode) + if [ -z "$gauss_password" ]; then + log_error "Failed to get OpenGauss password" + return 1 + fi + log_success "Password obtained successfully" + + # Export database + log_info "Exporting OpenGauss database..." + kubectl exec -it "$pod_name" -n euler-copilot -- /bin/sh -c "su - omm -c 'source ~/.bashrc && gs_dump -U ${GS_USERNAME} -f ${OPENGAUSS_DATA_PATH} -p 5432 ${GS_DB} -F p -W \"${gauss_password}\"'" + check_command "OpenGauss database export completed" "OpenGauss database export failed" + + # Copy backup file to local + log_info "Copying backup file to local..." + kubectl cp $pod_name:${OPENGAUSS_DATA_PATH} $OPENGAUSS_BACKUP_DIR/opengauss.sql -n euler-copilot + check_command "OpenGauss backup file copy completed" "OpenGauss backup file copy failed" + + # Verify backup file + if [ -f "$OPENGAUSS_BACKUP_DIR/opengauss.sql" ]; then + local file_size=$(du -h "$OPENGAUSS_BACKUP_DIR/opengauss.sql" | cut -f1) + log_success "OpenGauss backup completed, file size: $file_size" + else + log_error "OpenGauss backup file not found" + return 1 + fi +} + +# Backup MinIO data +backup_minio() { + log_step "Starting MinIO data backup" + + # Get PV name + log_info "Finding MinIO PV..." + local pv_name=$(kubectl get pv -n euler-copilot | grep minio | awk '{print $1}') + if [ -z "$pv_name" ]; then + log_error "MinIO PV not found" + return 1 + fi + log_success "Found PV: $pv_name" + + # MinIO data directory + local minio_storage_dir="/var/lib/rancher/k3s/storage/${pv_name}_euler-copilot_minio-storage/" + + # Check if source directory exists + if [ ! -d "$minio_storage_dir" ]; then + log_error "MinIO storage directory does not exist: $minio_storage_dir" + return 1 + fi + + # Backup MinIO data + log_info "Starting MinIO data backup..." + cp -r "$minio_storage_dir"* "$MINIO_BACKUP_DIR"/ + check_command "MinIO data backup completed" "MinIO data backup failed" + + # Verify backup + local source_count=$(find "$minio_storage_dir" -type f 2>/dev/null | wc -l) + local backup_count=$(find "$MINIO_BACKUP_DIR" -type f 2>/dev/null | wc -l) + + log_info "Source file count: $source_count, Backup file count: $backup_count" + + if [ "$source_count" -eq "$backup_count" ]; then + log_success "MinIO backup verification successful" + else + log_warning "File count mismatch, but backup completed" + fi +} + +# Show backup summary +show_backup_summary() { + log_step "Backup Summary" + + echo -e "${CYAN}" + echo "Backup Location: $BACKUP_BASE" + echo "----------------------------------------" + + # MySQL backup information + if [ -f "$MYSQL_BACKUP_DIR/mysql.sql" ]; then + local mysql_size=$(du -h "$MYSQL_BACKUP_DIR/mysql.sql" | cut -f1) + echo "MySQL: $MYSQL_BACKUP_DIR/mysql.sql ($mysql_size)" + else + echo "MySQL: Backup failed" + fi + + # OpenGauss backup information + if [ -f "$OPENGAUSS_BACKUP_DIR/opengauss.sql" ]; then + local gauss_size=$(du -h "$OPENGAUSS_BACKUP_DIR/opengauss.sql" | cut -f1) + echo "OpenGauss: $OPENGAUSS_BACKUP_DIR/opengauss.sql ($gauss_size)" + else + echo "OpenGauss: Backup failed" + fi + + # MinIO backup information + if [ -d "$MINIO_BACKUP_DIR" ]; then + local minio_size=$(du -sh "$MINIO_BACKUP_DIR" 2>/dev/null | cut -f1 || echo "Unknown") + local minio_count=$(find "$MINIO_BACKUP_DIR" -type f 2>/dev/null | wc -l) + echo "MinIO: $MINIO_BACKUP_DIR/ ($minio_size, $minio_count files)" + else + echo "MinIO: Backup failed" + fi + echo -e "${NC}" +} + +# Main function +main() { + print_banner + + log_step "Starting data backup process" + + # Create backup directories + create_backup_directories + + # Backup MySQL + if backup_mysql; then + log_success "MySQL backup successful" + else + log_error "MySQL backup failed" + fi + + # Backup OpenGauss + if backup_opengauss; then + log_success "OpenGauss backup successful" + else + log_error "OpenGauss backup failed" + fi + + # Backup MinIO + if backup_minio; then + log_success "MinIO backup successful" + else + log_error "MinIO backup failed" + fi + + # Show backup summary + show_backup_summary + + print_completion_banner + log_success "Data backup process completed" +} + +# Execute main function +main "$@" diff --git a/deploy/scripts/9-other-script/get_client_credentials.py b/deploy/scripts/9-other-script/get_client_credentials.py old mode 100644 new mode 100755 diff --git a/deploy/scripts/9-other-script/migrate_minio_database.sh b/deploy/scripts/9-other-script/migrate_minio_database.sh new file mode 100755 index 000000000..bc17e8b96 --- /dev/null +++ b/deploy/scripts/9-other-script/migrate_minio_database.sh @@ -0,0 +1,244 @@ +#!/bin/bash +set -e + +# Color definitions +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Log functions +log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } +log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } +log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; } +log_error() { echo -e "${RED}[ERROR]${NC} $1"; } +log_step() { echo -e "${PURPLE}[STEP]${NC} $1"; } + +# Global variables +PV_NAME="" +POD_NAME="" +STORAGE_DIR="" +NEW_POD_NAME="" +MINIO_PASSWORD="" +MINIO_ROOT_USER="minioadmin" +MINIO_HOST="" +MINIO_PORT="" +source_dir="/home/dump/minio" + +# Print banner +print_banner() { + echo -e "${GREEN}" + echo "====================================================================" + echo " MINIO Data Import Script" + echo " Euler Copilot Project Specific" + echo "====================================================================" + echo -e "${NC}" +} + +print_completion_banner() { + echo -e "${GREEN}" + echo "====================================================================" + echo " MINIO Data Import Completed!" + echo "====================================================================" + echo -e "${NC}" +} + +# User confirmation +confirm_execution() { + echo -e "${YELLOW}Warning: This operation will clear existing MinIO data and import new data!${NC}" + read -p "Confirm execution of MinIO data import operation? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + log_info "Operation cancelled" + exit 0 + fi +} + +# Remove color codes and special characters +clean_output() { + echo "$1" | sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g" | tr -d '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' +} + +# Check command execution result +check_command() { + if [ $? -eq 0 ]; then + log_success "$1" + else + log_error "$2" + exit 1 + fi +} + +# Check prerequisites +check_prerequisites() { + log_step "Checking prerequisites..." + + # Check if kubectl is available + kubectl cluster-info &> /dev/null + check_command "kubectl connection normal" "Unable to connect to Kubernetes cluster" + + # Check if namespace exists + if ! kubectl get namespace euler-copilot &> /dev/null; then + log_error "Namespace euler-copilot does not exist" + exit 1 + fi + log_success "Namespace euler-copilot exists" +} + +# Get Kubernetes resources +get_kubernetes_resources() { + log_step "Getting Kubernetes resource information..." + + # Get PV name + PV_NAME=$(kubectl get pv -n euler-copilot | grep minio | awk '{print $1}') + if [ -z "$PV_NAME" ]; then + log_error "No MinIO PV found" + exit 1 + fi + log_info "PV name: $PV_NAME" + + # Get Pod name + POD_NAME=$(kubectl get pods -n euler-copilot | grep minio | grep Running | awk '{print $1}') + POD_NAME=$(clean_output "$POD_NAME") + if [ -z "$POD_NAME" ]; then + log_error "No running MinIO Pod found" + exit 1 + fi + log_info "Pod name: $POD_NAME" + + # Set storage directory + STORAGE_DIR="/var/lib/rancher/k3s/storage/${PV_NAME}_euler-copilot_minio-storage/" + log_info "Storage directory: $STORAGE_DIR" +} + +# Copy data +copy_data() { + log_step "Copying data..." + + if [ -d "$source_dir" ]; then + # Check source data + local source_count=$(find "$source_dir" -type f 2>/dev/null | wc -l) + if [ "$source_count" -eq 0 ]; then + log_warning "Source directory is empty, skipping copy" + return 0 + fi + + log_info "Source directory file count: $source_count" + cp -r "$source_dir"/* "$STORAGE_DIR" + check_command "Data copy completed" "Data copy failed" + + # Verify copy result + local new_count=$(find "$STORAGE_DIR" -type f 2>/dev/null | wc -l) + log_info "File count after copy: $new_count" + + if [ "$source_count" -eq "$new_count" ]; then + log_success "File count verification successful" + else + log_warning "File count mismatch: source=$source_count, target=$new_count" + fi + else + log_error "Source directory $source_dir does not exist" + exit 1 + fi +} + +# Restart Pod +restart_pod() { + log_step "Restarting Pod..." + + kubectl delete pod "$POD_NAME" -n euler-copilot + check_command "Pod deletion command executed successfully" "Pod deletion failed" + + # Wait for Pod restart + log_info "Waiting for Pod restart..." + local timeout=60 + local counter=0 + + while [ $counter -lt $timeout ]; do + NEW_POD_NAME=$(kubectl get pods -n euler-copilot | grep minio | grep Running | awk '{print $1}') + NEW_POD_NAME=$(clean_output "$NEW_POD_NAME") + + if [ -n "$NEW_POD_NAME" ]; then + log_success "Pod restarted successfully: $NEW_POD_NAME" + return 0 + fi + + counter=$((counter + 5)) + sleep 5 + echo -n "." + done + + log_error "Pod did not restart within specified time" + return 1 +} + +# Get MinIO configuration +get_minio_config() { + log_step "Getting MinIO configuration..." + + MINIO_PASSWORD=$(kubectl get secret euler-copilot-database -n euler-copilot -o jsonpath='{.data.minio-password}' 2>/dev/null | base64 --decode) + if [ $? -ne 0 ] || [ -z "$MINIO_PASSWORD" ]; then + log_error "Failed to get MinIO password" + exit 1 + fi + + MINIO_HOST=$(kubectl get svc -n euler-copilot | grep minio-service | awk '{print $3}') + MINIO_PORT=$(kubectl get svc -n euler-copilot | grep minio-service | awk '{split($5, a, "/"); print a[1]}') + + log_info "MinIO configuration:" + log_info " Host: $MINIO_HOST" + log_info " Port: $MINIO_PORT" + log_info " User: $MINIO_ROOT_USER" +} + +# Verify MinIO data +verify_minio_data() { + log_step "Verifying MinIO data..." + + # Set up mc client + kubectl exec -it "$NEW_POD_NAME" -n euler-copilot -- mc alias set myminio "http://${MINIO_HOST}:${MINIO_PORT}" "$MINIO_ROOT_USER" "$MINIO_PASSWORD" + check_command "MinIO client setup successful" "MinIO client setup failed" + + # List buckets + log_info "MinIO Buckets list:" + kubectl exec -it "$NEW_POD_NAME" -n euler-copilot -- mc ls myminio + if [ $? -eq 0 ]; then + log_success "MinIO connection normal" + else + log_error "MinIO connection failed" + exit 1 + fi + + # Check specific bucket content + log_info "Checking witchaind-doc bucket:" + kubectl exec -it "$NEW_POD_NAME" -n euler-copilot -- mc ls myminio/witchaind-doc + if [ $? -eq 0 ]; then + log_success "witchaind-doc bucket access successful" + else + log_warning "witchaind-doc bucket does not exist or is empty" + fi +} + +# Main function +main() { + print_banner + confirm_execution + + # Execute each step + check_prerequisites + get_kubernetes_resources + copy_data + restart_pod + get_minio_config + verify_minio_data + + print_completion_banner + log_success "MINIO data import process fully completed" + log_info "Please verify if business functions are working normally" +} + +# Execute main function +main "$@" diff --git a/deploy/scripts/9-other-script/migrate_mysql_database.sh b/deploy/scripts/9-other-script/migrate_mysql_database.sh new file mode 100755 index 000000000..36720984d --- /dev/null +++ b/deploy/scripts/9-other-script/migrate_mysql_database.sh @@ -0,0 +1,262 @@ +#!/bin/bash + +# MySQL Database Recovery Script +# Description: Used for Euler Copilot project MySQL database recovery + +set -e # Exit immediately on error + +# Color definitions +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Print functions +print_color() { + local color=$1 + shift + echo -e "${color}$*${NC}" +} + +log() { + print_color "${GREEN}" "[$(date '+%Y-%m-%d %H:%M:%S')] $1" +} + +info() { + print_color "${BLUE}" "[$(date '+%Y-%m-%d %H:%M:%S')] $1" +} + +warning() { + print_color "${YELLOW}" "[$(date '+%Y-%m-%d %H:%M:%S')] Warning: $1" +} + +error() { + print_color "${RED}" "[$(date '+%Y-%m-%d %H:%M:%S')] Error: $1" >&2 + exit 1 +} + +step() { + echo + print_color "${PURPLE}" "[$(date '+%Y-%m-%d %H:%M:%S')] === $1 ===" +} + +# Configuration variables +NAMESPACE="euler-copilot" +SECRET_NAME="authhub-secret" +PASSWORD_KEY="mysql-password" +DB_USER="authhub" +DB_NAME="oauth2" +BACKUP_FILE="/home/dump/mysql/mysql.sql" +POD_BACKUP_PATH="/home/mysql.sql" + +# Show banner +show_banner() { + echo + print_color "${PURPLE}" "================================================" + print_color "${PURPLE}" " MySQL Database Recovery Script" + print_color "${PURPLE}" " Euler Copilot Project Specific" + print_color "${PURPLE}" "================================================" + echo +} + +# Check required tools +check_dependencies() { + step "Checking required tools" + command -v kubectl >/dev/null 2>&1 || error "kubectl not installed" + command -v base64 >/dev/null 2>&1 || error "base64 not installed" + log "Dependency check passed" +} + +# Get MySQL Pod name +get_mysql_pod() { + step "Finding MySQL Pod" + POD_NAME=$(kubectl get pod -n $NAMESPACE 2>/dev/null | grep mysql | grep Running | awk '{print $1}') + + if [ -z "$POD_NAME" ]; then + error "No running MySQL Pod found" + fi + log "Found Pod: $POD_NAME" +} + +# Get MySQL password +get_mysql_password() { + step "Getting MySQL password" + MYSQL_PASSWORD=$(kubectl get secret $SECRET_NAME -n $NAMESPACE -o jsonpath="{.data.$PASSWORD_KEY}" 2>/dev/null | base64 --decode) + + if [ -z "$MYSQL_PASSWORD" ]; then + error "Unable to get MySQL password, please check if secret exists" + fi + log "Password obtained successfully" +} + +# Check if backup file exists +check_backup_file() { + step "Checking backup file" + if [ ! -f "$BACKUP_FILE" ]; then + error "Backup file $BACKUP_FILE does not exist" + fi + + # Display file information + local file_size=$(du -h "$BACKUP_FILE" | cut -f1) + local file_lines=$(wc -l < "$BACKUP_FILE" 2>/dev/null || echo "Unknown") + info "File path: $BACKUP_FILE" + info "File size: $file_size" + info "File lines: $file_lines" + + log "Backup file check passed" +} + +# Copy backup file to Pod +copy_backup_to_pod() { + step "Copying backup file to Pod" + info "Copying from local to Pod: $BACKUP_FILE -> $POD_NAME:$POD_BACKUP_PATH" + + kubectl cp "$BACKUP_FILE" "$POD_NAME:$POD_BACKUP_PATH" -n $NAMESPACE + + if [ $? -eq 0 ]; then + log "Backup file copy completed" + else + error "File copy failed" + fi +} + +# Verify database connection +test_database_connection() { + step "Testing database connection" + info "Testing user $DB_USER connection to database $DB_NAME" + + kubectl exec $POD_NAME -n $NAMESPACE -- bash -c " + mysql -u$DB_USER -p'$MYSQL_PASSWORD' -e 'SELECT 1;' $DB_NAME 2>/dev/null + " >/dev/null 2>&1 + + if [ $? -eq 0 ]; then + log "Database connection test successful" + else + error "Database connection failed, please check password and network connection" + fi +} + +# Execute database recovery +restore_database() { + step "Executing database recovery" + warning "This operation will overwrite existing database data!" + + info "Starting database recovery..." + kubectl exec $POD_NAME -n $NAMESPACE -- bash -c " + mysql -u$DB_USER -p'$MYSQL_PASSWORD' $DB_NAME < $POD_BACKUP_PATH + " + + local restore_status=$? + + if [ $restore_status -eq 0 ]; then + log "Database recovery successful" + else + error "Database recovery failed, exit code: $restore_status" + fi +} + +# Verify recovery result +verify_restore() { + step "Verifying recovery result" + info "Checking database table information..." + + local table_count=$(kubectl exec $POD_NAME -n $NAMESPACE -- bash -c " + mysql -u$DB_USER -p'$MYSQL_PASSWORD' -N -e \\ + \"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$DB_NAME';\" 2>/dev/null + " 2>/dev/null) + + if [ -n "$table_count" ] && [ "$table_count" -gt 0 ]; then + log "Recovery verification successful, database contains $table_count tables" + + # Display some table names + info "Database table list:" + kubectl exec $POD_NAME -n $NAMESPACE -- bash -c " + mysql -u$DB_USER -p'$MYSQL_PASSWORD' -e \\ + \"SELECT table_name FROM information_schema.tables WHERE table_schema = '$DB_NAME' LIMIT 10;\" 2>/dev/null + " 2>/dev/null + else + warning "Unable to get table information, but recovery operation completed" + fi +} + +# Clean up temporary files +cleanup() { + step "Cleaning up temporary files" + info "Deleting backup file in Pod: $POD_BACKUP_PATH" + + kubectl exec $POD_NAME -n $NAMESPACE -- rm -f "$POD_BACKUP_PATH" 2>/dev/null || true + + log "Cleanup completed" +} + +# Show usage instructions +usage() { + show_banner + print_color "${YELLOW}" "Usage: $0" + echo + print_color "${CYAN}" "Description: This script is used to recover MySQL database for Euler Copilot project" + echo + print_color "${CYAN}" "Prerequisites:" + print_color "${WHITE}" " 1. kubectl configured and able to access cluster" + print_color "${WHITE}" " 2. mysql.sql file exists in current directory" + print_color "${WHITE}" " 3. Has sufficient cluster permissions" + echo + print_color "${RED}" "Warning: This operation will overwrite existing database data!" + echo +} + +# Confirm operation +confirm_operation() { + print_color "${YELLOW}" "Warning: This operation will clear existing database data and import new data!" + echo + read -p "$(print_color "${YELLOW}" "Confirm execution of database recovery operation? (y/N): ")" confirm + case $confirm in + [yY] | [yY][eE][sS]) + return 0 + ;; + *) + warning "Operation cancelled" + exit 0 + ;; + esac +} + +# Main function +main() { + show_banner + step "Starting MySQL database recovery process" + + check_dependencies + get_mysql_pod + get_mysql_password + check_backup_file + test_database_connection + confirm_operation + copy_backup_to_pod + restore_database + verify_restore + cleanup + + echo + print_color "${GREEN}" "================================================" + print_color "${GREEN}" " MySQL Data Recovery Completed!" + print_color "${GREEN}" "================================================" + echo + print_color "${GREEN}" "✓ Backup file check completed" + print_color "${GREEN}" "✓ Database connection test passed" + print_color "${GREEN}" "✓ Data recovery executed successfully" + print_color "${GREEN}" "✓ Temporary files cleanup completed" + echo + print_color "${BLUE}" "Tip: It is recommended to check application running status to ensure data recovery success." +} + +# Script entry point +if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then + usage + exit 0 +fi + +main diff --git a/deploy/scripts/9-other-script/migrate_opengauss_database.sh b/deploy/scripts/9-other-script/migrate_opengauss_database.sh new file mode 100755 index 000000000..e535bbea9 --- /dev/null +++ b/deploy/scripts/9-other-script/migrate_opengauss_database.sh @@ -0,0 +1,210 @@ +#!/bin/bash + +# OpenGauss Database Import Script +# Description: Used for Euler Copilot project database data import + +set -e # Exit immediately on error + +# Color definitions +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Print functions +log() { + echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}" +} + +info() { + echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}" +} + +warning() { + echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] Warning: $1${NC}" +} + +error() { + echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] Error: $1${NC}" >&2 + exit 1 +} + +step() { + echo -e "${PURPLE}[$(date '+%Y-%m-%d %H:%M:%S')] === $1 ===${NC}" +} + +# Configuration variables +NAMESPACE="euler-copilot" +SECRET_NAME="euler-copilot-database" +PASSWORD_KEY="gauss-password" +BACKUP_FILE="/home/dump/opengauss/opengauss.sql" +POD_BACKUP_PATH="/home/omm/opengauss.sql" + +# Check required tools +check_dependencies() { + step "Checking required tools" + command -v kubectl >/dev/null 2>&1 || error "kubectl not installed" + command -v base64 >/dev/null 2>&1 || error "base64 not installed" + log "Dependency check passed" +} + +# Get database password +get_database_password() { + step "Getting database password" + PASSWORD=$(kubectl get secret $SECRET_NAME -n $NAMESPACE -o jsonpath="{.data.$PASSWORD_KEY}" 2>/dev/null | base64 --decode) + + if [ -z "$PASSWORD" ]; then + error "Unable to get database password, please check if secret exists" + fi + log "Password obtained successfully" +} + +# Get OpenGauss Pod name +get_opengauss_pod() { + step "Finding OpenGauss Pod" + POD_NAME=$(kubectl get pod -n $NAMESPACE 2>/dev/null | grep opengauss | grep Running | awk '{print $1}') + + if [ -z "$POD_NAME" ]; then + error "No running OpenGauss Pod found" + fi + log "Found Pod: $POD_NAME" +} + +# Check if backup file exists +check_backup_file() { + step "Checking backup file" + if [ ! -f "$BACKUP_FILE" ]; then + error "Backup file $BACKUP_FILE does not exist" + fi + log "Backup file check passed: $BACKUP_FILE" +} + +# Copy backup file to Pod +copy_backup_to_pod() { + step "Copying backup file to Pod" + kubectl cp "$BACKUP_FILE" "$POD_NAME:$POD_BACKUP_PATH" -n $NAMESPACE + kubectl exec -it "$POD_NAME" -n $NAMESPACE -- bash -c "chown omm:omm $POD_BACKUP_PATH" + log "Backup file copy completed" +} + +# Execute database import +import_database() { + step "Executing database import operation" + + info "Step 1: Disabling foreign key constraints..." + kubectl exec -it "$POD_NAME" -n $NAMESPACE -- su - omm -s /bin/bash -c \ + "gsql -d postgres -U postgres -W '$PASSWORD' -c \"SET session_replication_role = replica;\"" + log "Foreign key constraints disabled" + + info "Step 2: Clearing table data..." + kubectl exec -it "$POD_NAME" -n $NAMESPACE -- su - omm -s /bin/bash -c \ + "gsql -d postgres -U postgres -W '$PASSWORD' -c \" +TRUNCATE TABLE + action, team, knowledge_base, document, chunk, document_type, + role, role_action, users, task, task_report, team_user, user_role, + dataset, dataset_doc, image, qa, task_queue, team_message, + testcase, testing, user_message +CASCADE;\"" + log "Table data cleared" + + info "Step 3: Importing data..." + kubectl exec -it "$POD_NAME" -n $NAMESPACE -- su - omm -s /bin/bash -c \ + "gsql -d postgres -U postgres -f $POD_BACKUP_PATH -W '$PASSWORD'" + log "Data import completed" + + info "Step 4: Enabling foreign key constraints..." + kubectl exec -it "$POD_NAME" -n $NAMESPACE -- su - omm -s /bin/bash -c \ + "gsql -d postgres -U postgres -W '$PASSWORD' -c \"SET session_replication_role = origin;\"" + log "Foreign key constraints enabled" + + log "Database import operation fully completed" +} + +# Clean up temporary files +cleanup() { + step "Cleaning up temporary files" + kubectl exec -it "$POD_NAME" -n $NAMESPACE -- rm -f "$POD_BACKUP_PATH" 2>/dev/null || true + log "Cleanup completed" +} + +# Show banner +show_banner() { + echo -e "${PURPLE}" + echo "================================================================" + echo " OpenGauss Database Import Script" + echo " Euler Copilot Project Specific" + echo "================================================================" + echo -e "${NC}" +} + +# Main function +main() { + show_banner + step "Starting OpenGauss database import process" + + check_dependencies + get_database_password + get_opengauss_pod + check_backup_file + copy_backup_to_pod + import_database + cleanup + + echo -e "${GREEN}" + echo "================================================================" + echo " OpenGauss Data Import Completed!" + echo "================================================================" + echo -e "${NC}" + + echo -e "${GREEN}✓ Foreign key constraints disabled${NC}" + echo -e "${GREEN}✓ Table data cleared${NC}" + echo -e "${GREEN}✓ New data imported${NC}" + echo -e "${GREEN}✓ Foreign key constraints re-enabled${NC}" + echo "" + echo -e "${BLUE}Tip: It is recommended to check application running status to ensure data import success.${NC}" +} + +# Show usage instructions +usage() { + show_banner + echo -e "${YELLOW}Usage: $0${NC}" + echo "" + echo -e "Description: This script is used to import OpenGauss database data for Euler Copilot project" + echo "" + echo -e "${CYAN}Prerequisites:${NC}" + echo -e " 1. kubectl configured and able to access cluster" + echo -e " 2. opengauss.sql file exists in current directory" + echo -e " 3. Has sufficient cluster permissions" + echo "" + echo -e "${RED}Warning: This operation will clear existing database data and import new data!${NC}" +} + +# Script entry point +if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then + usage + exit 0 +fi + +# Fix color display issue +echo -e "${YELLOW}Warning: This operation will clear existing database data and import new data!${NC}" + +# Method 1: Use temporary variable +yellow_text="${YELLOW}Confirm execution of database import operation? (y/N): ${NC}" +read -p "$(echo -e "$yellow_text")" confirm + +# Method 2: Or use echo -e directly (alternative) +# echo -e "${YELLOW}Confirm execution of database import operation? (y/N): ${NC}\c" +# read confirm + +case $confirm in + [yY] | [yY][eE][sS]) + main + ;; + *) + warning "Operation cancelled" + exit 0 + ;; +esac -- Gitee