diff --git a/hanatool.sh b/hanatool.sh new file mode 100644 index 0000000..046fb8e --- /dev/null +++ b/hanatool.sh @@ -0,0 +1,237 @@ +#!/bin/bash +# Version: 1.1.0 +# ============================================================================== +# SAP HANA Schema Management Tool (hanatool.sh) +# +# A command-line utility to quickly export, restore, or import-and-rename +# a SAP HANA schema. +# ============================================================================== + +# --- Default Settings --- +HDBSQL_PATH="/usr/sap/hdbclient/hdbsql" +COMPRESS=false +THREADS=0 # 0 means auto-calculate later + +# --- Help/Usage Function --- +usage() { + echo "SAP HANA Schema Management Tool" + echo "" + echo "Usage: $0 [USER_KEY] [ACTION] [SCHEMA_NAME] [PATH] [OPTIONS]" + echo " $0 [USER_KEY] import-rename [SCHEMA_NAME] [NEW_SCHEMA_NAME] [PATH] [OPTIONS]" + echo "" + echo "Actions:" + echo " export Export a schema to a specified path." + echo " restore Restore a schema from a specified path." + echo " import-rename Restore a schema from a path to a new schema name." + 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 import-rename only) The target schema name." + echo " PATH The file system path for the export/import 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 " --hdbsql Specify a custom path for the hdbsql executable." + echo " -h, --help Show this help message." + echo "" + echo "Examples:" + echo " # Export MYSCHEMA to /hana/backups/temp_export using compression and 8 threads" + echo " $0 MYKEY export MYSCHEMA /hana/backups/temp_export -c -t 8" + echo "" + echo " # Restore MYSCHEMA from a compressed archive" + echo " $0 MYKEY restore MYSCHEMA /hana/backups/MYSCHEMA_20240101.tar.gz -c" + echo "" + echo " # Import MYSCHEMA as MYSCHEMA_TEST using a custom hdbsql path" + echo " $0 MYKEY import-rename MYSCHEMA MYSCHEMA_TEST /hana/backups/temp_export --hdbsql /sap/custom/hdbsql" +} + +# --- Argument Parsing --- +POSITIONAL_ARGS=() +while [[ $# -gt 0 ]]; do + case $1 in + -t|--threads) + THREADS="$2" + shift # past argument + shift # past value + ;; + -c|--compress) + COMPRESS=true + shift # past argument + ;; + --hdbsql) + HDBSQL_PATH="$2" + shift # past argument + shift # past value + ;; + -h|--help) + usage + exit 0 + ;; + *) + POSITIONAL_ARGS+=("$1") # save positional arg + shift # past argument + ;; + esac +done +set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters + +# Assign positional arguments to variables +USER_KEY="$1" +ACTION="$2" +SCHEMA_NAME="$3" + +# --- Main Logic --- + +# Check for hdbsql executable +if [[ ! -x "$HDBSQL_PATH" ]]; then + echo "❌ Error: hdbsql not found or not executable at '${HDBSQL_PATH}'" + exit 1 +fi + +# Calculate default threads if not specified +if [[ "$THREADS" -eq 0 ]]; then + TOTAL_THREADS=$(nproc --all) + THREADS=$((TOTAL_THREADS / 2)) + if [[ "$THREADS" -eq 0 ]]; then + THREADS=1 + fi + echo "ℹ️ Auto-detected threads to use: ${THREADS}" +fi + +# Execute action based on user input +case "$ACTION" in + export) + TARGET_PATH="$4" + if [[ -z "$USER_KEY" || -z "$SCHEMA_NAME" || -z "$TARGET_PATH" ]]; then + echo "❌ Error: Missing arguments for 'export' action." + usage + exit 1 + fi + + echo "⬇️ Starting schema export..." + echo " - User Key: ${USER_KEY}" + echo " - Schema: ${SCHEMA_NAME}" + echo " - Path: ${TARGET_PATH}" + echo " - Compress: ${COMPRESS}" + echo " - Threads: ${THREADS}" + + EXPORT_DIR="$TARGET_PATH" + if [[ "$COMPRESS" == "true" ]]; then + # Use a temporary directory for the raw export + EXPORT_DIR=$(mktemp -d "${TARGET_PATH}/export_${SCHEMA_NAME}_XXXXXXXX") + echo "ℹ️ Using temporary export directory: ${EXPORT_DIR}" + fi + + mkdir -p "$EXPORT_DIR" + + QUERY="EXPORT \"${SCHEMA_NAME}\".\"*\" AS BINARY INTO '${EXPORT_DIR}' WITH REPLACE THREADS ${THREADS};" + + "$HDBSQL_PATH" -U "$USER_KEY" "$QUERY" > /dev/null 2>&1 + EXIT_CODE=$? + + if [[ "$EXIT_CODE" -eq 0 ]]; then + echo "✅ Successfully exported schema '${SCHEMA_NAME}' to '${EXPORT_DIR}'." + if [[ "$COMPRESS" == "true" ]]; then + ARCHIVE_FILE="${TARGET_PATH}/${SCHEMA_NAME}_$(date +%Y%m%d_%H%M%S).tar.gz" + echo "🗜️ Compressing files to '${ARCHIVE_FILE}'..." + tar -czf "$ARCHIVE_FILE" -C "$(dirname "$EXPORT_DIR")" "$(basename "$EXPORT_DIR")" + TAR_EXIT_CODE=$? + if [[ "$TAR_EXIT_CODE" -eq 0 ]]; then + echo "✅ Successfully created archive." + echo "🧹 Cleaning up temporary directory..." + rm -rf "$EXPORT_DIR" + else + echo "❌ Error: Failed to create archive from '${EXPORT_DIR}'." + fi + fi + else + echo "❌ Error: Failed to export schema '${SCHEMA_NAME}' (hdbsql exit code: ${EXIT_CODE})." + # Clean up temp dir on failure + if [[ "$COMPRESS" == "true" ]]; then rm -rf "$EXPORT_DIR"; fi + fi + ;; + + restore|import-rename) + if [[ "$ACTION" == "restore" ]]; 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." + usage + exit 1 + fi + 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 'import-rename' action." + usage + exit 1 + fi + fi + + echo "⬆️ Starting schema import..." + echo " - User Key: ${USER_KEY}" + echo " - Source Schema: ${SCHEMA_NAME}" + if [[ -n "$NEW_SCHEMA_NAME" ]]; then + echo " - Target Schema: ${NEW_SCHEMA_NAME}" + fi + echo " - Path: ${SOURCE_PATH}" + echo " - Compress: ${COMPRESS}" + echo " - Threads: ${THREADS}" + + IMPORT_DIR="$SOURCE_PATH" + if [[ "$COMPRESS" == "true" ]]; then + if [[ ! -f "$SOURCE_PATH" ]]; then + echo "❌ Error: Source path '${SOURCE_PATH}' is not a valid file for compressed import." + exit 1 + fi + IMPORT_DIR=$(mktemp -d "/tmp/import_${SCHEMA_NAME}_XXXXXXXX") + echo "ℹ️ Decompressing to temporary directory: ${IMPORT_DIR}" + tar -xzf "$SOURCE_PATH" -C "$IMPORT_DIR" --strip-components=1 + TAR_EXIT_CODE=$? + if [[ "$TAR_EXIT_CODE" -ne 0 ]]; then + echo "❌ Error: Failed to decompress '${SOURCE_PATH}'." + rm -rf "$IMPORT_DIR" + exit 1 + fi + fi + + if [[ ! -d "$IMPORT_DIR" ]]; then + echo "❌ Error: Import directory '${IMPORT_DIR}' does not exist." + exit 1 + fi + + QUERY_RENAME_PART="" + if [[ "$ACTION" == "import-rename" ]]; then + QUERY_RENAME_PART="WITH RENAME SCHEMA \"${SCHEMA_NAME}\" TO \"${NEW_SCHEMA_NAME}\"" + fi + + QUERY="IMPORT \"${SCHEMA_NAME}\".\"*\" AS BINARY FROM '${IMPORT_DIR}' ${QUERY_RENAME_PART} WITH IGNORE EXISTING THREADS ${THREADS};" + + "$HDBSQL_PATH" -U "$USER_KEY" "$QUERY" > /dev/null 2>&1 + EXIT_CODE=$? + + if [[ "$EXIT_CODE" -eq 0 ]]; then + echo "✅ Successfully imported schema." + else + echo "❌ Error: Failed to import schema (hdbsql exit code: ${EXIT_CODE})." + fi + + if [[ "$COMPRESS" == "true" ]]; then + echo "🧹 Cleaning up temporary directory..." + rm -rf "$IMPORT_DIR" + fi + ;; + + *) + echo "❌ Error: Invalid action '${ACTION}'." + usage + exit 1 + ;; +esac + +echo "✅ Process complete." + diff --git a/packages.conf b/packages.conf index 092569a..c8dc5b1 100644 --- a/packages.conf +++ b/packages.conf @@ -11,5 +11,6 @@ SCRIPT_PACKAGES["Aurora Suite"]="1.1.0|https://git.technopunk.space/tomi/Scripts SCRIPT_PACKAGES["Backup Suite"]="1.0.0|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.0.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"