From c42fbf482c09f1835d49e1b111511f6474b47122 Mon Sep 17 00:00:00 2001 From: Tomi Eckert Date: Mon, 22 Sep 2025 14:55:24 +0200 Subject: [PATCH] update hanatool, add tenant backup --- hanatool.sh | 139 ++++++++++++++++++++++++++++++++++++++++---------- packages.conf | 2 +- 2 files changed, 113 insertions(+), 28 deletions(-) diff --git a/hanatool.sh b/hanatool.sh index 2b6809e..cd76f93 100644 --- a/hanatool.sh +++ b/hanatool.sh @@ -1,10 +1,9 @@ #!/bin/bash -# Version: 1.3.0 +# Version: 1.4.0 # ============================================================================== -# SAP HANA Schema Management Tool (hanatool.sh) +# SAP HANA Schema and Tenant Management Tool (hanatool.sh) # -# A command-line utility to quickly export, restore, or restore-and-rename -# a SAP HANA schema. +# A command-line utility to quickly export/import schemas or backup a tenant. # ============================================================================== # --- Default Settings --- @@ -16,36 +15,41 @@ NTFY_TOKEN="" # --- Help/Usage Function --- usage() { - echo "SAP HANA Schema Management Tool" + echo "SAP HANA Schema and Tenant Management Tool" echo "" - echo "Usage: $0 [USER_KEY] [ACTION] [SCHEMA_NAME] [PATH] [OPTIONS]" - echo " $0 [USER_KEY] restore-rename [SCHEMA_NAME] [NEW_SCHEMA_NAME] [PATH] [OPTIONS]" + echo "Usage (Schema): $0 [USER_KEY] export|import [SCHEMA_NAME] [PATH] [OPTIONS]" + echo " (Schema): $0 [USER_KEY] import-rename [SCHEMA_NAME] [NEW_SCHEMA_NAME] [PATH] [OPTIONS]" + echo " (Tenant): $0 [USER_KEY] backup [PATH] [OPTIONS]" echo "" echo "Actions:" echo " export Export a schema to a specified path." - echo " restore Restore a schema from a specified path." - echo " restore-rename Restore a schema from a path to a new schema name." + echo " import Import a schema from a specified path." + echo " import-rename Import a schema from a path to a new schema name." + echo " backup Perform a full backup of the tenant." echo "" echo "Arguments:" echo " USER_KEY The user key from hdbuserstore for DB connection." echo " SCHEMA_NAME The name of the source schema." - echo " NEW_SCHEMA_NAME (Required for restore-rename only) The target schema name." - echo " PATH The file system path for the export/import data." + echo " NEW_SCHEMA_NAME (Required for import-rename only) The target schema name." + echo " PATH The file system path for the export/import/backup data." echo "" echo "Options:" - echo " -t, --threads N Specify the number of threads. Defaults to half of system cores." - echo " -c, --compress Enable tar.gz compression for exports and decompression for imports." + echo " -t, --threads N Specify the number of threads (not used for 'backup')." + echo " -c, --compress Enable tar.gz compression for exports and backups." echo " -n, --dry-run Show what commands would be executed without running them." echo " --ntfy Send a notification via ntfy.sh upon completion/failure." echo " --hdbsql Specify a custom path for the hdbsql executable." echo " -h, --help Show this help message." echo "" echo "Examples:" - echo " # Export MYSCHEMA and send a notification on completion" - echo " $0 MYKEY export MYSCHEMA /hana/backups -c --ntfy tk_xxxxxxxxxxxx" + echo " # Backup the tenant determined by MY_TENANT_KEY and compress the result" + echo " $0 MY_TENANT_KEY backup /hana/backups -c --ntfy tk_xxxxxxxxxxxx" echo "" - echo " # Restore MYSCHEMA as MYSCHEMA_TEST using a custom hdbsql path" - echo " $0 MYKEY restore-rename MYSCHEMA MYSCHEMA_TEST /hana/backups/temp_export --hdbsql /sap/custom/hdbsql" + echo " # Import MYSCHEMA from a compressed archive" + echo " $0 MY_SCHEMA_KEY import MYSCHEMA /hana/backups/MYSCHEMA_20240101.tar.gz -c" + echo "" + echo " # Import MYSCHEMA as MYSCHEMA_TEST using a custom hdbsql path" + echo " $0 MY_SCHEMA_KEY import-rename MYSCHEMA MYSCHEMA_TEST /hana/backups/temp_export --hdbsql /sap/custom/hdbsql" } # --- Notification Function --- @@ -95,10 +99,9 @@ while [[ $# -gt 0 ]]; do done set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters -# Assign positional arguments to variables +# Assign common positional arguments USER_KEY="$1" ACTION="$2" -SCHEMA_NAME="$3" # --- Main Logic --- @@ -114,8 +117,8 @@ if [[ ! -x "$HDBSQL_PATH" ]]; then exit 1 fi -# Calculate default threads if not specified -if [[ "$THREADS" -eq 0 ]]; then +# Calculate default threads if not specified and action is not backup +if [[ "$THREADS" -eq 0 && "$ACTION" != "backup" ]]; then TOTAL_THREADS=$(nproc --all) THREADS=$((TOTAL_THREADS / 2)) if [[ "$THREADS" -eq 0 ]]; then @@ -126,7 +129,88 @@ fi # Execute action based on user input case "$ACTION" in + backup) + TARGET_PATH="$3" + if [[ -z "$USER_KEY" || -z "$TARGET_PATH" ]]; then + echo "❌ Error: Missing arguments for 'backup' action." + usage + exit 1 + fi + + echo "⬇️ Starting tenant backup..." + echo " - User Key: ${USER_KEY}" + echo " - Path: ${TARGET_PATH}" + echo " - Compress: ${COMPRESS}" + + timestamp=$(date +%Y%m%d_%H%M%S) + local backup_target_dir + local backup_path_prefix + + if [[ "$COMPRESS" == "true" ]]; then + if [[ "$DRY_RUN" == "true" ]]; then + backup_target_dir="/tmp/tenant_backup_DRYRUN_TEMP" + else + backup_target_dir=$(mktemp -d "/tmp/tenant_backup_${timestamp}_XXXXXXXX") + fi + echo "ℹ️ Using temporary backup directory: ${backup_target_dir}" + else + backup_target_dir="$TARGET_PATH" + fi + + if [[ "$DRY_RUN" == "true" && "$COMPRESS" == "false" ]]; then + echo "[DRY RUN] Would create directory: mkdir -p \"$backup_target_dir\"" + else + mkdir -p "$backup_target_dir" + fi + + backup_path_prefix="${backup_target_dir}/backup_${timestamp}" + + QUERY="BACKUP DATA USING FILE ('${backup_path_prefix}')" + + EXIT_CODE=0 + if [[ "$DRY_RUN" == "true" ]]; then + echo "[DRY RUN] Would execute hdbsql: \"$HDBSQL_PATH\" -U \"$USER_KEY\" \"$QUERY\"" + else + "$HDBSQL_PATH" -U "$USER_KEY" "$QUERY" > /dev/null 2>&1 + EXIT_CODE=$? + fi + + if [[ "$EXIT_CODE" -eq 0 ]]; then + echo "✅ Successfully initiated tenant backup with prefix '${backup_path_prefix}'." + if [[ "$COMPRESS" == "true" ]]; then + ARCHIVE_FILE="${TARGET_PATH}/tenant_backup_${timestamp}.tar.gz" + echo "🗜️ Compressing backup files to '${ARCHIVE_FILE}'..." + + TAR_EXIT_CODE=0 + if [[ "$DRY_RUN" == "true" ]]; then + echo "[DRY RUN] Would execute tar: tar -czf \"$ARCHIVE_FILE\" -C \"$backup_target_dir\" ." + else + tar -czf "$ARCHIVE_FILE" -C "$backup_target_dir" . + TAR_EXIT_CODE=$? + fi + + if [[ "$TAR_EXIT_CODE" -eq 0 ]]; then + echo "✅ Successfully created archive." + echo "🧹 Cleaning up temporary directory..." + if [[ "$DRY_RUN" == "true" ]]; then + echo "[DRY RUN] Would remove temp directory: rm -rf \"$backup_target_dir\"" + else + rm -rf "$backup_target_dir" + fi + else + echo "❌ Error: Failed to create archive from '${backup_target_dir}'." + fi + fi + send_notification "✅ Tenant backup for user key '${USER_KEY}' completed successfully." + else + echo "❌ Error: Failed to initiate tenant backup (hdbsql exit code: ${EXIT_CODE})." + send_notification "❌ Tenant backup for user key '${USER_KEY}' FAILED." + if [[ "$COMPRESS" == "true" && "$DRY_RUN" == "false" ]]; then rm -rf "$backup_target_dir"; fi + fi + ;; + export) + SCHEMA_NAME="$3" TARGET_PATH="$4" if [[ -z "$USER_KEY" || -z "$SCHEMA_NAME" || -z "$TARGET_PATH" ]]; then echo "❌ Error: Missing arguments for 'export' action." @@ -201,20 +285,21 @@ case "$ACTION" in fi ;; - restore|restore-rename) - if [[ "$ACTION" == "restore" ]]; then + import|import-rename) + SCHEMA_NAME="$3" + if [[ "$ACTION" == "import" ]]; then SOURCE_PATH="$4" NEW_SCHEMA_NAME="" if [[ -z "$USER_KEY" || -z "$SCHEMA_NAME" || -z "$SOURCE_PATH" ]]; then - echo "❌ Error: Missing arguments for 'restore' action." + echo "❌ Error: Missing arguments for 'import' action." usage exit 1 fi - else # restore-rename + else # import-rename NEW_SCHEMA_NAME="$4" SOURCE_PATH="$5" if [[ -z "$USER_KEY" || -z "$SCHEMA_NAME" || -z "$NEW_SCHEMA_NAME" || -z "$SOURCE_PATH" ]]; then - echo "❌ Error: Missing arguments for 'restore-rename' action." + echo "❌ Error: Missing arguments for 'import-rename' action." usage exit 1 fi @@ -266,7 +351,7 @@ case "$ACTION" in fi QUERY_RENAME_PART="" - if [[ "$ACTION" == "restore-rename" ]]; then + if [[ "$ACTION" == "import-rename" ]]; then QUERY_RENAME_PART="WITH RENAME SCHEMA \"${SCHEMA_NAME}\" TO \"${NEW_SCHEMA_NAME}\"" fi diff --git a/packages.conf b/packages.conf index cf639d4..95bd00a 100644 --- a/packages.conf +++ b/packages.conf @@ -11,6 +11,6 @@ SCRIPT_PACKAGES["Aurora Suite"]="1.1.0|https://git.technopunk.space/tomi/Scripts SCRIPT_PACKAGES["Backup Suite"]="1.0.5|https://git.technopunk.space/tomi/Scripts/raw/branch/main/backup/backup.sh https://git.technopunk.space/tomi/Scripts/raw/branch/main/backup/backup.conf" SCRIPT_PACKAGES["Key Manager"]="1.2.1|https://git.technopunk.space/tomi/Scripts/raw/branch/main/hdb_keymanager.sh" SCRIPT_PACKAGES["File Cleaner"]="1.1.0|https://git.technopunk.space/tomi/Scripts/raw/branch/main/clean.sh" -SCRIPT_PACKAGES["HANA Tool"]="1.3.0|https://git.technopunk.space/tomi/Scripts/raw/branch/main/hanatool.sh" +SCRIPT_PACKAGES["HANA Tool"]="1.4.0|https://git.technopunk.space/tomi/Scripts/raw/branch/main/hanatool.sh" # Example: Add a new script with its version. # SCRIPT_PACKAGES["My Other Script"]="1.0.0|https://path/to/my-other-script.sh"