Index: /branches/amp_4_0/platform/tools/configure_opensearch_heap_memory.sh
===================================================================
--- /branches/amp_4_0/platform/tools/configure_opensearch_heap_memory.sh	(nonexistent)
+++ /branches/amp_4_0/platform/tools/configure_opensearch_heap_memory.sh	(working copy)
@@ -0,0 +1,85 @@
+#!/bin/bash
+set -e
+
+# --- Configuration ---
+OPENSEARCH_JVM_OPTS="/etc/opensearch/jvm.options"
+DATAPREPPER_SCRIPT="/usr/share/data-prepper/bin/data-prepper"
+DASHBOARDS_SERVICE="opensearch-dashboards.service"
+MAX_HEAP_MB=31744 # This limit is primarily for Java-based services (OpenSearch, Data Prepper)
+
+# --- Memory Calculation ---
+TOTAL_MEM_MB=$(free -m | awk '/^Mem:/{print $2}')
+OS_HEAP_MB=$(( TOTAL_MEM_MB * 40 / 100 ))
+DP_HEAP_MB=$(( TOTAL_MEM_MB * 25 / 100 ))
+
+# Explicitly set Dashboards memory to 4GB (4096 MB)
+DASHBOARDS_MB=4096
+
+# Apply MAX_HEAP_MB only to OpenSearch and Data Prepper
+(( OS_HEAP_MB > MAX_HEAP_MB )) && OS_HEAP_MB=$MAX_HEAP_MB
+(( DP_HEAP_MB > MAX_HEAP_MB )) && DP_HEAP_MB=$MAX_HEAP_MB
+
+
+echo "🧠 Total RAM: ${TOTAL_MEM_MB}MB"
+echo "📦 OpenSearch heap: ${OS_HEAP_MB}MB"
+echo "🚰 Data Prepper heap: ${DP_HEAP_MB}MB"
+echo "🖥️  Dashboards max-old-space-size: ${DASHBOARDS_MB}MB"
+
+# --- OpenSearch ---
+if [[ -f "$OPENSEARCH_JVM_OPTS" ]]; then
+  cp "$OPENSEARCH_JVM_OPTS" "$OPENSEARCH_JVM_OPTS.bak.$(date +%s)"
+  sed -i "s/^-Xms.*/-Xms${OS_HEAP_MB}m/" "$OPENSEARCH_JVM_OPTS"
+  sed -i "s/^-Xmx.*/-Xmx${OS_HEAP_MB}m/" "$OPENSEARCH_JVM_OPTS"
+  echo "✅ OpenSearch heap updated."
+else
+  echo "❌ OpenSearch JVM config not found."
+fi
+
+# --- Data Prepper ---
+DP_SERVICE=$(systemctl show -p FragmentPath data-prepper | cut -d'=' -f2)
+if [[ -n "$DP_SERVICE" && -f "$DP_SERVICE" ]]; then
+  cp "$DP_SERVICE" "$DP_SERVICE.bak.$(date +%s)"
+  sed -i '/^Environment="DATA_PREPPER_JAVA_OPTS=/d' "$DP_SERVICE"
+  sed -i "/^\[Service\]/a Environment=\"DATA_PREPPER_JAVA_OPTS=-Xms${DP_HEAP_MB}m -Xmx${DP_HEAP_MB}m\"" "$DP_SERVICE"
+  echo "✅ Data Prepper systemd unit updated."
+else
+  echo "❌ Data Prepper service unit not found."
+fi
+
+if [[ -f "$DATAPREPPER_SCRIPT" ]]; then
+  if ! grep -q 'export JAVA_OPTS="$JAVA_OPTS $DATA_PREPPER_JAVA_OPTS"' "$DATAPREPPER_SCRIPT"; then
+    cp "$DATAPREPPER_SCRIPT" "$DATAPREPPER_SCRIPT.bak.$(date +%s)"
+    sed -i '/^#!\/bin\/bash/a export JAVA_OPTS="$JAVA_OPTS $DATA_PREPPER_JAVA_OPTS"' "$DATAPREPPER_SCRIPT"
+    echo "✅ Patched Data Prepper launcher script."
+  else
+    echo "✅ Data Prepper launcher already patched."
+  fi
+else
+  echo "❌ Data Prepper script not found."
+fi
+
+# --- OpenSearch Dashboards ---
+DASHBOARDS_UNIT=$(systemctl show -p FragmentPath "$DASHBOARDS_SERVICE" | cut -d'=' -f2)
+if [[ -n "$DASHBOARDS_UNIT" && -f "$DASHBOARDS_UNIT" ]]; then
+  cp "$DASHBOARDS_UNIT" "$DASHBOARDS_UNIT.bak.$(date +%s)"
+  # The original sed command was sufficient, but we'll ensure it overrides any existing
+  # NODE_OPTIONS for max-old-space-size and adds the new value.
+  # We should also retain other NODE_OPTIONS if they exist, but for --max-old-space-size,
+  # we want to ensure only our new value is present.
+  sed -i '/^Environment="NODE_OPTIONS=/d' "$DASHBOARDS_UNIT" # Remove any existing NODE_OPTIONS
+  sed -i "/^\[Service\]/a Environment=\"NODE_OPTIONS=--max-old-space-size=${DASHBOARDS_MB}\"" "$DASHBOARDS_UNIT"
+  echo "✅ Dashboards memory setting updated."
+else
+  echo "❌ OpenSearch Dashboards service unit not found."
+fi
+
+# --- Reload + Restart ---
+systemctl daemon-reexec
+systemctl daemon-reload
+
+echo "♻️ Restarting services..."
+systemctl restart opensearch && echo "🚀 OpenSearch restarted."
+systemctl restart data-prepper && echo "🚀 Data Prepper restarted."
+systemctl restart "$DASHBOARDS_SERVICE" && echo "🚀 Dashboards restarted."
+
+echo "✅ All heap/memory updates applied successfully."
\ No newline at end of file
Index: /branches/amp_4_0/platform/tools/install_configure_opensearch.sh
===================================================================
--- /branches/amp_4_0/platform/tools/install_configure_opensearch.sh	(nonexistent)
+++ /branches/amp_4_0/platform/tools/install_configure_opensearch.sh	(working copy)
@@ -0,0 +1,602 @@
+#!/bin/bash
+
+# Script to install OpenSearch 3.x and OpenSearch Dashboards on Rocky Linux with
+# automated security setup (password change) and self-signed SSL certificates.
+
+# --- Configuration ---
+OPENSEARCH_REPO_DOWNLOAD_URL="https://artifacts.opensearch.org/releases/bundle/opensearch/3.x/opensearch-3.x.repo"
+OPENSEARCH_REPO_FILE="/etc/yum.repos.d/opensearch-3.x.repo"
+OPENSEARCH_GPG_KEY_URL="https://artifacts.opensearch.org/publickeys/opensearch-release.pgp"
+DASHBOARDS_REPO_DOWNLOAD_URL="https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/3.x/opensearch-dashboards-3.x.repo"
+DASHBOARDS_REPO_FILE="/etc/yum.repos.d/opensearch-dashboards-3.x.repo"
+OPENSEARCH_CONFIG_FILE="/etc/opensearch/opensearch.yml"
+OPENSEARCH_DATA_DIR="/var/lib/opensearch"
+OPENSEARCH_LOG_DIR="/var/log/opensearch"
+OPENSEARCH_SERVICE="opensearch"
+OPENSEARCH_SERVICE_FILE="/usr/lib/systemd/system/opensearch.service"
+SECURITY_CONFIG_DIR="/etc/opensearch/opensearch-security"
+
+DASHBOARDS_VERSION="3.0.0"
+DASHBOARDS_CONFIG_FILE="/etc/opensearch-dashboards/opensearch_dashboards.yml"
+DASHBOARDS_SERVICE="opensearch-dashboards"
+DASHBOARDS_PORT=5601
+
+NEW_ADMIN_PASSWORD="Arr@y2050" # WARNING: Hardcoded password, NOT for production!
+
+CERT_DIR="/etc/opensearch/certs"
+CA_KEY="${CERT_DIR}/root-ca-key.pem"
+CA_CERT="${CERT_DIR}/root-ca.pem"
+NODE_KEY="${CERT_DIR}/node-key.pem"
+NODE_CERT="${CERT_DIR}/node.pem"
+ADMIN_KEY="${CERT_DIR}/admin-key.pem"
+ADMIN_CERT="${CERT_DIR}/admin.pem"
+
+# Certificate DNs
+CA_DN="/C=IN/ST=Karnataka/L=Bengaluru/O=OpenSearchSelfSignedCA/CN=OpenSearchCA"
+NODE_DN="/C=IN/ST=Karnataka/L=Bengaluru/O=OpenSearchNode/CN=node-1"
+ADMIN_DN="/CN=admin/O=OpenSearchAdmin/L=Bengaluru/ST=Karnataka/C=IN"
+
+# Subject Alternative Names (SANs) for node certificate
+SAN_HOSTS="DNS:localhost,IP:127.0.0.1,DNS:node-1"
+
+JAVA_HOME_PATH="/usr/lib/jvm/java-21-openjdk-21.0.7.0.6-1.el9.x86_64"
+
+# --- Functions ---
+
+log_info() {
+    echo -e "\n\033[0;34m[INFO]\033[0m $1"
+}
+
+log_success() {
+    echo -e "\n\033[0;32m[SUCCESS]\033[0m $1"
+}
+
+log_warn() {
+    echo -e "\n\033[0;33m[WARNING]\033[0m $1"
+}
+
+log_error() {
+    echo -e "\n\033[0;31m[ERROR]\033[0m $1"
+    exit 1
+}
+
+# Check if certificate files exist
+check_cert_files() {
+    log_info "Checking certificate files..."
+    for file in "${CA_KEY}" "${CA_CERT}" "${NODE_KEY}" "${NODE_CERT}" "${ADMIN_KEY}" "${ADMIN_CERT}"; do
+        if [ ! -f "${file}" ]; then
+            log_error "Certificate file ${file} does not exist."
+        fi
+    done
+    log_success "All certificate files exist."
+}
+
+# --- Main Script ---
+
+log_info "Starting OpenSearch 3.x and Dashboards installation on Rocky Linux..."
+
+# 1. Check for root privileges
+if [[ $EUID -ne 0 ]]; then
+   log_error "This script must be run as root. Please use 'sudo bash $0'."
+fi
+
+# 2. Check for Java installation
+log_info "Checking for Java installation (OpenJDK 17 or higher recommended)..."
+if command -v java &>/dev/null; then
+    JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | cut -d'.' -f1)
+    if (( JAVA_VERSION >= 17 )); then
+        log_success "Java ${JAVA_VERSION} found. Compatible with OpenSearch 3.x."
+        if [ -z "${JAVA_HOME_PATH}" ]; then
+            DETECTED_JAVA_BIN=$(readlink -f $(which java))
+            if [ -n "${DETECTED_JAVA_BIN}" ]; then
+                JAVA_HOME_PATH=$(dirname $(dirname "${DETECTED_JAVA_BIN}"))
+                log_info "Auto-detected JAVA_HOME_PATH: ${JAVA_HOME_PATH}"
+            else
+                log_error "Failed to determine JAVA_HOME_PATH. Please set it manually."
+            fi
+        fi
+    else
+        log_error "Java version ${JAVA_VERSION} found. OpenSearch 3.x requires Java 17 or higher."
+    fi
+else
+    log_error "Java not found. Please install Java (OpenJDK 17 or higher)."
+fi
+
+# 3. Download OpenSearch repository file
+log_info "Downloading OpenSearch 3.x repository file: ${OPENSEARCH_REPO_FILE}..."
+sudo curl -o "${OPENSEARCH_REPO_FILE}" "${OPENSEARCH_REPO_DOWNLOAD_URL}" || log_error "Failed to download OpenSearch repository file."
+
+# Configure OpenSearch repository
+if ! grep -q "gpgcheck=1" "${OPENSEARCH_REPO_FILE}"; then
+    log_warn "Adding 'gpgcheck=1' to ${OPENSEARCH_REPO_FILE}."
+    echo "gpgcheck=1" | sudo tee -a "${OPENSEARCH_REPO_FILE}" > /dev/null
+fi
+if ! grep -q "gpgkey=" "${OPENSEARCH_REPO_FILE}"; then
+    log_warn "Adding 'gpgkey=${OPENSEARCH_GPG_KEY_URL}' to ${OPENSEARCH_REPO_FILE}."
+    echo "gpgkey=${OPENSEARCH_GPG_KEY_URL}" | sudo tee -a "${OPENSEARCH_REPO_FILE}" > /dev/null
+fi
+if ! grep -q "repo_gpgcheck=" "${OPENSEARCH_REPO_FILE}"; then
+    log_info "Adding 'repo_gpgcheck=0' to ${OPENSEARCH_REPO_FILE}."
+    echo "repo_gpgcheck=0" | sudo tee -a "${OPENSEARCH_REPO_FILE}" > /dev/null
+fi
+
+# 4. Download OpenSearch Dashboards repository file
+log_info "Downloading OpenSearch Dashboards 3.x repository file: ${DASHBOARDS_REPO_FILE}..."
+sudo curl -o "${DASHBOARDS_REPO_FILE}" "${DASHBOARDS_REPO_DOWNLOAD_URL}" || log_error "Failed to download OpenSearch Dashboards repository file."
+
+# Configure Dashboards repository
+if ! grep -q "gpgcheck=1" "${DASHBOARDS_REPO_FILE}"; then
+    log_warn "Adding 'gpgcheck=1' to ${DASHBOARDS_REPO_FILE}."
+    echo "gpgcheck=1" | sudo tee -a "${DASHBOARDS_REPO_FILE}" > /dev/null
+fi
+if ! grep -q "gpgkey=" "${DASHBOARDS_REPO_FILE}"; then
+    log_warn "Adding 'gpgkey=${OPENSEARCH_GPG_KEY_URL}' to ${DASHBOARDS_REPO_FILE}."
+    echo "gpgkey=${OPENSEARCH_GPG_KEY_URL}" | sudo tee -a "${DASHBOARDS_REPO_FILE}" > /dev/null
+fi
+if ! grep -q "repo_gpgcheck=" "${DASHBOARDS_REPO_FILE}"; then
+    log_info "Adding 'repo_gpgcheck=0' to ${DASHBOARDS_REPO_FILE}."
+    echo "repo_gpgcheck=0" | sudo tee -a "${DASHBOARDS_REPO_FILE}" > /dev/null
+fi
+
+# 5. Enable SHA1 for OpenSearch repositories (Rocky Linux 9 workaround)
+log_info "Temporarily enabling SHA1 crypto policy for repository verification..."
+sudo update-crypto-policies --set DEFAULT:SHA1 || log_error "Failed to enable SHA1 crypto policy."
+log_success "SHA1 crypto policy enabled."
+
+# 6. Clean DNF cache
+log_info "Cleaning DNF cache..."
+sudo dnf clean all || log_error "Failed to clean DNF cache."
+sudo dnf makecache -y || log_error "Failed to make DNF cache."
+log_success "DNF cache updated."
+
+# 7. Install OpenSearch and OpenSSL
+log_info "Installing OpenSearch 3.x and OpenSSL..."
+sudo dnf -y install opensearch openssl || log_error "Failed to install OpenSearch or OpenSSL."
+log_success "OpenSearch and OpenSSL installed."
+
+# 8. Install OpenSearch Dashboards
+log_info "Installing OpenSearch Dashboards ${DASHBOARDS_VERSION}..."
+sudo dnf -y install opensearch-dashboards || log_error "Failed to install OpenSearch Dashboards."
+log_success "OpenSearch Dashboards installed."
+
+# 9. Revert SHA1 crypto policy
+log_info "Reverting SHA1 crypto policy to default..."
+sudo update-crypto-policies --set DEFAULT || log_error "Failed to revert crypto policy."
+log_success "Crypto policy reverted to default."
+
+# 10. Set vm.max_map_count
+log_info "Setting vm.max_map_count for OpenSearch..."
+if ! grep -q "vm.max_map_count=262144" /etc/sysctl.d/99-opensearch.conf 2>/dev/null; then
+    echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.d/99-opensearch.conf > /dev/null
+    sudo sysctl --system || log_error "Failed to apply sysctl changes."
+    log_success "vm.max_map_count set to 262144."
+else
+    log_info "vm.max_map_count already configured."
+fi
+
+# 11. Create certificate directory
+log_info "Creating certificate directory: ${CERT_DIR}..."
+sudo mkdir -p "${CERT_DIR}" || log_error "Failed to create directory ${CERT_DIR}."
+
+# 12. Generate Self-Signed SSL Certificates
+log_info "Generating self-signed SSL certificates..."
+
+# Generate CA Key
+sudo openssl genrsa -out "${CA_KEY}" 2048 || log_error "Failed to generate CA key."
+sudo chmod 400 "${CA_KEY}"
+
+# Generate CA Certificate
+sudo openssl req -new -x509 -key "${CA_KEY}" -out "${CA_CERT}" -days 3650 -subj "${CA_DN}" || log_error "Failed to generate CA certificate."
+sudo chmod 444 "${CA_CERT}"
+
+# Create SAN config for Node certificate
+NODE_EXTFILE_TEMP="/tmp/node_san.cnf"
+echo "subjectAltName=${SAN_HOSTS}" | sudo tee "${NODE_EXTFILE_TEMP}" > /dev/null || log_error "Failed to create node SAN file."
+sudo chmod 644 "${NODE_EXTFILE_TEMP}"
+
+# Generate Node Key
+sudo openssl genrsa -out "${NODE_KEY}" 2048 || log_error "Failed to generate node key."
+sudo chmod 400 "${NODE_KEY}"
+
+# Generate Node CSR
+sudo openssl req -new -key "${NODE_KEY}" -out "${CERT_DIR}/node.csr" -subj "${NODE_DN}" || log_error "Failed to generate node CSR."
+
+# Sign Node Certificate
+sudo openssl x509 -req -in "${CERT_DIR}/node.csr" -CA "${CA_CERT}" -CAkey "${CA_KEY}" -CAcreateserial -out "${NODE_CERT}" -days 3650 -extfile "${NODE_EXTFILE_TEMP}" || log_error "Failed to sign node certificate."
+sudo chmod 444 "${NODE_CERT}"
+
+# Generate Admin Key
+sudo openssl genrsa -out "${ADMIN_KEY}" 2048 || log_error "Failed to generate admin key."
+sudo chmod 400 "${ADMIN_KEY}"
+
+# Generate Admin CSR
+sudo openssl req -new -key "${ADMIN_KEY}" -out "${CERT_DIR}/admin.csr" -subj "${ADMIN_DN}" || log_error "Failed to generate admin CSR."
+
+# Sign Admin Certificate
+sudo openssl x509 -req -in "${CERT_DIR}/admin.csr" -CA "${CA_CERT}" -CAkey "${CA_KEY}" -CAcreateserial -out "${ADMIN_CERT}" -days 3650 || log_error "Failed to sign admin certificate."
+sudo chmod 444 "${ADMIN_CERT}"
+
+# Clean up
+sudo rm -f "${CERT_DIR}/node.csr" "${CERT_DIR}/admin.csr" "${NODE_EXTFILE_TEMP}"
+log_success "SSL certificates generated."
+
+# 13. Set certificate permissions for OpenSearch
+log_info "Setting certificate permissions for OpenSearch..."
+sudo chown -R opensearch:opensearch "${CERT_DIR}" || log_error "Failed to chown certificate directory."
+sudo chmod 755 "${CERT_DIR}"
+sudo chmod 640 "${NODE_KEY}" "${ADMIN_KEY}"
+sudo chmod 644 "${NODE_CERT}" "${CA_CERT}" "${ADMIN_CERT}"
+log_success "Certificate permissions set for OpenSearch."
+
+# 14. Set certificate permissions for OpenSearch Dashboards
+log_info "Setting certificate permissions for OpenSearch Dashboards..."
+sudo chown opensearch:opensearch "${NODE_KEY}" "${NODE_CERT}" "${CA_CERT}" || log_error "Failed to set certificate ownership for Dashboards."
+log_success "Certificate permissions set for Dashboards."
+
+## Add opensearch-dashboards user to the opensearch group
+sudo usermod -aG opensearch opensearch-dashboards
+
+sudo chown -R opensearch:opensearch /etc/opensearch/
+sudo chmod -R u+rwX,go-w /etc/opensearch/
+
+# 15. Verify certificate files
+check_cert_files
+
+# 16. Configure OpenSearch
+log_info "Configuring OpenSearch..."
+
+sudo cp "${OPENSEARCH_CONFIG_FILE}" "${OPENSEARCH_CONFIG_FILE}.bak_$(date +%Y%m%d%H%M%S)"
+
+cat << EOF | sudo tee "${OPENSEARCH_CONFIG_FILE}" > /dev/null
+# Managed by OpenSearch installation script
+
+# Basic Configuration
+cluster.name: opensearch-cluster
+node.name: node-1
+network.host: 0.0.0.0
+
+# Single-node discovery
+discovery.seed_hosts: ["127.0.0.1"]
+cluster.initial_master_nodes: ["node-1"]
+
+# Security Plugin (TLS/SSL)
+plugins.security.ssl.http.enabled: true
+plugins.security.ssl.http.pemcert_filepath: ${NODE_CERT}
+plugins.security.ssl.http.pemkey_filepath: ${NODE_KEY}
+plugins.security.ssl.http.pemtrustedcas_filepath: ${CA_CERT}
+plugins.security.ssl.http.clientauth_mode: OPTIONAL
+
+plugins.security.ssl.transport.enabled: true
+plugins.security.ssl.transport.pemcert_filepath: ${NODE_CERT}
+plugins.security.ssl.transport.pemkey_filepath: ${NODE_KEY}
+plugins.security.ssl.transport.pemtrustedcas_filepath: ${CA_CERT}
+plugins.security.ssl.transport.enforce_hostname_verification: false
+
+plugins.security.allow_default_init_securityindex: true
+
+# Allow REST API access to these roles
+plugins.security.restapi.roles_enabled: ["security_rest_api_access"]
+
+# Admin DN
+plugins.security.authcz.admin_dn:
+  - C=IN,ST=Karnataka,L=Bengaluru,O=OpenSearchAdmin,CN=admin
+
+# Node DN
+plugins.security.nodes_dn:
+  - CN=node-1,O=OpenSearchNode,L=Bengaluru,ST=Karnataka,C=IN
+
+# Disable system call filter for dev/test
+bootstrap.system_call_filter: false
+EOF
+log_success "OpenSearch configuration updated."
+
+# 17. Configure OpenSearch Dashboards
+log_info "Configuring OpenSearch Dashboards..."
+
+sudo cp "${DASHBOARDS_CONFIG_FILE}" "${DASHBOARDS_CONFIG_FILE}.bak_$(date +%Y%m%d%H%M%S)"
+
+cat << EOF | sudo tee "${DASHBOARDS_CONFIG_FILE}" > /dev/null
+# Managed by OpenSearch installation script
+
+server.host: 0.0.0.0
+server.port: ${DASHBOARDS_PORT}
+opensearch.hosts: ["https://127.0.0.1:9200"]
+opensearch.ssl.verificationMode: certificate
+opensearch.username: "admin"
+opensearch.password: "${NEW_ADMIN_PASSWORD}"
+opensearch.requestHeadersWhitelist: ["securitytenant","Authorization"]
+
+# SSL Configuration
+server.ssl.enabled: true
+server.ssl.certificate: ${NODE_CERT}
+server.ssl.key: ${NODE_KEY}
+opensearch.ssl.certificateAuthorities: ["${CA_CERT}"]
+EOF
+
+# Set permissions
+sudo chown -R opensearch-dashboards:opensearch-dashboards "${DASHBOARDS_CONFIG_FILE}" || log_error "Failed to set permissions for Dashboards config."
+sudo chmod 600 "${DASHBOARDS_CONFIG_FILE}"
+log_success "OpenSearch Dashboards configuration updated."
+
+# 18. Configure OpenSearch systemd service
+log_info "Generating OpenSearch systemd service file..."
+
+sudo rm -f "${OPENSEARCH_SERVICE_FILE}"
+
+cat << EOF | sudo tee "${OPENSEARCH_SERVICE_FILE}" > /dev/null
+[Unit]
+Description=OpenSearch
+Documentation=https://opensearch.org/
+Wants=network-online.target
+After=network-online.target
+
+[Service]
+Environment="JAVA_HOME=${JAVA_HOME_PATH}"
+Environment="OPENSEARCH_INITIAL_ADMIN_PASSWORD=dummy_password"
+Type=notify
+RuntimeDirectory=opensearch
+EnvironmentFile=-/etc/default/opensearch
+EnvironmentFile=-/etc/sysconfig/opensearch
+
+WorkingDirectory=/usr/share/opensearch
+
+User=opensearch
+Group=opensearch
+
+ExecStartPre=/bin/mkdir -p /dev/shm/performanceanalyzer
+ExecStartPre=/bin/chown opensearch:opensearch /dev/shm/performanceanalyzer
+
+ExecStart=/usr/share/opensearch/bin/systemd-entrypoint -p \${PID_DIR}/opensearch.pid --quiet
+
+StandardOutput=journal
+StandardError=inherit
+SyslogIdentifier=opensearch
+
+LimitNOFILE=65535
+LimitNPROC=4096
+LimitAS=infinity
+LimitFSIZE=infinity
+
+TimeoutStopSec=0
+KillSignal=SIGTERM
+KillMode=process
+SendSIGKILL=no
+SuccessExitStatus=143
+
+TimeoutStartSec=75
+
+ProtectControlGroups=true
+ProtectKernelModules=true
+ProtectKernelTunables=true
+DevicePolicy=closed
+ProtectProc=invisible
+ProtectSystem=full
+LockPersonality=true
+NoNewPrivileges=true
+RestrictSUID SGID=true
+RestrictRealtime=true
+ProtectHostname=true
+ProtectKernelLogs=true
+ProtectClock=true
+
+SystemCallFilter=madvise mincore mlock mlock2 munlock get_mempolicy sched_getaffinity sched_setaffinity fcntl @system-service
+SystemCallFilter=~@reboot ~@swap
+SystemCallErrorNumber=EPERM
+
+CapabilityBoundingSet=~CAP_BLOCK_SUSPEND ~CAP_LEASE ~CAP_SYS_PACCT ~CAP_SYS_TTY_CONFIG ~CAP_SYS_ADMIN ~CAP_SYS_PTRACE ~CAP_NET_ADMIN
+
+RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
+
+ReadWritePaths=/var/log/opensearch
+ReadWritePaths=/var/lib/opensearch
+ReadWritePaths=/dev/shm/
+ReadWritePaths=-/etc/opensearch
+ReadWritePaths=-/mnt/snapshots
+
+ReadOnlyPaths=-/etc/os-release -/usr/lib/os-release -/etc/system-release
+ReadOnlyPaths=/proc/self/mountinfo /proc/diskstats
+ReadOnlyPaths=/proc/self/cgroup /sys/fs/cgroup/cpu /sys/fs/cgroup/cpuacct /sys/fs/cgroup/memory
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+sudo chmod 644 "${OPENSEARCH_SERVICE_FILE}"
+sudo chown root:root "${OPENSEARCH_SERVICE_FILE}"
+log_success "OpenSearch service configured."
+
+# 19. Configure OpenSearch Dashboards systemd service
+log_info "Configuring OpenSearch Dashboards systemd service..."
+DASHBOARDS_SERVICE_FILE="/usr/lib/systemd/system/${DASHBOARDS_SERVICE}.service"
+
+sudo rm -f "${DASHBOARDS_SERVICE_FILE}"
+
+cat << EOF | sudo tee "${DASHBOARDS_SERVICE_FILE}" > /dev/null
+[Unit]
+Description=OpenSearch Dashboards
+Documentation=https://opensearch.org/docs/latest/
+Wants=network-online.target
+After=network-online.target opensearch.service
+
+[Service]
+Type=simple
+User=opensearch-dashboards
+Group=opensearch-dashboards
+ExecStart=/usr/share/opensearch-dashboards/bin/opensearch-dashboards
+Restart=on-failure
+WorkingDirectory=/usr/share/opensearch-dashboards
+StandardOutput=journal
+StandardError=inherit
+SyslogIdentifier=opensearch-dashboards
+Environment=NODE_ENV=production
+Environment=CONFIG_PATH=${DASHBOARDS_CONFIG_FILE}
+
+LimitNOFILE=65535
+LimitNPROC=4096
+LimitAS=infinity
+LimitFSIZE=infinity
+
+TimeoutStopSec=0
+KillSignal=SIGTERM
+KillMode=process
+SendSIGKILL=no
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+sudo chmod 644 "${DASHBOARDS_SERVICE_FILE}"
+sudo chown root:root "${DASHBOARDS_SERVICE_FILE}"
+log_success "OpenSearch Dashboards service configured."
+
+# 20. Start OpenSearch
+log_info "Enabling and starting OpenSearch service..."
+sudo systemctl daemon-reload || log_error "Failed to reload systemd daemon."
+sudo systemctl enable "${OPENSEARCH_SERVICE}" || log_error "Failed to enable OpenSearch service."
+sudo systemctl restart "${OPENSEARCH_SERVICE}" || log_error "Failed to start OpenSearch service."
+
+# 21. Wait for OpenSearch
+log_info "Waiting for OpenSearch to start..."
+ATTEMPTS=60
+for i in $(seq 1 $ATTEMPTS); do
+    if curl -s -k -u admin:admin "https://localhost:9200/_plugins/_security/health?pretty" | grep -q "status.*UP"; then
+        log_success "OpenSearch service is up!"
+        break
+    else
+        log_info "Attempt $i/$ATTEMPTS: OpenSearch not available. Waiting 10 seconds..."
+        sleep 10
+    fi
+    if [ $i -eq $ATTEMPTS ]; then
+        log_error "OpenSearch did not start. Check logs."
+    fi
+done
+
+# 22. Initialize Security Plugin
+log_info "Initializing OpenSearch Security Plugin..."
+
+# Apply default security configuration with reload
+if JAVA_HOME="${JAVA_HOME_PATH}" sudo -E /usr/share/opensearch/plugins/opensearch-security/tools/securityadmin.sh \
+    -cd "${SECURITY_CONFIG_DIR}" \
+    -icl -nhnv \
+    -cacert "${CA_CERT}" -cert "${ADMIN_CERT}" -key "${ADMIN_KEY}" \
+    -rl; then
+
+    log_success "Security Plugin initialized."
+
+    log_info "Waiting for security index to stabilize..."
+    sleep 10 # Give it a moment after plugin initialization
+
+    log_info "Updating admin user roles and password..."
+
+    # Retry updating admin user roles up to 3 times
+    RETRY_COUNT=3
+    ADMIN_UPDATE_SUCCESS=false
+    for j in $(seq 1 $RETRY_COUNT); do
+        UPDATE_RESPONSE=$(curl -s -k -X PUT "https://localhost:9200/_plugins/_security/api/internalusers/admin" \
+            --cert "${ADMIN_CERT}" --key "${ADMIN_KEY}" \
+            -H "Content-Type: application/json" \
+            -d "{\"password\":\"${NEW_ADMIN_PASSWORD}\",\"backend_roles\":[\"security_admin\",\"all_access\", \"security_rest_api_access\"]}" --fail --show-error)
+
+        if echo "$UPDATE_RESPONSE" | grep -q "\"status\":\"OK\""; then
+            log_success "Admin user roles updated and password changed to '${NEW_ADMIN_PASSWORD}'."
+            ADMIN_UPDATE_SUCCESS=true
+            break
+        else
+            log_warn "Attempt $j/$RETRY_COUNT: Failed to update admin user roles. Response: $UPDATE_RESPONSE. Retrying in 5 seconds..."
+            sleep 5
+        fi
+    done
+
+    if [ "$ADMIN_UPDATE_SUCCESS" = false ]; then
+        log_error "Failed to update admin user roles after $RETRY_COUNT attempts."
+    fi
+
+    echo "[INFO] Mapping backend roles to security roles..."
+    # Add a small delay here to allow the previous update to settle
+    sleep 5
+
+    for role in all_access security_rest_api_access; do
+      echo "  ↳ Mapping backend role: ${role}"
+      MAPPING_RESPONSE=$(curl -s -k \
+        --cert /etc/opensearch/certs/admin.pem \
+        --key /etc/opensearch/certs/admin-key.pem \
+        -X PUT "https://localhost:9200/_plugins/_security/api/rolesmapping/${role}" \
+        -H 'Content-Type: application/json' \
+        -d "{\"backend_roles\": [\"${role}\"]}" | jq)
+      echo "$MAPPING_RESPONSE"
+      if echo "$MAPPING_RESPONSE" | grep -q "status"; then
+          log_success "Successfully mapped backend role: ${role}"
+      else
+          log_warn "Failed to map backend role: ${role}. Response: $MAPPING_RESPONSE"
+      fi
+      sleep 1 # Small delay between role mappings
+    done
+    echo "[SUCCESS] Role mappings completed."
+
+    # 23. Verify admin user roles - AFTER role mappings
+    log_info "Verifying admin user roles after mapping..."
+    # Add a small delay to ensure role mappings are fully applied
+    sleep 10
+    ADMIN_ROLES_VERIFY=$(curl -s -k -u admin:"${NEW_ADMIN_PASSWORD}" "https://localhost:9200/_plugins/_security/api/internalusers/admin?pretty")
+    if echo "$ADMIN_ROLES_VERIFY" | grep -q "security_admin" && \
+       echo "$ADMIN_ROLES_VERIFY" | grep -q "all_access" && \
+       echo "$ADMIN_ROLES_VERIFY" | grep -q "security_rest_api_access"; then
+        log_success "Admin user has all required roles: $(echo "$ADMIN_ROLES_VERIFY" | grep backend_roles)"
+    else
+        log_error "Admin user still missing required roles. Actual roles: $(echo "$ADMIN_ROLES_VERIFY" | grep backend_roles || echo 'None'). Please review security configuration."
+    fi
+
+else
+    log_error "Failed to initialize Security Plugin. Check logs."
+fi
+
+# 23. Verify admin user roles
+log_info "Verifying admin user roles..."
+ADMIN_ROLES=$(curl -s -k -u admin:"${NEW_ADMIN_PASSWORD}" "https://localhost:9200/_plugins/_security/api/internalusers/admin?pretty")
+if echo "$ADMIN_ROLES" | grep -q "all_access"; then
+    log_success "Admin user has required roles: $(echo "$ADMIN_ROLES" | grep backend_roles)"
+else
+    log_error "Admin user missing required roles. Actual roles: $(echo "$ADMIN_ROLES" | grep backend_roles || echo 'None'). Check security configuration."
+fi
+
+# 24. Start OpenSearch Dashboards
+log_info "Enabling and starting OpenSearch Dashboards service..."
+sudo systemctl daemon-reload || log_error "Failed to reload systemd daemon."
+sudo systemctl enable "${DASHBOARDS_SERVICE}" || log_error "Failed to enable OpenSearch Dashboards service."
+sudo systemctl restart "${DASHBOARDS_SERVICE}" || log_error "Failed to start OpenSearch Dashboards service."
+
+# 25. Wait for OpenSearch Dashboards
+log_info "Waiting for OpenSearch Dashboards to start..."
+ATTEMPTS=60
+for i in $(seq 1 $ATTEMPTS); do
+    if curl -s -k -u admin:"${NEW_ADMIN_PASSWORD}" "https://localhost:${DASHBOARDS_PORT}/api/status" | grep -q "green"; then
+        log_success "OpenSearch Dashboards is up!"
+        break
+    else
+        log_info "Attempt $i/$ATTEMPTS: Dashboards not available. Waiting 10 seconds..."
+        sleep 10
+    fi
+    if [ $i -eq $ATTEMPTS ]; then
+        log_error "OpenSearch Dashboards did not start. Check logs."
+    fi
+done
+
+# 26. Configure Firewall
+log_info "Configuring firewall for ports 9200, 9600, and ${DASHBOARDS_PORT}..."
+if systemctl is-active --quiet firewalld; then
+    sudo firewall-cmd --add-port=9200/tcp --permanent || log_warn "Failed to add port 9200/tcp."
+    sudo firewall-cmd --add-port=9600/tcp --permanent || log_warn "Failed to add port 9600/tcp."
+    sudo firewall-cmd --add-port=${DASHBOARDS_PORT}/tcp --permanent || log_warn "Failed to add port ${DASHBOARDS_PORT}/tcp."
+    sudo firewall-cmd --reload || log_warn "Failed to reload firewall."
+    log_success "Firewall rules updated."
+else
+    log_warn "Firewalld not running. Configure firewall manually for ports 9200, 9600, and ${DASHBOARDS_PORT}."
+fi
+
+# 27. Final Output
+log_success "OpenSearch 3.x and Dashboards installation complete!"
+log_info "Access OpenSearch at: https://$(hostname -I | awk '{print $1}'):9200 or https://127.0.0.1:9200"
+log_info "Access Dashboards at: https://$(hostname -I | awk '{print $1}'):${DASHBOARDS_PORT} or https://127.0.0.1:${DASHBOARDS_PORT}"
+log_info "Username: admin, Password: ${NEW_ADMIN_PASSWORD}"
+log_warn "Import CA certificate (${CA_CERT}) into your browser's trust store."
+log_warn "For production, use trusted CA certificates and secure passwords."
\ No newline at end of file
Index: /branches/amp_4_0/platform/tools/install_fluentbit_dataprepper.sh
===================================================================
--- /branches/amp_4_0/platform/tools/install_fluentbit_dataprepper.sh	(nonexistent)
+++ /branches/amp_4_0/platform/tools/install_fluentbit_dataprepper.sh	(working copy)
@@ -0,0 +1,566 @@
+#!/bin/bash
+
+# Script to install and configure Data Prepper, Fluent Bit, and rsyslog for OpenSearch.
+# Assumes OpenSearch and OpenSearch Dashboards are already installed and configured
+# (including SSL certificates and the 'admin' user with password) from a previous script run.
+
+# --- Configuration ---
+OPENSEARCH_HOST="localhost"
+OPENSEARCH_PORT=9200
+NEW_ADMIN_PASSWORD="Arr@y2050" # OpenSearch admin password
+CERT_DIR="/etc/opensearch/certs"
+CA_CERT="${CERT_DIR}/root-ca.pem"
+NODE_KEY="${CERT_DIR}/node-key.pem"
+NODE_CERT="${CERT_DIR}/node.pem"
+ADMIN_KEY="${CERT_DIR}/admin-key.pem"
+ADMIN_CERT="${CERT_DIR}/admin.pem"
+KEYSTORE="${CERT_DIR}/dataprepper-keystore.p12" # PKCS12 keystore
+JAVA_HOME_PATH="/usr/lib/jvm/java-21-openjdk-21.0.7.0.6-1.el9.x86_64" # JDK 21
+INDEX_PATTERN="acm-*"
+
+# Data Prepper Configuration
+DATA_PREPPER_INSTALL_DIR="/usr/share/data-prepper"
+DATA_PREPPER_CONFIG_DIR="${DATA_PREPPER_INSTALL_DIR}/config"
+DATA_PREPPER_PIPELINES_DIR="${DATA_PREPPER_INSTALL_DIR}/pipelines"
+DATA_PREPPER_LOG_DIR="/var/log/data-prepper"
+DATA_PREPPER_SERVICE="data-prepper"
+DATA_PREPPER_SERVICE_FILE="/usr/lib/systemd/system/${DATA_PREPPER_SERVICE}.service"
+DATA_PREPPER_USER="data-prepper"
+DATA_PREPPER_GROUP="data-prepper"
+DATA_PREPPER_HTTP_PORT=2021
+DATA_PREPPER_SOURCE_USER="data_prepper_user"
+DATA_PREPPER_SOURCE_PASSWORD="data_prepper_password"
+
+# Fluent Bit Configuration
+FLUENT_BIT_CONFIG_DIR="/etc/fluent-bit"
+FLUENT_BIT_LOG_DIR="/var/log/fluent-bit"
+FLUENT_BIT_SERVICE="fluent-bit"
+SYSLOG_TCP_PORT=514
+SYSLOG_UDP_PORT=514
+
+# rsyslog Configuration
+RSYSLOG_CONFIG_DIR="/etc/rsyslog.d"
+RSYSLOG_SERVICE="rsyslog"
+
+# --- Functions ---
+
+log_info() { echo -e "\n\033[0;34m[INFO]\033[0m $1"; }
+log_success() { echo -e "\n\033[0;32m[SUCCESS]\033[0m $1"; }
+log_warn() { echo -e "\n\033[0;33m[WARNING]\033[0m $1"; }
+log_error() { echo -e "\n\033[0;31m[ERROR]\033[0m $1"; exit 1; }
+
+create_data_prepper_user() {
+    log_info "Creating Data Prepper user and group..."
+    if ! id "${DATA_PREPPER_USER}" &>/dev/null; then
+        sudo groupadd --system "${DATA_PREPPER_GROUP}" || log_error "Failed to create group ${DATA_PREPPER_GROUP}."
+        sudo useradd --system -g "${DATA_PREPPER_GROUP}" -s /sbin/nologin -d "${DATA_PREPPER_INSTALL_DIR}" "${DATA_PREPPER_USER}" || log_error "Failed to create user ${DATA_PREPPER_USER}."
+        log_success "Data Prepper user '${DATA_PREPPER_USER}' and group '${DATA_PREPPER_GROUP}' created."
+    else
+        log_info "Data Prepper user '${DATA_PREPPER_USER}' already exists."
+    fi
+}
+
+convert_pem_to_keystore() {
+    log_info "Converting PEM certificates to PKCS12 keystore..."
+    if [ ! -f "${KEYSTORE}" ]; then
+        sudo openssl pkcs12 -export -in "${NODE_CERT}" -inkey "${NODE_KEY}" -out "${KEYSTORE}" -name dataprepper -passout pass: || log_error "Failed to create PKCS12 keystore."
+        sudo chown ${DATA_PREPPER_USER}:${DATA_PREPPER_GROUP} "${KEYSTORE}"
+        sudo chmod 640 "${KEYSTORE}"
+        log_success "PKCS12 keystore created at ${KEYSTORE}."
+    else
+        log_info "PKCS12 keystore already exists at ${KEYSTORE}."
+    fi
+}
+
+configure_data_prepper_server_config() {
+    log_info "Configuring Data Prepper server settings..."
+    sudo mkdir -p "${DATA_PREPPER_CONFIG_DIR}" "${DATA_PREPPER_LOG_DIR}" || log_error "Failed to create Data Prepper directories."
+    sudo chown -R ${DATA_PREPPER_USER}:${DATA_PREPPER_GROUP} "${DATA_PREPPER_CONFIG_DIR}" "${DATA_PREPPER_LOG_DIR}"
+    sudo chmod 750 "${DATA_PREPPER_LOG_DIR}"
+    sudo usermod -aG opensearch ${DATA_PREPPER_USER}
+    cat << EOF | sudo tee "${DATA_PREPPER_CONFIG_DIR}/data-prepper-config.yaml" > /dev/null
+ssl: true
+key_store_file_path: "${KEYSTORE}"
+key_store_password: ""
+private_key_password: ""
+server_port: 4900
+authentication:
+  http_basic:
+    username: "data_prepper_server_user"
+    password: "data_prepper_server_password"
+EOF
+    sudo chown ${DATA_PREPPER_USER}:${DATA_PREPPER_GROUP} "${DATA_PREPPER_CONFIG_DIR}/data-prepper-config.yaml"
+    sudo chmod 640 "${DATA_PREPPER_CONFIG_DIR}/data-prepper-config.yaml"
+    log_success "Data Prepper server configuration created."
+}
+
+configure_data_prepper_pipeline() {
+    log_info "Creating Data Prepper pipeline configuration..."
+    sudo mkdir -p "${DATA_PREPPER_PIPELINES_DIR}" || log_error "Failed to create ${DATA_PREPPER_PIPELINES_DIR}."
+    sudo chown -R ${DATA_PREPPER_USER}:${DATA_PREPPER_GROUP} "${DATA_PREPPER_PIPELINES_DIR}"
+    cat << EOF | sudo tee "${DATA_PREPPER_PIPELINES_DIR}/opensearch-pipeline.yaml" > /dev/null
+version: "2"
+opensearch-pipeline:
+  workers: 2
+  delay: 100
+  source:
+    http:
+      ssl: true
+      ssl_certificate_file: "${NODE_CERT}"
+      ssl_key_file: "${NODE_KEY}"
+      port: ${DATA_PREPPER_HTTP_PORT}
+      path: /
+  processor:
+    - date:
+        from_time_received: true
+  sink:
+    - opensearch:
+        hosts: ["https://localhost:9200"]
+        insecure: true
+        cert: "${CA_CERT}"
+        username: "${DATA_PREPPER_SOURCE_USER}"
+        password: "${DATA_PREPPER_SOURCE_PASSWORD}"
+        index: "acm-%{yyyy.MM.dd}"
+EOF
+    sudo chown ${DATA_PREPPER_USER}:${DATA_PREPPER_GROUP} "${DATA_PREPPER_PIPELINES_DIR}/opensearch-pipeline.yaml"
+    sudo chmod 640 "${DATA_PREPPER_PIPELINES_DIR}/opensearch-pipeline.yaml"
+    log_success "Data Prepper pipeline configuration created."
+}
+
+configure_data_prepper_service() {
+    log_info "Configuring Data Prepper systemd service..."
+    sudo rm -f "${DATA_PREPPER_SERVICE_FILE}"
+    cat << EOF | sudo tee "${DATA_PREPPER_SERVICE_FILE}" > /dev/null
+[Unit]
+Description=OpenSearch Data Prepper
+Documentation=https://opensearch.org/docs/latest/data-prepper/
+Wants=network-online.target
+After=network-online.target opensearch.service
+
+[Service]
+Environment="JAVA_HOME=${JAVA_HOME_PATH}"
+Type=simple
+User=${DATA_PREPPER_USER}
+Group=${DATA_PREPPER_GROUP}
+WorkingDirectory=${DATA_PREPPER_INSTALL_DIR}
+ExecStart=${DATA_PREPPER_INSTALL_DIR}/bin/data-prepper
+Restart=on-failure
+StandardOutput=append:${DATA_PREPPER_LOG_DIR}/data-prepper-service.log
+StandardError=append:${DATA_PREPPER_LOG_DIR}/data-prepper-service.log
+SyslogIdentifier=data-prepper
+LimitNOFILE=65535
+LimitNPROC=4096
+LimitAS=infinity
+LimitFSIZE=infinity
+TimeoutStopSec=0
+KillSignal=SIGTERM
+KillMode=process
+SendSIGKILL=no
+
+[Install]
+WantedBy=multi-user.target
+EOF
+    sudo chmod 644 "${DATA_PREPPER_SERVICE_FILE}"
+    sudo chown root:root "${DATA_PREPPER_SERVICE_FILE}"
+    log_success "Data Prepper service configured."
+}
+
+configure_rsyslog() {
+    [ "$EUID" -eq 0 ] || { log_error "Must run as root."; return 1; }
+    : "${RSYSLOG_CONFIG_DIR:=/etc/rsyslog.d}"
+    : "${SYSLOG_UDP_PORT:=514}"
+    : "${SYSLOG_TCP_PORT:=514}"
+    : "${RSYSLOG_SERVICE:=rsyslog}"
+    log_info "Configuring rsyslog to forward to Fluent Bit..."
+    sudo mkdir -p "${RSYSLOG_CONFIG_DIR}" || { log_error "Failed to create rsyslog config directory."; return 1; }
+    cat << EOF | sudo tee "${RSYSLOG_CONFIG_DIR}/fluent-bit.conf" > /dev/null || { log_error "Failed to write config."; return 1; }
+module(load="omfwd")
+*.* @127.0.0.1:${SYSLOG_UDP_PORT}
+*.* @@127.0.0.1:${SYSLOG_TCP_PORT}
+EOF
+    sudo chmod 644 "${RSYSLOG_CONFIG_DIR}/fluent-bit.conf" || { log_error "Failed to set permissions."; return 1; }
+    sudo cp /etc/rsyslog.conf /etc/rsyslog.conf.bak || log_error "Failed to backup rsyslog.conf."
+    sudo sed -i '/module(load="imudp")/s/^/#/' /etc/rsyslog.conf || { log_error "Failed to disable imudp module."; return 1; }
+    sudo sed -i '/module(load="imtcp")/s/^/#/' /etc/rsyslog.conf || { log_error "Failed to disable imtcp module."; return 1; }
+    sudo sed -i '/input(type="imudp" port="514")/s/^/#/' /etc/rsyslog.conf || { log_error "Failed to disable imudp input."; return 1; }
+    sudo sed -i '/input(type="imtcp" port="514")/s/^/#/' /etc/rsyslog.conf || { log_error "Failed to disable imtcp input."; return 1; }
+    sudo systemctl is-active --quiet "${RSYSLOG_SERVICE}" || { log_error "rsyslog service not running."; return 1; }
+    sudo systemctl restart "${RSYSLOG_SERVICE}" || { log_error "Failed to restart rsyslog service."; return 1; }
+    log_info "Ensuring firewall ports are open..."
+    if systemctl is-active --quiet firewalld; then
+        sudo firewall-cmd --add-port=514/tcp --permanent || log_error "Failed to open TCP 514."
+        sudo firewall-cmd --add-port=514/udp --permanent || log_error "Failed to open UDP 514."
+        sudo firewall-cmd --reload || log_error "Failed to reload firewall."
+    else
+        log_warn "Firewalld not running. Ensure ports 514 TCP/UDP are open."
+    fi
+    log_info "Testing rsyslog to Fluent Bit connectivity..."
+    sudo systemctl start fluent-bit || { log_error "Failed to start Fluent Bit service."; return 1; }
+    sudo systemctl is-active --quiet fluent-bit || { log_error "Fluent Bit service not running."; return 1; }
+    if ! command -v nc >/dev/null 2>&1; then
+        log_error "netcat (nc) not installed. Install with 'dnf install nc' and rerun."
+        return 1
+    fi
+    echo "Test rsyslog message" | logger -t "test_rsyslog"
+    sleep 2
+    for attempt in {1..3}; do
+        if timeout 2 nc -zv 127.0.0.1 ${SYSLOG_TCP_PORT} &>/dev/null && (echo -n "test" | timeout 2 nc -u -w 1 127.0.0.1 ${SYSLOG_UDP_PORT} &>/dev/null); then
+            log_success "rsyslog can connect to Fluent Bit on TCP/UDP 514."
+            break
+        elif [ $attempt -eq 3 ]; then
+            log_error "rsyslog cannot connect to Fluent Bit after $attempt attempts. Check firewall, SELinux, or Fluent Bit service."
+            return 1
+        fi
+        log_info "Attempt $attempt failed. Retrying in 2 seconds..."
+        sleep 2
+    done
+    log_success "rsyslog configured to forward to Fluent Bit."
+}
+
+create_index_pattern() {
+    log_info "Creating index pattern '${INDEX_PATTERN}' in OpenSearch..."
+    local INDEX_PATTERN_JSON=$(cat <<EOT
+{
+  "attributes": {
+    "title": "${INDEX_PATTERN}",
+    "timeFieldName": "@timestamp"
+  }
+}
+EOT
+)
+    local RESPONSE=$(curl -s -k -u admin:"${NEW_ADMIN_PASSWORD}" -X POST "https://${OPENSEARCH_HOST}:5601/api/saved_objects/index-pattern" -H "Content-Type: application/json" -H "osd-xsrf: true" -d "${INDEX_PATTERN_JSON}")
+    if echo "$RESPONSE" | grep -q '"id"'; then
+        log_success "Index pattern '${INDEX_PATTERN}' created."
+    else
+        log_error "Failed to create index pattern. Response: $RESPONSE"
+    fi
+}
+
+ensure_index_exists() {
+    local INDEX_NAME="acm-$(date +%Y.%m.%d)"
+    log_info "Ensuring index '${INDEX_NAME}' exists..."
+    local INDEX_RESPONSE=$(curl -s -k -u admin:"${NEW_ADMIN_PASSWORD}" -X PUT "https://${OPENSEARCH_HOST}:${OPENSEARCH_PORT}/${INDEX_NAME}" -H "Content-Type: application/json")
+
+    if echo "$INDEX_RESPONSE" | grep -q '"acknowledged":true'; then
+        log_success "Index '${INDEX_NAME}' created or already exists."
+    elif echo "$INDEX_RESPONSE" | grep -q 'resource_already_exists_exception'; then
+        log_info "Index '${INDEX_NAME}' already exists. Skipping creation."
+    else
+        log_error "Failed to create index. Response: $INDEX_RESPONSE"
+    fi
+}
+
+install_fluent_bit() {
+    log_info "Installing Fluent Bit..."
+    cat <<EOF | sudo tee /etc/yum.repos.d/fluent-bit.repo
+[fluent-bit]
+name=Fluent Bit
+baseurl=https://packages.fluentbit.io/centos/9/$basearch/
+gpgcheck=1
+gpgkey=https://packages.fluentbit.io/fluentbit.key
+enabled=1
+EOF
+    sudo dnf -y install fluent-bit-3.2.* || log_error "Failed to install Fluent Bit."
+    log_info "Relocating Fluent Bit to /usr/share/fluent-bit..."
+    sudo mkdir -p /usr/share/fluent-bit
+    sudo mv /opt/fluent-bit/* /usr/share/fluent-bit/ || log_error "Failed to relocate Fluent Bit."
+    sudo rmdir /opt/fluent-bit || log_warn "Failed to remove /opt/fluent-bit directory."
+    sudo sed -i 's|/opt/fluent-bit/bin/fluent-bit|/usr/share/fluent-bit/bin/fluent-bit|' /usr/lib/systemd/system/fluent-bit.service || log_error "Failed to update Fluent Bit service file."
+    log_success "Fluent Bit installed and relocated."
+}
+
+configure_fluent_bit() {
+    log_info "Configuring Fluent Bit..."
+    sudo mkdir -p "${FLUENT_BIT_CONFIG_DIR}" "${FLUENT_BIT_LOG_DIR}" || log_error "Failed to create Fluent Bit config directory."
+    sudo chown -R fluent-bit:fluent-bit "${FLUENT_BIT_CONFIG_DIR}" "${FLUENT_BIT_LOG_DIR}"
+    sudo chmod 750 "${FLUENT_BIT_LOG_DIR}"
+    cat <<EOF | sudo tee "${FLUENT_BIT_CONFIG_DIR}/fluent-bit.conf" > /dev/null
+[SERVICE]
+    flush        1
+    log_level    debug
+    log_file     ${FLUENT_BIT_LOG_DIR}/fluent-bit.log
+    daemon       off
+    parsers_file  parsers.conf
+    http_server  on
+    http_listen  0.0.0.0
+    http_port    2020
+
+[INPUT]
+    Name         syslog
+    Mode         tcp
+    Port         ${SYSLOG_TCP_PORT}
+    Parser       syslog-rfc5424
+    Listen       0.0.0.0
+
+[INPUT]
+    Name         syslog
+    Mode         udp
+    Port         ${SYSLOG_UDP_PORT}
+    Parser       syslog-rfc5424
+    Listen       0.0.0.0
+
+[OUTPUT]
+    Name          http
+    Match         *
+    Host          localhost
+    Port          ${DATA_PREPPER_HTTP_PORT}
+    URI           /
+    Format        json
+    tls           On
+    tls.verify    Off
+    tls.ca_file   ${CA_CERT}
+    header        Content-Type application/json
+    http_user     ${DATA_PREPPER_SOURCE_USER}
+    http_passwd   ${DATA_PREPPER_SOURCE_PASSWORD}
+EOF
+    cat <<EOF | sudo tee "${FLUENT_BIT_CONFIG_DIR}/parsers.conf" > /dev/null
+[PARSER]
+    Name        syslog-rfc5424
+    Format      regex
+    Regex       /^\<(?<pri>[0-9]+)\>(?<time>[^ ]+ [^ ]+ [^ ]+) (?<host>[^ ]+) (?<ident>[a-zA-Z0-9_\/\.\-]+)(?:\[(?<pid>[0-9]+)\])?\: (?<message>.*)$/
+    Time_Key    time
+    Time_Format %b %d %H:%M:%S
+    Time_Keep   On
+EOF
+    sudo chown -R fluent-bit:fluent-bit "${FLUENT_BIT_CONFIG_DIR}" "${FLUENT_BIT_LOG_DIR}"
+    sudo chmod 640 "${FLUENT_BIT_CONFIG_DIR}/fluent-bit.conf" "${FLUENT_BIT_CONFIG_DIR}/parsers.conf"
+    log_success "Fluent Bit configured."
+}
+
+configure_fluent_bit_service() {
+    log_info "Configuring Fluent Bit systemd service..."
+    sudo rm -f /usr/lib/systemd/system/fluent-bit.service
+    cat <<EOF | sudo tee /usr/lib/systemd/system/fluent-bit.service > /dev/null
+[Unit]
+Description=Fluent Bit - Lightweight Data Collector and Forwarder
+Documentation=https://fluentbit.io/
+After=network.target
+
+[Service]
+ExecStart=/usr/share/fluent-bit/bin/fluent-bit -c ${FLUENT_BIT_CONFIG_DIR}/fluent-bit.conf
+Restart=on-failure
+StandardOutput=append:${FLUENT_BIT_LOG_DIR}/fluent-bit-service.log
+StandardError=append:${FLUENT_BIT_LOG_DIR}/fluent-bit-service.log
+
+[Install]
+WantedBy=multi-user.target
+EOF
+    sudo systemctl daemon-reload
+    sudo systemctl enable fluent-bit
+    log_success "Fluent Bit service configured."
+}
+
+create_opensearch_data_prepper_security_user() {
+    ALL_ACCESS_ADMIN_ROLE_NAME="all_access"
+    log_info "Attempting to re-map admin certificate user to '${ALL_ACCESS_ADMIN_ROLE_NAME}' security role."
+    MAPPING_RESPONSE=$(curl -s -k --cert "${ADMIN_CERT}" --key "${ADMIN_KEY}" -X PUT "https://${OPENSEARCH_HOST}:${OPENSEARCH_PORT}/_plugins/_security/api/rolesmapping/${ALL_ACCESS_ADMIN_ROLE_NAME}" -H 'Content-Type: application/json' -d "{\"users\": [\"${ADMIN_CERT_SUBJECT}\"], \"backend_roles\": [\"${ALL_ACCESS_ADMIN_ROLE_NAME}\"]}")
+    if echo "$MAPPING_RESPONSE" | grep -q "\"status\":\"OK\"" || echo "$MAPPING_RESPONSE" | grep -q "\"status\":\"CREATED\""; then
+        log_success "Successfully re-mapped admin certificate user to '${ALL_ACCESS_ADMIN_ROLE_NAME}' role."
+    else
+        log_error "Failed to re-map admin certificate user. Response: $MAPPING_RESPONSE"
+    fi
+    sleep 5
+
+    log_info "Creating/updating Data Prepper user in OpenSearch..."
+    local DATA_PREPPER_ROLES_JSON=$(cat <<EOT
+{
+  "cluster_permissions": [
+    "cluster_composite_ops_ro",
+    "cluster_monitor",
+    "cluster_manage_pipeline"
+  ],
+  "index_permissions": [
+    {
+      "index_patterns": ["acm-*"],
+      "allowed_actions": [
+        "indices:data/write/bulk",
+        "indices:data/write/bulk[s]",
+        "indices:data/write/index",
+        "indices:data/read/search",
+        "indices:admin/create",
+        "indices:admin/mappings/get",
+        "indices:admin/mapping/put",
+        "indices:admin/template/*",
+        "indices:admin/ilm/put",
+        "indices:admin/get",
+        "indices:monitor/settings/get",
+        "indices:monitor/stats"
+      ]
+    },
+    {
+      "index_patterns": ["*"],
+      "allowed_actions": ["indices:admin/aliases/get"]
+    }
+  ]
+}
+EOT
+)
+    local DATA_PREPPER_ROLES_NAME="data_prepper_writer"
+    log_info "Creating/updating OpenSearch security role '${DATA_PREPPER_ROLES_NAME}'..."
+    local ROLE_RESPONSE=$(curl -s -k -X PUT "https://${OPENSEARCH_HOST}:${OPENSEARCH_PORT}/_plugins/_security/api/roles/${DATA_PREPPER_ROLES_NAME}" --cert "${ADMIN_CERT}" --key "${ADMIN_KEY}" -H "Content-Type: application/json" -d "${DATA_PREPPER_ROLES_JSON}")
+    if echo "$ROLE_RESPONSE" | grep -q "\"status\":\"OK\"" || echo "$ROLE_RESPONSE" | grep -q "\"status\":\"CREATED\""; then
+        log_success "OpenSearch security role '${DATA_PREPPER_ROLES_NAME}' created/updated."
+    else
+        log_error "Failed to create/update role '${DATA_PREPPER_ROLES_NAME}'. Response: $ROLE_RESPONSE"
+    fi
+    sleep 2
+    log_info "Creating/updating OpenSearch internal user '${DATA_PREPPER_SOURCE_USER}'..."
+    local USER_RESPONSE=$(curl -s -k -X PUT "https://${OPENSEARCH_HOST}:${OPENSEARCH_PORT}/_plugins/_security/api/internalusers/${DATA_PREPPER_SOURCE_USER}" --cert "${ADMIN_CERT}" --key "${ADMIN_KEY}" -H "Content-Type: application/json" -d "{\"password\":\"${DATA_PREPPER_SOURCE_PASSWORD}\",\"backend_roles\":[\"${DATA_PREPPER_ROLES_NAME}\"]}")
+    if echo "$USER_RESPONSE" | grep -q "\"status\":\"OK\"" || echo "$USER_RESPONSE" | grep -q "\"status\":\"CREATED\""; then
+        log_success "OpenSearch internal user '${DATA_PREPPER_SOURCE_USER}' created/updated."
+    else
+        log_error "Failed to create/update user '${DATA_PREPPER_SOURCE_USER}'. Response: $USER_RESPONSE"
+    fi
+    sleep 2
+    log_info "Mapping backend role '${DATA_PREPPER_ROLES_NAME}' to security role..."
+    local MAPPING_RESPONSE=$(curl -s -k --cert "${ADMIN_CERT}" --key "${ADMIN_KEY}" -X PUT "https://${OPENSEARCH_HOST}:${OPENSEARCH_PORT}/_plugins/_security/api/rolesmapping/${DATA_PREPPER_ROLES_NAME}" -H 'Content-Type: application/json' -d "{\"backend_roles\": [\"${DATA_PREPPER_ROLES_NAME}\"]}")
+    if echo "$MAPPING_RESPONSE" | grep -q "\"status\":\"OK\"" || echo "$MAPPING_RESPONSE" | grep -q "\"status\":\"CREATED\""; then
+        log_success "Successfully mapped backend role '${DATA_PREPPER_ROLES_NAME}'."
+    else
+        log_warn "Failed to map backend role '${DATA_PREPPER_ROLES_NAME}'. Response: $MAPPING_RESPONSE"
+    fi
+    sleep 5
+}
+
+wait_for_opensearch_health() {
+    log_info "Waiting for OpenSearch to be healthy..."
+    ATTEMPTS=20
+    for i in $(seq 1 $ATTEMPTS); do
+        if curl -s -k -u admin:"${NEW_ADMIN_PASSWORD}" "https://${OPENSEARCH_HOST}:${OPENSEARCH_PORT}/_plugins/_security/health?pretty" | grep -q "status.*UP"; then
+            log_success "OpenSearch is up and healthy."
+            break
+        else
+            log_info "Attempt $i/$ATTEMPTS: OpenSearch not ready. Waiting 5 seconds..."
+            sleep 5
+        fi
+        if [ $i -eq $ATTEMPTS ]; then
+            log_error "OpenSearch did not become healthy."
+        fi
+    done
+}
+
+create_fluent_bit_user() {
+    log_info "Creating Fluent Bit user and group..."
+    if ! id "fluent-bit" &>/dev/null; then
+        sudo groupadd --system fluent-bit || log_error "Failed to create group fluent-bit."
+        sudo useradd --system -g fluent-bit -s /sbin/nologin -d /usr/share/fluent-bit fluent-bit || log_error "Failed to create user fluent-bit."
+        log_success "Fluent Bit user and group created."
+    else
+        log_info "Fluent Bit user already exists."
+    fi
+}
+
+# --- Main Script ---
+
+log_info "Starting installation and configuration of Data Prepper, Fluent Bit, and rsyslog..."
+
+if [[ $EUID -ne 0 ]]; then
+   log_error "This script must be run as root."
+fi
+
+sudo dnf -y install nc net-tools
+wait_for_opensearch_health
+create_opensearch_data_prepper_security_user
+create_data_prepper_user
+convert_pem_to_keystore
+
+log_info "Beginning Data Prepper installation..."
+DATA_PREPPER_DOWNLOAD_PATH="/tmp/data-prepper.tar.gz"
+DATA_PREPPER_VERSION="2.11.0"
+DATA_PREPPER_DOWNLOAD_URL="https://artifacts.opensearch.org/data-prepper/${DATA_PREPPER_VERSION}/opensearch-data-prepper-jdk-${DATA_PREPPER_VERSION}-linux-x64.tar.gz"
+log_info "Downloading Data Prepper from ${DATA_PREPPER_DOWNLOAD_URL}..."
+if ! sudo curl -L --fail --silent --show-error -o "${DATA_PREPPER_DOWNLOAD_PATH}" "${DATA_PREPPER_DOWNLOAD_URL}"; then
+    log_error "Failed to download Data Prepper tarball."
+fi
+if [ ! -s "${DATA_PREPPER_DOWNLOAD_PATH}" ]; then
+    log_error "Downloaded Data Prepper tarball is empty or corrupted."
+fi
+log_success "Data Prepper tarball downloaded."
+log_info "Extracting Data Prepper to ${DATA_PREPPER_INSTALL_DIR}..."
+sudo mkdir -p "${DATA_PREPPER_INSTALL_DIR}" || log_error "Failed to create Data Prepper install directory."
+if ! sudo tar -xzf "${DATA_PREPPER_DOWNLOAD_PATH}" -C "${DATA_PREPPER_INSTALL_DIR}" --strip-components=1; then
+    log_error "Failed to extract Data Prepper tarball."
+fi
+sudo rm -f "${DATA_PREPPER_DOWNLOAD_PATH}"
+log_success "Data Prepper extracted."
+
+sudo chown -R ${DATA_PREPPER_USER}:${DATA_PREPPER_GROUP} "${DATA_PREPPER_INSTALL_DIR}" || log_error "Failed to set ownership."
+log_success "Data Prepper directory ownership set."
+
+configure_data_prepper_server_config
+configure_data_prepper_pipeline
+configure_data_prepper_service
+install_fluent_bit
+create_fluent_bit_user
+configure_fluent_bit
+configure_fluent_bit_service
+configure_rsyslog
+
+log_info "Enabling and starting services..."
+sudo systemctl daemon-reload || log_error "Failed to reload systemd daemon."
+sudo systemctl enable "${DATA_PREPPER_SERVICE}" || log_error "Failed to enable Data Prepper service."
+sudo systemctl restart "${DATA_PREPPER_SERVICE}" || log_error "Failed to start Data Prepper service."
+log_info "Data Prepper service started. Check journalctl -u ${DATA_PREPPER_SERVICE} for status."
+sleep 15
+
+sudo systemctl enable "${FLUENT_BIT_SERVICE}" || log_error "Failed to enable Fluent Bit service."
+sudo systemctl restart "${FLUENT_BIT_SERVICE}" || log_error "Failed to start Fluent Bit service."
+log_info "Fluent Bit service started. Check journalctl -u ${FLUENT_BIT_SERVICE} for status."
+sleep 5
+
+sudo systemctl enable "${RSYSLOG_SERVICE}" || log_error "Failed to enable rsyslog service."
+sudo systemctl restart "${RSYSLOG_SERVICE}" || log_error "Failed to start rsyslog service."
+log_info "rsyslog service started. Check journalctl -u ${RSYSLOG_SERVICE} for status."
+sleep 5
+
+log_info "Configuring firewall rules..."
+if systemctl is-active --quiet firewalld; then
+    sudo firewall-cmd --add-port=${DATA_PREPPER_HTTP_PORT}/tcp --permanent || log_warn "Failed to add Data Prepper HTTP port."
+    sudo firewall-cmd --add-port=${SYSLOG_TCP_PORT}/tcp --permanent || log_warn "Failed to add syslog TCP port."
+    sudo firewall-cmd --add-port=${SYSLOG_UDP_PORT}/udp --permanent || log_warn "Failed to add syslog UDP port."
+    sudo firewall-cmd --reload || log_warn "Failed to reload firewall."
+    log_success "Firewall rules updated."
+else
+    log_warn "Firewalld not running. Configure firewall manually."
+fi
+
+ensure_index_exists
+create_index_pattern
+
+log_info "Sending a sample syslog message to Fluent Bit..."
+logger -t "test_syslog" "This is a test message from Fluent Bit via Data Prepper."
+sleep 15
+
+log_info "Verifying data in OpenSearch..."
+
+
+SEARCH_QUERY='{"query": {"match": {"message": "This is a test message from Fluent Bit via Data Prepper."}}}'
+SEARCH_RESPONSE=$(curl -k -u admin:"${NEW_ADMIN_PASSWORD}" \
+  "https://${OPENSEARCH_HOST}:${OPENSEARCH_PORT}/${INDEX_PATTERN}/_search?pretty" \
+  -H "Content-Type: application/json" \
+  -d "$SEARCH_QUERY")
+
+echo "--- RAW SEARCH RESPONSE ---"
+echo "$SEARCH_RESPONSE"
+echo "---------------------------"
+
+if echo "$SEARCH_RESPONSE" | grep -q "error"; then
+    log_error "OpenSearch search returned an error. Response: ${SEARCH_RESPONSE}"
+    exit 1
+fi
+
+TOTAL_HITS=$(echo "$SEARCH_RESPONSE" | jq -r '.hits.total.value')
+
+# Check if TOTAL_HITS is a number and greater than 0
+if [[ "$TOTAL_HITS" =~ ^[0-9]+$ ]] && (( TOTAL_HITS > 0 )); then
+    log_success "Found ${TOTAL_HITS} matching documents in '${INDEX_PATTERN}'."
+    echo "Sample matching document (first 2):"
+    echo "$SEARCH_RESPONSE" | jq '.hits.hits[:2] | .[] | {index: ._index, id: ._id, message: ._source.message, timestamp: ._source."@timestamp", host: ._source.host}'
+    log_success "Data ingestion pipeline working!"
+else
+    log_error "Failed to find test syslog message or total hits is 0. Total Hits: ${TOTAL_HITS}. Response: ${SEARCH_RESPONSE}."
+fi
+
+log_success "Fluent Bit, Data Prepper, and rsyslog installation complete!"
+log_info "Configure systems to send syslog data to TCP/UDP ${SYSLOG_TCP_PORT}."
+log_info "Check OpenSearch Dashboards (admin/${NEW_ADMIN_PASSWORD}) to visualize '${INDEX_PATTERN}'."
Index: /branches/amp_4_0/platform/tools/install_java.sh
===================================================================
--- /branches/amp_4_0/platform/tools/install_java.sh	(nonexistent)
+++ /branches/amp_4_0/platform/tools/install_java.sh	(working copy)
@@ -0,0 +1,100 @@
+#!/bin/bash
+
+# Script to install OpenJDK 21 on Rocky Linux using DNF (RPM repository)
+# This version aims for a more robust JAVA_HOME detection.
+
+# --- Configuration ---
+JAVA_PACKAGE="java-21-openjdk-devel" # Installs JDK (including JRE)
+                                     # 'java-21-openjdk' would install only the JRE
+PROFILE_SCRIPT="/etc/profile.d/java.sh" # For setting JAVA_HOME
+
+# --- Functions ---
+
+log_info() {
+    echo -e "\n\033[0;34m[INFO]\033[0m $1"
+}
+
+log_success() {
+    echo -e "\n\033[0;32m[SUCCESS]\033[0m $1"
+}
+
+log_error() {
+    echo -e "\n\033[0;31m[ERROR]\033[0m $1"
+    exit 1
+}
+
+# --- Main Script ---
+
+log_info "Starting OpenJDK 21 installation on Rocky Linux via DNF..."
+
+# 1. Check for root privileges
+if [[ $EUID -ne 0 ]]; then
+   log_error "This script must be run as root. Please use 'sudo bash $0'."
+fi
+
+# 2. Update system packages
+log_info "Updating system packages and metadata..."
+sudo dnf -y update --refresh || log_error "Failed to update system packages or refresh metadata."
+
+# 3. Search for available OpenJDK 21 packages
+log_info "Searching for available OpenJDK 21 packages in repositories..."
+# This is just for user information, not a direct check for installation flow
+dnf search "${JAVA_PACKAGE}" &>/dev/null
+
+# 4. Install OpenJDK 21 if not already installed
+if ! dnf list installed "${JAVA_PACKAGE}" &>/dev/null; then
+    log_info "Installing OpenJDK 21 (${JAVA_PACKAGE}) from official repositories..."
+    sudo dnf -y install "${JAVA_PACKAGE}" || log_error "Failed to install OpenJDK 21. It might not be available in your enabled repositories, or there's a network issue."
+else
+    log_info "OpenJDK 21 (${JAVA_PACKAGE}) is already installed."
+fi
+
+# 5. Determine JAVA_HOME path more robustly
+log_info "Determining JAVA_HOME path..."
+
+# First, ensure java is in PATH for the current script execution context
+# This is crucial so that 'which java' works reliably
+source /etc/profile # Load system-wide path settings
+
+JAVA_BIN_PATH=$(which java)
+if [ -z "${JAVA_BIN_PATH}" ]; then
+    log_error "Could not find 'java' executable in PATH after installation. This is unexpected."
+fi
+
+# Use readlink -f to get the absolute, resolved path to the actual java executable
+# Then remove the '/bin/java' part to get JAVA_HOME
+JAVA_HOME_PATH=$(readlink -f "${JAVA_BIN_PATH}" | sed 's:/bin/java::')
+
+if [ -z "${JAVA_HOME_PATH}" ]; then
+    log_error "Failed to determine JAVA_HOME path using 'readlink -f'. Manual check might be required."
+else
+    log_info "Detected JAVA_HOME: ${JAVA_HOME_PATH}"
+    # 6. Set up JAVA_HOME and PATH environment variables
+    log_info "Setting up JAVA_HOME and PATH environment variables in ${PROFILE_SCRIPT}..."
+
+    # Clear any previous Java settings in the profile script related to OpenJDK 21
+    # This prevents duplicate or incorrect entries if the script is run multiple times
+    sudo sed -i '/^export JAVA_HOME=.*openjdk-21/,+2d' "${PROFILE_SCRIPT}" 2>/dev/null
+    sudo sed -i '/^export PATH=.*\$JAVA_HOME\/bin/,d' "${PROFILE_SCRIPT}" 2>/dev/null
+    sudo sed -i '/^export JDK_HOME=.*\$JAVA_HOME/,d' "${PROFILE_SCRIPT}" 2>/dev/null
+
+    echo "export JAVA_HOME=${JAVA_HOME_PATH}" | sudo tee "${PROFILE_SCRIPT}" > /dev/null
+    echo "export PATH=\$PATH:\$JAVA_HOME/bin" | sudo tee -a "${PROFILE_SCRIPT}" > /dev/null
+    echo "export JDK_HOME=\$JAVA_HOME" | sudo tee -a "${PROFILE_SCRIPT}" > /dev/null
+
+    log_success "Environment variables for JAVA_HOME set in ${PROFILE_SCRIPT}."
+    log_info "You may need to log out and log back in, or run 'source ${PROFILE_SCRIPT}' to apply changes for new sessions."
+fi
+
+# 7. Verify installation
+log_info "Verifying OpenJDK 21 installation..."
+source "${PROFILE_SCRIPT}" # Apply changes for the current session to verify
+java -version
+
+if [ $? -eq 0 ]; then
+    log_success "OpenJDK 21 installed successfully via DNF and JAVA_HOME configured!"
+    log_info "JAVA_HOME is set to: ${JAVA_HOME}"
+    log_info "To ensure changes persist, please log out and log back in, or reboot your system."
+else
+    log_error "OpenJDK 21 installation verification failed."
+fi
Index: /branches/amp_4_0/scripts/avxrepocreate.py
===================================================================
--- /branches/amp_4_0/scripts/avxrepocreate.py	(revision 2645)
+++ /branches/amp_4_0/scripts/avxrepocreate.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/python3.13
+#!/usr/bin/env python3
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
Index: /branches/amp_4_0/scripts/bond_operation.py
===================================================================
--- /branches/amp_4_0/scripts/bond_operation.py	(revision 2645)
+++ /branches/amp_4_0/scripts/bond_operation.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/python3.13
+#!/usr/bin/env python3
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
Index: /branches/amp_4_0/scripts/docker_operation.py
===================================================================
--- /branches/amp_4_0/scripts/docker_operation.py	(revision 2645)
+++ /branches/amp_4_0/scripts/docker_operation.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/python3.13
+#!/usr/bin/env python3
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -310,12 +310,12 @@
                 return ERRNO_VA_REMOVE_FAILED
 
             # remove container
-            rm_cli = ['docker', 'rm', self.name]
-            _, err, rc = log_exec(rm_cli)
-            if rc != 0:
-                logging.debug("Failed to rm container(%s)", err)
+            rm_cli = ['docker', 'rm', self.name]
+            _, err, rc = log_exec(rm_cli)
+            if rc != 0:
+                logging.debug("Failed to rm container(%s)", err)
                 return ERRNO_VA_REMOVE_FAILED
-
+
         # remove image
         rmi_cli = ['docker', 'rmi', self.name]
         _, err, rc = log_exec(rmi_cli)
Index: /branches/amp_4_0/scripts/init_network.py
===================================================================
--- /branches/amp_4_0/scripts/init_network.py	(revision 2645)
+++ /branches/amp_4_0/scripts/init_network.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/python3.13
+#!/usr/bin/env python3
 
 from glob import glob
 from time import sleep
Index: /branches/amp_4_0/scripts/mailnotify.py
===================================================================
--- /branches/amp_4_0/scripts/mailnotify.py	(revision 2645)
+++ /branches/amp_4_0/scripts/mailnotify.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/python3.13
+#!/usr/bin/env python3
 
 from email.mime.text import MIMEText
 from subprocess import Popen, PIPE
Index: /branches/amp_4_0/scripts/mgmt_interface.py
===================================================================
--- /branches/amp_4_0/scripts/mgmt_interface.py	(revision 2645)
+++ /branches/amp_4_0/scripts/mgmt_interface.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/python3.13
+#!/usr/bin/env python3
 from glob import glob
 import os
 
Index: /branches/amp_4_0/scripts/reloadmacpool.py
===================================================================
--- /branches/amp_4_0/scripts/reloadmacpool.py	(revision 2645)
+++ /branches/amp_4_0/scripts/reloadmacpool.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/python3.13
+#!/usr/bin/env python3
 
 import os
 import shutil
Index: /branches/amp_4_0/src/library/libpyexauth/pyexauth_build.py
===================================================================
--- /branches/amp_4_0/src/library/libpyexauth/pyexauth_build.py	(revision 2645)
+++ /branches/amp_4_0/src/library/libpyexauth/pyexauth_build.py	(working copy)
@@ -1,11 +1,15 @@
-#!/usr/bin/env python
-# file "pyexauth.py"
+#!/usr/bin/env python3
+from pathlib import Path
 
 from cffi import FFI
+
 ffi = FFI()
 
-apath="/home/admin/amp/madhuri/amp_4_0/build/array/BUILD/amp-4.0.0/src/library"
+script_path = Path(__file__).resolve()
+library_dir = script_path.parent.parent
 
+print(library_dir)
+
 ffi.cdef("int is_external_auth_on();")
 ffi.cdef("int exauth_priority();")
 ffi.cdef("int external_auth(char*, char*);")
@@ -22,8 +26,8 @@
 	exauth_conf_t g_exauth_conf;
 	exauth_conf_t *shm_p = NULL;
 """,
-	include_dirs=[f"{apath}/libexauth", f"{apath}/libpyauth"],
-	library_dirs=[f"{apath}/libexauth",f"{apath}/avx_log",f"{apath}/libpyauth"],
+	include_dirs=[f"{library_dir}/libexauth", f"{library_dir}/libpyauth"],
+	library_dirs=[f"{library_dir}/libexauth",f"{library_dir}/avx_log",f"{library_dir}/libpyauth"],
 	libraries=["exauth", "avxlog", "ssl", "pyauth", "crypt"]) 
 
 if __name__ == "__main__":
Index: /branches/amp_4_0/src/openssh/openssh-9.9p1.tar.gz
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/x-gzip
Index: /branches/amp_4_0/src/webui/webui/conf/build_config.py
===================================================================
--- /branches/amp_4_0/src/webui/webui/conf/build_config.py	(revision 2645)
+++ /branches/amp_4_0/src/webui/webui/conf/build_config.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/python3.13
+#!/usr/bin/env python3
 import sys
 import string
 
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/setup.sh
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/setup.sh	(revision 2645)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/setup.sh	(working copy)
@@ -1,9 +1,9 @@
 #!/bin/sh
 export DJANGO_SETTINGS_MODULE=djproject.settings
 /ca/bin/webui_agent &
-nohup python -W ignore /ca/webui/htdocs/new/src/manage.py runfcgi method=threaded daemonize=false maxchildren=500 host=127.0.0.1 port=3033 $1 &
-python /ca/webui/htdocs/new/src/cm/lib/init_ftp_server.py &
-python /ca/webui/htdocs/new/src/cm/lib/init_tftp_server.py &
+nohup python3 -W ignore /ca/webui/htdocs/new/src/manage.py runfcgi method=threaded daemonize=false maxchildren=500 host=127.0.0.1 port=3033 $1 &
+python3 /ca/webui/htdocs/new/src/cm/lib/init_ftp_server.py &
+python3 /ca/webui/htdocs/new/src/cm/lib/init_tftp_server.py &
 /usr/local/bin/composer/composer_node start
 
 # check license_server
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/auto-gencode.sh
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/auto-gencode.sh	(revision 2645)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/auto-gencode.sh	(working copy)
@@ -5,7 +5,7 @@
 
 export DJANGO_SETTINGS_MODULE=djproject.settings
 
-python gen_interface.py
+python3 gen_interface.py
 
 
 for dir in $DESTDIR 
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gen_frontend.py
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gen_frontend.py	(revision 2645)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gen_frontend.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/python3.13
+#!/usr/bin/env python3
 # -*- coding: iso-8859-15 -*-
 
 """
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/manage.py
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/manage.py	(revision 2645)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/manage.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 import os
 import sys
 import importlib
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/setup.py
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/setup.py	(revision 2645)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/setup.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/python3.13
+#!/usr/bin/env python3
 import os, sys
 from optparse import OptionParser
 from hive.lang import LANGS_LOCALE_DIR
@@ -6,13 +6,13 @@
 
 def main():
     USAGE = """
-    usage: python setup.py mlinit -l <language=all> -t <py|js|all> (Don't use this if you are not sure)
-           python setup.py mlupdate -l <language=all> -t <py|js|all>
-           python setup.py mlcompile -l <language=all> -t <py|js|all>
-           python setup.py restdoc -l <language=all>
+    usage: python3 setup.py mlinit -l <language=all> -t <py|js|all> (Don't use this if you are not sure)
+           python3 setup.py mlupdate -l <language=all> -t <py|js|all>
+           python3 setup.py mlcompile -l <language=all> -t <py|js|all>
+           python3 setup.py restdoc -l <language=all>
 
     available languages (-l): zh_CN, ja (default: all)
-    available targets (-t): py (python and jinja2), js (javascript and coffeescript) (default: all)
+    available targets (-t): py (python3 and jinja2), js (javascript and coffeescript) (default: all)
     """
     
     if len(sys.argv) < 2:
@@ -92,7 +92,7 @@
             os.system('pybabel compile -D django -i locale/%s/LC_MESSAGES/django.po -d locale -l %s' % (lang, lang))
         if target in ('all', 'js'):
             os.system('pybabel compile -D djangojs -i locale/%s/LC_MESSAGES/djangojs.po -d locale -l %s' % (lang, lang))
-            os.system('python manage.py compilejsi18n -l %s' % lang)
+            os.system('python3 manage.py compilejsi18n -l %s' % lang)
 
     if lang == 'all':
         for each_lang in LANGS_LOCALE_DIR:
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/storemon.py
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/storemon.py	(revision 2645)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/storemon.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3.13
+#!/usr/bin/env python3
 # encoding: utf-8
 """
 Data format in MongoDB
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/tools/xmltodict.py
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/tools/xmltodict.py	(revision 2645)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/tools/xmltodict.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3.13
+#!/usr/bin/env python3
 "Makes working with XML feel like you are working with JSON"
 
 from xml.parsers import expat
Index: /branches/amp_4_0/tools/image-minimizer
===================================================================
--- /branches/amp_4_0/tools/image-minimizer	(revision 2645)
+++ /branches/amp_4_0/tools/image-minimizer	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 #
 # image-minimizer: removes files and packages on the filesystem
 #
Index: /branches/amp_4_0/update/avxupdate.py
===================================================================
--- /branches/amp_4_0/update/avxupdate.py	(revision 2645)
+++ /branches/amp_4_0/update/avxupdate.py	(working copy)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/python3.13
+#!/usr/bin/env python3
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
