Sunday, November 9, 2025

#!/bin/bash ################################################################################ # Oracle 19c RAC Database Administration Script # Description: Main menu-driven script for Oracle RAC administration tasks # Version: 2.0 (Integrated) # Created: 2025-11-02 # Updated: 2025-11-10 - Updated to use integrated functions_common.sh ################################################################################ # Get script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Source configuration file CONFIG_FILE="${SCRIPT_DIR}/oracle_admin.conf" if [[ ! -f "${CONFIG_FILE}" ]]; then echo "ERROR: Configuration file not found: ${CONFIG_FILE}" exit 1 fi source "${CONFIG_FILE}" # Source common functions (INTEGRATED - includes all DG functions) source "${SCRIPT_DIR}/functions_common.sh" || { echo "ERROR: Cannot load functions_common.sh" exit 1 } # Source function libraries source "${SCRIPT_DIR}/functions_db_health.sh" || { echo "ERROR: Cannot load functions_db_health.sh" exit 1 } source "${SCRIPT_DIR}/functions_dg_health.sh" || { echo "ERROR: Cannot load functions_dg_health.sh" exit 1 } source "${SCRIPT_DIR}/functions_dg_switchover.sh" || { echo "ERROR: Cannot load functions_dg_switchover.sh" exit 1 } source "${SCRIPT_DIR}/functions_restore_point.sh" || { echo "ERROR: Cannot load functions_restore_point.sh" exit 1 } ################################################################################ # Global Variables ################################################################################ SCRIPT_VERSION="2.0" SCRIPT_NAME="Oracle 19c RAC Administration" ################################################################################ # Function: show_banner # Description: Displays the script banner ################################################################################ show_banner() { clear echo "===============================================================================" echo " ${SCRIPT_NAME} - Version ${SCRIPT_VERSION}" echo "===============================================================================" echo " Oracle Home: ${ORACLE_HOME}" echo " User: $(whoami)" echo " Date: $(date '+%Y-%m-%d %H:%M:%S')" echo "===============================================================================" echo "" } ################################################################################ # Function: show_main_menu # Description: Displays the main menu ################################################################################ show_main_menu() { echo "" echo "=== MAIN MENU ===" echo "" echo "1. Database Health Check" echo "2. Data Guard Health Check" echo "3. Data Guard Switchover" echo "4. Restore Point Management" echo "5. System Configuration" echo "6. View Logs" echo "7. Cleanup Old Reports" echo "0. Exit" echo "" echo -n "Enter your choice: " } ################################################################################ # Function: select_database # Description: Prompts user to select a database from the list # Returns: Selected database configuration (DB_NAME|SCAN|SERVICE) ################################################################################ select_database() { local prompt_message=$1 echo "" echo "=== ${prompt_message} ===" echo "" # Load all databases local all_dbs=$(load_database_list "ALL") if [[ -z "${all_dbs}" ]]; then log_message "ERROR" "No databases found in configuration" echo "ERROR: No databases configured" return 1 fi # Display database list local idx=1 declare -A db_map echo "Available Databases:" echo "" while IFS= read -r db_line; do IFS='|' read -r db scan service <<< "${db_line}" echo " ${idx}. ${db} (${scan}/${service})" db_map[$idx]="${db_line}" ((idx++)) done <<< "${all_dbs}" echo " A. ALL Databases" echo " M. Manual Input" echo " 0. Cancel" echo "" echo -n "Enter your choice: " read choice case ${choice} in 0) echo "Operation cancelled" return 1 ;; [Aa]) echo "ALL" return 0 ;; [Mm]) echo "" echo -n "Enter database name: " read manual_db if [[ -z "${manual_db}" ]]; then echo "ERROR: Database name cannot be empty" return 1 fi local manual_config=$(load_database_list "${manual_db}") if [[ -z "${manual_config}" ]]; then echo "ERROR: Database '${manual_db}' not found in configuration" return 1 fi echo "${manual_config}" return 0 ;; *) if [[ -n "${db_map[$choice]}" ]]; then echo "${db_map[$choice]}" return 0 else echo "ERROR: Invalid choice" return 1 fi ;; esac } ################################################################################ # Function: display_database_details # Description: Displays selected database connection details # Parameters: $1 - Database configuration (DB_NAME|SCAN|SERVICE or "ALL") ################################################################################ display_database_details() { local selection=$1 if [[ "${selection}" == "ALL" ]]; then echo "" echo "Selected: ALL Databases" echo "" local all_dbs=$(load_database_list "ALL") while IFS= read -r db_line; do IFS='|' read -r db scan service <<< "${db_line}" echo " - ${db}: ${scan}/${service}" done <<< "${all_dbs}" else IFS='|' read -r db scan service <<< "${selection}" echo "" echo "Selected Database Details:" echo " Database: ${db}" echo " SCAN Address: ${scan}" echo " Service Name: ${service}" echo " Connection: ${scan}/${service}" fi echo "" } ################################################################################ # Function: menu_database_health_check # Description: Handles database health check menu option ################################################################################ menu_database_health_check() { show_banner local selected_db=$(select_database "Select Database for Health Check") if [[ $? -ne 0 ]] || [[ -z "${selected_db}" ]]; then echo "No database selected" read -p "Press Enter to continue..." return 1 fi display_database_details "${selected_db}" echo "Starting Database Health Check..." echo "" if [[ "${selected_db}" == "ALL" ]]; then perform_db_health_check_all else IFS='|' read -r db_name scan service <<< "${selected_db}" perform_db_health_check "${db_name}" "${scan}" "${service}" fi echo "" read -p "Press Enter to continue..." } ################################################################################ # Function: menu_dg_health_check # Description: Handles Data Guard health check menu option ################################################################################ menu_dg_health_check() { show_banner local selected_db=$(select_database "Select Database for DG Health Check") if [[ $? -ne 0 ]] || [[ -z "${selected_db}" ]]; then echo "No database selected" read -p "Press Enter to continue..." return 1 fi display_database_details "${selected_db}" echo "Starting Data Guard Health Check..." echo "" if [[ "${selected_db}" == "ALL" ]]; then perform_dg_health_check_all else IFS='|' read -r db_name scan service <<< "${selected_db}" perform_dg_health_check "${db_name}" fi echo "" read -p "Press Enter to continue..." } ################################################################################ # Function: menu_dg_switchover # Description: Handles Data Guard switchover menu option ################################################################################ menu_dg_switchover() { show_banner local selected_db=$(select_database "Select Source Database for Switchover") if [[ $? -ne 0 ]] || [[ -z "${selected_db}" ]] || [[ "${selected_db}" == "ALL" ]]; then echo "Invalid selection - switchover requires specific database" read -p "Press Enter to continue..." return 1 fi IFS='|' read -r db_name scan service <<< "${selected_db}" display_database_details "${selected_db}" echo "Initiating Data Guard Switchover Process..." echo "" echo "WARNING: This will perform an actual database role change!" echo "" echo -n "Type 'YES' to continue or anything else to cancel: " read confirmation if [[ "${confirmation}" != "YES" ]]; then echo "Switchover cancelled" read -p "Press Enter to continue..." return 1 fi perform_dg_switchover "${db_name}" echo "" read -p "Press Enter to continue..." } ################################################################################ # Function: menu_restore_point # Description: Handles restore point management menu option ################################################################################ menu_restore_point() { show_banner echo "=== RESTORE POINT MANAGEMENT ===" echo "" echo "1. Create Restore Point (Primary Only)" echo "2. Create Restore Point (All DG Members)" echo "3. List Restore Points" echo "4. Drop Restore Point (Primary Only)" echo "5. Drop Restore Point (All DG Members)" echo "0. Back to Main Menu" echo "" echo -n "Enter your choice: " read rp_choice case ${rp_choice} in 1) menu_create_restore_point_primary ;; 2) menu_create_restore_point_all ;; 3) menu_list_restore_points ;; 4) menu_drop_restore_point_primary ;; 5) menu_drop_restore_point_all ;; 0) return 0 ;; *) echo "Invalid choice" read -p "Press Enter to continue..." ;; esac } ################################################################################ # Function: menu_create_restore_point_primary # Description: Creates restore point on primary database only ################################################################################ menu_create_restore_point_primary() { local selected_db=$(select_database "Select Database for Restore Point") if [[ $? -ne 0 ]] || [[ -z "${selected_db}" ]] || [[ "${selected_db}" == "ALL" ]]; then echo "Invalid selection" read -p "Press Enter to continue..." return 1 fi IFS='|' read -r db_name scan service <<< "${selected_db}" display_database_details "${selected_db}" echo -n "Enter restore point name: " read rp_name if [[ -z "${rp_name}" ]]; then echo "ERROR: Restore point name cannot be empty" read -p "Press Enter to continue..." return 1 fi create_restore_point_primary "${db_name}" "${scan}" "${service}" "${rp_name}" read -p "Press Enter to continue..." } ################################################################################ # Function: menu_create_restore_point_all # Description: Creates restore point on all DG members ################################################################################ menu_create_restore_point_all() { local selected_db=$(select_database "Select Database Configuration") if [[ $? -ne 0 ]] || [[ -z "${selected_db}" ]] || [[ "${selected_db}" == "ALL" ]]; then echo "Invalid selection" read -p "Press Enter to continue..." return 1 fi IFS='|' read -r db_name scan service <<< "${selected_db}" display_database_details "${selected_db}" echo -n "Enter restore point name: " read rp_name if [[ -z "${rp_name}" ]]; then echo "ERROR: Restore point name cannot be empty" read -p "Press Enter to continue..." return 1 fi create_restore_point_all_dg_members "${db_name}" "${rp_name}" read -p "Press Enter to continue..." } ################################################################################ # Function: menu_list_restore_points # Description: Lists restore points ################################################################################ menu_list_restore_points() { local selected_db=$(select_database "Select Database to List Restore Points") if [[ $? -ne 0 ]] || [[ -z "${selected_db}" ]] || [[ "${selected_db}" == "ALL" ]]; then echo "Invalid selection" read -p "Press Enter to continue..." return 1 fi IFS='|' read -r db_name scan service <<< "${selected_db}" display_database_details "${selected_db}" list_restore_points "${db_name}" "${scan}" "${service}" read -p "Press Enter to continue..." } ################################################################################ # Function: menu_drop_restore_point_primary # Description: Drops restore point from primary database ################################################################################ menu_drop_restore_point_primary() { local selected_db=$(select_database "Select Database") if [[ $? -ne 0 ]] || [[ -z "${selected_db}" ]] || [[ "${selected_db}" == "ALL" ]]; then echo "Invalid selection" read -p "Press Enter to continue..." return 1 fi IFS='|' read -r db_name scan service <<< "${selected_db}" display_database_details "${selected_db}" # List current restore points first list_restore_points "${db_name}" "${scan}" "${service}" echo "" echo -n "Enter restore point name to drop: " read rp_name if [[ -z "${rp_name}" ]]; then echo "ERROR: Restore point name cannot be empty" read -p "Press Enter to continue..." return 1 fi drop_restore_point_primary "${db_name}" "${scan}" "${service}" "${rp_name}" read -p "Press Enter to continue..." } ################################################################################ # Function: menu_drop_restore_point_all # Description: Drops restore point from all DG members ################################################################################ menu_drop_restore_point_all() { local selected_db=$(select_database "Select Database Configuration") if [[ $? -ne 0 ]] || [[ -z "${selected_db}" ]] || [[ "${selected_db}" == "ALL" ]]; then echo "Invalid selection" read -p "Press Enter to continue..." return 1 fi IFS='|' read -r db_name scan service <<< "${selected_db}" display_database_details "${selected_db}" echo -n "Enter restore point name to drop: " read rp_name if [[ -z "${rp_name}" ]]; then echo "ERROR: Restore point name cannot be empty" read -p "Press Enter to continue..." return 1 fi drop_restore_point_all_dg_members "${db_name}" "${rp_name}" read -p "Press Enter to continue..." } ################################################################################ # Function: menu_system_configuration # Description: Handles system configuration menu option ################################################################################ menu_system_configuration() { show_banner echo "=== SYSTEM CONFIGURATION ===" echo "" echo "1. View Configuration" echo "2. Edit Configuration File" echo "3. View Database List" echo "4. Edit Database List" echo "5. Test Email Configuration" echo "0. Back to Main Menu" echo "" echo -n "Enter your choice: " read config_choice case ${config_choice} in 1) view_configuration ;; 2) edit_configuration ;; 3) view_database_list ;; 4) edit_database_list ;; 5) test_email_configuration ;; 0) return 0 ;; *) echo "Invalid choice" read -p "Press Enter to continue..." ;; esac } ################################################################################ # Function: view_configuration # Description: Displays current configuration (passwords masked) ################################################################################ view_configuration() { echo "" echo "=== CURRENT CONFIGURATION ===" echo "" echo "Oracle Environment:" echo " ORACLE_HOME: ${ORACLE_HOME}" echo " ORACLE_BASE: ${ORACLE_BASE:-Not set}" echo "" echo "Database Connection:" echo " SYS_USER: ${SYS_USER}" echo " SYS_PASSWORD: ********" echo "" echo "File Locations:" echo " DATABASE_LIST_FILE: ${DATABASE_LIST_FILE}" echo " LOG_BASE_DIR: ${LOG_BASE_DIR}" echo " REPORT_BASE_DIR: ${REPORT_BASE_DIR}" echo "" echo "Email Configuration:" echo " SEND_EMAIL: ${SEND_EMAIL:-NO}" echo " EMAIL_FROM: ${EMAIL_FROM:-Not set}" echo " EMAIL_RECIPIENTS: ${EMAIL_RECIPIENTS:-Not set}" echo "" read -p "Press Enter to continue..." } ################################################################################ # Function: edit_configuration # Description: Opens configuration file in editor ################################################################################ edit_configuration() { echo "" echo "Opening configuration file in editor..." ${EDITOR:-vi} "${CONFIG_FILE}" echo "" echo "Configuration file updated" echo "NOTE: Restart the script for changes to take effect" read -p "Press Enter to continue..." } ################################################################################ # Function: view_database_list # Description: Displays database list ################################################################################ view_database_list() { echo "" echo "=== DATABASE LIST ===" echo "" if [[ ! -f "${DATABASE_LIST_FILE}" ]]; then echo "ERROR: Database list file not found: ${DATABASE_LIST_FILE}" read -p "Press Enter to continue..." return 1 fi cat "${DATABASE_LIST_FILE}" echo "" read -p "Press Enter to continue..." } ################################################################################ # Function: edit_database_list # Description: Opens database list in editor ################################################################################ edit_database_list() { echo "" echo "Opening database list in editor..." ${EDITOR:-vi} "${DATABASE_LIST_FILE}" echo "" echo "Database list updated" read -p "Press Enter to continue..." } ################################################################################ # Function: test_email_configuration # Description: Sends test email ################################################################################ test_email_configuration() { echo "" echo "=== TEST EMAIL CONFIGURATION ===" echo "" if [[ "${SEND_EMAIL}" != "YES" ]]; then echo "Email is not enabled in configuration" echo "Set SEND_EMAIL=YES in ${CONFIG_FILE}" read -p "Press Enter to continue..." return 1 fi echo "Sending test email to: ${EMAIL_RECIPIENTS}" local test_file="/tmp/oracle_admin_test_email_$$.html" cat > "${test_file}" << 'EOF' Test Email

Oracle RAC Administration - Test Email

This is a test email from the Oracle RAC Administration script.

If you receive this email, your email configuration is working correctly.

Generated: $(date)

EOF if send_email_report "Oracle RAC Admin - Test Email" "${test_file}" "${EMAIL_RECIPIENTS}"; then echo "Test email sent successfully" else echo "Failed to send test email" fi rm -f "${test_file}" read -p "Press Enter to continue..." } ################################################################################ # Function: menu_view_logs # Description: Displays recent log entries ################################################################################ menu_view_logs() { show_banner echo "=== VIEW LOGS ===" echo "" local log_file="${LOG_BASE_DIR}/oracle_admin_$(date '+%Y%m%d').log" if [[ ! -f "${log_file}" ]]; then echo "No log file found for today: ${log_file}" read -p "Press Enter to continue..." return 1 fi echo "Displaying last 50 lines from: ${log_file}" echo "" echo "-------------------------------------------------------------------" tail -50 "${log_file}" echo "-------------------------------------------------------------------" echo "" read -p "Press Enter to continue..." } ################################################################################ # Function: menu_cleanup_old_reports # Description: Cleans up old reports and logs ################################################################################ menu_cleanup_old_reports() { show_banner echo "=== CLEANUP OLD REPORTS ===" echo "" echo "This will remove files older than:" echo " - Reports: ${REPORT_RETENTION_DAYS} days" echo " - Logs: ${LOG_RETENTION_DAYS} days" echo "" echo -n "Continue? (y/n): " read confirm if [[ "${confirm}" != "y" ]] && [[ "${confirm}" != "Y" ]]; then echo "Cleanup cancelled" read -p "Press Enter to continue..." return 0 fi echo "" echo "Cleaning up old reports..." cleanup_old_files "${REPORT_BASE_DIR}" "${REPORT_RETENTION_DAYS}" echo "Cleaning up old logs..." cleanup_old_files "${LOG_BASE_DIR}" "${LOG_RETENTION_DAYS}" echo "" echo "Cleanup completed" read -p "Press Enter to continue..." } ################################################################################ # Main Script ################################################################################ # Validate prerequisites if ! validate_prerequisites; then echo "ERROR: Prerequisites validation failed" exit 1 fi log_message "INFO" "Oracle RAC Administration script started by ${USER}" # Main loop while true; do show_banner show_main_menu read main_choice case ${main_choice} in 1) menu_database_health_check ;; 2) menu_dg_health_check ;; 3) menu_dg_switchover ;; 4) menu_restore_point ;; 5) menu_system_configuration ;; 6) menu_view_logs ;; 7) menu_cleanup_old_reports ;; 0) echo "" echo "Exiting Oracle RAC Administration script..." log_message "INFO" "Oracle RAC Administration script exited by ${USER}" exit 0 ;; *) echo "Invalid choice. Please try again." sleep 2 ;; esac done ################################################################################ # End of oracle_rac_admin.sh ################################################################################